From a948a97339312bd5d832e53bf343231d1bfd1718 Mon Sep 17 00:00:00 2001 From: Dalton Hubble Date: Mon, 17 Apr 2017 16:46:25 -0700 Subject: [PATCH] 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)}) }