Skip to main content

CoreOS Online Validator Now Supports Ignition

Development on Ignition, CoreOS's machine provisioner, has continued apace since its public debut. Along with internal changes and fixes, Ignition has seen widening support in the CoreOS Linux operating system and associated tools.

CoreOS is an operating system designed for cluster nodes. It's minimal in many ways, and the best practice at hyperscale operations is treating machines immutably – configuring them at boot time, not with interactive root logins. From there, updates are automatic, and machine reconfiguration is ideally identical to a machine failure and replacement cycle. Cluster node machines of this sort typically provide an API-like mechanism for boot time configuration. To date, cloud-config has been a popular and somewhat widely supported tool for this job.

Validating Ignition configurations

CoreOS Ignition is an atomic provisioning utility that represents the future of boot provisioning functions handled currently by cloud-config and coreos-cloudinit. Ignition clarifies many of the vagaries of the organically-emerged cloud-config/cloudinit mechanism by clearly defining when, where, and how often it runs. By running only once at a node's first power on, and running from the initramfs, Ignition can assure atomicity of operations like disk partitioning, systemd unit creation and configuration, and network setup before the "real" operating system boots. This allows Ignition to reliably deliver a cleanly configured environment to the operating system.

CoreOS has for some time provided a validator for the user data definitions that drive boot time configuration, both in the cloud and on physical hardware. Today, we're happy to announce that Ignition configurations can now be validated, along with existing cloud-init configuration files.

 

CoreOS cloud-config and Ignition user-data validator

 

Better error checking

In addition to being able to validate Ignition configurations before using them, the validator introduces more powerful and comprehensive error checking than Ignition previously had. It now supports reporting multiple errors, instead of just the first error encountered, and includes source line numbers, when applicable. Additionally, it now reports warnings, deprecation notices, and informational messages to catch common mistakes, such as mistyped keys or specifying a file rooted in an undefined filesystem. These changes are also included in Ignition itself, so even without the external validator, Ignition will log more useful error messages on boot.

Does the validator still work for cloud-configs?

The validator automatically determines the type of configuration files, so users can validate both cloud-configs and Ignition configurations. If the type of configuration cannot be determined (e.g. if it is a cloud-config, but missing the #cloud-config line), the validator assumes it is an Ignition configuration.

Limitations

Ignition supports chain-loading configurations. An Ignition configuration can specify another Ignition configuration to download and append to itself. The validator, however, does not support validating referenced configurations, and will only validate the contents of the file provided. The validator will not download any other assets, such as files specified in storage.files, and so will not verify if a provided SHA-512 hash for a file matches the file contents. If you use these features, you will need to verify those manually.

Since remote configurations are not retrieved, parsed, or verified, if one part of a configuration references an element in a remote resource, a warning will be generated. One example of this is when files specified in the base configuration reference filesystems specified in an appended configuration.

Ignition v1 configurations have limited support. The validator will return at most one error, and does not support any of the warnings the v2 format supports. If you are using Ignition v1 configurations, you should migrate to using v2 configurations.

Under the hood - How we got line numbers from encoding/json

The problem with encoding/json

You may know that Go's encoding/json library doesn't support extracting information regarding where in the JSON source the unmarshalled data came from. After unmarshalling, it is impossible to tell where a given key or value originated in the JSON source. This made it necessary to extend the standard encoding/json library to allow the validator to report source line numbers for errors.

Expanding encoding/json

To implement the validator we modified encoding/json to allow decoding to a structure that supports recording offsets. The standard encoding/json package supports unmarshalling to either an interface{}, or a struct you have defined. We modified the library to add a third target: json.Node. When unmarshalling to a json.Node, our modified encoding/json library unmarshalls as if it were unmarshalling to an interface{}, except that the start and end offsets are recorded for each node. Instead of unmarshalling JSON objects to map[string]interface{} and JSON arrays to []interface{}, we unmarshall them to map[string]json.Node and []json.Node instead.

We have an active Go proposal for including these changes in the standard library.

Walking the two trees

To validate an Ignition configuration, we unmarshal the configuration twice - once into Ignition's internal representation, and once into a json.Node. This gives us two configuration trees, one being the unmarshalled configuration structure and the other a literal representation of the raw JSON data, with offsets. We then recursively walk down both trees in step, ensuring that when we visit a node in the configuration structure, we also visit the corresponding node in the literal tree. Since we walk the trees in step we can determine the offset information for the configuration structure by using the values in the json.Node that it corresponds to. Additionally, we can detect unused keys by finding entries that exist in the literal tree but do not correspond to struct fields in the unmarshalled tree. As the trees are walked, the validator calls a validate function on each node to build a report of errors, warnings, deprecations, and info it encountered.

Try it out

You can validate your configurations now using the online validator. Additionally, Ignition 0.9.1 adds support for the improved validation and will be included soon in the CoreOS Linux Alpha channel.

If you have any questions or concerns, please join us in IRC freenode/#coreos.