diff --git a/glide.lock b/glide.lock index 1dd00f01..4eed73c3 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 7de5ab95677974311285feaa83e24f127bbb4c64a68740bab24d71f491e8b689 -updated: 2017-05-24T15:28:05.291154327-07:00 +hash: 9c2d24d482e4b591552c20d251b4620bdc2a12256564f8f18d7cb30b797bfd33 +updated: 2017-08-08T13:27:35.465951914-07:00 imports: - name: github.com/ajeddeloh/go-json version: 73d058cf8437a1989030afe571eeab9f90eebbbd @@ -10,11 +10,14 @@ imports: - name: github.com/camlistore/camlistore version: 9106ce829629773474c689b34aacd7d3aaa99426 - name: github.com/coreos/container-linux-config-transpiler - version: 12554ca0a5ce8ea4a6c594242ccb23d8b9bff493 + version: d42f09a1374bc318d853b53e5a31148db68a4e2a subpackages: - config + - config/astyaml + - config/platform - config/templating - config/types + - config/types/util - name: github.com/coreos/coreos-cloudinit version: 5be99bf577f2768193c7fb587ef5a8806c1503cf subpackages: @@ -29,7 +32,7 @@ imports: - journal - unit - name: github.com/coreos/ignition - version: d75d0aa3bf307f0954ce4ea8cac56dacec8d16ce + version: 11813c57bc05f30644bbae7891ae30a4a62e0b33 subpackages: - config - config/types @@ -37,6 +40,8 @@ imports: - config/v1/types - config/v2_0 - config/v2_0/types + - config/v2_1 + - config/v2_1/types - config/validate - config/validate/astjson - config/validate/report @@ -98,7 +103,7 @@ imports: - internal/timeseries - trace - name: golang.org/x/sys - version: d4feaf1a7e61e1d9e79e6c4e76c6349e9cab0a03 + version: 8f0908ab3b2457e2e15403d3697c9ef5cb4b57a9 subpackages: - unix - name: google.golang.org/grpc diff --git a/glide.yaml b/glide.yaml index ca750625..23ce0360 100644 --- a/glide.yaml +++ b/glide.yaml @@ -19,13 +19,13 @@ import: - transport # Container Linux Config Transpiler and Ignition - package: github.com/coreos/container-linux-config-transpiler - version: v0.2.2 + version: v0.4.2 subpackages: - config - config/types - config/templating - package: github.com/coreos/ignition - version: d75d0aa3bf307f0954ce4ea8cac56dacec8d16ce + version: v0.17.2 subpackages: - config - config/types diff --git a/matchbox/http/ignition.go b/matchbox/http/ignition.go index e79b97d8..e54b9208 100644 --- a/matchbox/http/ignition.go +++ b/matchbox/http/ignition.go @@ -89,7 +89,7 @@ func (s *Server) ignitionHandler(core server.Server) ContextHandler { } // Parse bytes into a Container Linux Config - config, report := ct.Parse(buf.Bytes()) + config, ast, report := ct.Parse(buf.Bytes()) if report.IsFatal() { s.logger.Errorf("error parsing Container Linux config: %s", report.String()) http.NotFound(w, req) @@ -97,7 +97,7 @@ func (s *Server) ignitionHandler(core server.Server) ContextHandler { } // Convert Container Linux Config into an Ignition Config - ign, report := ct.ConvertAs2_0(config, "") + ign, report := ct.ConvertAs2_0(config, "", ast) if report.IsFatal() { s.logger.Errorf("error converting Container Linux config: %s", report.String()) http.NotFound(w, req) diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml.go deleted file mode 100644 index 1adcfef5..00000000 --- a/vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml.go +++ /dev/null @@ -1,90 +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 ( - "errors" - "io" - - yaml "github.com/ajeddeloh/yaml" - "github.com/coreos/ignition/config/validate" -) - -var ( - ErrNotDocumentNode = errors.New("Can only convert from document node") -) - -type yamlNode struct { - key yaml.Node - yaml.Node -} - -func fromYamlDocumentNode(n yaml.Node) (yamlNode, error) { - if n.Kind != yaml.DocumentNode { - return yamlNode{}, ErrNotDocumentNode - } - - return yamlNode{ - key: n, - Node: *n.Children[0], - }, nil -} - -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) { - return n.key.Line, n.key.Column, "" -} - -func (n yamlNode) LiteralValue() interface{} { - return n.Value -} - -func (n yamlNode) SliceChild(index int) (validate.AstNode, bool) { - if n.Kind != yaml.SequenceNode { - return nil, false - } - if index >= len(n.Children) { - return nil, false - } - - return yamlNode{ - key: yaml.Node{}, - Node: *n.Children[index], - }, true -} - -func (n yamlNode) KeyValueMap() (map[string]validate.AstNode, bool) { - if n.Kind != yaml.MappingNode { - return nil, false - } - - kvmap := map[string]validate.AstNode{} - for i := 0; i < len(n.Children); i += 2 { - key := *n.Children[i] - value := *n.Children[i+1] - kvmap[key.Value] = yamlNode{ - key: key, - Node: value, - } - } - return kvmap, true -} - -func (n yamlNode) Tag() string { - return "yaml" -} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml/astyaml.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml/astyaml.go new file mode 100644 index 00000000..6a51885d --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/astyaml/astyaml.go @@ -0,0 +1,134 @@ +// 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 astyaml + +import ( + "errors" + "io" + "strings" + + yaml "github.com/ajeddeloh/yaml" + "github.com/coreos/ignition/config/validate" +) + +var ( + ErrNotDocumentNode = errors.New("Can only convert from document node") + ErrNotMappingNode = errors.New("Tried to change the key of a node which is not a mapping node") + ErrKeyNotFound = errors.New("Key to be replaced not found") +) + +type YamlNode struct { + tag string + key yaml.Node + yaml.Node +} + +func FromYamlDocumentNode(n yaml.Node) (YamlNode, error) { + if n.Kind != yaml.DocumentNode { + return YamlNode{}, ErrNotDocumentNode + } + + return YamlNode{ + key: n, + tag: "yaml", + Node: *n.Children[0], + }, nil +} + +func (n YamlNode) ValueLineCol(source io.ReadSeeker) (int, int, string) { + return n.Line + 1, n.Column + 1, "" +} + +func (n YamlNode) KeyLineCol(source io.ReadSeeker) (int, int, string) { + return n.key.Line + 1, n.key.Column + 1, "" +} + +func (n YamlNode) LiteralValue() interface{} { + return n.Value +} + +func (n YamlNode) SliceChild(index int) (validate.AstNode, bool) { + if n.Kind != yaml.SequenceNode { + return nil, false + } + if index >= len(n.Children) { + return nil, false + } + + return YamlNode{ + key: yaml.Node{}, + tag: n.tag, + Node: *n.Children[index], + }, true +} + +func (n YamlNode) KeyValueMap() (map[string]validate.AstNode, bool) { + if n.Kind != yaml.MappingNode { + return nil, false + } + + kvmap := map[string]validate.AstNode{} + for i := 0; i < len(n.Children); i += 2 { + key := *n.Children[i] + if n.tag == "json" { + key.Value = getIgnKeyName(key.Value) + } + value := *n.Children[i+1] + kvmap[key.Value] = YamlNode{ + key: key, + tag: n.tag, + Node: value, + } + } + return kvmap, true +} + +// ChangeKey replaces the oldkey with a new key/value pair. Useful for patching +// up a tree parsed from yaml but then used for validating an ignition structure +func (n *YamlNode) ChangeKey(oldKeyName, newKeyName string, newValue YamlNode) error { + if n.Kind != yaml.MappingNode { + return ErrNotMappingNode + } + for i := 0; i < len(n.Children); i += 2 { + key := n.Children[i] + if key.Value == oldKeyName { + //key.Value = newKeyName + (*n.Children[i]).Value = newKeyName + *n.Children[i+1] = newValue.Node + return nil + } + } + + return ErrKeyNotFound +} + +// getIgnKeyName converts a snake_case (used by clct) to a camelCase (used by +// ignition) +func getIgnKeyName(keyname string) string { + words := strings.Split(keyname, "_") + for i, word := range words[1:] { + words[i+1] = strings.Title(word) + } + return strings.Join(words, "") +} + +func (n YamlNode) Tag() string { + return n.tag +} + +// ChangeTreeTag changes the value Tag() returns to newTag +func (n *YamlNode) ChangeTreeTag(newTag string) { + n.tag = newTag +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/config.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/config.go index a359dada..ada5a7b3 100644 --- a/vendor/github.com/coreos/container-linux-config-transpiler/config/config.go +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/config.go @@ -18,21 +18,27 @@ import ( "reflect" yaml "github.com/ajeddeloh/yaml" + "github.com/coreos/container-linux-config-transpiler/config/astyaml" + "github.com/coreos/container-linux-config-transpiler/config/platform" "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" ) -func Parse(data []byte) (types.Config, report.Report) { +// Parse will convert a byte slice containing a Container Linux Config into a +// golang struct representing the config, the parse tree from parsing the yaml +// and a report of any warnings or errors that occurred during the parsing. +func Parse(data []byte) (types.Config, validate.AstNode, report.Report) { var cfg types.Config var r report.Report if err := yaml.Unmarshal(data, &cfg); err != nil { - return types.Config{}, report.ReportFromError(err, report.EntryError) + return types.Config{}, nil, report.ReportFromError(err, report.EntryError) } nodes := yaml.UnmarshalToNode(data) + var root validate.AstNode if nodes == nil { r.Add(report.Entry{ Kind: report.EntryWarning, @@ -40,20 +46,35 @@ func Parse(data []byte) (types.Config, report.Report) { }) r.Merge(validate.ValidateWithoutSource(reflect.ValueOf(cfg))) } else { - root, err := fromYamlDocumentNode(*nodes) + var err error + root, err = astyaml.FromYamlDocumentNode(*nodes) if err != nil { - return types.Config{}, report.ReportFromError(err, report.EntryError) + return types.Config{}, nil, report.ReportFromError(err, report.EntryError) } - r.Merge(validate.Validate(reflect.ValueOf(cfg), root, nil)) + r.Merge(validate.Validate(reflect.ValueOf(cfg), root, nil, true)) } if r.IsFatal() { - return types.Config{}, r + return types.Config{}, nil, r } - return cfg, r + return cfg, root, r } -func ConvertAs2_0(in types.Config, platform string) (ignTypes.Config, report.Report) { - return types.ConvertAs2_0(in, platform) +// ConvertAs2_0 will convert a golang struct representing a Container Linux +// Config into an Ignition Config, and a report of any warnings or errors. It +// takes the parse tree from parsing the Container Linux config as well. +// ConvertAs2_0 also accepts a platform string, which can either be one of the +// platform strings defined in config/templating/templating.go or an empty +// string if [dynamic data](doc/dynamic-data.md) isn't used. +func ConvertAs2_0(in types.Config, p string, ast validate.AstNode) (ignTypes.Config, report.Report) { + if !platform.IsSupportedPlatform(p) { + r := report.Report{} + r.Add(report.Entry{ + Kind: report.EntryError, + Message: "unsupported platform", + }) + return ignTypes.Config{}, r + } + return types.ConvertAs2_0(in, p, ast) } diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/platform/platform.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/platform/platform.go new file mode 100644 index 00000000..07e98e53 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/platform/platform.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 platform + +const ( + Azure = "azure" + DO = "digitalocean" + EC2 = "ec2" + GCE = "gce" + Packet = "packet" + OpenStackMetadata = "openstack-metadata" + VagrantVirtualbox = "vagrant-virtualbox" +) + +var Platforms = []string{ + Azure, + DO, + EC2, + GCE, + Packet, + OpenStackMetadata, + VagrantVirtualbox, +} + +func IsSupportedPlatform(platform string) bool { + for _, supportedPlatform := range Platforms { + if supportedPlatform == platform { + return true + } + } + return 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 index d9820cbf..24142bde 100644 --- 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 @@ -17,6 +17,8 @@ package templating import ( "fmt" "strings" + + "github.com/coreos/container-linux-config-transpiler/config/platform" ) var ( @@ -24,24 +26,6 @@ var ( 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" @@ -51,12 +35,12 @@ const ( ) var platformTemplatingMap = map[string]map[string]string{ - PlatformAzure: { + platform.Azure: { // TODO: is this right? fieldV4Private: "COREOS_AZURE_IPV4_DYNAMIC", fieldV4Public: "COREOS_AZURE_IPV4_VIRTUAL", }, - PlatformDO: { + platform.DO: { // TODO: unused: COREOS_DIGITALOCEAN_IPV4_ANCHOR_0 fieldHostname: "COREOS_DIGITALOCEAN_HOSTNAME", fieldV4Private: "COREOS_DIGITALOCEAN_IPV4_PRIVATE_0", @@ -64,27 +48,31 @@ var platformTemplatingMap = map[string]map[string]string{ fieldV6Private: "COREOS_DIGITALOCEAN_IPV6_PRIVATE_0", fieldV6Public: "COREOS_DIGITALOCEAN_IPV6_PUBLIC_0", }, - PlatformEC2: { + platform.EC2: { fieldHostname: "COREOS_EC2_HOSTNAME", fieldV4Private: "COREOS_EC2_IPV4_LOCAL", fieldV4Public: "COREOS_EC2_IPV4_PUBLIC", }, - PlatformGCE: { + platform.GCE: { fieldHostname: "COREOS_GCE_HOSTNAME", - fieldV4Private: "COREOS_GCE_IP_EXTERNAL_0", - fieldV4Public: "COREOS_GCE_IP_LOCAL_0", + fieldV4Private: "COREOS_GCE_IP_LOCAL_0", + fieldV4Public: "COREOS_GCE_IP_EXTERNAL_0", }, - PlatformPacket: { + platform.Packet: { fieldHostname: "COREOS_PACKET_HOSTNAME", fieldV4Private: "COREOS_PACKET_IPV4_PRIVATE_0", fieldV4Public: "COREOS_PACKET_IPV4_PUBLIC_0", fieldV6Public: "COREOS_PACKET_IPV6_PUBLIC_0", }, - PlatformOpenStackMetadata: { + platform.OpenStackMetadata: { fieldHostname: "COREOS_OPENSTACK_HOSTNAME", fieldV4Private: "COREOS_OPENSTACK_IPV4_LOCAL", fieldV4Public: "COREOS_OPENSTACK_IPV4_PUBLIC", }, + platform.VagrantVirtualbox: { + fieldHostname: "COREOS_VAGRANT_VIRTUALBOX_HOSTNAME", + fieldV4Private: "COREOS_VAGRANT_VIRTUALBOX_PRIVATE_IPV4", + }, } // HasTemplating returns whether or not any of the environment variables present 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 index 95a2919d..34a62ccb 100644 --- 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 @@ -15,16 +15,48 @@ package types import ( + "errors" "fmt" "reflect" + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate/report" + + "github.com/coreos/container-linux-config-transpiler/config/platform" "github.com/coreos/container-linux-config-transpiler/config/templating" + "github.com/coreos/container-linux-config-transpiler/config/types/util" + "github.com/coreos/ignition/config/validate" ) var ( ErrPlatformUnspecified = fmt.Errorf("platform must be specified to use templating") + ErrInvalidKey = errors.New("Key is invalid (wrong type or not found") + ErrNilNode = errors.New("Ast node is nil") + ErrKeyNotFound = errors.New("Key not found") ) +func init() { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, p string) (ignTypes.Config, report.Report, validate.AstNode) { + if p == platform.OpenStackMetadata { + out.Systemd.Units = append(out.Systemd.Units, ignTypes.SystemdUnit{ + Name: "coreos-metadata.service", + DropIns: []ignTypes.SystemdUnitDropIn{{ + Name: "20-clct-provider-override.conf", + Contents: fmt.Sprintf("[Service]\nEnvironment=COREOS_METADATA_OPT_PROVIDER=--provider=%s", p), + }}, + }) + out.Systemd.Units = append(out.Systemd.Units, ignTypes.SystemdUnit{ + Name: "coreos-metadata-sshkeys@.service", + DropIns: []ignTypes.SystemdUnitDropIn{{ + Name: "20-clct-provider-override.conf", + Contents: fmt.Sprintf("[Service]\nEnvironment=COREOS_METADATA_OPT_PROVIDER=--provider=%s", p), + }}, + }) + } + return out, report.Report{}, ast + }) +} + func isZero(v interface{}) bool { if v == nil { return true @@ -36,37 +68,36 @@ func isZero(v interface{}) bool { // 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) { +func assembleUnit(exec string, args, vars []string, p string) (util.SystemdUnit, error) { hasTemplating := templating.HasTemplating(args) - var out string + out := util.NewSystemdUnit() if hasTemplating { - if platform == "" { - return "", ErrPlatformUnspecified + if p == "" { + return util.SystemdUnit{}, ErrPlatformUnspecified } - out = "[Unit]\nRequires=coreos-metadata.service\nAfter=coreos-metadata.service\n\n[Service]\nEnvironmentFile=/run/metadata/coreos\n" + out.Unit.Add("Requires=coreos-metadata.service") + out.Unit.Add("After=coreos-metadata.service") + out.Service.Add("EnvironmentFile=/run/metadata/coreos") var err error - args, err = templating.PerformTemplating(platform, args) + args, err = templating.PerformTemplating(p, args) if err != nil { - return "", err + return util.SystemdUnit{}, err } - } else { - out = "[Service]\n" } for _, v := range vars { - out += fmt.Sprintf("Environment=\"%s\"\n", v) + out.Service.Add(fmt.Sprintf("Environment=\"%s\"", v)) } for _, a := range args { exec += fmt.Sprintf(" \\\n %s", a) } - out += "ExecStart=\n" - out += fmt.Sprintf("ExecStart=%s", exec) + out.Service.Add("ExecStart=") + out.Service.Add(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 { +func getArgs(format, tagName string, e interface{}) []string { if e == nil { return nil } @@ -79,11 +110,58 @@ func getCliArgs(e interface{}) []string { 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)) + key := et.Field(i).Tag.Get(tagName) + if _, ok := val.(string); ok { + // to handle whitespace characters + val = fmt.Sprintf("%q", val) + } + vars = append(vars, fmt.Sprintf(format, key, val)) } } } return vars } + +// getCliArgs builds a list of --ARG=VAL from a struct with cli: tags on its members. +func getCliArgs(e interface{}) []string { + return getArgs("--%s=%v", "cli", e) +} + +// Get returns the value for key, where key is an int or string and n is a +// sequence node or mapping node, respectively. +func getNodeChild(n validate.AstNode, key interface{}) (validate.AstNode, error) { + if n == nil { + return nil, ErrNilNode + } + switch k := key.(type) { + case int: + if child, ok := n.SliceChild(k); ok { + return child, nil + } + case string: + kvmap, ok := n.KeyValueMap() + if !ok { + return nil, ErrInvalidKey + } + if v, ok := kvmap[k]; ok { + return v, nil + } + default: + return nil, ErrInvalidKey + } + // not found + return nil, ErrKeyNotFound +} + +// GetPath works like calling Get() repeatly with each argument. +func getNodeChildPath(n validate.AstNode, key ...interface{}) (validate.AstNode, error) { + if len(key) == 0 { + return n, nil + } + next, err := getNodeChild(n, key[0]) + if err != nil { + return nil, err + } + return getNodeChildPath(next, key[1:]...) +} 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 index 19d3a1d4..62d89eb2 100644 --- 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 @@ -18,6 +18,7 @@ import ( "net/url" ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -49,36 +50,48 @@ type ConfigReference struct { } 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) + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { + r := report.Report{} + cfgNode, _ := getNodeChildPath(ast, "ignition", "config", "append") + for i, ref := range in.Ignition.Config.Append { + tmp, _ := getNodeChild(cfgNode, i) + newRef, convertReport := convertConfigReference(ref, tmp) + r.Merge(convertReport) + if convertReport.IsFatal() { + // don't add to the output if invalid + continue } out.Ignition.Config.Append = append(out.Ignition.Config.Append, newRef) } + cfgNode, _ = getNodeChildPath(ast, "ignition", "config", "replace") if in.Ignition.Config.Replace != nil { - newRef, err := convertConfigReference(*in.Ignition.Config.Replace) - if err != nil { - return out, report.ReportFromError(err, report.EntryError) + newRef, convertReport := convertConfigReference(*in.Ignition.Config.Replace, cfgNode) + r.Merge(convertReport) + if convertReport.IsFatal() { + // don't add to the output if invalid + return out, r, ast } out.Ignition.Config.Replace = &newRef } - return out, report.Report{} + return out, r, ast }) } -func convertConfigReference(in ConfigReference) (ignTypes.ConfigReference, error) { +func convertConfigReference(in ConfigReference, ast validate.AstNode) (ignTypes.ConfigReference, report.Report) { source, err := url.Parse(in.Source) if err != nil { - return ignTypes.ConfigReference{}, err + r := report.ReportFromError(err, report.EntryError) + if n, err := getNodeChild(ast, "source"); err == nil { + r.AddPosition(n.ValueLineCol(nil)) + } + return ignTypes.ConfigReference{}, r } return ignTypes.ConfigReference{ Source: ignTypes.Url(*source), Verification: convertVerification(in.Verification), - }, nil + }, report.Report{} } func convertVerification(in Verification) ignTypes.Verification { 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 index 1942eaf2..a82429c9 100644 --- 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 @@ -17,12 +17,13 @@ package types import ( "reflect" + "github.com/coreos/container-linux-config-transpiler/config/astyaml" 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) +type converterFor2_0 func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) var convertersFor2_0 []converterFor2_0 @@ -30,7 +31,15 @@ func register2_0(f converterFor2_0) { convertersFor2_0 = append(convertersFor2_0, f) } -func ConvertAs2_0(in Config, platform string) (ignTypes.Config, report.Report) { +func ConvertAs2_0(in Config, platform string, ast validate.AstNode) (ignTypes.Config, report.Report) { + // convert our tree from having yaml tags to having json tags, so when Validate() is + // called on the tree, it can find the keys in the ignition structs (which are denoted + // by `json` tags) + if asYamlNode, ok := ast.(astyaml.YamlNode); ok { + asYamlNode.ChangeTreeTag("json") + ast = asYamlNode + } + out := ignTypes.Config{ Ignition: ignTypes.Ignition{ Version: ignTypes.IgnitionVersion{Major: 2, Minor: 0}, @@ -41,14 +50,14 @@ func ConvertAs2_0(in Config, platform string) (ignTypes.Config, report.Report) { for _, convert := range convertersFor2_0 { var subReport report.Report - out, subReport = convert(in, out, platform) + out, subReport, ast = convert(in, ast, out, platform) r.Merge(subReport) } if r.IsFatal() { return ignTypes.Config{}, r } - validationReport := validate.ValidateWithoutSource(reflect.ValueOf(out)) + validationReport := validate.Validate(reflect.ValueOf(out), ast, nil, false) r.Merge(validationReport) if r.IsFatal() { return ignTypes.Config{}, 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 index 851ed4bc..baa49d2b 100644 --- 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 @@ -19,6 +19,7 @@ import ( "github.com/alecthomas/units" ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -41,35 +42,49 @@ type Partition struct { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { - for _, disk := range in.Storage.Disks { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { + r := report.Report{} + for disk_idx, disk := range in.Storage.Disks { newDisk := ignTypes.Disk{ Device: ignTypes.Path(disk.Device), WipeTable: disk.WipeTable, } - for _, partition := range disk.Partitions { + for part_idx, partition := range disk.Partitions { size, err := convertPartitionDimension(partition.Size) if err != nil { - return out, report.ReportFromError(err, report.EntryError) + convertReport := report.ReportFromError(err, report.EntryError) + if sub_node, err := getNodeChildPath(ast, "storage", "disks", disk_idx, "partitions", part_idx, "size"); err == nil { + convertReport.AddPosition(sub_node.ValueLineCol(nil)) + } + r.Merge(convertReport) + // dont add invalid partitions + continue } start, err := convertPartitionDimension(partition.Start) if err != nil { - return out, report.ReportFromError(err, report.EntryError) + convertReport := report.ReportFromError(err, report.EntryError) + if sub_node, err := getNodeChildPath(ast, "storage", "disks", disk_idx, "partitions", part_idx, "start"); err == nil { + convertReport.AddPosition(sub_node.ValueLineCol(nil)) + } + r.Merge(convertReport) + // dont add invalid partitions + continue } - newDisk.Partitions = append(newDisk.Partitions, ignTypes.Partition{ + newPart := ignTypes.Partition{ Label: ignTypes.PartitionLabel(partition.Label), Number: partition.Number, Size: size, Start: start, TypeGUID: ignTypes.PartitionTypeGUID(partition.TypeGUID), - }) + } + newDisk.Partitions = append(newDisk.Partitions, newPart) } out.Storage.Disks = append(out.Storage.Disks, newDisk) } - return out, report.Report{} + return out, r, ast }) } 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 index cf0b7659..3d971ed4 100644 --- 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 @@ -19,6 +19,7 @@ import ( "strings" ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -27,7 +28,7 @@ type Docker struct { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { 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{ @@ -39,6 +40,6 @@ func init() { }}, }) } - return out, report.Report{} + return out, report.Report{}, ast }) } 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 index 8fd186fc..6f90228b 100644 --- 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 @@ -20,6 +20,7 @@ import ( "github.com/coreos/go-semver/semver" ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -54,7 +55,7 @@ func (e EtcdVersion) Validate() report.Report { return report.ReportFromError(EtcdVersionTooOld, report.EntryError) case v.Major == 2 && v.Minor > 3: fallthrough - case v.Major == 3 && v.Minor > 1: + case v.Major == 3 && v.Minor > 2: return report.ReportFromError(EtcdMinorVersionTooNew, report.EntryWarning) case v.Major > 3: return report.ReportFromError(EtcdMajorVersionTooNew, report.EntryError) @@ -101,22 +102,28 @@ func (etcd *Etcd) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } etcd.Options = o - } else if version.Major == 3 && version.Minor >= 1 { + } else if version.Major == 3 && version.Minor == 1 { o := Etcd3_1{} if err := unmarshal(&o); err != nil { return err } etcd.Options = o + } else if version.Major == 3 && version.Minor >= 2 { + o := Etcd3_2{} + 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) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { if in.Etcd != nil { contents, err := etcdContents(*in.Etcd, platform) if err != nil { - return ignTypes.Config{}, report.ReportFromError(err, report.EntryError) + return ignTypes.Config{}, report.ReportFromError(err, report.EntryError), ast } out.Systemd.Units = append(out.Systemd.Units, ignTypes.SystemdUnit{ Name: "etcd-member.service", @@ -127,7 +134,7 @@ func init() { }}, }) } - return out, report.Report{} + return out, report.Report{}, ast }) } @@ -139,7 +146,12 @@ func etcdContents(etcd Etcd, platform string) (string, error) { vars = []string{fmt.Sprintf("ETCD_IMAGE_TAG=v%s", etcd.Version)} } - return assembleUnit("/usr/lib/coreos/etcd-wrapper $ETCD_OPTS", args, vars, platform) + unit, err := assembleUnit("/usr/lib/coreos/etcd-wrapper $ETCD_OPTS", args, vars, platform) + if err != nil { + return "", err + } + + return unit.String(), nil } type Etcd3_0 struct { @@ -149,6 +161,7 @@ type Etcd3_0 struct { SnapshotCount int `yaml:"snapshot_count" cli:"snapshot-count"` HeartbeatInterval int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` ElectionTimeout int `yaml:"election_timeout" cli:"election-timeout"` + EnablePprof bool `yaml:"enable_pprof" cli:"enable-pprof"` 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"` @@ -195,6 +208,7 @@ type Etcd3_1 struct { SnapshotCount int `yaml:"snapshot_count" cli:"snapshot-count"` HeartbeatInterval int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` ElectionTimeout int `yaml:"election_timeout" cli:"election-timeout"` + EnablePprof bool `yaml:"enable_pprof" cli:"enable-pprof"` 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"` @@ -236,6 +250,57 @@ type Etcd3_1 struct { LogOutput string `yaml:"log_output" cli:"log-output"` } +type Etcd3_2 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"` + EnablePprof bool `yaml:"enable_pprof" cli:"enable-pprof"` + EnableV2 bool `yaml:"enable_v2" cli:"enable-v2"` + 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"` + AuthToken string `yaml:"auth_token" cli:"auth-token"` + 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"` 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 index 81eb8b9a..651dc6ba 100644 --- 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 @@ -17,7 +17,10 @@ package types import ( "net/url" + "github.com/coreos/container-linux-config-transpiler/config/astyaml" + ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" "github.com/vincent-petithory/dataurl" ) @@ -51,8 +54,11 @@ type FileGroup struct { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { - for _, file := range in.Storage.Files { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { + r := report.Report{} + files_node, _ := getNodeChildPath(ast, "storage", "files") + for i, file := range in.Storage.Files { + file_node, _ := getNodeChild(files_node, i) newFile := ignTypes.File{ Filesystem: file.Filesystem, Path: ignTypes.Path(file.Path), @@ -73,10 +79,29 @@ func init() { if file.Contents.Remote.Url != "" { source, err := url.Parse(file.Contents.Remote.Url) if err != nil { - return out, report.ReportFromError(err, report.EntryError) + // if invalid, record error and continue + convertReport := report.ReportFromError(err, report.EntryError) + if n, err := getNodeChildPath(file_node, "contents", "remote", "url"); err != nil { + line, col, _ := n.ValueLineCol(nil) + convertReport.AddPosition(line, col, "") + } + continue + } + + // patch the yaml tree to look like the ignition tree by making contents + // the remote section and changing the name from url -> source + asYamlNode, ok := file_node.(astyaml.YamlNode) + if ok { + newContents, _ := getNodeChildPath(file_node, "contents", "remote") + newContentsAsYaml := newContents.(astyaml.YamlNode) + asYamlNode.ChangeKey("contents", "contents", newContentsAsYaml) + + url, _ := getNodeChild(newContents.(astyaml.YamlNode), "url") + newContentsAsYaml.ChangeKey("url", "source", url.(astyaml.YamlNode)) } newFile.Contents = ignTypes.FileContents{Source: ignTypes.Url(*source)} + } if newFile.Contents == (ignTypes.FileContents{}) { @@ -93,6 +118,6 @@ func init() { out.Storage.Files = append(out.Storage.Files, newFile) } - return out, report.Report{} + return out, r, ast }) } 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 index f6d11d67..2890b900 100644 --- 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 @@ -16,6 +16,7 @@ package types import ( ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -37,7 +38,7 @@ type Create struct { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { for _, filesystem := range in.Storage.Filesystems { newFilesystem := ignTypes.Filesystem{ Name: filesystem.Name, @@ -66,6 +67,6 @@ func init() { out.Storage.Filesystems = append(out.Storage.Filesystems, newFilesystem) } - return out, report.Report{} + return out, report.Report{}, ast }) } 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 index 677fa7f6..ea41a0e0 100644 --- 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 @@ -1,23 +1,28 @@ package types import ( + "encoding/json" "errors" "fmt" "github.com/coreos/go-semver/semver" ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "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") + 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") + ErrNetConfigInvalidJSON = errors.New("flannel network config doesn't appear to be valid JSON") + ErrNetConfigProvidedAndKubeMgrSet = errors.New("flannel network config cannot be provided if kube_subnet_mgr is set") + OldestFlannelVersion = *semver.New("0.5.0") + FlannelDefaultVersion = *semver.New("0.6.0") ) type Flannel struct { - Version *FlannelVersion `yaml:"version"` + Version *FlannelVersion `yaml:"version"` + NetworkConfig NetworkConfig `yaml:"network_config"` Options } @@ -25,6 +30,20 @@ type flannelCommon Flannel type FlannelVersion semver.Version +type NetworkConfig string + +func (nc NetworkConfig) Validate() report.Report { + if nc == "" { + return report.Report{} + } + tmp := make(map[string]interface{}) + err := json.Unmarshal([]byte(nc), &tmp) + if err != nil { + return report.ReportFromError(ErrNetConfigInvalidJSON, report.EntryError) + } + return report.Report{} +} + func (v *FlannelVersion) UnmarshalYAML(unmarshal func(interface{}) error) error { t := semver.Version(*v) if err := unmarshal(&t); err != nil { @@ -49,6 +68,16 @@ func (fv FlannelVersion) String() string { return semver.Version(fv).String() } +func (f *Flannel) Validate() report.Report { + switch o := f.Options.(type) { + case Flannel0_7: + if o.KubeSubnetMgr && f.NetworkConfig != "" { + return report.ReportFromError(ErrNetConfigProvidedAndKubeMgrSet, report.EntryError) + } + } + return report.Report{} +} + func (flannel *Flannel) UnmarshalYAML(unmarshal func(interface{}) error) error { t := flannelCommon(*flannel) if err := unmarshal(&t); err != nil { @@ -86,11 +115,11 @@ func (flannel *Flannel) UnmarshalYAML(unmarshal func(interface{}) error) error { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { if in.Flannel != nil { contents, err := flannelContents(*in.Flannel, platform) if err != nil { - return ignTypes.Config{}, report.ReportFromError(err, report.EntryError) + return ignTypes.Config{}, report.ReportFromError(err, report.EntryError), ast } out.Systemd.Units = append(out.Systemd.Units, ignTypes.SystemdUnit{ Name: "flanneld.service", @@ -101,16 +130,63 @@ func init() { }}, }) } - return out, report.Report{} + return out, report.Report{}, ast }) } // 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)} + var vars []string + if flannel.Version != nil { + vars = []string{fmt.Sprintf("FLANNEL_IMAGE_TAG=v%s", flannel.Version)} + } - return assembleUnit("/usr/lib/coreos/flannel-wrapper $FLANNEL_OPTS", args, vars, platform) + unit, err := assembleUnit("/usr/lib/coreos/flannel-wrapper $FLANNEL_OPTS", args, vars, platform) + if err != nil { + return "", err + } + + if flannel.NetworkConfig != "" { + pre := "ExecStartPre=/usr/bin/etcdctl" + var endpoints string + var etcdCAFile string + var etcdCertFile string + var etcdKeyFile string + switch o := flannel.Options.(type) { + case Flannel0_7: + endpoints = o.EtcdEndpoints + etcdCAFile = o.EtcdCAFile + etcdCertFile = o.EtcdCertFile + etcdKeyFile = o.EtcdKeyFile + case Flannel0_6: + endpoints = o.EtcdEndpoints + etcdCAFile = o.EtcdCAFile + etcdCertFile = o.EtcdCertFile + etcdKeyFile = o.EtcdKeyFile + case Flannel0_5: + endpoints = o.EtcdEndpoints + etcdCAFile = o.EtcdCAFile + etcdCertFile = o.EtcdCertFile + etcdKeyFile = o.EtcdKeyFile + } + if endpoints != "" { + pre += fmt.Sprintf(" --endpoints=%q", endpoints) + } + if etcdCAFile != "" { + pre += fmt.Sprintf(" --ca-file=%q", etcdCAFile) + } + if etcdCertFile != "" { + pre += fmt.Sprintf(" --cert-file=%q", etcdCertFile) + } + if etcdKeyFile != "" { + pre += fmt.Sprintf(" --key-file=%q", etcdKeyFile) + } + pre += fmt.Sprintf(" set /coreos.com/network/config %q", flannel.NetworkConfig) + unit.Service.Add(pre) + } + + return unit.String(), nil } // Flannel0_7 represents flannel options for version 0.7.x. Don't embed Flannel0_6 because 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 index 9c91de73..9a305052 100644 --- 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 @@ -16,20 +16,47 @@ package types import ( "errors" + "fmt" "strings" + "time" "github.com/coreos/ignition/config/validate/report" ) var ( - ErrUnknownStrategy = errors.New("unknown reboot strategy") + ErrMissingStartOrLength = errors.New("window-start and window-length must both be specified") + ErrUnknownStrategy = errors.New("unknown reboot strategy") + ErrParsingWindowStart = errors.New("couldn't parse window start") + ErrUnknownDay = errors.New("unknown day in window start") + ErrParsingWindow = errors.New("couldn't parse window start") + ErrParsingLength = errors.New("couldn't parse window length") ) type Locksmith struct { - RebootStrategy RebootStrategy `yaml:"reboot_strategy"` + RebootStrategy RebootStrategy `yaml:"reboot_strategy" locksmith:"REBOOT_STRATEGY"` + WindowStart WindowStart `yaml:"window_start" locksmith:"LOCKSMITHD_REBOOT_WINDOW_START"` + WindowLength WindowLength `yaml:"window_length" locksmith:"LOCKSMITHD_REBOOT_WINDOW_LENGTH"` + Group string `yaml:"group" locksmith:"LOCKSMITHD_GROUP"` + EtcdEndpoints string `yaml:"etcd_endpoints" locksmith:"LOCKSMITHD_ENDPOINT"` + EtcdCAFile string `yaml:"etcd_cafile" locksmith:"LOCKSMITHD_ETCD_CAFILE"` + EtcdCertFile string `yaml:"etcd_certfile" locksmith:"LOCKSMITHD_ETCD_CERTFILE"` + EtcdKeyFile string `yaml:"etcd_keyfile" locksmith:"LOCKSMITHD_ETCD_KEYFILE"` +} + +func (l Locksmith) configLines() []string { + return getArgs("%s=%q", "locksmith", l) } type RebootStrategy string +type WindowStart string +type WindowLength string + +func (l Locksmith) Validate() report.Report { + if (l.WindowStart != "" && l.WindowLength == "") || (l.WindowStart == "" && l.WindowLength != "") { + return report.ReportFromError(ErrMissingStartOrLength, report.EntryError) + } + return report.Report{} +} func (r RebootStrategy) Validate() report.Report { switch strings.ToLower(string(r)) { @@ -39,3 +66,42 @@ func (r RebootStrategy) Validate() report.Report { return report.ReportFromError(ErrUnknownStrategy, report.EntryError) } } + +func (s WindowStart) Validate() report.Report { + if s == "" { + return report.Report{} + } + var day string + var t string + + _, err := fmt.Sscanf(string(s), "%s %s", &day, &t) + if err != nil { + day = "not-present" + t = string(s) + } + + switch strings.ToLower(day) { + case "sun", "mon", "tue", "wed", "thu", "fri", "sat", "not-present": + break + default: + return report.ReportFromError(ErrUnknownDay, report.EntryError) + } + + _, err = time.Parse("15:04", t) + if err != nil { + return report.ReportFromError(ErrParsingWindow, report.EntryError) + } + + return report.Report{} +} + +func (l WindowLength) Validate() report.Report { + if l == "" { + return report.Report{} + } + _, err := time.ParseDuration(string(l)) + if err != nil { + return report.ReportFromError(ErrParsingLength, report.EntryError) + } + return report.Report{} +} 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 index 5191aabb..8c589248 100644 --- 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 @@ -16,6 +16,7 @@ package types import ( ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -29,13 +30,13 @@ type NetworkdUnit struct { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { 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{} + return out, report.Report{}, ast }) } diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/passwd.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/passwd.go index 950c8ba7..c3c51cb6 100644 --- a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/passwd.go +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/passwd.go @@ -16,6 +16,7 @@ package types import ( ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -52,8 +53,11 @@ type Group struct { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { for _, user := range in.Passwd.Users { + if user.Name != "core" && user.Create == nil { + user.Create = &UserCreate{} + } newUser := ignTypes.User{ Name: user.Name, PasswordHash: user.PasswordHash, @@ -86,6 +90,6 @@ func init() { System: group.System, }) } - return out, report.Report{} + return out, report.Report{}, ast }) } 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 index 9d11d868..7cc5e809 100644 --- 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 @@ -16,6 +16,7 @@ package types import ( ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -27,7 +28,7 @@ type Raid struct { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { for _, array := range in.Storage.Arrays { newArray := ignTypes.Raid{ Name: array.Name, @@ -41,6 +42,6 @@ func init() { out.Storage.Arrays = append(out.Storage.Arrays, newArray) } - return out, report.Report{} + return out, report.Report{}, ast }) } 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 index ea6a9935..492ac32a 100644 --- 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 @@ -16,6 +16,7 @@ package types import ( ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" ) @@ -37,7 +38,7 @@ type SystemdUnitDropIn struct { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { for _, unit := range in.Systemd.Units { newUnit := ignTypes.SystemdUnit{ Name: ignTypes.SystemdUnitName(unit.Name), @@ -55,6 +56,6 @@ func init() { out.Systemd.Units = append(out.Systemd.Units, newUnit) } - return out, report.Report{} + return out, report.Report{}, ast }) } 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 index 4adf0d01..2f6bc45b 100644 --- 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 @@ -21,6 +21,7 @@ import ( "strings" ignTypes "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/report" "github.com/vincent-petithory/dataurl" ) @@ -58,7 +59,7 @@ func (s UpdateServer) Validate() report.Report { } func init() { - register2_0(func(in Config, out ignTypes.Config, platform string) (ignTypes.Config, report.Report) { + register2_0(func(in Config, ast validate.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, validate.AstNode) { var contents string if in.Update != nil { if in.Update.Group != "" { @@ -69,8 +70,9 @@ func init() { } } if in.Locksmith != nil { - if in.Locksmith.RebootStrategy != "" { - contents += fmt.Sprintf("\nREBOOT_STRATEGY=%s", strings.ToLower(string(in.Locksmith.RebootStrategy))) + lines := in.Locksmith.configLines() + if len(lines) > 0 { + contents += "\n" + strings.Join(lines, "\n") } } if contents != "" { @@ -86,6 +88,6 @@ func init() { }, }) } - return out, report.Report{} + return out, report.Report{}, ast }) } diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/util/unit.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/util/unit.go new file mode 100644 index 00000000..03fb0a92 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/util/unit.go @@ -0,0 +1,62 @@ +// 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 util + +type SystemdUnit struct { + Unit *UnitSection + Service *UnitSection + Install *UnitSection +} + +func NewSystemdUnit() SystemdUnit { + return SystemdUnit{ + Unit: &UnitSection{}, + Service: &UnitSection{}, + Install: &UnitSection{}, + } +} + +type UnitSection []string + +func (u *UnitSection) Add(line string) { + *u = append(*u, line) +} + +func (s SystemdUnit) String() string { + res := "" + + type section struct { + name string + contents []string + } + + for _, sec := range []section{ + {"Unit", *s.Unit}, + {"Service", *s.Service}, + {"Install", *s.Install}, + } { + if len(sec.contents) == 0 { + continue + } + if res != "" { + res += "\n\n" + } + res += "[" + sec.name + "]" + for _, line := range sec.contents { + res += "\n" + line + } + } + return res +} diff --git a/vendor/github.com/coreos/ignition/config/append.go b/vendor/github.com/coreos/ignition/config/append.go index 10915bc1..c66a1223 100644 --- a/vendor/github.com/coreos/ignition/config/append.go +++ b/vendor/github.com/coreos/ignition/config/append.go @@ -36,11 +36,10 @@ func Append(oldConfig, newConfig types.Config) 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". +// overwriting old values with the new for all other types. Some individual +// struct fields have alternate merge strategies, determined by the field name. +// Currently these fields are "ignition.version", which uses the old value, and +// "ignition.config" which uses the new value. func appendStruct(vOld, vNew reflect.Value) reflect.Value { tOld := vOld.Type() vRes := reflect.New(tOld) @@ -50,11 +49,11 @@ func appendStruct(vOld, vNew reflect.Value) reflect.Value { vfNew := vNew.Field(i) vfRes := vRes.Elem().Field(i) - switch tOld.Field(i).Tag.Get("merge") { - case "old": + switch tOld.Field(i).Name { + case "Version": vfRes.Set(vfOld) continue - case "new": + case "Config": vfRes.Set(vfNew) continue } diff --git a/vendor/github.com/coreos/ignition/config/config.go b/vendor/github.com/coreos/ignition/config/config.go index fc41815b..1263b558 100644 --- a/vendor/github.com/coreos/ignition/config/config.go +++ b/vendor/github.com/coreos/ignition/config/config.go @@ -22,55 +22,69 @@ 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/v2_1" "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" + "github.com/coreos/go-semver/semver" "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") + 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") + ErrUnknownVersion = errors.New("unsupported config version") + ErrVersionIndeterminable = errors.New("unable to determine version") ) // 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 version(rawConfig) { - case types.IgnitionVersion{Major: 1}: + version, err := Version(rawConfig) + if err != nil && err != ErrVersionIndeterminable { + // If we can't determine the version, ignore this error so that in the + // default case of the switch statement we can check for empty configs, + // cloud configs, and other such things. + return types.Config{}, report.ReportFromError(err, report.EntryError), err + } + switch version { + case semver.Version{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}: + case types.MaxVersion: + return ParseFromLatest(rawConfig) + case semver.Version{Major: 2, Minor: 1}: + return ParseFromV2_1(rawConfig) + case semver.Version{Major: 2, Minor: 0}: return ParseFromV2_0(rawConfig) default: - return ParseFromLatest(rawConfig) + 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 + } + return types.Config{}, report.Report{}, ErrUnknownVersion } } func ParseFromLatest(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() + versionReport := config.Ignition.Validate() if versionReport.IsFatal() { return types.Config{}, versionReport, ErrInvalid } @@ -123,7 +137,7 @@ func ParseFromLatest(rawConfig []byte) (types.Config, report.Report, error) { }) r.Merge(validate.ValidateWithoutSource(configValue)) } else { - r.Merge(validate.Validate(configValue, astjson.FromJsonRoot(ast), bytes.NewReader(rawConfig))) + r.Merge(validate.Validate(configValue, astjson.FromJsonRoot(ast), bytes.NewReader(rawConfig), true)) } if r.IsFatal() { @@ -151,23 +165,36 @@ func ParseFromV2_0(rawConfig []byte) (types.Config, report.Report, error) { return TranslateFromV2_0(cfg), report, err } -func version(rawConfig []byte) types.IgnitionVersion { +func ParseFromV2_1(rawConfig []byte) (types.Config, report.Report, error) { + cfg, report, err := v2_1.Parse(rawConfig) + if err != nil { + return types.Config{}, report, err + } + + return TranslateFromV2_1(cfg), report, err +} + +func Version(rawConfig []byte) (semver.Version, error) { var composite struct { Version *int `json:"ignitionVersion"` Ignition struct { - Version *types.IgnitionVersion `json:"version"` + Version *string `json:"version"` } `json:"ignition"` } if json.Unmarshal(rawConfig, &composite) == nil { if composite.Ignition.Version != nil { - return *composite.Ignition.Version + v, err := types.Ignition{Version: *composite.Ignition.Version}.Semver() + if err != nil { + return semver.Version{}, err + } + return *v, nil } else if composite.Version != nil { - return types.IgnitionVersion{Major: int64(*composite.Version)} + return semver.Version{Major: int64(*composite.Version)}, nil } } - return types.IgnitionVersion{} + return semver.Version{}, ErrVersionIndeterminable } 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 befe7440..a5eb9bc2 100644 --- a/vendor/github.com/coreos/ignition/config/translate.go +++ b/vendor/github.com/coreos/ignition/config/translate.go @@ -16,34 +16,52 @@ package config import ( "fmt" + "net/url" + "strings" "github.com/coreos/ignition/config/types" v1 "github.com/coreos/ignition/config/v1/types" v2_0 "github.com/coreos/ignition/config/v2_0/types" + v2_1 "github.com/coreos/ignition/config/v2_1/types" "github.com/vincent-petithory/dataurl" ) +func intToPtr(x int) *int { + return &x +} + +func strToPtr(s string) *string { + if s == "" { + return nil + } + return &s +} + +func boolToPtr(b bool) *bool { + return &b +} + func TranslateFromV1(old v1.Config) types.Config { config := types.Config{ Ignition: types.Ignition{ - Version: types.IgnitionVersion(v2_0.MaxVersion), + Version: v2_0.MaxVersion.String(), }, } for _, oldDisk := range old.Storage.Disks { disk := types.Disk{ - Device: types.Path(oldDisk.Device), + Device: string(oldDisk.Device), WipeTable: oldDisk.WipeTable, } for _, oldPartition := range oldDisk.Partitions { disk.Partitions = append(disk.Partitions, types.Partition{ - Label: types.PartitionLabel(oldPartition.Label), + Label: string(oldPartition.Label), Number: oldPartition.Number, - Size: types.PartitionDimension(oldPartition.Size), - Start: types.PartitionDimension(oldPartition.Start), - TypeGUID: types.PartitionTypeGUID(oldPartition.TypeGUID), + Size: int(oldPartition.Size), + Start: int(oldPartition.Start), + TypeGUID: string(oldPartition.TypeGUID), }) } @@ -58,25 +76,25 @@ func TranslateFromV1(old v1.Config) types.Config { } for _, oldDevice := range oldArray.Devices { - array.Devices = append(array.Devices, types.Path(oldDevice)) + array.Devices = append(array.Devices, types.Device(oldDevice)) } - config.Storage.Arrays = append(config.Storage.Arrays, array) + config.Storage.Raid = append(config.Storage.Raid, array) } for i, oldFilesystem := range old.Storage.Filesystems { filesystem := types.Filesystem{ Name: fmt.Sprintf("_translate-filesystem-%d", i), - Mount: &types.FilesystemMount{ - Device: types.Path(oldFilesystem.Device), - Format: types.FilesystemFormat(oldFilesystem.Format), + Mount: &types.Mount{ + Device: string(oldFilesystem.Device), + Format: string(oldFilesystem.Format), }, } if oldFilesystem.Create != nil { - filesystem.Mount.Create = &types.FilesystemCreate{ + filesystem.Mount.Create = &types.Create{ Force: oldFilesystem.Create.Force, - Options: types.MkfsOptions(oldFilesystem.Create.Options), + Options: translateV1MkfsOptionsToV2_2OptionSlice(oldFilesystem.Create.Options), } } @@ -86,15 +104,17 @@ func TranslateFromV1(old v1.Config) types.Config { file := types.File{ 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}, + Path: string(oldFile.Path), + User: types.NodeUser{ID: intToPtr(oldFile.Uid)}, + Group: types.NodeGroup{ID: intToPtr(oldFile.Gid)}, }, - Contents: types.FileContents{ - Source: types.Url{ - Scheme: "data", - Opaque: "," + dataurl.EscapeString(oldFile.Contents), + FileEmbedded1: types.FileEmbedded1{ + Mode: int(oldFile.Mode), + Contents: types.FileContents{ + Source: (&url.URL{ + Scheme: "data", + Opaque: "," + dataurl.EscapeString(oldFile.Contents), + }).String(), }, }, } @@ -104,16 +124,16 @@ func TranslateFromV1(old v1.Config) types.Config { } for _, oldUnit := range old.Systemd.Units { - unit := types.SystemdUnit{ - Name: types.SystemdUnitName(oldUnit.Name), + unit := types.Unit{ + Name: string(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), + unit.Dropins = append(unit.Dropins, types.Dropin{ + Name: string(oldDropIn.Name), Contents: oldDropIn.Contents, }) } @@ -122,27 +142,33 @@ func TranslateFromV1(old v1.Config) types.Config { } for _, oldUnit := range old.Networkd.Units { - config.Networkd.Units = append(config.Networkd.Units, types.NetworkdUnit{ - Name: types.NetworkdUnitName(oldUnit.Name), + config.Networkd.Units = append(config.Networkd.Units, types.Networkdunit{ + Name: string(oldUnit.Name), Contents: oldUnit.Contents, }) } for _, oldUser := range old.Passwd.Users { - user := types.User{ + user := types.PasswdUser{ Name: oldUser.Name, - PasswordHash: oldUser.PasswordHash, - SSHAuthorizedKeys: oldUser.SSHAuthorizedKeys, + PasswordHash: strToPtr(oldUser.PasswordHash), + SSHAuthorizedKeys: translateStringSliceToV2_2SSHAuthorizedKeySlice(oldUser.SSHAuthorizedKeys), } if oldUser.Create != nil { - user.Create = &types.UserCreate{ - Uid: oldUser.Create.Uid, - GECOS: oldUser.Create.GECOS, - Homedir: oldUser.Create.Homedir, + var uid *int + if oldUser.Create.Uid != nil { + tmp := int(*oldUser.Create.Uid) + uid = &tmp + } + + user.Create = &types.Usercreate{ + UID: uid, + Gecos: oldUser.Create.GECOS, + HomeDir: oldUser.Create.Homedir, NoCreateHome: oldUser.Create.NoCreateHome, PrimaryGroup: oldUser.Create.PrimaryGroup, - Groups: oldUser.Create.Groups, + Groups: translateStringSliceToV2_2UsercreateGroupSlice(oldUser.Create.Groups), NoUserGroup: oldUser.Create.NoUserGroup, System: oldUser.Create.System, NoLogInit: oldUser.Create.NoLogInit, @@ -154,9 +180,14 @@ func TranslateFromV1(old v1.Config) types.Config { } for _, oldGroup := range old.Passwd.Groups { - config.Passwd.Groups = append(config.Passwd.Groups, types.Group{ + var gid *int + if oldGroup.Gid != nil { + tmp := int(*oldGroup.Gid) + gid = &tmp + } + config.Passwd.Groups = append(config.Passwd.Groups, types.PasswdGroup{ Name: oldGroup.Name, - Gid: oldGroup.Gid, + Gid: gid, PasswordHash: oldGroup.PasswordHash, System: oldGroup.System, }) @@ -165,25 +196,53 @@ func TranslateFromV1(old v1.Config) types.Config { return config } +// golang-- +func translateV1MkfsOptionsToV2_2OptionSlice(opts v1.MkfsOptions) []types.CreateOption { + newOpts := make([]types.CreateOption, len(opts)) + for i, o := range opts { + newOpts[i] = types.CreateOption(o) + } + return newOpts +} + +// golang-- +func translateStringSliceToV2_2SSHAuthorizedKeySlice(keys []string) []types.SSHAuthorizedKey { + newKeys := make([]types.SSHAuthorizedKey, len(keys)) + for i, k := range keys { + newKeys[i] = types.SSHAuthorizedKey(k) + } + return newKeys +} + +// golang-- +func translateStringSliceToV2_2UsercreateGroupSlice(groups []string) []types.UsercreateGroup { + var newGroups []types.UsercreateGroup + for _, g := range groups { + newGroups = append(newGroups, types.UsercreateGroup(g)) + } + return newGroups +} + 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) + // .String() here is a wrapper around MarshalJSON, which will put the hash in quotes + h := strings.Trim(old.Hash.String(), "\"") ver.Hash = &h } return ver } translateConfigReference := func(old v2_0.ConfigReference) types.ConfigReference { return types.ConfigReference{ - Source: types.Url(old.Source), + Source: old.Source.String(), Verification: translateVerification(old.Verification), } } config := types.Config{ Ignition: types.Ignition{ - Version: types.IgnitionVersion(types.MaxVersion), + Version: types.MaxVersion.String(), }, } @@ -199,17 +258,17 @@ func TranslateFromV2_0(old v2_0.Config) types.Config { for _, oldDisk := range old.Storage.Disks { disk := types.Disk{ - Device: types.Path(oldDisk.Device), + Device: string(oldDisk.Device), WipeTable: oldDisk.WipeTable, } for _, oldPartition := range oldDisk.Partitions { disk.Partitions = append(disk.Partitions, types.Partition{ - Label: types.PartitionLabel(oldPartition.Label), + Label: string(oldPartition.Label), Number: oldPartition.Number, - Size: types.PartitionDimension(oldPartition.Size), - Start: types.PartitionDimension(oldPartition.Start), - TypeGUID: types.PartitionTypeGUID(oldPartition.TypeGUID), + Size: int(oldPartition.Size), + Start: int(oldPartition.Start), + TypeGUID: string(oldPartition.TypeGUID), }) } @@ -224,10 +283,10 @@ func TranslateFromV2_0(old v2_0.Config) types.Config { } for _, oldDevice := range oldArray.Devices { - array.Devices = append(array.Devices, types.Path(oldDevice)) + array.Devices = append(array.Devices, types.Device(oldDevice)) } - config.Storage.Arrays = append(config.Storage.Arrays, array) + config.Storage.Raid = append(config.Storage.Raid, array) } for _, oldFilesystem := range old.Storage.Filesystems { @@ -236,22 +295,22 @@ func TranslateFromV2_0(old v2_0.Config) types.Config { } if oldFilesystem.Mount != nil { - filesystem.Mount = &types.FilesystemMount{ - Device: types.Path(oldFilesystem.Mount.Device), - Format: types.FilesystemFormat(oldFilesystem.Mount.Format), + filesystem.Mount = &types.Mount{ + Device: string(oldFilesystem.Mount.Device), + Format: string(oldFilesystem.Mount.Format), } if oldFilesystem.Mount.Create != nil { - filesystem.Mount.Create = &types.FilesystemCreate{ + filesystem.Mount.Create = &types.Create{ Force: oldFilesystem.Mount.Create.Force, - Options: types.MkfsOptions(oldFilesystem.Mount.Create.Options), + Options: translateV2_0MkfsOptionsToV2_2OptionSlice(oldFilesystem.Mount.Create.Options), } } } if oldFilesystem.Path != nil { - path := types.Path(*oldFilesystem.Path) - filesystem.Path = &path + p := string(*oldFilesystem.Path) + filesystem.Path = &p } config.Storage.Filesystems = append(config.Storage.Filesystems, filesystem) @@ -261,15 +320,17 @@ func TranslateFromV2_0(old v2_0.Config) types.Config { 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}, + Path: string(oldFile.Path), + User: types.NodeUser{ID: intToPtr(oldFile.User.Id)}, + Group: types.NodeGroup{ID: intToPtr(oldFile.Group.Id)}, }, - Contents: types.FileContents{ - Compression: types.Compression(oldFile.Contents.Compression), - Source: types.Url(oldFile.Contents.Source), - Verification: translateVerification(oldFile.Contents.Verification), + FileEmbedded1: types.FileEmbedded1{ + Mode: int(oldFile.Mode), + Contents: types.FileContents{ + Compression: string(oldFile.Contents.Compression), + Source: oldFile.Contents.Source.String(), + Verification: translateVerification(oldFile.Contents.Verification), + }, }, } @@ -277,16 +338,16 @@ func TranslateFromV2_0(old v2_0.Config) types.Config { } for _, oldUnit := range old.Systemd.Units { - unit := types.SystemdUnit{ - Name: types.SystemdUnitName(oldUnit.Name), + unit := types.Unit{ + Name: string(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), + unit.Dropins = append(unit.Dropins, types.Dropin{ + Name: string(oldDropIn.Name), Contents: oldDropIn.Contents, }) } @@ -295,27 +356,32 @@ func TranslateFromV2_0(old v2_0.Config) types.Config { } for _, oldUnit := range old.Networkd.Units { - config.Networkd.Units = append(config.Networkd.Units, types.NetworkdUnit{ - Name: types.NetworkdUnitName(oldUnit.Name), + config.Networkd.Units = append(config.Networkd.Units, types.Networkdunit{ + Name: string(oldUnit.Name), Contents: oldUnit.Contents, }) } for _, oldUser := range old.Passwd.Users { - user := types.User{ + user := types.PasswdUser{ Name: oldUser.Name, - PasswordHash: oldUser.PasswordHash, - SSHAuthorizedKeys: oldUser.SSHAuthorizedKeys, + PasswordHash: strToPtr(oldUser.PasswordHash), + SSHAuthorizedKeys: translateStringSliceToV2_2SSHAuthorizedKeySlice(oldUser.SSHAuthorizedKeys), } if oldUser.Create != nil { - user.Create = &types.UserCreate{ - Uid: oldUser.Create.Uid, - GECOS: oldUser.Create.GECOS, - Homedir: oldUser.Create.Homedir, + var u *int + if oldUser.Create.Uid != nil { + tmp := int(*oldUser.Create.Uid) + u = &tmp + } + user.Create = &types.Usercreate{ + UID: u, + Gecos: oldUser.Create.GECOS, + HomeDir: oldUser.Create.Homedir, NoCreateHome: oldUser.Create.NoCreateHome, PrimaryGroup: oldUser.Create.PrimaryGroup, - Groups: oldUser.Create.Groups, + Groups: translateStringSliceToV2_2UsercreateGroupSlice(oldUser.Create.Groups), NoUserGroup: oldUser.Create.NoUserGroup, System: oldUser.Create.System, NoLogInit: oldUser.Create.NoLogInit, @@ -327,9 +393,14 @@ func TranslateFromV2_0(old v2_0.Config) types.Config { } for _, oldGroup := range old.Passwd.Groups { - config.Passwd.Groups = append(config.Passwd.Groups, types.Group{ + var g *int + if oldGroup.Gid != nil { + tmp := int(*oldGroup.Gid) + g = &tmp + } + config.Passwd.Groups = append(config.Passwd.Groups, types.PasswdGroup{ Name: oldGroup.Name, - Gid: oldGroup.Gid, + Gid: g, PasswordHash: oldGroup.PasswordHash, System: oldGroup.System, }) @@ -337,3 +408,327 @@ func TranslateFromV2_0(old v2_0.Config) types.Config { return config } + +// golang-- +func translateV2_0MkfsOptionsToV2_2OptionSlice(opts v2_0.MkfsOptions) []types.CreateOption { + newOpts := make([]types.CreateOption, len(opts)) + for i, o := range opts { + newOpts[i] = types.CreateOption(o) + } + return newOpts +} + +func TranslateFromV2_1(old v2_1.Config) types.Config { + translateConfigReference := func(old *v2_1.ConfigReference) *types.ConfigReference { + if old == nil { + return nil + } + return &types.ConfigReference{ + Source: old.Source, + Verification: types.Verification{ + Hash: old.Verification.Hash, + }, + } + } + translateConfigReferenceSlice := func(old []v2_1.ConfigReference) []types.ConfigReference { + var res []types.ConfigReference + for _, c := range old { + res = append(res, *translateConfigReference(&c)) + } + return res + } + translateNetworkdUnitSlice := func(old []v2_1.Networkdunit) []types.Networkdunit { + var res []types.Networkdunit + for _, u := range old { + res = append(res, types.Networkdunit{ + Contents: u.Contents, + Name: u.Name, + }) + } + return res + } + translatePasswdGroupSlice := func(old []v2_1.PasswdGroup) []types.PasswdGroup { + var res []types.PasswdGroup + for _, g := range old { + res = append(res, types.PasswdGroup{ + Gid: g.Gid, + Name: g.Name, + PasswordHash: g.PasswordHash, + System: g.System, + }) + } + return res + } + translatePasswdUsercreateGroupSlice := func(old []v2_1.UsercreateGroup) []types.UsercreateGroup { + var res []types.UsercreateGroup + for _, g := range old { + res = append(res, types.UsercreateGroup(g)) + } + return res + } + translatePasswdUsercreate := func(old *v2_1.Usercreate) *types.Usercreate { + if old == nil { + return nil + } + return &types.Usercreate{ + Gecos: old.Gecos, + Groups: translatePasswdUsercreateGroupSlice(old.Groups), + HomeDir: old.HomeDir, + NoCreateHome: old.NoCreateHome, + NoLogInit: old.NoLogInit, + NoUserGroup: old.NoUserGroup, + PrimaryGroup: old.PrimaryGroup, + Shell: old.Shell, + System: old.System, + UID: old.UID, + } + } + translatePasswdUserGroupSlice := func(old []v2_1.PasswdUserGroup) []types.PasswdUserGroup { + var res []types.PasswdUserGroup + for _, g := range old { + res = append(res, types.PasswdUserGroup(g)) + } + return res + } + translatePasswdSSHAuthorizedKeySlice := func(old []v2_1.SSHAuthorizedKey) []types.SSHAuthorizedKey { + res := make([]types.SSHAuthorizedKey, len(old)) + for i, k := range old { + res[i] = types.SSHAuthorizedKey(k) + } + return res + } + translatePasswdUserSlice := func(old []v2_1.PasswdUser) []types.PasswdUser { + var res []types.PasswdUser + for _, u := range old { + res = append(res, types.PasswdUser{ + Create: translatePasswdUsercreate(u.Create), + Gecos: u.Gecos, + Groups: translatePasswdUserGroupSlice(u.Groups), + HomeDir: u.HomeDir, + Name: u.Name, + NoCreateHome: u.NoCreateHome, + NoLogInit: u.NoLogInit, + NoUserGroup: u.NoUserGroup, + PasswordHash: u.PasswordHash, + PrimaryGroup: u.PrimaryGroup, + SSHAuthorizedKeys: translatePasswdSSHAuthorizedKeySlice(u.SSHAuthorizedKeys), + Shell: u.Shell, + System: u.System, + UID: u.UID, + }) + } + return res + } + translateNodeGroup := func(old v2_1.NodeGroup) types.NodeGroup { + return types.NodeGroup{ + ID: old.ID, + Name: old.Name, + } + } + translateNodeUser := func(old v2_1.NodeUser) types.NodeUser { + return types.NodeUser{ + ID: old.ID, + Name: old.Name, + } + } + translateNode := func(old v2_1.Node) types.Node { + return types.Node{ + Filesystem: old.Filesystem, + Group: translateNodeGroup(old.Group), + Path: old.Path, + User: translateNodeUser(old.User), + } + } + translateDirectorySlice := func(old []v2_1.Directory) []types.Directory { + var res []types.Directory + for _, x := range old { + res = append(res, types.Directory{ + Node: translateNode(x.Node), + DirectoryEmbedded1: types.DirectoryEmbedded1{ + Mode: x.DirectoryEmbedded1.Mode, + }, + }) + } + return res + } + translatePartitionSlice := func(old []v2_1.Partition) []types.Partition { + var res []types.Partition + for _, x := range old { + res = append(res, types.Partition{ + GUID: x.GUID, + Label: x.Label, + Number: x.Number, + Size: x.Size, + Start: x.Start, + TypeGUID: x.TypeGUID, + }) + } + return res + } + translateDiskSlice := func(old []v2_1.Disk) []types.Disk { + var res []types.Disk + for _, x := range old { + res = append(res, types.Disk{ + Device: x.Device, + Partitions: translatePartitionSlice(x.Partitions), + WipeTable: x.WipeTable, + }) + } + return res + } + translateFileSlice := func(old []v2_1.File) []types.File { + var res []types.File + for _, x := range old { + res = append(res, types.File{ + Node: translateNode(x.Node), + FileEmbedded1: types.FileEmbedded1{ + Contents: types.FileContents{ + Compression: x.Contents.Compression, + Source: x.Contents.Source, + Verification: types.Verification{ + Hash: x.Contents.Verification.Hash, + }, + }, + Mode: x.Mode, + }, + }) + } + return res + } + translateMountCreateOptionSlice := func(old []v2_1.CreateOption) []types.CreateOption { + var res []types.CreateOption + for _, x := range old { + res = append(res, types.CreateOption(x)) + } + return res + } + translateMountCreate := func(old *v2_1.Create) *types.Create { + if old == nil { + return nil + } + return &types.Create{ + Force: old.Force, + Options: translateMountCreateOptionSlice(old.Options), + } + } + translateMountOptionSlice := func(old []v2_1.MountOption) []types.MountOption { + var res []types.MountOption + for _, x := range old { + res = append(res, types.MountOption(x)) + } + return res + } + translateMount := func(old *v2_1.Mount) *types.Mount { + if old == nil { + return nil + } + return &types.Mount{ + Create: translateMountCreate(old.Create), + Device: old.Device, + Format: old.Format, + Label: old.Label, + Options: translateMountOptionSlice(old.Options), + UUID: old.UUID, + WipeFilesystem: old.WipeFilesystem, + } + } + translateFilesystemSlice := func(old []v2_1.Filesystem) []types.Filesystem { + var res []types.Filesystem + for _, x := range old { + res = append(res, types.Filesystem{ + Mount: translateMount(x.Mount), + Name: x.Name, + Path: x.Path, + }) + } + return res + } + translateLinkSlice := func(old []v2_1.Link) []types.Link { + var res []types.Link + for _, x := range old { + res = append(res, types.Link{ + Node: translateNode(x.Node), + LinkEmbedded1: types.LinkEmbedded1{ + Hard: x.Hard, + Target: x.Target, + }, + }) + } + return res + } + translateDeviceSlice := func(old []v2_1.Device) []types.Device { + var res []types.Device + for _, x := range old { + res = append(res, types.Device(x)) + } + return res + } + translateRaidSlice := func(old []v2_1.Raid) []types.Raid { + var res []types.Raid + for _, x := range old { + res = append(res, types.Raid{ + Devices: translateDeviceSlice(x.Devices), + Level: x.Level, + Name: x.Name, + Spares: x.Spares, + }) + } + return res + } + translateSystemdDropinSlice := func(old []v2_1.Dropin) []types.Dropin { + var res []types.Dropin + for _, x := range old { + res = append(res, types.Dropin{ + Contents: x.Contents, + Name: x.Name, + }) + } + return res + } + translateSystemdUnitSlice := func(old []v2_1.Unit) []types.Unit { + var res []types.Unit + for _, x := range old { + res = append(res, types.Unit{ + Contents: x.Contents, + Dropins: translateSystemdDropinSlice(x.Dropins), + Enable: x.Enable, + Enabled: x.Enabled, + Mask: x.Mask, + Name: x.Name, + }) + } + return res + } + config := types.Config{ + Ignition: types.Ignition{ + Version: types.MaxVersion.String(), + Timeouts: types.Timeouts{ + HTTPResponseHeaders: old.Ignition.Timeouts.HTTPResponseHeaders, + HTTPTotal: old.Ignition.Timeouts.HTTPTotal, + }, + Config: types.IgnitionConfig{ + Replace: translateConfigReference(old.Ignition.Config.Replace), + Append: translateConfigReferenceSlice(old.Ignition.Config.Append), + }, + }, + Networkd: types.Networkd{ + Units: translateNetworkdUnitSlice(old.Networkd.Units), + }, + Passwd: types.Passwd{ + Groups: translatePasswdGroupSlice(old.Passwd.Groups), + Users: translatePasswdUserSlice(old.Passwd.Users), + }, + Storage: types.Storage{ + Directories: translateDirectorySlice(old.Storage.Directories), + Disks: translateDiskSlice(old.Storage.Disks), + Files: translateFileSlice(old.Storage.Files), + Filesystems: translateFilesystemSlice(old.Storage.Filesystems), + Links: translateLinkSlice(old.Storage.Links), + Raid: translateRaidSlice(old.Storage.Raid), + }, + Systemd: types.Systemd{ + Units: translateSystemdUnitSlice(old.Systemd.Units), + }, + } + 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 22b8295f..9e2e65e1 100644 --- a/vendor/github.com/coreos/ignition/config/types/config.go +++ b/vendor/github.com/coreos/ignition/config/types/config.go @@ -25,19 +25,11 @@ import ( var ( MaxVersion = semver.Version{ Major: 2, - Minor: 1, + Minor: 2, PreRelease: "experimental", } ) -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{ diff --git a/vendor/github.com/coreos/ignition/config/types/directory.go b/vendor/github.com/coreos/ignition/config/types/directory.go index fb93be56..16adad05 100644 --- a/vendor/github.com/coreos/ignition/config/types/directory.go +++ b/vendor/github.com/coreos/ignition/config/types/directory.go @@ -1,4 +1,4 @@ -// Copyright 2016 CoreOS, Inc. +// 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. @@ -15,15 +15,16 @@ package types import ( - "path" + "github.com/coreos/ignition/config/validate/report" ) -type Directory Node - -func (d *Directory) Depth() int { - count := 0 - for p := path.Clean(string(d.Path)); p != "/"; count++ { - p = path.Dir(p) +func (d Directory) ValidateMode() report.Report { + r := report.Report{} + if err := validateMode(d.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) } - return count + return r } diff --git a/vendor/github.com/coreos/ignition/config/types/disk.go b/vendor/github.com/coreos/ignition/config/types/disk.go index 275913b4..21273a1c 100644 --- a/vendor/github.com/coreos/ignition/config/types/disk.go +++ b/vendor/github.com/coreos/ignition/config/types/disk.go @@ -20,20 +20,22 @@ import ( "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 { + return report.Report{} } -func (n Disk) Validate() report.Report { - r := report.Report{} +func (n Disk) ValidateDevice() report.Report { if len(n.Device) == 0 { - r.Add(report.Entry{ - Message: "disk device is required", - Kind: report.EntryError, - }) + return report.ReportFromError(fmt.Errorf("disk device is required"), report.EntryError) } + if err := validatePath(string(n.Device)); err != nil { + return report.ReportFromError(err, report.EntryError) + } + return report.Report{} +} + +func (n Disk) ValidatePartitions() report.Report { + r := report.Report{} if n.partitionNumbersCollide() { r.Add(report.Entry{ Message: fmt.Sprintf("disk %q: partition numbers collide", n.Device), @@ -72,7 +74,7 @@ func (n Disk) partitionNumbersCollide() bool { } // end returns the last sector of a partition. -func (p Partition) end() PartitionDimension { +func (p Partition) end() int { if p.Size == 0 { // a size of 0 means "fill available", just return the start as the end for those. return p.Start diff --git a/vendor/github.com/coreos/ignition/config/types/file.go b/vendor/github.com/coreos/ignition/config/types/file.go index 1fbaf4e7..866fc054 100644 --- a/vendor/github.com/coreos/ignition/config/types/file.go +++ b/vendor/github.com/coreos/ignition/config/types/file.go @@ -14,14 +14,49 @@ package types -// File represents regular files -type File struct { - Node - Contents FileContents `json:"contents,omitempty"` +import ( + "errors" + "fmt" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrCompressionInvalid = errors.New("invalid compression method") +) + +func (f File) ValidateMode() report.Report { + r := report.Report{} + if err := validateMode(f.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r } -type FileContents struct { - Compression Compression `json:"compression,omitempty"` - Source Url `json:"source,omitempty"` - Verification Verification `json:"verification,omitempty"` +func (fc FileContents) ValidateCompression() report.Report { + r := report.Report{} + switch fc.Compression { + case "", "gzip": + default: + r.Add(report.Entry{ + Message: ErrCompressionInvalid.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (fc FileContents) ValidateSource() report.Report { + r := report.Report{} + err := validateURL(fc.Source) + if err != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("invalid url %q: %v", fc.Source, err), + Kind: report.EntryError, + }) + } + return r } diff --git a/vendor/github.com/coreos/ignition/config/types/filesystem.go b/vendor/github.com/coreos/ignition/config/types/filesystem.go index bbd0c75b..3c5a47d5 100644 --- a/vendor/github.com/coreos/ignition/config/types/filesystem.go +++ b/vendor/github.com/coreos/ignition/config/types/filesystem.go @@ -16,52 +16,145 @@ package types import ( "errors" + "fmt" "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") + 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") + ErrUsedCreateAndMountOpts = errors.New("cannot use both create object and mount-level options field") + ErrUsedCreateAndWipeFilesystem = errors.New("cannot use both create object and wipeFilesystem field") + ErrWarningCreateDeprecated = errors.New("the create object has been deprecated in favor of mount-level options") + ErrExt4LabelTooLong = errors.New("filesystem labels cannot be longer than 16 characters when using ext4") + ErrBtrfsLabelTooLong = errors.New("filesystem labels cannot be longer than 256 characters when using btrfs") + ErrXfsLabelTooLong = errors.New("filesystem labels cannot be longer than 12 characters when using xfs") + ErrSwapLabelTooLong = errors.New("filesystem labels cannot be longer than 15 characters when using swap") + ErrVfatLabelTooLong = errors.New("filesystem labels cannot be longer than 11 characters when using vfat") ) -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 { + r := report.Report{} if f.Mount == nil && f.Path == nil { - return report.ReportFromError(ErrFilesystemNoMountPath, report.EntryError) + r.Add(report.Entry{ + Message: ErrFilesystemNoMountPath.Error(), + Kind: report.EntryError, + }) } - if f.Mount != nil && f.Path != nil { - return report.ReportFromError(ErrFilesystemMountAndPath, report.EntryError) + if f.Mount != nil { + if f.Path != nil { + r.Add(report.Entry{ + Message: ErrFilesystemMountAndPath.Error(), + Kind: report.EntryError, + }) + } + if f.Mount.Create != nil { + if f.Mount.WipeFilesystem { + r.Add(report.Entry{ + Message: ErrUsedCreateAndWipeFilesystem.Error(), + Kind: report.EntryError, + }) + } + if len(f.Mount.Options) > 0 { + r.Add(report.Entry{ + Message: ErrUsedCreateAndMountOpts.Error(), + Kind: report.EntryError, + }) + } + r.Add(report.Entry{ + Message: ErrWarningCreateDeprecated.Error(), + Kind: report.EntryWarning, + }) + } } - return report.Report{} + return r } -type FilesystemFormat string +func (f Filesystem) ValidatePath() report.Report { + r := report.Report{} + if f.Path != nil && validatePath(*f.Path) != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("filesystem %q: path not absolute", f.Name), + Kind: report.EntryError, + }) + } + return r +} -func (f FilesystemFormat) Validate() report.Report { - switch f { - case "ext4", "btrfs", "xfs": - return report.Report{} +func (m Mount) Validate() report.Report { + r := report.Report{} + switch m.Format { + case "ext4", "btrfs", "xfs", "swap", "vfat": default: - return report.ReportFromError(ErrFilesystemInvalidFormat, report.EntryError) + r.Add(report.Entry{ + Message: ErrFilesystemInvalidFormat.Error(), + Kind: report.EntryError, + }) } + return r } -type MkfsOptions []string +func (m Mount) ValidateDevice() report.Report { + r := report.Report{} + if err := validatePath(m.Device); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (m Mount) ValidateLabel() report.Report { + r := report.Report{} + if m.Label == nil { + return r + } + switch m.Format { + case "ext4": + if len(*m.Label) > 16 { + // source: man mkfs.ext4 + r.Add(report.Entry{ + Message: ErrExt4LabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "btrfs": + if len(*m.Label) > 256 { + // source: man mkfs.btrfs + r.Add(report.Entry{ + Message: ErrBtrfsLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "xfs": + if len(*m.Label) > 12 { + // source: man mkfs.xfs + r.Add(report.Entry{ + Message: ErrXfsLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "swap": + // mkswap's man page does not state a limit on label size, but through + // experimentation it appears that mkswap will truncate long labels to + // 15 characters, so let's enforce that. + if len(*m.Label) > 15 { + r.Add(report.Entry{ + Message: ErrSwapLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "vfat": + if len(*m.Label) > 11 { + // source: man mkfs.fat + r.Add(report.Entry{ + Message: ErrVfatLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/types/ignition.go b/vendor/github.com/coreos/ignition/config/types/ignition.go index 29a3ea53..661b898d 100644 --- a/vendor/github.com/coreos/ignition/config/types/ignition.go +++ b/vendor/github.com/coreos/ignition/config/types/ignition.go @@ -15,7 +15,6 @@ package types import ( - "encoding/json" "errors" "github.com/coreos/go-semver/semver" @@ -24,46 +23,36 @@ import ( ) var ( - ErrOldVersion = errors.New("incorrect config version (too old)") - ErrNewVersion = errors.New("incorrect config version (too new)") + ErrOldVersion = errors.New("incorrect config version (too old)") + ErrNewVersion = errors.New("incorrect config version (too new)") + ErrInvalidVersion = errors.New("invalid config version (couldn't parse)") ) -type Ignition struct { - Version IgnitionVersion `json:"version,omitempty" merge:"old"` - Config IgnitionConfig `json:"config,omitempty" merge:"new"` - Timeouts Timeouts `json:"timeouts,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 +func (c ConfigReference) ValidateSource() report.Report { + r := report.Report{} + err := validateURL(c.Source) + if err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) } - *v = IgnitionVersion(tv) - return nil + return r } -func (v IgnitionVersion) MarshalJSON() ([]byte, error) { - return semver.Version(v).MarshalJSON() +func (v Ignition) Semver() (*semver.Version, error) { + return semver.NewVersion(v.Version) } -func (v IgnitionVersion) Validate() report.Report { - if MaxVersion.Major > v.Major { +func (v Ignition) Validate() report.Report { + tv, err := v.Semver() + if err != nil { + return report.ReportFromError(ErrInvalidVersion, report.EntryError) + } + if MaxVersion.Major > tv.Major { return report.ReportFromError(ErrOldVersion, report.EntryError) } - if MaxVersion.LessThan(semver.Version(v)) { + if MaxVersion.LessThan(*tv) { return report.ReportFromError(ErrNewVersion, report.EntryError) } return report.Report{} diff --git a/vendor/github.com/coreos/ignition/config/types/compression.go b/vendor/github.com/coreos/ignition/config/types/link.go similarity index 66% rename from vendor/github.com/coreos/ignition/config/types/compression.go rename to vendor/github.com/coreos/ignition/config/types/link.go index 65c3e25c..1b7794c0 100644 --- a/vendor/github.com/coreos/ignition/config/types/compression.go +++ b/vendor/github.com/coreos/ignition/config/types/link.go @@ -1,4 +1,4 @@ -// Copyright 2016 CoreOS, Inc. +// 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. @@ -15,22 +15,21 @@ package types import ( - "errors" + "fmt" "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) +func (s Link) Validate() report.Report { + r := report.Report{} + if !s.Hard { + err := validatePath(s.Target) + if err != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("problem with target path %q: %v", s.Target, err), + Kind: report.EntryError, + }) + } } - return report.Report{} + return r } diff --git a/vendor/github.com/coreos/ignition/config/types/networkd.go b/vendor/github.com/coreos/ignition/config/types/mode.go similarity index 72% rename from vendor/github.com/coreos/ignition/config/types/networkd.go rename to vendor/github.com/coreos/ignition/config/types/mode.go index 470c7211..09608b51 100644 --- a/vendor/github.com/coreos/ignition/config/types/networkd.go +++ b/vendor/github.com/coreos/ignition/config/types/mode.go @@ -1,4 +1,4 @@ -// Copyright 2016 CoreOS, Inc. +// 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. @@ -14,6 +14,17 @@ package types -type Networkd struct { - Units []NetworkdUnit `json:"units,omitempty"` +import ( + "errors" +) + +var ( + ErrFileIllegalMode = errors.New("illegal file mode") +) + +func validateMode(m int) error { + if m < 0 || m > 07777 { + return ErrFileIllegalMode + } + return nil } diff --git a/vendor/github.com/coreos/ignition/config/types/node.go b/vendor/github.com/coreos/ignition/config/types/node.go index f69722ad..5c117f06 100644 --- a/vendor/github.com/coreos/ignition/config/types/node.go +++ b/vendor/github.com/coreos/ignition/config/types/node.go @@ -16,45 +16,63 @@ package types import ( "errors" - "os" + "path/filepath" "github.com/coreos/ignition/config/validate/report" ) var ( - ErrNoFilesystem = errors.New("no filesystem specified") - ErrFileIllegalMode = errors.New("illegal file mode") + ErrNoFilesystem = errors.New("no filesystem specified") + ErrBothIDAndNameSet = errors.New("cannot set both id and name") ) -// 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 { +func (n Node) ValidateFilesystem() report.Report { + r := report.Report{} if n.Filesystem == "" { - return report.ReportFromError(ErrNoFilesystem, report.EntryError) + r.Add(report.Entry{ + Message: ErrNoFilesystem.Error(), + Kind: report.EntryError, + }) } - return report.Report{} + return r } -type NodeMode os.FileMode - -func (m NodeMode) Validate() report.Report { - if (m &^ 07777) != 0 { - return report.ReportFromError(ErrFileIllegalMode, report.EntryError) +func (n Node) ValidatePath() report.Report { + r := report.Report{} + if err := validatePath(n.Path); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) } - return report.Report{} + return r +} + +func (n Node) Depth() int { + count := 0 + for p := filepath.Clean(string(n.Path)); p != "/"; count++ { + p = filepath.Dir(p) + } + return count +} + +func (nu NodeUser) Validate() report.Report { + r := report.Report{} + if nu.ID != nil && nu.Name != "" { + r.Add(report.Entry{ + Message: ErrBothIDAndNameSet.Error(), + Kind: report.EntryError, + }) + } + return r +} +func (ng NodeGroup) Validate() report.Report { + r := report.Report{} + if ng.ID != nil && ng.Name != "" { + r.Add(report.Entry{ + Message: ErrBothIDAndNameSet.Error(), + Kind: report.EntryError, + }) + } + return r } diff --git a/vendor/github.com/coreos/ignition/config/types/partition.go b/vendor/github.com/coreos/ignition/config/types/partition.go index 9ed03c32..4473b667 100644 --- a/vendor/github.com/coreos/ignition/config/types/partition.go +++ b/vendor/github.com/coreos/ignition/config/types/partition.go @@ -15,45 +15,59 @@ package types import ( + "errors" "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"` -} +const ( + guidRegexStr = "^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$" +) -type PartitionLabel string +var ( + ErrLabelTooLong = errors.New("partition labels may not exceed 36 characters") + ErrDoesntMatchGUIDRegex = errors.New("doesn't match the form \"01234567-89AB-CDEF-EDCB-A98765432101\"") +) -func (n PartitionLabel) Validate() report.Report { +func (p Partition) ValidateLabel() report.Report { + r := 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) + if len(p.Label) > 36 { + r.Add(report.Entry{ + Message: ErrLabelTooLong.Error(), + Kind: report.EntryError, + }) } - return report.Report{} + return r } -type PartitionDimension uint64 +func (p Partition) ValidateTypeGUID() report.Report { + return validateGUID(p.TypeGUID) +} -type PartitionTypeGUID string +func (p Partition) ValidateGUID() report.Report { + return validateGUID(p.GUID) +} -func (d PartitionTypeGUID) Validate() report.Report { - ok, err := regexp.MatchString("^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$", string(d)) +func validateGUID(guid string) report.Report { + r := report.Report{} + ok, err := regexp.MatchString(guidRegexStr, guid) if err != nil { - return report.ReportFromError(fmt.Errorf("error matching type-guid regexp: %v", err), report.EntryError) + r.Add(report.Entry{ + Message: fmt.Sprintf("error matching guid regexp: %v", err), + Kind: report.EntryError, + }) + } else if !ok { + r.Add(report.Entry{ + Message: ErrDoesntMatchGUIDRegex.Error(), + Kind: 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{} + return r } diff --git a/vendor/github.com/coreos/ignition/config/types/passwd.go b/vendor/github.com/coreos/ignition/config/types/passwd.go index 0ffff43b..5f7d9641 100644 --- a/vendor/github.com/coreos/ignition/config/types/passwd.go +++ b/vendor/github.com/coreos/ignition/config/types/passwd.go @@ -1,4 +1,4 @@ -// Copyright 2016 CoreOS, Inc. +// 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. @@ -14,7 +14,69 @@ package types -type Passwd struct { - Users []User `json:"users,omitempty"` - Groups []Group `json:"groups,omitempty"` +import ( + "errors" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrPasswdCreateDeprecated = errors.New("the create object has been deprecated in favor of user-level options") + ErrPasswdCreateAndGecos = errors.New("cannot use both the create object and the user-level gecos field") + ErrPasswdCreateAndGroups = errors.New("cannot use both the create object and the user-level groups field") + ErrPasswdCreateAndHomeDir = errors.New("cannot use both the create object and the user-level homeDir field") + ErrPasswdCreateAndNoCreateHome = errors.New("cannot use both the create object and the user-level noCreateHome field") + ErrPasswdCreateAndNoLogInit = errors.New("cannot use both the create object and the user-level noLogInit field") + ErrPasswdCreateAndNoUserGroup = errors.New("cannot use both the create object and the user-level noUserGroup field") + ErrPasswdCreateAndPrimaryGroup = errors.New("cannot use both the create object and the user-level primaryGroup field") + ErrPasswdCreateAndShell = errors.New("cannot use both the create object and the user-level shell field") + ErrPasswdCreateAndSystem = errors.New("cannot use both the create object and the user-level system field") + ErrPasswdCreateAndUID = errors.New("cannot use both the create object and the user-level uid field") +) + +func (p PasswdUser) Validate() report.Report { + r := report.Report{} + if p.Create != nil { + r.Add(report.Entry{ + Message: ErrPasswdCreateDeprecated.Error(), + Kind: report.EntryWarning, + }) + addErr := func(err error) { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + if p.Gecos != "" { + addErr(ErrPasswdCreateAndGecos) + } + if len(p.Groups) > 0 { + addErr(ErrPasswdCreateAndGroups) + } + if p.HomeDir != "" { + addErr(ErrPasswdCreateAndHomeDir) + } + if p.NoCreateHome { + addErr(ErrPasswdCreateAndNoCreateHome) + } + if p.NoLogInit { + addErr(ErrPasswdCreateAndNoLogInit) + } + if p.NoUserGroup { + addErr(ErrPasswdCreateAndNoUserGroup) + } + if p.PrimaryGroup != "" { + addErr(ErrPasswdCreateAndPrimaryGroup) + } + if p.Shell != "" { + addErr(ErrPasswdCreateAndShell) + } + if p.System { + addErr(ErrPasswdCreateAndSystem) + } + if p.UID != nil { + addErr(ErrPasswdCreateAndUID) + } + } + return r } diff --git a/vendor/github.com/coreos/ignition/config/types/path.go b/vendor/github.com/coreos/ignition/config/types/path.go index 0d07d81f..0bdbdcb0 100644 --- a/vendor/github.com/coreos/ignition/config/types/path.go +++ b/vendor/github.com/coreos/ignition/config/types/path.go @@ -17,23 +17,15 @@ package types 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 -} - -func (p Path) Validate() report.Report { - if !path.IsAbs(string(p)) { - return report.ReportFromError(ErrPathRelative, report.EntryError) +func validatePath(p string) error { + if !path.IsAbs(p) { + return ErrPathRelative } - return report.Report{} + return nil } diff --git a/vendor/github.com/coreos/ignition/config/types/raid.go b/vendor/github.com/coreos/ignition/config/types/raid.go index 4236255d..f43b152d 100644 --- a/vendor/github.com/coreos/ignition/config/types/raid.go +++ b/vendor/github.com/coreos/ignition/config/types/raid.go @@ -20,18 +20,15 @@ import ( "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 { +func (n Raid) ValidateLevel() report.Report { + r := 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) + r.Add(report.Entry{ + Message: fmt.Sprintf("spares unsupported for %q arrays", n.Level), + Kind: report.EntryError, + }) } case "raid1", "1", "mirror": case "raid4", "4": @@ -39,7 +36,23 @@ func (n Raid) Validate() report.Report { case "raid6", "6": case "raid10", "10": default: - return report.ReportFromError(fmt.Errorf("unrecognized raid level: %q", n.Level), report.EntryError) + r.Add(report.Entry{ + Message: fmt.Sprintf("unrecognized raid level: %q", n.Level), + Kind: report.EntryError, + }) } - return report.Report{} + return r +} + +func (n Raid) ValidateDevices() report.Report { + r := report.Report{} + for _, d := range n.Devices { + if err := validatePath(string(d)); err != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("array %q: device path not absolute: %q", n.Name, d), + Kind: report.EntryError, + }) + } + } + return r } diff --git a/vendor/github.com/coreos/ignition/config/types/schema.go b/vendor/github.com/coreos/ignition/config/types/schema.go new file mode 100644 index 00000000..e0caed5e --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/types/schema.go @@ -0,0 +1,221 @@ +package types + +// generated by "schematyper --package=types schema/ignition.json -o config/types/schema.go --root-type=Config" -- DO NOT EDIT + +type Config struct { + Ignition Ignition `json:"ignition"` + Networkd Networkd `json:"networkd,omitempty"` + Passwd Passwd `json:"passwd,omitempty"` + Storage Storage `json:"storage,omitempty"` + Systemd Systemd `json:"systemd,omitempty"` +} + +type ConfigReference struct { + Source string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type Create struct { + Force bool `json:"force,omitempty"` + Options []CreateOption `json:"options,omitempty"` +} + +type CreateOption string + +type Device string + +type Directory struct { + Node + DirectoryEmbedded1 +} + +type DirectoryEmbedded1 struct { + Mode int `json:"mode,omitempty"` +} + +type Disk struct { + Device string `json:"device,omitempty"` + Partitions []Partition `json:"partitions,omitempty"` + WipeTable bool `json:"wipeTable,omitempty"` +} + +type Dropin struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name,omitempty"` +} + +type File struct { + Node + FileEmbedded1 +} + +type FileContents struct { + Compression string `json:"compression,omitempty"` + Source string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type FileEmbedded1 struct { + Contents FileContents `json:"contents,omitempty"` + Mode int `json:"mode,omitempty"` +} + +type Filesystem struct { + Mount *Mount `json:"mount,omitempty"` + Name string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` +} + +type Ignition struct { + Config IgnitionConfig `json:"config,omitempty"` + Timeouts Timeouts `json:"timeouts,omitempty"` + Version string `json:"version,omitempty"` +} + +type IgnitionConfig struct { + Append []ConfigReference `json:"append,omitempty"` + Replace *ConfigReference `json:"replace,omitempty"` +} + +type Link struct { + Node + LinkEmbedded1 +} + +type LinkEmbedded1 struct { + Hard bool `json:"hard,omitempty"` + Target string `json:"target,omitempty"` +} + +type Mount struct { + Create *Create `json:"create,omitempty"` + Device string `json:"device,omitempty"` + Format string `json:"format,omitempty"` + Label *string `json:"label,omitempty"` + Options []MountOption `json:"options,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeFilesystem bool `json:"wipeFilesystem,omitempty"` +} + +type MountOption string + +type Networkd struct { + Units []Networkdunit `json:"units,omitempty"` +} + +type Networkdunit struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name,omitempty"` +} + +type Node struct { + Filesystem string `json:"filesystem,omitempty"` + Group NodeGroup `json:"group,omitempty"` + Path string `json:"path,omitempty"` + User NodeUser `json:"user,omitempty"` +} + +type NodeGroup struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type NodeUser struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type Partition struct { + GUID string `json:"guid,omitempty"` + Label string `json:"label,omitempty"` + Number int `json:"number,omitempty"` + Size int `json:"size,omitempty"` + Start int `json:"start,omitempty"` + TypeGUID string `json:"typeGuid,omitempty"` +} + +type Passwd struct { + Groups []PasswdGroup `json:"groups,omitempty"` + Users []PasswdUser `json:"users,omitempty"` +} + +type PasswdGroup struct { + Gid *int `json:"gid,omitempty"` + Name string `json:"name,omitempty"` + PasswordHash string `json:"passwordHash,omitempty"` + System bool `json:"system,omitempty"` +} + +type PasswdUser struct { + Create *Usercreate `json:"create,omitempty"` + Gecos string `json:"gecos,omitempty"` + Groups []PasswdUserGroup `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + Name string `json:"name,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PasswordHash *string `json:"passwordHash,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type PasswdUserGroup string + +type Raid struct { + Devices []Device `json:"devices,omitempty"` + Level string `json:"level,omitempty"` + Name string `json:"name,omitempty"` + Spares int `json:"spares,omitempty"` +} + +type SSHAuthorizedKey string + +type Storage struct { + Directories []Directory `json:"directories,omitempty"` + Disks []Disk `json:"disks,omitempty"` + Files []File `json:"files,omitempty"` + Filesystems []Filesystem `json:"filesystems,omitempty"` + Links []Link `json:"links,omitempty"` + Raid []Raid `json:"raid,omitempty"` +} + +type Systemd struct { + Units []Unit `json:"units,omitempty"` +} + +type Timeouts struct { + HTTPResponseHeaders *int `json:"httpResponseHeaders,omitempty"` + HTTPTotal *int `json:"httpTotal,omitempty"` +} + +type Unit struct { + Contents string `json:"contents,omitempty"` + Dropins []Dropin `json:"dropins,omitempty"` + Enable bool `json:"enable,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Mask bool `json:"mask,omitempty"` + Name string `json:"name,omitempty"` +} + +type Usercreate struct { + Gecos string `json:"gecos,omitempty"` + Groups []UsercreateGroup `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type UsercreateGroup string + +type Verification struct { + Hash *string `json:"hash,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/config/types/unit.go b/vendor/github.com/coreos/ignition/config/types/unit.go index 020d10a5..3d3fc8db 100644 --- a/vendor/github.com/coreos/ignition/config/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/types/unit.go @@ -25,79 +25,77 @@ import ( "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"` -} +var ( + ErrInvalidSystemdExt = errors.New("invalid systemd unit extension") + ErrInvalidNetworkdExt = errors.New("invalid networkd unit extension") +) -func (u SystemdUnit) Validate() report.Report { +func (u Unit) ValidateContents() report.Report { + r := report.Report{} if err := validateUnitContent(u.Contents); err != nil { - return report.ReportFromError(err, report.EntryError) + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) } - - return report.Report{} + return r } -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)) { +func (u Unit) ValidateName() report.Report { + r := report.Report{} + switch path.Ext(u.Name) { 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) + r.Add(report.Entry{ + Message: ErrInvalidSystemdExt.Error(), + Kind: report.EntryError, + }) } + return r } -type SystemdUnitDropInName string +func (d Dropin) Validate() report.Report { + r := report.Report{} -func (n SystemdUnitDropInName) Validate() report.Report { - switch path.Ext(string(n)) { + if err := validateUnitContent(d.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + switch path.Ext(d.Name) { case ".conf": - return report.Report{} default: - return report.ReportFromError(errors.New("invalid systemd unit drop-in extension"), report.EntryError) + r.Add(report.Entry{ + Message: fmt.Sprintf("invalid systemd unit drop-in extension: %q", path.Ext(d.Name)), + Kind: report.EntryError, + }) } + + return r } -type NetworkdUnit struct { - Name NetworkdUnitName `json:"name,omitempty"` - Contents string `json:"contents,omitempty"` -} +func (u Networkdunit) Validate() report.Report { + r := report.Report{} -func (u NetworkdUnit) Validate() report.Report { if err := validateUnitContent(u.Contents); err != nil { - return report.ReportFromError(err, report.EntryError) + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) } - return report.Report{} -} - -type NetworkdUnitName string - -func (n NetworkdUnitName) Validate() report.Report { - switch path.Ext(string(n)) { + switch path.Ext(u.Name) { case ".link", ".netdev", ".network": - return report.Report{} default: - return report.ReportFromError(errors.New("invalid networkd unit extension"), report.EntryError) + r.Add(report.Entry{ + Message: ErrInvalidNetworkdExt.Error(), + Kind: report.EntryError, + }) } + + return r } func validateUnitContent(content string) error { diff --git a/vendor/github.com/coreos/ignition/config/types/url.go b/vendor/github.com/coreos/ignition/config/types/url.go index 8bf0e6ea..f6270c9a 100644 --- a/vendor/github.com/coreos/ignition/config/types/url.go +++ b/vendor/github.com/coreos/ignition/config/types/url.go @@ -15,11 +15,9 @@ package types import ( - "encoding/json" "errors" "net/url" - "github.com/coreos/ignition/config/validate/report" "github.com/vincent-petithory/dataurl" ) @@ -27,46 +25,25 @@ 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 +func validateURL(s string) error { + // Empty url is valid, indicates an empty file + if s == "" { + return nil } - - pu, err := url.Parse(tu) + u, err := url.Parse(s) 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{} + switch u.Scheme { + case "http", "https", "oem", "tftp", "s3": + return nil case "data": - if _, err := dataurl.DecodeString(u.String()); err != nil { - return report.ReportFromError(err, report.EntryError) + if _, err := dataurl.DecodeString(s); err != nil { + return err } - return report.Report{} + return nil default: - return report.ReportFromError(ErrInvalidScheme, report.EntryError) + return ErrInvalidScheme } } diff --git a/vendor/github.com/coreos/ignition/config/types/user.go b/vendor/github.com/coreos/ignition/config/types/user.go deleted file mode 100644 index f6653e27..00000000 --- a/vendor/github.com/coreos/ignition/config/types/user.go +++ /dev/null @@ -1,35 +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 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/types/verification.go b/vendor/github.com/coreos/ignition/config/types/verification.go index b7cef403..d2158b80 100644 --- a/vendor/github.com/coreos/ignition/config/types/verification.go +++ b/vendor/github.com/coreos/ignition/config/types/verification.go @@ -14,6 +14,70 @@ package types -type Verification struct { - Hash *Hash `json:"hash,omitempty"` +import ( + "crypto" + "encoding/hex" + "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") +) + +// HashParts will return the sum and function (in that order) of the hash stored +// in this Verification, or an error if there is an issue during parsing. +func (v Verification) HashParts() (string, string, error) { + if v.Hash == nil { + // The hash can be nil + return "", "", nil + } + parts := strings.SplitN(*v.Hash, "-", 2) + if len(parts) != 2 { + return "", "", ErrHashMalformed + } + + return parts[0], parts[1], nil +} + +func (v Verification) Validate() report.Report { + r := report.Report{} + + if v.Hash == nil { + // The hash can be nil + return r + } + + function, sum, err := v.HashParts() + if err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + return r + } + var hash crypto.Hash + switch function { + case "sha512": + hash = crypto.SHA512 + default: + r.Add(report.Entry{ + Message: ErrHashUnrecognized.Error(), + Kind: report.EntryError, + }) + return r + } + + if len(sum) != hex.EncodedLen(hash.Size()) { + r.Add(report.Entry{ + Message: ErrHashWrongSize.Error(), + Kind: report.EntryError, + }) + } + + return r } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/config.go b/vendor/github.com/coreos/ignition/config/v2_0/config.go index 20b2fdbf..d85d6d4b 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/config.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/config.go @@ -105,7 +105,7 @@ func Parse(rawConfig []byte) (types.Config, report.Report, error) { }) r.Merge(validate.ValidateWithoutSource(configValue)) } else { - r.Merge(validate.Validate(configValue, astjson.FromJsonRoot(ast), bytes.NewReader(rawConfig))) + r.Merge(validate.Validate(configValue, astjson.FromJsonRoot(ast), bytes.NewReader(rawConfig), true)) } if r.IsFatal() { 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 index 77d11d3d..5d0f682d 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/hash.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/hash.go @@ -56,6 +56,11 @@ func (h Hash) MarshalJSON() ([]byte, error) { return []byte(`"` + h.Function + "-" + h.Sum + `"`), nil } +func (h Hash) String() string { + bytes, _ := h.MarshalJSON() + return string(bytes) +} + func (h Hash) Validate() report.Report { var hash crypto.Hash switch h.Function { diff --git a/vendor/github.com/coreos/ignition/config/v2_1/append.go b/vendor/github.com/coreos/ignition/config/v2_1/append.go new file mode 100644 index 00000000..f2b0d001 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/append.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 v2_1 + +import ( + "reflect" + + "github.com/coreos/ignition/config/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. Some individual +// struct fields have alternate merge strategies, determined by the field name. +// Currently these fields are "ignition.version", which uses the old value, and +// "ignition.config" which uses the new value. +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).Name { + case "Version": + vfRes.Set(vfOld) + continue + case "Config": + 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_1/cloudinit.go b/vendor/github.com/coreos/ignition/config/v2_1/cloudinit.go new file mode 100644 index 00000000..a019320f --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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_1 + +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_1/config.go b/vendor/github.com/coreos/ignition/config/v2_1/config.go new file mode 100644 index 00000000..0b4a2ee5 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/config.go @@ -0,0 +1,118 @@ +// 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_1 + +import ( + "bytes" + "errors" + "reflect" + + "github.com/coreos/ignition/config/v2_1/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") +) + +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.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), true)) + } + + 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_1/types/config.go b/vendor/github.com/coreos/ignition/config/v2_1/types/config.go new file mode 100644 index 00000000..842040ba --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/config.go @@ -0,0 +1,79 @@ +// 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: 1, + } +) + +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/types/group.go b/vendor/github.com/coreos/ignition/config/v2_1/types/directory.go similarity index 65% rename from vendor/github.com/coreos/ignition/config/types/group.go rename to vendor/github.com/coreos/ignition/config/v2_1/types/directory.go index 27e51048..16adad05 100644 --- a/vendor/github.com/coreos/ignition/config/types/group.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/directory.go @@ -1,4 +1,4 @@ -// Copyright 2016 CoreOS, Inc. +// 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. @@ -14,9 +14,17 @@ package types -type Group struct { - Name string `json:"name,omitempty"` - Gid *uint `json:"gid,omitempty"` - PasswordHash string `json:"passwordHash,omitempty"` - System bool `json:"system,omitempty"` +import ( + "github.com/coreos/ignition/config/validate/report" +) + +func (d Directory) ValidateMode() report.Report { + r := report.Report{} + if err := validateMode(d.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r } diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_1/types/disk.go new file mode 100644 index 00000000..21273a1c --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/disk.go @@ -0,0 +1,126 @@ +// 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" +) + +func (n Disk) Validate() report.Report { + return report.Report{} +} + +func (n Disk) ValidateDevice() report.Report { + if len(n.Device) == 0 { + return report.ReportFromError(fmt.Errorf("disk device is required"), report.EntryError) + } + if err := validatePath(string(n.Device)); err != nil { + return report.ReportFromError(err, report.EntryError) + } + return report.Report{} +} + +func (n Disk) ValidatePartitions() report.Report { + r := report.Report{} + 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() int { + 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_1/types/file.go b/vendor/github.com/coreos/ignition/config/v2_1/types/file.go new file mode 100644 index 00000000..866fc054 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/file.go @@ -0,0 +1,62 @@ +// 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/ignition/config/validate/report" +) + +var ( + ErrCompressionInvalid = errors.New("invalid compression method") +) + +func (f File) ValidateMode() report.Report { + r := report.Report{} + if err := validateMode(f.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (fc FileContents) ValidateCompression() report.Report { + r := report.Report{} + switch fc.Compression { + case "", "gzip": + default: + r.Add(report.Entry{ + Message: ErrCompressionInvalid.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (fc FileContents) ValidateSource() report.Report { + r := report.Report{} + err := validateURL(fc.Source) + if err != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("invalid url %q: %v", fc.Source, err), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_1/types/filesystem.go new file mode 100644 index 00000000..3c5a47d5 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/filesystem.go @@ -0,0 +1,160 @@ +// 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/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") + ErrUsedCreateAndMountOpts = errors.New("cannot use both create object and mount-level options field") + ErrUsedCreateAndWipeFilesystem = errors.New("cannot use both create object and wipeFilesystem field") + ErrWarningCreateDeprecated = errors.New("the create object has been deprecated in favor of mount-level options") + ErrExt4LabelTooLong = errors.New("filesystem labels cannot be longer than 16 characters when using ext4") + ErrBtrfsLabelTooLong = errors.New("filesystem labels cannot be longer than 256 characters when using btrfs") + ErrXfsLabelTooLong = errors.New("filesystem labels cannot be longer than 12 characters when using xfs") + ErrSwapLabelTooLong = errors.New("filesystem labels cannot be longer than 15 characters when using swap") + ErrVfatLabelTooLong = errors.New("filesystem labels cannot be longer than 11 characters when using vfat") +) + +func (f Filesystem) Validate() report.Report { + r := report.Report{} + if f.Mount == nil && f.Path == nil { + r.Add(report.Entry{ + Message: ErrFilesystemNoMountPath.Error(), + Kind: report.EntryError, + }) + } + if f.Mount != nil { + if f.Path != nil { + r.Add(report.Entry{ + Message: ErrFilesystemMountAndPath.Error(), + Kind: report.EntryError, + }) + } + if f.Mount.Create != nil { + if f.Mount.WipeFilesystem { + r.Add(report.Entry{ + Message: ErrUsedCreateAndWipeFilesystem.Error(), + Kind: report.EntryError, + }) + } + if len(f.Mount.Options) > 0 { + r.Add(report.Entry{ + Message: ErrUsedCreateAndMountOpts.Error(), + Kind: report.EntryError, + }) + } + r.Add(report.Entry{ + Message: ErrWarningCreateDeprecated.Error(), + Kind: report.EntryWarning, + }) + } + } + return r +} + +func (f Filesystem) ValidatePath() report.Report { + r := report.Report{} + if f.Path != nil && validatePath(*f.Path) != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("filesystem %q: path not absolute", f.Name), + Kind: report.EntryError, + }) + } + return r +} + +func (m Mount) Validate() report.Report { + r := report.Report{} + switch m.Format { + case "ext4", "btrfs", "xfs", "swap", "vfat": + default: + r.Add(report.Entry{ + Message: ErrFilesystemInvalidFormat.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (m Mount) ValidateDevice() report.Report { + r := report.Report{} + if err := validatePath(m.Device); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (m Mount) ValidateLabel() report.Report { + r := report.Report{} + if m.Label == nil { + return r + } + switch m.Format { + case "ext4": + if len(*m.Label) > 16 { + // source: man mkfs.ext4 + r.Add(report.Entry{ + Message: ErrExt4LabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "btrfs": + if len(*m.Label) > 256 { + // source: man mkfs.btrfs + r.Add(report.Entry{ + Message: ErrBtrfsLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "xfs": + if len(*m.Label) > 12 { + // source: man mkfs.xfs + r.Add(report.Entry{ + Message: ErrXfsLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "swap": + // mkswap's man page does not state a limit on label size, but through + // experimentation it appears that mkswap will truncate long labels to + // 15 characters, so let's enforce that. + if len(*m.Label) > 15 { + r.Add(report.Entry{ + Message: ErrSwapLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "vfat": + if len(*m.Label) > 11 { + // source: man mkfs.fat + r.Add(report.Entry{ + Message: ErrVfatLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_1/types/ignition.go new file mode 100644 index 00000000..661b898d --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/ignition.go @@ -0,0 +1,59 @@ +// 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 ( + "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)") + ErrInvalidVersion = errors.New("invalid config version (couldn't parse)") +) + +func (c ConfigReference) ValidateSource() report.Report { + r := report.Report{} + err := validateURL(c.Source) + if err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (v Ignition) Semver() (*semver.Version, error) { + return semver.NewVersion(v.Version) +} + +func (v Ignition) Validate() report.Report { + tv, err := v.Semver() + if err != nil { + return report.ReportFromError(ErrInvalidVersion, report.EntryError) + } + if MaxVersion.Major > tv.Major { + return report.ReportFromError(ErrOldVersion, report.EntryError) + } + if MaxVersion.LessThan(*tv) { + return report.ReportFromError(ErrNewVersion, report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/types/storage.go b/vendor/github.com/coreos/ignition/config/v2_1/types/link.go similarity index 59% rename from vendor/github.com/coreos/ignition/config/types/storage.go rename to vendor/github.com/coreos/ignition/config/v2_1/types/link.go index 79e4d0fd..1b7794c0 100644 --- a/vendor/github.com/coreos/ignition/config/types/storage.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/link.go @@ -1,4 +1,4 @@ -// Copyright 2016 CoreOS, Inc. +// 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. @@ -14,10 +14,22 @@ 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"` - Directories []Directory `json:"directories,omitempty"` +import ( + "fmt" + + "github.com/coreos/ignition/config/validate/report" +) + +func (s Link) Validate() report.Report { + r := report.Report{} + if !s.Hard { + err := validatePath(s.Target) + if err != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("problem with target path %q: %v", s.Target, err), + Kind: report.EntryError, + }) + } + } + return r } diff --git a/vendor/github.com/coreos/ignition/config/types/systemd.go b/vendor/github.com/coreos/ignition/config/v2_1/types/mode.go similarity index 72% rename from vendor/github.com/coreos/ignition/config/types/systemd.go rename to vendor/github.com/coreos/ignition/config/v2_1/types/mode.go index 97194b91..09608b51 100644 --- a/vendor/github.com/coreos/ignition/config/types/systemd.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/mode.go @@ -1,4 +1,4 @@ -// Copyright 2016 CoreOS, Inc. +// 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. @@ -14,6 +14,17 @@ package types -type Systemd struct { - Units []SystemdUnit `json:"units,omitempty"` +import ( + "errors" +) + +var ( + ErrFileIllegalMode = errors.New("illegal file mode") +) + +func validateMode(m int) error { + if m < 0 || m > 07777 { + return ErrFileIllegalMode + } + return nil } diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/node.go b/vendor/github.com/coreos/ignition/config/v2_1/types/node.go new file mode 100644 index 00000000..5c117f06 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/node.go @@ -0,0 +1,78 @@ +// 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" + "path/filepath" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrNoFilesystem = errors.New("no filesystem specified") + ErrBothIDAndNameSet = errors.New("cannot set both id and name") +) + +func (n Node) ValidateFilesystem() report.Report { + r := report.Report{} + if n.Filesystem == "" { + r.Add(report.Entry{ + Message: ErrNoFilesystem.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (n Node) ValidatePath() report.Report { + r := report.Report{} + if err := validatePath(n.Path); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (n Node) Depth() int { + count := 0 + for p := filepath.Clean(string(n.Path)); p != "/"; count++ { + p = filepath.Dir(p) + } + return count +} + +func (nu NodeUser) Validate() report.Report { + r := report.Report{} + if nu.ID != nil && nu.Name != "" { + r.Add(report.Entry{ + Message: ErrBothIDAndNameSet.Error(), + Kind: report.EntryError, + }) + } + return r +} +func (ng NodeGroup) Validate() report.Report { + r := report.Report{} + if ng.ID != nil && ng.Name != "" { + r.Add(report.Entry{ + Message: ErrBothIDAndNameSet.Error(), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_1/types/partition.go new file mode 100644 index 00000000..4473b667 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/partition.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 ( + "errors" + "fmt" + "regexp" + + "github.com/coreos/ignition/config/validate/report" +) + +const ( + guidRegexStr = "^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$" +) + +var ( + ErrLabelTooLong = errors.New("partition labels may not exceed 36 characters") + ErrDoesntMatchGUIDRegex = errors.New("doesn't match the form \"01234567-89AB-CDEF-EDCB-A98765432101\"") +) + +func (p Partition) ValidateLabel() report.Report { + r := 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(p.Label) > 36 { + r.Add(report.Entry{ + Message: ErrLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (p Partition) ValidateTypeGUID() report.Report { + return validateGUID(p.TypeGUID) +} + +func (p Partition) ValidateGUID() report.Report { + return validateGUID(p.GUID) +} + +func validateGUID(guid string) report.Report { + r := report.Report{} + ok, err := regexp.MatchString(guidRegexStr, guid) + if err != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("error matching guid regexp: %v", err), + Kind: report.EntryError, + }) + } else if !ok { + r.Add(report.Entry{ + Message: ErrDoesntMatchGUIDRegex.Error(), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_1/types/passwd.go new file mode 100644 index 00000000..5f7d9641 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/passwd.go @@ -0,0 +1,82 @@ +// 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" + + "github.com/coreos/ignition/config/validate/report" +) + +var ( + ErrPasswdCreateDeprecated = errors.New("the create object has been deprecated in favor of user-level options") + ErrPasswdCreateAndGecos = errors.New("cannot use both the create object and the user-level gecos field") + ErrPasswdCreateAndGroups = errors.New("cannot use both the create object and the user-level groups field") + ErrPasswdCreateAndHomeDir = errors.New("cannot use both the create object and the user-level homeDir field") + ErrPasswdCreateAndNoCreateHome = errors.New("cannot use both the create object and the user-level noCreateHome field") + ErrPasswdCreateAndNoLogInit = errors.New("cannot use both the create object and the user-level noLogInit field") + ErrPasswdCreateAndNoUserGroup = errors.New("cannot use both the create object and the user-level noUserGroup field") + ErrPasswdCreateAndPrimaryGroup = errors.New("cannot use both the create object and the user-level primaryGroup field") + ErrPasswdCreateAndShell = errors.New("cannot use both the create object and the user-level shell field") + ErrPasswdCreateAndSystem = errors.New("cannot use both the create object and the user-level system field") + ErrPasswdCreateAndUID = errors.New("cannot use both the create object and the user-level uid field") +) + +func (p PasswdUser) Validate() report.Report { + r := report.Report{} + if p.Create != nil { + r.Add(report.Entry{ + Message: ErrPasswdCreateDeprecated.Error(), + Kind: report.EntryWarning, + }) + addErr := func(err error) { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + if p.Gecos != "" { + addErr(ErrPasswdCreateAndGecos) + } + if len(p.Groups) > 0 { + addErr(ErrPasswdCreateAndGroups) + } + if p.HomeDir != "" { + addErr(ErrPasswdCreateAndHomeDir) + } + if p.NoCreateHome { + addErr(ErrPasswdCreateAndNoCreateHome) + } + if p.NoLogInit { + addErr(ErrPasswdCreateAndNoLogInit) + } + if p.NoUserGroup { + addErr(ErrPasswdCreateAndNoUserGroup) + } + if p.PrimaryGroup != "" { + addErr(ErrPasswdCreateAndPrimaryGroup) + } + if p.Shell != "" { + addErr(ErrPasswdCreateAndShell) + } + if p.System { + addErr(ErrPasswdCreateAndSystem) + } + if p.UID != nil { + addErr(ErrPasswdCreateAndUID) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/types/timeouts.go b/vendor/github.com/coreos/ignition/config/v2_1/types/path.go similarity index 76% rename from vendor/github.com/coreos/ignition/config/types/timeouts.go rename to vendor/github.com/coreos/ignition/config/v2_1/types/path.go index 77efaf65..0bdbdcb0 100644 --- a/vendor/github.com/coreos/ignition/config/types/timeouts.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/path.go @@ -14,7 +14,18 @@ package types -type Timeouts struct { - HttpResponseHeaders *int `json:"httpResponseHeaders,omitempty"` - HttpTotal *int `json:"httpTotal,omitempty"` +import ( + "errors" + "path" +) + +var ( + ErrPathRelative = errors.New("path not absolute") +) + +func validatePath(p string) error { + if !path.IsAbs(p) { + return ErrPathRelative + } + return nil } diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_1/types/raid.go new file mode 100644 index 00000000..f43b152d --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/raid.go @@ -0,0 +1,58 @@ +// 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" +) + +func (n Raid) ValidateLevel() report.Report { + r := report.Report{} + switch n.Level { + case "linear", "raid0", "0", "stripe": + if n.Spares != 0 { + r.Add(report.Entry{ + Message: fmt.Sprintf("spares unsupported for %q arrays", n.Level), + Kind: report.EntryError, + }) + } + case "raid1", "1", "mirror": + case "raid4", "4": + case "raid5", "5": + case "raid6", "6": + case "raid10", "10": + default: + r.Add(report.Entry{ + Message: fmt.Sprintf("unrecognized raid level: %q", n.Level), + Kind: report.EntryError, + }) + } + return r +} + +func (n Raid) ValidateDevices() report.Report { + r := report.Report{} + for _, d := range n.Devices { + if err := validatePath(string(d)); err != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("array %q: device path not absolute: %q", n.Name, d), + Kind: report.EntryError, + }) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/schema.go b/vendor/github.com/coreos/ignition/config/v2_1/types/schema.go new file mode 100644 index 00000000..e0caed5e --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/schema.go @@ -0,0 +1,221 @@ +package types + +// generated by "schematyper --package=types schema/ignition.json -o config/types/schema.go --root-type=Config" -- DO NOT EDIT + +type Config struct { + Ignition Ignition `json:"ignition"` + Networkd Networkd `json:"networkd,omitempty"` + Passwd Passwd `json:"passwd,omitempty"` + Storage Storage `json:"storage,omitempty"` + Systemd Systemd `json:"systemd,omitempty"` +} + +type ConfigReference struct { + Source string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type Create struct { + Force bool `json:"force,omitempty"` + Options []CreateOption `json:"options,omitempty"` +} + +type CreateOption string + +type Device string + +type Directory struct { + Node + DirectoryEmbedded1 +} + +type DirectoryEmbedded1 struct { + Mode int `json:"mode,omitempty"` +} + +type Disk struct { + Device string `json:"device,omitempty"` + Partitions []Partition `json:"partitions,omitempty"` + WipeTable bool `json:"wipeTable,omitempty"` +} + +type Dropin struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name,omitempty"` +} + +type File struct { + Node + FileEmbedded1 +} + +type FileContents struct { + Compression string `json:"compression,omitempty"` + Source string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type FileEmbedded1 struct { + Contents FileContents `json:"contents,omitempty"` + Mode int `json:"mode,omitempty"` +} + +type Filesystem struct { + Mount *Mount `json:"mount,omitempty"` + Name string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` +} + +type Ignition struct { + Config IgnitionConfig `json:"config,omitempty"` + Timeouts Timeouts `json:"timeouts,omitempty"` + Version string `json:"version,omitempty"` +} + +type IgnitionConfig struct { + Append []ConfigReference `json:"append,omitempty"` + Replace *ConfigReference `json:"replace,omitempty"` +} + +type Link struct { + Node + LinkEmbedded1 +} + +type LinkEmbedded1 struct { + Hard bool `json:"hard,omitempty"` + Target string `json:"target,omitempty"` +} + +type Mount struct { + Create *Create `json:"create,omitempty"` + Device string `json:"device,omitempty"` + Format string `json:"format,omitempty"` + Label *string `json:"label,omitempty"` + Options []MountOption `json:"options,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeFilesystem bool `json:"wipeFilesystem,omitempty"` +} + +type MountOption string + +type Networkd struct { + Units []Networkdunit `json:"units,omitempty"` +} + +type Networkdunit struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name,omitempty"` +} + +type Node struct { + Filesystem string `json:"filesystem,omitempty"` + Group NodeGroup `json:"group,omitempty"` + Path string `json:"path,omitempty"` + User NodeUser `json:"user,omitempty"` +} + +type NodeGroup struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type NodeUser struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type Partition struct { + GUID string `json:"guid,omitempty"` + Label string `json:"label,omitempty"` + Number int `json:"number,omitempty"` + Size int `json:"size,omitempty"` + Start int `json:"start,omitempty"` + TypeGUID string `json:"typeGuid,omitempty"` +} + +type Passwd struct { + Groups []PasswdGroup `json:"groups,omitempty"` + Users []PasswdUser `json:"users,omitempty"` +} + +type PasswdGroup struct { + Gid *int `json:"gid,omitempty"` + Name string `json:"name,omitempty"` + PasswordHash string `json:"passwordHash,omitempty"` + System bool `json:"system,omitempty"` +} + +type PasswdUser struct { + Create *Usercreate `json:"create,omitempty"` + Gecos string `json:"gecos,omitempty"` + Groups []PasswdUserGroup `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + Name string `json:"name,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PasswordHash *string `json:"passwordHash,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type PasswdUserGroup string + +type Raid struct { + Devices []Device `json:"devices,omitempty"` + Level string `json:"level,omitempty"` + Name string `json:"name,omitempty"` + Spares int `json:"spares,omitempty"` +} + +type SSHAuthorizedKey string + +type Storage struct { + Directories []Directory `json:"directories,omitempty"` + Disks []Disk `json:"disks,omitempty"` + Files []File `json:"files,omitempty"` + Filesystems []Filesystem `json:"filesystems,omitempty"` + Links []Link `json:"links,omitempty"` + Raid []Raid `json:"raid,omitempty"` +} + +type Systemd struct { + Units []Unit `json:"units,omitempty"` +} + +type Timeouts struct { + HTTPResponseHeaders *int `json:"httpResponseHeaders,omitempty"` + HTTPTotal *int `json:"httpTotal,omitempty"` +} + +type Unit struct { + Contents string `json:"contents,omitempty"` + Dropins []Dropin `json:"dropins,omitempty"` + Enable bool `json:"enable,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Mask bool `json:"mask,omitempty"` + Name string `json:"name,omitempty"` +} + +type Usercreate struct { + Gecos string `json:"gecos,omitempty"` + Groups []UsercreateGroup `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type UsercreateGroup string + +type Verification struct { + Hash *string `json:"hash,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_1/types/unit.go new file mode 100644 index 00000000..3d3fc8db --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/unit.go @@ -0,0 +1,109 @@ +// 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" +) + +var ( + ErrInvalidSystemdExt = errors.New("invalid systemd unit extension") + ErrInvalidNetworkdExt = errors.New("invalid networkd unit extension") +) + +func (u Unit) ValidateContents() report.Report { + r := report.Report{} + if err := validateUnitContent(u.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (u Unit) ValidateName() report.Report { + r := report.Report{} + switch path.Ext(u.Name) { + case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": + default: + r.Add(report.Entry{ + Message: ErrInvalidSystemdExt.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (d Dropin) Validate() report.Report { + r := report.Report{} + + if err := validateUnitContent(d.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + switch path.Ext(d.Name) { + case ".conf": + default: + r.Add(report.Entry{ + Message: fmt.Sprintf("invalid systemd unit drop-in extension: %q", path.Ext(d.Name)), + Kind: report.EntryError, + }) + } + + return r +} + +func (u Networkdunit) Validate() report.Report { + r := report.Report{} + + if err := validateUnitContent(u.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + switch path.Ext(u.Name) { + case ".link", ".netdev", ".network": + default: + r.Add(report.Entry{ + Message: ErrInvalidNetworkdExt.Error(), + Kind: report.EntryError, + }) + } + + return r +} + +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_1/types/url.go b/vendor/github.com/coreos/ignition/config/v2_1/types/url.go new file mode 100644 index 00000000..f6270c9a --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/url.go @@ -0,0 +1,49 @@ +// 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" + "net/url" + + "github.com/vincent-petithory/dataurl" +) + +var ( + ErrInvalidScheme = errors.New("invalid url scheme") +) + +func validateURL(s string) error { + // Empty url is valid, indicates an empty file + if s == "" { + return nil + } + u, err := url.Parse(s) + if err != nil { + return err + } + + switch u.Scheme { + case "http", "https", "oem", "tftp", "s3": + return nil + case "data": + if _, err := dataurl.DecodeString(s); err != nil { + return err + } + return nil + default: + return ErrInvalidScheme + } +} diff --git a/vendor/github.com/coreos/ignition/config/types/hash.go b/vendor/github.com/coreos/ignition/config/v2_1/types/verification.go similarity index 52% rename from vendor/github.com/coreos/ignition/config/types/hash.go rename to vendor/github.com/coreos/ignition/config/v2_1/types/verification.go index 77d11d3d..d2158b80 100644 --- a/vendor/github.com/coreos/ignition/config/types/hash.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/verification.go @@ -17,7 +17,6 @@ package types import ( "crypto" "encoding/hex" - "encoding/json" "errors" "strings" @@ -30,44 +29,55 @@ var ( 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 +// HashParts will return the sum and function (in that order) of the hash stored +// in this Verification, or an error if there is an issue during parsing. +func (v Verification) HashParts() (string, string, error) { + if v.Hash == nil { + // The hash can be nil + return "", "", nil } - - parts := strings.SplitN(th, "-", 2) + parts := strings.SplitN(*v.Hash, "-", 2) if len(parts) != 2 { - return ErrHashMalformed + return "", "", ErrHashMalformed } - h.Function = parts[0] - h.Sum = parts[1] - - return nil + return parts[0], parts[1], nil } -func (h Hash) MarshalJSON() ([]byte, error) { - return []byte(`"` + h.Function + "-" + h.Sum + `"`), nil -} +func (v Verification) Validate() report.Report { + r := report.Report{} -func (h Hash) Validate() report.Report { + if v.Hash == nil { + // The hash can be nil + return r + } + + function, sum, err := v.HashParts() + if err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + return r + } var hash crypto.Hash - switch h.Function { + switch function { case "sha512": hash = crypto.SHA512 default: - return report.ReportFromError(ErrHashUnrecognized, report.EntryError) + r.Add(report.Entry{ + Message: ErrHashUnrecognized.Error(), + Kind: report.EntryError, + }) + return r } - if len(h.Sum) != hex.EncodedLen(hash.Size()) { - return report.ReportFromError(ErrHashWrongSize, report.EntryError) + if len(sum) != hex.EncodedLen(hash.Size()) { + r.Add(report.Entry{ + Message: ErrHashWrongSize.Error(), + Kind: report.EntryError, + }) } - return report.Report{} + return r } diff --git a/vendor/github.com/coreos/ignition/config/validate/validate.go b/vendor/github.com/coreos/ignition/config/validate/validate.go index 33e3a8f7..4111e6ca 100644 --- a/vendor/github.com/coreos/ignition/config/validate/validate.go +++ b/vendor/github.com/coreos/ignition/config/validate/validate.go @@ -54,8 +54,9 @@ type AstNode interface { } // Validate walks down a struct tree calling Validate on every node that implements it, building -// A report of all the errors, warnings, info, and deprecations it encounters -func Validate(vObj reflect.Value, ast AstNode, source io.ReadSeeker) (r report.Report) { +// A report of all the errors, warnings, info, and deprecations it encounters. If checkUnusedKeys +// is true, Validate will generate warnings for unused keys in the ast, otherwise it will not. +func Validate(vObj reflect.Value, ast AstNode, source io.ReadSeeker, checkUnusedKeys bool) (r report.Report) { if !vObj.IsValid() { return } @@ -85,11 +86,11 @@ func Validate(vObj reflect.Value, ast AstNode, source io.ReadSeeker) (r report.R switch vObj.Kind() { case reflect.Ptr: - sub_report := Validate(vObj.Elem(), ast, source) + sub_report := Validate(vObj.Elem(), ast, source, checkUnusedKeys) sub_report.AddPosition(line, col, "") r.Merge(sub_report) case reflect.Struct: - sub_report := validateStruct(vObj, ast, source) + sub_report := validateStruct(vObj, ast, source, checkUnusedKeys) sub_report.AddPosition(line, col, "") r.Merge(sub_report) case reflect.Slice: @@ -100,7 +101,7 @@ func Validate(vObj reflect.Value, ast AstNode, source io.ReadSeeker) (r report.R sub_node = n } } - sub_report := Validate(vObj.Index(i), sub_node, source) + sub_report := Validate(vObj.Index(i), sub_node, source, checkUnusedKeys) sub_report.AddPosition(line, col, "") r.Merge(sub_report) } @@ -109,7 +110,7 @@ func Validate(vObj reflect.Value, ast AstNode, source io.ReadSeeker) (r report.R } func ValidateWithoutSource(cfg reflect.Value) (report report.Report) { - return Validate(cfg, nil, nil) + return Validate(cfg, nil, nil, false) } type field struct { @@ -137,7 +138,7 @@ func getFields(vObj reflect.Value) []field { return ret } -func validateStruct(vObj reflect.Value, ast AstNode, source io.ReadSeeker) report.Report { +func validateStruct(vObj reflect.Value, ast AstNode, source io.ReadSeeker, checkUnusedKeys bool) report.Report { r := report.Report{} // isFromObject will be true if this struct was unmarshalled from a JSON object. @@ -173,17 +174,28 @@ func validateStruct(vObj reflect.Value, ast AstNode, source io.ReadSeeker) repor src = source } } - sub_report := Validate(f.Value, sub_node, src) + // Default to deepest node if the node's type isn't an object, // such as when a json string actually unmarshal to structs (like with version) line, col := 0, 0 if ast != nil { line, col, _ = ast.ValueLineCol(src) } + + // If there's a Validate func for the given field, call it + funct := vObj.MethodByName("Validate" + f.Type.Name) + if funct.IsValid() { + res := funct.Call(nil) + sub_report := res[0].Interface().(report.Report) + sub_report.AddPosition(line, col, "") + r.Merge(sub_report) + } + + sub_report := Validate(f.Value, sub_node, src, checkUnusedKeys) sub_report.AddPosition(line, col, "") r.Merge(sub_report) } - if !isFromObject { + if !isFromObject || !checkUnusedKeys { // If this struct was not unmarshalled from a JSON object, there cannot be unused keys. return r } diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go index 0d1771c3..3d534d2d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_darwin.go +++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go @@ -144,6 +144,7 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) ( uintptr(options), 0, ) + use(unsafe.Pointer(_p0)) if e1 != 0 { return nil, e1 } @@ -196,6 +197,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) } r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags)) + use(unsafe.Pointer(_p0)) n = int(r0) if e1 != 0 { err = e1 diff --git a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go index fbbe0dce..ec408ee7 100644 --- a/vendor/golang.org/x/sys/unix/syscall_dragonfly.go +++ b/vendor/golang.org/x/sys/unix/syscall_dragonfly.go @@ -109,6 +109,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) } r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) + use(unsafe.Pointer(_p0)) n = int(r0) if e1 != 0 { err = e1 diff --git a/vendor/golang.org/x/sys/unix/syscall_freebsd.go b/vendor/golang.org/x/sys/unix/syscall_freebsd.go index ec56ed60..520ccbea 100644 --- a/vendor/golang.org/x/sys/unix/syscall_freebsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_freebsd.go @@ -129,6 +129,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) } r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) + use(unsafe.Pointer(_p0)) n = int(r0) if e1 != 0 { err = e1 diff --git a/vendor/golang.org/x/sys/unix/syscall_linux.go b/vendor/golang.org/x/sys/unix/syscall_linux.go index 9ca104c9..6d10c9cf 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux.go @@ -60,6 +60,15 @@ func Openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) return openat(dirfd, path, flags|O_LARGEFILE, mode) } +//sys ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) + +func Ppoll(fds []PollFd, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + if len(fds) == 0 { + return ppoll(nil, 0, timeout, sigmask) + } + return ppoll(&fds[0], len(fds), timeout, sigmask) +} + //sys readlinkat(dirfd int, path string, buf []byte) (n int, err error) func Readlink(path string, buf []byte) (n int, err error) { @@ -1043,8 +1052,6 @@ func Munmap(b []byte) (err error) { // Newfstatat // Nfsservctl // Personality -// Poll -// Ppoll // Pselect6 // Ptrace // Putpmsg diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_386.go b/vendor/golang.org/x/sys/unix/syscall_linux_386.go index bea01cb5..2b881b97 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_386.go @@ -388,3 +388,12 @@ func (msghdr *Msghdr) SetControllen(length int) { func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } + +//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) + +func Poll(fds []PollFd, timeout int) (n int, err error) { + if len(fds) == 0 { + return poll(nil, 0, timeout) + } + return poll(&fds[0], len(fds), timeout) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go index 721f24b6..18911c2d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_amd64.go @@ -146,3 +146,12 @@ func (msghdr *Msghdr) SetControllen(length int) { func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } + +//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) + +func Poll(fds []PollFd, timeout int) (n int, err error) { + if len(fds) == 0 { + return poll(nil, 0, timeout) + } + return poll(&fds[0], len(fds), timeout) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go index 122df649..71d87022 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm.go @@ -252,3 +252,12 @@ func (msghdr *Msghdr) SetControllen(length int) { func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint32(length) } + +//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) + +func Poll(fds []PollFd, timeout int) (n int, err error) { + if len(fds) == 0 { + return poll(nil, 0, timeout) + } + return poll(&fds[0], len(fds), timeout) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go index d1051868..4b6ff2a8 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_arm64.go @@ -178,3 +178,15 @@ const ( SYS_EPOLL_CREATE = 1042 SYS_EPOLL_WAIT = 1069 ) + +func Poll(fds []PollFd, timeout int) (n int, err error) { + var ts *Timespec + if timeout >= 0 { + ts = new(Timespec) + *ts = NsecToTimespec(int64(timeout) * 1e6) + } + if len(fds) == 0 { + return ppoll(nil, 0, ts, nil) + } + return ppoll(&fds[0], len(fds), ts, nil) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go index bb15ba3e..440f54ee 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_mips64x.go @@ -204,3 +204,12 @@ func (msghdr *Msghdr) SetControllen(length int) { func (cmsg *Cmsghdr) SetLen(length int) { cmsg.Len = uint64(length) } + +//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) + +func Poll(fds []PollFd, timeout int) (n int, err error) { + if len(fds) == 0 { + return poll(nil, 0, timeout) + } + return poll(&fds[0], len(fds), timeout) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go index acd2e1c7..60770f62 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_ppc64x.go @@ -124,3 +124,12 @@ func Pipe2(p []int, flags int) (err error) { p[1] = int(pp[1]) return } + +//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) + +func Poll(fds []PollFd, timeout int) (n int, err error) { + if len(fds) == 0 { + return poll(nil, 0, timeout) + } + return poll(&fds[0], len(fds), timeout) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go index 3f98904e..81c5f473 100644 --- a/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/syscall_linux_s390x.go @@ -318,3 +318,12 @@ func Shutdown(s, how int) error { } return nil } + +//sys poll(fds *PollFd, nfds int, timeout int) (n int, err error) + +func Poll(fds []PollFd, timeout int) (n int, err error) { + if len(fds) == 0 { + return poll(nil, 0, timeout) + } + return poll(&fds[0], len(fds), timeout) +} diff --git a/vendor/golang.org/x/sys/unix/syscall_openbsd.go b/vendor/golang.org/x/sys/unix/syscall_openbsd.go index 246131d2..554a8234 100644 --- a/vendor/golang.org/x/sys/unix/syscall_openbsd.go +++ b/vendor/golang.org/x/sys/unix/syscall_openbsd.go @@ -111,6 +111,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) { bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf)) } r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags)) + use(unsafe.Pointer(_p0)) n = int(r0) if e1 != 0 { err = e1 diff --git a/vendor/golang.org/x/sys/unix/syscall_solaris.go b/vendor/golang.org/x/sys/unix/syscall_solaris.go index eb489b15..acb74b1d 100644 --- a/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -72,18 +72,20 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int, return origlen - len(buf), count, names } -func pipe() (r uintptr, w uintptr, err uintptr) +//sysnb pipe(p *[2]_C_int) (n int, err error) func Pipe(p []int) (err error) { if len(p) != 2 { return EINVAL } - r0, w0, e1 := pipe() - if e1 != 0 { - err = syscall.Errno(e1) + var pp [2]_C_int + n, err := pipe(&pp) + if n != 0 { + return err } - p[0], p[1] = int(r0), int(w0) - return + p[0] = int(pp[0]) + p[1] = int(pp[1]) + return nil } func (sa *SockaddrInet4) sockaddr() (unsafe.Pointer, _Socklen, error) { @@ -269,24 +271,34 @@ func (w WaitStatus) StopSignal() syscall.Signal { func (w WaitStatus) TrapCause() int { return -1 } -func wait4(pid uintptr, wstatus *WaitStatus, options uintptr, rusage *Rusage) (wpid uintptr, err uintptr) +//sys wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error) -func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int, err error) { - r0, e1 := wait4(uintptr(pid), wstatus, uintptr(options), rusage) - if e1 != 0 { - err = syscall.Errno(e1) +func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (int, error) { + var status _C_int + rpid, err := wait4(int32(pid), &status, options, rusage) + wpid := int(rpid) + if wpid == -1 { + return wpid, err } - return int(r0), err + if wstatus != nil { + *wstatus = WaitStatus(status) + } + return wpid, nil } -func gethostname() (name string, err uintptr) +//sys gethostname(buf []byte) (n int, err error) func Gethostname() (name string, err error) { - name, e1 := gethostname() - if e1 != 0 { - err = syscall.Errno(e1) + var buf [MaxHostNameLen]byte + n, err := gethostname(buf[:]) + if n != 0 { + return "", err } - return name, err + n = clen(buf[:]) + if n < 1 { + return "", EFAULT + } + return string(buf[:n]), nil } //sys utimes(path string, times *[2]Timeval) (err error) diff --git a/vendor/golang.org/x/sys/unix/types_linux.go b/vendor/golang.org/x/sys/unix/types_linux.go index d004b4a4..7dea79a8 100644 --- a/vendor/golang.org/x/sys/unix/types_linux.go +++ b/vendor/golang.org/x/sys/unix/types_linux.go @@ -24,6 +24,7 @@ package unix #include #include #include +#include #include #include #include @@ -430,6 +431,20 @@ const ( AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW ) +type PollFd C.struct_pollfd + +const ( + POLLIN = C.POLLIN + POLLPRI = C.POLLPRI + POLLOUT = C.POLLOUT + POLLRDHUP = C.POLLRDHUP + POLLERR = C.POLLERR + POLLHUP = C.POLLHUP + POLLNVAL = C.POLLNVAL +) + +type Sigset_t C.sigset_t + // Terminal handling type Termios C.termios_t diff --git a/vendor/golang.org/x/sys/unix/types_solaris.go b/vendor/golang.org/x/sys/unix/types_solaris.go index 6ad50eab..c5d5c8f1 100644 --- a/vendor/golang.org/x/sys/unix/types_solaris.go +++ b/vendor/golang.org/x/sys/unix/types_solaris.go @@ -22,6 +22,7 @@ package unix #define __USE_LEGACY_PROTOTYPES__ // iovec #include #include +#include #include #include #include @@ -81,6 +82,7 @@ const ( sizeofLong = C.sizeof_long sizeofLongLong = C.sizeof_longlong PathMax = C.PATH_MAX + MaxHostNameLen = C.MAXHOSTNAMELEN ) // Basic types diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 80b73811..8f920124 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -216,6 +216,7 @@ const ( CLONE_FILES = 0x400 CLONE_FS = 0x200 CLONE_IO = 0x80000000 + CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 64cc0b7d..49b6c354 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -216,6 +216,7 @@ const ( CLONE_FILES = 0x400 CLONE_FS = 0x200 CLONE_IO = 0x80000000 + CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 1cc76a78..f036758f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -212,6 +212,7 @@ const ( CLONE_FILES = 0x400 CLONE_FS = 0x200 CLONE_IO = 0x80000000 + CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index 47027b79..16dcbc9c 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -222,6 +222,7 @@ const ( CLONE_FILES = 0x400 CLONE_FS = 0x200 CLONE_IO = 0x80000000 + CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 98056fe2..36535b24 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -221,6 +221,7 @@ const ( CLONE_FILES = 0x400 CLONE_FS = 0x200 CLONE_IO = 0x80000000 + CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index e5debb68..112f05de 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -221,6 +221,7 @@ const ( CLONE_FILES = 0x400 CLONE_FS = 0x200 CLONE_IO = 0x80000000 + CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index 5b90d07e..8b42ca2f 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -223,6 +223,7 @@ const ( CLONE_FILES = 0x400 CLONE_FS = 0x200 CLONE_IO = 0x80000000 + CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 diff --git a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index 0861bd56..e8d12b5d 100644 --- a/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -222,6 +222,7 @@ const ( CLONE_FILES = 0x400 CLONE_FS = 0x200 CLONE_IO = 0x80000000 + CLONE_NEWCGROUP = 0x2000000 CLONE_NEWIPC = 0x8000000 CLONE_NEWNET = 0x40000000 CLONE_NEWNS = 0x20000 diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go index 749f3e46..1f7a7566 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_386.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1636,3 +1647,14 @@ func Utime(path string, buf *Utimbuf) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go index 1096aa54..b4e24fc0 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_amd64.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1830,3 +1841,14 @@ func pipe2(p *[2]_C_int, flags int) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go index 9066e1cb..20bf33ce 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1737,3 +1748,14 @@ func setrlimit(resource int, rlim *rlimit32) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go index 5b916122..c7286db4 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_arm64.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go index 738c8309..b709ed2f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1779,3 +1790,14 @@ func stat(path string, st *stat_t) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go index 2a035783..5cb1c567 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_mips64le.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1779,3 +1790,14 @@ func stat(path string, st *stat_t) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go index 4bd18dce..873bb18f 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1841,3 +1852,14 @@ func pipe2(p *[2]_C_int, flags int) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go index fbb43516..bf08835c 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_ppc64le.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1841,3 +1852,14 @@ func pipe2(p *[2]_C_int, flags int) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go index f8aa91f1..dbaa53b9 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_linux_s390x.go @@ -53,6 +53,17 @@ func openat(dirfd int, path string, flags int, mode uint32) (fd int, err error) // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func ppoll(fds *PollFd, nfds int, timeout *Timespec, sigmask *Sigset_t) (n int, err error) { + r0, _, e1 := Syscall6(SYS_PPOLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(unsafe.Pointer(timeout)), uintptr(unsafe.Pointer(sigmask)), 0, 0) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func readlinkat(dirfd int, path string, buf []byte) (n int, err error) { var _p0 *byte _p0, err = BytePtrFromString(path) @@ -1621,3 +1632,14 @@ func pipe2(p *[2]_C_int, flags int) (err error) { } return } + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + +func poll(fds *PollFd, nfds int, timeout int) (n int, err error) { + r0, _, e1 := Syscall(SYS_POLL, uintptr(unsafe.Pointer(fds)), uintptr(nfds), uintptr(timeout)) + n = int(r0) + if e1 != 0 { + err = errnoErr(e1) + } + return +} diff --git a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index 43264278..c0ecfc04 100644 --- a/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -10,10 +10,13 @@ import ( "unsafe" ) +//go:cgo_import_dynamic libc_pipe pipe "libc.so" //go:cgo_import_dynamic libc_getsockname getsockname "libsocket.so" //go:cgo_import_dynamic libc_getcwd getcwd "libc.so" //go:cgo_import_dynamic libc_getgroups getgroups "libc.so" //go:cgo_import_dynamic libc_setgroups setgroups "libc.so" +//go:cgo_import_dynamic libc_wait4 wait4 "libc.so" +//go:cgo_import_dynamic libc_gethostname gethostname "libc.so" //go:cgo_import_dynamic libc_utimes utimes "libc.so" //go:cgo_import_dynamic libc_utimensat utimensat "libc.so" //go:cgo_import_dynamic libc_fcntl fcntl "libc.so" @@ -125,10 +128,13 @@ import ( //go:cgo_import_dynamic libc_recvfrom recvfrom "libsocket.so" //go:cgo_import_dynamic libc_sysconf sysconf "libc.so" +//go:linkname procpipe libc_pipe //go:linkname procgetsockname libc_getsockname //go:linkname procGetcwd libc_getcwd //go:linkname procgetgroups libc_getgroups //go:linkname procsetgroups libc_setgroups +//go:linkname procwait4 libc_wait4 +//go:linkname procgethostname libc_gethostname //go:linkname procutimes libc_utimes //go:linkname procutimensat libc_utimensat //go:linkname procfcntl libc_fcntl @@ -241,10 +247,13 @@ import ( //go:linkname procsysconf libc_sysconf var ( + procpipe, procgetsockname, procGetcwd, procgetgroups, procsetgroups, + procwait4, + procgethostname, procutimes, procutimensat, procfcntl, @@ -357,6 +366,15 @@ var ( procsysconf syscallFunc ) +func pipe(p *[2]_C_int) (n int, err error) { + r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procpipe)), 1, uintptr(unsafe.Pointer(p)), 0, 0, 0, 0, 0) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} + func getsockname(fd int, rsa *RawSockaddrAny, addrlen *_Socklen) (err error) { _, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgetsockname)), 3, uintptr(fd), uintptr(unsafe.Pointer(rsa)), uintptr(unsafe.Pointer(addrlen)), 0, 0, 0) if e1 != 0 { @@ -395,6 +413,28 @@ func setgroups(ngid int, gid *_Gid_t) (err error) { return } +func wait4(pid int32, statusp *_C_int, options int, rusage *Rusage) (wpid int32, err error) { + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procwait4)), 4, uintptr(pid), uintptr(unsafe.Pointer(statusp)), uintptr(options), uintptr(unsafe.Pointer(rusage)), 0, 0) + wpid = int32(r0) + if e1 != 0 { + err = e1 + } + return +} + +func gethostname(buf []byte) (n int, err error) { + var _p0 *byte + if len(buf) > 0 { + _p0 = &buf[0] + } + r0, _, e1 := sysvicall6(uintptr(unsafe.Pointer(&procgethostname)), 2, uintptr(unsafe.Pointer(_p0)), uintptr(len(buf)), 0, 0, 0, 0) + n = int(r0) + if e1 != 0 { + err = e1 + } + return +} + func utimes(path string, times *[2]Timeval) (err error) { var _p0 *byte _p0, err = BytePtrFromString(path) diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index fb1257ae..f3ddf534 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -595,6 +595,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index 34edb368..a923bef3 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -613,6 +613,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 0fef350b..817ac9c2 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -575,6 +575,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index 28b7cd43..e786addf 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -592,6 +592,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 8fe5af26..b29894de 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -596,6 +596,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index df16e83c..d9af71b6 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -596,6 +596,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index d1105402..4218170a 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -602,6 +602,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 8e25c9ff..7db4c78c 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -602,6 +602,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 268e3736..76ee57cb 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -617,6 +617,26 @@ const ( AT_SYMLINK_NOFOLLOW = 0x100 ) +type PollFd struct { + Fd int32 + Events int16 + Revents int16 +} + +const ( + POLLIN = 0x1 + POLLPRI = 0x2 + POLLOUT = 0x4 + POLLRDHUP = 0x2000 + POLLERR = 0x8 + POLLHUP = 0x10 + POLLNVAL = 0x20 +) + +type Sigset_t struct { + X__val [16]uint64 +} + type Termios struct { Iflag uint32 Oflag uint32 diff --git a/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go index b3b928a5..02777e4d 100644 --- a/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go +++ b/vendor/golang.org/x/sys/unix/ztypes_solaris_amd64.go @@ -1,6 +1,6 @@ // +build amd64,solaris // Created by cgo -godefs - DO NOT EDIT -// cgo -godefs types_solaris.go +// cgo -godefs types_solaris.go | go run mkpost.go package unix @@ -11,6 +11,7 @@ const ( sizeofLong = 0x8 sizeofLongLong = 0x8 PathMax = 0x400 + MaxHostNameLen = 0x100 ) type (