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 42d74556..c6ace4d1 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 @@ -21,7 +21,7 @@ import ( "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_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" @@ -62,13 +62,13 @@ func Parse(data []byte) (types.Config, astnode.AstNode, report.Report) { return cfg, root, r } -// ConvertAs2_0 will convert a golang struct representing a Container Linux +// Convert 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 +// Convert 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 astnode.AstNode) (ignTypes.Config, report.Report) { +func Convert(in types.Config, p string, ast astnode.AstNode) (ignTypes.Config, report.Report) { if !platform.IsSupportedPlatform(p) { r := report.Report{} r.Add(report.Entry{ @@ -77,5 +77,5 @@ func ConvertAs2_0(in types.Config, p string, ast astnode.AstNode) (ignTypes.Conf }) return ignTypes.Config{}, r } - return types.ConvertAs2_0(in, p, ast) + return types.Convert(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 index 88a16c8e..0bf4f73c 100644 --- 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 @@ -23,6 +23,7 @@ const ( OpenStackMetadata = "openstack-metadata" VagrantVirtualbox = "vagrant-virtualbox" CloudStackConfigDrive = "cloudstack-configdrive" + Custom = "custom" ) var Platforms = []string{ @@ -34,6 +35,7 @@ var Platforms = []string{ OpenStackMetadata, VagrantVirtualbox, CloudStackConfigDrive, + Custom, } func IsSupportedPlatform(platform string) bool { 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 573611ea..b97b8287 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 @@ -76,6 +76,13 @@ var platformTemplatingMap = map[string]map[string]string{ platform.CloudStackConfigDrive: { fieldHostname: "CLOUDSTACK_LOCAL_HOSTNAME", }, + platform.Custom: { + fieldHostname: "COREOS_CUSTOM_HOSTNAME", + fieldV4Private: "COREOS_CUSTOM_PRIVATE_IPV4", + fieldV4Public: "COREOS_CUSTOM_PUBLIC_IPV4", + fieldV6Private: "COREOS_CUSTOM_PRIVATE_IPV6", + fieldV6Public: "COREOS_CUSTOM_PUBLIC_IPV6", + }, } // 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 ecc3e36f..1a18b0e6 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 @@ -19,12 +19,13 @@ import ( "fmt" "reflect" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/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" + iutil "github.com/coreos/container-linux-config-transpiler/internal/util" "github.com/coreos/ignition/config/validate/astnode" ) @@ -36,18 +37,19 @@ var ( ) func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, p string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, p string) (ignTypes.Config, report.Report, astnode.AstNode) { if p == platform.OpenStackMetadata || p == platform.CloudStackConfigDrive { out.Systemd.Units = append(out.Systemd.Units, ignTypes.Unit{ Name: "coreos-metadata.service", - Dropins: []ignTypes.Dropin{{ + Dropins: []ignTypes.SystemdDropin{{ 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.Unit{ - Name: "coreos-metadata-sshkeys@.service", - Dropins: []ignTypes.Dropin{{ + Name: "coreos-metadata-sshkeys@.service", + Enabled: iutil.BoolToPtr(true), + Dropins: []ignTypes.SystemdDropin{{ Name: "20-clct-provider-override.conf", Contents: fmt.Sprintf("[Service]\nEnvironment=COREOS_METADATA_OPT_PROVIDER=--provider=%s", p), }}, @@ -111,6 +113,9 @@ func getArgs(format, tagName string, e interface{}) []string { vars = append(vars, getCliArgs(val)...) } else { key := et.Field(i).Tag.Get(tagName) + if ev.Field(i).Kind() == reflect.Ptr { + val = reflect.Indirect(ev.Field(i)).Interface() + } if _, ok := val.(string); ok { // to handle whitespace characters val = fmt.Sprintf("%q", val) 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 19c9ea17..567bcad4 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 @@ -17,7 +17,7 @@ package types import ( "net/url" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -38,6 +38,7 @@ type Config struct { type Ignition struct { Config IgnitionConfig `yaml:"config"` Timeouts Timeouts `yaml:"timeouts"` + Security Security `yaml:"security"` } type IgnitionConfig struct { @@ -56,7 +57,7 @@ type Timeouts struct { } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { r := report.Report{} out.Ignition.Timeouts.HTTPResponseHeaders = in.Ignition.Timeouts.HTTPResponseHeaders out.Ignition.Timeouts.HTTPTotal = in.Ignition.Timeouts.HTTPTotal 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 e4862de5..c61316c4 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 @@ -18,21 +18,21 @@ import ( "reflect" "github.com/coreos/container-linux-config-transpiler/config/astyaml" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) -type converterFor2_0 func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) +type converter func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) -var convertersFor2_0 []converterFor2_0 +var converters []converter -func register2_0(f converterFor2_0) { - convertersFor2_0 = append(convertersFor2_0, f) +func register(f converter) { + converters = append(converters, f) } -func ConvertAs2_0(in Config, platform string, ast astnode.AstNode) (ignTypes.Config, report.Report) { +func Convert(in Config, platform string, ast astnode.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) @@ -43,13 +43,13 @@ func ConvertAs2_0(in Config, platform string, ast astnode.AstNode) (ignTypes.Con out := ignTypes.Config{ Ignition: ignTypes.Ignition{ - Version: "2.1.0", + Version: "2.2.0", }, } r := report.Report{} - for _, convert := range convertersFor2_0 { + for _, convert := range converters { var subReport report.Report out, subReport, ast = convert(in, ast, out, platform) r.Merge(subReport) 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 9d94d35b..4ca365cf 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 @@ -18,7 +18,7 @@ import ( "fmt" "github.com/alecthomas/units" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -52,7 +52,7 @@ type Partition struct { } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { r := report.Report{} for disk_idx, disk := range in.Storage.Disks { newDisk := ignTypes.Disk{ 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 565e6973..6a9865a3 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 @@ -18,7 +18,7 @@ import ( "fmt" "strings" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -28,13 +28,13 @@ type Docker struct { } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.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.Unit{ Name: "docker.service", Enable: true, - Dropins: []ignTypes.Dropin{{ + Dropins: []ignTypes.SystemdDropin{{ Name: "20-clct-docker.conf", Contents: contents, }}, 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 e0d110a9..f9abf155 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 @@ -19,7 +19,7 @@ import ( "fmt" "github.com/coreos/go-semver/semver" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -55,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 > 2: + case v.Major == 3 && v.Minor > 3: return report.ReportFromError(EtcdMinorVersionTooNew, report.EntryWarning) case v.Major > 3: return report.ReportFromError(EtcdMajorVersionTooNew, report.EntryError) @@ -108,18 +108,25 @@ func (etcd *Etcd) UnmarshalYAML(unmarshal func(interface{}) error) error { return err } etcd.Options = o - } else if version.Major == 3 && version.Minor >= 2 { + } else if version.Major == 3 && version.Minor == 2 { o := Etcd3_2{} if err := unmarshal(&o); err != nil { return err } etcd.Options = o + } else if version.Major == 3 && version.Minor >= 3 { + o := Etcd3_3{} + if err := unmarshal(&o); err != nil { + return err + } + etcd.Options = o } + return nil } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { if in.Etcd != nil { contents, err := etcdContents(*in.Etcd, platform) if err != nil { @@ -128,7 +135,7 @@ func init() { out.Systemd.Units = append(out.Systemd.Units, ignTypes.Unit{ Name: "etcd-member.service", Enable: true, - Dropins: []ignTypes.Dropin{{ + Dropins: []ignTypes.SystemdDropin{{ Name: "20-clct-etcd-member.conf", Contents: contents, }}, @@ -155,192 +162,257 @@ func etcdContents(etcd Etcd, platform string) (string, error) { } type Etcd3_0 struct { - Name string `yaml:"name" cli:"name"` - DataDir string `yaml:"data_dir" cli:"data-dir"` - WalDir string `yaml:"wal_dir" cli:"wal-dir"` - SnapshotCount int `yaml:"snapshot_count" cli:"snapshot-count"` - HeartbeatInterval int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` - ElectionTimeout int `yaml:"election_timeout" cli:"election-timeout"` - 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"` - MaxWals int `yaml:"max_wals" cli:"max-wals"` - Cors string `yaml:"cors" cli:"cors"` - InitialAdvertisePeerUrls string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` - InitialCluster string `yaml:"initial_cluster" cli:"initial-cluster"` - InitialClusterState string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` - InitialClusterToken string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` - AdvertiseClientUrls string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` - Discovery string `yaml:"discovery" cli:"discovery"` - DiscoverySrv string `yaml:"discovery_srv" cli:"discovery-srv"` - DiscoveryFallback string `yaml:"discovery_fallback" cli:"discovery-fallback"` - DiscoveryProxy string `yaml:"discovery_proxy" cli:"discovery-proxy"` - StrictReconfigCheck bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` - AutoCompactionRetention int `yaml:"auto_compaction_retention" cli:"auto-compaction-retention"` - Proxy string `yaml:"proxy" cli:"proxy"` - ProxyFailureWait int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` - ProxyRefreshInterval int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` - ProxyDialTimeout int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` - ProxyWriteTimeout int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` - ProxyReadTimeout int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` - CaFile string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` - CertFile string `yaml:"cert_file" cli:"cert-file"` - KeyFile string `yaml:"key_file" cli:"key-file"` - ClientCertAuth bool `yaml:"client_cert_auth" cli:"client-cert-auth"` - TrustedCaFile string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` - AutoTls bool `yaml:"auto_tls" cli:"auto-tls"` - PeerCaFile string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` - PeerCertFile string `yaml:"peer_cert_file" cli:"peer-cert-file"` - PeerKeyFile string `yaml:"peer_key_file" cli:"peer-key-file"` - PeerClientCertAuth bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` - PeerTrustedCaFile string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` - PeerAutoTls bool `yaml:"peer_auto_tls" cli:"peer-auto-tls"` - Debug bool `yaml:"debug" cli:"debug"` - LogPackageLevels string `yaml:"log_package_levels" cli:"log-package-levels"` - ForceNewCluster bool `yaml:"force_new_cluster" cli:"force-new-cluster"` + 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"` + ListenPeerUrls *string `yaml:"listen_peer_urls" cli:"listen-peer-urls"` + ListenClientUrls *string `yaml:"listen_client_urls" cli:"listen-client-urls"` + MaxSnapshots *int `yaml:"max_snapshots" cli:"max-snapshots"` + MaxWals *int `yaml:"max_wals" cli:"max-wals"` + Cors *string `yaml:"cors" cli:"cors"` + InitialAdvertisePeerUrls *string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` + InitialCluster *string `yaml:"initial_cluster" cli:"initial-cluster"` + InitialClusterState *string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` + InitialClusterToken *string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` + AdvertiseClientUrls *string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` + Discovery *string `yaml:"discovery" cli:"discovery"` + DiscoverySrv *string `yaml:"discovery_srv" cli:"discovery-srv"` + DiscoveryFallback *string `yaml:"discovery_fallback" cli:"discovery-fallback"` + DiscoveryProxy *string `yaml:"discovery_proxy" cli:"discovery-proxy"` + StrictReconfigCheck *bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` + AutoCompactionRetention *int `yaml:"auto_compaction_retention" cli:"auto-compaction-retention"` + Proxy *string `yaml:"proxy" cli:"proxy"` + ProxyFailureWait *int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` + ProxyRefreshInterval *int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` + ProxyDialTimeout *int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` + ProxyWriteTimeout *int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` + ProxyReadTimeout *int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` + CaFile *string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` + CertFile *string `yaml:"cert_file" cli:"cert-file"` + KeyFile *string `yaml:"key_file" cli:"key-file"` + ClientCertAuth *bool `yaml:"client_cert_auth" cli:"client-cert-auth"` + TrustedCaFile *string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` + AutoTls *bool `yaml:"auto_tls" cli:"auto-tls"` + PeerCaFile *string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` + PeerCertFile *string `yaml:"peer_cert_file" cli:"peer-cert-file"` + PeerKeyFile *string `yaml:"peer_key_file" cli:"peer-key-file"` + PeerClientCertAuth *bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` + PeerTrustedCaFile *string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` + PeerAutoTls *bool `yaml:"peer_auto_tls" cli:"peer-auto-tls"` + Debug *bool `yaml:"debug" cli:"debug"` + LogPackageLevels *string `yaml:"log_package_levels" cli:"log-package-levels"` + ForceNewCluster *bool `yaml:"force_new_cluster" cli:"force-new-cluster"` } type Etcd3_1 struct { - Name string `yaml:"name" cli:"name"` - DataDir string `yaml:"data_dir" cli:"data-dir"` - WalDir string `yaml:"wal_dir" cli:"wal-dir"` - SnapshotCount int `yaml:"snapshot_count" cli:"snapshot-count"` - HeartbeatInterval int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` - ElectionTimeout int `yaml:"election_timeout" cli:"election-timeout"` - 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"` - MaxWals int `yaml:"max_wals" cli:"max-wals"` - Cors string `yaml:"cors" cli:"cors"` - InitialAdvertisePeerUrls string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` - InitialCluster string `yaml:"initial_cluster" cli:"initial-cluster"` - InitialClusterState string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` - InitialClusterToken string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` - AdvertiseClientUrls string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` - Discovery string `yaml:"discovery" cli:"discovery"` - DiscoverySrv string `yaml:"discovery_srv" cli:"discovery-srv"` - DiscoveryFallback string `yaml:"discovery_fallback" cli:"discovery-fallback"` - DiscoveryProxy string `yaml:"discovery_proxy" cli:"discovery-proxy"` - StrictReconfigCheck bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` - AutoCompactionRetention int `yaml:"auto_compaction_retention" cli:"auto-compaction-retention"` - Proxy string `yaml:"proxy" cli:"proxy"` - ProxyFailureWait int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` - ProxyRefreshInterval int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` - ProxyDialTimeout int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` - ProxyWriteTimeout int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` - ProxyReadTimeout int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` - CaFile string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` - CertFile string `yaml:"cert_file" cli:"cert-file"` - KeyFile string `yaml:"key_file" cli:"key-file"` - ClientCertAuth bool `yaml:"client_cert_auth" cli:"client-cert-auth"` - TrustedCaFile string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` - AutoTls bool `yaml:"auto_tls" cli:"auto-tls"` - PeerCaFile string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` - PeerCertFile string `yaml:"peer_cert_file" cli:"peer-cert-file"` - PeerKeyFile string `yaml:"peer_key_file" cli:"peer-key-file"` - PeerClientCertAuth bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` - PeerTrustedCaFile string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` - PeerAutoTls bool `yaml:"peer_auto_tls" cli:"peer-auto-tls"` - Debug bool `yaml:"debug" cli:"debug"` - LogPackageLevels string `yaml:"log_package_levels" cli:"log-package-levels"` - ForceNewCluster bool `yaml:"force_new_cluster" cli:"force-new-cluster"` - Metrics string `yaml:"metrics" cli:"metrics"` - LogOutput string `yaml:"log_output" cli:"log-output"` + 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"` + ListenPeerUrls *string `yaml:"listen_peer_urls" cli:"listen-peer-urls"` + ListenClientUrls *string `yaml:"listen_client_urls" cli:"listen-client-urls"` + MaxSnapshots *int `yaml:"max_snapshots" cli:"max-snapshots"` + MaxWals *int `yaml:"max_wals" cli:"max-wals"` + Cors *string `yaml:"cors" cli:"cors"` + InitialAdvertisePeerUrls *string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` + InitialCluster *string `yaml:"initial_cluster" cli:"initial-cluster"` + InitialClusterState *string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` + InitialClusterToken *string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` + AdvertiseClientUrls *string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` + Discovery *string `yaml:"discovery" cli:"discovery"` + DiscoverySrv *string `yaml:"discovery_srv" cli:"discovery-srv"` + DiscoveryFallback *string `yaml:"discovery_fallback" cli:"discovery-fallback"` + DiscoveryProxy *string `yaml:"discovery_proxy" cli:"discovery-proxy"` + StrictReconfigCheck *bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` + AutoCompactionRetention *int `yaml:"auto_compaction_retention" cli:"auto-compaction-retention"` + Proxy *string `yaml:"proxy" cli:"proxy"` + ProxyFailureWait *int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` + ProxyRefreshInterval *int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` + ProxyDialTimeout *int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` + ProxyWriteTimeout *int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` + ProxyReadTimeout *int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` + CaFile *string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` + CertFile *string `yaml:"cert_file" cli:"cert-file"` + KeyFile *string `yaml:"key_file" cli:"key-file"` + ClientCertAuth *bool `yaml:"client_cert_auth" cli:"client-cert-auth"` + TrustedCaFile *string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` + AutoTls *bool `yaml:"auto_tls" cli:"auto-tls"` + PeerCaFile *string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` + PeerCertFile *string `yaml:"peer_cert_file" cli:"peer-cert-file"` + PeerKeyFile *string `yaml:"peer_key_file" cli:"peer-key-file"` + PeerClientCertAuth *bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` + PeerTrustedCaFile *string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` + PeerAutoTls *bool `yaml:"peer_auto_tls" cli:"peer-auto-tls"` + Debug *bool `yaml:"debug" cli:"debug"` + LogPackageLevels *string `yaml:"log_package_levels" cli:"log-package-levels"` + ForceNewCluster *bool `yaml:"force_new_cluster" cli:"force-new-cluster"` + Metrics *string `yaml:"metrics" cli:"metrics"` + LogOutput *string `yaml:"log_output" cli:"log-output"` } type 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"` + 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 Etcd3_3 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"` + QuotaBackendBytes *int `yaml:"quota_backend_bytes" cli:"quota-backend-bytes"` + MaxTxnOps *int `yaml:"max_txn_ops" cli:"max-txn-ops"` + MaxRequestBytes *int `yaml:"max_request_bytes" cli:"max-request-bytes"` + GrpcKeepaliveMinTime *string `yaml:"grpc_keepalive_min_time" cli:"grpc-keepalive-min-time"` + GrpcKeepaliveInterval *string `yaml:"grpc_keepalive_interval" cli:"grpc-keepalive-interval"` + GrpcKeepaliveTimeout *string `yaml:"grpc_keepalive_timeout" cli:"grpc-keepalive-timeout"` + 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 *string `yaml:"auto_compaction_retention" cli:"auto-compaction-retention"` + AutoCompactionMode *string `yaml:"auto_compaction_mode" cli:"auto-compaction-mode"` + 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"` + ClientCrlFile *string `yaml:"client_crl_file" cli:"client-crl-file"` + 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"` + PeerCrlFile *string `yaml:"peer_crl_file" cli:"peer-crl-file"` + PeerTrustedCaFile *string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` + PeerAutoTls *bool `yaml:"peer_auto_tls" cli:"peer-auto-tls"` + PeerCertAllowedCn *string `yaml:"peer_cert_allowed_cn" cli:"peer-cert-allowed-cn"` + 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"` + ListenMetricsUrls *string `yaml:"listen_metrics_urls" cli:"listen-metrics-urls"` + ExperimentalInitialCorruptCheck *bool `yaml:"experimental_initial_corrupt_check" cli:"experimental-initial-corrupt-check"` + ExperimentalCorruptCheckTime *string `yaml:"experimental_corrupt_check_time" cli:"experimental-corrupt-check-time"` + ExperimentalEnableV2V3 *string `yaml:"experimental_enable_v2v3" cli:"experimental-enable-v2v3"` } type Etcd2 struct { - AdvertiseClientURLs string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` - CAFile string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` - CertFile string `yaml:"cert_file" cli:"cert-file"` - ClientCertAuth bool `yaml:"client_cert_auth" cli:"client-cert-auth"` - CorsOrigins string `yaml:"cors" cli:"cors"` - DataDir string `yaml:"data_dir" cli:"data-dir"` - Debug bool `yaml:"debug" cli:"debug"` - Discovery string `yaml:"discovery" cli:"discovery"` - DiscoveryFallback string `yaml:"discovery_fallback" cli:"discovery-fallback"` - DiscoverySRV string `yaml:"discovery_srv" cli:"discovery-srv"` - DiscoveryProxy string `yaml:"discovery_proxy" cli:"discovery-proxy"` - ElectionTimeout int `yaml:"election_timeout" cli:"election-timeout"` - EnablePprof bool `yaml:"enable_pprof" cli:"enable-pprof"` - ForceNewCluster bool `yaml:"force_new_cluster" cli:"force-new-cluster"` - HeartbeatInterval int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` - InitialAdvertisePeerURLs string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` - InitialCluster string `yaml:"initial_cluster" cli:"initial-cluster"` - InitialClusterState string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` - InitialClusterToken string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` - KeyFile string `yaml:"key_file" cli:"key-file"` - ListenClientURLs string `yaml:"listen_client_urls" cli:"listen-client-urls"` - ListenPeerURLs string `yaml:"listen_peer_urls" cli:"listen-peer-urls"` - LogPackageLevels string `yaml:"log_package_levels" cli:"log-package-levels"` - MaxSnapshots int `yaml:"max_snapshots" cli:"max-snapshots"` - MaxWALs int `yaml:"max_wals" cli:"max-wals"` - Name string `yaml:"name" cli:"name"` - PeerCAFile string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` - PeerCertFile string `yaml:"peer_cert_file" cli:"peer-cert-file"` - PeerKeyFile string `yaml:"peer_key_file" cli:"peer-key-file"` - PeerClientCertAuth bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` - PeerTrustedCAFile string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` - Proxy string `yaml:"proxy" cli:"proxy" valid:"^(on|off|readonly)$"` - ProxyDialTimeout int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` - ProxyFailureWait int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` - ProxyReadTimeout int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` - ProxyRefreshInterval int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` - ProxyWriteTimeout int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` - SnapshotCount int `yaml:"snapshot_count" cli:"snapshot-count"` - StrictReconfigCheck bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` - TrustedCAFile string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` - WalDir string `yaml:"wal_dir" cli:"wal-dir"` + AdvertiseClientURLs *string `yaml:"advertise_client_urls" cli:"advertise-client-urls"` + CAFile *string `yaml:"ca_file" cli:"ca-file" deprecated:"ca_file obsoleted by trusted_ca_file and client_cert_auth"` + CertFile *string `yaml:"cert_file" cli:"cert-file"` + ClientCertAuth *bool `yaml:"client_cert_auth" cli:"client-cert-auth"` + CorsOrigins *string `yaml:"cors" cli:"cors"` + DataDir *string `yaml:"data_dir" cli:"data-dir"` + Debug *bool `yaml:"debug" cli:"debug"` + Discovery *string `yaml:"discovery" cli:"discovery"` + DiscoveryFallback *string `yaml:"discovery_fallback" cli:"discovery-fallback"` + DiscoverySRV *string `yaml:"discovery_srv" cli:"discovery-srv"` + DiscoveryProxy *string `yaml:"discovery_proxy" cli:"discovery-proxy"` + ElectionTimeout *int `yaml:"election_timeout" cli:"election-timeout"` + EnablePprof *bool `yaml:"enable_pprof" cli:"enable-pprof"` + ForceNewCluster *bool `yaml:"force_new_cluster" cli:"force-new-cluster"` + HeartbeatInterval *int `yaml:"heartbeat_interval" cli:"heartbeat-interval"` + InitialAdvertisePeerURLs *string `yaml:"initial_advertise_peer_urls" cli:"initial-advertise-peer-urls"` + InitialCluster *string `yaml:"initial_cluster" cli:"initial-cluster"` + InitialClusterState *string `yaml:"initial_cluster_state" cli:"initial-cluster-state"` + InitialClusterToken *string `yaml:"initial_cluster_token" cli:"initial-cluster-token"` + KeyFile *string `yaml:"key_file" cli:"key-file"` + ListenClientURLs *string `yaml:"listen_client_urls" cli:"listen-client-urls"` + ListenPeerURLs *string `yaml:"listen_peer_urls" cli:"listen-peer-urls"` + LogPackageLevels *string `yaml:"log_package_levels" cli:"log-package-levels"` + MaxSnapshots *int `yaml:"max_snapshots" cli:"max-snapshots"` + MaxWALs *int `yaml:"max_wals" cli:"max-wals"` + Name *string `yaml:"name" cli:"name"` + PeerCAFile *string `yaml:"peer_ca_file" cli:"peer-ca-file" deprecated:"peer_ca_file obsoleted peer_trusted_ca_file and peer_client_cert_auth"` + PeerCertFile *string `yaml:"peer_cert_file" cli:"peer-cert-file"` + PeerKeyFile *string `yaml:"peer_key_file" cli:"peer-key-file"` + PeerClientCertAuth *bool `yaml:"peer_client_cert_auth" cli:"peer-client-cert-auth"` + PeerTrustedCAFile *string `yaml:"peer_trusted_ca_file" cli:"peer-trusted-ca-file"` + Proxy *string `yaml:"proxy" cli:"proxy" valid:"^(on|off|readonly)$"` + ProxyDialTimeout *int `yaml:"proxy_dial_timeout" cli:"proxy-dial-timeout"` + ProxyFailureWait *int `yaml:"proxy_failure_wait" cli:"proxy-failure-wait"` + ProxyReadTimeout *int `yaml:"proxy_read_timeout" cli:"proxy-read-timeout"` + ProxyRefreshInterval *int `yaml:"proxy_refresh_interval" cli:"proxy-refresh-interval"` + ProxyWriteTimeout *int `yaml:"proxy_write_timeout" cli:"proxy-write-timeout"` + SnapshotCount *int `yaml:"snapshot_count" cli:"snapshot-count"` + StrictReconfigCheck *bool `yaml:"strict_reconfig_check" cli:"strict-reconfig-check"` + TrustedCAFile *string `yaml:"trusted_ca_file" cli:"trusted-ca-file"` + WalDir *string `yaml:"wal_dir" cli:"wal-dir"` } diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/files.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/files.go index 6a1c13aa..f3356677 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 @@ -15,16 +15,32 @@ package types import ( + "errors" + "flag" + "fmt" + "io/ioutil" "net/url" + "path" "github.com/coreos/container-linux-config-transpiler/config/astyaml" + "github.com/coreos/container-linux-config-transpiler/internal/util" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" "github.com/vincent-petithory/dataurl" ) +var ( + DefaultFileMode = 0644 + DefaultDirMode = 0755 + + WarningUnsetFileMode = fmt.Errorf("mode unspecified for file, defaulting to %#o", DefaultFileMode) + WarningUnsetDirMode = fmt.Errorf("mode unspecified for directory, defaulting to %#o", DefaultDirMode) + + ErrTooManyFileSources = errors.New("only one of the following can be set: local, inline, remote.url") +) + type FileUser struct { Id *int `yaml:"id"` Name string `yaml:"name"` @@ -38,15 +54,18 @@ type FileGroup struct { type File struct { Filesystem string `yaml:"filesystem"` Path string `yaml:"path"` - User FileUser `yaml:"user"` - Group FileGroup `yaml:"group"` - Mode int `yaml:"mode"` + User *FileUser `yaml:"user"` + Group *FileGroup `yaml:"group"` + Mode *int `yaml:"mode"` Contents FileContents `yaml:"contents"` + Overwrite *bool `yaml:"overwrite"` + Append bool `yaml:"append"` } type FileContents struct { Remote Remote `yaml:"remote"` Inline string `yaml:"inline"` + Local string `yaml:"local"` } type Remote struct { @@ -56,45 +75,87 @@ type Remote struct { } type Directory struct { - Filesystem string `yaml:"filesystem"` - Path string `yaml:"path"` - User FileUser `yaml:"user"` - Group FileGroup `yaml:"group"` - Mode int `yaml:"mode"` + Filesystem string `yaml:"filesystem"` + Path string `yaml:"path"` + User *FileUser `yaml:"user"` + Group *FileGroup `yaml:"group"` + Mode *int `yaml:"mode"` + Overwrite *bool `yaml:"overwrite"` } type Link struct { - Filesystem string `yaml:"filesystem"` - Path string `yaml:"path"` - User FileUser `yaml:"user"` - Group FileGroup `yaml:"group"` - Hard bool `yaml:"hard"` - Target string `yaml:"target"` + Filesystem string `yaml:"filesystem"` + Path string `yaml:"path"` + User *FileUser `yaml:"user"` + Group *FileGroup `yaml:"group"` + Hard bool `yaml:"hard"` + Target string `yaml:"target"` + Overwrite *bool `yaml:"overwrite"` +} + +func (f File) ValidateMode() report.Report { + if f.Mode == nil { + return report.ReportFromError(WarningUnsetFileMode, report.EntryWarning) + } + return report.Report{} +} + +func (d Directory) ValidateMode() report.Report { + if d.Mode == nil { + return report.ReportFromError(WarningUnsetDirMode, report.EntryWarning) + } + return report.Report{} +} + +func (fc FileContents) Validate() report.Report { + i := 0 + if fc.Remote.Url != "" { + i++ + } + if fc.Inline != "" { + i++ + } + if fc.Local != "" { + i++ + } + if i > 1 { + return report.ReportFromError(ErrTooManyFileSources, report.EntryError) + } + return report.Report{} } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { r := report.Report{} files_node, _ := getNodeChildPath(ast, "storage", "files") for i, file := range in.Storage.Files { + if file.Mode == nil { + file.Mode = util.IntToPtr(DefaultFileMode) + } file_node, _ := getNodeChild(files_node, i) newFile := ignTypes.File{ Node: ignTypes.Node{ Filesystem: file.Filesystem, Path: file.Path, - User: ignTypes.NodeUser{ - ID: file.User.Id, - Name: file.User.Name, - }, - Group: ignTypes.NodeGroup{ - ID: file.Group.Id, - Name: file.Group.Name, - }, + Overwrite: file.Overwrite, }, FileEmbedded1: ignTypes.FileEmbedded1{ - Mode: file.Mode, + Mode: file.Mode, + Append: file.Append, }, } + if file.User != nil { + newFile.User = &ignTypes.NodeUser{ + ID: file.User.Id, + Name: file.User.Name, + } + } + if file.Group != nil { + newFile.Group = &ignTypes.NodeGroup{ + ID: file.Group.Id, + Name: file.Group.Name, + } + } if file.Contents.Inline != "" { newFile.Contents = ignTypes.FileContents{ @@ -105,6 +166,42 @@ func init() { } } + if file.Contents.Local != "" { + // The provided local file path is relative to the value of the + // --files-dir flag. + filesDir := flag.Lookup("files-dir") + if filesDir == nil || filesDir.Value.String() == "" { + err := errors.New("local files require setting the --files-dir flag to the directory that contains the file") + flagReport := report.ReportFromError(err, report.EntryError) + if n, err := getNodeChildPath(file_node, "contents", "local"); err == nil { + line, col, _ := n.ValueLineCol(nil) + flagReport.AddPosition(line, col, "") + } + r.Merge(flagReport) + continue + } + localPath := path.Join(filesDir.Value.String(), file.Contents.Local) + contents, err := ioutil.ReadFile(localPath) + if err != nil { + // If the file could not be read, record error and continue. + convertReport := report.ReportFromError(err, report.EntryError) + if n, err := getNodeChildPath(file_node, "contents", "local"); err == nil { + line, col, _ := n.ValueLineCol(nil) + convertReport.AddPosition(line, col, "") + } + r.Merge(convertReport) + continue + } + + // Include the contents of the local file as if it were provided inline. + newFile.Contents = ignTypes.FileContents{ + Source: (&url.URL{ + Scheme: "data", + Opaque: "," + dataurl.Escape(contents), + }).String(), + } + } + if file.Contents.Remote.Url != "" { source, err := url.Parse(file.Contents.Remote.Url) if err != nil { @@ -114,6 +211,7 @@ func init() { line, col, _ := n.ValueLineCol(nil) convertReport.AddPosition(line, col, "") } + r.Merge(convertReport) continue } @@ -145,43 +243,58 @@ func init() { out.Storage.Files = append(out.Storage.Files, newFile) } for _, dir := range in.Storage.Directories { - out.Storage.Directories = append(out.Storage.Directories, ignTypes.Directory{ + if dir.Mode == nil { + dir.Mode = util.IntToPtr(DefaultDirMode) + } + newDir := ignTypes.Directory{ Node: ignTypes.Node{ Filesystem: dir.Filesystem, Path: dir.Path, - User: ignTypes.NodeUser{ - ID: dir.User.Id, - Name: dir.User.Name, - }, - Group: ignTypes.NodeGroup{ - ID: dir.Group.Id, - Name: dir.Group.Name, - }, + Overwrite: dir.Overwrite, }, DirectoryEmbedded1: ignTypes.DirectoryEmbedded1{ Mode: dir.Mode, }, - }) + } + if dir.User != nil { + newDir.User = &ignTypes.NodeUser{ + ID: dir.User.Id, + Name: dir.User.Name, + } + } + if dir.Group != nil { + newDir.Group = &ignTypes.NodeGroup{ + ID: dir.Group.Id, + Name: dir.Group.Name, + } + } + out.Storage.Directories = append(out.Storage.Directories, newDir) } for _, link := range in.Storage.Links { - out.Storage.Links = append(out.Storage.Links, ignTypes.Link{ + newLink := ignTypes.Link{ Node: ignTypes.Node{ Filesystem: link.Filesystem, Path: link.Path, - User: ignTypes.NodeUser{ - ID: link.User.Id, - Name: link.User.Name, - }, - Group: ignTypes.NodeGroup{ - ID: link.Group.Id, - Name: link.Group.Name, - }, + Overwrite: link.Overwrite, }, LinkEmbedded1: ignTypes.LinkEmbedded1{ Hard: link.Hard, Target: link.Target, }, - }) + } + if link.User != nil { + newLink.User = &ignTypes.NodeUser{ + ID: link.User.Id, + Name: link.User.Name, + } + } + if link.Group != nil { + newLink.Group = &ignTypes.NodeGroup{ + ID: link.Group.Id, + Name: link.Group.Name, + } + } + out.Storage.Links = append(out.Storage.Links, newLink) } 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 ddc4ebf7..73dd465f 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 @@ -15,7 +15,7 @@ package types import ( - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -42,7 +42,7 @@ type Create struct { } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { r := report.Report{} for _, filesystem := range in.Storage.Filesystems { newFilesystem := ignTypes.Filesystem{ 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 2dc26dbc..31abc9af 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 @@ -6,7 +6,7 @@ import ( "fmt" "github.com/coreos/go-semver/semver" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -71,7 +71,7 @@ func (fv FlannelVersion) String() string { func (f *Flannel) Validate() report.Report { switch o := f.Options.(type) { case Flannel0_7: - if o.KubeSubnetMgr && f.NetworkConfig != "" { + if o.KubeSubnetMgr != nil && *o.KubeSubnetMgr && f.NetworkConfig != "" { return report.ReportFromError(ErrNetConfigProvidedAndKubeMgrSet, report.EntryError) } } @@ -115,7 +115,7 @@ func (flannel *Flannel) UnmarshalYAML(unmarshal func(interface{}) error) error { } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { if in.Flannel != nil { contents, err := flannelContents(*in.Flannel, platform) if err != nil { @@ -124,7 +124,7 @@ func init() { out.Systemd.Units = append(out.Systemd.Units, ignTypes.Unit{ Name: "flanneld.service", Enable: true, - Dropins: []ignTypes.Dropin{{ + Dropins: []ignTypes.SystemdDropin{{ Name: "20-clct-flannel.conf", Contents: contents, }}, @@ -149,10 +149,10 @@ func flannelContents(flannel Flannel, platform string) (string, error) { if flannel.NetworkConfig != "" { pre := "ExecStartPre=/usr/bin/etcdctl" - var endpoints string - var etcdCAFile string - var etcdCertFile string - var etcdKeyFile string + var endpoints *string + var etcdCAFile *string + var etcdCertFile *string + var etcdKeyFile *string switch o := flannel.Options.(type) { case Flannel0_7: endpoints = o.EtcdEndpoints @@ -170,17 +170,17 @@ func flannelContents(flannel Flannel, platform string) (string, error) { etcdCertFile = o.EtcdCertFile etcdKeyFile = o.EtcdKeyFile } - if endpoints != "" { - pre += fmt.Sprintf(" --endpoints=%q", endpoints) + if endpoints != nil { + pre += fmt.Sprintf(" --endpoints=%q", *endpoints) } - if etcdCAFile != "" { - pre += fmt.Sprintf(" --ca-file=%q", etcdCAFile) + if etcdCAFile != nil { + pre += fmt.Sprintf(" --ca-file=%q", *etcdCAFile) } - if etcdCertFile != "" { - pre += fmt.Sprintf(" --cert-file=%q", etcdCertFile) + if etcdCertFile != nil { + pre += fmt.Sprintf(" --cert-file=%q", *etcdCertFile) } - if etcdKeyFile != "" { - pre += fmt.Sprintf(" --key-file=%q", etcdKeyFile) + if etcdKeyFile != nil { + pre += fmt.Sprintf(" --key-file=%q", *etcdKeyFile) } pre += fmt.Sprintf(" set /coreos.com/network/config %q", flannel.NetworkConfig) unit.Service.Add(pre) @@ -192,42 +192,42 @@ func flannelContents(flannel Flannel, platform string) (string, error) { // Flannel0_7 represents flannel options for version 0.7.x. Don't embed Flannel0_6 because // the yaml parser doesn't handle embedded structs type Flannel0_7 struct { - EtcdUsername string `yaml:"etcd_username" cli:"etcd-username"` - EtcdPassword string `yaml:"etcd_password" cli:"etcd-password"` - EtcdEndpoints string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` - EtcdCAFile string `yaml:"etcd_cafile" cli:"etcd-cafile"` - EtcdCertFile string `yaml:"etcd_certfile" cli:"etcd-certfile"` - EtcdKeyFile string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` - EtcdPrefix string `yaml:"etcd_prefix" cli:"etcd-prefix"` - IPMasq string `yaml:"ip_masq" cli:"ip-masq"` - SubnetFile string `yaml:"subnet_file" cli:"subnet-file"` - Iface string `yaml:"interface" cli:"iface"` - PublicIP string `yaml:"public_ip" cli:"public-ip"` - KubeSubnetMgr bool `yaml:"kube_subnet_mgr" cli:"kube-subnet-mgr"` + EtcdUsername *string `yaml:"etcd_username" cli:"etcd-username"` + EtcdPassword *string `yaml:"etcd_password" cli:"etcd-password"` + EtcdEndpoints *string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` + EtcdCAFile *string `yaml:"etcd_cafile" cli:"etcd-cafile"` + EtcdCertFile *string `yaml:"etcd_certfile" cli:"etcd-certfile"` + EtcdKeyFile *string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` + EtcdPrefix *string `yaml:"etcd_prefix" cli:"etcd-prefix"` + IPMasq *string `yaml:"ip_masq" cli:"ip-masq"` + SubnetFile *string `yaml:"subnet_file" cli:"subnet-file"` + Iface *string `yaml:"interface" cli:"iface"` + PublicIP *string `yaml:"public_ip" cli:"public-ip"` + KubeSubnetMgr *bool `yaml:"kube_subnet_mgr" cli:"kube-subnet-mgr"` } type Flannel0_6 struct { - EtcdUsername string `yaml:"etcd_username" cli:"etcd-username"` - EtcdPassword string `yaml:"etcd_password" cli:"etcd-password"` - EtcdEndpoints string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` - EtcdCAFile string `yaml:"etcd_cafile" cli:"etcd-cafile"` - EtcdCertFile string `yaml:"etcd_certfile" cli:"etcd-certfile"` - EtcdKeyFile string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` - EtcdPrefix string `yaml:"etcd_prefix" cli:"etcd-prefix"` - IPMasq string `yaml:"ip_masq" cli:"ip-masq"` - SubnetFile string `yaml:"subnet_file" cli:"subnet-file"` - Iface string `yaml:"interface" cli:"iface"` - PublicIP string `yaml:"public_ip" cli:"public-ip"` + EtcdUsername *string `yaml:"etcd_username" cli:"etcd-username"` + EtcdPassword *string `yaml:"etcd_password" cli:"etcd-password"` + EtcdEndpoints *string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` + EtcdCAFile *string `yaml:"etcd_cafile" cli:"etcd-cafile"` + EtcdCertFile *string `yaml:"etcd_certfile" cli:"etcd-certfile"` + EtcdKeyFile *string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` + EtcdPrefix *string `yaml:"etcd_prefix" cli:"etcd-prefix"` + IPMasq *string `yaml:"ip_masq" cli:"ip-masq"` + SubnetFile *string `yaml:"subnet_file" cli:"subnet-file"` + Iface *string `yaml:"interface" cli:"iface"` + PublicIP *string `yaml:"public_ip" cli:"public-ip"` } type Flannel0_5 struct { - EtcdEndpoints string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` - EtcdCAFile string `yaml:"etcd_cafile" cli:"etcd-cafile"` - EtcdCertFile string `yaml:"etcd_certfile" cli:"etcd-certfile"` - EtcdKeyFile string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` - EtcdPrefix string `yaml:"etcd_prefix" cli:"etcd-prefix"` - IPMasq string `yaml:"ip_masq" cli:"ip-masq"` - SubnetFile string `yaml:"subnet_file" cli:"subnet-file"` - Iface string `yaml:"interface" cli:"iface"` - PublicIP string `yaml:"public_ip" cli:"public-ip"` + EtcdEndpoints *string `yaml:"etcd_endpoints" cli:"etcd-endpoints"` + EtcdCAFile *string `yaml:"etcd_cafile" cli:"etcd-cafile"` + EtcdCertFile *string `yaml:"etcd_certfile" cli:"etcd-certfile"` + EtcdKeyFile *string `yaml:"etcd_keyfile" cli:"etcd-keyfile"` + EtcdPrefix *string `yaml:"etcd_prefix" cli:"etcd-prefix"` + IPMasq *string `yaml:"ip_masq" cli:"ip-masq"` + SubnetFile *string `yaml:"subnet_file" cli:"subnet-file"` + Iface *string `yaml:"interface" cli:"iface"` + PublicIP *string `yaml:"public_ip" cli:"public-ip"` } diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/locksmith.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/locksmith.go index c289ce01..f701a16f 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 @@ -33,29 +33,36 @@ var ( ) type Locksmith struct { - RebootStrategy string `yaml:"reboot_strategy" locksmith:"REBOOT_STRATEGY"` - WindowStart string `yaml:"window_start" locksmith:"LOCKSMITHD_REBOOT_WINDOW_START"` - WindowLength string `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"` + RebootStrategy *string `yaml:"reboot_strategy" locksmith:"REBOOT_STRATEGY"` + WindowStart *string `yaml:"window_start" locksmith:"LOCKSMITHD_REBOOT_WINDOW_START"` + WindowLength *string `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=%v", "locksmith", l) } +func nilOrEmpty(s *string) bool { + return s == nil || *s == "" +} + func (l Locksmith) Validate() report.Report { - if (l.WindowStart != "" && l.WindowLength == "") || (l.WindowStart == "" && l.WindowLength != "") { + if (!nilOrEmpty(l.WindowStart) && nilOrEmpty(l.WindowLength)) || (nilOrEmpty(l.WindowStart) && !nilOrEmpty(l.WindowLength)) { return report.ReportFromError(ErrMissingStartOrLength, report.EntryError) } return report.Report{} } func (l Locksmith) ValidateRebootStrategy() report.Report { - switch strings.ToLower(l.RebootStrategy) { + if nilOrEmpty(l.RebootStrategy) { + return report.Report{} + } + switch strings.ToLower(*l.RebootStrategy) { case "reboot", "etcd-lock", "off": return report.Report{} default: @@ -64,16 +71,16 @@ func (l Locksmith) ValidateRebootStrategy() report.Report { } func (l Locksmith) ValidateWindowStart() report.Report { - if l.WindowStart == "" { + if nilOrEmpty(l.WindowStart) { return report.Report{} } var day string var t string - _, err := fmt.Sscanf(l.WindowStart, "%s %s", &day, &t) + _, err := fmt.Sscanf(*l.WindowStart, "%s %s", &day, &t) if err != nil { day = "not-present" - t = l.WindowStart + t = *l.WindowStart } switch strings.ToLower(day) { @@ -92,10 +99,10 @@ func (l Locksmith) ValidateWindowStart() report.Report { } func (l Locksmith) ValidateWindowLength() report.Report { - if l.WindowLength == "" { + if nilOrEmpty(l.WindowLength) { return report.Report{} } - _, err := time.ParseDuration(l.WindowLength) + _, err := time.ParseDuration(*l.WindowLength) if err != nil { return report.ReportFromError(ErrParsingLength, report.EntryError) } diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/networkd.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/networkd.go index f77c4260..01490b84 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 @@ -15,7 +15,7 @@ package types import ( - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -25,17 +25,30 @@ type Networkd struct { } type NetworkdUnit struct { + Name string `yaml:"name"` + Contents string `yaml:"contents"` + Dropins []NetworkdUnitDropIn `yaml:"dropins"` +} + +type NetworkdUnitDropIn struct { Name string `yaml:"name"` Contents string `yaml:"contents"` } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { for _, unit := range in.Networkd.Units { - out.Networkd.Units = append(out.Networkd.Units, ignTypes.Networkdunit{ + newUnit := ignTypes.Networkdunit{ Name: unit.Name, Contents: unit.Contents, - }) + } + for _, dropIn := range unit.Dropins { + newUnit.Dropins = append(newUnit.Dropins, ignTypes.NetworkdDropin{ + Name: dropIn.Name, + Contents: dropIn.Contents, + }) + } + out.Networkd.Units = append(out.Networkd.Units, newUnit) } 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 54a68a76..e12cd504 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 @@ -15,7 +15,7 @@ package types import ( - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -63,7 +63,7 @@ type Group struct { } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { for _, user := range in.Passwd.Users { newUser := ignTypes.PasswdUser{ Name: user.Name, @@ -74,7 +74,7 @@ func init() { HomeDir: user.HomeDir, NoCreateHome: user.NoCreateHome, PrimaryGroup: user.PrimaryGroup, - Groups: convertStringSliceIntoTypesPasswdUserGroupSlice(user.Groups), + Groups: convertStringSliceIntoTypesGroupSlice(user.Groups), NoUserGroup: user.NoUserGroup, System: user.System, NoLogInit: user.NoLogInit, @@ -130,10 +130,10 @@ func convertStringSliceIntoTypesUsercreateGroupSlice(ss []string) []ignTypes.Use } // golang-- -func convertStringSliceIntoTypesPasswdUserGroupSlice(ss []string) []ignTypes.PasswdUserGroup { - var res []ignTypes.PasswdUserGroup +func convertStringSliceIntoTypesGroupSlice(ss []string) []ignTypes.Group { + var res []ignTypes.Group for _, s := range ss { - res = append(res, ignTypes.PasswdUserGroup(s)) + res = append(res, ignTypes.Group(s)) } return res } 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 d4fa6cd3..014ee9dd 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 @@ -15,7 +15,7 @@ package types import ( - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -25,16 +25,18 @@ type Raid struct { Level string `yaml:"level"` Devices []string `yaml:"devices"` Spares int `yaml:"spares"` + Options []string `yaml:"options"` } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { for _, array := range in.Storage.Arrays { newArray := ignTypes.Raid{ Name: array.Name, Level: array.Level, Spares: array.Spares, Devices: convertStringSliceToTypesDeviceSlice(array.Devices), + Options: convertStringSiceToTypesRaidOptionSlice(array.Options), } out.Storage.Raid = append(out.Storage.Raid, newArray) @@ -51,3 +53,12 @@ func convertStringSliceToTypesDeviceSlice(ss []string) []ignTypes.Device { } return res } + +// golang-- +func convertStringSiceToTypesRaidOptionSlice(ss []string) []ignTypes.RaidOption { + var res []ignTypes.RaidOption + for _, s := range ss { + res = append(res, ignTypes.RaidOption(s)) + } + return res +} diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/config/types/security.go b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/security.go new file mode 100644 index 00000000..6e831532 --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/config/types/security.go @@ -0,0 +1,46 @@ +// Copyright 2018 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + ignTypes "github.com/coreos/ignition/config/v2_2/types" + "github.com/coreos/ignition/config/validate/astnode" + "github.com/coreos/ignition/config/validate/report" +) + +type Security struct { + TLS TLS `yaml:"tls"` +} + +type TLS struct { + CertificateAuthorities []CaReference `yaml:"certificate_authorities"` +} + +type CaReference struct { + Source string `yaml:"source"` + Verification Verification `yaml:"verification"` +} + +func init() { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + for _, ca := range in.Ignition.Security.TLS.CertificateAuthorities { + out.Ignition.Security.TLS.CertificateAuthorities = append(out.Ignition.Security.TLS.CertificateAuthorities, ignTypes.CaReference{ + Source: ca.Source, + Verification: convertVerification(ca.Verification), + }) + } + 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 3a6921cc..42e054b0 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 @@ -15,7 +15,7 @@ package types import ( - ignTypes "github.com/coreos/ignition/config/v2_1/types" + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -39,7 +39,7 @@ type SystemdUnitDropIn struct { } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { for _, unit := range in.Systemd.Units { newUnit := ignTypes.Unit{ Name: unit.Name, @@ -50,7 +50,7 @@ func init() { } for _, dropIn := range unit.Dropins { - newUnit.Dropins = append(newUnit.Dropins, ignTypes.Dropin{ + newUnit.Dropins = append(newUnit.Dropins, ignTypes.SystemdDropin{ Name: dropIn.Name, Contents: dropIn.Contents, }) 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 1dded416..ae65490b 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 @@ -20,7 +20,9 @@ import ( "net/url" "strings" - ignTypes "github.com/coreos/ignition/config/v2_1/types" + "github.com/coreos/container-linux-config-transpiler/internal/util" + + ignTypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" "github.com/vincent-petithory/dataurl" @@ -59,7 +61,7 @@ func (s UpdateServer) Validate() report.Report { } func init() { - register2_0(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { + register(func(in Config, ast astnode.AstNode, out ignTypes.Config, platform string) (ignTypes.Config, report.Report, astnode.AstNode) { var contents string if in.Update != nil { if in.Update.Group != "" { @@ -82,7 +84,7 @@ func init() { Path: "/etc/coreos/update.conf", }, FileEmbedded1: ignTypes.FileEmbedded1{ - Mode: 0644, + Mode: util.IntToPtr(0644), Contents: ignTypes.FileContents{ Source: (&url.URL{ Scheme: "data", diff --git a/vendor/github.com/coreos/container-linux-config-transpiler/internal/util/type_casts.go b/vendor/github.com/coreos/container-linux-config-transpiler/internal/util/type_casts.go new file mode 100644 index 00000000..126e252f --- /dev/null +++ b/vendor/github.com/coreos/container-linux-config-transpiler/internal/util/type_casts.go @@ -0,0 +1,27 @@ +// 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 util + +func IntToPtr(i int) *int { + return &i +} + +func BoolToPtr(b bool) *bool { + return &b +} + +func StringToPtr(s string) *string { + return &s +} diff --git a/vendor/github.com/coreos/ignition/config/append.go b/vendor/github.com/coreos/ignition/config/append.go deleted file mode 100644 index c66a1223..00000000 --- a/vendor/github.com/coreos/ignition/config/append.go +++ /dev/null @@ -1,72 +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 ( - "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/config.go b/vendor/github.com/coreos/ignition/config/config.go deleted file mode 100644 index 229c0ab8..00000000 --- a/vendor/github.com/coreos/ignition/config/config.go +++ /dev/null @@ -1,215 +0,0 @@ -// 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 config - -import ( - "bytes" - "errors" - "reflect" - - "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") - 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) { - 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 - } - - version, err := Version(rawConfig) - if err != nil && err != ErrVersionIndeterminable { - // If we can't determine the version, its probably invalid json and we want to fall through - // to handle that in ParseFromLatest, since it will generate the highlight string and report - // line and column. - 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.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: - // It's not empty, it's not a cloud config, and it's not a script, but - // we can't determine the version of it (or it's 0.0.0, hooray golang - // zero values). We know it's not valid, but try to parse it anyway with - // ParseFromLatest to generate any parse errors. - config, rep, err := ParseFromLatest(rawConfig) - if err != nil || rep.IsFatal() { - return config, rep, err - } - // Somehow parsing succeeded without any errors or fatal reports. This - // should be an impossible state, but since we're in this part of the - // switch statement we know at the very least the version is invalid, so - // return that. - return types.Config{}, report.Report{}, ErrUnknownVersion - } -} - -func ParseFromLatest(rawConfig []byte) (types.Config, report.Report, error) { - 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 ParseFromV1(rawConfig []byte) (types.Config, error) { - config, err := v1.Parse(rawConfig) - if err != nil { - return types.Config{}, err - } - - return TranslateFromV1(config), nil -} - -func ParseFromV2_0(rawConfig []byte) (types.Config, report.Report, error) { - cfg, report, err := v2_0.Parse(rawConfig) - if err != nil { - return types.Config{}, report, err - } - - return TranslateFromV2_0(cfg), report, err -} - -func 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 *string `json:"version"` - } `json:"ignition"` - } - - if json.Unmarshal(rawConfig, &composite) == nil { - if composite.Ignition.Version != nil { - 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 semver.Version{Major: int64(*composite.Version)}, nil - } - } - - return semver.Version{}, ErrVersionIndeterminable -} - -func isEmpty(userdata []byte) bool { - return len(userdata) == 0 -} diff --git a/vendor/github.com/coreos/ignition/config/shared/errors/errors.go b/vendor/github.com/coreos/ignition/config/shared/errors/errors.go new file mode 100644 index 00000000..81e85762 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/shared/errors/errors.go @@ -0,0 +1,106 @@ +// Copyright 2018 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 errors includes errors that are used in multiple config versions +package errors + +import ( + "errors" + "fmt" +) + +var ( + // Parsing / general errors + ErrInvalid = errors.New("config is not valid") + ErrCloudConfig = errors.New("not a config (found coreos-cloudconfig)") + ErrEmpty = errors.New("not a config (empty)") + ErrUnknownVersion = errors.New("unsupported config version") + ErrScript = errors.New("not a config (found coreos-cloudinit script)") + ErrDeprecated = errors.New("config format deprecated") + ErrCompressionInvalid = errors.New("invalid compression method") + + // Ignition section errors + 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)") + + // Storage section errors + ErrPermissionsUnset = errors.New("permissions unset, defaulting to 0000") + ErrDiskDeviceRequired = errors.New("disk device is required") + ErrPartitionNumbersCollide = errors.New("partition numbers collide") + ErrPartitionsOverlap = errors.New("partitions overlap") + ErrPartitionsMisaligned = errors.New("partitions misaligned") + ErrAppendAndOverwrite = errors.New("cannot set both append and overwrite to true") + 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") + ErrFileIllegalMode = errors.New("illegal file mode") + ErrNoFilesystem = errors.New("no filesystem specified") + ErrBothIDAndNameSet = errors.New("cannot set both id and name") + ErrLabelTooLong = errors.New("partition labels may not exceed 36 characters") + ErrDoesntMatchGUIDRegex = errors.New("doesn't match the form \"01234567-89AB-CDEF-EDCB-A98765432101\"") + ErrLabelContainsColon = errors.New("partition label will be truncated to text before the colon") + ErrPathRelative = errors.New("path not absolute") + ErrSparesUnsupportedForLevel = errors.New("spares unsupported for arrays with a level greater than 0") + ErrUnrecognizedRaidLevel = errors.New("unrecognized raid level") + ErrShouldNotExistWithOthers = errors.New("shouldExist specified false with other options also specified") + ErrZeroesWithShouldNotExist = errors.New("shouldExist is false for a partition and other partition(s) has start or size 0") + ErrPartitionsUnitsMismatch = errors.New("cannot mix MBs and sectors within a disk") + ErrSizeDeprecated = errors.New("size is deprecated; use sizeMB instead") + ErrStartDeprecated = errors.New("start is deprecated; use startMB instead") + + // Passwd section errors + 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") + + // Systemd and Networkd section errors + ErrInvalidSystemdExt = errors.New("invalid systemd unit extension") + ErrInvalidSystemdDropinExt = errors.New("invalid systemd drop-in extension") + ErrInvalidNetworkdExt = errors.New("invalid networkd unit extension") + ErrInvalidNetworkdDropinExt = errors.New("invalid networkd drop-in extension") + + // Misc errors + ErrInvalidScheme = errors.New("invalid url scheme") + ErrInvalidUrl = errors.New("unable to parse url") + ErrHashMalformed = errors.New("malformed hash specifier") + ErrHashWrongSize = errors.New("incorrect size for hash sum") + ErrHashUnrecognized = errors.New("unrecognized hash function") + ErrEngineConfiguration = errors.New("engine incorrectly configured") + + // AWS S3 specific errors + ErrInvalidS3ObjectVersionId = errors.New("invalid S3 object VersionId") +) + +// NewNoInstallSectionError produces an error indicating the given unit, named +// name, is missing an Install section. +func NewNoInstallSectionError(name string) error { + return fmt.Errorf("unit %q is enabled, but has no install section so enable does nothing", name) +} diff --git a/vendor/github.com/coreos/ignition/config/shared/validations/unit.go b/vendor/github.com/coreos/ignition/config/shared/validations/unit.go new file mode 100644 index 00000000..2924fac8 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/shared/validations/unit.go @@ -0,0 +1,54 @@ +// Copyright 2018 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 validations contains validations shared between multiple config +// versions. +package validations + +import ( + "github.com/coreos/go-systemd/unit" + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +// ValidateInstallSection is a helper to validate a given unit +func ValidateInstallSection(name string, enabled bool, contentsEmpty bool, contentSections []*unit.UnitOption) report.Report { + if !enabled { + // install sections don't matter for not-enabled units + return report.Report{} + } + if contentsEmpty { + // install sections don't matter if it has no contents, e.g. it's being masked or just has dropins or such + return report.Report{} + } + if contentSections == nil { + // Should only happen if the unit could not be parsed, at which point an + // error is probably already in the report so we don't need to double-up on + // errors + warnings. + return report.Report{} + } + + for _, section := range contentSections { + if section.Section == "Install" { + return report.Report{} + } + } + + return report.Report{ + Entries: []report.Entry{{ + Message: errors.NewNoInstallSectionError(name).Error(), + Kind: report.EntryWarning, + }}, + } +} diff --git a/vendor/github.com/coreos/ignition/config/translate.go b/vendor/github.com/coreos/ignition/config/translate.go deleted file mode 100644 index a5eb9bc2..00000000 --- a/vendor/github.com/coreos/ignition/config/translate.go +++ /dev/null @@ -1,734 +0,0 @@ -// Copyright 2016 CoreOS, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package config - -import ( - "fmt" - "net/url" - "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: v2_0.MaxVersion.String(), - }, - } - - for _, oldDisk := range old.Storage.Disks { - disk := types.Disk{ - Device: string(oldDisk.Device), - WipeTable: oldDisk.WipeTable, - } - - for _, oldPartition := range oldDisk.Partitions { - disk.Partitions = append(disk.Partitions, types.Partition{ - Label: string(oldPartition.Label), - Number: oldPartition.Number, - Size: int(oldPartition.Size), - Start: int(oldPartition.Start), - TypeGUID: string(oldPartition.TypeGUID), - }) - } - - config.Storage.Disks = append(config.Storage.Disks, disk) - } - - for _, oldArray := range old.Storage.Arrays { - array := types.Raid{ - Name: oldArray.Name, - Level: oldArray.Level, - Spares: oldArray.Spares, - } - - for _, oldDevice := range oldArray.Devices { - array.Devices = append(array.Devices, types.Device(oldDevice)) - } - - 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.Mount{ - Device: string(oldFilesystem.Device), - Format: string(oldFilesystem.Format), - }, - } - - if oldFilesystem.Create != nil { - filesystem.Mount.Create = &types.Create{ - Force: oldFilesystem.Create.Force, - Options: translateV1MkfsOptionsToV2_2OptionSlice(oldFilesystem.Create.Options), - } - } - - config.Storage.Filesystems = append(config.Storage.Filesystems, filesystem) - - for _, oldFile := range oldFilesystem.Files { - file := types.File{ - Node: types.Node{ - Filesystem: filesystem.Name, - Path: string(oldFile.Path), - User: types.NodeUser{ID: intToPtr(oldFile.Uid)}, - Group: types.NodeGroup{ID: intToPtr(oldFile.Gid)}, - }, - FileEmbedded1: types.FileEmbedded1{ - Mode: int(oldFile.Mode), - Contents: types.FileContents{ - Source: (&url.URL{ - Scheme: "data", - Opaque: "," + dataurl.EscapeString(oldFile.Contents), - }).String(), - }, - }, - } - - config.Storage.Files = append(config.Storage.Files, file) - } - } - - for _, oldUnit := range old.Systemd.Units { - 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.Dropin{ - Name: string(oldDropIn.Name), - Contents: oldDropIn.Contents, - }) - } - - config.Systemd.Units = append(config.Systemd.Units, unit) - } - - for _, oldUnit := range old.Networkd.Units { - config.Networkd.Units = append(config.Networkd.Units, types.Networkdunit{ - Name: string(oldUnit.Name), - Contents: oldUnit.Contents, - }) - } - - for _, oldUser := range old.Passwd.Users { - user := types.PasswdUser{ - Name: oldUser.Name, - PasswordHash: strToPtr(oldUser.PasswordHash), - SSHAuthorizedKeys: translateStringSliceToV2_2SSHAuthorizedKeySlice(oldUser.SSHAuthorizedKeys), - } - - if oldUser.Create != nil { - 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: translateStringSliceToV2_2UsercreateGroupSlice(oldUser.Create.Groups), - NoUserGroup: oldUser.Create.NoUserGroup, - System: oldUser.Create.System, - NoLogInit: oldUser.Create.NoLogInit, - Shell: oldUser.Create.Shell, - } - } - - config.Passwd.Users = append(config.Passwd.Users, user) - } - - for _, oldGroup := range old.Passwd.Groups { - 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: gid, - PasswordHash: oldGroup.PasswordHash, - System: oldGroup.System, - }) - } - - 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 { - // .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: old.Source.String(), - Verification: translateVerification(old.Verification), - } - } - - config := types.Config{ - Ignition: types.Ignition{ - Version: types.MaxVersion.String(), - }, - } - - if old.Ignition.Config.Replace != nil { - ref := translateConfigReference(*old.Ignition.Config.Replace) - config.Ignition.Config.Replace = &ref - } - - for _, oldAppend := range old.Ignition.Config.Append { - config.Ignition.Config.Append = - append(config.Ignition.Config.Append, translateConfigReference(oldAppend)) - } - - for _, oldDisk := range old.Storage.Disks { - disk := types.Disk{ - Device: string(oldDisk.Device), - WipeTable: oldDisk.WipeTable, - } - - for _, oldPartition := range oldDisk.Partitions { - disk.Partitions = append(disk.Partitions, types.Partition{ - Label: string(oldPartition.Label), - Number: oldPartition.Number, - Size: int(oldPartition.Size), - Start: int(oldPartition.Start), - TypeGUID: string(oldPartition.TypeGUID), - }) - } - - config.Storage.Disks = append(config.Storage.Disks, disk) - } - - for _, oldArray := range old.Storage.Arrays { - array := types.Raid{ - Name: oldArray.Name, - Level: oldArray.Level, - Spares: oldArray.Spares, - } - - for _, oldDevice := range oldArray.Devices { - array.Devices = append(array.Devices, types.Device(oldDevice)) - } - - config.Storage.Raid = append(config.Storage.Raid, array) - } - - for _, oldFilesystem := range old.Storage.Filesystems { - filesystem := types.Filesystem{ - Name: oldFilesystem.Name, - } - - if oldFilesystem.Mount != nil { - filesystem.Mount = &types.Mount{ - Device: string(oldFilesystem.Mount.Device), - Format: string(oldFilesystem.Mount.Format), - } - - if oldFilesystem.Mount.Create != nil { - filesystem.Mount.Create = &types.Create{ - Force: oldFilesystem.Mount.Create.Force, - Options: translateV2_0MkfsOptionsToV2_2OptionSlice(oldFilesystem.Mount.Create.Options), - } - } - } - - if oldFilesystem.Path != nil { - p := string(*oldFilesystem.Path) - filesystem.Path = &p - } - - config.Storage.Filesystems = append(config.Storage.Filesystems, filesystem) - } - - for _, oldFile := range old.Storage.Files { - file := types.File{ - Node: types.Node{ - Filesystem: oldFile.Filesystem, - Path: string(oldFile.Path), - User: types.NodeUser{ID: intToPtr(oldFile.User.Id)}, - Group: types.NodeGroup{ID: intToPtr(oldFile.Group.Id)}, - }, - 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), - }, - }, - } - - config.Storage.Files = append(config.Storage.Files, file) - } - - for _, oldUnit := range old.Systemd.Units { - 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.Dropin{ - Name: string(oldDropIn.Name), - Contents: oldDropIn.Contents, - }) - } - - config.Systemd.Units = append(config.Systemd.Units, unit) - } - - for _, oldUnit := range old.Networkd.Units { - config.Networkd.Units = append(config.Networkd.Units, types.Networkdunit{ - Name: string(oldUnit.Name), - Contents: oldUnit.Contents, - }) - } - - for _, oldUser := range old.Passwd.Users { - user := types.PasswdUser{ - Name: oldUser.Name, - PasswordHash: strToPtr(oldUser.PasswordHash), - SSHAuthorizedKeys: translateStringSliceToV2_2SSHAuthorizedKeySlice(oldUser.SSHAuthorizedKeys), - } - - if oldUser.Create != nil { - 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: translateStringSliceToV2_2UsercreateGroupSlice(oldUser.Create.Groups), - NoUserGroup: oldUser.Create.NoUserGroup, - System: oldUser.Create.System, - NoLogInit: oldUser.Create.NoLogInit, - Shell: oldUser.Create.Shell, - } - } - - config.Passwd.Users = append(config.Passwd.Users, user) - } - - for _, oldGroup := range old.Passwd.Groups { - 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: g, - PasswordHash: oldGroup.PasswordHash, - System: oldGroup.System, - }) - } - - 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/passwd.go b/vendor/github.com/coreos/ignition/config/types/passwd.go deleted file mode 100644 index 5f7d9641..00000000 --- a/vendor/github.com/coreos/ignition/config/types/passwd.go +++ /dev/null @@ -1,82 +0,0 @@ -// 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/util/helpers.go b/vendor/github.com/coreos/ignition/config/util/helpers.go new file mode 100644 index 00000000..7d55548f --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/util/helpers.go @@ -0,0 +1,34 @@ +// Copyright 2018 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 + +func IntToPtr(x int) *int { + return &x +} + +func StrToPtr(s string) *string { + if s == "" { + return nil + } + return &s +} + +func StrToPtrStrict(s string) *string { + return &s +} + +func BoolToPtr(b bool) *bool { + return &b +} diff --git a/vendor/github.com/coreos/ignition/config/util/parsingErrors.go b/vendor/github.com/coreos/ignition/config/util/parsingErrors.go new file mode 100644 index 00000000..aee77826 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/util/parsingErrors.go @@ -0,0 +1,74 @@ +// Copyright 2018 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 + +import ( + "bytes" + "errors" + + configErrors "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/v2_4_experimental/types" + "github.com/coreos/ignition/config/validate/report" + + json "github.com/ajeddeloh/go-json" + "go4.org/errorutil" +) + +var ( + ErrValidConfig = errors.New("HandleParseErrors called with a valid config") +) + +// HandleParseErrors will attempt to unmarshal an invalid rawConfig into the +// latest config struct, so as to generate a report.Report from the errors. It +// will always return an error. This is called after config/v* parse functions +// chain has failed to parse a config. +func HandleParseErrors(rawConfig []byte) (report.Report, error) { + config := types.Config{} + err := json.Unmarshal(rawConfig, &config) + if err == nil { + return report.Report{}, ErrValidConfig + } + + // 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 report.Report{ + Entries: []report.Entry{{ + Kind: report.EntryError, + Message: serr.Error(), + Line: line, + Column: col, + Highlight: highlight, + }}, + }, + configErrors.ErrInvalid + } + + if terr, ok := err.(*json.UnmarshalTypeError); ok { + line, col, highlight := errorutil.HighlightBytePosition(bytes.NewReader(rawConfig), terr.Offset) + return report.Report{ + Entries: []report.Entry{{ + Kind: report.EntryError, + Message: terr.Error(), + Line: line, + Column: col, + Highlight: highlight, + }}, + }, + configErrors.ErrInvalid + } + + return report.ReportFromError(err, report.EntryError), err +} diff --git a/vendor/github.com/coreos/ignition/config/v1/config.go b/vendor/github.com/coreos/ignition/config/v1/config.go index e7f889bb..21e79f81 100644 --- a/vendor/github.com/coreos/ignition/config/v1/config.go +++ b/vendor/github.com/coreos/ignition/config/v1/config.go @@ -15,41 +15,43 @@ package v1 import ( - "bytes" - "encoding/json" - "errors" - "fmt" - + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/util" "github.com/coreos/ignition/config/v1/types" + "github.com/coreos/ignition/config/validate" + "github.com/coreos/ignition/config/validate/report" - "go4.org/errorutil" + json "github.com/ajeddeloh/go-json" ) -var ( - ErrVersion = errors.New("incorrect config version") - 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)") -) - -func Parse(rawConfig []byte) (config types.Config, err error) { - if err = json.Unmarshal(rawConfig, &config); err == nil { - if config.Version != types.Version { - err = ErrVersion - } - } else if isEmpty(rawConfig) { - err = ErrEmpty +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if isEmpty(rawConfig) { + return types.Config{}, report.Report{}, errors.ErrEmpty } else if isCloudConfig(rawConfig) { - err = ErrCloudConfig + return types.Config{}, report.Report{}, errors.ErrCloudConfig } else if isScript(rawConfig) { - err = ErrScript - } - if serr, ok := err.(*json.SyntaxError); ok { - line, col, highlight := errorutil.HighlightBytePosition(bytes.NewReader(rawConfig), serr.Offset) - err = fmt.Errorf("error at line %d, column %d\n%s%v", line, col, highlight, err) + return types.Config{}, report.Report{}, errors.ErrScript } - return + var err error + var config types.Config + + err = json.Unmarshal(rawConfig, &config) + if err != nil { + rpt, err := util.HandleParseErrors(rawConfig) + // HandleParseErrors always returns an error + return types.Config{}, rpt, err + } + + if config.Version != types.Version { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion + } + + rpt := validate.ValidateConfig(rawConfig, config) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.ErrInvalid + } + return config, rpt, nil } func isEmpty(userdata []byte) bool { diff --git a/vendor/github.com/coreos/ignition/config/v1/types/config.go b/vendor/github.com/coreos/ignition/config/v1/types/config.go index dc5b9395..3a369e4f 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/config.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/config.go @@ -14,14 +14,18 @@ package types -import ( - "reflect" -) +import "github.com/coreos/go-semver/semver" const ( Version = 1 ) +var ( + MaxVersion = semver.Version{ + Major: Version, + } +) + type Config struct { Version int `json:"ignitionVersion"` Storage Storage `json:"storage,omitempty"` @@ -29,45 +33,3 @@ type Config struct { Networkd Networkd `json:"networkd,omitempty"` Passwd Passwd `json:"passwd,omitempty"` } - -func (c Config) AssertValid() error { - return assertStructValid(reflect.ValueOf(c)) -} - -func assertValid(vObj reflect.Value) error { - if !vObj.IsValid() { - return nil - } - - if obj, ok := vObj.Interface().(interface { - AssertValid() error - }); ok && !(vObj.Kind() == reflect.Ptr && vObj.IsNil()) { - if err := obj.AssertValid(); err != nil { - return err - } - } - - switch vObj.Kind() { - case reflect.Ptr: - return assertValid(vObj.Elem()) - case reflect.Struct: - return assertStructValid(vObj) - case reflect.Slice: - for i := 0; i < vObj.Len(); i++ { - if err := assertValid(vObj.Index(i)); err != nil { - return err - } - } - } - - return nil -} - -func assertStructValid(vObj reflect.Value) error { - for i := 0; i < vObj.Type().NumField(); i++ { - if err := assertValid(vObj.Field(i)); err != nil { - return err - } - } - return nil -} diff --git a/vendor/github.com/coreos/ignition/config/v1/types/disk.go b/vendor/github.com/coreos/ignition/config/v1/types/disk.go index f16d13f7..62517856 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/disk.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/disk.go @@ -15,8 +15,8 @@ package types import ( - "encoding/json" - "fmt" + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" ) type Disk struct { @@ -24,32 +24,35 @@ type Disk struct { WipeTable bool `json:"wipeTable,omitempty"` Partitions []Partition `json:"partitions,omitempty"` } -type disk Disk -func (n *Disk) UnmarshalJSON(data []byte) error { - tn := disk(*n) - if err := json.Unmarshal(data, &tn); err != nil { - return err - } - *n = Disk(tn) - return n.AssertValid() -} - -func (n Disk) AssertValid() error { +func (n Disk) Validate() report.Report { + r := report.Report{} if len(n.Device) == 0 { - return fmt.Errorf("disk device is required") + r.Add(report.Entry{ + Kind: report.EntryError, + Message: errors.ErrDiskDeviceRequired.Error(), + }) } if n.partitionNumbersCollide() { - return fmt.Errorf("disk %q: partition numbers collide", n.Device) + r.Add(report.Entry{ + Kind: report.EntryError, + Message: errors.ErrPartitionNumbersCollide.Error(), + }) } if n.partitionsOverlap() { - return fmt.Errorf("disk %q: partitions overlap", n.Device) + r.Add(report.Entry{ + Kind: report.EntryError, + Message: errors.ErrPartitionsOverlap.Error(), + }) } if n.partitionsMisaligned() { - return fmt.Errorf("disk %q: partitions misaligned", n.Device) + r.Add(report.Entry{ + Kind: report.EntryError, + Message: errors.ErrPartitionsMisaligned.Error(), + }) } // Disks which get to this point will likely succeed in sgdisk - return nil + return r } // partitionNumbersCollide returns true if partition numbers in n.Partitions are not unique. diff --git a/vendor/github.com/coreos/ignition/config/v1/types/file.go b/vendor/github.com/coreos/ignition/config/v1/types/file.go index e17d3378..8775c19f 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/file.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/file.go @@ -15,13 +15,10 @@ package types import ( - "encoding/json" - "errors" "os" -) -var ( - ErrFileIllegalMode = errors.New("illegal file mode") + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" ) type FileMode os.FileMode @@ -33,20 +30,10 @@ type File struct { Uid int `json:"uid,omitempty"` Gid int `json:"gid,omitempty"` } -type fileMode FileMode -func (m *FileMode) UnmarshalJSON(data []byte) error { - tm := fileMode(*m) - if err := json.Unmarshal(data, &tm); err != nil { - return err - } - *m = FileMode(tm) - return m.AssertValid() -} - -func (m FileMode) AssertValid() error { +func (m FileMode) Validate() report.Report { if (m &^ 07777) != 0 { - return ErrFileIllegalMode + return report.ReportFromError(errors.ErrFileIllegalMode, report.EntryError) } - return nil + return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v1/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v1/types/filesystem.go index 0de2ce79..7986bd72 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/filesystem.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/filesystem.go @@ -15,12 +15,8 @@ package types import ( - "encoding/json" - "errors" -) - -var ( - ErrFilesystemInvalidFormat = errors.New("invalid filesystem format") + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" ) type Filesystem struct { @@ -34,60 +30,16 @@ type FilesystemCreate struct { Force bool `json:"force,omitempty"` Options MkfsOptions `json:"options,omitempty"` } -type filesystem Filesystem - -func (f *Filesystem) UnmarshalJSON(data []byte) error { - tf := filesystem(*f) - if err := json.Unmarshal(data, &tf); err != nil { - return err - } - *f = Filesystem(tf) - return f.AssertValid() -} - -func (f Filesystem) AssertValid() error { - if err := f.Device.AssertValid(); err != nil { - return err - } - if err := f.Format.AssertValid(); err != nil { - return err - } - return nil -} type FilesystemFormat string -type filesystemFormat FilesystemFormat -func (f *FilesystemFormat) UnmarshalJSON(data []byte) error { - tf := filesystemFormat(*f) - if err := json.Unmarshal(data, &tf); err != nil { - return err - } - *f = FilesystemFormat(tf) - return f.AssertValid() -} - -func (f FilesystemFormat) AssertValid() error { +func (f FilesystemFormat) Validate() report.Report { switch f { case "ext4", "btrfs", "xfs": - return nil + return report.Report{} default: - return ErrFilesystemInvalidFormat + return report.ReportFromError(errors.ErrFilesystemInvalidFormat, report.EntryError) } } type MkfsOptions []string -type mkfsOptions MkfsOptions - -func (o *MkfsOptions) UnmarshalJSON(data []byte) error { - to := mkfsOptions(*o) - if err := json.Unmarshal(data, &to); err != nil { - return err - } - *o = MkfsOptions(to) - return o.AssertValid() -} - -func (o MkfsOptions) AssertValid() error { - return nil -} diff --git a/vendor/github.com/coreos/ignition/config/v1/types/partition.go b/vendor/github.com/coreos/ignition/config/v1/types/partition.go index 0d986a69..16270de2 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/partition.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/partition.go @@ -15,9 +15,11 @@ package types import ( - "encoding/json" "fmt" "regexp" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" ) type Partition struct { @@ -29,59 +31,30 @@ type Partition struct { } type PartitionLabel string -type partitionLabel PartitionLabel -func (n *PartitionLabel) UnmarshalJSON(data []byte) error { - tn := partitionLabel(*n) - if err := json.Unmarshal(data, &tn); err != nil { - return err - } - *n = PartitionLabel(tn) - return n.AssertValid() -} - -func (n PartitionLabel) AssertValid() error { +func (n PartitionLabel) Validate() report.Report { // http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries: // 56 (0x38) 72 bytes Partition name (36 UTF-16LE code units) // XXX(vc): note GPT calls it a name, we're using label for consistency // with udev naming /dev/disk/by-partlabel/*. if len(string(n)) > 36 { - return fmt.Errorf("partition labels may not exceed 36 characters") + return report.ReportFromError(errors.ErrLabelTooLong, report.EntryError) } - return nil + return report.Report{} } type PartitionDimension uint64 -func (n *PartitionDimension) UnmarshalJSON(data []byte) error { - var pd uint64 - if err := json.Unmarshal(data, &pd); err != nil { - return err - } - *n = PartitionDimension(pd) - return nil -} - type PartitionTypeGUID string -type partitionTypeGUID PartitionTypeGUID -func (d *PartitionTypeGUID) UnmarshalJSON(data []byte) error { - td := partitionTypeGUID(*d) - if err := json.Unmarshal(data, &td); err != nil { - return err - } - *d = PartitionTypeGUID(td) - return d.AssertValid() -} - -func (d PartitionTypeGUID) AssertValid() error { +func (d PartitionTypeGUID) Validate() report.Report { ok, err := regexp.MatchString("^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$", string(d)) if err != nil { - return fmt.Errorf("error matching type-guid regexp: %v", err) + return report.ReportFromError(fmt.Errorf("error matching type-guid regexp: %v", err), report.EntryError) } if !ok { - return fmt.Errorf(`partition type-guid must have the form "01234567-89AB-CDEF-EDCB-A98765432101", got: %q`, string(d)) + return report.ReportFromError(fmt.Errorf(`partition type-guid must have the form "01234567-89AB-CDEF-EDCB-A98765432101", got: %q`, string(d)), report.EntryError) } - return nil + return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v1/types/path.go b/vendor/github.com/coreos/ignition/config/v1/types/path.go index 0cdc59a6..e37341c1 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/path.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/path.go @@ -15,29 +15,17 @@ package types import ( - "encoding/json" - "errors" "path" -) -var ( - ErrPathRelative = errors.New("path not absolute") + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" ) type Path string -func (d *Path) UnmarshalJSON(data []byte) error { - var s string - if err := json.Unmarshal(data, &s); err != nil { - return err - } - *d = Path(s) - return d.AssertValid() -} - -func (d Path) AssertValid() error { +func (d Path) Validate() report.Report { if !path.IsAbs(string(d)) { - return ErrPathRelative + return report.ReportFromError(errors.ErrPathRelative, report.EntryError) } - return nil + return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v1/types/raid.go b/vendor/github.com/coreos/ignition/config/v1/types/raid.go index 33375609..329b123e 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/raid.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/raid.go @@ -15,8 +15,8 @@ package types import ( - "encoding/json" - "fmt" + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" ) type Raid struct { @@ -25,22 +25,12 @@ type Raid struct { Devices []Path `json:"devices,omitempty"` Spares int `json:"spares,omitempty"` } -type raid Raid -func (n *Raid) UnmarshalJSON(data []byte) error { - tn := raid(*n) - if err := json.Unmarshal(data, &tn); err != nil { - return err - } - *n = Raid(tn) - return n.AssertValid() -} - -func (n Raid) AssertValid() error { +func (n Raid) Validate() report.Report { switch n.Level { case "linear", "raid0", "0", "stripe": if n.Spares != 0 { - return fmt.Errorf("spares unsupported for %q arrays", n.Level) + return report.ReportFromError(errors.ErrSparesUnsupportedForLevel, report.EntryError) } case "raid1", "1", "mirror": case "raid4", "4": @@ -48,7 +38,7 @@ func (n Raid) AssertValid() error { case "raid6", "6": case "raid10", "10": default: - return fmt.Errorf("unrecognized raid level: %q", n.Level) + return report.ReportFromError(errors.ErrUnrecognizedRaidLevel, report.EntryError) } - return nil + return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v1/types/unit.go b/vendor/github.com/coreos/ignition/config/v1/types/unit.go index c1ec79de..5e983cc1 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/unit.go @@ -15,9 +15,10 @@ package types import ( - "encoding/json" - "errors" "path" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" ) type SystemdUnit struct { @@ -34,44 +35,24 @@ type SystemdUnitDropIn struct { } type SystemdUnitName string -type systemdUnitName SystemdUnitName -func (n *SystemdUnitName) UnmarshalJSON(data []byte) error { - tn := systemdUnitName(*n) - if err := json.Unmarshal(data, &tn); err != nil { - return err - } - *n = SystemdUnitName(tn) - return n.AssertValid() -} - -func (n SystemdUnitName) AssertValid() error { +func (n SystemdUnitName) Validate() report.Report { switch path.Ext(string(n)) { case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": - return nil + return report.Report{} default: - return errors.New("invalid systemd unit extension") + return report.ReportFromError(errors.ErrInvalidSystemdExt, report.EntryError) } } type SystemdUnitDropInName string -type systemdUnitDropInName SystemdUnitDropInName -func (n *SystemdUnitDropInName) UnmarshalJSON(data []byte) error { - tn := systemdUnitDropInName(*n) - if err := json.Unmarshal(data, &tn); err != nil { - return err - } - *n = SystemdUnitDropInName(tn) - return n.AssertValid() -} - -func (n SystemdUnitDropInName) AssertValid() error { +func (n SystemdUnitDropInName) Validate() report.Report { switch path.Ext(string(n)) { case ".conf": - return nil + return report.Report{} default: - return errors.New("invalid systemd unit drop-in extension") + return report.ReportFromError(errors.ErrInvalidSystemdDropinExt, report.EntryError) } } @@ -81,22 +62,12 @@ type NetworkdUnit struct { } type NetworkdUnitName string -type networkdUnitName NetworkdUnitName -func (n *NetworkdUnitName) UnmarshalJSON(data []byte) error { - tn := networkdUnitName(*n) - if err := json.Unmarshal(data, &tn); err != nil { - return err - } - *n = NetworkdUnitName(tn) - return n.AssertValid() -} - -func (n NetworkdUnitName) AssertValid() error { +func (n NetworkdUnitName) Validate() report.Report { switch path.Ext(string(n)) { case ".link", ".netdev", ".network": - return nil + return report.Report{} default: - return errors.New("invalid networkd unit extension") + return report.ReportFromError(errors.ErrInvalidNetworkdExt, report.EntryError) } } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/append.go b/vendor/github.com/coreos/ignition/config/v2_0/append.go deleted file mode 100644 index cee6bc41..00000000 --- a/vendor/github.com/coreos/ignition/config/v2_0/append.go +++ /dev/null @@ -1,73 +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 v2_0 - -import ( - "reflect" - - "github.com/coreos/ignition/config/v2_0/types" -) - -// Append appends newConfig to oldConfig and returns the result. Appending one -// config to another is accomplished by iterating over every field in the -// config structure, appending slices, recursively appending structs, and -// overwriting old values with new values for all other types. -func Append(oldConfig, newConfig types.Config) types.Config { - vOld := reflect.ValueOf(oldConfig) - vNew := reflect.ValueOf(newConfig) - - vResult := appendStruct(vOld, vNew) - - return vResult.Interface().(types.Config) -} - -// appendStruct is an internal helper function to AppendConfig. Given two values -// of structures (assumed to be the same type), recursively iterate over every -// field in the struct, appending slices, recursively appending structs, and -// overwriting old values with the new for all other types. Individual fields -// are able to override their merge strategy using the "merge" tag. Accepted -// values are "new" or "old": "new" uses the new value, "old" uses the old -// value. These are currently only used for "ignition.config" and -// "ignition.version". -func appendStruct(vOld, vNew reflect.Value) reflect.Value { - tOld := vOld.Type() - vRes := reflect.New(tOld) - - for i := 0; i < tOld.NumField(); i++ { - vfOld := vOld.Field(i) - vfNew := vNew.Field(i) - vfRes := vRes.Elem().Field(i) - - switch tOld.Field(i).Tag.Get("merge") { - case "old": - vfRes.Set(vfOld) - continue - case "new": - vfRes.Set(vfNew) - continue - } - - switch vfOld.Type().Kind() { - case reflect.Struct: - vfRes.Set(appendStruct(vfOld, vfNew)) - case reflect.Slice: - vfRes.Set(reflect.AppendSlice(vfOld, vfNew)) - default: - vfRes.Set(vfNew) - } - } - - return vRes.Elem() -} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/config.go b/vendor/github.com/coreos/ignition/config/v2_0/config.go index d85d6d4b..f1385bf1 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/config.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/config.go @@ -15,104 +15,54 @@ package v2_0 import ( - "bytes" - "errors" - "reflect" - + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/v1" "github.com/coreos/ignition/config/v2_0/types" "github.com/coreos/ignition/config/validate" - astjson "github.com/coreos/ignition/config/validate/astjson" "github.com/coreos/ignition/config/validate/report" json "github.com/ajeddeloh/go-json" - "go4.org/errorutil" -) - -var ( - ErrCloudConfig = errors.New("not a config (found coreos-cloudconfig)") - ErrEmpty = errors.New("not a config (empty)") - ErrScript = errors.New("not a config (found coreos-cloudinit script)") - ErrDeprecated = errors.New("config format deprecated") - ErrInvalid = errors.New("config is not valid") + "github.com/coreos/go-semver/semver" ) // Parse parses the raw config into a types.Config struct and generates a report of any // errors, warnings, info, and deprecations it encountered func Parse(rawConfig []byte) (types.Config, report.Report, error) { if isEmpty(rawConfig) { - return types.Config{}, report.Report{}, ErrEmpty + return types.Config{}, report.Report{}, errors.ErrEmpty } else if isCloudConfig(rawConfig) { - return types.Config{}, report.Report{}, ErrCloudConfig + return types.Config{}, report.Report{}, errors.ErrCloudConfig } else if isScript(rawConfig) { - return types.Config{}, report.Report{}, ErrScript + return types.Config{}, report.Report{}, errors.ErrScript } var err error var config types.Config - // These errors are fatal and the config should not be further validated - if err = json.Unmarshal(rawConfig, &config); err == nil { - versionReport := config.Ignition.Version.Validate() - if versionReport.IsFatal() { - return types.Config{}, versionReport, ErrInvalid + err = json.Unmarshal(rawConfig, &config) + + if err != nil || semver.Version(config.Ignition.Version).LessThan(types.MaxVersion) { + // We can fail unmarshaling if it's an older config. Attempt to parse + // it as such. + config, rpt, err := v1.Parse(rawConfig) + if err != nil { + return types.Config{}, rpt, err } + + rpt.Merge(report.ReportFromError(errors.ErrDeprecated, report.EntryDeprecated)) + return TranslateFromV1(config), rpt, err } - // 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 semver.Version(config.Ignition.Version) != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion } - 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 + rpt := validate.ValidateConfig(rawConfig, config) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.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 + return config, rpt, nil } func isEmpty(userdata []byte) bool { diff --git a/vendor/github.com/coreos/ignition/config/v2_0/translate.go b/vendor/github.com/coreos/ignition/config/v2_0/translate.go new file mode 100644 index 00000000..832adce5 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_0/translate.go @@ -0,0 +1,173 @@ +// Copyright 2018 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v2_0 + +import ( + "fmt" + + v1 "github.com/coreos/ignition/config/v1/types" + "github.com/coreos/ignition/config/v2_0/types" + "github.com/vincent-petithory/dataurl" +) + +func TranslateFromV1(old v1.Config) types.Config { + config := types.Config{ + Ignition: types.Ignition{ + Version: types.IgnitionVersion(types.MaxVersion), + }, + } + + for _, oldDisk := range old.Storage.Disks { + disk := types.Disk{ + Device: types.Path(oldDisk.Device), + WipeTable: oldDisk.WipeTable, + } + + for _, oldPartition := range oldDisk.Partitions { + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: types.PartitionLabel(oldPartition.Label), + Number: oldPartition.Number, + Size: types.PartitionDimension(oldPartition.Size), + Start: types.PartitionDimension(oldPartition.Start), + TypeGUID: types.PartitionTypeGUID(oldPartition.TypeGUID), + }) + } + + config.Storage.Disks = append(config.Storage.Disks, disk) + } + + for _, oldArray := range old.Storage.Arrays { + array := types.Raid{ + Name: oldArray.Name, + Level: oldArray.Level, + Spares: oldArray.Spares, + } + + for _, oldDevice := range oldArray.Devices { + array.Devices = append(array.Devices, types.Path(oldDevice)) + } + + config.Storage.Arrays = append(config.Storage.Arrays, array) + } + + for 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), + }, + } + + if oldFilesystem.Create != nil { + filesystem.Mount.Create = &types.FilesystemCreate{ + Force: oldFilesystem.Create.Force, + Options: types.MkfsOptions(oldFilesystem.Create.Options), + } + } + + config.Storage.Filesystems = append(config.Storage.Filesystems, filesystem) + + for _, oldFile := range oldFilesystem.Files { + file := types.File{ + Filesystem: filesystem.Name, + Path: types.Path(oldFile.Path), + User: types.FileUser{Id: oldFile.Uid}, + Group: types.FileGroup{Id: oldFile.Gid}, + Mode: types.FileMode(oldFile.Mode), + Contents: types.FileContents{ + Source: types.Url{ + Scheme: "data", + Opaque: "," + dataurl.EscapeString(oldFile.Contents), + }, + }, + } + + config.Storage.Files = append(config.Storage.Files, file) + } + } + + for _, oldUnit := range old.Systemd.Units { + unit := types.SystemdUnit{ + Name: types.SystemdUnitName(oldUnit.Name), + Enable: oldUnit.Enable, + Mask: oldUnit.Mask, + Contents: oldUnit.Contents, + } + + for _, oldDropIn := range oldUnit.DropIns { + unit.DropIns = append(unit.DropIns, types.SystemdUnitDropIn{ + Name: types.SystemdUnitDropInName(oldDropIn.Name), + Contents: oldDropIn.Contents, + }) + } + + config.Systemd.Units = append(config.Systemd.Units, unit) + } + + for _, oldUnit := range old.Networkd.Units { + config.Networkd.Units = append(config.Networkd.Units, types.NetworkdUnit{ + Name: types.NetworkdUnitName(oldUnit.Name), + Contents: oldUnit.Contents, + }) + } + + for _, oldUser := range old.Passwd.Users { + user := types.User{ + Name: oldUser.Name, + PasswordHash: oldUser.PasswordHash, + SSHAuthorizedKeys: oldUser.SSHAuthorizedKeys, + } + + if oldUser.Create != nil { + var uid *uint + if oldUser.Create.Uid != nil { + tmp := uint(*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, + NoUserGroup: oldUser.Create.NoUserGroup, + System: oldUser.Create.System, + NoLogInit: oldUser.Create.NoLogInit, + Shell: oldUser.Create.Shell, + } + } + + config.Passwd.Users = append(config.Passwd.Users, user) + } + + for _, oldGroup := range old.Passwd.Groups { + var gid *uint + if oldGroup.Gid != nil { + tmp := uint(*oldGroup.Gid) + gid = &tmp + } + config.Passwd.Groups = append(config.Passwd.Groups, types.Group{ + Name: oldGroup.Name, + Gid: gid, + PasswordHash: oldGroup.PasswordHash, + System: oldGroup.System, + }) + } + + return config +} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/compression.go b/vendor/github.com/coreos/ignition/config/v2_0/types/compression.go index 65c3e25c..f56e5b9c 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/compression.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/compression.go @@ -15,22 +15,17 @@ package types import ( - "errors" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrCompressionInvalid = errors.New("invalid compression method") -) - type Compression string func (c Compression) Validate() report.Report { switch c { case "", "gzip": default: - return report.ReportFromError(ErrCompressionInvalid, report.EntryError) + return report.ReportFromError(errors.ErrCompressionInvalid, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_0/types/disk.go index 69652345..b68c5c93 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/disk.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/disk.go @@ -15,8 +15,7 @@ package types import ( - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -30,25 +29,25 @@ func (n Disk) Validate() report.Report { r := report.Report{} if len(n.Device) == 0 { r.Add(report.Entry{ - Message: "disk device is required", + Message: errors.ErrDiskDeviceRequired.Error(), Kind: report.EntryError, }) } if n.partitionNumbersCollide() { r.Add(report.Entry{ - Message: fmt.Sprintf("disk %q: partition numbers collide", n.Device), + Message: errors.ErrPartitionNumbersCollide.Error(), Kind: report.EntryError, }) } if n.partitionsOverlap() { r.Add(report.Entry{ - Message: fmt.Sprintf("disk %q: partitions overlap", n.Device), + Message: errors.ErrPartitionsOverlap.Error(), Kind: report.EntryError, }) } if n.partitionsMisaligned() { r.Add(report.Entry{ - Message: fmt.Sprintf("disk %q: partitions misaligned", n.Device), + Message: errors.ErrPartitionsMisaligned.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/file.go b/vendor/github.com/coreos/ignition/config/v2_0/types/file.go index cc660b55..8d3e7905 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/file.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/file.go @@ -15,17 +15,12 @@ package types import ( - "errors" "os" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrFileIllegalMode = errors.New("illegal file mode") - ErrNoFilesystem = errors.New("no filesystem specified") -) - type File struct { Filesystem string `json:"filesystem,omitempty"` Path Path `json:"path,omitempty"` @@ -37,7 +32,7 @@ type File struct { func (f File) Validate() report.Report { if f.Filesystem == "" { - return report.ReportFromError(ErrNoFilesystem, report.EntryError) + return report.ReportFromError(errors.ErrNoFilesystem, report.EntryError) } return report.Report{} } @@ -60,7 +55,7 @@ type FileMode os.FileMode func (m FileMode) Validate() report.Report { if (m &^ 07777) != 0 { - return report.ReportFromError(ErrFileIllegalMode, report.EntryError) + return report.ReportFromError(errors.ErrFileIllegalMode, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_0/types/filesystem.go index bbd0c75b..e3572711 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/filesystem.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/filesystem.go @@ -15,17 +15,10 @@ package types import ( - "errors" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrFilesystemInvalidFormat = errors.New("invalid filesystem format") - ErrFilesystemNoMountPath = errors.New("filesystem is missing mount or path") - ErrFilesystemMountAndPath = errors.New("filesystem has both mount and path defined") -) - type Filesystem struct { Name string `json:"name,omitempty"` Mount *FilesystemMount `json:"mount,omitempty"` @@ -45,10 +38,10 @@ type FilesystemCreate struct { func (f Filesystem) Validate() report.Report { if f.Mount == nil && f.Path == nil { - return report.ReportFromError(ErrFilesystemNoMountPath, report.EntryError) + return report.ReportFromError(errors.ErrFilesystemNoMountPath, report.EntryError) } if f.Mount != nil && f.Path != nil { - return report.ReportFromError(ErrFilesystemMountAndPath, report.EntryError) + return report.ReportFromError(errors.ErrFilesystemMountAndPath, report.EntryError) } return report.Report{} } @@ -60,7 +53,7 @@ func (f FilesystemFormat) Validate() report.Report { case "ext4", "btrfs", "xfs": return report.Report{} default: - return report.ReportFromError(ErrFilesystemInvalidFormat, report.EntryError) + return report.ReportFromError(errors.ErrFilesystemInvalidFormat, report.EntryError) } } 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 5d0f682d..628524dc 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 @@ -18,18 +18,12 @@ import ( "crypto" "encoding/hex" "encoding/json" - "errors" "strings" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrHashMalformed = errors.New("malformed hash specifier") - ErrHashWrongSize = errors.New("incorrect size for hash sum") - ErrHashUnrecognized = errors.New("unrecognized hash function") -) - type Hash struct { Function string Sum string @@ -43,7 +37,7 @@ func (h *Hash) UnmarshalJSON(data []byte) error { parts := strings.SplitN(th, "-", 2) if len(parts) != 2 { - return ErrHashMalformed + return errors.ErrHashMalformed } h.Function = parts[0] @@ -67,11 +61,11 @@ func (h Hash) Validate() report.Report { case "sha512": hash = crypto.SHA512 default: - return report.ReportFromError(ErrHashUnrecognized, report.EntryError) + return report.ReportFromError(errors.ErrHashUnrecognized, report.EntryError) } if len(h.Sum) != hex.EncodedLen(hash.Size()) { - return report.ReportFromError(ErrHashWrongSize, report.EntryError) + return report.ReportFromError(errors.ErrHashWrongSize, report.EntryError) } return report.Report{} diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_0/types/ignition.go index c9519a15..deeb822d 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/ignition.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/ignition.go @@ -16,18 +16,13 @@ package types import ( "encoding/json" - "errors" "github.com/coreos/go-semver/semver" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrOldVersion = errors.New("incorrect config version (too old)") - ErrNewVersion = errors.New("incorrect config version (too new)") -) - type Ignition struct { Version IgnitionVersion `json:"version,omitempty" merge:"old"` Config IgnitionConfig `json:"config,omitempty" merge:"new"` @@ -60,10 +55,10 @@ func (v IgnitionVersion) MarshalJSON() ([]byte, error) { func (v IgnitionVersion) Validate() report.Report { if MaxVersion.Major > v.Major { - return report.ReportFromError(ErrOldVersion, report.EntryError) + return report.ReportFromError(errors.ErrOldVersion, report.EntryError) } if MaxVersion.LessThan(semver.Version(v)) { - return report.ReportFromError(ErrNewVersion, report.EntryError) + return report.ReportFromError(errors.ErrNewVersion, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_0/types/partition.go index 9ed03c32..c36545d4 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/partition.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/partition.go @@ -17,7 +17,9 @@ package types import ( "fmt" "regexp" + "strings" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -38,7 +40,10 @@ func (n PartitionLabel) Validate() report.Report { // XXX(vc): note GPT calls it a name, we're using label for consistency // with udev naming /dev/disk/by-partlabel/*. if len(string(n)) > 36 { - return report.ReportFromError(fmt.Errorf("partition labels may not exceed 36 characters"), report.EntryError) + return report.ReportFromError(errors.ErrLabelTooLong, report.EntryError) + } + if strings.Contains(string(n), ":") { + return report.ReportFromError(errors.ErrLabelContainsColon, report.EntryWarning) } return report.Report{} } @@ -53,7 +58,7 @@ func (d PartitionTypeGUID) Validate() report.Report { return report.ReportFromError(fmt.Errorf("error matching type-guid regexp: %v", err), report.EntryError) } if !ok { - return report.ReportFromError(fmt.Errorf(`partition type-guid must have the form "01234567-89AB-CDEF-EDCB-A98765432101", got: %q`, string(d)), report.EntryError) + return report.ReportFromError(errors.ErrDoesntMatchGUIDRegex, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/path.go b/vendor/github.com/coreos/ignition/config/v2_0/types/path.go index 0d07d81f..dcf35f80 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/path.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/path.go @@ -15,16 +15,12 @@ package types import ( - "errors" "path" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrPathRelative = errors.New("path not absolute") -) - type Path string func (p Path) MarshalJSON() ([]byte, error) { @@ -33,7 +29,7 @@ func (p Path) MarshalJSON() ([]byte, error) { func (p Path) Validate() report.Report { if !path.IsAbs(string(p)) { - return report.ReportFromError(ErrPathRelative, report.EntryError) + return report.ReportFromError(errors.ErrPathRelative, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_0/types/raid.go index 4236255d..329b123e 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/raid.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/raid.go @@ -15,8 +15,7 @@ package types import ( - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -31,7 +30,7 @@ func (n Raid) Validate() report.Report { switch n.Level { case "linear", "raid0", "0", "stripe": if n.Spares != 0 { - return report.ReportFromError(fmt.Errorf("spares unsupported for %q arrays", n.Level), report.EntryError) + return report.ReportFromError(errors.ErrSparesUnsupportedForLevel, report.EntryError) } case "raid1", "1", "mirror": case "raid4", "4": @@ -39,7 +38,7 @@ 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) + return report.ReportFromError(errors.ErrUnrecognizedRaidLevel, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_0/types/unit.go index 020d10a5..06d99f26 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/unit.go @@ -15,13 +15,14 @@ package types import ( - "bytes" - "errors" "fmt" "path" + "strings" "github.com/coreos/go-systemd/unit" + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/shared/validations" "github.com/coreos/ignition/config/validate/report" ) @@ -34,11 +35,15 @@ type SystemdUnit struct { } func (u SystemdUnit) Validate() report.Report { - if err := validateUnitContent(u.Contents); err != nil { + r := report.Report{} + opts, err := validateUnitContent(u.Contents) + if err != nil { return report.ReportFromError(err, report.EntryError) } - return report.Report{} + r.Merge(validations.ValidateInstallSection(string(u.Name), u.Enable, u.Contents == "", opts)) + + return r } type SystemdUnitDropIn struct { @@ -47,7 +52,7 @@ type SystemdUnitDropIn struct { } func (u SystemdUnitDropIn) Validate() report.Report { - if err := validateUnitContent(u.Contents); err != nil { + if _, err := validateUnitContent(u.Contents); err != nil { return report.ReportFromError(err, report.EntryError) } @@ -61,7 +66,7 @@ func (n SystemdUnitName) Validate() report.Report { 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) + return report.ReportFromError(errors.ErrInvalidSystemdExt, report.EntryError) } } @@ -72,7 +77,7 @@ func (n SystemdUnitDropInName) Validate() report.Report { case ".conf": return report.Report{} default: - return report.ReportFromError(errors.New("invalid systemd unit drop-in extension"), report.EntryError) + return report.ReportFromError(errors.ErrInvalidSystemdDropinExt, report.EntryError) } } @@ -82,7 +87,7 @@ type NetworkdUnit struct { } func (u NetworkdUnit) Validate() report.Report { - if err := validateUnitContent(u.Contents); err != nil { + if _, err := validateUnitContent(u.Contents); err != nil { return report.ReportFromError(err, report.EntryError) } @@ -96,16 +101,15 @@ func (n NetworkdUnitName) Validate() report.Report { case ".link", ".netdev", ".network": return report.Report{} default: - return report.ReportFromError(errors.New("invalid networkd unit extension"), report.EntryError) + return report.ReportFromError(errors.ErrInvalidNetworkdExt, report.EntryError) } } -func validateUnitContent(content string) error { - c := bytes.NewBufferString(content) - _, err := unit.Deserialize(c) +func validateUnitContent(content string) ([]*unit.UnitOption, error) { + c := strings.NewReader(content) + opts, err := unit.Deserialize(c) if err != nil { - return fmt.Errorf("invalid unit content: %s", err) + return nil, fmt.Errorf("invalid unit content: %s", err) } - - return nil + return opts, nil } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/url.go b/vendor/github.com/coreos/ignition/config/v2_0/types/url.go index 8bf0e6ea..b8ed9611 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/url.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/url.go @@ -16,15 +16,12 @@ package types import ( "encoding/json" - "errors" "net/url" - "github.com/coreos/ignition/config/validate/report" "github.com/vincent-petithory/dataurl" -) -var ( - ErrInvalidScheme = errors.New("invalid url scheme") + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" ) type Url url.URL @@ -37,7 +34,7 @@ func (u *Url) UnmarshalJSON(data []byte) error { pu, err := url.Parse(tu) if err != nil { - return err + return errors.ErrInvalidUrl } *u = Url(*pu) @@ -67,6 +64,6 @@ func (u Url) Validate() report.Report { } return report.Report{} default: - return report.ReportFromError(ErrInvalidScheme, report.EntryError) + return report.ReportFromError(errors.ErrInvalidScheme, report.EntryError) } } diff --git a/vendor/github.com/coreos/ignition/config/v2_1/append.go b/vendor/github.com/coreos/ignition/config/v2_1/append.go deleted file mode 100644 index f2b0d001..00000000 --- a/vendor/github.com/coreos/ignition/config/v2_1/append.go +++ /dev/null @@ -1,72 +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 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/config.go b/vendor/github.com/coreos/ignition/config/v2_1/config.go index 0b4a2ee5..3fd271dd 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/config.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/config.go @@ -15,102 +15,52 @@ package v2_1 import ( - "bytes" - "errors" - "reflect" - + "github.com/coreos/go-semver/semver" + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/v2_0" "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 + return types.Config{}, report.Report{}, errors.ErrEmpty } else if isCloudConfig(rawConfig) { - return types.Config{}, report.Report{}, ErrCloudConfig + return types.Config{}, report.Report{}, errors.ErrCloudConfig } else if isScript(rawConfig) { - return types.Config{}, report.Report{}, ErrScript + return types.Config{}, report.Report{}, errors.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 + err = json.Unmarshal(rawConfig, &config) + + version, semverErr := semver.NewVersion(config.Ignition.Version) + + if err != nil || semverErr != nil || version.LessThan(types.MaxVersion) { + // We can fail unmarshaling if it's an older config. Attempt to parse + // it as such. + config, rpt, err := v2_0.Parse(rawConfig) + if err != nil { + return types.Config{}, rpt, err } + return TranslateFromV2_0(config), rpt, err } - // 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 *version != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion } - 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 + rpt := validate.ValidateConfig(rawConfig, config) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.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 + return config, rpt, nil } func isEmpty(userdata []byte) bool { diff --git a/vendor/github.com/coreos/ignition/config/v2_1/translate.go b/vendor/github.com/coreos/ignition/config/v2_1/translate.go new file mode 100644 index 00000000..e6b80dd1 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/translate.go @@ -0,0 +1,236 @@ +// Copyright 2018 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 ( + "strings" + + "github.com/coreos/ignition/config/util" + v2_0 "github.com/coreos/ignition/config/v2_0/types" + "github.com/coreos/ignition/config/v2_1/types" +) + +// golang-- +func translateV2_0MkfsOptionsTov2_1OptionSlice(opts v2_0.MkfsOptions) []types.CreateOption { + newOpts := make([]types.CreateOption, len(opts)) + for i, o := range opts { + newOpts[i] = types.CreateOption(o) + } + return newOpts +} + +// golang-- +func translateStringSliceTov2_1SSHAuthorizedKeySlice(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_1UsercreateGroupSlice(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 { + // .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: old.Source.String(), + Verification: translateVerification(old.Verification), + } + } + + config := types.Config{ + Ignition: types.Ignition{ + Version: types.MaxVersion.String(), + }, + } + + if old.Ignition.Config.Replace != nil { + ref := translateConfigReference(*old.Ignition.Config.Replace) + config.Ignition.Config.Replace = &ref + } + + for _, oldAppend := range old.Ignition.Config.Append { + config.Ignition.Config.Append = + append(config.Ignition.Config.Append, translateConfigReference(oldAppend)) + } + + for _, oldDisk := range old.Storage.Disks { + disk := types.Disk{ + Device: string(oldDisk.Device), + WipeTable: oldDisk.WipeTable, + } + + for _, oldPartition := range oldDisk.Partitions { + disk.Partitions = append(disk.Partitions, types.Partition{ + Label: string(oldPartition.Label), + Number: oldPartition.Number, + Size: int(oldPartition.Size), + Start: int(oldPartition.Start), + TypeGUID: string(oldPartition.TypeGUID), + }) + } + + config.Storage.Disks = append(config.Storage.Disks, disk) + } + + for _, oldArray := range old.Storage.Arrays { + array := types.Raid{ + Name: oldArray.Name, + Level: oldArray.Level, + Spares: oldArray.Spares, + } + + for _, oldDevice := range oldArray.Devices { + array.Devices = append(array.Devices, types.Device(oldDevice)) + } + + config.Storage.Raid = append(config.Storage.Raid, array) + } + + for _, oldFilesystem := range old.Storage.Filesystems { + filesystem := types.Filesystem{ + Name: oldFilesystem.Name, + } + + if oldFilesystem.Mount != nil { + filesystem.Mount = &types.Mount{ + Device: string(oldFilesystem.Mount.Device), + Format: string(oldFilesystem.Mount.Format), + } + + if oldFilesystem.Mount.Create != nil { + filesystem.Mount.Create = &types.Create{ + Force: oldFilesystem.Mount.Create.Force, + Options: translateV2_0MkfsOptionsTov2_1OptionSlice(oldFilesystem.Mount.Create.Options), + } + } + } + + if oldFilesystem.Path != nil { + p := string(*oldFilesystem.Path) + filesystem.Path = &p + } + + config.Storage.Filesystems = append(config.Storage.Filesystems, filesystem) + } + + for _, oldFile := range old.Storage.Files { + file := types.File{ + Node: types.Node{ + Filesystem: oldFile.Filesystem, + Path: string(oldFile.Path), + User: types.NodeUser{ID: util.IntToPtr(oldFile.User.Id)}, + Group: types.NodeGroup{ID: util.IntToPtr(oldFile.Group.Id)}, + }, + 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), + }, + }, + } + + config.Storage.Files = append(config.Storage.Files, file) + } + + for _, oldUnit := range old.Systemd.Units { + 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.Dropin{ + Name: string(oldDropIn.Name), + Contents: oldDropIn.Contents, + }) + } + + config.Systemd.Units = append(config.Systemd.Units, unit) + } + + for _, oldUnit := range old.Networkd.Units { + config.Networkd.Units = append(config.Networkd.Units, types.Networkdunit{ + Name: string(oldUnit.Name), + Contents: oldUnit.Contents, + }) + } + + for _, oldUser := range old.Passwd.Users { + user := types.PasswdUser{ + Name: oldUser.Name, + PasswordHash: util.StrToPtr(oldUser.PasswordHash), + SSHAuthorizedKeys: translateStringSliceTov2_1SSHAuthorizedKeySlice(oldUser.SSHAuthorizedKeys), + } + + if oldUser.Create != nil { + 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: translateStringSliceTov2_1UsercreateGroupSlice(oldUser.Create.Groups), + NoUserGroup: oldUser.Create.NoUserGroup, + System: oldUser.Create.System, + NoLogInit: oldUser.Create.NoLogInit, + Shell: oldUser.Create.Shell, + } + } + + config.Passwd.Users = append(config.Passwd.Users, user) + } + + for _, oldGroup := range old.Passwd.Groups { + 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: g, + PasswordHash: oldGroup.PasswordHash, + System: oldGroup.System, + }) + } + + return config +} 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 index f556e182..f0af504a 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/disk.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/disk.go @@ -15,8 +15,7 @@ package types import ( - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -26,7 +25,7 @@ func (n Disk) Validate() report.Report { func (n Disk) ValidateDevice() report.Report { if len(n.Device) == 0 { - return report.ReportFromError(fmt.Errorf("disk device is required"), report.EntryError) + return report.ReportFromError(errors.ErrDiskDeviceRequired, report.EntryError) } if err := validatePath(string(n.Device)); err != nil { return report.ReportFromError(err, report.EntryError) @@ -38,19 +37,19 @@ 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), + Message: errors.ErrPartitionNumbersCollide.Error(), Kind: report.EntryError, }) } if n.partitionsOverlap() { r.Add(report.Entry{ - Message: fmt.Sprintf("disk %q: partitions overlap", n.Device), + Message: errors.ErrPartitionsOverlap.Error(), Kind: report.EntryError, }) } if n.partitionsMisaligned() { r.Add(report.Entry{ - Message: fmt.Sprintf("disk %q: partitions misaligned", n.Device), + Message: errors.ErrPartitionsMisaligned.Error(), Kind: report.EntryError, }) } 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 index 866fc054..ac79cd85 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/file.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/file.go @@ -15,16 +15,10 @@ package types import ( - "errors" - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "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 { @@ -42,7 +36,7 @@ func (fc FileContents) ValidateCompression() report.Report { case "", "gzip": default: r.Add(report.Entry{ - Message: ErrCompressionInvalid.Error(), + Message: errors.ErrCompressionInvalid.Error(), Kind: report.EntryError, }) } @@ -54,7 +48,7 @@ func (fc FileContents) ValidateSource() report.Report { err := validateURL(fc.Source) if err != nil { r.Add(report.Entry{ - Message: fmt.Sprintf("invalid url %q: %v", fc.Source, err), + Message: err.Error(), Kind: report.EntryError, }) } 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 index 3c5a47d5..a2e43ffd 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/filesystem.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/filesystem.go @@ -15,56 +15,40 @@ package types import ( - "errors" - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrFilesystemInvalidFormat = errors.New("invalid filesystem format") - ErrFilesystemNoMountPath = errors.New("filesystem is missing mount or path") - ErrFilesystemMountAndPath = errors.New("filesystem has both mount and path defined") - 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(), + Message: errors.ErrFilesystemNoMountPath.Error(), Kind: report.EntryError, }) } if f.Mount != nil { if f.Path != nil { r.Add(report.Entry{ - Message: ErrFilesystemMountAndPath.Error(), + Message: errors.ErrFilesystemMountAndPath.Error(), Kind: report.EntryError, }) } if f.Mount.Create != nil { if f.Mount.WipeFilesystem { r.Add(report.Entry{ - Message: ErrUsedCreateAndWipeFilesystem.Error(), + Message: errors.ErrUsedCreateAndWipeFilesystem.Error(), Kind: report.EntryError, }) } if len(f.Mount.Options) > 0 { r.Add(report.Entry{ - Message: ErrUsedCreateAndMountOpts.Error(), + Message: errors.ErrUsedCreateAndMountOpts.Error(), Kind: report.EntryError, }) } r.Add(report.Entry{ - Message: ErrWarningCreateDeprecated.Error(), + Message: errors.ErrWarningCreateDeprecated.Error(), Kind: report.EntryWarning, }) } @@ -76,7 +60,7 @@ 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), + Message: errors.ErrPathRelative.Error(), Kind: report.EntryError, }) } @@ -89,7 +73,7 @@ func (m Mount) Validate() report.Report { case "ext4", "btrfs", "xfs", "swap", "vfat": default: r.Add(report.Entry{ - Message: ErrFilesystemInvalidFormat.Error(), + Message: errors.ErrFilesystemInvalidFormat.Error(), Kind: report.EntryError, }) } @@ -117,7 +101,7 @@ func (m Mount) ValidateLabel() report.Report { if len(*m.Label) > 16 { // source: man mkfs.ext4 r.Add(report.Entry{ - Message: ErrExt4LabelTooLong.Error(), + Message: errors.ErrExt4LabelTooLong.Error(), Kind: report.EntryError, }) } @@ -125,7 +109,7 @@ func (m Mount) ValidateLabel() report.Report { if len(*m.Label) > 256 { // source: man mkfs.btrfs r.Add(report.Entry{ - Message: ErrBtrfsLabelTooLong.Error(), + Message: errors.ErrBtrfsLabelTooLong.Error(), Kind: report.EntryError, }) } @@ -133,7 +117,7 @@ func (m Mount) ValidateLabel() report.Report { if len(*m.Label) > 12 { // source: man mkfs.xfs r.Add(report.Entry{ - Message: ErrXfsLabelTooLong.Error(), + Message: errors.ErrXfsLabelTooLong.Error(), Kind: report.EntryError, }) } @@ -143,7 +127,7 @@ func (m Mount) ValidateLabel() report.Report { // 15 characters, so let's enforce that. if len(*m.Label) > 15 { r.Add(report.Entry{ - Message: ErrSwapLabelTooLong.Error(), + Message: errors.ErrSwapLabelTooLong.Error(), Kind: report.EntryError, }) } @@ -151,7 +135,7 @@ func (m Mount) ValidateLabel() report.Report { if len(*m.Label) > 11 { // source: man mkfs.fat r.Add(report.Entry{ - Message: ErrVfatLabelTooLong.Error(), + Message: errors.ErrVfatLabelTooLong.Error(), Kind: report.EntryError, }) } 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 index 661b898d..bddf4958 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/ignition.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/ignition.go @@ -15,19 +15,12 @@ package types import ( - "errors" - "github.com/coreos/go-semver/semver" + "github.com/coreos/ignition/config/shared/errors" "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) @@ -47,13 +40,13 @@ func (v Ignition) Semver() (*semver.Version, error) { func (v Ignition) Validate() report.Report { tv, err := v.Semver() if err != nil { - return report.ReportFromError(ErrInvalidVersion, report.EntryError) + return report.ReportFromError(errors.ErrInvalidVersion, report.EntryError) } if MaxVersion.Major > tv.Major { - return report.ReportFromError(ErrOldVersion, report.EntryError) + return report.ReportFromError(errors.ErrOldVersion, report.EntryError) } if MaxVersion.LessThan(*tv) { - return report.ReportFromError(ErrNewVersion, report.EntryError) + return report.ReportFromError(errors.ErrNewVersion, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/mode.go b/vendor/github.com/coreos/ignition/config/v2_1/types/mode.go index 09608b51..12d4188e 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/mode.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/mode.go @@ -15,16 +15,12 @@ package types import ( - "errors" -) - -var ( - ErrFileIllegalMode = errors.New("illegal file mode") + "github.com/coreos/ignition/config/shared/errors" ) func validateMode(m int) error { if m < 0 || m > 07777 { - return ErrFileIllegalMode + return errors.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 index 5c117f06..50badfdf 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/node.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/node.go @@ -15,22 +15,17 @@ package types import ( - "errors" "path/filepath" + "github.com/coreos/ignition/config/shared/errors" "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(), + Message: errors.ErrNoFilesystem.Error(), Kind: report.EntryError, }) } @@ -60,7 +55,7 @@ func (nu NodeUser) Validate() report.Report { r := report.Report{} if nu.ID != nil && nu.Name != "" { r.Add(report.Entry{ - Message: ErrBothIDAndNameSet.Error(), + Message: errors.ErrBothIDAndNameSet.Error(), Kind: report.EntryError, }) } @@ -70,7 +65,7 @@ func (ng NodeGroup) Validate() report.Report { r := report.Report{} if ng.ID != nil && ng.Name != "" { r.Add(report.Entry{ - Message: ErrBothIDAndNameSet.Error(), + Message: errors.ErrBothIDAndNameSet.Error(), Kind: report.EntryError, }) } 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 index 4473b667..084dce7c 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/partition.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/partition.go @@ -15,10 +15,11 @@ package types import ( - "errors" "fmt" "regexp" + "strings" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -26,11 +27,6 @@ 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: @@ -40,10 +36,18 @@ func (p Partition) ValidateLabel() report.Report { // with udev naming /dev/disk/by-partlabel/*. if len(p.Label) > 36 { r.Add(report.Entry{ - Message: ErrLabelTooLong.Error(), + Message: errors.ErrLabelTooLong.Error(), Kind: report.EntryError, }) } + + // sgdisk uses colons for delimitting compound arguments and does not allow escaping them. + if strings.Contains(p.Label, ":") { + r.Add(report.Entry{ + Message: errors.ErrLabelContainsColon.Error(), + Kind: report.EntryWarning, + }) + } return r } @@ -65,7 +69,7 @@ func validateGUID(guid string) report.Report { }) } else if !ok { r.Add(report.Entry{ - Message: ErrDoesntMatchGUIDRegex.Error(), + Message: errors.ErrDoesntMatchGUIDRegex.Error(), Kind: report.EntryError, }) } 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 index 5f7d9641..10508c56 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/passwd.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/passwd.go @@ -15,30 +15,15 @@ package types import ( - "errors" - + "github.com/coreos/ignition/config/shared/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(), + Message: errors.ErrPasswdCreateDeprecated.Error(), Kind: report.EntryWarning, }) addErr := func(err error) { @@ -48,34 +33,34 @@ func (p PasswdUser) Validate() report.Report { }) } if p.Gecos != "" { - addErr(ErrPasswdCreateAndGecos) + addErr(errors.ErrPasswdCreateAndGecos) } if len(p.Groups) > 0 { - addErr(ErrPasswdCreateAndGroups) + addErr(errors.ErrPasswdCreateAndGroups) } if p.HomeDir != "" { - addErr(ErrPasswdCreateAndHomeDir) + addErr(errors.ErrPasswdCreateAndHomeDir) } if p.NoCreateHome { - addErr(ErrPasswdCreateAndNoCreateHome) + addErr(errors.ErrPasswdCreateAndNoCreateHome) } if p.NoLogInit { - addErr(ErrPasswdCreateAndNoLogInit) + addErr(errors.ErrPasswdCreateAndNoLogInit) } if p.NoUserGroup { - addErr(ErrPasswdCreateAndNoUserGroup) + addErr(errors.ErrPasswdCreateAndNoUserGroup) } if p.PrimaryGroup != "" { - addErr(ErrPasswdCreateAndPrimaryGroup) + addErr(errors.ErrPasswdCreateAndPrimaryGroup) } if p.Shell != "" { - addErr(ErrPasswdCreateAndShell) + addErr(errors.ErrPasswdCreateAndShell) } if p.System { - addErr(ErrPasswdCreateAndSystem) + addErr(errors.ErrPasswdCreateAndSystem) } if p.UID != nil { - addErr(ErrPasswdCreateAndUID) + addErr(errors.ErrPasswdCreateAndUID) } } return r diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/path.go b/vendor/github.com/coreos/ignition/config/v2_1/types/path.go index 0bdbdcb0..780607c3 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/path.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/path.go @@ -15,17 +15,14 @@ package types import ( - "errors" "path" -) -var ( - ErrPathRelative = errors.New("path not absolute") + "github.com/coreos/ignition/config/shared/errors" ) func validatePath(p string) error { if !path.IsAbs(p) { - return ErrPathRelative + return errors.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 index f43b152d..3aceaa9f 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/raid.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/raid.go @@ -15,8 +15,7 @@ package types import ( - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -26,7 +25,7 @@ func (n Raid) ValidateLevel() report.Report { case "linear", "raid0", "0", "stripe": if n.Spares != 0 { r.Add(report.Entry{ - Message: fmt.Sprintf("spares unsupported for %q arrays", n.Level), + Message: errors.ErrSparesUnsupportedForLevel.Error(), Kind: report.EntryError, }) } @@ -37,7 +36,7 @@ func (n Raid) ValidateLevel() report.Report { case "raid10", "10": default: r.Add(report.Entry{ - Message: fmt.Sprintf("unrecognized raid level: %q", n.Level), + Message: errors.ErrUnrecognizedRaidLevel.Error(), Kind: report.EntryError, }) } @@ -49,7 +48,7 @@ func (n Raid) ValidateDevices() 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), + Message: errors.ErrPathRelative.Error(), Kind: report.EntryError, }) } 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 index 3d3fc8db..07e6fe6f 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/unit.go @@ -15,29 +15,30 @@ package types import ( - "bytes" - "errors" "fmt" "path" + "strings" "github.com/coreos/go-systemd/unit" + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/shared/validations" "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 { + opts, err := validateUnitContent(u.Contents) + if err != nil { r.Add(report.Entry{ Message: err.Error(), Kind: report.EntryError, }) } + + isEnabled := u.Enable || (u.Enabled != nil && *u.Enabled) + r.Merge(validations.ValidateInstallSection(u.Name, isEnabled, u.Contents == "", opts)) + return r } @@ -47,7 +48,7 @@ func (u Unit) ValidateName() report.Report { case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": default: r.Add(report.Entry{ - Message: ErrInvalidSystemdExt.Error(), + Message: errors.ErrInvalidSystemdExt.Error(), Kind: report.EntryError, }) } @@ -57,7 +58,7 @@ func (u Unit) ValidateName() report.Report { func (d Dropin) Validate() report.Report { r := report.Report{} - if err := validateUnitContent(d.Contents); err != nil { + if _, err := validateUnitContent(d.Contents); err != nil { r.Add(report.Entry{ Message: err.Error(), Kind: report.EntryError, @@ -68,7 +69,7 @@ func (d Dropin) Validate() report.Report { case ".conf": default: r.Add(report.Entry{ - Message: fmt.Sprintf("invalid systemd unit drop-in extension: %q", path.Ext(d.Name)), + Message: errors.ErrInvalidSystemdDropinExt.Error(), Kind: report.EntryError, }) } @@ -79,7 +80,7 @@ func (d Dropin) Validate() report.Report { func (u Networkdunit) Validate() report.Report { r := report.Report{} - if err := validateUnitContent(u.Contents); err != nil { + if _, err := validateUnitContent(u.Contents); err != nil { r.Add(report.Entry{ Message: err.Error(), Kind: report.EntryError, @@ -90,7 +91,7 @@ func (u Networkdunit) Validate() report.Report { case ".link", ".netdev", ".network": default: r.Add(report.Entry{ - Message: ErrInvalidNetworkdExt.Error(), + Message: errors.ErrInvalidNetworkdExt.Error(), Kind: report.EntryError, }) } @@ -98,12 +99,11 @@ func (u Networkdunit) Validate() report.Report { return r } -func validateUnitContent(content string) error { - c := bytes.NewBufferString(content) - _, err := unit.Deserialize(c) +func validateUnitContent(content string) ([]*unit.UnitOption, error) { + c := strings.NewReader(content) + opts, err := unit.Deserialize(c) if err != nil { - return fmt.Errorf("invalid unit content: %s", err) + return nil, fmt.Errorf("invalid unit content: %s", err) } - - return nil + return opts, 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 index f6270c9a..648328ac 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/url.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/url.go @@ -15,16 +15,12 @@ package types import ( - "errors" "net/url" + "github.com/coreos/ignition/config/shared/errors" "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 == "" { @@ -32,11 +28,18 @@ func validateURL(s string) error { } u, err := url.Parse(s) if err != nil { - return err + return errors.ErrInvalidUrl } switch u.Scheme { - case "http", "https", "oem", "tftp", "s3": + case "http", "https", "oem", "tftp": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } return nil case "data": if _, err := dataurl.DecodeString(s); err != nil { @@ -44,6 +47,6 @@ func validateURL(s string) error { } return nil default: - return ErrInvalidScheme + return errors.ErrInvalidScheme } } diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_1/types/verification.go index d2158b80..51e7d155 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/verification.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/verification.go @@ -17,18 +17,12 @@ package types import ( "crypto" "encoding/hex" - "errors" "strings" + "github.com/coreos/ignition/config/shared/errors" "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) { @@ -38,7 +32,7 @@ func (v Verification) HashParts() (string, string, error) { } parts := strings.SplitN(*v.Hash, "-", 2) if len(parts) != 2 { - return "", "", ErrHashMalformed + return "", "", errors.ErrHashMalformed } return parts[0], parts[1], nil @@ -66,7 +60,7 @@ func (v Verification) Validate() report.Report { hash = crypto.SHA512 default: r.Add(report.Entry{ - Message: ErrHashUnrecognized.Error(), + Message: errors.ErrHashUnrecognized.Error(), Kind: report.EntryError, }) return r @@ -74,7 +68,7 @@ func (v Verification) Validate() report.Report { if len(sum) != hex.EncodedLen(hash.Size()) { r.Add(report.Entry{ - Message: ErrHashWrongSize.Error(), + Message: errors.ErrHashWrongSize.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/cloudinit.go b/vendor/github.com/coreos/ignition/config/v2_2/cloudinit.go similarity index 98% rename from vendor/github.com/coreos/ignition/config/cloudinit.go rename to vendor/github.com/coreos/ignition/config/v2_2/cloudinit.go index 8f1f5fb7..36a54393 100644 --- a/vendor/github.com/coreos/ignition/config/cloudinit.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/cloudinit.go @@ -14,7 +14,7 @@ // These functions are copied from github.com/coreos/coreos-cloudinit/config. -package config +package v2_2 import ( "bytes" diff --git a/vendor/github.com/coreos/ignition/config/v2_2/config.go b/vendor/github.com/coreos/ignition/config/v2_2/config.go new file mode 100644 index 00000000..c934a9e4 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/config.go @@ -0,0 +1,71 @@ +// 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_2 + +import ( + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/v2_1" + "github.com/coreos/ignition/config/v2_2/types" + "github.com/coreos/ignition/config/validate" + "github.com/coreos/ignition/config/validate/report" + + json "github.com/ajeddeloh/go-json" + "github.com/coreos/go-semver/semver" +) + +// Parse parses the raw config into a types.Config struct and generates a report of any +// errors, warnings, info, and deprecations it encountered. Unlike config.Parse, +// it does not attempt to translate the config. +func Parse(rawConfig []byte) (types.Config, report.Report, error) { + if isEmpty(rawConfig) { + return types.Config{}, report.Report{}, errors.ErrEmpty + } else if isCloudConfig(rawConfig) { + return types.Config{}, report.Report{}, errors.ErrCloudConfig + } else if isScript(rawConfig) { + return types.Config{}, report.Report{}, errors.ErrScript + } + + var err error + var config types.Config + + err = json.Unmarshal(rawConfig, &config) + + version, semverErr := semver.NewVersion(config.Ignition.Version) + + if err != nil || semverErr != nil || version.LessThan(types.MaxVersion) { + // We can fail unmarshaling if it's an older config. Attempt to parse + // it as such. + config, rpt, err := v2_1.Parse(rawConfig) + if err != nil { + return types.Config{}, rpt, err + } + return TranslateFromV2_1(config), rpt, err + } + + if *version != types.MaxVersion { + return types.Config{}, report.Report{}, errors.ErrUnknownVersion + } + + rpt := validate.ValidateConfig(rawConfig, config) + if rpt.IsFatal() { + return types.Config{}, rpt, errors.ErrInvalid + } + + return config, rpt, nil +} + +func isEmpty(userdata []byte) bool { + return len(userdata) == 0 +} diff --git a/vendor/github.com/coreos/ignition/config/v2_2/translate.go b/vendor/github.com/coreos/ignition/config/v2_2/translate.go new file mode 100644 index 00000000..56a6b33f --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/translate.go @@ -0,0 +1,354 @@ +// Copyright 2018 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_2 + +import ( + "github.com/coreos/ignition/config/util" + v2_1 "github.com/coreos/ignition/config/v2_1/types" + "github.com/coreos/ignition/config/v2_2/types" +) + +// 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_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.Group { + var res []types.Group + for _, g := range old { + res = append(res, types.Group(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: util.IntToPtr(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: util.IntToPtr(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.SystemdDropin { + var res []types.SystemdDropin + for _, x := range old { + res = append(res, types.SystemdDropin{ + 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/link.go b/vendor/github.com/coreos/ignition/config/v2_2/types/ca.go similarity index 67% rename from vendor/github.com/coreos/ignition/config/types/link.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/ca.go index 1b7794c0..7440e1e2 100644 --- a/vendor/github.com/coreos/ignition/config/types/link.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/ca.go @@ -1,4 +1,4 @@ -// Copyright 2017 CoreOS, Inc. +// Copyright 2018 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,21 +15,13 @@ package types 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, - }) - } +func (c CaReference) ValidateSource() report.Report { + err := validateURL(c.Source) + if err != nil { + return report.ReportFromError(err, report.EntryError) } - return r + return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_2/types/config.go b/vendor/github.com/coreos/ignition/config/v2_2/types/config.go new file mode 100644 index 00000000..b1fcfcd9 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/config.go @@ -0,0 +1,91 @@ +// 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: 2, + } +) + +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 checkNodeFilesystems(node Node, filesystems map[string]struct{}, nodeType string) report.Report { + r := report.Report{} + if node.Filesystem == "" { + // Filesystem was not specified. This is an error, but its handled in types.File's Validate, not here + return r + } + _, ok := filesystems[node.Filesystem] + if !ok { + r.Add(report.Entry{ + Kind: report.EntryWarning, + Message: fmt.Sprintf("%v %q references nonexistent filesystem %q. (This is ok if it is defined in a referenced config)", + nodeType, node.Path, node.Filesystem), + }) + } + return r +} + +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 { + r.Merge(checkNodeFilesystems(file.Node, filesystems, "File")) + } + for _, link := range cfg.Storage.Links { + r.Merge(checkNodeFilesystems(link.Node, filesystems, "Link")) + } + for _, dir := range cfg.Storage.Directories { + r.Merge(checkNodeFilesystems(dir.Node, filesystems, "Directory")) + } +} + +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/directory.go b/vendor/github.com/coreos/ignition/config/v2_2/types/directory.go similarity index 82% rename from vendor/github.com/coreos/ignition/config/types/directory.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/directory.go index 16adad05..9fdc732a 100644 --- a/vendor/github.com/coreos/ignition/config/types/directory.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/directory.go @@ -15,6 +15,7 @@ package types import ( + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -26,5 +27,11 @@ func (d Directory) ValidateMode() report.Report { Kind: report.EntryError, }) } + if d.Mode == nil { + r.Add(report.Entry{ + Message: errors.ErrPermissionsUnset.Error(), + Kind: report.EntryWarning, + }) + } return r } diff --git a/vendor/github.com/coreos/ignition/config/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_2/types/disk.go similarity index 91% rename from vendor/github.com/coreos/ignition/config/types/disk.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/disk.go index f556e182..f0af504a 100644 --- a/vendor/github.com/coreos/ignition/config/types/disk.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/disk.go @@ -15,8 +15,7 @@ package types import ( - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -26,7 +25,7 @@ func (n Disk) Validate() report.Report { func (n Disk) ValidateDevice() report.Report { if len(n.Device) == 0 { - return report.ReportFromError(fmt.Errorf("disk device is required"), report.EntryError) + return report.ReportFromError(errors.ErrDiskDeviceRequired, report.EntryError) } if err := validatePath(string(n.Device)); err != nil { return report.ReportFromError(err, report.EntryError) @@ -38,19 +37,19 @@ 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), + Message: errors.ErrPartitionNumbersCollide.Error(), Kind: report.EntryError, }) } if n.partitionsOverlap() { r.Add(report.Entry{ - Message: fmt.Sprintf("disk %q: partitions overlap", n.Device), + Message: errors.ErrPartitionsOverlap.Error(), Kind: report.EntryError, }) } if n.partitionsMisaligned() { r.Add(report.Entry{ - Message: fmt.Sprintf("disk %q: partitions misaligned", n.Device), + Message: errors.ErrPartitionsMisaligned.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/v2_2/types/file.go b/vendor/github.com/coreos/ignition/config/v2_2/types/file.go new file mode 100644 index 00000000..b235d16c --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/file.go @@ -0,0 +1,69 @@ +// 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 ( + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (f File) Validate() report.Report { + if f.Overwrite != nil && *f.Overwrite && f.Append { + return report.ReportFromError(errors.ErrAppendAndOverwrite, report.EntryError) + } + return report.Report{} +} + +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, + }) + } + if f.Mode == nil { + r.Add(report.Entry{ + Message: errors.ErrPermissionsUnset.Error(), + Kind: report.EntryWarning, + }) + } + return r +} + +func (fc FileContents) ValidateCompression() report.Report { + r := report.Report{} + switch fc.Compression { + case "", "gzip": + default: + r.Add(report.Entry{ + Message: errors.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: err.Error(), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_2/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_2/types/filesystem.go new file mode 100644 index 00000000..a2e43ffd --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/filesystem.go @@ -0,0 +1,144 @@ +// 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 ( + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (f Filesystem) Validate() report.Report { + r := report.Report{} + if f.Mount == nil && f.Path == nil { + r.Add(report.Entry{ + Message: errors.ErrFilesystemNoMountPath.Error(), + Kind: report.EntryError, + }) + } + if f.Mount != nil { + if f.Path != nil { + r.Add(report.Entry{ + Message: errors.ErrFilesystemMountAndPath.Error(), + Kind: report.EntryError, + }) + } + if f.Mount.Create != nil { + if f.Mount.WipeFilesystem { + r.Add(report.Entry{ + Message: errors.ErrUsedCreateAndWipeFilesystem.Error(), + Kind: report.EntryError, + }) + } + if len(f.Mount.Options) > 0 { + r.Add(report.Entry{ + Message: errors.ErrUsedCreateAndMountOpts.Error(), + Kind: report.EntryError, + }) + } + r.Add(report.Entry{ + Message: errors.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: errors.ErrPathRelative.Error(), + 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: errors.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: errors.ErrExt4LabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "btrfs": + if len(*m.Label) > 256 { + // source: man mkfs.btrfs + r.Add(report.Entry{ + Message: errors.ErrBtrfsLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "xfs": + if len(*m.Label) > 12 { + // source: man mkfs.xfs + r.Add(report.Entry{ + Message: errors.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: errors.ErrSwapLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + case "vfat": + if len(*m.Label) > 11 { + // source: man mkfs.fat + r.Add(report.Entry{ + Message: errors.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/v2_2/types/ignition.go similarity index 73% rename from vendor/github.com/coreos/ignition/config/types/ignition.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/ignition.go index 661b898d..bddf4958 100644 --- a/vendor/github.com/coreos/ignition/config/types/ignition.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/ignition.go @@ -15,19 +15,12 @@ package types import ( - "errors" - "github.com/coreos/go-semver/semver" + "github.com/coreos/ignition/config/shared/errors" "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) @@ -47,13 +40,13 @@ func (v Ignition) Semver() (*semver.Version, error) { func (v Ignition) Validate() report.Report { tv, err := v.Semver() if err != nil { - return report.ReportFromError(ErrInvalidVersion, report.EntryError) + return report.ReportFromError(errors.ErrInvalidVersion, report.EntryError) } if MaxVersion.Major > tv.Major { - return report.ReportFromError(ErrOldVersion, report.EntryError) + return report.ReportFromError(errors.ErrOldVersion, report.EntryError) } if MaxVersion.LessThan(*tv) { - return report.ReportFromError(ErrNewVersion, report.EntryError) + return report.ReportFromError(errors.ErrNewVersion, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/types/mode.go b/vendor/github.com/coreos/ignition/config/v2_2/types/mode.go similarity index 79% rename from vendor/github.com/coreos/ignition/config/types/mode.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/mode.go index 09608b51..d06045d6 100644 --- a/vendor/github.com/coreos/ignition/config/types/mode.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/mode.go @@ -15,16 +15,12 @@ package types import ( - "errors" + "github.com/coreos/ignition/config/shared/errors" ) -var ( - ErrFileIllegalMode = errors.New("illegal file mode") -) - -func validateMode(m int) error { - if m < 0 || m > 07777 { - return ErrFileIllegalMode +func validateMode(m *int) error { + if m != nil && (*m < 0 || *m > 07777) { + return errors.ErrFileIllegalMode } return nil } diff --git a/vendor/github.com/coreos/ignition/config/types/node.go b/vendor/github.com/coreos/ignition/config/v2_2/types/node.go similarity index 85% rename from vendor/github.com/coreos/ignition/config/types/node.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/node.go index 5c117f06..50badfdf 100644 --- a/vendor/github.com/coreos/ignition/config/types/node.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/node.go @@ -15,22 +15,17 @@ package types import ( - "errors" "path/filepath" + "github.com/coreos/ignition/config/shared/errors" "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(), + Message: errors.ErrNoFilesystem.Error(), Kind: report.EntryError, }) } @@ -60,7 +55,7 @@ func (nu NodeUser) Validate() report.Report { r := report.Report{} if nu.ID != nil && nu.Name != "" { r.Add(report.Entry{ - Message: ErrBothIDAndNameSet.Error(), + Message: errors.ErrBothIDAndNameSet.Error(), Kind: report.EntryError, }) } @@ -70,7 +65,7 @@ func (ng NodeGroup) Validate() report.Report { r := report.Report{} if ng.ID != nil && ng.Name != "" { r.Add(report.Entry{ - Message: ErrBothIDAndNameSet.Error(), + Message: errors.ErrBothIDAndNameSet.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_2/types/partition.go similarity index 81% rename from vendor/github.com/coreos/ignition/config/types/partition.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/partition.go index 4473b667..084dce7c 100644 --- a/vendor/github.com/coreos/ignition/config/types/partition.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/partition.go @@ -15,10 +15,11 @@ package types import ( - "errors" "fmt" "regexp" + "strings" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -26,11 +27,6 @@ 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: @@ -40,10 +36,18 @@ func (p Partition) ValidateLabel() report.Report { // with udev naming /dev/disk/by-partlabel/*. if len(p.Label) > 36 { r.Add(report.Entry{ - Message: ErrLabelTooLong.Error(), + Message: errors.ErrLabelTooLong.Error(), Kind: report.EntryError, }) } + + // sgdisk uses colons for delimitting compound arguments and does not allow escaping them. + if strings.Contains(p.Label, ":") { + r.Add(report.Entry{ + Message: errors.ErrLabelContainsColon.Error(), + Kind: report.EntryWarning, + }) + } return r } @@ -65,7 +69,7 @@ func validateGUID(guid string) report.Report { }) } else if !ok { r.Add(report.Entry{ - Message: ErrDoesntMatchGUIDRegex.Error(), + Message: errors.ErrDoesntMatchGUIDRegex.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/v2_2/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_2/types/passwd.go new file mode 100644 index 00000000..10508c56 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/passwd.go @@ -0,0 +1,67 @@ +// 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 ( + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (p PasswdUser) Validate() report.Report { + r := report.Report{} + if p.Create != nil { + r.Add(report.Entry{ + Message: errors.ErrPasswdCreateDeprecated.Error(), + Kind: report.EntryWarning, + }) + addErr := func(err error) { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + if p.Gecos != "" { + addErr(errors.ErrPasswdCreateAndGecos) + } + if len(p.Groups) > 0 { + addErr(errors.ErrPasswdCreateAndGroups) + } + if p.HomeDir != "" { + addErr(errors.ErrPasswdCreateAndHomeDir) + } + if p.NoCreateHome { + addErr(errors.ErrPasswdCreateAndNoCreateHome) + } + if p.NoLogInit { + addErr(errors.ErrPasswdCreateAndNoLogInit) + } + if p.NoUserGroup { + addErr(errors.ErrPasswdCreateAndNoUserGroup) + } + if p.PrimaryGroup != "" { + addErr(errors.ErrPasswdCreateAndPrimaryGroup) + } + if p.Shell != "" { + addErr(errors.ErrPasswdCreateAndShell) + } + if p.System { + addErr(errors.ErrPasswdCreateAndSystem) + } + if p.UID != nil { + addErr(errors.ErrPasswdCreateAndUID) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/types/path.go b/vendor/github.com/coreos/ignition/config/v2_2/types/path.go similarity index 88% rename from vendor/github.com/coreos/ignition/config/types/path.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/path.go index 0bdbdcb0..780607c3 100644 --- a/vendor/github.com/coreos/ignition/config/types/path.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/path.go @@ -15,17 +15,14 @@ package types import ( - "errors" "path" -) -var ( - ErrPathRelative = errors.New("path not absolute") + "github.com/coreos/ignition/config/shared/errors" ) func validatePath(p string) error { if !path.IsAbs(p) { - return ErrPathRelative + return errors.ErrPathRelative } return nil } diff --git a/vendor/github.com/coreos/ignition/config/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_2/types/raid.go similarity index 85% rename from vendor/github.com/coreos/ignition/config/types/raid.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/raid.go index f43b152d..3aceaa9f 100644 --- a/vendor/github.com/coreos/ignition/config/types/raid.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/raid.go @@ -15,8 +15,7 @@ package types import ( - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -26,7 +25,7 @@ func (n Raid) ValidateLevel() report.Report { case "linear", "raid0", "0", "stripe": if n.Spares != 0 { r.Add(report.Entry{ - Message: fmt.Sprintf("spares unsupported for %q arrays", n.Level), + Message: errors.ErrSparesUnsupportedForLevel.Error(), Kind: report.EntryError, }) } @@ -37,7 +36,7 @@ func (n Raid) ValidateLevel() report.Report { case "raid10", "10": default: r.Add(report.Entry{ - Message: fmt.Sprintf("unrecognized raid level: %q", n.Level), + Message: errors.ErrUnrecognizedRaidLevel.Error(), Kind: report.EntryError, }) } @@ -49,7 +48,7 @@ func (n Raid) ValidateDevices() 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), + Message: errors.ErrPathRelative.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/types/schema.go b/vendor/github.com/coreos/ignition/config/v2_2/types/schema.go similarity index 78% rename from vendor/github.com/coreos/ignition/config/types/schema.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/schema.go index e0caed5e..4b32b337 100644 --- a/vendor/github.com/coreos/ignition/config/types/schema.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/schema.go @@ -2,6 +2,11 @@ package types // generated by "schematyper --package=types schema/ignition.json -o config/types/schema.go --root-type=Config" -- DO NOT EDIT +type CaReference struct { + Source string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + type Config struct { Ignition Ignition `json:"ignition"` Networkd Networkd `json:"networkd,omitempty"` @@ -30,7 +35,7 @@ type Directory struct { } type DirectoryEmbedded1 struct { - Mode int `json:"mode,omitempty"` + Mode *int `json:"mode,omitempty"` } type Disk struct { @@ -39,11 +44,6 @@ type Disk struct { WipeTable bool `json:"wipeTable,omitempty"` } -type Dropin struct { - Contents string `json:"contents,omitempty"` - Name string `json:"name,omitempty"` -} - type File struct { Node FileEmbedded1 @@ -56,8 +56,9 @@ type FileContents struct { } type FileEmbedded1 struct { + Append bool `json:"append,omitempty"` Contents FileContents `json:"contents,omitempty"` - Mode int `json:"mode,omitempty"` + Mode *int `json:"mode,omitempty"` } type Filesystem struct { @@ -66,8 +67,11 @@ type Filesystem struct { Path *string `json:"path,omitempty"` } +type Group string + type Ignition struct { Config IgnitionConfig `json:"config,omitempty"` + Security Security `json:"security,omitempty"` Timeouts Timeouts `json:"timeouts,omitempty"` Version string `json:"version,omitempty"` } @@ -103,16 +107,23 @@ type Networkd struct { Units []Networkdunit `json:"units,omitempty"` } -type Networkdunit struct { +type NetworkdDropin struct { Contents string `json:"contents,omitempty"` Name string `json:"name,omitempty"` } +type Networkdunit struct { + Contents string `json:"contents,omitempty"` + Dropins []NetworkdDropin `json:"dropins,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"` + Filesystem string `json:"filesystem,omitempty"` + Group *NodeGroup `json:"group,omitempty"` + Overwrite *bool `json:"overwrite,omitempty"` + Path string `json:"path,omitempty"` + User *NodeUser `json:"user,omitempty"` } type NodeGroup struct { @@ -149,7 +160,7 @@ type PasswdGroup struct { type PasswdUser struct { Create *Usercreate `json:"create,omitempty"` Gecos string `json:"gecos,omitempty"` - Groups []PasswdUserGroup `json:"groups,omitempty"` + Groups []Group `json:"groups,omitempty"` HomeDir string `json:"homeDir,omitempty"` Name string `json:"name,omitempty"` NoCreateHome bool `json:"noCreateHome,omitempty"` @@ -163,17 +174,22 @@ type PasswdUser struct { 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"` + Devices []Device `json:"devices,omitempty"` + Level string `json:"level,omitempty"` + Name string `json:"name,omitempty"` + Options []RaidOption `json:"options,omitempty"` + Spares int `json:"spares,omitempty"` } +type RaidOption string + type SSHAuthorizedKey string +type Security struct { + TLS TLS `json:"tls,omitempty"` +} + type Storage struct { Directories []Directory `json:"directories,omitempty"` Disks []Disk `json:"disks,omitempty"` @@ -187,18 +203,27 @@ type Systemd struct { Units []Unit `json:"units,omitempty"` } +type SystemdDropin struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name,omitempty"` +} + +type TLS struct { + CertificateAuthorities []CaReference `json:"certificateAuthorities,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"` + Contents string `json:"contents,omitempty"` + Dropins []SystemdDropin `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 { diff --git a/vendor/github.com/coreos/ignition/config/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_2/types/unit.go similarity index 58% rename from vendor/github.com/coreos/ignition/config/types/unit.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/unit.go index 3d3fc8db..70fe1179 100644 --- a/vendor/github.com/coreos/ignition/config/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/unit.go @@ -15,29 +15,30 @@ package types import ( - "bytes" - "errors" "fmt" "path" + "strings" "github.com/coreos/go-systemd/unit" + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/shared/validations" "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 { + opts, err := validateUnitContent(u.Contents) + if err != nil { r.Add(report.Entry{ Message: err.Error(), Kind: report.EntryError, }) } + + isEnabled := u.Enable || (u.Enabled != nil && *u.Enabled) + r.Merge(validations.ValidateInstallSection(u.Name, isEnabled, u.Contents == "", opts)) + return r } @@ -47,17 +48,17 @@ func (u Unit) ValidateName() report.Report { case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": default: r.Add(report.Entry{ - Message: ErrInvalidSystemdExt.Error(), + Message: errors.ErrInvalidSystemdExt.Error(), Kind: report.EntryError, }) } return r } -func (d Dropin) Validate() report.Report { +func (d SystemdDropin) Validate() report.Report { r := report.Report{} - if err := validateUnitContent(d.Contents); err != nil { + if _, err := validateUnitContent(d.Contents); err != nil { r.Add(report.Entry{ Message: err.Error(), Kind: report.EntryError, @@ -68,7 +69,7 @@ func (d Dropin) Validate() report.Report { case ".conf": default: r.Add(report.Entry{ - Message: fmt.Sprintf("invalid systemd unit drop-in extension: %q", path.Ext(d.Name)), + Message: errors.ErrInvalidSystemdDropinExt.Error(), Kind: report.EntryError, }) } @@ -79,7 +80,7 @@ func (d Dropin) Validate() report.Report { func (u Networkdunit) Validate() report.Report { r := report.Report{} - if err := validateUnitContent(u.Contents); err != nil { + if _, err := validateUnitContent(u.Contents); err != nil { r.Add(report.Entry{ Message: err.Error(), Kind: report.EntryError, @@ -90,7 +91,7 @@ func (u Networkdunit) Validate() report.Report { case ".link", ".netdev", ".network": default: r.Add(report.Entry{ - Message: ErrInvalidNetworkdExt.Error(), + Message: errors.ErrInvalidNetworkdExt.Error(), Kind: report.EntryError, }) } @@ -98,12 +99,33 @@ func (u Networkdunit) Validate() report.Report { 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) +func (d NetworkdDropin) Validate() report.Report { + r := report.Report{} + + if _, err := validateUnitContent(d.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) } - return nil + switch path.Ext(d.Name) { + case ".conf": + default: + r.Add(report.Entry{ + Message: errors.ErrInvalidNetworkdDropinExt.Error(), + Kind: report.EntryError, + }) + } + + return r +} + +func validateUnitContent(content string) ([]*unit.UnitOption, error) { + c := strings.NewReader(content) + opts, err := unit.Deserialize(c) + if err != nil { + return nil, fmt.Errorf("invalid unit content: %s", err) + } + return opts, nil } diff --git a/vendor/github.com/coreos/ignition/config/types/url.go b/vendor/github.com/coreos/ignition/config/v2_2/types/url.go similarity index 75% rename from vendor/github.com/coreos/ignition/config/types/url.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/url.go index f6270c9a..11148fc0 100644 --- a/vendor/github.com/coreos/ignition/config/types/url.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/url.go @@ -15,14 +15,11 @@ package types import ( - "errors" "net/url" "github.com/vincent-petithory/dataurl" -) -var ( - ErrInvalidScheme = errors.New("invalid url scheme") + "github.com/coreos/ignition/config/shared/errors" ) func validateURL(s string) error { @@ -32,11 +29,18 @@ func validateURL(s string) error { } u, err := url.Parse(s) if err != nil { - return err + return errors.ErrInvalidUrl } switch u.Scheme { - case "http", "https", "oem", "tftp", "s3": + case "http", "https", "oem", "tftp": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } return nil case "data": if _, err := dataurl.DecodeString(s); err != nil { @@ -44,6 +48,6 @@ func validateURL(s string) error { } return nil default: - return ErrInvalidScheme + return errors.ErrInvalidScheme } } diff --git a/vendor/github.com/coreos/ignition/config/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_2/types/verification.go similarity index 83% rename from vendor/github.com/coreos/ignition/config/types/verification.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/verification.go index d2158b80..51e7d155 100644 --- a/vendor/github.com/coreos/ignition/config/types/verification.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/verification.go @@ -17,18 +17,12 @@ package types import ( "crypto" "encoding/hex" - "errors" "strings" + "github.com/coreos/ignition/config/shared/errors" "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) { @@ -38,7 +32,7 @@ func (v Verification) HashParts() (string, string, error) { } parts := strings.SplitN(*v.Hash, "-", 2) if len(parts) != 2 { - return "", "", ErrHashMalformed + return "", "", errors.ErrHashMalformed } return parts[0], parts[1], nil @@ -66,7 +60,7 @@ func (v Verification) Validate() report.Report { hash = crypto.SHA512 default: r.Add(report.Entry{ - Message: ErrHashUnrecognized.Error(), + Message: errors.ErrHashUnrecognized.Error(), Kind: report.EntryError, }) return r @@ -74,7 +68,7 @@ func (v Verification) Validate() report.Report { if len(sum) != hex.EncodedLen(hash.Size()) { r.Add(report.Entry{ - Message: ErrHashWrongSize.Error(), + Message: errors.ErrHashWrongSize.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/ca.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/ca.go new file mode 100644 index 00000000..7440e1e2 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/ca.go @@ -0,0 +1,27 @@ +// Copyright 2018 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 ( + "github.com/coreos/ignition/config/validate/report" +) + +func (c CaReference) ValidateSource() report.Report { + err := validateURL(c.Source) + if err != nil { + return report.ReportFromError(err, report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/types/config.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/config.go similarity index 99% rename from vendor/github.com/coreos/ignition/config/types/config.go rename to vendor/github.com/coreos/ignition/config/v2_4_experimental/types/config.go index b948a164..e3a05e80 100644 --- a/vendor/github.com/coreos/ignition/config/types/config.go +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/config.go @@ -25,7 +25,7 @@ import ( var ( MaxVersion = semver.Version{ Major: 2, - Minor: 2, + Minor: 4, PreRelease: "experimental", } ) diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/link.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/directory.go similarity index 66% rename from vendor/github.com/coreos/ignition/config/v2_1/types/link.go rename to vendor/github.com/coreos/ignition/config/v2_4_experimental/types/directory.go index 1b7794c0..9fdc732a 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/link.go +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/directory.go @@ -15,21 +15,23 @@ package types import ( - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -func (s Link) Validate() report.Report { +func (d Directory) ValidateMode() 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, - }) - } + if err := validateMode(d.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + if d.Mode == nil { + r.Add(report.Entry{ + Message: errors.ErrPermissionsUnset.Error(), + Kind: report.EntryWarning, + }) } return r } diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/disk.go new file mode 100644 index 00000000..1430b0fd --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/disk.go @@ -0,0 +1,164 @@ +// 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 ( + "github.com/coreos/ignition/config/shared/errors" + "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(errors.ErrDiskDeviceRequired, 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: errors.ErrPartitionNumbersCollide.Error(), + Kind: report.EntryError, + }) + } + if n.partitionsOverlap() { + r.Add(report.Entry{ + Message: errors.ErrPartitionsOverlap.Error(), + Kind: report.EntryError, + }) + } + if n.partitionsMisaligned() { + r.Add(report.Entry{ + Message: errors.ErrPartitionsMisaligned.Error(), + Kind: report.EntryError, + }) + } + if n.partitionsMixZeroesAndNonexistence() { + r.Add(report.Entry{ + Message: errors.ErrZeroesWithShouldNotExist.Error(), + Kind: report.EntryError, + }) + } + if n.partitionsUnitsMismatch() { + r.Add(report.Entry{ + Message: errors.ErrPartitionsUnitsMismatch.Error(), + 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 { + if p.Number != 0 { + // a number of 0 means next available number, multiple devices can specify this + 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. Only used by partitionsOverlap. Requires non-nil Start and Size. +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 == nil || p.Size == nil || *p.Start == 0 { + continue + } + + for _, o := range n.Partitions { + if o.Start == nil || o.Size == nil || 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 != nil && ((*p.Start & (2048 - 1)) != 0) { + return true + } + } + return false +} + +func (n Disk) partitionsMixZeroesAndNonexistence() bool { + hasZero := false + hasShouldNotExist := false + for _, p := range n.Partitions { + hasShouldNotExist = hasShouldNotExist || (p.ShouldExist != nil && !*p.ShouldExist) + hasZero = hasZero || (p.Number == 0) + } + return hasZero && hasShouldNotExist +} + +func (n Disk) partitionsUnitsMismatch() bool { + partsInMb := false + partsNotInMb := false + for _, p := range n.Partitions { + if p.Size != nil || p.Start != nil { + partsNotInMb = true + } + if p.SizeMiB != nil || p.StartMiB != nil { + partsInMb = true + } + } + return partsInMb && partsNotInMb +} diff --git a/vendor/github.com/coreos/ignition/config/types/file.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/file.go similarity index 75% rename from vendor/github.com/coreos/ignition/config/types/file.go rename to vendor/github.com/coreos/ignition/config/v2_4_experimental/types/file.go index 866fc054..1897dc42 100644 --- a/vendor/github.com/coreos/ignition/config/types/file.go +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/file.go @@ -15,15 +15,18 @@ package types import ( - "errors" "fmt" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrCompressionInvalid = errors.New("invalid compression method") -) +func (f File) Validate() report.Report { + if f.Overwrite != nil && *f.Overwrite && f.Append { + return report.ReportFromError(errors.ErrAppendAndOverwrite, report.EntryError) + } + return report.Report{} +} func (f File) ValidateMode() report.Report { r := report.Report{} @@ -33,6 +36,12 @@ func (f File) ValidateMode() report.Report { Kind: report.EntryError, }) } + if f.Mode == nil { + r.Add(report.Entry{ + Message: errors.ErrPermissionsUnset.Error(), + Kind: report.EntryWarning, + }) + } return r } @@ -42,7 +51,7 @@ func (fc FileContents) ValidateCompression() report.Report { case "", "gzip": default: r.Add(report.Entry{ - Message: ErrCompressionInvalid.Error(), + Message: errors.ErrCompressionInvalid.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/filesystem.go similarity index 63% rename from vendor/github.com/coreos/ignition/config/types/filesystem.go rename to vendor/github.com/coreos/ignition/config/v2_4_experimental/types/filesystem.go index 3c5a47d5..2e847da6 100644 --- a/vendor/github.com/coreos/ignition/config/types/filesystem.go +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/filesystem.go @@ -15,56 +15,42 @@ package types import ( - "errors" "fmt" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrFilesystemInvalidFormat = errors.New("invalid filesystem format") - ErrFilesystemNoMountPath = errors.New("filesystem is missing mount or path") - ErrFilesystemMountAndPath = errors.New("filesystem has both mount and path defined") - 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(), + Message: errors.ErrFilesystemNoMountPath.Error(), Kind: report.EntryError, }) } if f.Mount != nil { if f.Path != nil { r.Add(report.Entry{ - Message: ErrFilesystemMountAndPath.Error(), + Message: errors.ErrFilesystemMountAndPath.Error(), Kind: report.EntryError, }) } if f.Mount.Create != nil { if f.Mount.WipeFilesystem { r.Add(report.Entry{ - Message: ErrUsedCreateAndWipeFilesystem.Error(), + Message: errors.ErrUsedCreateAndWipeFilesystem.Error(), Kind: report.EntryError, }) } if len(f.Mount.Options) > 0 { r.Add(report.Entry{ - Message: ErrUsedCreateAndMountOpts.Error(), + Message: errors.ErrUsedCreateAndMountOpts.Error(), Kind: report.EntryError, }) } r.Add(report.Entry{ - Message: ErrWarningCreateDeprecated.Error(), + Message: errors.ErrWarningCreateDeprecated.Error(), Kind: report.EntryWarning, }) } @@ -89,7 +75,7 @@ func (m Mount) Validate() report.Report { case "ext4", "btrfs", "xfs", "swap", "vfat": default: r.Add(report.Entry{ - Message: ErrFilesystemInvalidFormat.Error(), + Message: errors.ErrFilesystemInvalidFormat.Error(), Kind: report.EntryError, }) } @@ -117,7 +103,7 @@ func (m Mount) ValidateLabel() report.Report { if len(*m.Label) > 16 { // source: man mkfs.ext4 r.Add(report.Entry{ - Message: ErrExt4LabelTooLong.Error(), + Message: errors.ErrExt4LabelTooLong.Error(), Kind: report.EntryError, }) } @@ -125,7 +111,7 @@ func (m Mount) ValidateLabel() report.Report { if len(*m.Label) > 256 { // source: man mkfs.btrfs r.Add(report.Entry{ - Message: ErrBtrfsLabelTooLong.Error(), + Message: errors.ErrBtrfsLabelTooLong.Error(), Kind: report.EntryError, }) } @@ -133,7 +119,7 @@ func (m Mount) ValidateLabel() report.Report { if len(*m.Label) > 12 { // source: man mkfs.xfs r.Add(report.Entry{ - Message: ErrXfsLabelTooLong.Error(), + Message: errors.ErrXfsLabelTooLong.Error(), Kind: report.EntryError, }) } @@ -143,7 +129,7 @@ func (m Mount) ValidateLabel() report.Report { // 15 characters, so let's enforce that. if len(*m.Label) > 15 { r.Add(report.Entry{ - Message: ErrSwapLabelTooLong.Error(), + Message: errors.ErrSwapLabelTooLong.Error(), Kind: report.EntryError, }) } @@ -151,7 +137,7 @@ func (m Mount) ValidateLabel() report.Report { if len(*m.Label) > 11 { // source: man mkfs.fat r.Add(report.Entry{ - Message: ErrVfatLabelTooLong.Error(), + Message: errors.ErrVfatLabelTooLong.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/ignition.go new file mode 100644 index 00000000..bddf4958 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/ignition.go @@ -0,0 +1,52 @@ +// 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 ( + "github.com/coreos/go-semver/semver" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +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(errors.ErrInvalidVersion, report.EntryError) + } + if MaxVersion.Major > tv.Major { + return report.ReportFromError(errors.ErrOldVersion, report.EntryError) + } + if MaxVersion.LessThan(*tv) { + return report.ReportFromError(errors.ErrNewVersion, report.EntryError) + } + return report.Report{} +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/mode.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/mode.go new file mode 100644 index 00000000..d06045d6 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/mode.go @@ -0,0 +1,26 @@ +// 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 ( + "github.com/coreos/ignition/config/shared/errors" +) + +func validateMode(m *int) error { + if m != nil && (*m < 0 || *m > 07777) { + return errors.ErrFileIllegalMode + } + return nil +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/node.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/node.go new file mode 100644 index 00000000..50badfdf --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/node.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 ( + "path/filepath" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (n Node) ValidateFilesystem() report.Report { + r := report.Report{} + if n.Filesystem == "" { + r.Add(report.Entry{ + Message: errors.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: errors.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: errors.ErrBothIDAndNameSet.Error(), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/partition.go new file mode 100644 index 00000000..dbe38adc --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/partition.go @@ -0,0 +1,112 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "regexp" + "strings" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +const ( + guidRegexStr = "^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$" +) + +func (p Partition) Validate() report.Report { + r := report.Report{} + if (p.Start != nil || p.Size != nil) && (p.StartMiB != nil || p.SizeMiB != nil) { + r.Add(report.Entry{ + Message: errors.ErrPartitionsUnitsMismatch.Error(), + Kind: report.EntryError, + }) + } + if p.ShouldExist != nil && !*p.ShouldExist && + (p.Label != nil || p.TypeGUID != "" || p.GUID != "" || p.Start != nil || p.Size != nil) { + r.Add(report.Entry{ + Message: errors.ErrShouldNotExistWithOthers.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (p Partition) ValidateSize() report.Report { + if p.Size != nil { + return report.ReportFromError(errors.ErrSizeDeprecated, report.EntryDeprecated) + } + return report.Report{} +} + +func (p Partition) ValidateStart() report.Report { + if p.Start != nil { + return report.ReportFromError(errors.ErrStartDeprecated, report.EntryDeprecated) + } + return report.Report{} +} + +func (p Partition) ValidateLabel() report.Report { + r := report.Report{} + if p.Label == nil { + return r + } + // 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: errors.ErrLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + + // sgdisk uses colons for delimitting compound arguments and does not allow escaping them. + if strings.Contains(*p.Label, ":") { + r.Add(report.Entry{ + Message: errors.ErrLabelContainsColon.Error(), + Kind: report.EntryWarning, + }) + } + 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: errors.ErrDoesntMatchGUIDRegex.Error(), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/passwd.go new file mode 100644 index 00000000..10508c56 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/passwd.go @@ -0,0 +1,67 @@ +// 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 ( + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (p PasswdUser) Validate() report.Report { + r := report.Report{} + if p.Create != nil { + r.Add(report.Entry{ + Message: errors.ErrPasswdCreateDeprecated.Error(), + Kind: report.EntryWarning, + }) + addErr := func(err error) { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + if p.Gecos != "" { + addErr(errors.ErrPasswdCreateAndGecos) + } + if len(p.Groups) > 0 { + addErr(errors.ErrPasswdCreateAndGroups) + } + if p.HomeDir != "" { + addErr(errors.ErrPasswdCreateAndHomeDir) + } + if p.NoCreateHome { + addErr(errors.ErrPasswdCreateAndNoCreateHome) + } + if p.NoLogInit { + addErr(errors.ErrPasswdCreateAndNoLogInit) + } + if p.NoUserGroup { + addErr(errors.ErrPasswdCreateAndNoUserGroup) + } + if p.PrimaryGroup != "" { + addErr(errors.ErrPasswdCreateAndPrimaryGroup) + } + if p.Shell != "" { + addErr(errors.ErrPasswdCreateAndShell) + } + if p.System { + addErr(errors.ErrPasswdCreateAndSystem) + } + if p.UID != nil { + addErr(errors.ErrPasswdCreateAndUID) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/path.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/path.go new file mode 100644 index 00000000..780607c3 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/path.go @@ -0,0 +1,28 @@ +// 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 ( + "path" + + "github.com/coreos/ignition/config/shared/errors" +) + +func validatePath(p string) error { + if !path.IsAbs(p) { + return errors.ErrPathRelative + } + return nil +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/raid.go new file mode 100644 index 00000000..3aceaa9f --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/raid.go @@ -0,0 +1,57 @@ +// 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 ( + "github.com/coreos/ignition/config/shared/errors" + "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: errors.ErrSparesUnsupportedForLevel.Error(), + 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: errors.ErrUnrecognizedRaidLevel.Error(), + 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: errors.ErrPathRelative.Error(), + Kind: report.EntryError, + }) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/schema.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/schema.go new file mode 100644 index 00000000..5f91b71e --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/schema.go @@ -0,0 +1,250 @@ +package types + +// generated by "schematyper --package=types schema/ignition.json -o internal/config/types/schema.go --root-type=Config" -- DO NOT EDIT + +type CaReference struct { + Source string `json:"source"` + Verification Verification `json:"verification,omitempty"` +} + +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"` + 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"` + Partitions []Partition `json:"partitions,omitempty"` + WipeTable bool `json:"wipeTable,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 { + Append bool `json:"append,omitempty"` + 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 Group string + +type Ignition struct { + Config IgnitionConfig `json:"config,omitempty"` + Security Security `json:"security,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"` +} + +type Mount struct { + Create *Create `json:"create,omitempty"` + Device string `json:"device"` + Format string `json:"format"` + 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 NetworkdDropin struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name"` +} + +type Networkdunit struct { + Contents string `json:"contents,omitempty"` + Dropins []NetworkdDropin `json:"dropins,omitempty"` + Name string `json:"name"` +} + +type Node struct { + Filesystem string `json:"filesystem"` + Group *NodeGroup `json:"group,omitempty"` + Overwrite *bool `json:"overwrite,omitempty"` + Path string `json:"path"` + 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"` + ShouldExist *bool `json:"shouldExist,omitempty"` + Size *int `json:"size,omitempty"` + SizeMiB *int `json:"sizeMiB,omitempty"` + Start *int `json:"start,omitempty"` + StartMiB *int `json:"startMiB,omitempty"` + TypeGUID string `json:"typeGuid,omitempty"` + WipePartitionEntry bool `json:"wipePartitionEntry,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"` + PasswordHash string `json:"passwordHash,omitempty"` + System bool `json:"system,omitempty"` +} + +type PasswdUser struct { + Create *Usercreate `json:"create,omitempty"` + Gecos string `json:"gecos,omitempty"` + Groups []Group `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + Name string `json:"name"` + 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 Raid struct { + Devices []Device `json:"devices"` + Level string `json:"level"` + Name string `json:"name"` + Options []RaidOption `json:"options,omitempty"` + Spares int `json:"spares,omitempty"` +} + +type RaidOption string + +type SSHAuthorizedKey string + +type Security struct { + TLS `json:"tls,omitempty"` +} + +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 SystemdDropin struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name"` +} + +type TLS struct { + CertificateAuthorities []CaReference `json:"certificateAuthorities,omitempty"` +} + +type Timeouts struct { + HTTPResponseHeaders *int `json:"httpResponseHeaders,omitempty"` + HTTPTotal *int `json:"httpTotal,omitempty"` +} + +type Unit struct { + Contents string `json:"contents,omitempty"` + Dropins []SystemdDropin `json:"dropins,omitempty"` + Enable bool `json:"enable,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Mask bool `json:"mask,omitempty"` + Name string `json:"name"` +} + +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_4_experimental/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/unit.go new file mode 100644 index 00000000..70fe1179 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/unit.go @@ -0,0 +1,131 @@ +// 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" + "path" + "strings" + + "github.com/coreos/go-systemd/unit" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/shared/validations" + "github.com/coreos/ignition/config/validate/report" +) + +func (u Unit) ValidateContents() report.Report { + r := report.Report{} + opts, err := validateUnitContent(u.Contents) + if err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + isEnabled := u.Enable || (u.Enabled != nil && *u.Enabled) + r.Merge(validations.ValidateInstallSection(u.Name, isEnabled, u.Contents == "", opts)) + + 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: errors.ErrInvalidSystemdExt.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (d SystemdDropin) 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: errors.ErrInvalidSystemdDropinExt.Error(), + 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: errors.ErrInvalidNetworkdExt.Error(), + Kind: report.EntryError, + }) + } + + return r +} + +func (d NetworkdDropin) 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: errors.ErrInvalidNetworkdDropinExt.Error(), + Kind: report.EntryError, + }) + } + + return r +} + +func validateUnitContent(content string) ([]*unit.UnitOption, error) { + c := strings.NewReader(content) + opts, err := unit.Deserialize(c) + if err != nil { + return nil, fmt.Errorf("invalid unit content: %s", err) + } + return opts, nil +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/url.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/url.go new file mode 100644 index 00000000..11148fc0 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/url.go @@ -0,0 +1,53 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "net/url" + + "github.com/vincent-petithory/dataurl" + + "github.com/coreos/ignition/config/shared/errors" +) + +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 errors.ErrInvalidUrl + } + + switch u.Scheme { + case "http", "https", "oem", "tftp": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } + return nil + case "data": + if _, err := dataurl.DecodeString(s); err != nil { + return err + } + return nil + default: + return errors.ErrInvalidScheme + } +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/verification.go new file mode 100644 index 00000000..51e7d155 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4_experimental/types/verification.go @@ -0,0 +1,77 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "crypto" + "encoding/hex" + "strings" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +// 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 "", "", errors.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: errors.ErrHashUnrecognized.Error(), + Kind: report.EntryError, + }) + return r + } + + if len(sum) != hex.EncodedLen(hash.Size()) { + r.Add(report.Entry{ + Message: errors.ErrHashWrongSize.Error(), + Kind: report.EntryError, + }) + } + + 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 8951be41..12f9bf20 100644 --- a/vendor/github.com/coreos/ignition/config/validate/validate.go +++ b/vendor/github.com/coreos/ignition/config/validate/validate.go @@ -15,11 +15,14 @@ package validate import ( + "bytes" "fmt" "io" "reflect" "strings" + json "github.com/ajeddeloh/go-json" + "github.com/coreos/ignition/config/validate/astjson" "github.com/coreos/ignition/config/validate/astnode" "github.com/coreos/ignition/config/validate/report" ) @@ -28,6 +31,24 @@ type validator interface { Validate() report.Report } +// ValidateConfig validates a raw config object into a given config version +func ValidateConfig(rawConfig []byte, config interface{}) report.Report { + // 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(ValidateWithoutSource(configValue)) + } else { + r.Merge(Validate(configValue, astjson.FromJsonRoot(ast), bytes.NewReader(rawConfig), true)) + } + return r +} + // 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. If checkUnusedKeys // is true, Validate will generate warnings for unused keys in the ast, otherwise it will not. @@ -153,8 +174,9 @@ func validateStruct(vObj reflect.Value, ast astnode.AstNode, source io.ReadSeeke // 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 + highlight := "" if ast != nil { - line, col, _ = ast.ValueLineCol(src) + line, col, highlight = ast.ValueLineCol(src) } // If there's a Validate func for the given field, call it @@ -162,16 +184,16 @@ func validateStruct(vObj reflect.Value, ast astnode.AstNode, source io.ReadSeeke if funct.IsValid() { if sub_node != nil { // if sub_node is non-nil, we can get better line/col info - line, col, _ = sub_node.ValueLineCol(src) + line, col, highlight = sub_node.ValueLineCol(src) } res := funct.Call(nil) sub_report := res[0].Interface().(report.Report) - sub_report.AddPosition(line, col, "") + sub_report.AddPosition(line, col, highlight) r.Merge(sub_report) } sub_report := Validate(f.Value, sub_node, src, checkUnusedKeys) - sub_report.AddPosition(line, col, "") + sub_report.AddPosition(line, col, highlight) r.Merge(sub_report) } if !isFromObject || !checkUnusedKeys { diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE index 473b670a..f38ec595 100644 --- a/vendor/github.com/stretchr/testify/LICENSE +++ b/vendor/github.com/stretchr/testify/LICENSE @@ -1,22 +1,21 @@ -Copyright (c) 2012 - 2013 Mat Ryer and Tyler Bunnell +MIT License -Please consider promoting this project if you find it useful. +Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell -Permission is hereby granted, free of charge, to any person -obtaining a copy of this software and associated documentation -files (the "Software"), to deal in the Software without restriction, -including without limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of the Software, -and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included -in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, -DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT -OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE -OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go index 5bdec56c..9bd4a80e 100644 --- a/vendor/github.com/stretchr/testify/assert/assertions.go +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -39,7 +39,7 @@ type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool // for table driven tests. type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool -// ValuesAssertionFunc is a common function prototype when validating an error value. Can be useful +// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful // for table driven tests. type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool @@ -179,7 +179,11 @@ func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { return "" } if len(msgAndArgs) == 1 { - return msgAndArgs[0].(string) + msg := msgAndArgs[0] + if msgAsStr, ok := msg.(string); ok { + return msgAsStr + } + return fmt.Sprintf("%+v", msg) } if len(msgAndArgs) > 1 { return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) @@ -415,6 +419,17 @@ func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { return Fail(t, "Expected value not to be nil.", msgAndArgs...) } +// containsKind checks if a specified kind in the slice of kinds. +func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { + for i := 0; i < len(kinds); i++ { + if kind == kinds[i] { + return true + } + } + + return false +} + // isNil checks if a specified object is nil or not, without Failing. func isNil(object interface{}) bool { if object == nil { @@ -423,7 +438,14 @@ func isNil(object interface{}) bool { value := reflect.ValueOf(object) kind := value.Kind() - if kind >= reflect.Chan && kind <= reflect.Slice && value.IsNil() { + isNilableKind := containsKind( + []reflect.Kind{ + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice}, + kind) + + if isNilableKind && value.IsNil() { return true } @@ -1327,7 +1349,7 @@ func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { } // diff returns a diff of both values as long as both are of the same type and -// are a struct, map, slice or array. Otherwise it returns an empty string. +// are a struct, map, slice, array or string. Otherwise it returns an empty string. func diff(expected interface{}, actual interface{}) string { if expected == nil || actual == nil { return "" @@ -1345,7 +1367,7 @@ func diff(expected interface{}, actual interface{}) string { } var e, a string - if ek != reflect.String { + if et != reflect.TypeOf("") { e = spewConfig.Sdump(expected) a = spewConfig.Sdump(actual) } else { diff --git a/vendor/modules.txt b/vendor/modules.txt index 5794d58f..39803e84 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -4,32 +4,37 @@ github.com/ajeddeloh/go-json github.com/ajeddeloh/yaml # github.com/alecthomas/units v0.0.0-20150109002421-6b4e7dc5e314 github.com/alecthomas/units -# github.com/coreos/container-linux-config-transpiler v0.5.0 +# github.com/coreos/container-linux-config-transpiler v0.9.0 github.com/coreos/container-linux-config-transpiler/config 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 github.com/coreos/container-linux-config-transpiler/config/templating github.com/coreos/container-linux-config-transpiler/config/types/util +github.com/coreos/container-linux-config-transpiler/internal/util # github.com/coreos/coreos-cloudinit v1.13.0 github.com/coreos/coreos-cloudinit/config # github.com/coreos/go-semver v0.0.0-20170209201757-5e3acbb5668c github.com/coreos/go-semver/semver # github.com/coreos/go-systemd v0.0.0-20160826104600-43e4800a6165 github.com/coreos/go-systemd/unit -# github.com/coreos/ignition v0.19.0 -github.com/coreos/ignition/config -github.com/coreos/ignition/config/v2_1/types +# github.com/coreos/ignition v0.31.0 +github.com/coreos/ignition/config/v2_2 +github.com/coreos/ignition/config/v2_2/types github.com/coreos/ignition/config/validate github.com/coreos/ignition/config/validate/astnode github.com/coreos/ignition/config/validate/report -github.com/coreos/ignition/config/types -github.com/coreos/ignition/config/v1 -github.com/coreos/ignition/config/v1/types +github.com/coreos/ignition/config/shared/errors +github.com/coreos/ignition/config/util +github.com/coreos/ignition/config/v2_1 +github.com/coreos/ignition/config/v2_1/types +github.com/coreos/ignition/config/shared/validations +github.com/coreos/ignition/config/validate/astjson +github.com/coreos/ignition/config/v2_4_experimental/types github.com/coreos/ignition/config/v2_0 github.com/coreos/ignition/config/v2_0/types -github.com/coreos/ignition/config/v2_1 -github.com/coreos/ignition/config/validate/astjson +github.com/coreos/ignition/config/v1 +github.com/coreos/ignition/config/v1/types # github.com/coreos/pkg v0.0.0-20160221035341-66fe44ad037c github.com/coreos/pkg/flagutil # github.com/coreos/yaml v0.0.0-20141224210557-6b16a5714269 @@ -51,7 +56,7 @@ github.com/sirupsen/logrus/hooks/test github.com/spf13/cobra # github.com/spf13/pflag v0.0.0-20151218134703-7f60f83a2c81 github.com/spf13/pflag -# github.com/stretchr/testify v1.2.2 +# github.com/stretchr/testify v1.3.0 github.com/stretchr/testify/assert # github.com/vincent-petithory/dataurl v0.0.0-20160330182126-9a301d65acbb github.com/vincent-petithory/dataurl