From 3f43e4ecb653f0b5a22308f84310c9ba446a8dbe Mon Sep 17 00:00:00 2001 From: Dalton Hubble Date: Mon, 17 Apr 2017 16:44:33 -0700 Subject: [PATCH 1/4] matchbox,docs: Switch from Fuze to Container Linux Config * Container Linux Configs are Fuze configs, just renamed --- Documentation/ignition.md | 47 ++++++++-------------------------- Documentation/matchbox.md | 6 ++--- matchbox/http/ignition.go | 26 +++++++++---------- matchbox/http/ignition_test.go | 4 +-- 4 files changed, 29 insertions(+), 54 deletions(-) diff --git a/Documentation/ignition.md b/Documentation/ignition.md index f4729957..2adc415d 100644 --- a/Documentation/ignition.md +++ b/Documentation/ignition.md @@ -1,16 +1,16 @@ -# Ignition +# Container Linux Configs -Ignition is a system for declaratively provisioning disks during the initramfs, before systemd starts. It runs only on the first boot and handles partitioning disks, formatting partitions, writing files (regular files, systemd units, networkd units, etc.), and configuring users. See the Ignition [docs](https://coreos.com/ignition/docs/latest/) for details. +A Container Linux Config is a YAML document which declares how Container Linux instances' disks should be provisioned on network boot and first-boot from disk. Configs can declare disk paritions, write files (regular files, systemd units, networkd units, etc.), and configure users. See the Container Linux Config [spec](https://coreos.com/os/docs/latest/configuration.html). -## Fuze configs +### Ignition -Ignition 2.0.0+ configs are versioned, *machine-friendly* JSON documents (which contain encoded file contents). Operators should write and maintain configs in a *human-friendly* format, such as CoreOS [fuze](https://github.com/coreos/fuze) configs. As of `matchbox` v0.4.0, Fuze configs are the primary way to use CoreOS Ignition. +Container Linux Configs are validated and converted to *machine-friendly* Ignition configs (JSON) by matchbox when serving to booting machines. [Ignition](https://coreos.com/ignition/docs/latest/), the provisioning utility shipped in Container Linux, will parse and execute the Ignition config to realize the desired configuration. Matchbox users usually only need to write Container Linux Configs. -The [Fuze schema](https://github.com/coreos/fuze/blob/master/doc/configuration.md) formalizes and improves upon the YAML to Ignition JSON transform. Fuze provides better support for Ignition 2.0.0+, handles file content encoding, patches Ignition bugs, performs better validations, and lets services (like `matchbox`) negotiate the Ignition version required by a CoreOS client. +*Note: Container Linux directory names are still named "ignition" for historical reasons as outlined below. A future breaking change will rename to "container-linux-config".* -### Adding Fuze configs +## Adding Container Linux Configs -Fuze template files can be added in the `/var/lib/matchbox/ignition` directory or in an `ignition` subdirectory of a custom `-data-path`. Template files may contain [Go template](https://golang.org/pkg/text/template/) elements which will be evaluated with group metadata, selectors, and query params. +Container Linux Config templates can be added to the `/var/lib/matchbox/ignition` directory or in an `ignition` subdirectory of a custom `-data-path`. Template files may contain [Go template](https://golang.org/pkg/text/template/) elements which will be evaluated with group metadata, selectors, and query params. ``` /var/lib/matchbox @@ -23,38 +23,13 @@ Fuze template files can be added in the `/var/lib/matchbox/ignition` directory o └── profiles ``` -### Reference +## Referencing in Profiles -Reference an Fuze config in a [Profile](matchbox.md#profiles) with `ignition_id`. When PXE booting, use the kernel option `coreos.first_boot=1` and `coreos.config.url` to point to the `matchbox` [Ignition endpoint](api.md#ignition-config). - -### Migration from v0.3.0 - -In v0.4.0, `matchbox` switched to using the CoreOS [fuze](https://github.com/coreos/fuze) library, which formalizes and improves upon the YAML to Ignition JSON transform. Fuze provides better support for Ignition 2.0.0+, handles file content encoding, patches Ignition bugs, and performs better validations. - -Upgrade your Ignition YAML templates to match the [Fuze config schema](https://github.com/coreos/fuze/blob/master/doc/configuration.md). Typically, you'll need to do the following: - -* Remove `ignition_version: 1`, Fuze configs are version-less -* Update `filesystems` section and set the `name` -* Update `files` section to use `inline` as shown below -* Replace `uid` and `gid` with `user` and `group` objects as shown above - -Maintain readable inline file contents in Fuze: - -``` -... -files: - - path: /etc/foo.conf - filesystem: root - contents: - inline: | - foo bar -``` - -Support for the older Ignition v1 format has been dropped, so CoreOS machines must be **1010.1.0 or newer**. Read the upstream Ignition v1 to 2.0.0 [migration guide](https://coreos.com/ignition/docs/latest/migrating-configs.html) to understand the reasons behind schema changes. +Profiles can include a Container Linux Config for provisioning machines. Specify the Container Linux Config in a [Profile](matchbox.md#profiles) with `ignition_id`. When PXE booting, use the kernel option `coreos.first_boot=1` and `coreos.config.url` to point to the `matchbox` [Ignition endpoint](api.md#ignition-config). ## Examples -Here is an example Fuze template. This template will be rendered into a Fuze config (YAML), using group metadata, selectors, and query params as template variables. Finally, the Fuze config is served to client machines as Ignition JSON. +Here is an example Container Linux Config template. Variables will be interpreted using group metadata, selectors, and query params. Matchbox will convert the config to Ignition to serve Container Linux machines. ignition/format-disk.yaml.tmpl: @@ -162,7 +137,7 @@ The Ignition config response (formatted) to a query `/ignition?label=value` for } ``` -See [examples/ignition](../examples/ignition) for numerous Fuze template examples. +See [examples/ignition](../examples/ignition) for numerous Container Linux Config template examples. ### Raw Ignition diff --git a/Documentation/matchbox.md b/Documentation/matchbox.md index 89a0eaa0..d602e0ad 100644 --- a/Documentation/matchbox.md +++ b/Documentation/matchbox.md @@ -130,16 +130,16 @@ Group selectors can use any key/value pairs you find useful. However, several la ### Config templates -Profiles can reference various templated configs. Ignition JSON configs can be generated from [Fuze config](https://github.com/coreos/fuze/blob/master/doc/configuration.md) template files. Cloud-Config templates files can be used to render a script or Cloud-Config. Generic template files can be used to render arbitrary untyped configs (experimental). Each template may contain [Go template](https://golang.org/pkg/text/template/) elements which will be rendered with machine group metadata, selectors, and query params. +Profiles can reference various templated configs. Ignition JSON configs can be generated from [Container Linux Config](https://github.com/coreos/container-linux-config-transpiler/blob/master/doc/configuration.md) template files. Cloud-Config templates files can be used to render a script or Cloud-Config. Generic template files can be used to render arbitrary untyped configs (experimental). Each template may contain [Go template](https://golang.org/pkg/text/template/) elements which will be rendered with machine group metadata, selectors, and query params. For details and examples: -* [Ignition Config](ignition.md) +* [Container Linux Config](ignition.md) * [Cloud-Config](cloud-config.md) #### Variables -Within Ignition/Fuze templates, Cloud-Config templates, or generic templates, you can use group metadata, selectors, or request-scoped query params. For example, a request `/generic?mac=52-54-00-89-d8-10&foo=some-param&bar=b` would match the `node1.json` machine group shown above. If the group's profile ("etcd") referenced a generic template, the following variables could be used. +Within Container Linux Config templates, Cloud-Config templates, or generic templates, you can use group metadata, selectors, or request-scoped query params. For example, a request `/generic?mac=52-54-00-89-d8-10&foo=some-param&bar=b` would match the `node1.json` machine group shown above. If the group's profile ("etcd") referenced a generic template, the following variables could be used. ``` diff --git a/matchbox/http/ignition.go b/matchbox/http/ignition.go index 9cb50fa2..e79b97d8 100644 --- a/matchbox/http/ignition.go +++ b/matchbox/http/ignition.go @@ -7,7 +7,7 @@ import ( "context" "github.com/Sirupsen/logrus" - fuze "github.com/coreos/fuze/config" + ct "github.com/coreos/container-linux-config-transpiler/config" ignition "github.com/coreos/ignition/config" "github.com/coreos/matchbox/matchbox/server" @@ -16,9 +16,9 @@ import ( // ignitionHandler returns a handler that responds with the Ignition config // matching the request. The Ignition file referenced in the Profile is parsed -// as raw Ignition (for .ign/.ignition) or rendered to a Fuze config (YAML) -// and converted to Ignition. Ignition configs are served as HTTP JSON -// responses. +// as raw Ignition (for .ign/.ignition) or rendered from a Container Linux +// Config (YAML) and converted to Ignition. Ignition configs are served as HTTP +// JSON responses. func (s *Server) ignitionHandler(core server.Server) ContextHandler { fn := func(ctx context.Context, w http.ResponseWriter, req *http.Request) { group, err := groupFromContext(ctx) @@ -48,7 +48,7 @@ func (s *Server) ignitionHandler(core server.Server) ContextHandler { "group": group.Id, "group_name": group.Name, "profile": group.Profile, - }).Infof("No Ignition or Fuze template named: %s", profile.IgnitionId) + }).Infof("No Ignition or Container Linux Config template named: %s", profile.IgnitionId) http.NotFound(w, req) return } @@ -58,7 +58,7 @@ func (s *Server) ignitionHandler(core server.Server) ContextHandler { "labels": labelsFromRequest(nil, req), "group": group.Id, "profile": profile.Id, - }).Debug("Matched an Ignition or Fuze template") + }).Debug("Matched an Ignition or Container Linux Config template") // Skip rendering if raw Ignition JSON is provided if isIgnition(profile.IgnitionId) { @@ -70,7 +70,7 @@ func (s *Server) ignitionHandler(core server.Server) ContextHandler { return } - // Fuze Config template + // Container Linux Config template // collect data for rendering data, err := collectVariables(req, group) @@ -88,18 +88,18 @@ func (s *Server) ignitionHandler(core server.Server) ContextHandler { return } - // Parse bytes into a Fuze Config - config, report := fuze.Parse(buf.Bytes()) + // Parse bytes into a Container Linux Config + config, report := ct.Parse(buf.Bytes()) if report.IsFatal() { - s.logger.Errorf("error parsing Fuze config: %s", report.String()) + s.logger.Errorf("error parsing Container Linux config: %s", report.String()) http.NotFound(w, req) return } - // Convert Fuze Config into an Ignition Config - ign, report := fuze.ConvertAs2_0_0(config) + // Convert Container Linux Config into an Ignition Config + ign, report := ct.ConvertAs2_0(config, "") if report.IsFatal() { - s.logger.Errorf("error converting Fuze config: %s", report.String()) + s.logger.Errorf("error converting Container Linux config: %s", report.String()) http.NotFound(w, req) return } diff --git a/matchbox/http/ignition_test.go b/matchbox/http/ignition_test.go index 22f86a1c..f52cfeb7 100644 --- a/matchbox/http/ignition_test.go +++ b/matchbox/http/ignition_test.go @@ -40,7 +40,7 @@ func TestIgnitionHandler_V2JSON(t *testing.T) { } func TestIgnitionHandler_V2YAML(t *testing.T) { - // exercise templating features, not a realistic Fuze template + // exercise templating features, not a realistic Container Linux Config template content := ` systemd: units: @@ -66,7 +66,7 @@ systemd: req, _ := http.NewRequest("GET", "/?foo=some-param&bar=b", nil) h.ServeHTTP(ctx, w, req) // assert that: - // - Fuze template rendered with Group selectors, metadata, and query variables + // - Container Linux Config template rendered with Group selectors, metadata, and query variables // - Transformed to an Ignition config (JSON) assert.Equal(t, http.StatusOK, w.Code) assert.Equal(t, jsonContentType, w.HeaderMap.Get(contentType)) From a948a97339312bd5d832e53bf343231d1bfd1718 Mon Sep 17 00:00:00 2001 From: Dalton Hubble Date: Mon, 17 Apr 2017 16:46:25 -0700 Subject: [PATCH 2/4] glide.yaml: Vendor Container Linux Config transpiler * Update and vendor ct, Ignition, and deps --- glide.lock | 24 +- glide.yaml | 27 +- .../LICENSE | 0 .../NOTICE | 0 .../config/astyaml.go | 24 +- .../config/config.go | 9 +- .../config/templating/templating.go | 135 +++++++++ .../config/types/common.go | 89 ++++++ .../config/types/config.go | 95 ++++++ .../config/types/converter.go | 58 ++++ .../config/types/disks.go | 95 ++++++ .../config/types/docker.go | 44 +++ .../config/types/etcd.go | 281 ++++++++++++++++++ .../config/types/files.go | 98 ++++++ .../config/types/filesystems.go | 71 +++++ .../config/types/flannel.go | 157 ++++++++++ .../config/types/locksmith.go | 41 +++ .../config/types/networkd.go | 41 +++ .../config/types/passwd.go | 44 +++ .../config/types/raid.go | 46 +++ .../config/types/storage.go | 0 .../config/types/systemd.go | 60 ++++ .../config/types/update.go | 91 ++++++ .../config/types/verification.go | 0 .../github.com/coreos/fuze/config/convert.go | 281 ------------------ .../coreos/fuze/config/types/config.go | 37 --- .../coreos/fuze/config/types/files.go | 43 --- .../coreos/go-semver/semver/semver.go | 100 ++++--- .../coreos/go-systemd/unit/deserialize.go | 276 +++++++++++++++++ .../coreos/go-systemd/unit/escape.go | 116 ++++++++ .../coreos/go-systemd/unit/option.go | 54 ++++ .../coreos/go-systemd/unit/serialize.go | 75 +++++ .../coreos/ignition/config/config.go | 37 ++- .../coreos/ignition/config/translate.go | 192 +++++++++++- .../coreos/ignition/config/types/config.go | 5 +- .../config/types/directory.go} | 23 +- .../coreos/ignition/config/types/file.go | 45 +-- .../coreos/ignition/config/types/ignition.go | 5 +- .../coreos/ignition/config/types/node.go | 60 ++++ .../coreos/ignition/config/types/path.go | 4 +- .../coreos/ignition/config/types/storage.go | 1 + .../config/types/timeouts.go} | 8 +- .../coreos/ignition/config/types/unit.go | 46 ++- .../coreos/ignition/config/types/url.go | 12 +- .../coreos/ignition/config/v1/types/path.go | 11 +- .../coreos/ignition/config/v1/types/unit.go | 8 +- .../coreos/ignition/config/v2_0/append.go | 73 +++++ .../coreos/ignition/config/v2_0/cloudinit.go | 53 ++++ .../coreos/ignition/config/v2_0/config.go | 120 ++++++++ .../ignition/config/v2_0/types/compression.go | 36 +++ .../ignition/config/v2_0/types/config.go | 87 ++++++ .../coreos/ignition/config/v2_0/types/disk.go | 124 ++++++++ .../coreos/ignition/config/v2_0/types/file.go | 66 ++++ .../ignition/config/v2_0/types/filesystem.go | 67 +++++ .../config/v2_0/types/group.go} | 17 +- .../coreos/ignition/config/v2_0/types/hash.go | 73 +++++ .../ignition/config/v2_0/types/ignition.go | 69 +++++ .../config/v2_0}/types/networkd.go | 7 +- .../ignition/config/v2_0/types/partition.go | 59 ++++ .../ignition/config/v2_0/types/passwd.go | 20 ++ .../config/v2_0/types/path.go} | 33 +- .../coreos/ignition/config/v2_0/types/raid.go | 45 +++ .../ignition/config/v2_0/types/storage.go | 22 ++ .../ignition/config/v2_0/types/systemd.go | 19 ++ .../coreos/ignition/config/v2_0/types/unit.go | 111 +++++++ .../coreos/ignition/config/v2_0/types/url.go | 72 +++++ .../coreos/ignition/config/v2_0/types/user.go | 35 +++ .../config/v2_0/types/verification.go | 19 ++ .../ignition/config/validate/validate.go | 16 +- 69 files changed, 3630 insertions(+), 582 deletions(-) rename vendor/github.com/coreos/{fuze => container-linux-config-transpiler}/LICENSE (100%) rename vendor/github.com/coreos/{fuze => container-linux-config-transpiler}/NOTICE (100%) rename vendor/github.com/coreos/{fuze => container-linux-config-transpiler}/config/astyaml.go (73%) rename vendor/github.com/coreos/{fuze => container-linux-config-transpiler}/config/config.go (82%) create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/templating/templating.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/common.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/config.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/converter.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/disks.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/docker.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/etcd.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/files.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/filesystems.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/flannel.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/locksmith.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/networkd.go rename vendor/github.com/coreos/{fuze => container-linux-config-transpiler}/config/types/passwd.go (54%) create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/raid.go rename vendor/github.com/coreos/{fuze => container-linux-config-transpiler}/config/types/storage.go (100%) create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/systemd.go create mode 100644 vendor/github.com/coreos/container-linux-config-transpiler/config/types/update.go rename vendor/github.com/coreos/{fuze => container-linux-config-transpiler}/config/types/verification.go (100%) delete mode 100644 vendor/github.com/coreos/fuze/config/convert.go delete mode 100644 vendor/github.com/coreos/fuze/config/types/config.go delete mode 100644 vendor/github.com/coreos/fuze/config/types/files.go create mode 100644 vendor/github.com/coreos/go-systemd/unit/deserialize.go create mode 100644 vendor/github.com/coreos/go-systemd/unit/escape.go create mode 100644 vendor/github.com/coreos/go-systemd/unit/option.go create mode 100644 vendor/github.com/coreos/go-systemd/unit/serialize.go rename vendor/github.com/coreos/{fuze/config/types/filesystems.go => ignition/config/types/directory.go} (65%) create mode 100644 vendor/github.com/coreos/ignition/config/types/node.go rename vendor/github.com/coreos/{fuze/config/types/raid.go => ignition/config/types/timeouts.go} (79%) create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/append.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/cloudinit.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/config.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/compression.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/config.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/disk.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/file.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/filesystem.go rename vendor/github.com/coreos/{fuze/config/types/disks.go => ignition/config/v2_0/types/group.go} (64%) create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/hash.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/ignition.go rename vendor/github.com/coreos/{fuze/config => ignition/config/v2_0}/types/networkd.go (82%) create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/partition.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/passwd.go rename vendor/github.com/coreos/{fuze/config/types/systemd.go => ignition/config/v2_0/types/path.go} (59%) create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/raid.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/storage.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/systemd.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/unit.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/url.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/user.go create mode 100644 vendor/github.com/coreos/ignition/config/v2_0/types/verification.go diff --git a/glide.lock b/glide.lock index 6c3afb96..4d2a54e2 100644 --- a/glide.lock +++ b/glide.lock @@ -1,38 +1,42 @@ -hash: 9b6db105e9175308cb3a911161d68bbc80a5ee762bb7f08c926101cc5389b115 -updated: 2017-04-10T15:46:19.530989294-07:00 +hash: d7d6d80b5734d981194ff7ff4cfa150cedae4549133301d1845f110e48729543 +updated: 2017-04-17T15:53:14.762097698-07:00 imports: - name: github.com/ajeddeloh/go-json version: 73d058cf8437a1989030afe571eeab9f90eebbbd - name: github.com/ajeddeloh/yaml version: 1072abfea31191db507785e2e0c1b8d1440d35a5 - name: github.com/alecthomas/units - version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a + version: 6b4e7dc5e3143b85ea77909c72caf89416fc2915 - name: github.com/camlistore/camlistore version: 9106ce829629773474c689b34aacd7d3aaa99426 +- name: github.com/coreos/container-linux-config-transpiler + version: 12554ca0a5ce8ea4a6c594242ccb23d8b9bff493 + subpackages: + - config + - config/templating + - config/types - name: github.com/coreos/coreos-cloudinit version: 4c333e657bfbaa8f6594298b48324f45e6bf5961 subpackages: - config -- name: github.com/coreos/fuze - version: 63c72bc1c8875f7f4ca11800a1a8de0478a69a12 - subpackages: - - config - - config/types - name: github.com/coreos/go-semver - version: 294930c1e79c64e7dbe360054274fdad492c8cf5 + version: 5e3acbb5668c4c3deb4842615c4098eb61fb6b1e subpackages: - semver - name: github.com/coreos/go-systemd version: 43e4800a6165b4e02bb2a36673c54b230d6f7b26 subpackages: - journal + - unit - name: github.com/coreos/ignition - version: 3ffd793b1292c6b0b3519bce214bdb41f336faa7 + version: d75d0aa3bf307f0954ce4ea8cac56dacec8d16ce subpackages: - config - config/types - config/v1 - config/v1/types + - config/v2_0 + - config/v2_0/types - config/validate - config/validate/astjson - config/validate/report diff --git a/glide.yaml b/glide.yaml index 5c064c2a..518a4dd5 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,9 +17,15 @@ import: - naming - peer - transport -# Ignition and Fuze parse machine configs +# Container Linux Config Transpiler and Ignition +- package: github.com/coreos/container-linux-config-transpiler + version: v0.2.2 + subpackages: + - config + - config/types + - config/templating - package: github.com/coreos/ignition - version: 3ffd793b1292c6b0b3519bce214bdb41f336faa7 + version: d75d0aa3bf307f0954ce4ea8cac56dacec8d16ce subpackages: - config - config/types @@ -28,15 +34,16 @@ import: - config/validate - config/validate/astjson - config/validate/report -- package: github.com/coreos/fuze - version: 63c72bc1c8875f7f4ca11800a1a8de0478a69a12 - subpackages: - - config - - config/types - package: github.com/ajeddeloh/yaml version: 1072abfea31191db507785e2e0c1b8d1440d35a5 - package: github.com/vincent-petithory/dataurl version: 9a301d65acbb728fcc3ace14f45f511a4cfeea9c +- package: github.com/alecthomas/units + version: 6b4e7dc5e3143b85ea77909c72caf89416fc2915 +- package: github.com/coreos/go-semver + version: 5e3acbb5668c4c3deb4842615c4098eb61fb6b1e + subpackages: + - semver - package: github.com/coreos/coreos-cloudinit version: v1.11.0 subpackages: @@ -71,14 +78,8 @@ import: version: f7716cbe52baa25d2e9b0d0da546fcf909fc16b4 - package: github.com/coreos/yaml version: 6b16a5714269b2f70720a45406b1babd947a17ef -- package: github.com/alecthomas/units - version: 2efee857e7cfd4f3d0138cc3cbb1b4966962b93a - package: github.com/camlistore/camlistore version: 9106ce829629773474c689b34aacd7d3aaa99426 -- package: github.com/coreos/go-semver - version: 294930c1e79c64e7dbe360054274fdad492c8cf5 - subpackages: - - semver - package: github.com/coreos/go-systemd version: v12 subpackages: diff --git a/vendor/github.com/coreos/fuze/LICENSE b/vendor/github.com/coreos/container-linux-config-transpiler/LICENSE similarity index 100% rename from vendor/github.com/coreos/fuze/LICENSE rename to vendor/github.com/coreos/container-linux-config-transpiler/LICENSE diff --git a/vendor/github.com/coreos/fuze/NOTICE b/vendor/github.com/coreos/container-linux-config-transpiler/NOTICE similarity index 100% rename from vendor/github.com/coreos/fuze/NOTICE rename to vendor/github.com/coreos/container-linux-config-transpiler/NOTICE diff --git a/vendor/github.com/coreos/fuze/config/astyaml.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml.go similarity index 73% rename from vendor/github.com/coreos/fuze/config/astyaml.go rename to vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml.go index 40e98712..1adcfef5 100644 --- a/vendor/github.com/coreos/fuze/config/astyaml.go +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml.go @@ -26,35 +26,35 @@ var ( ErrNotDocumentNode = errors.New("Can only convert from document node") ) -type YamlNode struct { +type yamlNode struct { key yaml.Node yaml.Node } -func FromYamlDocumentNode(n yaml.Node) (YamlNode, error) { +func fromYamlDocumentNode(n yaml.Node) (yamlNode, error) { if n.Kind != yaml.DocumentNode { - return YamlNode{}, ErrNotDocumentNode + return yamlNode{}, ErrNotDocumentNode } - return YamlNode{ + return yamlNode{ key: n, Node: *n.Children[0], }, nil } -func (n YamlNode) ValueLineCol(source io.ReadSeeker) (int, int, string) { +func (n yamlNode) ValueLineCol(source io.ReadSeeker) (int, int, string) { return n.Line, n.Column, "" } -func (n YamlNode) KeyLineCol(source io.ReadSeeker) (int, int, string) { +func (n yamlNode) KeyLineCol(source io.ReadSeeker) (int, int, string) { return n.key.Line, n.key.Column, "" } -func (n YamlNode) LiteralValue() interface{} { +func (n yamlNode) LiteralValue() interface{} { return n.Value } -func (n YamlNode) SliceChild(index int) (validate.AstNode, bool) { +func (n yamlNode) SliceChild(index int) (validate.AstNode, bool) { if n.Kind != yaml.SequenceNode { return nil, false } @@ -62,13 +62,13 @@ func (n YamlNode) SliceChild(index int) (validate.AstNode, bool) { return nil, false } - return YamlNode{ + return yamlNode{ key: yaml.Node{}, Node: *n.Children[index], }, true } -func (n YamlNode) KeyValueMap() (map[string]validate.AstNode, bool) { +func (n yamlNode) KeyValueMap() (map[string]validate.AstNode, bool) { if n.Kind != yaml.MappingNode { return nil, false } @@ -77,7 +77,7 @@ func (n YamlNode) KeyValueMap() (map[string]validate.AstNode, bool) { for i := 0; i < len(n.Children); i += 2 { key := *n.Children[i] value := *n.Children[i+1] - kvmap[key.Value] = YamlNode{ + kvmap[key.Value] = yamlNode{ key: key, Node: value, } @@ -85,6 +85,6 @@ func (n YamlNode) KeyValueMap() (map[string]validate.AstNode, bool) { return kvmap, true } -func (n YamlNode) Tag() string { +func (n yamlNode) Tag() string { return "yaml" } diff --git a/vendor/github.com/coreos/fuze/config/config.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/config.go similarity index 82% rename from vendor/github.com/coreos/fuze/config/config.go rename to vendor/github.com/coreos/container-linux-config-transpiler/config/config.go index 777bc5c3..a359dada 100644 --- a/vendor/github.com/coreos/fuze/config/config.go +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/config.go @@ -18,7 +18,8 @@ import ( "reflect" yaml "github.com/ajeddeloh/yaml" - "github.com/coreos/fuze/config/types" + "github.com/coreos/container-linux-config-transpiler/config/types" + ignTypes "github.com/coreos/ignition/config/v2_0/types" "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -39,7 +40,7 @@ func Parse(data []byte) (types.Config, report.Report) { }) r.Merge(validate.ValidateWithoutSource(reflect.ValueOf(cfg))) } else { - root, err := FromYamlDocumentNode(*nodes) + root, err := fromYamlDocumentNode(*nodes) if err != nil { return types.Config{}, report.ReportFromError(err, report.EntryError) } @@ -52,3 +53,7 @@ func Parse(data []byte) (types.Config, report.Report) { } return cfg, r } + +func ConvertAs2_0(in types.Config, platform string) (ignTypes.Config, report.Report) { + return types.ConvertAs2_0(in, platform) +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/templating/templating.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/templating/templating.go new file mode 100644 index 00000000..d9820cbf --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/templating/templating.go @@ -0,0 +1,135 @@ +// Copyright 2017 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package templating + +import ( + "fmt" + "strings" +) + +var ( + ErrUnknownPlatform = fmt.Errorf("unsupported platform") + ErrUnknownField = fmt.Errorf("unknown field") +) + +const ( + PlatformAzure = "azure" + PlatformDO = "digitalocean" + PlatformEC2 = "ec2" + PlatformGCE = "gce" + PlatformPacket = "packet" + PlatformOpenStackMetadata = "openstack-metadata" +) + +var Platforms = []string{ + PlatformAzure, + PlatformDO, + PlatformEC2, + PlatformGCE, + PlatformPacket, + PlatformOpenStackMetadata, +} + +const ( + fieldHostname = "HOSTNAME" + fieldV4Private = "PRIVATE_IPV4" + fieldV4Public = "PUBLIC_IPV4" + fieldV6Private = "PRIVATE_IPV6" + fieldV6Public = "PUBLIC_IPV6" +) + +var platformTemplatingMap = map[string]map[string]string{ + PlatformAzure: { + // TODO: is this right? + fieldV4Private: "COREOS_AZURE_IPV4_DYNAMIC", + fieldV4Public: "COREOS_AZURE_IPV4_VIRTUAL", + }, + PlatformDO: { + // TODO: unused: COREOS_DIGITALOCEAN_IPV4_ANCHOR_0 + fieldHostname: "COREOS_DIGITALOCEAN_HOSTNAME", + fieldV4Private: "COREOS_DIGITALOCEAN_IPV4_PRIVATE_0", + fieldV4Public: "COREOS_DIGITALOCEAN_IPV4_PUBLIC_0", + fieldV6Private: "COREOS_DIGITALOCEAN_IPV6_PRIVATE_0", + fieldV6Public: "COREOS_DIGITALOCEAN_IPV6_PUBLIC_0", + }, + PlatformEC2: { + fieldHostname: "COREOS_EC2_HOSTNAME", + fieldV4Private: "COREOS_EC2_IPV4_LOCAL", + fieldV4Public: "COREOS_EC2_IPV4_PUBLIC", + }, + PlatformGCE: { + fieldHostname: "COREOS_GCE_HOSTNAME", + fieldV4Private: "COREOS_GCE_IP_EXTERNAL_0", + fieldV4Public: "COREOS_GCE_IP_LOCAL_0", + }, + PlatformPacket: { + fieldHostname: "COREOS_PACKET_HOSTNAME", + fieldV4Private: "COREOS_PACKET_IPV4_PRIVATE_0", + fieldV4Public: "COREOS_PACKET_IPV4_PUBLIC_0", + fieldV6Public: "COREOS_PACKET_IPV6_PUBLIC_0", + }, + PlatformOpenStackMetadata: { + fieldHostname: "COREOS_OPENSTACK_HOSTNAME", + fieldV4Private: "COREOS_OPENSTACK_IPV4_LOCAL", + fieldV4Public: "COREOS_OPENSTACK_IPV4_PUBLIC", + }, +} + +// HasTemplating returns whether or not any of the environment variables present +// in the passed in list use ct templating +func HasTemplating(vars []string) bool { + for _, v := range vars { + if strings.ContainsRune(v, '{') || strings.ContainsRune(v, '}') { + return true + } + } + return false +} + +func PerformTemplating(platform string, vars []string) ([]string, error) { + if _, ok := platformTemplatingMap[platform]; !ok { + return nil, ErrUnknownPlatform + } + + for i := range vars { + startIndex := strings.IndexRune(vars[i], '{') + endIndex := strings.IndexRune(vars[i], '}') + for startIndex != -1 && endIndex != -1 && startIndex < endIndex { + fieldName := vars[i][startIndex+1 : endIndex] + fieldVal, ok := platformTemplatingMap[platform][fieldName] + if !ok { + return nil, ErrUnknownField + } + vars[i] = strings.Replace(vars[i], "{"+fieldName+"}", "${"+fieldVal+"}", 1) + + // start the search for a new start index from the old end index, or + // we'll just find the curly braces we just substituted in + startIndex = strings.IndexRune(vars[i][endIndex:], '{') + if startIndex != -1 { + startIndex += endIndex + + // and start the search for a new end index from the new start + // index, or as before we'll just find the curly braces we just + // substituted in + endIndex = strings.IndexRune(vars[i][startIndex:], '}') + if endIndex != -1 { + endIndex += startIndex + } + } + + } + } + return vars, nil +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/common.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/common.go new file mode 100644 index 00000000..95a2919d --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/common.go @@ -0,0 +1,89 @@ +// Copyright 2017 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "reflect" + + "github.com/coreos/container-linux-config-transpiler/config/templating" +) + +var ( + ErrPlatformUnspecified = fmt.Errorf("platform must be specified to use templating") +) + +func isZero(v interface{}) bool { + if v == nil { + return true + } + zv := reflect.Zero(reflect.TypeOf(v)) + return reflect.DeepEqual(v, zv.Interface()) +} + +// assembleUnit will assemble the contents of a systemd unit dropin that will +// have the given environment variables, and call the given exec line with the +// provided args prepended to it +func assembleUnit(exec string, args, vars []string, platform string) (string, error) { + hasTemplating := templating.HasTemplating(args) + + var out string + if hasTemplating { + if platform == "" { + return "", ErrPlatformUnspecified + } + out = "[Unit]\nRequires=coreos-metadata.service\nAfter=coreos-metadata.service\n\n[Service]\nEnvironmentFile=/run/metadata/coreos\n" + var err error + args, err = templating.PerformTemplating(platform, args) + if err != nil { + return "", err + } + } else { + out = "[Service]\n" + } + + for _, v := range vars { + out += fmt.Sprintf("Environment=\"%s\"\n", v) + } + for _, a := range args { + exec += fmt.Sprintf(" \\\n %s", a) + } + out += "ExecStart=\n" + out += fmt.Sprintf("ExecStart=%s", exec) + return out, nil +} + +// getCliArgs builds a list of --ARG=VAL from a struct with cli: tags on its members. +func getCliArgs(e interface{}) []string { + if e == nil { + return nil + } + et := reflect.TypeOf(e) + ev := reflect.ValueOf(e) + + vars := []string{} + for i := 0; i < et.NumField(); i++ { + if val := ev.Field(i).Interface(); !isZero(val) { + if et.Field(i).Anonymous { + vars = append(vars, getCliArgs(val)...) + } else { + key := et.Field(i).Tag.Get("cli") + vars = append(vars, fmt.Sprintf("--%s=%q", key, val)) + } + } + } + + return vars +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/config.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/config.go new file mode 100644 index 00000000..19d3a1d4 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/config.go @@ -0,0 +1,95 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "net/url" + + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +type Config struct { + Ignition Ignition `yaml:"ignition"` + Storage Storage `yaml:"storage"` + Systemd Systemd `yaml:"systemd"` + Networkd Networkd `yaml:"networkd"` + Passwd Passwd `yaml:"passwd"` + Etcd *Etcd `yaml:"etcd"` + Flannel *Flannel `yaml:"flannel"` + Update *Update `yaml:"update"` + Docker *Docker `yaml:"docker"` + Locksmith *Locksmith `yaml:"locksmith"` +} + +type Ignition struct { + Config IgnitionConfig `yaml:"config"` +} + +type IgnitionConfig struct { + Append []ConfigReference `yaml:"append"` + Replace *ConfigReference `yaml:"replace"` +} + +type ConfigReference struct { + Source string `yaml:"source"` + Verification Verification `yaml:"verification"` +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + for _, ref := range in.Ignition.Config.Append { + newRef, err := convertConfigReference(ref) + if err != nil { + return out, report.ReportFromError(err, report.EntryError) + } + out.Ignition.Config.Append = append(out.Ignition.Config.Append, newRef) + } + + if in.Ignition.Config.Replace != nil { + newRef, err := convertConfigReference(*in.Ignition.Config.Replace) + if err != nil { + return out, report.ReportFromError(err, report.EntryError) + } + out.Ignition.Config.Replace = &newRef + } + return out, report.Report{} + }) +} + +func convertConfigReference(in ConfigReference) (ignTypes.ConfigReference, error) { + source, err := url.Parse(in.Source) + if err != nil { + return ignTypes.ConfigReference{}, err + } + + return ignTypes.ConfigReference{ + Source: ignTypes.Url(*source), + Verification: convertVerification(in.Verification), + }, nil +} + +func convertVerification(in Verification) ignTypes.Verification { + if in.Hash.Function == "" || in.Hash.Sum == "" { + return ignTypes.Verification{} + } + + return ignTypes.Verification{ + &ignTypes.Hash{ + Function: in.Hash.Function, + Sum: in.Hash.Sum, + }, + } +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/converter.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/converter.go new file mode 100644 index 00000000..1942eaf2 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/converter.go @@ -0,0 +1,58 @@ +// Copyright 2017 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "reflect" + + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" + "github.com/coreos/ignition/config/validate/report" +) + +type converterFor2_0 func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) + +var convertersFor2_0 []converterFor2_0 + +func register2_0(f converterFor2_0) { + convertersFor2_0 = append(convertersFor2_0, f) +} + +func ConvertAs2_0(in Config, platform string) (ignTypes.Config, report.Report) { + out := ignTypes.Config{ + Ignition: ignTypes.Ignition{ + Version: ignTypes.IgnitionVersion{Major: 2, Minor: 0}, + }, + } + + r := report.Report{} + + for _, convert := range convertersFor2_0 { + var subReport report.Report + out, subReport = convert(in, out, platform) + r.Merge(subReport) + } + if r.IsFatal() { + return ignTypes.Config{}, r + } + + validationReport := validate.ValidateWithoutSource(reflect.ValueOf(out)) + r.Merge(validationReport) + if r.IsFatal() { + return ignTypes.Config{}, r + } + + return out, r +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/disks.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/disks.go new file mode 100644 index 00000000..851ed4bc --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/disks.go @@ -0,0 +1,95 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + + "github.com/alecthomas/units" + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +const ( + BYTES_PER_SECTOR = 512 +) + +type Disk struct { + Device string `yaml:"device"` + WipeTable bool `yaml:"wipe_table"` + Partitions []Partition `yaml:"partitions"` +} + +type Partition struct { + Label string `yaml:"label"` + Number int `yaml:"number"` + Size string `yaml:"size"` + Start string `yaml:"start"` + TypeGUID string `yaml:"type_guid"` +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + for _, disk := range in.Storage.Disks { + newDisk := ignTypes.Disk{ + Device: ignTypes.Path(disk.Device), + WipeTable: disk.WipeTable, + } + + for _, partition := range disk.Partitions { + size, err := convertPartitionDimension(partition.Size) + if err != nil { + return out, report.ReportFromError(err, report.EntryError) + } + start, err := convertPartitionDimension(partition.Start) + if err != nil { + return out, report.ReportFromError(err, report.EntryError) + } + + newDisk.Partitions = append(newDisk.Partitions, ignTypes.Partition{ + Label: ignTypes.PartitionLabel(partition.Label), + Number: partition.Number, + Size: size, + Start: start, + TypeGUID: ignTypes.PartitionTypeGUID(partition.TypeGUID), + }) + } + + out.Storage.Disks = append(out.Storage.Disks, newDisk) + } + return out, report.Report{} + }) +} + +func convertPartitionDimension(in string) (ignTypes.PartitionDimension, error) { + if in == "" { + return 0, nil + } + + b, err := units.ParseBase2Bytes(in) + if err != nil { + return 0, err + } + if b < 0 { + return 0, fmt.Errorf("invalid dimension (negative): %q", in) + } + + // Translate bytes into sectors + sectors := (b / BYTES_PER_SECTOR) + if b%BYTES_PER_SECTOR != 0 { + sectors++ + } + return ignTypes.PartitionDimension(uint64(sectors)), nil +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/docker.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/docker.go new file mode 100644 index 00000000..cf0b7659 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/docker.go @@ -0,0 +1,44 @@ +// Copyright 2017 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "strings" + + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +type Docker struct { + Flags []string `yaml:"flags"` +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + if in.Docker != nil { + contents := fmt.Sprintf("[Service]\nEnvironment=\"DOCKER_OPTS=%s\"", strings.Join(in.Docker.Flags, " ")) + out.Systemd.Units = append(out.Systemd.Units, ignTypes.SystemdUnit{ + Name: "docker.service", + Enable: true, + DropIns: []ignTypes.SystemdUnitDropIn{{ + Name: "20-clct-docker.conf", + Contents: contents, + }}, + }) + } + return out, report.Report{} + }) +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/etcd.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/etcd.go new file mode 100644 index 00000000..8fd186fc --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/etcd.go @@ -0,0 +1,281 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "errors" + "fmt" + + "github.com/coreos/go-semver/semver" + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +var ( + EtcdVersionTooOld = errors.New("Etcd version specified is not valid (too old)") + EtcdMinorVersionTooNew = errors.New("Etcd minor version specified is too new, only options available in the previous minor version will be accepted") + EtcdMajorVersionTooNew = errors.New("Etcd version is not valid (too new)") + OldestEtcd = *semver.New("2.3.0") + EtcdDefaultVersion = *semver.New("3.0.0") +) + +// Options can be the options for any Etcd version +type Options interface{} + +type etcdCommon Etcd + +type EtcdVersion semver.Version + +func (e *EtcdVersion) UnmarshalYAML(unmarshal func(interface{}) error) error { + t := semver.Version(*e) + if err := unmarshal(&t); err != nil { + return err + } + *e = EtcdVersion(t) + return nil +} + +func (e EtcdVersion) Validate() report.Report { + v := semver.Version(e) + switch { + case v.LessThan(OldestEtcd): + return report.ReportFromError(EtcdVersionTooOld, report.EntryError) + case v.Major == 2 && v.Minor > 3: + fallthrough + case v.Major == 3 && v.Minor > 1: + return report.ReportFromError(EtcdMinorVersionTooNew, report.EntryWarning) + case v.Major > 3: + return report.ReportFromError(EtcdMajorVersionTooNew, report.EntryError) + } + return report.Report{} +} + +func (e EtcdVersion) String() string { + return semver.Version(e).String() +} + +// Etcd is a stub for yaml unmarshalling that figures out which +// of the other Etcd structs to use and unmarshals to that. Options needs +// to be an embedded type so that the structure of the yaml tree matches the +// structure of the go config tree +type Etcd struct { + Version *EtcdVersion `yaml:"version"` + Options +} + +func (etcd *Etcd) UnmarshalYAML(unmarshal func(interface{}) error) error { + t := etcdCommon(*etcd) + if err := unmarshal(&t); err != nil { + return err + } + *etcd = Etcd(t) + + var version semver.Version + if etcd.Version == nil { + version = EtcdDefaultVersion + } else { + version = semver.Version(*etcd.Version) + } + + if version.Major == 2 && version.Minor >= 3 { + o := Etcd2{} + if err := unmarshal(&o); err != nil { + return err + } + etcd.Options = o + } else if version.Major == 3 && version.Minor == 0 { + o := Etcd3_0{} + if err := unmarshal(&o); err != nil { + return err + } + etcd.Options = o + } else if version.Major == 3 && version.Minor >= 1 { + o := Etcd3_1{} + if err := unmarshal(&o); err != nil { + return err + } + etcd.Options = o + } + return nil +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + if in.Etcd != nil { + contents, err := etcdContents(*in.Etcd, platform) + if err != nil { + return ignTypes.Config{}, report.ReportFromError(err, report.EntryError) + } + out.Systemd.Units = append(out.Systemd.Units, ignTypes.SystemdUnit{ + Name: "etcd-member.service", + Enable: true, + DropIns: []ignTypes.SystemdUnitDropIn{{ + Name: "20-clct-etcd-member.conf", + Contents: contents, + }}, + }) + } + return out, report.Report{} + }) +} + +// etcdContents creates the string containing the systemd drop in for etcd-member +func etcdContents(etcd Etcd, platform string) (string, error) { + args := getCliArgs(etcd.Options) + var vars []string + if etcd.Version != nil { + vars = []string{fmt.Sprintf("ETCD_IMAGE_TAG=v%s", etcd.Version)} + } + + return assembleUnit("/usr/lib/coreos/etcd-wrapper $ETCD_OPTS", args, vars, platform) +} + +type Etcd3_0 struct { + Name string `yaml:"name" cli:"name"` + DataDir string `yaml:"data_dir" cli:"data-dir"` + WalDir string `yaml:"wal_dir" cli:"wal-dir"` + SnapshotCount int `yaml:"snapshot_count" cli:"snapshot-count"` + HeartbeatInterval int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` + ElectionTimeout int `yaml:"election_timeout" cli:"election-timeout"` + ListenPeerUrls string `yaml:"listen_peer_urls" cli:"listen-peer-urls"` + ListenClientUrls string `yaml:"listen_client_urls" cli:"listen-client-urls"` + MaxSnapshots int `yaml:"max_snapshots" cli:"max-snapshots"` + MaxWals int `yaml:"max_wals" cli:"max-wals"` + Cors string `yaml:"cors" cli:"cors"` + InitialAdvertisePeerUrls string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` + InitialCluster string `yaml:"initial_cluster" cli:"initial-cluster"` + InitialClusterState string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` + InitialClusterToken string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` + AdvertiseClientUrls string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` + Discovery string `yaml:"discovery" cli:"discovery"` + DiscoverySrv string `yaml:"discovery_srv" cli:"discovery-srv"` + DiscoveryFallback string `yaml:"discovery_fallback" cli:"discovery-fallback"` + DiscoveryProxy string `yaml:"discovery_proxy" cli:"discovery-proxy"` + StrictReconfigCheck bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` + AutoCompactionRetention int `yaml:"auto_compaction_retention" cli:"auto-compaction-retention"` + Proxy string `yaml:"proxy" cli:"proxy"` + ProxyFailureWait int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` + ProxyRefreshInterval int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` + ProxyDialTimeout int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` + ProxyWriteTimeout int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` + ProxyReadTimeout int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` + CaFile string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` + CertFile string `yaml:"cert_file" cli:"cert-file"` + KeyFile string `yaml:"key_file" cli:"key-file"` + ClientCertAuth bool `yaml:"client_cert_auth" cli:"client-cert-auth"` + TrustedCaFile string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` + AutoTls bool `yaml:"auto_tls" cli:"auto-tls"` + PeerCaFile string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` + PeerCertFile string `yaml:"peer_cert_file" cli:"peer-cert-file"` + PeerKeyFile string `yaml:"peer_key_file" cli:"peer-key-file"` + PeerClientCertAuth bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` + PeerTrustedCaFile string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` + PeerAutoTls bool `yaml:"peer_auto_tls" cli:"peer-auto-tls"` + Debug bool `yaml:"debug" cli:"debug"` + LogPackageLevels string `yaml:"log_package_levels" cli:"log-package-levels"` + ForceNewCluster bool `yaml:"force_new_cluster" cli:"force-new-cluster"` +} + +type Etcd3_1 struct { + Name string `yaml:"name" cli:"name"` + DataDir string `yaml:"data_dir" cli:"data-dir"` + WalDir string `yaml:"wal_dir" cli:"wal-dir"` + SnapshotCount int `yaml:"snapshot_count" cli:"snapshot-count"` + HeartbeatInterval int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` + ElectionTimeout int `yaml:"election_timeout" cli:"election-timeout"` + ListenPeerUrls string `yaml:"listen_peer_urls" cli:"listen-peer-urls"` + ListenClientUrls string `yaml:"listen_client_urls" cli:"listen-client-urls"` + MaxSnapshots int `yaml:"max_snapshots" cli:"max-snapshots"` + MaxWals int `yaml:"max_wals" cli:"max-wals"` + Cors string `yaml:"cors" cli:"cors"` + InitialAdvertisePeerUrls string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` + InitialCluster string `yaml:"initial_cluster" cli:"initial-cluster"` + InitialClusterState string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` + InitialClusterToken string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` + AdvertiseClientUrls string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` + Discovery string `yaml:"discovery" cli:"discovery"` + DiscoverySrv string `yaml:"discovery_srv" cli:"discovery-srv"` + DiscoveryFallback string `yaml:"discovery_fallback" cli:"discovery-fallback"` + DiscoveryProxy string `yaml:"discovery_proxy" cli:"discovery-proxy"` + StrictReconfigCheck bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` + AutoCompactionRetention int `yaml:"auto_compaction_retention" cli:"auto-compaction-retention"` + Proxy string `yaml:"proxy" cli:"proxy"` + ProxyFailureWait int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` + ProxyRefreshInterval int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` + ProxyDialTimeout int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` + ProxyWriteTimeout int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` + ProxyReadTimeout int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` + CaFile string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` + CertFile string `yaml:"cert_file" cli:"cert-file"` + KeyFile string `yaml:"key_file" cli:"key-file"` + ClientCertAuth bool `yaml:"client_cert_auth" cli:"client-cert-auth"` + TrustedCaFile string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` + AutoTls bool `yaml:"auto_tls" cli:"auto-tls"` + PeerCaFile string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` + PeerCertFile string `yaml:"peer_cert_file" cli:"peer-cert-file"` + PeerKeyFile string `yaml:"peer_key_file" cli:"peer-key-file"` + PeerClientCertAuth bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` + PeerTrustedCaFile string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` + PeerAutoTls bool `yaml:"peer_auto_tls" cli:"peer-auto-tls"` + Debug bool `yaml:"debug" cli:"debug"` + LogPackageLevels string `yaml:"log_package_levels" cli:"log-package-levels"` + ForceNewCluster bool `yaml:"force_new_cluster" cli:"force-new-cluster"` + Metrics string `yaml:"metrics" cli:"metrics"` + LogOutput string `yaml:"log_output" cli:"log-output"` +} + +type Etcd2 struct { + AdvertiseClientURLs string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` + CAFile string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` + CertFile string `yaml:"cert_file" cli:"cert-file"` + ClientCertAuth bool `yaml:"client_cert_auth" cli:"client-cert-auth"` + CorsOrigins string `yaml:"cors" cli:"cors"` + DataDir string `yaml:"data_dir" cli:"data-dir"` + Debug bool `yaml:"debug" cli:"debug"` + Discovery string `yaml:"discovery" cli:"discovery"` + DiscoveryFallback string `yaml:"discovery_fallback" cli:"discovery-fallback"` + DiscoverySRV string `yaml:"discovery_srv" cli:"discovery-srv"` + DiscoveryProxy string `yaml:"discovery_proxy" cli:"discovery-proxy"` + ElectionTimeout int `yaml:"election_timeout" cli:"election-timeout"` + EnablePprof bool `yaml:"enable_pprof" cli:"enable-pprof"` + ForceNewCluster bool `yaml:"force_new_cluster" cli:"force-new-cluster"` + HeartbeatInterval int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` + InitialAdvertisePeerURLs string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` + InitialCluster string `yaml:"initial_cluster" cli:"initial-cluster"` + InitialClusterState string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` + InitialClusterToken string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` + KeyFile string `yaml:"key_file" cli:"key-file"` + ListenClientURLs string `yaml:"listen_client_urls" cli:"listen-client-urls"` + ListenPeerURLs string `yaml:"listen_peer_urls" cli:"listen-peer-urls"` + LogPackageLevels string `yaml:"log_package_levels" cli:"log-package-levels"` + MaxSnapshots int `yaml:"max_snapshots" cli:"max-snapshots"` + MaxWALs int `yaml:"max_wals" cli:"max-wals"` + Name string `yaml:"name" cli:"name"` + PeerCAFile string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` + PeerCertFile string `yaml:"peer_cert_file" cli:"peer-cert-file"` + PeerKeyFile string `yaml:"peer_key_file" cli:"peer-key-file"` + PeerClientCertAuth bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` + PeerTrustedCAFile string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` + Proxy string `yaml:"proxy" cli:"proxy" valid:"^(on|off|readonly)$"` + ProxyDialTimeout int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` + ProxyFailureWait int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` + ProxyReadTimeout int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` + ProxyRefreshInterval int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` + ProxyWriteTimeout int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` + SnapshotCount int `yaml:"snapshot_count" cli:"snapshot-count"` + StrictReconfigCheck bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` + TrustedCAFile string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` + WalDir string `yaml:"wal_dir" cli:"wal-dir"` +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/files.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/files.go new file mode 100644 index 00000000..81eb8b9a --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/files.go @@ -0,0 +1,98 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "net/url" + + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" + "github.com/vincent-petithory/dataurl" +) + +type File struct { + Filesystem string `yaml:"filesystem"` + Path string `yaml:"path"` + Mode int `yaml:"mode"` + Contents FileContents `yaml:"contents"` + User FileUser `yaml:"user"` + Group FileGroup `yaml:"group"` +} + +type FileContents struct { + Remote Remote `yaml:"remote"` + Inline string `yaml:"inline"` +} + +type Remote struct { + Url string `yaml:"url"` + Compression string `yaml:"compression"` + Verification Verification `yaml:"verification"` +} + +type FileUser struct { + Id int `yaml:"id"` +} + +type FileGroup struct { + Id int `yaml:"id"` +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + for _, file := range in.Storage.Files { + newFile := ignTypes.File{ + Filesystem: file.Filesystem, + Path: ignTypes.Path(file.Path), + Mode: ignTypes.FileMode(file.Mode), + User: ignTypes.FileUser{Id: file.User.Id}, + Group: ignTypes.FileGroup{Id: file.Group.Id}, + } + + if file.Contents.Inline != "" { + newFile.Contents = ignTypes.FileContents{ + Source: ignTypes.Url{ + Scheme: "data", + Opaque: "," + dataurl.EscapeString(file.Contents.Inline), + }, + } + } + + if file.Contents.Remote.Url != "" { + source, err := url.Parse(file.Contents.Remote.Url) + if err != nil { + return out, report.ReportFromError(err, report.EntryError) + } + + newFile.Contents = ignTypes.FileContents{Source: ignTypes.Url(*source)} + } + + if newFile.Contents == (ignTypes.FileContents{}) { + newFile.Contents = ignTypes.FileContents{ + Source: ignTypes.Url{ + Scheme: "data", + Opaque: ",", + }, + } + } + + newFile.Contents.Compression = ignTypes.Compression(file.Contents.Remote.Compression) + newFile.Contents.Verification = convertVerification(file.Contents.Remote.Verification) + + out.Storage.Files = append(out.Storage.Files, newFile) + } + return out, report.Report{} + }) +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/filesystems.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/filesystems.go new file mode 100644 index 00000000..f6d11d67 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/filesystems.go @@ -0,0 +1,71 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +type Filesystem struct { + Name string `yaml:"name"` + Mount *Mount `yaml:"mount"` + Path string `yaml:"path"` +} + +type Mount struct { + Device string `yaml:"device"` + Format string `yaml:"format"` + Create *Create `yaml:"create"` +} + +type Create struct { + Force bool `yaml:"force"` + Options []string `yaml:"options"` +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + for _, filesystem := range in.Storage.Filesystems { + newFilesystem := ignTypes.Filesystem{ + Name: filesystem.Name, + Path: func(p ignTypes.Path) *ignTypes.Path { + if p == "" { + return nil + } + + return &p + }(ignTypes.Path(filesystem.Path)), + } + + if filesystem.Mount != nil { + newFilesystem.Mount = &ignTypes.FilesystemMount{ + Device: ignTypes.Path(filesystem.Mount.Device), + Format: ignTypes.FilesystemFormat(filesystem.Mount.Format), + } + + if filesystem.Mount.Create != nil { + newFilesystem.Mount.Create = &ignTypes.FilesystemCreate{ + Force: filesystem.Mount.Create.Force, + Options: ignTypes.MkfsOptions(filesystem.Mount.Create.Options), + } + } + } + + out.Storage.Filesystems = append(out.Storage.Filesystems, newFilesystem) + } + return out, report.Report{} + }) +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/flannel.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/flannel.go new file mode 100644 index 00000000..677fa7f6 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/flannel.go @@ -0,0 +1,157 @@ +package types + +import ( + "errors" + "fmt" + + "github.com/coreos/go-semver/semver" + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrFlannelTooOld = errors.New("invalid flannel version (too old)") + ErrFlannelMinorTooNew = errors.New("flannel minor version too new. Only options available in the previous minor version will be supported") + OldestFlannelVersion = *semver.New("0.5.0") + FlannelDefaultVersion = *semver.New("0.6.0") +) + +type Flannel struct { + Version *FlannelVersion `yaml:"version"` + Options +} + +type flannelCommon Flannel + +type FlannelVersion semver.Version + +func (v *FlannelVersion) UnmarshalYAML(unmarshal func(interface{}) error) error { + t := semver.Version(*v) + if err := unmarshal(&t); err != nil { + return err + } + *v = FlannelVersion(t) + return nil +} + +func (fv FlannelVersion) Validate() report.Report { + v := semver.Version(fv) + switch { + case v.LessThan(OldestFlannelVersion): + return report.ReportFromError(ErrFlannelTooOld, report.EntryError) + case v.Major == 0 && fv.Minor > 7: + return report.ReportFromError(ErrFlannelMinorTooNew, report.EntryWarning) + } + return report.Report{} +} + +func (fv FlannelVersion) String() string { + return semver.Version(fv).String() +} + +func (flannel *Flannel) UnmarshalYAML(unmarshal func(interface{}) error) error { + t := flannelCommon(*flannel) + if err := unmarshal(&t); err != nil { + return err + } + *flannel = Flannel(t) + + var v semver.Version + if flannel.Version == nil { + v = FlannelDefaultVersion + } else { + v = semver.Version(*flannel.Version) + } + + if v.Major == 0 && v.Minor >= 7 { + o := Flannel0_7{} + if err := unmarshal(&o); err != nil { + return err + } + flannel.Options = o + } else if v.Major == 0 && v.Minor == 6 { + o := Flannel0_6{} + if err := unmarshal(&o); err != nil { + return err + } + flannel.Options = o + } else if v.Major == 0 && v.Minor == 5 { + o := Flannel0_5{} + if err := unmarshal(&o); err != nil { + return err + } + flannel.Options = o + } + return nil +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + if in.Flannel != nil { + contents, err := flannelContents(*in.Flannel, platform) + if err != nil { + return ignTypes.Config{}, report.ReportFromError(err, report.EntryError) + } + out.Systemd.Units = append(out.Systemd.Units, ignTypes.SystemdUnit{ + Name: "flanneld.service", + Enable: true, + DropIns: []ignTypes.SystemdUnitDropIn{{ + Name: "20-clct-flannel.conf", + Contents: contents, + }}, + }) + } + return out, report.Report{} + }) +} + +// flannelContents creates the string containing the systemd drop in for flannel +func flannelContents(flannel Flannel, platform string) (string, error) { + args := getCliArgs(flannel.Options) + vars := []string{fmt.Sprintf("FLANNEL_IMAGE_TAG=v%s", flannel.Version)} + + return assembleUnit("/usr/lib/coreos/flannel-wrapper $FLANNEL_OPTS", args, vars, platform) +} + +// Flannel0_7 represents flannel options for version 0.7.x. Don't embed Flannel0_6 because +// the yaml parser doesn't handle embedded structs +type Flannel0_7 struct { + EtcdUsername string `yaml:"etcd_username" cli:"etcd-username"` + EtcdPassword string `yaml:"etcd_password" cli:"etcd-password"` + EtcdEndpoints string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` + EtcdCAFile string `yaml:"etcd_cafile" cli:"etcd-cafile"` + EtcdCertFile string `yaml:"etcd_certfile" cli:"etcd-certfile"` + EtcdKeyFile string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` + EtcdPrefix string `yaml:"etcd_prefix" cli:"etcd-prefix"` + IPMasq string `yaml:"ip_masq" cli:"ip-masq"` + SubnetFile string `yaml:"subnet_file" cli:"subnet-file"` + Iface string `yaml:"interface" cli:"iface"` + PublicIP string `yaml:"public_ip" cli:"public-ip"` + KubeSubnetMgr bool `yaml:"kube_subnet_mgr" cli:"kube-subnet-mgr"` +} + +type Flannel0_6 struct { + EtcdUsername string `yaml:"etcd_username" cli:"etcd-username"` + EtcdPassword string `yaml:"etcd_password" cli:"etcd-password"` + EtcdEndpoints string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` + EtcdCAFile string `yaml:"etcd_cafile" cli:"etcd-cafile"` + EtcdCertFile string `yaml:"etcd_certfile" cli:"etcd-certfile"` + EtcdKeyFile string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` + EtcdPrefix string `yaml:"etcd_prefix" cli:"etcd-prefix"` + IPMasq string `yaml:"ip_masq" cli:"ip-masq"` + SubnetFile string `yaml:"subnet_file" cli:"subnet-file"` + Iface string `yaml:"interface" cli:"iface"` + PublicIP string `yaml:"public_ip" cli:"public-ip"` +} + +type Flannel0_5 struct { + EtcdEndpoints string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` + EtcdCAFile string `yaml:"etcd_cafile" cli:"etcd-cafile"` + EtcdCertFile string `yaml:"etcd_certfile" cli:"etcd-certfile"` + EtcdKeyFile string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` + EtcdPrefix string `yaml:"etcd_prefix" cli:"etcd-prefix"` + IPMasq string `yaml:"ip_masq" cli:"ip-masq"` + SubnetFile string `yaml:"subnet_file" cli:"subnet-file"` + Iface string `yaml:"interface" cli:"iface"` + PublicIP string `yaml:"public_ip" cli:"public-ip"` +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/locksmith.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/locksmith.go new file mode 100644 index 00000000..9c91de73 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/locksmith.go @@ -0,0 +1,41 @@ +// Copyright 2017 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "errors" + "strings" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrUnknownStrategy = errors.New("unknown reboot strategy") +) + +type Locksmith struct { + RebootStrategy RebootStrategy `yaml:"reboot_strategy"` +} + +type RebootStrategy string + +func (r RebootStrategy) Validate() report.Report { + switch strings.ToLower(string(r)) { + case "reboot", "etcd-lock", "off": + return report.Report{} + default: + return report.ReportFromError(ErrUnknownStrategy, report.EntryError) + } +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/networkd.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/networkd.go new file mode 100644 index 00000000..5191aabb --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/networkd.go @@ -0,0 +1,41 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +type Networkd struct { + Units []NetworkdUnit `yaml:"units"` +} + +type NetworkdUnit struct { + Name string `yaml:"name"` + Contents string `yaml:"contents"` +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + for _, unit := range in.Networkd.Units { + out.Networkd.Units = append(out.Networkd.Units, ignTypes.NetworkdUnit{ + Name: ignTypes.NetworkdUnitName(unit.Name), + Contents: unit.Contents, + }) + } + return out, report.Report{} + }) +} diff --git a/vendor/github.com/coreos/fuze/config/types/passwd.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/passwd.go similarity index 54% rename from vendor/github.com/coreos/fuze/config/types/passwd.go rename to vendor/github.com/coreos/container-linux-config-transpiler/config/types/passwd.go index 5e064798..950c8ba7 100644 --- a/vendor/github.com/coreos/fuze/config/types/passwd.go +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/passwd.go @@ -14,6 +14,11 @@ package types +import ( + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + type Passwd struct { Users []User `yaml:"users"` Groups []Group `yaml:"groups"` @@ -45,3 +50,42 @@ type Group struct { PasswordHash string `yaml:"password_hash"` System bool `yaml:"system"` } + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + for _, user := range in.Passwd.Users { + newUser := ignTypes.User{ + Name: user.Name, + PasswordHash: user.PasswordHash, + SSHAuthorizedKeys: user.SSHAuthorizedKeys, + } + + if user.Create != nil { + newUser.Create = &ignTypes.UserCreate{ + Uid: user.Create.Uid, + GECOS: user.Create.GECOS, + Homedir: user.Create.Homedir, + NoCreateHome: user.Create.NoCreateHome, + PrimaryGroup: user.Create.PrimaryGroup, + Groups: user.Create.Groups, + NoUserGroup: user.Create.NoUserGroup, + System: user.Create.System, + NoLogInit: user.Create.NoLogInit, + Shell: user.Create.Shell, + } + } + + out.Passwd.Users = append(out.Passwd.Users, newUser) + } + + for _, group := range in.Passwd.Groups { + out.Passwd.Groups = append(out.Passwd.Groups, ignTypes.Group{ + Name: group.Name, + Gid: group.Gid, + PasswordHash: group.PasswordHash, + System: group.System, + }) + } + return out, report.Report{} + }) +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/raid.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/raid.go new file mode 100644 index 00000000..9d11d868 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/raid.go @@ -0,0 +1,46 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +type Raid struct { + Name string `yaml:"name"` + Level string `yaml:"level"` + Devices []string `yaml:"devices"` + Spares int `yaml:"spares"` +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + for _, array := range in.Storage.Arrays { + newArray := ignTypes.Raid{ + Name: array.Name, + Level: array.Level, + Spares: array.Spares, + } + + for _, device := range array.Devices { + newArray.Devices = append(newArray.Devices, ignTypes.Path(device)) + } + + out.Storage.Arrays = append(out.Storage.Arrays, newArray) + } + return out, report.Report{} + }) +} diff --git a/vendor/github.com/coreos/fuze/config/types/storage.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/storage.go similarity index 100% rename from vendor/github.com/coreos/fuze/config/types/storage.go rename to vendor/github.com/coreos/container-linux-config-transpiler/config/types/storage.go diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/systemd.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/systemd.go new file mode 100644 index 00000000..ea6a9935 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/systemd.go @@ -0,0 +1,60 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" +) + +type Systemd struct { + Units []SystemdUnit `yaml:"units"` +} + +type SystemdUnit struct { + Name string `yaml:"name"` + Enable bool `yaml:"enable"` + Mask bool `yaml:"mask"` + Contents string `yaml:"contents"` + DropIns []SystemdUnitDropIn `yaml:"dropins"` +} + +type SystemdUnitDropIn struct { + Name string `yaml:"name"` + Contents string `yaml:"contents"` +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + for _, unit := range in.Systemd.Units { + newUnit := ignTypes.SystemdUnit{ + Name: ignTypes.SystemdUnitName(unit.Name), + Enable: unit.Enable, + Mask: unit.Mask, + Contents: unit.Contents, + } + + for _, dropIn := range unit.DropIns { + newUnit.DropIns = append(newUnit.DropIns, ignTypes.SystemdUnitDropIn{ + Name: ignTypes.SystemdUnitDropInName(dropIn.Name), + Contents: dropIn.Contents, + }) + } + + out.Systemd.Units = append(out.Systemd.Units, newUnit) + } + return out, report.Report{} + }) +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/update.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/update.go new file mode 100644 index 00000000..4adf0d01 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/update.go @@ -0,0 +1,91 @@ +// Copyright 2017 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "errors" + "fmt" + "net/url" + "strings" + + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" + "github.com/vincent-petithory/dataurl" +) + +var ( + ErrUnknownGroup = errors.New("unknown update group") +) + +type Update struct { + Group UpdateGroup `yaml:"group"` + Server UpdateServer `yaml:"server"` +} + +type UpdateGroup string +type UpdateServer string + +func (u Update) Validate() report.Report { + switch strings.ToLower(string(u.Group)) { + case "stable", "beta", "alpha": + return report.Report{} + default: + if u.Server == "" { + return report.ReportFromError(ErrUnknownGroup, report.EntryWarning) + } + return report.Report{} + } +} + +func (s UpdateServer) Validate() report.Report { + _, err := url.Parse(string(s)) + if err != nil { + return report.ReportFromError(err, report.EntryError) + } + return report.Report{} +} + +func init() { + register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + var contents string + if in.Update != nil { + if in.Update.Group != "" { + contents += fmt.Sprintf("GROUP=%s", strings.ToLower(string(in.Update.Group))) + } + if in.Update.Server != "" { + contents += fmt.Sprintf("\nSERVER=%s", in.Update.Server) + } + } + if in.Locksmith != nil { + if in.Locksmith.RebootStrategy != "" { + contents += fmt.Sprintf("\nREBOOT_STRATEGY=%s", strings.ToLower(string(in.Locksmith.RebootStrategy))) + } + } + if contents != "" { + out.Storage.Files = append(out.Storage.Files, ignTypes.File{ + Filesystem: "root", + Path: "/etc/coreos/update.conf", + Mode: 0644, + Contents: ignTypes.FileContents{ + Source: ignTypes.Url{ + Scheme: "data", + Opaque: "," + dataurl.EscapeString(contents), + }, + }, + }) + } + return out, report.Report{} + }) +} diff --git a/vendor/github.com/coreos/fuze/config/types/verification.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/verification.go similarity index 100% rename from vendor/github.com/coreos/fuze/config/types/verification.go rename to vendor/github.com/coreos/container-linux-config-transpiler/config/types/verification.go diff --git a/vendor/github.com/coreos/fuze/config/convert.go b/vendor/github.com/coreos/fuze/config/convert.go deleted file mode 100644 index 5b886d59..00000000 --- a/vendor/github.com/coreos/fuze/config/convert.go +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright 2016 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package config - -import ( - "fmt" - "net/url" - "reflect" - - "github.com/alecthomas/units" - fuzeTypes "github.com/coreos/fuze/config/types" - "github.com/coreos/ignition/config/types" - "github.com/coreos/ignition/config/validate" - "github.com/coreos/ignition/config/validate/report" - "github.com/vincent-petithory/dataurl" -) - -const ( - BYTES_PER_SECTOR = 512 -) - -func ConvertAs2_0_0(in fuzeTypes.Config) (types.Config, report.Report) { - out := types.Config{ - Ignition: types.Ignition{ - Version: types.IgnitionVersion{Major: 2, Minor: 0}, - }, - } - - for _, ref := range in.Ignition.Config.Append { - newRef, err := convertConfigReference(ref) - if err != nil { - return types.Config{}, report.ReportFromError(err, report.EntryError) - } - out.Ignition.Config.Append = append(out.Ignition.Config.Append, newRef) - } - - if in.Ignition.Config.Replace != nil { - newRef, err := convertConfigReference(*in.Ignition.Config.Replace) - if err != nil { - return types.Config{}, report.ReportFromError(err, report.EntryError) - } - out.Ignition.Config.Replace = &newRef - } - - for _, disk := range in.Storage.Disks { - newDisk := types.Disk{ - Device: types.Path(disk.Device), - WipeTable: disk.WipeTable, - } - - for _, partition := range disk.Partitions { - size, err := convertPartitionDimension(partition.Size) - if err != nil { - return types.Config{}, report.ReportFromError(err, report.EntryError) - } - start, err := convertPartitionDimension(partition.Start) - if err != nil { - return types.Config{}, report.ReportFromError(err, report.EntryError) - } - - newDisk.Partitions = append(newDisk.Partitions, types.Partition{ - Label: types.PartitionLabel(partition.Label), - Number: partition.Number, - Size: size, - Start: start, - TypeGUID: types.PartitionTypeGUID(partition.TypeGUID), - }) - } - - out.Storage.Disks = append(out.Storage.Disks, newDisk) - } - - for _, array := range in.Storage.Arrays { - newArray := types.Raid{ - Name: array.Name, - Level: array.Level, - Spares: array.Spares, - } - - for _, device := range array.Devices { - newArray.Devices = append(newArray.Devices, types.Path(device)) - } - - out.Storage.Arrays = append(out.Storage.Arrays, newArray) - } - - for _, filesystem := range in.Storage.Filesystems { - newFilesystem := types.Filesystem{ - Name: filesystem.Name, - Path: func(p types.Path) *types.Path { - if p == "" { - return nil - } - - return &p - }(types.Path(filesystem.Path)), - } - - if filesystem.Mount != nil { - newFilesystem.Mount = &types.FilesystemMount{ - Device: types.Path(filesystem.Mount.Device), - Format: types.FilesystemFormat(filesystem.Mount.Format), - } - - if filesystem.Mount.Create != nil { - newFilesystem.Mount.Create = &types.FilesystemCreate{ - Force: filesystem.Mount.Create.Force, - Options: types.MkfsOptions(filesystem.Mount.Create.Options), - } - } - } - - out.Storage.Filesystems = append(out.Storage.Filesystems, newFilesystem) - } - - for _, file := range in.Storage.Files { - newFile := types.File{ - Filesystem: file.Filesystem, - Path: types.Path(file.Path), - Mode: types.FileMode(file.Mode), - User: types.FileUser{Id: file.User.Id}, - Group: types.FileGroup{Id: file.Group.Id}, - } - - if file.Contents.Inline != "" { - newFile.Contents = types.FileContents{ - Source: types.Url{ - Scheme: "data", - Opaque: "," + dataurl.EscapeString(file.Contents.Inline), - }, - } - } - - if file.Contents.Remote.Url != "" { - source, err := url.Parse(file.Contents.Remote.Url) - if err != nil { - return types.Config{}, report.ReportFromError(err, report.EntryError) - } - - newFile.Contents = types.FileContents{Source: types.Url(*source)} - } - - if newFile.Contents == (types.FileContents{}) { - newFile.Contents = types.FileContents{ - Source: types.Url{ - Scheme: "data", - Opaque: ",", - }, - } - } - - newFile.Contents.Compression = types.Compression(file.Contents.Remote.Compression) - newFile.Contents.Verification = convertVerification(file.Contents.Remote.Verification) - - out.Storage.Files = append(out.Storage.Files, newFile) - } - - for _, unit := range in.Systemd.Units { - newUnit := types.SystemdUnit{ - Name: types.SystemdUnitName(unit.Name), - Enable: unit.Enable, - Mask: unit.Mask, - Contents: unit.Contents, - } - - for _, dropIn := range unit.DropIns { - newUnit.DropIns = append(newUnit.DropIns, types.SystemdUnitDropIn{ - Name: types.SystemdUnitDropInName(dropIn.Name), - Contents: dropIn.Contents, - }) - } - - out.Systemd.Units = append(out.Systemd.Units, newUnit) - } - - for _, unit := range in.Networkd.Units { - out.Networkd.Units = append(out.Networkd.Units, types.NetworkdUnit{ - Name: types.NetworkdUnitName(unit.Name), - Contents: unit.Contents, - }) - } - - for _, user := range in.Passwd.Users { - newUser := types.User{ - Name: user.Name, - PasswordHash: user.PasswordHash, - SSHAuthorizedKeys: user.SSHAuthorizedKeys, - } - - if user.Create != nil { - newUser.Create = &types.UserCreate{ - Uid: user.Create.Uid, - GECOS: user.Create.GECOS, - Homedir: user.Create.Homedir, - NoCreateHome: user.Create.NoCreateHome, - PrimaryGroup: user.Create.PrimaryGroup, - Groups: user.Create.Groups, - NoUserGroup: user.Create.NoUserGroup, - System: user.Create.System, - NoLogInit: user.Create.NoLogInit, - Shell: user.Create.Shell, - } - } - - out.Passwd.Users = append(out.Passwd.Users, newUser) - } - - for _, group := range in.Passwd.Groups { - out.Passwd.Groups = append(out.Passwd.Groups, types.Group{ - Name: group.Name, - Gid: group.Gid, - PasswordHash: group.PasswordHash, - System: group.System, - }) - } - - r := validate.ValidateWithoutSource(reflect.ValueOf(out)) - if r.IsFatal() { - return types.Config{}, r - } - - return out, r -} - -func convertConfigReference(in fuzeTypes.ConfigReference) (types.ConfigReference, error) { - source, err := url.Parse(in.Source) - if err != nil { - return types.ConfigReference{}, err - } - - return types.ConfigReference{ - Source: types.Url(*source), - Verification: convertVerification(in.Verification), - }, nil -} - -func convertVerification(in fuzeTypes.Verification) types.Verification { - if in.Hash.Function == "" || in.Hash.Sum == "" { - return types.Verification{} - } - - return types.Verification{ - &types.Hash{ - Function: in.Hash.Function, - Sum: in.Hash.Sum, - }, - } -} - -func convertPartitionDimension(in string) (types.PartitionDimension, error) { - if in == "" { - return 0, nil - } - - b, err := units.ParseBase2Bytes(in) - if err != nil { - return 0, err - } - if b < 0 { - return 0, fmt.Errorf("invalid dimension (negative): %q", in) - } - - // Translate bytes into sectors - sectors := (b / BYTES_PER_SECTOR) - if b%BYTES_PER_SECTOR != 0 { - sectors++ - } - return types.PartitionDimension(uint64(sectors)), nil -} diff --git a/vendor/github.com/coreos/fuze/config/types/config.go b/vendor/github.com/coreos/fuze/config/types/config.go deleted file mode 100644 index ceddd26b..00000000 --- a/vendor/github.com/coreos/fuze/config/types/config.go +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2016 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -type Config struct { - Ignition Ignition `yaml:"ignition"` - Storage Storage `yaml:"storage"` - Systemd Systemd `yaml:"systemd"` - Networkd Networkd `yaml:"networkd"` - Passwd Passwd `yaml:"passwd"` -} - -type Ignition struct { - Config IgnitionConfig `yaml:"config"` -} - -type IgnitionConfig struct { - Append []ConfigReference `yaml:"append"` - Replace *ConfigReference `yaml:"replace"` -} - -type ConfigReference struct { - Source string `yaml:"source"` - Verification Verification `yaml:"verification"` -} diff --git a/vendor/github.com/coreos/fuze/config/types/files.go b/vendor/github.com/coreos/fuze/config/types/files.go deleted file mode 100644 index c0749094..00000000 --- a/vendor/github.com/coreos/fuze/config/types/files.go +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2016 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package types - -type File struct { - Filesystem string `yaml:"filesystem"` - Path string `yaml:"path"` - Mode int `yaml:"mode"` - Contents FileContents `yaml:"contents"` - User FileUser `yaml:"user"` - Group FileGroup `yaml:"group"` -} - -type FileContents struct { - Remote Remote `yaml:"remote"` - Inline string `yaml:"inline"` -} - -type Remote struct { - Url string `yaml:"url"` - Compression string `yaml:"compression"` - Verification Verification `yaml:"verification"` -} - -type FileUser struct { - Id int `yaml:"id"` -} - -type FileGroup struct { - Id int `yaml:"id"` -} diff --git a/vendor/github.com/coreos/go-semver/semver/semver.go b/vendor/github.com/coreos/go-semver/semver/semver.go index 000a0205..9c8072d1 100644 --- a/vendor/github.com/coreos/go-semver/semver/semver.go +++ b/vendor/github.com/coreos/go-semver/semver/semver.go @@ -44,16 +44,36 @@ func splitOff(input *string, delim string) (val string) { return val } +func New(version string) *Version { + return Must(NewVersion(version)) +} + func NewVersion(version string) (*Version, error) { v := Version{} - v.Metadata = splitOff(&version, "+") - v.PreRelease = PreRelease(splitOff(&version, "-")) + if err := v.Set(version); err != nil { + return nil, err + } + return &v, nil +} + +// Must is a helper for wrapping NewVersion and will panic if err is not nil. +func Must(v *Version, err error) *Version { + if err != nil { + panic(err) + } + return v +} + +// Set parses and updates v from the given version string. Implements flag.Value +func (v *Version) Set(version string) error { + metadata := splitOff(&version, "+") + preRelease := PreRelease(splitOff(&version, "-")) dotParts := strings.SplitN(version, ".", 3) if len(dotParts) != 3 { - return nil, errors.New(fmt.Sprintf("%s is not in dotted-tri format", version)) + return fmt.Errorf("%s is not in dotted-tri format", version) } parsed := make([]int64, 3, 3) @@ -62,22 +82,16 @@ func NewVersion(version string) (*Version, error) { val, err := strconv.ParseInt(v, 10, 64) parsed[i] = val if err != nil { - return nil, err + return err } } + v.Metadata = metadata + v.PreRelease = preRelease v.Major = parsed[0] v.Minor = parsed[1] v.Patch = parsed[2] - - return &v, nil -} - -func Must(v *Version, err error) *Version { - if err != nil { - panic(err) - } - return v + return nil } func (v Version) String() string { @@ -101,12 +115,7 @@ func (v *Version) UnmarshalYAML(unmarshal func(interface{}) error) error { if err := unmarshal(&data); err != nil { return err } - vv, err := NewVersion(data) - if err != nil { - return err - } - *v = *vv - return nil + return v.Set(data) } func (v Version) MarshalJSON() ([]byte, error) { @@ -121,30 +130,29 @@ func (v *Version) UnmarshalJSON(data []byte) error { if l < 2 || data[0] != '"' || data[l-1] != '"' { return errors.New("invalid semver string") } - vv, err := NewVersion(string(data[1 : l-1])) - if err != nil { - return err - } - *v = *vv - return nil + return v.Set(string(data[1 : l-1])) } +// Compare tests if v is less than, equal to, or greater than versionB, +// returning -1, 0, or +1 respectively. +func (v Version) Compare(versionB Version) int { + if cmp := recursiveCompare(v.Slice(), versionB.Slice()); cmp != 0 { + return cmp + } + return preReleaseCompare(v, versionB) +} + +// Equal tests if v is equal to versionB. +func (v Version) Equal(versionB Version) bool { + return v.Compare(versionB) == 0 +} + +// LessThan tests if v is less than versionB. func (v Version) LessThan(versionB Version) bool { - versionA := v - cmp := recursiveCompare(versionA.Slice(), versionB.Slice()) - - if cmp == 0 { - cmp = preReleaseCompare(versionA, versionB) - } - - if cmp == -1 { - return true - } - - return false + return v.Compare(versionB) < 0 } -/* Slice converts the comparable parts of the semver into a slice of strings */ +// Slice converts the comparable parts of the semver into a slice of integers. func (v Version) Slice() []int64 { return []int64{v.Major, v.Minor, v.Patch} } @@ -166,7 +174,7 @@ func preReleaseCompare(versionA Version, versionB Version) int { return -1 } - // If there is a prelease, check and compare each part. + // If there is a prerelease, check and compare each part. return recursivePreReleaseCompare(a.Slice(), b.Slice()) } @@ -188,9 +196,12 @@ func recursiveCompare(versionA []int64, versionB []int64) int { } func recursivePreReleaseCompare(versionA []string, versionB []string) int { - // Handle slice length disparity. + // A larger set of pre-release fields has a higher precedence than a smaller set, + // if all of the preceding identifiers are equal. if len(versionA) == 0 { - // Nothing to compare too, so we return 0 + if len(versionB) > 0 { + return -1 + } return 0 } else if len(versionB) == 0 { // We're longer than versionB so return 1. @@ -213,6 +224,13 @@ func recursivePreReleaseCompare(versionA []string, versionB []string) int { bInt = true } + // Numeric identifiers always have lower precedence than non-numeric identifiers. + if aInt && !bInt { + return -1 + } else if !aInt && bInt { + return 1 + } + // Handle Integer Comparison if aInt && bInt { if aI > bI { diff --git a/vendor/github.com/coreos/go-systemd/unit/deserialize.go b/vendor/github.com/coreos/go-systemd/unit/deserialize.go new file mode 100644 index 00000000..8a88162f --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/unit/deserialize.go @@ -0,0 +1,276 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unit + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "io" + "strings" + "unicode" +) + +const ( + // SYSTEMD_LINE_MAX mimics the maximum line length that systemd can use. + // On typical systemd platforms (i.e. modern Linux), this will most + // commonly be 2048, so let's use that as a sanity check. + // Technically, we should probably pull this at runtime: + // SYSTEMD_LINE_MAX = int(C.sysconf(C.__SC_LINE_MAX)) + // but this would introduce an (unfortunate) dependency on cgo + SYSTEMD_LINE_MAX = 2048 + + // characters that systemd considers indicate a newline + SYSTEMD_NEWLINE = "\r\n" +) + +var ( + ErrLineTooLong = fmt.Errorf("line too long (max %d bytes)", SYSTEMD_LINE_MAX) +) + +// Deserialize parses a systemd unit file into a list of UnitOption objects. +func Deserialize(f io.Reader) (opts []*UnitOption, err error) { + lexer, optchan, errchan := newLexer(f) + go lexer.lex() + + for opt := range optchan { + opts = append(opts, &(*opt)) + } + + err = <-errchan + return opts, err +} + +func newLexer(f io.Reader) (*lexer, <-chan *UnitOption, <-chan error) { + optchan := make(chan *UnitOption) + errchan := make(chan error, 1) + buf := bufio.NewReader(f) + + return &lexer{buf, optchan, errchan, ""}, optchan, errchan +} + +type lexer struct { + buf *bufio.Reader + optchan chan *UnitOption + errchan chan error + section string +} + +func (l *lexer) lex() { + var err error + defer func() { + close(l.optchan) + close(l.errchan) + }() + next := l.lexNextSection + for next != nil { + if l.buf.Buffered() >= SYSTEMD_LINE_MAX { + // systemd truncates lines longer than LINE_MAX + // https://bugs.freedesktop.org/show_bug.cgi?id=85308 + // Rather than allowing this to pass silently, let's + // explicitly gate people from encountering this + line, err := l.buf.Peek(SYSTEMD_LINE_MAX) + if err != nil { + l.errchan <- err + return + } + if bytes.IndexAny(line, SYSTEMD_NEWLINE) == -1 { + l.errchan <- ErrLineTooLong + return + } + } + + next, err = next() + if err != nil { + l.errchan <- err + return + } + } +} + +type lexStep func() (lexStep, error) + +func (l *lexer) lexSectionName() (lexStep, error) { + sec, err := l.buf.ReadBytes(']') + if err != nil { + return nil, errors.New("unable to find end of section") + } + + return l.lexSectionSuffixFunc(string(sec[:len(sec)-1])), nil +} + +func (l *lexer) lexSectionSuffixFunc(section string) lexStep { + return func() (lexStep, error) { + garbage, _, err := l.toEOL() + if err != nil { + return nil, err + } + + garbage = bytes.TrimSpace(garbage) + if len(garbage) > 0 { + return nil, fmt.Errorf("found garbage after section name %s: %v", l.section, garbage) + } + + return l.lexNextSectionOrOptionFunc(section), nil + } +} + +func (l *lexer) ignoreLineFunc(next lexStep) lexStep { + return func() (lexStep, error) { + for { + line, _, err := l.toEOL() + if err != nil { + return nil, err + } + + line = bytes.TrimSuffix(line, []byte{' '}) + + // lack of continuation means this line has been exhausted + if !bytes.HasSuffix(line, []byte{'\\'}) { + break + } + } + + // reached end of buffer, safe to exit + return next, nil + } +} + +func (l *lexer) lexNextSection() (lexStep, error) { + r, _, err := l.buf.ReadRune() + if err != nil { + if err == io.EOF { + err = nil + } + return nil, err + } + + if r == '[' { + return l.lexSectionName, nil + } else if isComment(r) { + return l.ignoreLineFunc(l.lexNextSection), nil + } + + return l.lexNextSection, nil +} + +func (l *lexer) lexNextSectionOrOptionFunc(section string) lexStep { + return func() (lexStep, error) { + r, _, err := l.buf.ReadRune() + if err != nil { + if err == io.EOF { + err = nil + } + return nil, err + } + + if unicode.IsSpace(r) { + return l.lexNextSectionOrOptionFunc(section), nil + } else if r == '[' { + return l.lexSectionName, nil + } else if isComment(r) { + return l.ignoreLineFunc(l.lexNextSectionOrOptionFunc(section)), nil + } + + l.buf.UnreadRune() + return l.lexOptionNameFunc(section), nil + } +} + +func (l *lexer) lexOptionNameFunc(section string) lexStep { + return func() (lexStep, error) { + var partial bytes.Buffer + for { + r, _, err := l.buf.ReadRune() + if err != nil { + return nil, err + } + + if r == '\n' || r == '\r' { + return nil, errors.New("unexpected newline encountered while parsing option name") + } + + if r == '=' { + break + } + + partial.WriteRune(r) + } + + name := strings.TrimSpace(partial.String()) + return l.lexOptionValueFunc(section, name, bytes.Buffer{}), nil + } +} + +func (l *lexer) lexOptionValueFunc(section, name string, partial bytes.Buffer) lexStep { + return func() (lexStep, error) { + for { + line, eof, err := l.toEOL() + if err != nil { + return nil, err + } + + if len(bytes.TrimSpace(line)) == 0 { + break + } + + partial.Write(line) + + // lack of continuation means this value has been exhausted + idx := bytes.LastIndex(line, []byte{'\\'}) + if idx == -1 || idx != (len(line)-1) { + break + } + + if !eof { + partial.WriteRune('\n') + } + + return l.lexOptionValueFunc(section, name, partial), nil + } + + val := partial.String() + if strings.HasSuffix(val, "\n") { + // A newline was added to the end, so the file didn't end with a backslash. + // => Keep the newline + val = strings.TrimSpace(val) + "\n" + } else { + val = strings.TrimSpace(val) + } + l.optchan <- &UnitOption{Section: section, Name: name, Value: val} + + return l.lexNextSectionOrOptionFunc(section), nil + } +} + +// toEOL reads until the end-of-line or end-of-file. +// Returns (data, EOFfound, error) +func (l *lexer) toEOL() ([]byte, bool, error) { + line, err := l.buf.ReadBytes('\n') + // ignore EOF here since it's roughly equivalent to EOL + if err != nil && err != io.EOF { + return nil, false, err + } + + line = bytes.TrimSuffix(line, []byte{'\r'}) + line = bytes.TrimSuffix(line, []byte{'\n'}) + + return line, err == io.EOF, nil +} + +func isComment(r rune) bool { + return r == '#' || r == ';' +} diff --git a/vendor/github.com/coreos/go-systemd/unit/escape.go b/vendor/github.com/coreos/go-systemd/unit/escape.go new file mode 100644 index 00000000..63b11726 --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/unit/escape.go @@ -0,0 +1,116 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Implements systemd-escape [--unescape] [--path] + +package unit + +import ( + "fmt" + "strconv" + "strings" +) + +const ( + allowed = `:_.abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789` +) + +// If isPath is true: +// We remove redundant '/'s, the leading '/', and trailing '/'. +// If the result is empty, a '/' is inserted. +// +// We always: +// Replace the following characters with `\x%x`: +// Leading `.` +// `-`, `\`, and anything not in this set: `:-_.\[0-9a-zA-Z]` +// Replace '/' with '-'. +func escape(unescaped string, isPath bool) string { + e := []byte{} + inSlashes := false + start := true + for i := 0; i < len(unescaped); i++ { + c := unescaped[i] + if isPath { + if c == '/' { + inSlashes = true + continue + } else if inSlashes { + inSlashes = false + if !start { + e = append(e, '-') + } + } + } + + if c == '/' { + e = append(e, '-') + } else if start && c == '.' || strings.IndexByte(allowed, c) == -1 { + e = append(e, []byte(fmt.Sprintf(`\x%x`, c))...) + } else { + e = append(e, c) + } + start = false + } + if isPath && len(e) == 0 { + e = append(e, '-') + } + return string(e) +} + +// If isPath is true: +// We always return a string beginning with '/'. +// +// We always: +// Replace '-' with '/'. +// Replace `\x%x` with the value represented in hex. +func unescape(escaped string, isPath bool) string { + u := []byte{} + for i := 0; i < len(escaped); i++ { + c := escaped[i] + if c == '-' { + c = '/' + } else if c == '\\' && len(escaped)-i >= 4 && escaped[i+1] == 'x' { + n, err := strconv.ParseInt(escaped[i+2:i+4], 16, 8) + if err == nil { + c = byte(n) + i += 3 + } + } + u = append(u, c) + } + if isPath && (len(u) == 0 || u[0] != '/') { + u = append([]byte("/"), u...) + } + return string(u) +} + +// UnitNameEscape escapes a string as `systemd-escape` would +func UnitNameEscape(unescaped string) string { + return escape(unescaped, false) +} + +// UnitNameUnescape unescapes a string as `systemd-escape --unescape` would +func UnitNameUnescape(escaped string) string { + return unescape(escaped, false) +} + +// UnitNamePathEscape escapes a string as `systemd-escape --path` would +func UnitNamePathEscape(unescaped string) string { + return escape(unescaped, true) +} + +// UnitNamePathUnescape unescapes a string as `systemd-escape --path --unescape` would +func UnitNamePathUnescape(escaped string) string { + return unescape(escaped, true) +} diff --git a/vendor/github.com/coreos/go-systemd/unit/option.go b/vendor/github.com/coreos/go-systemd/unit/option.go new file mode 100644 index 00000000..e5d21e19 --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/unit/option.go @@ -0,0 +1,54 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unit + +import ( + "fmt" +) + +type UnitOption struct { + Section string + Name string + Value string +} + +func NewUnitOption(section, name, value string) *UnitOption { + return &UnitOption{Section: section, Name: name, Value: value} +} + +func (uo *UnitOption) String() string { + return fmt.Sprintf("{Section: %q, Name: %q, Value: %q}", uo.Section, uo.Name, uo.Value) +} + +func (uo *UnitOption) Match(other *UnitOption) bool { + return uo.Section == other.Section && + uo.Name == other.Name && + uo.Value == other.Value +} + +func AllMatch(u1 []*UnitOption, u2 []*UnitOption) bool { + length := len(u1) + if length != len(u2) { + return false + } + + for i := 0; i < length; i++ { + if !u1[i].Match(u2[i]) { + return false + } + } + + return true +} diff --git a/vendor/github.com/coreos/go-systemd/unit/serialize.go b/vendor/github.com/coreos/go-systemd/unit/serialize.go new file mode 100644 index 00000000..e07799ca --- /dev/null +++ b/vendor/github.com/coreos/go-systemd/unit/serialize.go @@ -0,0 +1,75 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package unit + +import ( + "bytes" + "io" +) + +// Serialize encodes all of the given UnitOption objects into a +// unit file. When serialized the options are sorted in their +// supplied order but grouped by section. +func Serialize(opts []*UnitOption) io.Reader { + var buf bytes.Buffer + + if len(opts) == 0 { + return &buf + } + + // Index of sections -> ordered options + idx := map[string][]*UnitOption{} + // Separately preserve order in which sections were seen + sections := []string{} + for _, opt := range opts { + sec := opt.Section + if _, ok := idx[sec]; !ok { + sections = append(sections, sec) + } + idx[sec] = append(idx[sec], opt) + } + + for i, sect := range sections { + writeSectionHeader(&buf, sect) + writeNewline(&buf) + + opts := idx[sect] + for _, opt := range opts { + writeOption(&buf, opt) + writeNewline(&buf) + } + if i < len(sections)-1 { + writeNewline(&buf) + } + } + + return &buf +} + +func writeNewline(buf *bytes.Buffer) { + buf.WriteRune('\n') +} + +func writeSectionHeader(buf *bytes.Buffer, section string) { + buf.WriteRune('[') + buf.WriteString(section) + buf.WriteRune(']') +} + +func writeOption(buf *bytes.Buffer, opt *UnitOption) { + buf.WriteString(opt.Name) + buf.WriteRune('=') + buf.WriteString(opt.Value) +} diff --git a/vendor/github.com/coreos/ignition/config/config.go b/vendor/github.com/coreos/ignition/config/config.go index 78ec4ec2..fc41815b 100644 --- a/vendor/github.com/coreos/ignition/config/config.go +++ b/vendor/github.com/coreos/ignition/config/config.go @@ -21,6 +21,7 @@ import ( "github.com/coreos/ignition/config/types" "github.com/coreos/ignition/config/v1" + "github.com/coreos/ignition/config/v2_0" "github.com/coreos/ignition/config/validate" astjson "github.com/coreos/ignition/config/validate/astjson" "github.com/coreos/ignition/config/validate/report" @@ -40,14 +41,16 @@ var ( // Parse parses the raw config into a types.Config struct and generates a report of any // errors, warnings, info, and deprecations it encountered func Parse(rawConfig []byte) (types.Config, report.Report, error) { - switch majorVersion(rawConfig) { - case 1: + switch version(rawConfig) { + case types.IgnitionVersion{Major: 1}: config, err := ParseFromV1(rawConfig) if err != nil { return types.Config{}, report.ReportFromError(err, report.EntryError), err } return config, report.ReportFromError(ErrDeprecated, report.EntryDeprecated), nil + case types.IgnitionVersion{Major: 2, Minor: 0}: + return ParseFromV2_0(rawConfig) default: return ParseFromLatest(rawConfig) } @@ -136,10 +139,19 @@ func ParseFromV1(rawConfig []byte) (types.Config, error) { return types.Config{}, err } - return TranslateFromV1(config) + return TranslateFromV1(config), nil } -func majorVersion(rawConfig []byte) int64 { +func ParseFromV2_0(rawConfig []byte) (types.Config, report.Report, error) { + cfg, report, err := v2_0.Parse(rawConfig) + if err != nil { + return types.Config{}, report, err + } + + return TranslateFromV2_0(cfg), report, err +} + +func version(rawConfig []byte) types.IgnitionVersion { var composite struct { Version *int `json:"ignitionVersion"` Ignition struct { @@ -147,18 +159,15 @@ func majorVersion(rawConfig []byte) int64 { } `json:"ignition"` } - if json.Unmarshal(rawConfig, &composite) != nil { - return 0 + if json.Unmarshal(rawConfig, &composite) == nil { + if composite.Ignition.Version != nil { + return *composite.Ignition.Version + } else if composite.Version != nil { + return types.IgnitionVersion{Major: int64(*composite.Version)} + } } - var major int64 - if composite.Ignition.Version != nil { - major = composite.Ignition.Version.Major - } else if composite.Version != nil { - major = int64(*composite.Version) - } - - return major + return types.IgnitionVersion{} } func isEmpty(userdata []byte) bool { diff --git a/vendor/github.com/coreos/ignition/config/translate.go b/vendor/github.com/coreos/ignition/config/translate.go index f0875455..befe7440 100644 --- a/vendor/github.com/coreos/ignition/config/translate.go +++ b/vendor/github.com/coreos/ignition/config/translate.go @@ -19,14 +19,15 @@ import ( "github.com/coreos/ignition/config/types" v1 "github.com/coreos/ignition/config/v1/types" + v2_0 "github.com/coreos/ignition/config/v2_0/types" "github.com/vincent-petithory/dataurl" ) -func TranslateFromV1(old v1.Config) (types.Config, error) { +func TranslateFromV1(old v1.Config) types.Config { config := types.Config{ Ignition: types.Ignition{ - Version: types.IgnitionVersion{Major: 2}, + Version: types.IgnitionVersion(v2_0.MaxVersion), }, } @@ -83,17 +84,19 @@ func TranslateFromV1(old v1.Config) (types.Config, error) { for _, oldFile := range oldFilesystem.Files { file := types.File{ - Filesystem: filesystem.Name, - Path: types.Path(oldFile.Path), + Node: types.Node{ + Filesystem: filesystem.Name, + Path: types.Path(oldFile.Path), + Mode: types.NodeMode(oldFile.Mode), + User: types.NodeUser{Id: oldFile.Uid}, + Group: types.NodeGroup{Id: oldFile.Gid}, + }, Contents: types.FileContents{ Source: types.Url{ Scheme: "data", Opaque: "," + dataurl.EscapeString(oldFile.Contents), }, }, - Mode: types.FileMode(oldFile.Mode), - User: types.FileUser{Id: oldFile.Uid}, - Group: types.FileGroup{Id: oldFile.Gid}, } config.Storage.Files = append(config.Storage.Files, file) @@ -159,5 +162,178 @@ func TranslateFromV1(old v1.Config) (types.Config, error) { }) } - return config, nil + return config +} + +func TranslateFromV2_0(old v2_0.Config) types.Config { + translateVerification := func(old v2_0.Verification) types.Verification { + var ver types.Verification + if old.Hash != nil { + h := types.Hash(*old.Hash) + ver.Hash = &h + } + return ver + } + translateConfigReference := func(old v2_0.ConfigReference) types.ConfigReference { + return types.ConfigReference{ + Source: types.Url(old.Source), + Verification: translateVerification(old.Verification), + } + } + + config := types.Config{ + Ignition: types.Ignition{ + Version: types.IgnitionVersion(types.MaxVersion), + }, + } + + if old.Ignition.Config.Replace != nil { + ref := translateConfigReference(*old.Ignition.Config.Replace) + config.Ignition.Config.Replace = &ref + } + + for _, oldAppend := range old.Ignition.Config.Append { + config.Ignition.Config.Append = + append(config.Ignition.Config.Append, translateConfigReference(oldAppend)) + } + + for _, oldDisk := range old.Storage.Disks { + disk := types.Disk{ + Device: types.Path(oldDisk.Device), + WipeTable: oldDisk.WipeTable, + } + + for _, oldPartition := range oldDisk.Partitions { + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: types.PartitionLabel(oldPartition.Label), + Number: oldPartition.Number, + Size: types.PartitionDimension(oldPartition.Size), + Start: types.PartitionDimension(oldPartition.Start), + TypeGUID: types.PartitionTypeGUID(oldPartition.TypeGUID), + }) + } + + config.Storage.Disks = append(config.Storage.Disks, disk) + } + + for _, oldArray := range old.Storage.Arrays { + array := types.Raid{ + Name: oldArray.Name, + Level: oldArray.Level, + Spares: oldArray.Spares, + } + + for _, oldDevice := range oldArray.Devices { + array.Devices = append(array.Devices, types.Path(oldDevice)) + } + + config.Storage.Arrays = append(config.Storage.Arrays, array) + } + + for _, oldFilesystem := range old.Storage.Filesystems { + filesystem := types.Filesystem{ + Name: oldFilesystem.Name, + } + + if oldFilesystem.Mount != nil { + filesystem.Mount = &types.FilesystemMount{ + Device: types.Path(oldFilesystem.Mount.Device), + Format: types.FilesystemFormat(oldFilesystem.Mount.Format), + } + + if oldFilesystem.Mount.Create != nil { + filesystem.Mount.Create = &types.FilesystemCreate{ + Force: oldFilesystem.Mount.Create.Force, + Options: types.MkfsOptions(oldFilesystem.Mount.Create.Options), + } + } + } + + if oldFilesystem.Path != nil { + path := types.Path(*oldFilesystem.Path) + filesystem.Path = &path + } + + config.Storage.Filesystems = append(config.Storage.Filesystems, filesystem) + } + + for _, oldFile := range old.Storage.Files { + file := types.File{ + Node: types.Node{ + Filesystem: oldFile.Filesystem, + Path: types.Path(oldFile.Path), + Mode: types.NodeMode(oldFile.Mode), + User: types.NodeUser{Id: oldFile.User.Id}, + Group: types.NodeGroup{Id: oldFile.Group.Id}, + }, + Contents: types.FileContents{ + Compression: types.Compression(oldFile.Contents.Compression), + Source: types.Url(oldFile.Contents.Source), + Verification: translateVerification(oldFile.Contents.Verification), + }, + } + + config.Storage.Files = append(config.Storage.Files, file) + } + + for _, oldUnit := range old.Systemd.Units { + unit := types.SystemdUnit{ + Name: types.SystemdUnitName(oldUnit.Name), + Enable: oldUnit.Enable, + Mask: oldUnit.Mask, + Contents: oldUnit.Contents, + } + + for _, oldDropIn := range oldUnit.DropIns { + unit.DropIns = append(unit.DropIns, types.SystemdUnitDropIn{ + Name: types.SystemdUnitDropInName(oldDropIn.Name), + Contents: oldDropIn.Contents, + }) + } + + config.Systemd.Units = append(config.Systemd.Units, unit) + } + + for _, oldUnit := range old.Networkd.Units { + config.Networkd.Units = append(config.Networkd.Units, types.NetworkdUnit{ + Name: types.NetworkdUnitName(oldUnit.Name), + Contents: oldUnit.Contents, + }) + } + + for _, oldUser := range old.Passwd.Users { + user := types.User{ + Name: oldUser.Name, + PasswordHash: oldUser.PasswordHash, + SSHAuthorizedKeys: oldUser.SSHAuthorizedKeys, + } + + if oldUser.Create != nil { + user.Create = &types.UserCreate{ + Uid: oldUser.Create.Uid, + GECOS: oldUser.Create.GECOS, + Homedir: oldUser.Create.Homedir, + NoCreateHome: oldUser.Create.NoCreateHome, + PrimaryGroup: oldUser.Create.PrimaryGroup, + Groups: oldUser.Create.Groups, + NoUserGroup: oldUser.Create.NoUserGroup, + System: oldUser.Create.System, + NoLogInit: oldUser.Create.NoLogInit, + Shell: oldUser.Create.Shell, + } + } + + config.Passwd.Users = append(config.Passwd.Users, user) + } + + for _, oldGroup := range old.Passwd.Groups { + config.Passwd.Groups = append(config.Passwd.Groups, types.Group{ + Name: oldGroup.Name, + Gid: oldGroup.Gid, + PasswordHash: oldGroup.PasswordHash, + System: oldGroup.System, + }) + } + + return config } diff --git a/vendor/github.com/coreos/ignition/config/types/config.go b/vendor/github.com/coreos/ignition/config/types/config.go index 38551589..22b8295f 100644 --- a/vendor/github.com/coreos/ignition/config/types/config.go +++ b/vendor/github.com/coreos/ignition/config/types/config.go @@ -24,8 +24,9 @@ import ( var ( MaxVersion = semver.Version{ - Major: 2, - Minor: 0, + Major: 2, + Minor: 1, + PreRelease: "experimental", } ) diff --git a/vendor/github.com/coreos/fuze/config/types/filesystems.go b/vendor/github.com/coreos/ignition/config/types/directory.go similarity index 65% rename from vendor/github.com/coreos/fuze/config/types/filesystems.go rename to vendor/github.com/coreos/ignition/config/types/directory.go index d9fbbe4f..fb93be56 100644 --- a/vendor/github.com/coreos/fuze/config/types/filesystems.go +++ b/vendor/github.com/coreos/ignition/config/types/directory.go @@ -14,19 +14,16 @@ package types -type Filesystem struct { - Name string `yaml:"name"` - Mount *Mount `yaml:"mount"` - Path string `yaml:"path"` -} +import ( + "path" +) -type Mount struct { - Device string `yaml:"device"` - Format string `yaml:"format"` - Create *Create `yaml:"create"` -} +type Directory Node -type Create struct { - Force bool `yaml:"force"` - Options []string `yaml:"options"` +func (d *Directory) Depth() int { + count := 0 + for p := path.Clean(string(d.Path)); p != "/"; count++ { + p = path.Dir(p) + } + return count } diff --git a/vendor/github.com/coreos/ignition/config/types/file.go b/vendor/github.com/coreos/ignition/config/types/file.go index cc660b55..1fbaf4e7 100644 --- a/vendor/github.com/coreos/ignition/config/types/file.go +++ b/vendor/github.com/coreos/ignition/config/types/file.go @@ -14,40 +14,10 @@ package types -import ( - "errors" - "os" - - "github.com/coreos/ignition/config/validate/report" -) - -var ( - ErrFileIllegalMode = errors.New("illegal file mode") - ErrNoFilesystem = errors.New("no filesystem specified") -) - +// File represents regular files type File struct { - Filesystem string `json:"filesystem,omitempty"` - Path Path `json:"path,omitempty"` - Contents FileContents `json:"contents,omitempty"` - Mode FileMode `json:"mode,omitempty"` - User FileUser `json:"user,omitempty"` - Group FileGroup `json:"group,omitempty"` -} - -func (f File) Validate() report.Report { - if f.Filesystem == "" { - return report.ReportFromError(ErrNoFilesystem, report.EntryError) - } - return report.Report{} -} - -type FileUser struct { - Id int `json:"id,omitempty"` -} - -type FileGroup struct { - Id int `json:"id,omitempty"` + Node + Contents FileContents `json:"contents,omitempty"` } type FileContents struct { @@ -55,12 +25,3 @@ type FileContents struct { Source Url `json:"source,omitempty"` Verification Verification `json:"verification,omitempty"` } - -type FileMode os.FileMode - -func (m FileMode) Validate() report.Report { - if (m &^ 07777) != 0 { - return report.ReportFromError(ErrFileIllegalMode, report.EntryError) - } - return report.Report{} -} diff --git a/vendor/github.com/coreos/ignition/config/types/ignition.go b/vendor/github.com/coreos/ignition/config/types/ignition.go index c9519a15..29a3ea53 100644 --- a/vendor/github.com/coreos/ignition/config/types/ignition.go +++ b/vendor/github.com/coreos/ignition/config/types/ignition.go @@ -29,8 +29,9 @@ var ( ) type Ignition struct { - Version IgnitionVersion `json:"version,omitempty" merge:"old"` - Config IgnitionConfig `json:"config,omitempty" merge:"new"` + Version IgnitionVersion `json:"version,omitempty" merge:"old"` + Config IgnitionConfig `json:"config,omitempty" merge:"new"` + Timeouts Timeouts `json:"timeouts,omitempty" merge:"new"` } type IgnitionConfig struct { diff --git a/vendor/github.com/coreos/ignition/config/types/node.go b/vendor/github.com/coreos/ignition/config/types/node.go new file mode 100644 index 00000000..f69722ad --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/types/node.go @@ -0,0 +1,60 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "errors" + "os" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrNoFilesystem = errors.New("no filesystem specified") + ErrFileIllegalMode = errors.New("illegal file mode") +) + +// Node represents all common info for files (special types, e.g. directories, included). +type Node struct { + Filesystem string `json:"filesystem,omitempty"` + Path Path `json:"path,omitempty"` + Mode NodeMode `json:"mode,omitempty"` + User NodeUser `json:"user,omitempty"` + Group NodeGroup `json:"group,omitempty"` +} + +type NodeUser struct { + Id int `json:"id,omitempty"` +} + +type NodeGroup struct { + Id int `json:"id,omitempty"` +} + +func (n Node) Validate() report.Report { + if n.Filesystem == "" { + return report.ReportFromError(ErrNoFilesystem, report.EntryError) + } + return report.Report{} +} + +type NodeMode os.FileMode + +func (m NodeMode) Validate() report.Report { + if (m &^ 07777) != 0 { + return report.ReportFromError(ErrFileIllegalMode, report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/types/path.go b/vendor/github.com/coreos/ignition/config/types/path.go index 9e00b371..0d07d81f 100644 --- a/vendor/github.com/coreos/ignition/config/types/path.go +++ b/vendor/github.com/coreos/ignition/config/types/path.go @@ -16,7 +16,7 @@ package types import ( "errors" - "path/filepath" + "path" "github.com/coreos/ignition/config/validate/report" ) @@ -32,7 +32,7 @@ func (p Path) MarshalJSON() ([]byte, error) { } func (p Path) Validate() report.Report { - if !filepath.IsAbs(string(p)) { + if !path.IsAbs(string(p)) { return report.ReportFromError(ErrPathRelative, report.EntryError) } return report.Report{} diff --git a/vendor/github.com/coreos/ignition/config/types/storage.go b/vendor/github.com/coreos/ignition/config/types/storage.go index bd734377..79e4d0fd 100644 --- a/vendor/github.com/coreos/ignition/config/types/storage.go +++ b/vendor/github.com/coreos/ignition/config/types/storage.go @@ -19,4 +19,5 @@ type Storage struct { Arrays []Raid `json:"raid,omitempty"` Filesystems []Filesystem `json:"filesystems,omitempty"` Files []File `json:"files,omitempty"` + Directories []Directory `json:"directories,omitempty"` } diff --git a/vendor/github.com/coreos/fuze/config/types/raid.go b/vendor/github.com/coreos/ignition/config/types/timeouts.go similarity index 79% rename from vendor/github.com/coreos/fuze/config/types/raid.go rename to vendor/github.com/coreos/ignition/config/types/timeouts.go index 7f56b275..77efaf65 100644 --- a/vendor/github.com/coreos/fuze/config/types/raid.go +++ b/vendor/github.com/coreos/ignition/config/types/timeouts.go @@ -14,9 +14,7 @@ package types -type Raid struct { - Name string `yaml:"name"` - Level string `yaml:"level"` - Devices []string `yaml:"devices"` - Spares int `yaml:"spares"` +type Timeouts struct { + HttpResponseHeaders *int `json:"httpResponseHeaders,omitempty"` + HttpTotal *int `json:"httpTotal,omitempty"` } diff --git a/vendor/github.com/coreos/ignition/config/types/unit.go b/vendor/github.com/coreos/ignition/config/types/unit.go index 44be844e..020d10a5 100644 --- a/vendor/github.com/coreos/ignition/config/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/types/unit.go @@ -15,8 +15,12 @@ package types import ( + "bytes" "errors" - "path/filepath" + "fmt" + "path" + + "github.com/coreos/go-systemd/unit" "github.com/coreos/ignition/config/validate/report" ) @@ -29,15 +33,31 @@ type SystemdUnit struct { DropIns []SystemdUnitDropIn `json:"dropins,omitempty"` } +func (u SystemdUnit) Validate() report.Report { + if err := validateUnitContent(u.Contents); err != nil { + return report.ReportFromError(err, report.EntryError) + } + + return report.Report{} +} + type SystemdUnitDropIn struct { Name SystemdUnitDropInName `json:"name,omitempty"` Contents string `json:"contents,omitempty"` } +func (u SystemdUnitDropIn) Validate() report.Report { + if err := validateUnitContent(u.Contents); err != nil { + return report.ReportFromError(err, report.EntryError) + } + + return report.Report{} +} + type SystemdUnitName string func (n SystemdUnitName) Validate() report.Report { - switch filepath.Ext(string(n)) { + switch path.Ext(string(n)) { case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": return report.Report{} default: @@ -48,7 +68,7 @@ func (n SystemdUnitName) Validate() report.Report { type SystemdUnitDropInName string func (n SystemdUnitDropInName) Validate() report.Report { - switch filepath.Ext(string(n)) { + switch path.Ext(string(n)) { case ".conf": return report.Report{} default: @@ -61,13 +81,31 @@ type NetworkdUnit struct { Contents string `json:"contents,omitempty"` } +func (u NetworkdUnit) Validate() report.Report { + if err := validateUnitContent(u.Contents); err != nil { + return report.ReportFromError(err, report.EntryError) + } + + return report.Report{} +} + type NetworkdUnitName string func (n NetworkdUnitName) Validate() report.Report { - switch filepath.Ext(string(n)) { + switch path.Ext(string(n)) { case ".link", ".netdev", ".network": return report.Report{} default: return report.ReportFromError(errors.New("invalid networkd unit extension"), report.EntryError) } } + +func validateUnitContent(content string) error { + c := bytes.NewBufferString(content) + _, err := unit.Deserialize(c) + if err != nil { + return fmt.Errorf("invalid unit content: %s", err) + } + + return nil +} diff --git a/vendor/github.com/coreos/ignition/config/types/url.go b/vendor/github.com/coreos/ignition/config/types/url.go index 9810c817..8bf0e6ea 100644 --- a/vendor/github.com/coreos/ignition/config/types/url.go +++ b/vendor/github.com/coreos/ignition/config/types/url.go @@ -20,6 +20,7 @@ import ( "net/url" "github.com/coreos/ignition/config/validate/report" + "github.com/vincent-petithory/dataurl" ) var ( @@ -58,9 +59,14 @@ func (u Url) Validate() report.Report { return report.Report{} } switch url.URL(u).Scheme { - case "http", "https", "oem", "data": + case "http", "https", "oem": return report.Report{} + case "data": + if _, err := dataurl.DecodeString(u.String()); err != nil { + return report.ReportFromError(err, report.EntryError) + } + return report.Report{} + default: + return report.ReportFromError(ErrInvalidScheme, report.EntryError) } - - return report.ReportFromError(ErrInvalidScheme, report.EntryError) } diff --git a/vendor/github.com/coreos/ignition/config/v1/types/path.go b/vendor/github.com/coreos/ignition/config/v1/types/path.go index 0b82c113..0cdc59a6 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/path.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/path.go @@ -17,7 +17,7 @@ package types import ( "encoding/json" "errors" - "path/filepath" + "path" ) var ( @@ -25,19 +25,18 @@ var ( ) type Path string -type path Path func (d *Path) UnmarshalJSON(data []byte) error { - td := path(*d) - if err := json.Unmarshal(data, &td); err != nil { + var s string + if err := json.Unmarshal(data, &s); err != nil { return err } - *d = Path(td) + *d = Path(s) return d.AssertValid() } func (d Path) AssertValid() error { - if !filepath.IsAbs(string(d)) { + if !path.IsAbs(string(d)) { return ErrPathRelative } return nil diff --git a/vendor/github.com/coreos/ignition/config/v1/types/unit.go b/vendor/github.com/coreos/ignition/config/v1/types/unit.go index 463ae77f..c1ec79de 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/unit.go @@ -17,7 +17,7 @@ package types import ( "encoding/json" "errors" - "path/filepath" + "path" ) type SystemdUnit struct { @@ -46,7 +46,7 @@ func (n *SystemdUnitName) UnmarshalJSON(data []byte) error { } func (n SystemdUnitName) AssertValid() error { - switch filepath.Ext(string(n)) { + switch path.Ext(string(n)) { case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": return nil default: @@ -67,7 +67,7 @@ func (n *SystemdUnitDropInName) UnmarshalJSON(data []byte) error { } func (n SystemdUnitDropInName) AssertValid() error { - switch filepath.Ext(string(n)) { + switch path.Ext(string(n)) { case ".conf": return nil default: @@ -93,7 +93,7 @@ func (n *NetworkdUnitName) UnmarshalJSON(data []byte) error { } func (n NetworkdUnitName) AssertValid() error { - switch filepath.Ext(string(n)) { + switch path.Ext(string(n)) { case ".link", ".netdev", ".network": return nil default: diff --git a/vendor/github.com/coreos/ignition/config/v2_0/append.go b/vendor/github.com/coreos/ignition/config/v2_0/append.go new file mode 100644 index 00000000..cee6bc41 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/append.go @@ -0,0 +1,73 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v2_0 + +import ( + "reflect" + + "github.com/coreos/ignition/config/v2_0/types" +) + +// Append appends newConfig to oldConfig and returns the result. Appending one +// config to another is accomplished by iterating over every field in the +// config structure, appending slices, recursively appending structs, and +// overwriting old values with new values for all other types. +func Append(oldConfig, newConfig types.Config) types.Config { + vOld := reflect.ValueOf(oldConfig) + vNew := reflect.ValueOf(newConfig) + + vResult := appendStruct(vOld, vNew) + + return vResult.Interface().(types.Config) +} + +// appendStruct is an internal helper function to AppendConfig. Given two values +// of structures (assumed to be the same type), recursively iterate over every +// field in the struct, appending slices, recursively appending structs, and +// overwriting old values with the new for all other types. Individual fields +// are able to override their merge strategy using the "merge" tag. Accepted +// values are "new" or "old": "new" uses the new value, "old" uses the old +// value. These are currently only used for "ignition.config" and +// "ignition.version". +func appendStruct(vOld, vNew reflect.Value) reflect.Value { + tOld := vOld.Type() + vRes := reflect.New(tOld) + + for i := 0; i < tOld.NumField(); i++ { + vfOld := vOld.Field(i) + vfNew := vNew.Field(i) + vfRes := vRes.Elem().Field(i) + + switch tOld.Field(i).Tag.Get("merge") { + case "old": + vfRes.Set(vfOld) + continue + case "new": + vfRes.Set(vfNew) + continue + } + + switch vfOld.Type().Kind() { + case reflect.Struct: + vfRes.Set(appendStruct(vfOld, vfNew)) + case reflect.Slice: + vfRes.Set(reflect.AppendSlice(vfOld, vfNew)) + default: + vfRes.Set(vfNew) + } + } + + return vRes.Elem() +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/cloudinit.go b/vendor/github.com/coreos/ignition/config/v2_0/cloudinit.go new file mode 100644 index 00000000..9e1f2ad0 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/cloudinit.go @@ -0,0 +1,53 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// These functions are copied from github.com/coreos/coreos-cloudinit/config. + +package v2_0 + +import ( + "bytes" + "compress/gzip" + "io/ioutil" + "strings" + "unicode" +) + +func isCloudConfig(userdata []byte) bool { + header := strings.SplitN(string(decompressIfGzipped(userdata)), "\n", 2)[0] + + // Trim trailing whitespaces + header = strings.TrimRightFunc(header, unicode.IsSpace) + + return (header == "#cloud-config") +} + +func isScript(userdata []byte) bool { + header := strings.SplitN(string(decompressIfGzipped(userdata)), "\n", 2)[0] + return strings.HasPrefix(header, "#!") +} + +func decompressIfGzipped(data []byte) []byte { + if reader, err := gzip.NewReader(bytes.NewReader(data)); err == nil { + uncompressedData, err := ioutil.ReadAll(reader) + reader.Close() + if err == nil { + return uncompressedData + } else { + return data + } + } else { + return data + } +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/config.go b/vendor/github.com/coreos/ignition/config/v2_0/config.go new file mode 100644 index 00000000..20b2fdbf --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/config.go @@ -0,0 +1,120 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v2_0 + +import ( + "bytes" + "errors" + "reflect" + + "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" + astjson "github.com/coreos/ignition/config/validate/astjson" + "github.com/coreos/ignition/config/validate/report" + + json "github.com/ajeddeloh/go-json" + "go4.org/errorutil" +) + +var ( + ErrCloudConfig = errors.New("not a config (found coreos-cloudconfig)") + ErrEmpty = errors.New("not a config (empty)") + ErrScript = errors.New("not a config (found coreos-cloudinit script)") + ErrDeprecated = errors.New("config format deprecated") + ErrInvalid = errors.New("config is not valid") +) + +// Parse parses the raw config into a types.Config struct and generates a report of any +// errors, warnings, info, and deprecations it encountered +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if isEmpty(rawConfig) { + return types.Config{}, report.Report{}, ErrEmpty + } else if isCloudConfig(rawConfig) { + return types.Config{}, report.Report{}, ErrCloudConfig + } else if isScript(rawConfig) { + return types.Config{}, report.Report{}, ErrScript + } + + var err error + var config types.Config + + // These errors are fatal and the config should not be further validated + if err = json.Unmarshal(rawConfig, &config); err == nil { + versionReport := config.Ignition.Version.Validate() + if versionReport.IsFatal() { + return types.Config{}, versionReport, ErrInvalid + } + } + + // Handle json syntax and type errors first, since they are fatal but have offset info + if serr, ok := err.(*json.SyntaxError); ok { + line, col, highlight := errorutil.HighlightBytePosition(bytes.NewReader(rawConfig), serr.Offset) + return types.Config{}, + report.Report{ + Entries: []report.Entry{{ + Kind: report.EntryError, + Message: serr.Error(), + Line: line, + Column: col, + Highlight: highlight, + }}, + }, + ErrInvalid + } + + if terr, ok := err.(*json.UnmarshalTypeError); ok { + line, col, highlight := errorutil.HighlightBytePosition(bytes.NewReader(rawConfig), terr.Offset) + return types.Config{}, + report.Report{ + Entries: []report.Entry{{ + Kind: report.EntryError, + Message: terr.Error(), + Line: line, + Column: col, + Highlight: highlight, + }}, + }, + ErrInvalid + } + + // Handle other fatal errors (i.e. invalid version) + if err != nil { + return types.Config{}, report.ReportFromError(err, report.EntryError), err + } + + // Unmarshal again to a json.Node to get offset information for building a report + var ast json.Node + var r report.Report + configValue := reflect.ValueOf(config) + if err := json.Unmarshal(rawConfig, &ast); err != nil { + r.Add(report.Entry{ + Kind: report.EntryWarning, + Message: "Ignition could not unmarshal your config for reporting line numbers. This should never happen. Please file a bug.", + }) + r.Merge(validate.ValidateWithoutSource(configValue)) + } else { + r.Merge(validate.Validate(configValue, astjson.FromJsonRoot(ast), bytes.NewReader(rawConfig))) + } + + if r.IsFatal() { + return types.Config{}, r, ErrInvalid + } + + return config, r, nil +} + +func isEmpty(userdata []byte) bool { + return len(userdata) == 0 +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/compression.go b/vendor/github.com/coreos/ignition/config/v2_0/types/compression.go new file mode 100644 index 00000000..65c3e25c --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/compression.go @@ -0,0 +1,36 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "errors" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrCompressionInvalid = errors.New("invalid compression method") +) + +type Compression string + +func (c Compression) Validate() report.Report { + switch c { + case "", "gzip": + default: + return report.ReportFromError(ErrCompressionInvalid, report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/config.go b/vendor/github.com/coreos/ignition/config/v2_0/types/config.go new file mode 100644 index 00000000..38551589 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/config.go @@ -0,0 +1,87 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + + "github.com/coreos/go-semver/semver" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + MaxVersion = semver.Version{ + Major: 2, + Minor: 0, + } +) + +type Config struct { + Ignition Ignition `json:"ignition"` + Storage Storage `json:"storage,omitempty"` + Systemd Systemd `json:"systemd,omitempty"` + Networkd Networkd `json:"networkd,omitempty"` + Passwd Passwd `json:"passwd,omitempty"` +} + +func (c Config) Validate() report.Report { + r := report.Report{} + rules := []rule{ + checkFilesFilesystems, + checkDuplicateFilesystems, + } + + for _, rule := range rules { + rule(c, &r) + } + return r +} + +type rule func(cfg Config, report *report.Report) + +func checkFilesFilesystems(cfg Config, r *report.Report) { + filesystems := map[string]struct{}{"root": {}} + for _, filesystem := range cfg.Storage.Filesystems { + filesystems[filesystem.Name] = struct{}{} + } + for _, file := range cfg.Storage.Files { + if file.Filesystem == "" { + // Filesystem was not specified. This is an error, but its handled in types.File's Validate, not here + continue + } + _, ok := filesystems[file.Filesystem] + if !ok { + r.Add(report.Entry{ + Kind: report.EntryWarning, + Message: fmt.Sprintf("File %q references nonexistent filesystem %q. (This is ok if it is defined in a referenced config)", + file.Path, file.Filesystem), + }) + } + } +} + +func checkDuplicateFilesystems(cfg Config, r *report.Report) { + filesystems := map[string]struct{}{"root": {}} + for _, filesystem := range cfg.Storage.Filesystems { + if _, ok := filesystems[filesystem.Name]; ok { + r.Add(report.Entry{ + Kind: report.EntryWarning, + Message: fmt.Sprintf("Filesystem %q shadows exising filesystem definition", filesystem.Name), + }) + } + filesystems[filesystem.Name] = struct{}{} + } +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_0/types/disk.go new file mode 100644 index 00000000..275913b4 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/disk.go @@ -0,0 +1,124 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + + "github.com/coreos/ignition/config/validate/report" +) + +type Disk struct { + Device Path `json:"device,omitempty"` + WipeTable bool `json:"wipeTable,omitempty"` + Partitions []Partition `json:"partitions,omitempty"` +} + +func (n Disk) Validate() report.Report { + r := report.Report{} + if len(n.Device) == 0 { + r.Add(report.Entry{ + Message: "disk device is required", + Kind: report.EntryError, + }) + } + if n.partitionNumbersCollide() { + r.Add(report.Entry{ + Message: fmt.Sprintf("disk %q: partition numbers collide", n.Device), + Kind: report.EntryError, + }) + } + if n.partitionsOverlap() { + r.Add(report.Entry{ + Message: fmt.Sprintf("disk %q: partitions overlap", n.Device), + Kind: report.EntryError, + }) + } + if n.partitionsMisaligned() { + r.Add(report.Entry{ + Message: fmt.Sprintf("disk %q: partitions misaligned", n.Device), + Kind: report.EntryError, + }) + } + // Disks which have no errors at this point will likely succeed in sgdisk + return r +} + +// partitionNumbersCollide returns true if partition numbers in n.Partitions are not unique. +func (n Disk) partitionNumbersCollide() bool { + m := map[int][]Partition{} + for _, p := range n.Partitions { + m[p.Number] = append(m[p.Number], p) + } + for _, n := range m { + if len(n) > 1 { + // TODO(vc): return information describing the collision for logging + return true + } + } + return false +} + +// end returns the last sector of a partition. +func (p Partition) end() PartitionDimension { + if p.Size == 0 { + // a size of 0 means "fill available", just return the start as the end for those. + return p.Start + } + return p.Start + p.Size - 1 +} + +// partitionsOverlap returns true if any explicitly dimensioned partitions overlap +func (n Disk) partitionsOverlap() bool { + for _, p := range n.Partitions { + // Starts of 0 are placed by sgdisk into the "largest available block" at that time. + // We aren't going to check those for overlap since we don't have the disk geometry. + if p.Start == 0 { + continue + } + + for _, o := range n.Partitions { + if p == o || o.Start == 0 { + continue + } + + // is p.Start within o? + if p.Start >= o.Start && p.Start <= o.end() { + return true + } + + // is p.end() within o? + if p.end() >= o.Start && p.end() <= o.end() { + return true + } + + // do p.Start and p.end() straddle o? + if p.Start < o.Start && p.end() > o.end() { + return true + } + } + } + return false +} + +// partitionsMisaligned returns true if any of the partitions don't start on a 2048-sector (1MiB) boundary. +func (n Disk) partitionsMisaligned() bool { + for _, p := range n.Partitions { + if (p.Start & (2048 - 1)) != 0 { + return true + } + } + return false +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/file.go b/vendor/github.com/coreos/ignition/config/v2_0/types/file.go new file mode 100644 index 00000000..cc660b55 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/file.go @@ -0,0 +1,66 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "errors" + "os" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrFileIllegalMode = errors.New("illegal file mode") + ErrNoFilesystem = errors.New("no filesystem specified") +) + +type File struct { + Filesystem string `json:"filesystem,omitempty"` + Path Path `json:"path,omitempty"` + Contents FileContents `json:"contents,omitempty"` + Mode FileMode `json:"mode,omitempty"` + User FileUser `json:"user,omitempty"` + Group FileGroup `json:"group,omitempty"` +} + +func (f File) Validate() report.Report { + if f.Filesystem == "" { + return report.ReportFromError(ErrNoFilesystem, report.EntryError) + } + return report.Report{} +} + +type FileUser struct { + Id int `json:"id,omitempty"` +} + +type FileGroup struct { + Id int `json:"id,omitempty"` +} + +type FileContents struct { + Compression Compression `json:"compression,omitempty"` + Source Url `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type FileMode os.FileMode + +func (m FileMode) Validate() report.Report { + if (m &^ 07777) != 0 { + return report.ReportFromError(ErrFileIllegalMode, report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_0/types/filesystem.go new file mode 100644 index 00000000..bbd0c75b --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/filesystem.go @@ -0,0 +1,67 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "errors" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrFilesystemInvalidFormat = errors.New("invalid filesystem format") + ErrFilesystemNoMountPath = errors.New("filesystem is missing mount or path") + ErrFilesystemMountAndPath = errors.New("filesystem has both mount and path defined") +) + +type Filesystem struct { + Name string `json:"name,omitempty"` + Mount *FilesystemMount `json:"mount,omitempty"` + Path *Path `json:"path,omitempty"` +} + +type FilesystemMount struct { + Device Path `json:"device,omitempty"` + Format FilesystemFormat `json:"format,omitempty"` + Create *FilesystemCreate `json:"create,omitempty"` +} + +type FilesystemCreate struct { + Force bool `json:"force,omitempty"` + Options MkfsOptions `json:"options,omitempty"` +} + +func (f Filesystem) Validate() report.Report { + if f.Mount == nil && f.Path == nil { + return report.ReportFromError(ErrFilesystemNoMountPath, report.EntryError) + } + if f.Mount != nil && f.Path != nil { + return report.ReportFromError(ErrFilesystemMountAndPath, report.EntryError) + } + return report.Report{} +} + +type FilesystemFormat string + +func (f FilesystemFormat) Validate() report.Report { + switch f { + case "ext4", "btrfs", "xfs": + return report.Report{} + default: + return report.ReportFromError(ErrFilesystemInvalidFormat, report.EntryError) + } +} + +type MkfsOptions []string diff --git a/vendor/github.com/coreos/fuze/config/types/disks.go b/vendor/github.com/coreos/ignition/config/v2_0/types/group.go similarity index 64% rename from vendor/github.com/coreos/fuze/config/types/disks.go rename to vendor/github.com/coreos/ignition/config/v2_0/types/group.go index ba09ea10..27e51048 100644 --- a/vendor/github.com/coreos/fuze/config/types/disks.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/group.go @@ -14,16 +14,9 @@ package types -type Disk struct { - Device string `yaml:"device"` - WipeTable bool `yaml:"wipe_table"` - Partitions []Partition `yaml:"partitions"` -} - -type Partition struct { - Label string `yaml:"label"` - Number int `yaml:"number"` - Size string `yaml:"size"` - Start string `yaml:"start"` - TypeGUID string `yaml:"type_guid"` +type Group struct { + Name string `json:"name,omitempty"` + Gid *uint `json:"gid,omitempty"` + PasswordHash string `json:"passwordHash,omitempty"` + System bool `json:"system,omitempty"` } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/hash.go b/vendor/github.com/coreos/ignition/config/v2_0/types/hash.go new file mode 100644 index 00000000..77d11d3d --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/hash.go @@ -0,0 +1,73 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "crypto" + "encoding/hex" + "encoding/json" + "errors" + "strings" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrHashMalformed = errors.New("malformed hash specifier") + ErrHashWrongSize = errors.New("incorrect size for hash sum") + ErrHashUnrecognized = errors.New("unrecognized hash function") +) + +type Hash struct { + Function string + Sum string +} + +func (h *Hash) UnmarshalJSON(data []byte) error { + var th string + if err := json.Unmarshal(data, &th); err != nil { + return err + } + + parts := strings.SplitN(th, "-", 2) + if len(parts) != 2 { + return ErrHashMalformed + } + + h.Function = parts[0] + h.Sum = parts[1] + + return nil +} + +func (h Hash) MarshalJSON() ([]byte, error) { + return []byte(`"` + h.Function + "-" + h.Sum + `"`), nil +} + +func (h Hash) Validate() report.Report { + var hash crypto.Hash + switch h.Function { + case "sha512": + hash = crypto.SHA512 + default: + return report.ReportFromError(ErrHashUnrecognized, report.EntryError) + } + + if len(h.Sum) != hex.EncodedLen(hash.Size()) { + return report.ReportFromError(ErrHashWrongSize, report.EntryError) + } + + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_0/types/ignition.go new file mode 100644 index 00000000..c9519a15 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/ignition.go @@ -0,0 +1,69 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "encoding/json" + "errors" + + "github.com/coreos/go-semver/semver" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrOldVersion = errors.New("incorrect config version (too old)") + ErrNewVersion = errors.New("incorrect config version (too new)") +) + +type Ignition struct { + Version IgnitionVersion `json:"version,omitempty" merge:"old"` + Config IgnitionConfig `json:"config,omitempty" merge:"new"` +} + +type IgnitionConfig struct { + Append []ConfigReference `json:"append,omitempty"` + Replace *ConfigReference `json:"replace,omitempty"` +} + +type ConfigReference struct { + Source Url `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type IgnitionVersion semver.Version + +func (v *IgnitionVersion) UnmarshalJSON(data []byte) error { + tv := semver.Version(*v) + if err := json.Unmarshal(data, &tv); err != nil { + return err + } + *v = IgnitionVersion(tv) + return nil +} + +func (v IgnitionVersion) MarshalJSON() ([]byte, error) { + return semver.Version(v).MarshalJSON() +} + +func (v IgnitionVersion) Validate() report.Report { + if MaxVersion.Major > v.Major { + return report.ReportFromError(ErrOldVersion, report.EntryError) + } + if MaxVersion.LessThan(semver.Version(v)) { + return report.ReportFromError(ErrNewVersion, report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/fuze/config/types/networkd.go b/vendor/github.com/coreos/ignition/config/v2_0/types/networkd.go similarity index 82% rename from vendor/github.com/coreos/fuze/config/types/networkd.go rename to vendor/github.com/coreos/ignition/config/v2_0/types/networkd.go index f2a1c422..470c7211 100644 --- a/vendor/github.com/coreos/fuze/config/types/networkd.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/networkd.go @@ -15,10 +15,5 @@ package types type Networkd struct { - Units []NetworkdUnit `yaml:"units"` -} - -type NetworkdUnit struct { - Name string `yaml:"name"` - Contents string `yaml:"contents"` + Units []NetworkdUnit `json:"units,omitempty"` } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_0/types/partition.go new file mode 100644 index 00000000..9ed03c32 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/partition.go @@ -0,0 +1,59 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "regexp" + + "github.com/coreos/ignition/config/validate/report" +) + +type Partition struct { + Label PartitionLabel `json:"label,omitempty"` + Number int `json:"number"` + Size PartitionDimension `json:"size"` + Start PartitionDimension `json:"start"` + TypeGUID PartitionTypeGUID `json:"typeGuid,omitempty"` +} + +type PartitionLabel string + +func (n PartitionLabel) Validate() report.Report { + // http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries: + // 56 (0x38) 72 bytes Partition name (36 UTF-16LE code units) + + // XXX(vc): note GPT calls it a name, we're using label for consistency + // with udev naming /dev/disk/by-partlabel/*. + if len(string(n)) > 36 { + return report.ReportFromError(fmt.Errorf("partition labels may not exceed 36 characters"), report.EntryError) + } + return report.Report{} +} + +type PartitionDimension uint64 + +type PartitionTypeGUID string + +func (d PartitionTypeGUID) Validate() report.Report { + ok, err := regexp.MatchString("^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$", string(d)) + if err != nil { + return report.ReportFromError(fmt.Errorf("error matching type-guid regexp: %v", err), report.EntryError) + } + if !ok { + return report.ReportFromError(fmt.Errorf(`partition type-guid must have the form "01234567-89AB-CDEF-EDCB-A98765432101", got: %q`, string(d)), report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_0/types/passwd.go new file mode 100644 index 00000000..0ffff43b --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/passwd.go @@ -0,0 +1,20 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +type Passwd struct { + Users []User `json:"users,omitempty"` + Groups []Group `json:"groups,omitempty"` +} diff --git a/vendor/github.com/coreos/fuze/config/types/systemd.go b/vendor/github.com/coreos/ignition/config/v2_0/types/path.go similarity index 59% rename from vendor/github.com/coreos/fuze/config/types/systemd.go rename to vendor/github.com/coreos/ignition/config/v2_0/types/path.go index 5840e6ce..0d07d81f 100644 --- a/vendor/github.com/coreos/fuze/config/types/systemd.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/path.go @@ -14,19 +14,26 @@ package types -type Systemd struct { - Units []SystemdUnit `yaml:"units"` +import ( + "errors" + "path" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrPathRelative = errors.New("path not absolute") +) + +type Path string + +func (p Path) MarshalJSON() ([]byte, error) { + return []byte(`"` + string(p) + `"`), nil } -type SystemdUnit struct { - Name string `yaml:"name"` - Enable bool `yaml:"enable"` - Mask bool `yaml:"mask"` - Contents string `yaml:"contents"` - DropIns []SystemdUnitDropIn `yaml:"dropins"` -} - -type SystemdUnitDropIn struct { - Name string `yaml:"name"` - Contents string `yaml:"contents"` +func (p Path) Validate() report.Report { + if !path.IsAbs(string(p)) { + return report.ReportFromError(ErrPathRelative, report.EntryError) + } + return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_0/types/raid.go new file mode 100644 index 00000000..4236255d --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/raid.go @@ -0,0 +1,45 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + + "github.com/coreos/ignition/config/validate/report" +) + +type Raid struct { + Name string `json:"name"` + Level string `json:"level"` + Devices []Path `json:"devices,omitempty"` + Spares int `json:"spares,omitempty"` +} + +func (n Raid) Validate() report.Report { + switch n.Level { + case "linear", "raid0", "0", "stripe": + if n.Spares != 0 { + return report.ReportFromError(fmt.Errorf("spares unsupported for %q arrays", n.Level), report.EntryError) + } + case "raid1", "1", "mirror": + case "raid4", "4": + case "raid5", "5": + case "raid6", "6": + case "raid10", "10": + default: + return report.ReportFromError(fmt.Errorf("unrecognized raid level: %q", n.Level), report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/storage.go b/vendor/github.com/coreos/ignition/config/v2_0/types/storage.go new file mode 100644 index 00000000..bd734377 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/storage.go @@ -0,0 +1,22 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +type Storage struct { + Disks []Disk `json:"disks,omitempty"` + Arrays []Raid `json:"raid,omitempty"` + Filesystems []Filesystem `json:"filesystems,omitempty"` + Files []File `json:"files,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/systemd.go b/vendor/github.com/coreos/ignition/config/v2_0/types/systemd.go new file mode 100644 index 00000000..97194b91 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/systemd.go @@ -0,0 +1,19 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +type Systemd struct { + Units []SystemdUnit `json:"units,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_0/types/unit.go new file mode 100644 index 00000000..020d10a5 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/unit.go @@ -0,0 +1,111 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "bytes" + "errors" + "fmt" + "path" + + "github.com/coreos/go-systemd/unit" + + "github.com/coreos/ignition/config/validate/report" +) + +type SystemdUnit struct { + Name SystemdUnitName `json:"name,omitempty"` + Enable bool `json:"enable,omitempty"` + Mask bool `json:"mask,omitempty"` + Contents string `json:"contents,omitempty"` + DropIns []SystemdUnitDropIn `json:"dropins,omitempty"` +} + +func (u SystemdUnit) Validate() report.Report { + if err := validateUnitContent(u.Contents); err != nil { + return report.ReportFromError(err, report.EntryError) + } + + return report.Report{} +} + +type SystemdUnitDropIn struct { + Name SystemdUnitDropInName `json:"name,omitempty"` + Contents string `json:"contents,omitempty"` +} + +func (u SystemdUnitDropIn) Validate() report.Report { + if err := validateUnitContent(u.Contents); err != nil { + return report.ReportFromError(err, report.EntryError) + } + + return report.Report{} +} + +type SystemdUnitName string + +func (n SystemdUnitName) Validate() report.Report { + switch path.Ext(string(n)) { + case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": + return report.Report{} + default: + return report.ReportFromError(errors.New("invalid systemd unit extension"), report.EntryError) + } +} + +type SystemdUnitDropInName string + +func (n SystemdUnitDropInName) Validate() report.Report { + switch path.Ext(string(n)) { + case ".conf": + return report.Report{} + default: + return report.ReportFromError(errors.New("invalid systemd unit drop-in extension"), report.EntryError) + } +} + +type NetworkdUnit struct { + Name NetworkdUnitName `json:"name,omitempty"` + Contents string `json:"contents,omitempty"` +} + +func (u NetworkdUnit) Validate() report.Report { + if err := validateUnitContent(u.Contents); err != nil { + return report.ReportFromError(err, report.EntryError) + } + + return report.Report{} +} + +type NetworkdUnitName string + +func (n NetworkdUnitName) Validate() report.Report { + switch path.Ext(string(n)) { + case ".link", ".netdev", ".network": + return report.Report{} + default: + return report.ReportFromError(errors.New("invalid networkd unit extension"), report.EntryError) + } +} + +func validateUnitContent(content string) error { + c := bytes.NewBufferString(content) + _, err := unit.Deserialize(c) + if err != nil { + return fmt.Errorf("invalid unit content: %s", err) + } + + return nil +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/url.go b/vendor/github.com/coreos/ignition/config/v2_0/types/url.go new file mode 100644 index 00000000..8bf0e6ea --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/url.go @@ -0,0 +1,72 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "encoding/json" + "errors" + "net/url" + + "github.com/coreos/ignition/config/validate/report" + "github.com/vincent-petithory/dataurl" +) + +var ( + ErrInvalidScheme = errors.New("invalid url scheme") +) + +type Url url.URL + +func (u *Url) UnmarshalJSON(data []byte) error { + var tu string + if err := json.Unmarshal(data, &tu); err != nil { + return err + } + + pu, err := url.Parse(tu) + if err != nil { + return err + } + + *u = Url(*pu) + return nil +} + +func (u Url) MarshalJSON() ([]byte, error) { + return []byte(`"` + u.String() + `"`), nil +} + +func (u Url) String() string { + tu := url.URL(u) + return (&tu).String() +} + +func (u Url) Validate() report.Report { + // Empty url is valid, indicates an empty file + if u.String() == "" { + return report.Report{} + } + switch url.URL(u).Scheme { + case "http", "https", "oem": + return report.Report{} + case "data": + if _, err := dataurl.DecodeString(u.String()); err != nil { + return report.ReportFromError(err, report.EntryError) + } + return report.Report{} + default: + return report.ReportFromError(ErrInvalidScheme, report.EntryError) + } +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/user.go b/vendor/github.com/coreos/ignition/config/v2_0/types/user.go new file mode 100644 index 00000000..f6653e27 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/user.go @@ -0,0 +1,35 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +type User struct { + Name string `json:"name,omitempty"` + PasswordHash string `json:"passwordHash,omitempty"` + SSHAuthorizedKeys []string `json:"sshAuthorizedKeys,omitempty"` + Create *UserCreate `json:"create,omitempty"` +} + +type UserCreate struct { + Uid *uint `json:"uid,omitempty"` + GECOS string `json:"gecos,omitempty"` + Homedir string `json:"homeDir,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + Groups []string `json:"groups,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + System bool `json:"system,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + Shell string `json:"shell,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_0/types/verification.go new file mode 100644 index 00000000..b7cef403 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/verification.go @@ -0,0 +1,19 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +type Verification struct { + Hash *Hash `json:"hash,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/config/validate/validate.go b/vendor/github.com/coreos/ignition/config/validate/validate.go index c456867c..33e3a8f7 100644 --- a/vendor/github.com/coreos/ignition/config/validate/validate.go +++ b/vendor/github.com/coreos/ignition/config/validate/validate.go @@ -20,7 +20,6 @@ import ( "reflect" "strings" - "github.com/coreos/ignition/config/types" "github.com/coreos/ignition/config/validate/report" ) @@ -75,10 +74,7 @@ func Validate(vObj reflect.Value, ast AstNode, source io.ReadSeeker) (r report.R ((vObj.Kind() != reflect.Ptr) || (!vObj.IsNil() && !vObj.Elem().Type().Implements(reflect.TypeOf((*validator)(nil)).Elem()))) { sub_r := obj.Validate() - if vObj.Type() != reflect.TypeOf(types.Config{}) { - // Config checks are done on the config as a whole and shouldn't get line numbers - sub_r.AddPosition(line, col, highlight) - } + sub_r.AddPosition(line, col, highlight) r.Merge(sub_r) // Dont recurse on invalid inner nodes, it mostly leads to bogus messages @@ -122,12 +118,18 @@ type field struct { } // getFields returns a field of all the fields in the struct, including the fields of -// embedded structs. +// embedded structs and structs inside interface{}'s func getFields(vObj reflect.Value) []field { + if vObj.Kind() != reflect.Struct { + return nil + } ret := []field{} for i := 0; i < vObj.Type().NumField(); i++ { if vObj.Type().Field(i).Anonymous { - ret = append(ret, getFields(vObj.Field(i))...) + // in the case of an embedded type that is an alias to interface, extract the + // real type contained by the interface + realObj := reflect.ValueOf(vObj.Field(i).Interface()) + ret = append(ret, getFields(realObj)...) } else { ret = append(ret, field{Type: vObj.Type().Field(i), Value: vObj.Field(i)}) } From 32d48018e17c620c32176726eeca8fb475882584 Mon Sep 17 00:00:00 2001 From: Dalton Hubble Date: Mon, 17 Apr 2017 17:17:42 -0700 Subject: [PATCH 3/4] glide.yaml: Update and vendor coreos-cloudinit v1.13.0 --- glide.lock | 6 +++--- glide.yaml | 2 +- vendor/github.com/coreos/coreos-cloudinit/config/flannel.go | 2 ++ vendor/github.com/coreos/coreos-cloudinit/config/fleet.go | 2 ++ .../github.com/coreos/coreos-cloudinit/config/locksmith.go | 2 ++ .../github.com/coreos/coreos-cloudinit/coreos-cloudinit.go | 6 +----- 6 files changed, 11 insertions(+), 9 deletions(-) diff --git a/glide.lock b/glide.lock index 4d2a54e2..a5119b17 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: d7d6d80b5734d981194ff7ff4cfa150cedae4549133301d1845f110e48729543 -updated: 2017-04-17T15:53:14.762097698-07:00 +hash: 205de0b66ed059a1f10d3fb36c7d465439818123940a9aaa68ddc71cc3bbfddd +updated: 2017-04-17T17:09:48.864562358-07:00 imports: - name: github.com/ajeddeloh/go-json version: 73d058cf8437a1989030afe571eeab9f90eebbbd @@ -16,7 +16,7 @@ imports: - config/templating - config/types - name: github.com/coreos/coreos-cloudinit - version: 4c333e657bfbaa8f6594298b48324f45e6bf5961 + version: 5be99bf577f2768193c7fb587ef5a8806c1503cf subpackages: - config - name: github.com/coreos/go-semver diff --git a/glide.yaml b/glide.yaml index 518a4dd5..0a225866 100644 --- a/glide.yaml +++ b/glide.yaml @@ -45,7 +45,7 @@ import: subpackages: - semver - package: github.com/coreos/coreos-cloudinit - version: v1.11.0 + version: v1.13.0 subpackages: - config - package: github.com/coreos/pkg diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/flannel.go b/vendor/github.com/coreos/coreos-cloudinit/config/flannel.go index 7a953f8c..76ca695a 100644 --- a/vendor/github.com/coreos/coreos-cloudinit/config/flannel.go +++ b/vendor/github.com/coreos/coreos-cloudinit/config/flannel.go @@ -20,6 +20,8 @@ type Flannel struct { EtcdCertFile string `yaml:"etcd_certfile" env:"FLANNELD_ETCD_CERTFILE"` EtcdKeyFile string `yaml:"etcd_keyfile" env:"FLANNELD_ETCD_KEYFILE"` EtcdPrefix string `yaml:"etcd_prefix" env:"FLANNELD_ETCD_PREFIX"` + EtcdUsername string `yaml:"etcd_username" env:"FLANNELD_ETCD_USERNAME"` + EtcdPassword string `yaml:"etcd_password" env:"FLANNELD_ETCD_PASSWORD"` IPMasq string `yaml:"ip_masq" env:"FLANNELD_IP_MASQ"` SubnetFile string `yaml:"subnet_file" env:"FLANNELD_SUBNET_FILE"` Iface string `yaml:"interface" env:"FLANNELD_IFACE"` diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/fleet.go b/vendor/github.com/coreos/coreos-cloudinit/config/fleet.go index 970905cc..66c53bf6 100644 --- a/vendor/github.com/coreos/coreos-cloudinit/config/fleet.go +++ b/vendor/github.com/coreos/coreos-cloudinit/config/fleet.go @@ -25,6 +25,8 @@ type Fleet struct { EtcdKeyPrefix string `yaml:"etcd_key_prefix" env:"FLEET_ETCD_KEY_PREFIX"` EtcdRequestTimeout float64 `yaml:"etcd_request_timeout" env:"FLEET_ETCD_REQUEST_TIMEOUT"` EtcdServers string `yaml:"etcd_servers" env:"FLEET_ETCD_SERVERS"` + EtcdUsername string `yaml:"etcd_username" env:"FLEET_ETCD_USERNAME"` + EtcdPassword string `yaml:"etcd_password" env:"FLEET_ETCD_PASSWORD"` Metadata string `yaml:"metadata" env:"FLEET_METADATA"` PublicIP string `yaml:"public_ip" env:"FLEET_PUBLIC_IP"` TokenLimit int `yaml:"token_limit" env:"FLEET_TOKEN_LIMIT"` diff --git a/vendor/github.com/coreos/coreos-cloudinit/config/locksmith.go b/vendor/github.com/coreos/coreos-cloudinit/config/locksmith.go index aa1232d9..c261e356 100644 --- a/vendor/github.com/coreos/coreos-cloudinit/config/locksmith.go +++ b/vendor/github.com/coreos/coreos-cloudinit/config/locksmith.go @@ -19,6 +19,8 @@ type Locksmith struct { EtcdCAFile string `yaml:"etcd_cafile" env:"LOCKSMITHD_ETCD_CAFILE"` EtcdCertFile string `yaml:"etcd_certfile" env:"LOCKSMITHD_ETCD_CERTFILE"` EtcdKeyFile string `yaml:"etcd_keyfile" env:"LOCKSMITHD_ETCD_KEYFILE"` + EtcdUsername string `yaml:"etcd_username" env:"LOCKSMITHD_ETCD_USERNAME"` + EtcdPassword string `yaml:"etcd_password" env:"LOCKSMITHD_ETCD_PASSWORD"` Group string `yaml:"group" env:"LOCKSMITHD_GROUP"` RebootWindowStart string `yaml:"window_start" env:"REBOOT_WINDOW_START" valid:"^((?i:sun|mon|tue|wed|thu|fri|sat|sun) )?0*([0-9]|1[0-9]|2[0-3]):0*([0-9]|[1-5][0-9])$"` RebootWindowLength string `yaml:"window_length" env:"REBOOT_WINDOW_LENGTH" valid:"^[-+]?([0-9]*(\\.[0-9]*)?[a-z]+)+$"` diff --git a/vendor/github.com/coreos/coreos-cloudinit/coreos-cloudinit.go b/vendor/github.com/coreos/coreos-cloudinit/coreos-cloudinit.go index be613c39..d0d2c8a8 100644 --- a/vendor/github.com/coreos/coreos-cloudinit/coreos-cloudinit.go +++ b/vendor/github.com/coreos/coreos-cloudinit/coreos-cloudinit.go @@ -109,7 +109,6 @@ var ( oemConfigs = map[string]oemConfig{ "digitalocean": { "from-digitalocean-metadata": "http://169.254.169.254/", - "convert-netconf": "digitalocean", }, "ec2-compat": { "from-ec2-metadata": "http://169.254.169.254/", @@ -170,11 +169,10 @@ func main() { switch flags.convertNetconf { case "": case "debian": - case "digitalocean": case "packet": case "vmware": default: - fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian, digitalocean, packet, vmware'\n", flags.convertNetconf) + fmt.Printf("Invalid option to -convert-netconf: '%s'. Supported options: 'debian, packet, vmware'\n", flags.convertNetconf) os.Exit(2) } @@ -256,8 +254,6 @@ func main() { switch flags.convertNetconf { case "debian": ifaces, err = network.ProcessDebianNetconf(metadata.NetworkConfig.([]byte)) - case "digitalocean": - ifaces, err = network.ProcessDigitalOceanNetconf(metadata.NetworkConfig.(digitalocean.Metadata)) case "packet": ifaces, err = network.ProcessPacketNetconf(metadata.NetworkConfig.(packet.NetworkData)) case "vmware": From 311f1ec7cd8a4002684af78a6eaa5b44e1e63faf Mon Sep 17 00:00:00 2001 From: Dalton Hubble Date: Mon, 17 Apr 2017 17:31:36 -0700 Subject: [PATCH 4/4] Documentation: Move ignition.md to container-linux-config.md --- Documentation/cloud-config.md | 2 +- Documentation/{ignition.md => container-linux-config.md} | 0 Documentation/matchbox.md | 2 +- README.md | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename Documentation/{ignition.md => container-linux-config.md} (100%) diff --git a/Documentation/cloud-config.md b/Documentation/cloud-config.md index b308433f..efe61754 100644 --- a/Documentation/cloud-config.md +++ b/Documentation/cloud-config.md @@ -1,7 +1,7 @@ # Cloud config -**Note:** We recommend migrating to [Ignition](ignition.md) for hardware provisioning. +**Note:** We recommend migrating to [Container Linux Configs](container-linux-config.md) for hardware provisioning. CoreOS Cloud-Config is a system for configuring machines with a Cloud-Config file or executable script from user-data. Cloud-Config runs in userspace on each boot and implements a subset of the [cloud-init spec](http://cloudinit.readthedocs.org/en/latest/topics/format.html#cloud-config-data). See the cloud-config [docs](https://coreos.com/os/docs/latest/cloud-config.html) for details. diff --git a/Documentation/ignition.md b/Documentation/container-linux-config.md similarity index 100% rename from Documentation/ignition.md rename to Documentation/container-linux-config.md diff --git a/Documentation/matchbox.md b/Documentation/matchbox.md index d602e0ad..cbd22036 100644 --- a/Documentation/matchbox.md +++ b/Documentation/matchbox.md @@ -134,7 +134,7 @@ Profiles can reference various templated configs. Ignition JSON configs can be g For details and examples: -* [Container Linux Config](ignition.md) +* [Container Linux Config](container-linux-config.md) * [Cloud-Config](cloud-config.md) #### Variables diff --git a/README.md b/README.md index 73b546ed..d486a98f 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ Network boot and provision CoreOS clusters on virtual or physical hardware. * [Profiles](Documentation/matchbox.md#profiles) * [Groups](Documentation/matchbox.md#groups) * Config Templates - * [Ignition](Documentation/ignition.md) + * [Container Linux Config](Documentation/container-linux-config.md) * [Cloud-Config](Documentation/cloud-config.md) * [Configuration](Documentation/config.md) * [HTTP API](Documentation/api.md)