diff --git a/config.tf b/config.tf index 7654857c54..e4be32196d 100644 --- a/config.tf +++ b/config.tf @@ -61,18 +61,18 @@ variable "tectonic_container_images" { awscli = "quay.io/coreos/awscli:025a357f05242fdad6a81e8a6b520098aa65a600" gcloudsdk = "google/cloud-sdk:178.0.0-alpine" bootkube = "quay.io/coreos/bootkube:v0.10.0" - tnc_operator = "quay.io/coreos/tectonic-node-controller-operator-dev:c7add4ccd821710b4b5d012c6af9fd4f8e9a288b" + tnc_operator = "quay.io/coreos/tectonic-node-controller-operator-dev:8563b8b3355a44eb17c2981da3fb42b4c2453646" etcd_cert_signer = "quay.io/coreos/kube-etcd-signer-server:678cc8e6841e2121ebfdb6e2db568fce290b67d6" etcd = "quay.io/coreos/etcd:v3.2.14" hyperkube = "openshift/origin-node:latest" - kube_core_renderer = "quay.io/coreos/kube-core-renderer-dev:c7add4ccd821710b4b5d012c6af9fd4f8e9a288b" - kube_core_operator = "quay.io/coreos/kube-core-operator-dev:c7add4ccd821710b4b5d012c6af9fd4f8e9a288b" - tectonic_channel_operator = "quay.io/coreos/tectonic-channel-operator-dev:c7add4ccd821710b4b5d012c6af9fd4f8e9a288b" - kube_addon_operator = "quay.io/coreos/kube-addon-operator-dev:c7add4ccd821710b4b5d012c6af9fd4f8e9a288b" + kube_core_renderer = "quay.io/coreos/kube-core-renderer-dev:8563b8b3355a44eb17c2981da3fb42b4c2453646" + kube_core_operator = "quay.io/coreos/kube-core-operator-dev:8563b8b3355a44eb17c2981da3fb42b4c2453646" + tectonic_channel_operator = "quay.io/coreos/tectonic-channel-operator-dev:8563b8b3355a44eb17c2981da3fb42b4c2453646" + kube_addon_operator = "quay.io/coreos/kube-addon-operator-dev:8563b8b3355a44eb17c2981da3fb42b4c2453646" tectonic_alm_operator = "quay.io/coreos/tectonic-alm-operator:v0.3.1" - tectonic_ingress_controller_operator = "quay.io/coreos/tectonic-ingress-controller-operator-dev:c7add4ccd821710b4b5d012c6af9fd4f8e9a288b" - tectonic_utility_operator = "quay.io/coreos/tectonic-utility-operator-dev:c7add4ccd821710b4b5d012c6af9fd4f8e9a288b" - tectonic_network_operator = "quay.io/coreos/tectonic-network-operator-dev:c7add4ccd821710b4b5d012c6af9fd4f8e9a288b" + tectonic_ingress_controller_operator = "quay.io/coreos/tectonic-ingress-controller-operator-dev:8563b8b3355a44eb17c2981da3fb42b4c2453646" + tectonic_utility_operator = "quay.io/coreos/tectonic-utility-operator-dev:8563b8b3355a44eb17c2981da3fb42b4c2453646" + tectonic_network_operator = "quay.io/coreos/tectonic-network-operator-dev:8563b8b3355a44eb17c2981da3fb42b4c2453646" } } diff --git a/glide.lock b/glide.lock index 4e344b4f6f..f84603408a 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ -hash: 98bfaa467f036a2f503722076628d66097e5d84bf86dbc97abb8cc5f23064148 -updated: 2018-06-07T11:12:15.139135692-07:00 +hash: 0ecb3a97e888271fd9f1c815585759d843593950543e284e3f22b941707f12c5 +updated: 2018-06-14T10:48:03.647701802-07:00 imports: - name: github.com/ajeddeloh/go-json version: 73d058cf8437a1989030afe571eeab9f90eebbbd @@ -18,19 +18,24 @@ imports: subpackages: - semver - name: github.com/coreos/go-systemd - version: 40e2722dffead74698ca12a750f64ef313ddce05 + version: 39ca1b05acc7ad1220e09f133283b8859a8b71ab subpackages: - dbus - unit - name: github.com/coreos/ignition - version: bd3876b8f1d627625fe266a0e35256ba05e664e3 + version: 76107251acd117c6d3e5b4dae2b47f82f944984b subpackages: - - config/errors + - config/shared/errors + - config/shared/validations - config/util - config/v1 - config/v1/types - config/v2_0 - config/v2_0/types + - config/v2_1 + - config/v2_1/types + - config/v2_2 + - config/v2_2/types - config/v2_3_experimental/types - config/validate - config/validate/astjson @@ -92,8 +97,6 @@ imports: - name: golang.org/x/crypto version: df8d4716b3472e4a531c33cedbe537dae921a1a9 subpackages: - - bcrypt - - blowfish - ed25519 - ed25519/internal/edwards25519 - name: golang.org/x/net diff --git a/glide.yaml b/glide.yaml index 2dd46a473a..2d9a4bdd73 100644 --- a/glide.yaml +++ b/glide.yaml @@ -17,4 +17,6 @@ import: - package: golang.org/x/crypto version: df8d4716b3472e4a531c33cedbe537dae921a1a9 - package: github.com/coreos/ignition - version: v0.23.0 + version: v0.26.0 +- package: github.com/vincent-petithory/dataurl + version: 9a301d65acbb728fcc3ace14f45f511a4cfeea9c diff --git a/installer/pkg/config-generator/BUILD.bazel b/installer/pkg/config-generator/BUILD.bazel index aca54bc434..38fa5ce8fe 100644 --- a/installer/pkg/config-generator/BUILD.bazel +++ b/installer/pkg/config-generator/BUILD.bazel @@ -11,14 +11,15 @@ go_library( deps = [ "//installer/pkg/config:go_default_library", "//vendor/github.com/apparentlymart/go-cidr/cidr:go_default_library", - "//vendor/github.com/coreos/ignition/config/v2_0:go_default_library", - "//vendor/github.com/coreos/ignition/config/v2_0/types:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_2:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_2/types:go_default_library", "//vendor/github.com/coreos/tectonic-config/config/kube-addon:go_default_library", "//vendor/github.com/coreos/tectonic-config/config/kube-core:go_default_library", "//vendor/github.com/coreos/tectonic-config/config/tectonic-network:go_default_library", "//vendor/github.com/coreos/tectonic-config/config/tectonic-node-controller:go_default_library", "//vendor/github.com/coreos/tectonic-config/config/tectonic-utility:go_default_library", "//vendor/github.com/ghodss/yaml:go_default_library", + "//vendor/github.com/vincent-petithory/dataurl:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", ], ) diff --git a/installer/pkg/config-generator/ignition.go b/installer/pkg/config-generator/ignition.go index 4da0ba4194..74209baf9d 100644 --- a/installer/pkg/config-generator/ignition.go +++ b/installer/pkg/config-generator/ignition.go @@ -5,21 +5,24 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net/url" "os" "path/filepath" - ignconfig "github.com/coreos/ignition/config/v2_0" - ignconfigtypes "github.com/coreos/ignition/config/v2_0/types" + ignconfig "github.com/coreos/ignition/config/v2_2" + ignconfigtypes "github.com/coreos/ignition/config/v2_2/types" "github.com/coreos/tectonic-installer/installer/pkg/config" + "github.com/vincent-petithory/dataurl" ) var ( - ignVersion = ignconfigtypes.IgnitionVersion{Major: 2, Minor: 0, Patch: 0} + ignVersion = "2.2.0" ignFilesPath = map[string]string{ "master": config.IgnitionMaster, "worker": config.IgnitionWorker, "etcd": config.IgnitionEtcd, } + caPath = "generated/tls/root-ca.crt" ) func (c *ConfigGenerator) poolToRoleMap() map[string]string { @@ -51,6 +54,11 @@ func (c *ConfigGenerator) GenerateIgnConfig(clusterDir string) error { // add loop over count if role is etcd c.embedAppendBlock(ignCfg, role) + ca := filepath.Join(clusterDir, caPath) + if err = c.appendCertificateAuthority(ignCfg, ca); err != nil { + return err + } + // agentless platforms (e.g. libvirt) need to embed the ssh key c.embedUserBlock(ignCfg) @@ -91,12 +99,25 @@ func (c *ConfigGenerator) embedAppendBlock(ignCfg *ignconfigtypes.Config, role s ignCfg.Ignition.Config.Append = append(ignCfg.Ignition.Config.Append, appendBlock) } +func (c *ConfigGenerator) appendCertificateAuthority(ignCfg *ignconfigtypes.Config, caPath string) error { + ca, err := ioutil.ReadFile(caPath) + if err != nil { + return err + } + + ignCfg.Ignition.Security.TLS.CertificateAuthorities = append(ignCfg.Ignition.Security.TLS.CertificateAuthorities, ignconfigtypes.CaReference{ + Source: dataurl.EncodeBytes(ca), + }) + + return nil +} + func (c *ConfigGenerator) embedUserBlock(ignCfg *ignconfigtypes.Config) { - if c.Platform == "libvirt" { - userBlock := ignconfigtypes.User{ + if c.Platform.String() == config.PlatformLibvirt.String() { + userBlock := ignconfigtypes.PasswdUser{ Name: "core", - SSHAuthorizedKeys: []string{ - c.Libvirt.SSHKey, + SSHAuthorizedKeys: []ignconfigtypes.SSHAuthorizedKey{ + ignconfigtypes.SSHAuthorizedKey(c.Libvirt.SSHKey), }, } @@ -104,23 +125,33 @@ func (c *ConfigGenerator) embedUserBlock(ignCfg *ignconfigtypes.Config) { } } -func (c *ConfigGenerator) getTNCURL(role string) ignconfigtypes.Url { - var url ignconfigtypes.Url +func (c *ConfigGenerator) getTNCURL(role string) string { + var u string // cloud platforms put this behind a load balancer which remaps ports; // libvirt doesn't do that - use the tnc port directly port := 80 - if c.Platform == "libvirt" { + if c.Platform.String() == config.PlatformLibvirt.String() { port = 49500 } + + // XXX: The bootstrap node on AWS uses a CNAME to redirect TNC-bound + // traffic to S3. Because of this, HTTPS cannot be used. + scheme := "https" + if c.Platform.String() == config.PlatformAWS.String() && role == "master" { + scheme = "http" + } + if role == "master" || role == "worker" { - url = ignconfigtypes.Url{ - Scheme: "http", - Host: fmt.Sprintf("%s-tnc.%s:%d", c.Name, c.BaseDomain, port), - Path: fmt.Sprintf("/config/%s", role), - } + u = func() *url.URL { + return &url.URL{ + Scheme: scheme, + Host: fmt.Sprintf("%s-tnc.%s:%d", c.Name, c.BaseDomain, port), + Path: fmt.Sprintf("/config/%s", role), + } + }().String() } - return url + return u } func ignCfgToFile(ignCfg ignconfigtypes.Config, filePath string) error { diff --git a/installer/pkg/config/BUILD.bazel b/installer/pkg/config/BUILD.bazel index 0d8c3dbba7..3525080882 100644 --- a/installer/pkg/config/BUILD.bazel +++ b/installer/pkg/config/BUILD.bazel @@ -15,7 +15,7 @@ go_library( "//installer/pkg/config/libvirt:go_default_library", "//installer/pkg/validate:go_default_library", "//vendor/github.com/Sirupsen/logrus:go_default_library", - "//vendor/github.com/coreos/ignition/config/v2_0:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_2:go_default_library", "//vendor/github.com/coreos/tectonic-config/config/tectonic-network:go_default_library", "//vendor/gopkg.in/yaml.v2:go_default_library", ], diff --git a/installer/pkg/config/validate.go b/installer/pkg/config/validate.go index d9a04ae1ae..dc517fdf00 100644 --- a/installer/pkg/config/validate.go +++ b/installer/pkg/config/validate.go @@ -11,7 +11,7 @@ import ( "github.com/coreos/tectonic-installer/installer/pkg/validate" log "github.com/Sirupsen/logrus" - ignconfig "github.com/coreos/ignition/config/v2_0" + ignconfig "github.com/coreos/ignition/config/v2_2" "github.com/coreos/tectonic-config/config/tectonic-network" ) diff --git a/modules/bootkube/manifests.tf b/modules/bootkube/manifests.tf index 92781a63f7..e196bdddb6 100644 --- a/modules/bootkube/manifests.tf +++ b/modules/bootkube/manifests.tf @@ -14,6 +14,7 @@ variable "manifest_names" { "pull.json", "tectonic-network-operator.yaml", "tectonic-node-controller-operator.yaml", + "tnc-tls-secret.yaml", ] } @@ -52,6 +53,9 @@ data "template_file" "manifest_file_list" { etcd_ca_cert = "${base64encode(var.etcd_ca_cert_pem)}" etcd_client_cert = "${base64encode(var.etcd_client_cert_pem)}" etcd_client_key = "${base64encode(var.etcd_client_key_pem)}" + + tnc_tls_cert = "${base64encode(var.tnc_cert_pem)}" + tnc_tls_key = "${base64encode(var.tnc_key_pem)}" } } diff --git a/modules/bootkube/resources/bootkube.sh b/modules/bootkube/resources/bootkube.sh index a26503af2a..2ace2488b4 100644 --- a/modules/bootkube/resources/bootkube.sh +++ b/modules/bootkube/resources/bootkube.sh @@ -1,6 +1,8 @@ #!/bin/bash set -e +echo "Rendering Kubernetes core manifests..." + # shellcheck disable=SC2154 /usr/bin/docker run \ --volume "$(pwd)":/assets \ @@ -9,6 +11,8 @@ set -e --config=/assets/kco-config.yaml \ --output=/assets +echo "Rendering TNC manifests..." + # shellcheck disable=SC2154 /usr/bin/docker run \ --user 0 \ @@ -28,6 +32,8 @@ cp "$(pwd)/tnc-bootstrap/tectonic-node-controller-config.yaml" /etc/kubernetes/t # docker container. # See https://github.com/kubernetes/kubernetes/issues/43292 +echo "Starting etcd certificate signer..." + # shellcheck disable=SC2154,SC2034 signer_id=$(/usr/bin/docker run -d \ --tmpfs /tmp \ @@ -44,24 +50,48 @@ signer_id=$(/usr/bin/docker run -d \ --peercertdur=26280h \ --servercertdur=26280h) +echo "Waiting for etcd cluster..." + # Wait for the etcd cluster to come up. export ETCDCTL_API=3 -# shellcheck disable=SC2154,SC2086 -/usr/bin/etcdctl \ - --dial-timeout=10m \ - --cacert=/opt/tectonic/tls/etcd-client-ca.crt \ - --cert=/opt/tectonic/tls/etcd-client.crt \ - --key=/opt/tectonic/tls/etcd-client.key \ - --endpoints=${etcd_cluster} \ - endpoint health + +i=0 +while true; do + set +e + # shellcheck disable=SC2154,SC2086 + /usr/bin/etcdctl \ + --dial-timeout=10m \ + --cacert=/opt/tectonic/tls/etcd-client-ca.crt \ + --cert=/opt/tectonic/tls/etcd-client.crt \ + --key=/opt/tectonic/tls/etcd-client.key \ + --endpoints=${etcd_cluster} \ + endpoint health + status=$? + set -e + + if [ "$status" -eq 0 ]; then + break + fi + + i=$((i+1)) + [ $i -eq 10 ] && echo "etcdctl failed too many times." && exit 1 + + echo "etcdctl failed. Retrying in 5 seconds..." + sleep 5 +done + export ETCDCTL_API= +echo "etcd cluster up. Killing etcd certificate signer..." + # shellcheck disable=SC2154,SC1083 /usr/bin/docker kill $${signer_id} rm /etc/kubernetes/manifests/tectonic-node-controller-pod.yaml cp -r "$(pwd)/bootstrap-configs" /etc/kubernetes/bootstrap-configs +echo "Starting bootkube..." + # shellcheck disable=SC2154 /usr/bin/docker run \ --volume "$(pwd)":/assets \ diff --git a/modules/tectonic/resources/manifests/secrets/tnc-tls.yaml b/modules/bootkube/resources/manifests/tnc-tls-secret.yaml similarity index 100% rename from modules/tectonic/resources/manifests/secrets/tnc-tls.yaml rename to modules/bootkube/resources/manifests/tnc-tls-secret.yaml diff --git a/modules/bootkube/variables.tf b/modules/bootkube/variables.tf index 5087ebbbd3..6aba396955 100644 --- a/modules/bootkube/variables.tf +++ b/modules/bootkube/variables.tf @@ -123,6 +123,14 @@ variable "kubelet_key_pem" { description = "The kubelet key in PEM format." } +variable "tnc_cert_pem" { + type = "string" +} + +variable "tnc_key_pem" { + type = "string" +} + variable "oidc_ca_cert" { type = "string" } diff --git a/modules/tectonic/manifests.tf b/modules/tectonic/manifests.tf index 9e264a6305..d0b2699f32 100644 --- a/modules/tectonic/manifests.tf +++ b/modules/tectonic/manifests.tf @@ -13,7 +13,6 @@ variable "manifest_names" { "rbac/role-user.yaml", "secrets/ca-cert.yaml", "secrets/ingress-tls.yaml", - "secrets/tnc-tls.yaml", "secrets/license.json", "secrets/pull.json", "security/priviledged-scc-tectonic.yaml", @@ -74,9 +73,6 @@ data "template_file" "manifest_file_list" { ingress_tls_key = "${base64encode(var.ingress_key_pem)}" ingress_tls_bundle = "${base64encode(var.ingress_bundle_pem)}" - tnc_tls_cert = "${base64encode(var.tnc_cert_pem)}" - tnc_tls_key = "${base64encode(var.tnc_key_pem)}" - platform = "${var.platform}" } } diff --git a/modules/tectonic/resources/tectonic.sh b/modules/tectonic/resources/tectonic.sh index 3a2287d1af..48f45b611f 100755 --- a/modules/tectonic/resources/tectonic.sh +++ b/modules/tectonic/resources/tectonic.sh @@ -144,7 +144,6 @@ echo "Creating Tectonic Secrets" kubectl create -f secrets/pull.json kubectl create -f secrets/license.json kubectl create -f secrets/ingress-tls.yaml -kubectl create -f secrets/tnc-tls.yaml kubectl create -f secrets/ca-cert.yaml kubectl create -f ingress/pull.json diff --git a/modules/tectonic/variables.tf b/modules/tectonic/variables.tf index db72855558..05c0694f6b 100644 --- a/modules/tectonic/variables.tf +++ b/modules/tectonic/variables.tf @@ -70,11 +70,3 @@ variable "ingress_key_pem" { variable "ingress_bundle_pem" { type = "string" } - -variable "tnc_cert_pem" { - type = "string" -} - -variable "tnc_key_pem" { - type = "string" -} diff --git a/steps/assets/base/tectonic.tf b/steps/assets/base/tectonic.tf index ffa1586ee6..01b744fa85 100644 --- a/steps/assets/base/tectonic.tf +++ b/steps/assets/base/tectonic.tf @@ -40,6 +40,8 @@ module "bootkube" { kube_ca_key_pem = "${local.kube_ca_key_pem}" kubelet_cert_pem = "${local.kubelet_cert_pem}" kubelet_key_pem = "${local.kubelet_key_pem}" + tnc_cert_pem = "${local.tnc_cert_pem}" + tnc_key_pem = "${local.tnc_key_pem}" oidc_ca_cert = "${local.oidc_ca_cert}" root_ca_cert_pem = "${local.root_ca_cert_pem}" @@ -68,9 +70,6 @@ module "tectonic" { ingress_key_pem = "${local.ingress_key_pem}" ingress_bundle_pem = "${join("", list(local.ingress_cert_pem, local.ingress_key_pem, local.ingress_ca_cert_pem))}" - tnc_cert_pem = "${local.tnc_cert_pem}" - tnc_key_pem = "${local.tnc_key_pem}" - platform = "${var.tectonic_platform}" ingress_kind = "${var.ingress_kind}" } diff --git a/vendor/github.com/coreos/go-systemd/dbus/methods.go b/vendor/github.com/coreos/go-systemd/dbus/methods.go index 4511d0a92b..0b4207229f 100644 --- a/vendor/github.com/coreos/go-systemd/dbus/methods.go +++ b/vendor/github.com/coreos/go-systemd/dbus/methods.go @@ -313,6 +313,7 @@ func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitSt // names and returns an UnitStatus array. Comparing to ListUnitsByPatterns // method, this method returns statuses even for inactive or non-existing // units. Input array should contain exact unit names, but not patterns. +// Note: Requires systemd v230 or higher func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) { return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store) } diff --git a/vendor/github.com/coreos/go-systemd/dbus/set.go b/vendor/github.com/coreos/go-systemd/dbus/set.go index f92e6fbed1..17c5d48565 100644 --- a/vendor/github.com/coreos/go-systemd/dbus/set.go +++ b/vendor/github.com/coreos/go-systemd/dbus/set.go @@ -36,7 +36,7 @@ func (s *set) Length() int { } func (s *set) Values() (values []string) { - for val, _ := range s.data { + for val := range s.data { values = append(values, val) } return diff --git a/vendor/github.com/coreos/go-systemd/dbus/subscription.go b/vendor/github.com/coreos/go-systemd/dbus/subscription.go index 5e8e9aedc2..70e63a6f16 100644 --- a/vendor/github.com/coreos/go-systemd/dbus/subscription.go +++ b/vendor/github.com/coreos/go-systemd/dbus/subscription.go @@ -37,22 +37,12 @@ func (c *Conn) Subscribe() error { c.sigconn.BusObject().Call("org.freedesktop.DBus.AddMatch", 0, "type='signal',interface='org.freedesktop.DBus.Properties',member='PropertiesChanged'") - err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store() - if err != nil { - return err - } - - return nil + return c.sigobj.Call("org.freedesktop.systemd1.Manager.Subscribe", 0).Store() } // Unsubscribe this connection from systemd dbus events. func (c *Conn) Unsubscribe() error { - err := c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store() - if err != nil { - return err - } - - return nil + return c.sigobj.Call("org.freedesktop.systemd1.Manager.Unsubscribe", 0).Store() } func (c *Conn) dispatch() { diff --git a/vendor/github.com/coreos/go-systemd/unit/deserialize.go b/vendor/github.com/coreos/go-systemd/unit/deserialize.go index 8a88162f98..bf97280521 100644 --- a/vendor/github.com/coreos/go-systemd/unit/deserialize.go +++ b/vendor/github.com/coreos/go-systemd/unit/deserialize.go @@ -33,11 +33,13 @@ const ( // but this would introduce an (unfortunate) dependency on cgo SYSTEMD_LINE_MAX = 2048 - // characters that systemd considers indicate a newline + // SYSTEMD_NEWLINE defines characters that systemd considers indicators + // for a newline. SYSTEMD_NEWLINE = "\r\n" ) var ( + // ErrLineTooLong gets returned when a line is too long for systemd to handle. ErrLineTooLong = fmt.Errorf("line too long (max %d bytes)", SYSTEMD_LINE_MAX) ) @@ -70,7 +72,6 @@ type lexer struct { } func (l *lexer) lex() { - var err error defer func() { close(l.optchan) close(l.errchan) @@ -93,6 +94,7 @@ func (l *lexer) lex() { } } + var err error next, err = next() if err != nil { l.errchan <- err diff --git a/vendor/github.com/coreos/go-systemd/unit/option.go b/vendor/github.com/coreos/go-systemd/unit/option.go index e5d21e19d9..98e1af5c99 100644 --- a/vendor/github.com/coreos/go-systemd/unit/option.go +++ b/vendor/github.com/coreos/go-systemd/unit/option.go @@ -18,12 +18,14 @@ import ( "fmt" ) +// UnitOption represents an option in a systemd unit file. type UnitOption struct { Section string Name string Value string } +// NewUnitOption returns a new UnitOption instance with pre-set values. func NewUnitOption(section, name, value string) *UnitOption { return &UnitOption{Section: section, Name: name, Value: value} } @@ -32,12 +34,15 @@ func (uo *UnitOption) String() string { return fmt.Sprintf("{Section: %q, Name: %q, Value: %q}", uo.Section, uo.Name, uo.Value) } +// Match compares two UnitOptions and returns true if they are identical. func (uo *UnitOption) Match(other *UnitOption) bool { return uo.Section == other.Section && uo.Name == other.Name && uo.Value == other.Value } +// AllMatch compares two slices of UnitOptions and returns true if they are +// identical. func AllMatch(u1 []*UnitOption, u2 []*UnitOption) bool { length := len(u1) if length != len(u2) { diff --git a/vendor/github.com/coreos/ignition/config/errors/BUILD.bazel b/vendor/github.com/coreos/ignition/config/shared/errors/BUILD.bazel similarity index 71% rename from vendor/github.com/coreos/ignition/config/errors/BUILD.bazel rename to vendor/github.com/coreos/ignition/config/shared/errors/BUILD.bazel index bc426c68f2..ba7794913d 100644 --- a/vendor/github.com/coreos/ignition/config/errors/BUILD.bazel +++ b/vendor/github.com/coreos/ignition/config/shared/errors/BUILD.bazel @@ -3,6 +3,6 @@ load("@io_bazel_rules_go//go:def.bzl", "go_library") go_library( name = "go_default_library", srcs = ["errors.go"], - importpath = "github.com/coreos/ignition/config/errors", + importpath = "github.com/coreos/ignition/config/shared/errors", visibility = ["//visibility:public"], ) 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 0000000000..f2d1ddf286 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/shared/errors/errors.go @@ -0,0 +1,99 @@ +// 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") + + // 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") +) + +// 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/BUILD.bazel b/vendor/github.com/coreos/ignition/config/shared/validations/BUILD.bazel new file mode 100644 index 0000000000..b58819f08e --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/shared/validations/BUILD.bazel @@ -0,0 +1,13 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = ["unit.go"], + importpath = "github.com/coreos/ignition/config/shared/validations", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/coreos/go-systemd/unit:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", + ], +) 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 0000000000..2924fac863 --- /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/util/BUILD.bazel b/vendor/github.com/coreos/ignition/config/util/BUILD.bazel index 5de43d8efd..c8b3bf3ae6 100644 --- a/vendor/github.com/coreos/ignition/config/util/BUILD.bazel +++ b/vendor/github.com/coreos/ignition/config/util/BUILD.bazel @@ -5,16 +5,13 @@ go_library( srcs = [ "helpers.go", "parsingErrors.go", - "validate.go", ], importpath = "github.com/coreos/ignition/config/util", visibility = ["//visibility:public"], deps = [ "//vendor/github.com/ajeddeloh/go-json:go_default_library", - "//vendor/github.com/coreos/ignition/config/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", "//vendor/github.com/coreos/ignition/config/v2_3_experimental/types:go_default_library", - "//vendor/github.com/coreos/ignition/config/validate:go_default_library", - "//vendor/github.com/coreos/ignition/config/validate/astjson:go_default_library", "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", "//vendor/go4.org/errorutil:go_default_library", ], diff --git a/vendor/github.com/coreos/ignition/config/util/helpers.go b/vendor/github.com/coreos/ignition/config/util/helpers.go index 687949b15a..7d55548fdf 100644 --- a/vendor/github.com/coreos/ignition/config/util/helpers.go +++ b/vendor/github.com/coreos/ignition/config/util/helpers.go @@ -25,6 +25,10 @@ func StrToPtr(s string) *string { 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 index 5d27b2e1cb..6b6b114daf 100644 --- a/vendor/github.com/coreos/ignition/config/util/parsingErrors.go +++ b/vendor/github.com/coreos/ignition/config/util/parsingErrors.go @@ -18,7 +18,7 @@ import ( "bytes" "errors" - configErrors "github.com/coreos/ignition/config/errors" + configErrors "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/v2_3_experimental/types" "github.com/coreos/ignition/config/validate/report" diff --git a/vendor/github.com/coreos/ignition/config/util/validate.go b/vendor/github.com/coreos/ignition/config/util/validate.go deleted file mode 100644 index 826555b493..0000000000 --- a/vendor/github.com/coreos/ignition/config/util/validate.go +++ /dev/null @@ -1,43 +0,0 @@ -// 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" - "reflect" - - "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" -) - -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(validate.ValidateWithoutSource(configValue)) - } else { - r.Merge(validate.Validate(configValue, astjson.FromJsonRoot(ast), bytes.NewReader(rawConfig), true)) - } - return r -} diff --git a/vendor/github.com/coreos/ignition/config/v1/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v1/BUILD.bazel index 42b97248c4..d68bbd4b4b 100644 --- a/vendor/github.com/coreos/ignition/config/v1/BUILD.bazel +++ b/vendor/github.com/coreos/ignition/config/v1/BUILD.bazel @@ -10,9 +10,10 @@ go_library( visibility = ["//visibility:public"], deps = [ "//vendor/github.com/ajeddeloh/go-json:go_default_library", - "//vendor/github.com/coreos/ignition/config/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", "//vendor/github.com/coreos/ignition/config/util:go_default_library", "//vendor/github.com/coreos/ignition/config/v1/types:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate:go_default_library", "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", ], ) diff --git a/vendor/github.com/coreos/ignition/config/v1/config.go b/vendor/github.com/coreos/ignition/config/v1/config.go index 445395913b..21e79f81e5 100644 --- a/vendor/github.com/coreos/ignition/config/v1/config.go +++ b/vendor/github.com/coreos/ignition/config/v1/config.go @@ -15,9 +15,10 @@ package v1 import ( - "github.com/coreos/ignition/config/errors" + "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" json "github.com/ajeddeloh/go-json" @@ -43,10 +44,10 @@ func Parse(rawConfig []byte) (types.Config, report.Report, error) { } if config.Version != types.Version { - return types.Config{}, report.Report{}, errors.ErrInvalid + return types.Config{}, report.Report{}, errors.ErrUnknownVersion } - rpt := util.ValidateConfig(rawConfig, config) + rpt := validate.ValidateConfig(rawConfig, config) if rpt.IsFatal() { return types.Config{}, rpt, errors.ErrInvalid } diff --git a/vendor/github.com/coreos/ignition/config/v1/types/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v1/types/BUILD.bazel index b669b610a1..1784ae21a5 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/BUILD.bazel +++ b/vendor/github.com/coreos/ignition/config/v1/types/BUILD.bazel @@ -20,5 +20,8 @@ go_library( ], importpath = "github.com/coreos/ignition/config/v1/types", visibility = ["//visibility:public"], - deps = ["//vendor/github.com/coreos/ignition/config/validate/report:go_default_library"], + deps = [ + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", + ], ) 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 eb1b8bd9e1..62517856dc 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,7 @@ package types import ( - "fmt" - + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -31,25 +30,25 @@ func (n Disk) Validate() report.Report { if len(n.Device) == 0 { r.Add(report.Entry{ Kind: report.EntryError, - Message: "disk device is required", + Message: errors.ErrDiskDeviceRequired.Error(), }) } if n.partitionNumbersCollide() { r.Add(report.Entry{ Kind: report.EntryError, - Message: fmt.Sprintf("disk %q: partition numbers collide", n.Device), + Message: errors.ErrPartitionNumbersCollide.Error(), }) } if n.partitionsOverlap() { r.Add(report.Entry{ Kind: report.EntryError, - Message: fmt.Sprintf("disk %q: partitions overlap", n.Device), + Message: errors.ErrPartitionsOverlap.Error(), }) } if n.partitionsMisaligned() { r.Add(report.Entry{ Kind: report.EntryError, - Message: fmt.Sprintf("disk %q: partitions misaligned", n.Device), + Message: errors.ErrPartitionsMisaligned.Error(), }) } // Disks which get to this point will likely succeed in sgdisk 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 36e918baeb..8775c19fd5 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/file.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/file.go @@ -15,16 +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") -) - type FileMode os.FileMode type File struct { @@ -37,7 +33,7 @@ type File struct { 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/v1/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v1/types/filesystem.go index 2282e98147..7986bd724c 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/filesystem.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/filesystem.go @@ -15,15 +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") -) - type Filesystem struct { Device Path `json:"device,omitempty"` Format FilesystemFormat `json:"format,omitempty"` @@ -43,7 +38,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/v1/types/partition.go b/vendor/github.com/coreos/ignition/config/v1/types/partition.go index 94bf35b3c0..16270de2cf 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/partition.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/partition.go @@ -15,17 +15,13 @@ package types import ( - "errors" "fmt" "regexp" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrPartitionLabelTooLong = errors.New("partition labels may not exceed 36 characters") -) - type Partition struct { Label PartitionLabel `json:"label,omitempty"` Number int `json:"number"` @@ -43,7 +39,7 @@ 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(ErrPartitionLabelTooLong, report.EntryError) + return report.ReportFromError(errors.ErrLabelTooLong, report.EntryError) } 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 5476463999..e37341c1ac 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/path.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/path.go @@ -15,21 +15,17 @@ 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 (d Path) Validate() report.Report { if !path.IsAbs(string(d)) { - 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/v1/types/raid.go b/vendor/github.com/coreos/ignition/config/v1/types/raid.go index 4236255d6f..329b123e6d 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,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/v1/types/unit.go b/vendor/github.com/coreos/ignition/config/v1/types/unit.go index 60579163ae..5e983cc145 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/unit.go @@ -15,18 +15,12 @@ package types import ( - "errors" "path" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrSystemdUnitInvalidExt = errors.New("invalid systemd unit extension") - ErrSystemdDropInInvalidExt = errors.New("invalid systemd unit extension") - ErrNetworkdUnitInvalidExt = errors.New("invalid networkd unit extension") -) - type SystemdUnit struct { Name SystemdUnitName `json:"name,omitempty"` Enable bool `json:"enable,omitempty"` @@ -47,7 +41,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(ErrSystemdUnitInvalidExt, report.EntryError) + return report.ReportFromError(errors.ErrInvalidSystemdExt, report.EntryError) } } @@ -58,7 +52,7 @@ func (n SystemdUnitDropInName) Validate() report.Report { case ".conf": return report.Report{} default: - return report.ReportFromError(ErrSystemdDropInInvalidExt, report.EntryError) + return report.ReportFromError(errors.ErrInvalidSystemdDropinExt, report.EntryError) } } @@ -74,6 +68,6 @@ func (n NetworkdUnitName) Validate() report.Report { case ".link", ".netdev", ".network": return report.Report{} default: - return report.ReportFromError(ErrNetworkdUnitInvalidExt, report.EntryError) + return report.ReportFromError(errors.ErrInvalidNetworkdExt, report.EntryError) } } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v2_0/BUILD.bazel index f5211af815..152b2ccd58 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/BUILD.bazel +++ b/vendor/github.com/coreos/ignition/config/v2_0/BUILD.bazel @@ -13,11 +13,11 @@ go_library( deps = [ "//vendor/github.com/ajeddeloh/go-json:go_default_library", "//vendor/github.com/coreos/go-semver/semver:go_default_library", - "//vendor/github.com/coreos/ignition/config/errors:go_default_library", - "//vendor/github.com/coreos/ignition/config/util:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", "//vendor/github.com/coreos/ignition/config/v1:go_default_library", "//vendor/github.com/coreos/ignition/config/v1/types:go_default_library", "//vendor/github.com/coreos/ignition/config/v2_0/types:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate:go_default_library", "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", "//vendor/github.com/vincent-petithory/dataurl:go_default_library", ], 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 c0365c485c..f1385bf1ca 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/config.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/config.go @@ -15,10 +15,10 @@ package v2_0 import ( - "github.com/coreos/ignition/config/errors" - "github.com/coreos/ignition/config/util" + "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" "github.com/coreos/ignition/config/validate/report" json "github.com/ajeddeloh/go-json" @@ -57,7 +57,7 @@ func Parse(rawConfig []byte) (types.Config, report.Report, error) { return types.Config{}, report.Report{}, errors.ErrUnknownVersion } - rpt := util.ValidateConfig(rawConfig, config) + rpt := validate.ValidateConfig(rawConfig, config) if rpt.IsFatal() { return types.Config{}, rpt, errors.ErrInvalid } diff --git a/vendor/github.com/coreos/ignition/config/v2_0/types/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v2_0/types/BUILD.bazel index 8127b41507..15653e94d0 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/types/BUILD.bazel +++ b/vendor/github.com/coreos/ignition/config/v2_0/types/BUILD.bazel @@ -28,6 +28,8 @@ go_library( deps = [ "//vendor/github.com/coreos/go-semver/semver:go_default_library", "//vendor/github.com/coreos/go-systemd/unit:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/validations:go_default_library", "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", "//vendor/github.com/vincent-petithory/dataurl:go_default_library", ], 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 65c3e25cb1..f56e5b9c80 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 6965234553..b68c5c930e 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 cc660b559c..8d3e79054d 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 bbd0c75bd8..e3572711da 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 5d0f682d96..628524dc6d 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 c9519a15a9..deeb822d09 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 03a0ce453e..c36545d4a6 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 @@ -19,6 +19,7 @@ import ( "regexp" "strings" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -39,10 +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(fmt.Errorf("partition label will be truncated to text before the colon"), report.EntryWarning) + return report.ReportFromError(errors.ErrLabelContainsColon, report.EntryWarning) } return report.Report{} } @@ -57,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 0d07d81f7d..dcf35f8075 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 4236255d6f..329b123e6d 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 020d10a50e..06d99f2661 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 8bf0e6eaab..b8ed96118b 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/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v2_1/BUILD.bazel new file mode 100644 index 0000000000..062e9367b3 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/BUILD.bazel @@ -0,0 +1,24 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "append.go", + "cloudinit.go", + "config.go", + "translate.go", + ], + importpath = "github.com/coreos/ignition/config/v2_1", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/ajeddeloh/go-json:go_default_library", + "//vendor/github.com/coreos/go-semver/semver:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/util:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_0:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_0/types:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_1/types:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", + ], +) diff --git a/vendor/github.com/coreos/ignition/config/v2_1/append.go b/vendor/github.com/coreos/ignition/config/v2_1/append.go new file mode 100644 index 0000000000..b1517b7310 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/append.go @@ -0,0 +1,72 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v2_1 + +import ( + "reflect" + + "github.com/coreos/ignition/config/v2_1/types" +) + +// Append appends newConfig to oldConfig and returns the result. Appending one +// config to another is accomplished by iterating over every field in the +// config structure, appending slices, recursively appending structs, and +// overwriting old values with new values for all other types. +func Append(oldConfig, newConfig types.Config) types.Config { + vOld := reflect.ValueOf(oldConfig) + vNew := reflect.ValueOf(newConfig) + + vResult := appendStruct(vOld, vNew) + + return vResult.Interface().(types.Config) +} + +// appendStruct is an internal helper function to AppendConfig. Given two values +// of structures (assumed to be the same type), recursively iterate over every +// field in the struct, appending slices, recursively appending structs, and +// overwriting old values with the new for all other types. Some individual +// struct fields have alternate merge strategies, determined by the field name. +// Currently these fields are "ignition.version", which uses the old value, and +// "ignition.config" which uses the new value. +func appendStruct(vOld, vNew reflect.Value) reflect.Value { + tOld := vOld.Type() + vRes := reflect.New(tOld) + + for i := 0; i < tOld.NumField(); i++ { + vfOld := vOld.Field(i) + vfNew := vNew.Field(i) + vfRes := vRes.Elem().Field(i) + + switch tOld.Field(i).Name { + case "Version": + vfRes.Set(vfOld) + continue + case "Config": + vfRes.Set(vfNew) + continue + } + + switch vfOld.Type().Kind() { + case reflect.Struct: + vfRes.Set(appendStruct(vfOld, vfNew)) + case reflect.Slice: + vfRes.Set(reflect.AppendSlice(vfOld, vfNew)) + default: + vfRes.Set(vfNew) + } + } + + return vRes.Elem() +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/cloudinit.go b/vendor/github.com/coreos/ignition/config/v2_1/cloudinit.go new file mode 100644 index 0000000000..a019320f41 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/cloudinit.go @@ -0,0 +1,53 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// These functions are copied from github.com/coreos/coreos-cloudinit/config. + +package v2_1 + +import ( + "bytes" + "compress/gzip" + "io/ioutil" + "strings" + "unicode" +) + +func isCloudConfig(userdata []byte) bool { + header := strings.SplitN(string(decompressIfGzipped(userdata)), "\n", 2)[0] + + // Trim trailing whitespaces + header = strings.TrimRightFunc(header, unicode.IsSpace) + + return (header == "#cloud-config") +} + +func isScript(userdata []byte) bool { + header := strings.SplitN(string(decompressIfGzipped(userdata)), "\n", 2)[0] + return strings.HasPrefix(header, "#!") +} + +func decompressIfGzipped(data []byte) []byte { + if reader, err := gzip.NewReader(bytes.NewReader(data)); err == nil { + uncompressedData, err := ioutil.ReadAll(reader) + reader.Close() + if err == nil { + return uncompressedData + } else { + return data + } + } else { + return data + } +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/config.go b/vendor/github.com/coreos/ignition/config/v2_1/config.go new file mode 100644 index 0000000000..3fd271dd7e --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/config.go @@ -0,0 +1,68 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v2_1 + +import ( + "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" + "github.com/coreos/ignition/config/validate/report" + + json "github.com/ajeddeloh/go-json" +) + +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_0.Parse(rawConfig) + if err != nil { + return types.Config{}, rpt, err + } + return TranslateFromV2_0(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_1/translate.go b/vendor/github.com/coreos/ignition/config/v2_1/translate.go new file mode 100644 index 0000000000..e6b80dd122 --- /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/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v2_1/types/BUILD.bazel new file mode 100644 index 0000000000..48713810c4 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/BUILD.bazel @@ -0,0 +1,34 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "config.go", + "directory.go", + "disk.go", + "file.go", + "filesystem.go", + "ignition.go", + "link.go", + "mode.go", + "node.go", + "partition.go", + "passwd.go", + "path.go", + "raid.go", + "schema.go", + "unit.go", + "url.go", + "verification.go", + ], + importpath = "github.com/coreos/ignition/config/v2_1/types", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/coreos/go-semver/semver:go_default_library", + "//vendor/github.com/coreos/go-systemd/unit:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/validations:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", + "//vendor/github.com/vincent-petithory/dataurl:go_default_library", + ], +) diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/config.go b/vendor/github.com/coreos/ignition/config/v2_1/types/config.go new file mode 100644 index 0000000000..0e83bc6ad1 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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: 1, + } +) + +func (c Config) Validate() report.Report { + r := report.Report{} + rules := []rule{ + checkFilesFilesystems, + checkDuplicateFilesystems, + } + + for _, rule := range rules { + rule(c, &r) + } + return r +} + +type rule func(cfg Config, report *report.Report) + +func 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/v2_1/types/directory.go b/vendor/github.com/coreos/ignition/config/v2_1/types/directory.go new file mode 100644 index 0000000000..16adad0591 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/directory.go @@ -0,0 +1,30 @@ +// 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/validate/report" +) + +func (d Directory) ValidateMode() report.Report { + r := report.Report{} + if err := validateMode(d.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_1/types/disk.go new file mode 100644 index 0000000000..f0af504a17 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/disk.go @@ -0,0 +1,128 @@ +// 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, + }) + } + // 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. +func (p Partition) end() int { + if p.Size == 0 { + // a size of 0 means "fill available", just return the start as the end for those. + return p.Start + } + return p.Start + p.Size - 1 +} + +// partitionsOverlap returns true if any explicitly dimensioned partitions overlap +func (n Disk) partitionsOverlap() bool { + for _, p := range n.Partitions { + // Starts of 0 are placed by sgdisk into the "largest available block" at that time. + // We aren't going to check those for overlap since we don't have the disk geometry. + if p.Start == 0 { + continue + } + + for _, o := range n.Partitions { + if p == o || o.Start == 0 { + continue + } + + // is p.Start within o? + if p.Start >= o.Start && p.Start <= o.end() { + return true + } + + // is p.end() within o? + if p.end() >= o.Start && p.end() <= o.end() { + return true + } + + // do p.Start and p.end() straddle o? + if p.Start < o.Start && p.end() > o.end() { + return true + } + } + } + return false +} + +// partitionsMisaligned returns true if any of the partitions don't start on a 2048-sector (1MiB) boundary. +func (n Disk) partitionsMisaligned() bool { + for _, p := range n.Partitions { + if (p.Start & (2048 - 1)) != 0 { + return true + } + } + return false +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/file.go b/vendor/github.com/coreos/ignition/config/v2_1/types/file.go new file mode 100644 index 0000000000..ac79cd8585 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/file.go @@ -0,0 +1,56 @@ +// 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) ValidateMode() report.Report { + r := report.Report{} + if err := validateMode(f.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (fc FileContents) ValidateCompression() report.Report { + r := report.Report{} + switch fc.Compression { + case "", "gzip": + default: + r.Add(report.Entry{ + Message: 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_1/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_1/types/filesystem.go new file mode 100644 index 0000000000..a2e43ffda1 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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/v2_1/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_1/types/ignition.go new file mode 100644 index 0000000000..bddf495833 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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_1/types/link.go b/vendor/github.com/coreos/ignition/config/v2_1/types/link.go new file mode 100644 index 0000000000..f028442528 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/link.go @@ -0,0 +1,33 @@ +// 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/validate/report" +) + +func (s LinkEmbedded1) ValidateTarget() report.Report { + r := report.Report{} + if !s.Hard { + err := validatePath(s.Target) + 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_1/types/mode.go b/vendor/github.com/coreos/ignition/config/v2_1/types/mode.go new file mode 100644 index 0000000000..12d4188e95 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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 < 0 || m > 07777 { + 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 new file mode 100644 index 0000000000..50badfdfb9 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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_1/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_1/types/partition.go new file mode 100644 index 0000000000..084dce7ce2 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/partition.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 ( + "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) ValidateLabel() report.Report { + r := report.Report{} + // http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries: + // 56 (0x38) 72 bytes Partition name (36 UTF-16LE code units) + + // XXX(vc): note GPT calls it a name, we're using label for consistency + // with udev naming /dev/disk/by-partlabel/*. + if len(p.Label) > 36 { + r.Add(report.Entry{ + Message: 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_1/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_1/types/passwd.go new file mode 100644 index 0000000000..10508c56c0 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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_1/types/path.go b/vendor/github.com/coreos/ignition/config/v2_1/types/path.go new file mode 100644 index 0000000000..780607c31a --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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_1/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_1/types/raid.go new file mode 100644 index 0000000000..3aceaa9faa --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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_1/types/schema.go b/vendor/github.com/coreos/ignition/config/v2_1/types/schema.go new file mode 100644 index 0000000000..e0caed5e6e --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/schema.go @@ -0,0 +1,221 @@ +package types + +// generated by "schematyper --package=types schema/ignition.json -o config/types/schema.go --root-type=Config" -- DO NOT EDIT + +type Config struct { + Ignition Ignition `json:"ignition"` + Networkd Networkd `json:"networkd,omitempty"` + Passwd Passwd `json:"passwd,omitempty"` + Storage Storage `json:"storage,omitempty"` + Systemd Systemd `json:"systemd,omitempty"` +} + +type ConfigReference struct { + Source string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type Create struct { + Force bool `json:"force,omitempty"` + Options []CreateOption `json:"options,omitempty"` +} + +type CreateOption string + +type Device string + +type Directory struct { + Node + DirectoryEmbedded1 +} + +type DirectoryEmbedded1 struct { + Mode int `json:"mode,omitempty"` +} + +type Disk struct { + Device string `json:"device,omitempty"` + Partitions []Partition `json:"partitions,omitempty"` + WipeTable bool `json:"wipeTable,omitempty"` +} + +type Dropin struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name,omitempty"` +} + +type File struct { + Node + FileEmbedded1 +} + +type FileContents struct { + Compression string `json:"compression,omitempty"` + Source string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type FileEmbedded1 struct { + Contents FileContents `json:"contents,omitempty"` + Mode int `json:"mode,omitempty"` +} + +type Filesystem struct { + Mount *Mount `json:"mount,omitempty"` + Name string `json:"name,omitempty"` + Path *string `json:"path,omitempty"` +} + +type Ignition struct { + Config IgnitionConfig `json:"config,omitempty"` + Timeouts Timeouts `json:"timeouts,omitempty"` + Version string `json:"version,omitempty"` +} + +type IgnitionConfig struct { + Append []ConfigReference `json:"append,omitempty"` + Replace *ConfigReference `json:"replace,omitempty"` +} + +type Link struct { + Node + LinkEmbedded1 +} + +type LinkEmbedded1 struct { + Hard bool `json:"hard,omitempty"` + Target string `json:"target,omitempty"` +} + +type Mount struct { + Create *Create `json:"create,omitempty"` + Device string `json:"device,omitempty"` + Format string `json:"format,omitempty"` + Label *string `json:"label,omitempty"` + Options []MountOption `json:"options,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeFilesystem bool `json:"wipeFilesystem,omitempty"` +} + +type MountOption string + +type Networkd struct { + Units []Networkdunit `json:"units,omitempty"` +} + +type Networkdunit struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name,omitempty"` +} + +type Node struct { + Filesystem string `json:"filesystem,omitempty"` + Group NodeGroup `json:"group,omitempty"` + Path string `json:"path,omitempty"` + User NodeUser `json:"user,omitempty"` +} + +type NodeGroup struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type NodeUser struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type Partition struct { + GUID string `json:"guid,omitempty"` + Label string `json:"label,omitempty"` + Number int `json:"number,omitempty"` + Size int `json:"size,omitempty"` + Start int `json:"start,omitempty"` + TypeGUID string `json:"typeGuid,omitempty"` +} + +type Passwd struct { + Groups []PasswdGroup `json:"groups,omitempty"` + Users []PasswdUser `json:"users,omitempty"` +} + +type PasswdGroup struct { + Gid *int `json:"gid,omitempty"` + Name string `json:"name,omitempty"` + PasswordHash string `json:"passwordHash,omitempty"` + System bool `json:"system,omitempty"` +} + +type PasswdUser struct { + Create *Usercreate `json:"create,omitempty"` + Gecos string `json:"gecos,omitempty"` + Groups []PasswdUserGroup `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + Name string `json:"name,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PasswordHash *string `json:"passwordHash,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type PasswdUserGroup string + +type Raid struct { + Devices []Device `json:"devices,omitempty"` + Level string `json:"level,omitempty"` + Name string `json:"name,omitempty"` + Spares int `json:"spares,omitempty"` +} + +type SSHAuthorizedKey string + +type Storage struct { + Directories []Directory `json:"directories,omitempty"` + Disks []Disk `json:"disks,omitempty"` + Files []File `json:"files,omitempty"` + Filesystems []Filesystem `json:"filesystems,omitempty"` + Links []Link `json:"links,omitempty"` + Raid []Raid `json:"raid,omitempty"` +} + +type Systemd struct { + Units []Unit `json:"units,omitempty"` +} + +type Timeouts struct { + HTTPResponseHeaders *int `json:"httpResponseHeaders,omitempty"` + HTTPTotal *int `json:"httpTotal,omitempty"` +} + +type Unit struct { + Contents string `json:"contents,omitempty"` + Dropins []Dropin `json:"dropins,omitempty"` + Enable bool `json:"enable,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Mask bool `json:"mask,omitempty"` + Name string `json:"name,omitempty"` +} + +type Usercreate struct { + Gecos string `json:"gecos,omitempty"` + Groups []UsercreateGroup `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type UsercreateGroup string + +type Verification struct { + Hash *string `json:"hash,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_1/types/unit.go new file mode 100644 index 0000000000..07e6fe6f5c --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/unit.go @@ -0,0 +1,109 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "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 Dropin) Validate() report.Report { + r := report.Report{} + + if _, err := validateUnitContent(d.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + switch path.Ext(d.Name) { + case ".conf": + default: + r.Add(report.Entry{ + Message: 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 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_1/types/url.go b/vendor/github.com/coreos/ignition/config/v2_1/types/url.go new file mode 100644 index 0000000000..0fdc4a170e --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/url.go @@ -0,0 +1,45 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "net/url" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/vincent-petithory/dataurl" +) + +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", "s3": + 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_1/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_1/types/verification.go new file mode 100644 index 0000000000..51e7d1550a --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_1/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/v2_2/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v2_2/BUILD.bazel new file mode 100644 index 0000000000..ed53cc36ae --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/BUILD.bazel @@ -0,0 +1,24 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "append.go", + "cloudinit.go", + "config.go", + "translate.go", + ], + importpath = "github.com/coreos/ignition/config/v2_2", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/ajeddeloh/go-json:go_default_library", + "//vendor/github.com/coreos/go-semver/semver:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/util:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_1:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_1/types:go_default_library", + "//vendor/github.com/coreos/ignition/config/v2_2/types:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", + ], +) diff --git a/vendor/github.com/coreos/ignition/config/v2_2/append.go b/vendor/github.com/coreos/ignition/config/v2_2/append.go new file mode 100644 index 0000000000..cf28f40905 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/append.go @@ -0,0 +1,76 @@ +// 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_2 + +import ( + "reflect" + + "github.com/coreos/ignition/config/v2_2/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: + if vfNew.Kind() == reflect.Ptr && vfNew.IsNil() { + vfRes.Set(vfOld) + } else { + vfRes.Set(vfNew) + } + } + } + + return vRes.Elem() +} diff --git a/vendor/github.com/coreos/ignition/config/v2_2/cloudinit.go b/vendor/github.com/coreos/ignition/config/v2_2/cloudinit.go new file mode 100644 index 0000000000..36a5439324 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/cloudinit.go @@ -0,0 +1,53 @@ +// Copyright 2015 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// These functions are copied from github.com/coreos/coreos-cloudinit/config. + +package v2_2 + +import ( + "bytes" + "compress/gzip" + "io/ioutil" + "strings" + "unicode" +) + +func isCloudConfig(userdata []byte) bool { + header := strings.SplitN(string(decompressIfGzipped(userdata)), "\n", 2)[0] + + // Trim trailing whitespaces + header = strings.TrimRightFunc(header, unicode.IsSpace) + + return (header == "#cloud-config") +} + +func isScript(userdata []byte) bool { + header := strings.SplitN(string(decompressIfGzipped(userdata)), "\n", 2)[0] + return strings.HasPrefix(header, "#!") +} + +func decompressIfGzipped(data []byte) []byte { + if reader, err := gzip.NewReader(bytes.NewReader(data)); err == nil { + uncompressedData, err := ioutil.ReadAll(reader) + reader.Close() + if err == nil { + return uncompressedData + } else { + return data + } + } else { + return data + } +} diff --git a/vendor/github.com/coreos/ignition/config/v2_2/config.go b/vendor/github.com/coreos/ignition/config/v2_2/config.go new file mode 100644 index 0000000000..c934a9e4a3 --- /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 0000000000..56a6b33fc9 --- /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/v2_2/types/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v2_2/types/BUILD.bazel new file mode 100644 index 0000000000..4e8e66ca3c --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/BUILD.bazel @@ -0,0 +1,35 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "ca.go", + "config.go", + "directory.go", + "disk.go", + "file.go", + "filesystem.go", + "ignition.go", + "link.go", + "mode.go", + "node.go", + "partition.go", + "passwd.go", + "path.go", + "raid.go", + "schema.go", + "unit.go", + "url.go", + "verification.go", + ], + importpath = "github.com/coreos/ignition/config/v2_2/types", + visibility = ["//visibility:public"], + deps = [ + "//vendor/github.com/coreos/go-semver/semver:go_default_library", + "//vendor/github.com/coreos/go-systemd/unit:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/validations:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", + "//vendor/github.com/vincent-petithory/dataurl:go_default_library", + ], +) diff --git a/vendor/github.com/coreos/ignition/config/errors/errors.go b/vendor/github.com/coreos/ignition/config/v2_2/types/ca.go similarity index 50% rename from vendor/github.com/coreos/ignition/config/errors/errors.go rename to vendor/github.com/coreos/ignition/config/v2_2/types/ca.go index 5ab5967a03..7440e1e2f3 100644 --- a/vendor/github.com/coreos/ignition/config/errors/errors.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/ca.go @@ -12,17 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -package errors +package types -import "errors" - -var ( - 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") - ErrVersion = errors.New("incorrect config version") - ErrCompressionInvalid = errors.New("invalid compression method") +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/v2_2/types/config.go b/vendor/github.com/coreos/ignition/config/v2_2/types/config.go new file mode 100644 index 0000000000..b1fcfcd991 --- /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/v2_2/types/directory.go b/vendor/github.com/coreos/ignition/config/v2_2/types/directory.go new file mode 100644 index 0000000000..9fdc732a64 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/directory.go @@ -0,0 +1,37 @@ +// 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 (d Directory) ValidateMode() report.Report { + r := report.Report{} + if err := validateMode(d.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + 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_2/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_2/types/disk.go new file mode 100644 index 0000000000..f0af504a17 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/disk.go @@ -0,0 +1,128 @@ +// 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, + }) + } + // 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. +func (p Partition) end() int { + if p.Size == 0 { + // a size of 0 means "fill available", just return the start as the end for those. + return p.Start + } + return p.Start + p.Size - 1 +} + +// partitionsOverlap returns true if any explicitly dimensioned partitions overlap +func (n Disk) partitionsOverlap() bool { + for _, p := range n.Partitions { + // Starts of 0 are placed by sgdisk into the "largest available block" at that time. + // We aren't going to check those for overlap since we don't have the disk geometry. + if p.Start == 0 { + continue + } + + for _, o := range n.Partitions { + if p == o || o.Start == 0 { + continue + } + + // is p.Start within o? + if p.Start >= o.Start && p.Start <= o.end() { + return true + } + + // is p.end() within o? + if p.end() >= o.Start && p.end() <= o.end() { + return true + } + + // do p.Start and p.end() straddle o? + if p.Start < o.Start && p.end() > o.end() { + return true + } + } + } + return false +} + +// partitionsMisaligned returns true if any of the partitions don't start on a 2048-sector (1MiB) boundary. +func (n Disk) partitionsMisaligned() bool { + for _, p := range n.Partitions { + if (p.Start & (2048 - 1)) != 0 { + return true + } + } + return false +} diff --git a/vendor/github.com/coreos/ignition/config/v2_2/types/file.go b/vendor/github.com/coreos/ignition/config/v2_2/types/file.go new file mode 100644 index 0000000000..b235d16c09 --- /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 0000000000..a2e43ffda1 --- /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/v2_2/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_2/types/ignition.go new file mode 100644 index 0000000000..bddf495833 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/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_2/types/link.go b/vendor/github.com/coreos/ignition/config/v2_2/types/link.go new file mode 100644 index 0000000000..f028442528 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/link.go @@ -0,0 +1,33 @@ +// 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/validate/report" +) + +func (s LinkEmbedded1) ValidateTarget() report.Report { + r := report.Report{} + if !s.Hard { + err := validatePath(s.Target) + 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/mode.go b/vendor/github.com/coreos/ignition/config/v2_2/types/mode.go new file mode 100644 index 0000000000..d06045d675 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/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_2/types/node.go b/vendor/github.com/coreos/ignition/config/v2_2/types/node.go new file mode 100644 index 0000000000..50badfdfb9 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/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_2/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_2/types/partition.go new file mode 100644 index 0000000000..084dce7ce2 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/partition.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 ( + "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) ValidateLabel() report.Report { + r := report.Report{} + // http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries: + // 56 (0x38) 72 bytes Partition name (36 UTF-16LE code units) + + // XXX(vc): note GPT calls it a name, we're using label for consistency + // with udev naming /dev/disk/by-partlabel/*. + if len(p.Label) > 36 { + r.Add(report.Entry{ + Message: 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_2/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_2/types/passwd.go new file mode 100644 index 0000000000..10508c56c0 --- /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/v2_2/types/path.go b/vendor/github.com/coreos/ignition/config/v2_2/types/path.go new file mode 100644 index 0000000000..780607c31a --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/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_2/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_2/types/raid.go new file mode 100644 index 0000000000..3aceaa9faa --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/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_2/types/schema.go b/vendor/github.com/coreos/ignition/config/v2_2/types/schema.go new file mode 100644 index 0000000000..4b32b337b3 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/schema.go @@ -0,0 +1,246 @@ +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"` + Passwd Passwd `json:"passwd,omitempty"` + Storage Storage `json:"storage,omitempty"` + Systemd Systemd `json:"systemd,omitempty"` +} + +type ConfigReference struct { + Source string `json:"source,omitempty"` + Verification Verification `json:"verification,omitempty"` +} + +type Create struct { + Force bool `json:"force,omitempty"` + Options []CreateOption `json:"options,omitempty"` +} + +type CreateOption string + +type Device string + +type Directory struct { + Node + DirectoryEmbedded1 +} + +type DirectoryEmbedded1 struct { + Mode *int `json:"mode,omitempty"` +} + +type Disk struct { + Device string `json:"device,omitempty"` + Partitions []Partition `json:"partitions,omitempty"` + WipeTable bool `json:"wipeTable,omitempty"` +} + +type 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,omitempty"` +} + +type Mount struct { + Create *Create `json:"create,omitempty"` + Device string `json:"device,omitempty"` + Format string `json:"format,omitempty"` + Label *string `json:"label,omitempty"` + Options []MountOption `json:"options,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeFilesystem bool `json:"wipeFilesystem,omitempty"` +} + +type MountOption string + +type Networkd struct { + Units []Networkdunit `json:"units,omitempty"` +} + +type 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"` + Overwrite *bool `json:"overwrite,omitempty"` + Path string `json:"path,omitempty"` + User *NodeUser `json:"user,omitempty"` +} + +type NodeGroup struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type NodeUser struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type Partition struct { + GUID string `json:"guid,omitempty"` + Label string `json:"label,omitempty"` + Number int `json:"number,omitempty"` + Size int `json:"size,omitempty"` + Start int `json:"start,omitempty"` + TypeGUID string `json:"typeGuid,omitempty"` +} + +type Passwd struct { + Groups []PasswdGroup `json:"groups,omitempty"` + Users []PasswdUser `json:"users,omitempty"` +} + +type PasswdGroup struct { + Gid *int `json:"gid,omitempty"` + Name string `json:"name,omitempty"` + PasswordHash string `json:"passwordHash,omitempty"` + System bool `json:"system,omitempty"` +} + +type PasswdUser struct { + Create *Usercreate `json:"create,omitempty"` + Gecos string `json:"gecos,omitempty"` + Groups []Group `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + Name string `json:"name,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PasswordHash *string `json:"passwordHash,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type Raid struct { + 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"` + 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,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 []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 { + 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_2/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_2/types/unit.go new file mode 100644 index 0000000000..70fe1179a4 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/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_2/types/url.go b/vendor/github.com/coreos/ignition/config/v2_2/types/url.go new file mode 100644 index 0000000000..2e90ff6d07 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/url.go @@ -0,0 +1,46 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "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", "s3": + 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_2/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_2/types/verification.go new file mode 100644 index 0000000000..51e7d1550a --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_2/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/v2_3_experimental/types/BUILD.bazel b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/BUILD.bazel index 86f236f618..f5ac4f6161 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/BUILD.bazel +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/BUILD.bazel @@ -27,7 +27,8 @@ go_library( deps = [ "//vendor/github.com/coreos/go-semver/semver:go_default_library", "//vendor/github.com/coreos/go-systemd/unit:go_default_library", - "//vendor/github.com/coreos/ignition/config/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/errors:go_default_library", + "//vendor/github.com/coreos/ignition/config/shared/validations:go_default_library", "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", "//vendor/github.com/vincent-petithory/dataurl:go_default_library", ], diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ca.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ca.go index 93d60bb5fe..7440e1e2f3 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ca.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ca.go @@ -15,17 +15,13 @@ package types import ( - "fmt" - "github.com/coreos/ignition/config/validate/report" ) func (c CaReference) ValidateSource() report.Report { err := validateURL(c.Source) if err != nil { - return report.ReportFromError( - fmt.Errorf("invalid url %q: %v", c.Source, err), - report.EntryError) + return report.ReportFromError(err, report.EntryError) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/directory.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/directory.go index d003a7096b..9fdc732a64 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/directory.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/directory.go @@ -15,6 +15,7 @@ package types import ( + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -28,7 +29,7 @@ func (d Directory) ValidateMode() report.Report { } if d.Mode == nil { r.Add(report.Entry{ - Message: "directory permissions unset, defaulting to 0000", + Message: errors.ErrPermissionsUnset.Error(), Kind: report.EntryWarning, }) } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/disk.go index f556e1826a..ebffc2cd67 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/disk.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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,25 @@ 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, + }) + } + if n.partitionsMixZeroesAndNonexistence() { + r.Add(report.Entry{ + Message: errors.ErrZeroesWithShouldNotExist.Error(), Kind: report.EntryError, }) } @@ -76,13 +81,13 @@ func (n Disk) partitionNumbersCollide() bool { return false } -// end returns the last sector of a partition. +// 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 { + 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 } - return p.Start + p.Size - 1 + return *p.Start + *p.Size - 1 } // partitionsOverlap returns true if any explicitly dimensioned partitions overlap @@ -90,27 +95,27 @@ func (n Disk) partitionsOverlap() bool { for _, p := range n.Partitions { // Starts of 0 are placed by sgdisk into the "largest available block" at that time. // We aren't going to check those for overlap since we don't have the disk geometry. - if p.Start == 0 { + if p.Start == nil || p.Size == nil || *p.Start == 0 { continue } for _, o := range n.Partitions { - if p == o || o.Start == 0 { + 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() { + 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() { + 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() { + if *p.Start < *o.Start && p.end() > o.end() { return true } } @@ -121,9 +126,19 @@ func (n Disk) partitionsOverlap() bool { // partitionsMisaligned returns true if any of the partitions don't start on a 2048-sector (1MiB) boundary. func (n Disk) partitionsMisaligned() bool { for _, p := range n.Partitions { - if (p.Start & (2048 - 1)) != 0 { + 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 +} diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/file.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/file.go index d9540735d0..1897dc42c8 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/file.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/file.go @@ -15,20 +15,15 @@ package types import ( - "errors" "fmt" - configErrors "github.com/coreos/ignition/config/errors" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -var ( - ErrAppendAndOverwrite = errors.New("cannot set both append and overwrite to true") -) - func (f File) Validate() report.Report { if f.Overwrite != nil && *f.Overwrite && f.Append { - return report.ReportFromError(ErrAppendAndOverwrite, report.EntryError) + return report.ReportFromError(errors.ErrAppendAndOverwrite, report.EntryError) } return report.Report{} } @@ -43,7 +38,7 @@ func (f File) ValidateMode() report.Report { } if f.Mode == nil { r.Add(report.Entry{ - Message: "file permissions unset, defaulting to 0000", + Message: errors.ErrPermissionsUnset.Error(), Kind: report.EntryWarning, }) } @@ -56,7 +51,7 @@ func (fc FileContents) ValidateCompression() report.Report { case "", "gzip": default: r.Add(report.Entry{ - Message: configErrors.ErrCompressionInvalid.Error(), + Message: errors.ErrCompressionInvalid.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/filesystem.go index 3c5a47d55a..2e847da69d 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/filesystem.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_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_3_experimental/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ignition.go index 661b898d40..bddf495833 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ignition.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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_3_experimental/types/link.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/link.go index 1b7794c0db..f028442528 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/link.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/link.go @@ -15,18 +15,16 @@ package types import ( - "fmt" - "github.com/coreos/ignition/config/validate/report" ) -func (s Link) Validate() report.Report { +func (s LinkEmbedded1) ValidateTarget() 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), + Message: err.Error(), Kind: report.EntryError, }) } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/mode.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/mode.go index f861a39b7b..d06045d675 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/mode.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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 != nil && (*m < 0 || *m > 07777) { - return ErrFileIllegalMode + return errors.ErrFileIllegalMode } return nil } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/node.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/node.go index 5c117f0674..50badfdfb9 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/node.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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_3_experimental/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/partition.go index 2d44defb6b..4e962b6391 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/partition.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/partition.go @@ -15,11 +15,11 @@ package types import ( - "errors" "fmt" "regexp" "strings" + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) @@ -27,30 +27,35 @@ 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\"") - ErrLabelContainsColon = errors.New("partition label will be truncated to text before the colon") -) +func (p Partition) Validate() report.Report { + if p.ShouldExist != nil && !*p.ShouldExist && + (p.Label != nil || p.TypeGUID != "" || p.GUID != "" || p.Start != nil || p.Size != nil) { + return report.ReportFromError(errors.ErrShouldNotExistWithOthers, report.EntryError) + } + 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 { + 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, ":") { + if strings.Contains(*p.Label, ":") { r.Add(report.Entry{ - Message: ErrLabelContainsColon.Error(), + Message: errors.ErrLabelContainsColon.Error(), Kind: report.EntryWarning, }) } @@ -75,7 +80,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_3_experimental/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/passwd.go index 5f7d96415f..10508c56c0 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/passwd.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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_3_experimental/types/path.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/path.go index 0bdbdcb009..780607c31a 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/path.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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_3_experimental/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/raid.go index f43b152d5c..3aceaa9faa 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/raid.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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_3_experimental/types/schema.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/schema.go index aabc84abf4..73424c546e 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/schema.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/schema.go @@ -137,12 +137,14 @@ type NodeUser struct { } type Partition struct { - GUID string `json:"guid,omitempty"` - Label string `json:"label,omitempty"` - Number int `json:"number,omitempty"` - Size int `json:"size,omitempty"` - Start int `json:"start,omitempty"` - TypeGUID string `json:"typeGuid,omitempty"` + 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"` + Start *int `json:"start,omitempty"` + TypeGUID string `json:"typeGuid,omitempty"` + WipePartitionEntry bool `json:"wipePartitionEntry,omitempty"` } type Passwd struct { diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/unit.go index 7ad9fed581..70fe1179a4 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/unit.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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 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 SystemdDropin) 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 SystemdDropin) 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, }) } @@ -101,7 +102,7 @@ func (u Networkdunit) Validate() report.Report { func (d NetworkdDropin) 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, @@ -112,7 +113,7 @@ func (d NetworkdDropin) Validate() report.Report { case ".conf": default: r.Add(report.Entry{ - Message: fmt.Sprintf("invalid networkd unit drop-in extension: %q", path.Ext(d.Name)), + Message: errors.ErrInvalidNetworkdDropinExt.Error(), Kind: report.EntryError, }) } @@ -120,12 +121,11 @@ func (d NetworkdDropin) 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_3_experimental/types/url.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/url.go index f6270c9a2c..2e90ff6d07 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/url.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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,7 +29,7 @@ func validateURL(s string) error { } u, err := url.Parse(s) if err != nil { - return err + return errors.ErrInvalidUrl } switch u.Scheme { @@ -44,6 +41,6 @@ func validateURL(s string) error { } return nil default: - return ErrInvalidScheme + return errors.ErrInvalidScheme } } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/verification.go index d2158b8082..51e7d1550a 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/verification.go +++ b/vendor/github.com/coreos/ignition/config/v2_3_experimental/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/validate/BUILD.bazel b/vendor/github.com/coreos/ignition/config/validate/BUILD.bazel index 4cdc4b7a43..4d3f282d7b 100644 --- a/vendor/github.com/coreos/ignition/config/validate/BUILD.bazel +++ b/vendor/github.com/coreos/ignition/config/validate/BUILD.bazel @@ -6,6 +6,8 @@ go_library( importpath = "github.com/coreos/ignition/config/validate", visibility = ["//visibility:public"], deps = [ + "//vendor/github.com/ajeddeloh/go-json:go_default_library", + "//vendor/github.com/coreos/ignition/config/validate/astjson:go_default_library", "//vendor/github.com/coreos/ignition/config/validate/astnode:go_default_library", "//vendor/github.com/coreos/ignition/config/validate/report:go_default_library", ], diff --git a/vendor/github.com/coreos/ignition/config/validate/validate.go b/vendor/github.com/coreos/ignition/config/validate/validate.go index 8951be410a..12f9bf205f 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/golang.org/x/crypto/bcrypt/BUILD.bazel b/vendor/golang.org/x/crypto/bcrypt/BUILD.bazel deleted file mode 100644 index 7bffdea4eb..0000000000 --- a/vendor/golang.org/x/crypto/bcrypt/BUILD.bazel +++ /dev/null @@ -1,12 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "base64.go", - "bcrypt.go", - ], - importpath = "golang.org/x/crypto/bcrypt", - visibility = ["//visibility:public"], - deps = ["//vendor/golang.org/x/crypto/blowfish:go_default_library"], -) diff --git a/vendor/golang.org/x/crypto/bcrypt/base64.go b/vendor/golang.org/x/crypto/bcrypt/base64.go deleted file mode 100644 index fc31160908..0000000000 --- a/vendor/golang.org/x/crypto/bcrypt/base64.go +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package bcrypt - -import "encoding/base64" - -const alphabet = "./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - -var bcEncoding = base64.NewEncoding(alphabet) - -func base64Encode(src []byte) []byte { - n := bcEncoding.EncodedLen(len(src)) - dst := make([]byte, n) - bcEncoding.Encode(dst, src) - for dst[n-1] == '=' { - n-- - } - return dst[:n] -} - -func base64Decode(src []byte) ([]byte, error) { - numOfEquals := 4 - (len(src) % 4) - for i := 0; i < numOfEquals; i++ { - src = append(src, '=') - } - - dst := make([]byte, bcEncoding.DecodedLen(len(src))) - n, err := bcEncoding.Decode(dst, src) - if err != nil { - return nil, err - } - return dst[:n], nil -} diff --git a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go b/vendor/golang.org/x/crypto/bcrypt/bcrypt.go deleted file mode 100644 index aeb73f81a1..0000000000 --- a/vendor/golang.org/x/crypto/bcrypt/bcrypt.go +++ /dev/null @@ -1,295 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package bcrypt implements Provos and Mazières's bcrypt adaptive hashing -// algorithm. See http://www.usenix.org/event/usenix99/provos/provos.pdf -package bcrypt // import "golang.org/x/crypto/bcrypt" - -// The code is a port of Provos and Mazières's C implementation. -import ( - "crypto/rand" - "crypto/subtle" - "errors" - "fmt" - "io" - "strconv" - - "golang.org/x/crypto/blowfish" -) - -const ( - MinCost int = 4 // the minimum allowable cost as passed in to GenerateFromPassword - MaxCost int = 31 // the maximum allowable cost as passed in to GenerateFromPassword - DefaultCost int = 10 // the cost that will actually be set if a cost below MinCost is passed into GenerateFromPassword -) - -// The error returned from CompareHashAndPassword when a password and hash do -// not match. -var ErrMismatchedHashAndPassword = errors.New("crypto/bcrypt: hashedPassword is not the hash of the given password") - -// The error returned from CompareHashAndPassword when a hash is too short to -// be a bcrypt hash. -var ErrHashTooShort = errors.New("crypto/bcrypt: hashedSecret too short to be a bcrypted password") - -// The error returned from CompareHashAndPassword when a hash was created with -// a bcrypt algorithm newer than this implementation. -type HashVersionTooNewError byte - -func (hv HashVersionTooNewError) Error() string { - return fmt.Sprintf("crypto/bcrypt: bcrypt algorithm version '%c' requested is newer than current version '%c'", byte(hv), majorVersion) -} - -// The error returned from CompareHashAndPassword when a hash starts with something other than '$' -type InvalidHashPrefixError byte - -func (ih InvalidHashPrefixError) Error() string { - return fmt.Sprintf("crypto/bcrypt: bcrypt hashes must start with '$', but hashedSecret started with '%c'", byte(ih)) -} - -type InvalidCostError int - -func (ic InvalidCostError) Error() string { - return fmt.Sprintf("crypto/bcrypt: cost %d is outside allowed range (%d,%d)", int(ic), int(MinCost), int(MaxCost)) -} - -const ( - majorVersion = '2' - minorVersion = 'a' - maxSaltSize = 16 - maxCryptedHashSize = 23 - encodedSaltSize = 22 - encodedHashSize = 31 - minHashSize = 59 -) - -// magicCipherData is an IV for the 64 Blowfish encryption calls in -// bcrypt(). It's the string "OrpheanBeholderScryDoubt" in big-endian bytes. -var magicCipherData = []byte{ - 0x4f, 0x72, 0x70, 0x68, - 0x65, 0x61, 0x6e, 0x42, - 0x65, 0x68, 0x6f, 0x6c, - 0x64, 0x65, 0x72, 0x53, - 0x63, 0x72, 0x79, 0x44, - 0x6f, 0x75, 0x62, 0x74, -} - -type hashed struct { - hash []byte - salt []byte - cost int // allowed range is MinCost to MaxCost - major byte - minor byte -} - -// GenerateFromPassword returns the bcrypt hash of the password at the given -// cost. If the cost given is less than MinCost, the cost will be set to -// DefaultCost, instead. Use CompareHashAndPassword, as defined in this package, -// to compare the returned hashed password with its cleartext version. -func GenerateFromPassword(password []byte, cost int) ([]byte, error) { - p, err := newFromPassword(password, cost) - if err != nil { - return nil, err - } - return p.Hash(), nil -} - -// CompareHashAndPassword compares a bcrypt hashed password with its possible -// plaintext equivalent. Returns nil on success, or an error on failure. -func CompareHashAndPassword(hashedPassword, password []byte) error { - p, err := newFromHash(hashedPassword) - if err != nil { - return err - } - - otherHash, err := bcrypt(password, p.cost, p.salt) - if err != nil { - return err - } - - otherP := &hashed{otherHash, p.salt, p.cost, p.major, p.minor} - if subtle.ConstantTimeCompare(p.Hash(), otherP.Hash()) == 1 { - return nil - } - - return ErrMismatchedHashAndPassword -} - -// Cost returns the hashing cost used to create the given hashed -// password. When, in the future, the hashing cost of a password system needs -// to be increased in order to adjust for greater computational power, this -// function allows one to establish which passwords need to be updated. -func Cost(hashedPassword []byte) (int, error) { - p, err := newFromHash(hashedPassword) - if err != nil { - return 0, err - } - return p.cost, nil -} - -func newFromPassword(password []byte, cost int) (*hashed, error) { - if cost < MinCost { - cost = DefaultCost - } - p := new(hashed) - p.major = majorVersion - p.minor = minorVersion - - err := checkCost(cost) - if err != nil { - return nil, err - } - p.cost = cost - - unencodedSalt := make([]byte, maxSaltSize) - _, err = io.ReadFull(rand.Reader, unencodedSalt) - if err != nil { - return nil, err - } - - p.salt = base64Encode(unencodedSalt) - hash, err := bcrypt(password, p.cost, p.salt) - if err != nil { - return nil, err - } - p.hash = hash - return p, err -} - -func newFromHash(hashedSecret []byte) (*hashed, error) { - if len(hashedSecret) < minHashSize { - return nil, ErrHashTooShort - } - p := new(hashed) - n, err := p.decodeVersion(hashedSecret) - if err != nil { - return nil, err - } - hashedSecret = hashedSecret[n:] - n, err = p.decodeCost(hashedSecret) - if err != nil { - return nil, err - } - hashedSecret = hashedSecret[n:] - - // The "+2" is here because we'll have to append at most 2 '=' to the salt - // when base64 decoding it in expensiveBlowfishSetup(). - p.salt = make([]byte, encodedSaltSize, encodedSaltSize+2) - copy(p.salt, hashedSecret[:encodedSaltSize]) - - hashedSecret = hashedSecret[encodedSaltSize:] - p.hash = make([]byte, len(hashedSecret)) - copy(p.hash, hashedSecret) - - return p, nil -} - -func bcrypt(password []byte, cost int, salt []byte) ([]byte, error) { - cipherData := make([]byte, len(magicCipherData)) - copy(cipherData, magicCipherData) - - c, err := expensiveBlowfishSetup(password, uint32(cost), salt) - if err != nil { - return nil, err - } - - for i := 0; i < 24; i += 8 { - for j := 0; j < 64; j++ { - c.Encrypt(cipherData[i:i+8], cipherData[i:i+8]) - } - } - - // Bug compatibility with C bcrypt implementations. We only encode 23 of - // the 24 bytes encrypted. - hsh := base64Encode(cipherData[:maxCryptedHashSize]) - return hsh, nil -} - -func expensiveBlowfishSetup(key []byte, cost uint32, salt []byte) (*blowfish.Cipher, error) { - csalt, err := base64Decode(salt) - if err != nil { - return nil, err - } - - // Bug compatibility with C bcrypt implementations. They use the trailing - // NULL in the key string during expansion. - // We copy the key to prevent changing the underlying array. - ckey := append(key[:len(key):len(key)], 0) - - c, err := blowfish.NewSaltedCipher(ckey, csalt) - if err != nil { - return nil, err - } - - var i, rounds uint64 - rounds = 1 << cost - for i = 0; i < rounds; i++ { - blowfish.ExpandKey(ckey, c) - blowfish.ExpandKey(csalt, c) - } - - return c, nil -} - -func (p *hashed) Hash() []byte { - arr := make([]byte, 60) - arr[0] = '$' - arr[1] = p.major - n := 2 - if p.minor != 0 { - arr[2] = p.minor - n = 3 - } - arr[n] = '$' - n++ - copy(arr[n:], []byte(fmt.Sprintf("%02d", p.cost))) - n += 2 - arr[n] = '$' - n++ - copy(arr[n:], p.salt) - n += encodedSaltSize - copy(arr[n:], p.hash) - n += encodedHashSize - return arr[:n] -} - -func (p *hashed) decodeVersion(sbytes []byte) (int, error) { - if sbytes[0] != '$' { - return -1, InvalidHashPrefixError(sbytes[0]) - } - if sbytes[1] > majorVersion { - return -1, HashVersionTooNewError(sbytes[1]) - } - p.major = sbytes[1] - n := 3 - if sbytes[2] != '$' { - p.minor = sbytes[2] - n++ - } - return n, nil -} - -// sbytes should begin where decodeVersion left off. -func (p *hashed) decodeCost(sbytes []byte) (int, error) { - cost, err := strconv.Atoi(string(sbytes[0:2])) - if err != nil { - return -1, err - } - err = checkCost(cost) - if err != nil { - return -1, err - } - p.cost = cost - return 3, nil -} - -func (p *hashed) String() string { - return fmt.Sprintf("&{hash: %#v, salt: %#v, cost: %d, major: %c, minor: %c}", string(p.hash), p.salt, p.cost, p.major, p.minor) -} - -func checkCost(cost int) error { - if cost < MinCost || cost > MaxCost { - return InvalidCostError(cost) - } - return nil -} diff --git a/vendor/golang.org/x/crypto/blowfish/BUILD.bazel b/vendor/golang.org/x/crypto/blowfish/BUILD.bazel deleted file mode 100644 index 4c073d5e48..0000000000 --- a/vendor/golang.org/x/crypto/blowfish/BUILD.bazel +++ /dev/null @@ -1,12 +0,0 @@ -load("@io_bazel_rules_go//go:def.bzl", "go_library") - -go_library( - name = "go_default_library", - srcs = [ - "block.go", - "cipher.go", - "const.go", - ], - importpath = "golang.org/x/crypto/blowfish", - visibility = ["//visibility:public"], -) diff --git a/vendor/golang.org/x/crypto/blowfish/block.go b/vendor/golang.org/x/crypto/blowfish/block.go deleted file mode 100644 index 9d80f19521..0000000000 --- a/vendor/golang.org/x/crypto/blowfish/block.go +++ /dev/null @@ -1,159 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package blowfish - -// getNextWord returns the next big-endian uint32 value from the byte slice -// at the given position in a circular manner, updating the position. -func getNextWord(b []byte, pos *int) uint32 { - var w uint32 - j := *pos - for i := 0; i < 4; i++ { - w = w<<8 | uint32(b[j]) - j++ - if j >= len(b) { - j = 0 - } - } - *pos = j - return w -} - -// ExpandKey performs a key expansion on the given *Cipher. Specifically, it -// performs the Blowfish algorithm's key schedule which sets up the *Cipher's -// pi and substitution tables for calls to Encrypt. This is used, primarily, -// by the bcrypt package to reuse the Blowfish key schedule during its -// set up. It's unlikely that you need to use this directly. -func ExpandKey(key []byte, c *Cipher) { - j := 0 - for i := 0; i < 18; i++ { - // Using inlined getNextWord for performance. - var d uint32 - for k := 0; k < 4; k++ { - d = d<<8 | uint32(key[j]) - j++ - if j >= len(key) { - j = 0 - } - } - c.p[i] ^= d - } - - var l, r uint32 - for i := 0; i < 18; i += 2 { - l, r = encryptBlock(l, r, c) - c.p[i], c.p[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s0[i], c.s0[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s1[i], c.s1[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s2[i], c.s2[i+1] = l, r - } - for i := 0; i < 256; i += 2 { - l, r = encryptBlock(l, r, c) - c.s3[i], c.s3[i+1] = l, r - } -} - -// This is similar to ExpandKey, but folds the salt during the key -// schedule. While ExpandKey is essentially expandKeyWithSalt with an all-zero -// salt passed in, reusing ExpandKey turns out to be a place of inefficiency -// and specializing it here is useful. -func expandKeyWithSalt(key []byte, salt []byte, c *Cipher) { - j := 0 - for i := 0; i < 18; i++ { - c.p[i] ^= getNextWord(key, &j) - } - - j = 0 - var l, r uint32 - for i := 0; i < 18; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.p[i], c.p[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s0[i], c.s0[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s1[i], c.s1[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s2[i], c.s2[i+1] = l, r - } - - for i := 0; i < 256; i += 2 { - l ^= getNextWord(salt, &j) - r ^= getNextWord(salt, &j) - l, r = encryptBlock(l, r, c) - c.s3[i], c.s3[i+1] = l, r - } -} - -func encryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { - xl, xr := l, r - xl ^= c.p[0] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[1] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[2] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[3] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[4] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[5] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[6] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[7] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[8] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[9] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[10] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[11] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[12] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[13] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[14] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[15] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[16] - xr ^= c.p[17] - return xr, xl -} - -func decryptBlock(l, r uint32, c *Cipher) (uint32, uint32) { - xl, xr := l, r - xl ^= c.p[17] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[16] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[15] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[14] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[13] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[12] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[11] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[10] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[9] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[8] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[7] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[6] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[5] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[4] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[3] - xr ^= ((c.s0[byte(xl>>24)] + c.s1[byte(xl>>16)]) ^ c.s2[byte(xl>>8)]) + c.s3[byte(xl)] ^ c.p[2] - xl ^= ((c.s0[byte(xr>>24)] + c.s1[byte(xr>>16)]) ^ c.s2[byte(xr>>8)]) + c.s3[byte(xr)] ^ c.p[1] - xr ^= c.p[0] - return xr, xl -} diff --git a/vendor/golang.org/x/crypto/blowfish/cipher.go b/vendor/golang.org/x/crypto/blowfish/cipher.go deleted file mode 100644 index 2641dadd64..0000000000 --- a/vendor/golang.org/x/crypto/blowfish/cipher.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package blowfish implements Bruce Schneier's Blowfish encryption algorithm. -package blowfish // import "golang.org/x/crypto/blowfish" - -// The code is a port of Bruce Schneier's C implementation. -// See https://www.schneier.com/blowfish.html. - -import "strconv" - -// The Blowfish block size in bytes. -const BlockSize = 8 - -// A Cipher is an instance of Blowfish encryption using a particular key. -type Cipher struct { - p [18]uint32 - s0, s1, s2, s3 [256]uint32 -} - -type KeySizeError int - -func (k KeySizeError) Error() string { - return "crypto/blowfish: invalid key size " + strconv.Itoa(int(k)) -} - -// NewCipher creates and returns a Cipher. -// The key argument should be the Blowfish key, from 1 to 56 bytes. -func NewCipher(key []byte) (*Cipher, error) { - var result Cipher - if k := len(key); k < 1 || k > 56 { - return nil, KeySizeError(k) - } - initCipher(&result) - ExpandKey(key, &result) - return &result, nil -} - -// NewSaltedCipher creates a returns a Cipher that folds a salt into its key -// schedule. For most purposes, NewCipher, instead of NewSaltedCipher, is -// sufficient and desirable. For bcrypt compatibility, the key can be over 56 -// bytes. -func NewSaltedCipher(key, salt []byte) (*Cipher, error) { - if len(salt) == 0 { - return NewCipher(key) - } - var result Cipher - if k := len(key); k < 1 { - return nil, KeySizeError(k) - } - initCipher(&result) - expandKeyWithSalt(key, salt, &result) - return &result, nil -} - -// BlockSize returns the Blowfish block size, 8 bytes. -// It is necessary to satisfy the Block interface in the -// package "crypto/cipher". -func (c *Cipher) BlockSize() int { return BlockSize } - -// Encrypt encrypts the 8-byte buffer src using the key k -// and stores the result in dst. -// Note that for amounts of data larger than a block, -// it is not safe to just call Encrypt on successive blocks; -// instead, use an encryption mode like CBC (see crypto/cipher/cbc.go). -func (c *Cipher) Encrypt(dst, src []byte) { - l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) - r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) - l, r = encryptBlock(l, r, c) - dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) - dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) -} - -// Decrypt decrypts the 8-byte buffer src using the key k -// and stores the result in dst. -func (c *Cipher) Decrypt(dst, src []byte) { - l := uint32(src[0])<<24 | uint32(src[1])<<16 | uint32(src[2])<<8 | uint32(src[3]) - r := uint32(src[4])<<24 | uint32(src[5])<<16 | uint32(src[6])<<8 | uint32(src[7]) - l, r = decryptBlock(l, r, c) - dst[0], dst[1], dst[2], dst[3] = byte(l>>24), byte(l>>16), byte(l>>8), byte(l) - dst[4], dst[5], dst[6], dst[7] = byte(r>>24), byte(r>>16), byte(r>>8), byte(r) -} - -func initCipher(c *Cipher) { - copy(c.p[0:], p[0:]) - copy(c.s0[0:], s0[0:]) - copy(c.s1[0:], s1[0:]) - copy(c.s2[0:], s2[0:]) - copy(c.s3[0:], s3[0:]) -} diff --git a/vendor/golang.org/x/crypto/blowfish/const.go b/vendor/golang.org/x/crypto/blowfish/const.go deleted file mode 100644 index d04077595a..0000000000 --- a/vendor/golang.org/x/crypto/blowfish/const.go +++ /dev/null @@ -1,199 +0,0 @@ -// Copyright 2010 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// The startup permutation array and substitution boxes. -// They are the hexadecimal digits of PI; see: -// https://www.schneier.com/code/constants.txt. - -package blowfish - -var s0 = [256]uint32{ - 0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7, 0xb8e1afed, 0x6a267e96, - 0xba7c9045, 0xf12c7f99, 0x24a19947, 0xb3916cf7, 0x0801f2e2, 0x858efc16, - 0x636920d8, 0x71574e69, 0xa458fea3, 0xf4933d7e, 0x0d95748f, 0x728eb658, - 0x718bcd58, 0x82154aee, 0x7b54a41d, 0xc25a59b5, 0x9c30d539, 0x2af26013, - 0xc5d1b023, 0x286085f0, 0xca417918, 0xb8db38ef, 0x8e79dcb0, 0x603a180e, - 0x6c9e0e8b, 0xb01e8a3e, 0xd71577c1, 0xbd314b27, 0x78af2fda, 0x55605c60, - 0xe65525f3, 0xaa55ab94, 0x57489862, 0x63e81440, 0x55ca396a, 0x2aab10b6, - 0xb4cc5c34, 0x1141e8ce, 0xa15486af, 0x7c72e993, 0xb3ee1411, 0x636fbc2a, - 0x2ba9c55d, 0x741831f6, 0xce5c3e16, 0x9b87931e, 0xafd6ba33, 0x6c24cf5c, - 0x7a325381, 0x28958677, 0x3b8f4898, 0x6b4bb9af, 0xc4bfe81b, 0x66282193, - 0x61d809cc, 0xfb21a991, 0x487cac60, 0x5dec8032, 0xef845d5d, 0xe98575b1, - 0xdc262302, 0xeb651b88, 0x23893e81, 0xd396acc5, 0x0f6d6ff3, 0x83f44239, - 0x2e0b4482, 0xa4842004, 0x69c8f04a, 0x9e1f9b5e, 0x21c66842, 0xf6e96c9a, - 0x670c9c61, 0xabd388f0, 0x6a51a0d2, 0xd8542f68, 0x960fa728, 0xab5133a3, - 0x6eef0b6c, 0x137a3be4, 0xba3bf050, 0x7efb2a98, 0xa1f1651d, 0x39af0176, - 0x66ca593e, 0x82430e88, 0x8cee8619, 0x456f9fb4, 0x7d84a5c3, 0x3b8b5ebe, - 0xe06f75d8, 0x85c12073, 0x401a449f, 0x56c16aa6, 0x4ed3aa62, 0x363f7706, - 0x1bfedf72, 0x429b023d, 0x37d0d724, 0xd00a1248, 0xdb0fead3, 0x49f1c09b, - 0x075372c9, 0x80991b7b, 0x25d479d8, 0xf6e8def7, 0xe3fe501a, 0xb6794c3b, - 0x976ce0bd, 0x04c006ba, 0xc1a94fb6, 0x409f60c4, 0x5e5c9ec2, 0x196a2463, - 0x68fb6faf, 0x3e6c53b5, 0x1339b2eb, 0x3b52ec6f, 0x6dfc511f, 0x9b30952c, - 0xcc814544, 0xaf5ebd09, 0xbee3d004, 0xde334afd, 0x660f2807, 0x192e4bb3, - 0xc0cba857, 0x45c8740f, 0xd20b5f39, 0xb9d3fbdb, 0x5579c0bd, 0x1a60320a, - 0xd6a100c6, 0x402c7279, 0x679f25fe, 0xfb1fa3cc, 0x8ea5e9f8, 0xdb3222f8, - 0x3c7516df, 0xfd616b15, 0x2f501ec8, 0xad0552ab, 0x323db5fa, 0xfd238760, - 0x53317b48, 0x3e00df82, 0x9e5c57bb, 0xca6f8ca0, 0x1a87562e, 0xdf1769db, - 0xd542a8f6, 0x287effc3, 0xac6732c6, 0x8c4f5573, 0x695b27b0, 0xbbca58c8, - 0xe1ffa35d, 0xb8f011a0, 0x10fa3d98, 0xfd2183b8, 0x4afcb56c, 0x2dd1d35b, - 0x9a53e479, 0xb6f84565, 0xd28e49bc, 0x4bfb9790, 0xe1ddf2da, 0xa4cb7e33, - 0x62fb1341, 0xcee4c6e8, 0xef20cada, 0x36774c01, 0xd07e9efe, 0x2bf11fb4, - 0x95dbda4d, 0xae909198, 0xeaad8e71, 0x6b93d5a0, 0xd08ed1d0, 0xafc725e0, - 0x8e3c5b2f, 0x8e7594b7, 0x8ff6e2fb, 0xf2122b64, 0x8888b812, 0x900df01c, - 0x4fad5ea0, 0x688fc31c, 0xd1cff191, 0xb3a8c1ad, 0x2f2f2218, 0xbe0e1777, - 0xea752dfe, 0x8b021fa1, 0xe5a0cc0f, 0xb56f74e8, 0x18acf3d6, 0xce89e299, - 0xb4a84fe0, 0xfd13e0b7, 0x7cc43b81, 0xd2ada8d9, 0x165fa266, 0x80957705, - 0x93cc7314, 0x211a1477, 0xe6ad2065, 0x77b5fa86, 0xc75442f5, 0xfb9d35cf, - 0xebcdaf0c, 0x7b3e89a0, 0xd6411bd3, 0xae1e7e49, 0x00250e2d, 0x2071b35e, - 0x226800bb, 0x57b8e0af, 0x2464369b, 0xf009b91e, 0x5563911d, 0x59dfa6aa, - 0x78c14389, 0xd95a537f, 0x207d5ba2, 0x02e5b9c5, 0x83260376, 0x6295cfa9, - 0x11c81968, 0x4e734a41, 0xb3472dca, 0x7b14a94a, 0x1b510052, 0x9a532915, - 0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400, 0x08ba6fb5, 0x571be91f, - 0xf296ec6b, 0x2a0dd915, 0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664, - 0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a, -} - -var s1 = [256]uint32{ - 0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623, 0xad6ea6b0, 0x49a7df7d, - 0x9cee60b8, 0x8fedb266, 0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1, - 0x193602a5, 0x75094c29, 0xa0591340, 0xe4183a3e, 0x3f54989a, 0x5b429d65, - 0x6b8fe4d6, 0x99f73fd6, 0xa1d29c07, 0xefe830f5, 0x4d2d38e6, 0xf0255dc1, - 0x4cdd2086, 0x8470eb26, 0x6382e9c6, 0x021ecc5e, 0x09686b3f, 0x3ebaefc9, - 0x3c971814, 0x6b6a70a1, 0x687f3584, 0x52a0e286, 0xb79c5305, 0xaa500737, - 0x3e07841c, 0x7fdeae5c, 0x8e7d44ec, 0x5716f2b8, 0xb03ada37, 0xf0500c0d, - 0xf01c1f04, 0x0200b3ff, 0xae0cf51a, 0x3cb574b2, 0x25837a58, 0xdc0921bd, - 0xd19113f9, 0x7ca92ff6, 0x94324773, 0x22f54701, 0x3ae5e581, 0x37c2dadc, - 0xc8b57634, 0x9af3dda7, 0xa9446146, 0x0fd0030e, 0xecc8c73e, 0xa4751e41, - 0xe238cd99, 0x3bea0e2f, 0x3280bba1, 0x183eb331, 0x4e548b38, 0x4f6db908, - 0x6f420d03, 0xf60a04bf, 0x2cb81290, 0x24977c79, 0x5679b072, 0xbcaf89af, - 0xde9a771f, 0xd9930810, 0xb38bae12, 0xdccf3f2e, 0x5512721f, 0x2e6b7124, - 0x501adde6, 0x9f84cd87, 0x7a584718, 0x7408da17, 0xbc9f9abc, 0xe94b7d8c, - 0xec7aec3a, 0xdb851dfa, 0x63094366, 0xc464c3d2, 0xef1c1847, 0x3215d908, - 0xdd433b37, 0x24c2ba16, 0x12a14d43, 0x2a65c451, 0x50940002, 0x133ae4dd, - 0x71dff89e, 0x10314e55, 0x81ac77d6, 0x5f11199b, 0x043556f1, 0xd7a3c76b, - 0x3c11183b, 0x5924a509, 0xf28fe6ed, 0x97f1fbfa, 0x9ebabf2c, 0x1e153c6e, - 0x86e34570, 0xeae96fb1, 0x860e5e0a, 0x5a3e2ab3, 0x771fe71c, 0x4e3d06fa, - 0x2965dcb9, 0x99e71d0f, 0x803e89d6, 0x5266c825, 0x2e4cc978, 0x9c10b36a, - 0xc6150eba, 0x94e2ea78, 0xa5fc3c53, 0x1e0a2df4, 0xf2f74ea7, 0x361d2b3d, - 0x1939260f, 0x19c27960, 0x5223a708, 0xf71312b6, 0xebadfe6e, 0xeac31f66, - 0xe3bc4595, 0xa67bc883, 0xb17f37d1, 0x018cff28, 0xc332ddef, 0xbe6c5aa5, - 0x65582185, 0x68ab9802, 0xeecea50f, 0xdb2f953b, 0x2aef7dad, 0x5b6e2f84, - 0x1521b628, 0x29076170, 0xecdd4775, 0x619f1510, 0x13cca830, 0xeb61bd96, - 0x0334fe1e, 0xaa0363cf, 0xb5735c90, 0x4c70a239, 0xd59e9e0b, 0xcbaade14, - 0xeecc86bc, 0x60622ca7, 0x9cab5cab, 0xb2f3846e, 0x648b1eaf, 0x19bdf0ca, - 0xa02369b9, 0x655abb50, 0x40685a32, 0x3c2ab4b3, 0x319ee9d5, 0xc021b8f7, - 0x9b540b19, 0x875fa099, 0x95f7997e, 0x623d7da8, 0xf837889a, 0x97e32d77, - 0x11ed935f, 0x16681281, 0x0e358829, 0xc7e61fd6, 0x96dedfa1, 0x7858ba99, - 0x57f584a5, 0x1b227263, 0x9b83c3ff, 0x1ac24696, 0xcdb30aeb, 0x532e3054, - 0x8fd948e4, 0x6dbc3128, 0x58ebf2ef, 0x34c6ffea, 0xfe28ed61, 0xee7c3c73, - 0x5d4a14d9, 0xe864b7e3, 0x42105d14, 0x203e13e0, 0x45eee2b6, 0xa3aaabea, - 0xdb6c4f15, 0xfacb4fd0, 0xc742f442, 0xef6abbb5, 0x654f3b1d, 0x41cd2105, - 0xd81e799e, 0x86854dc7, 0xe44b476a, 0x3d816250, 0xcf62a1f2, 0x5b8d2646, - 0xfc8883a0, 0xc1c7b6a3, 0x7f1524c3, 0x69cb7492, 0x47848a0b, 0x5692b285, - 0x095bbf00, 0xad19489d, 0x1462b174, 0x23820e00, 0x58428d2a, 0x0c55f5ea, - 0x1dadf43e, 0x233f7061, 0x3372f092, 0x8d937e41, 0xd65fecf1, 0x6c223bdb, - 0x7cde3759, 0xcbee7460, 0x4085f2a7, 0xce77326e, 0xa6078084, 0x19f8509e, - 0xe8efd855, 0x61d99735, 0xa969a7aa, 0xc50c06c2, 0x5a04abfc, 0x800bcadc, - 0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9, 0xdb73dbd3, 0x105588cd, - 0x675fda79, 0xe3674340, 0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20, - 0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7, -} - -var s2 = [256]uint32{ - 0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934, 0x411520f7, 0x7602d4f7, - 0xbcf46b2e, 0xd4a20068, 0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af, - 0x1e39f62e, 0x97244546, 0x14214f74, 0xbf8b8840, 0x4d95fc1d, 0x96b591af, - 0x70f4ddd3, 0x66a02f45, 0xbfbc09ec, 0x03bd9785, 0x7fac6dd0, 0x31cb8504, - 0x96eb27b3, 0x55fd3941, 0xda2547e6, 0xabca0a9a, 0x28507825, 0x530429f4, - 0x0a2c86da, 0xe9b66dfb, 0x68dc1462, 0xd7486900, 0x680ec0a4, 0x27a18dee, - 0x4f3ffea2, 0xe887ad8c, 0xb58ce006, 0x7af4d6b6, 0xaace1e7c, 0xd3375fec, - 0xce78a399, 0x406b2a42, 0x20fe9e35, 0xd9f385b9, 0xee39d7ab, 0x3b124e8b, - 0x1dc9faf7, 0x4b6d1856, 0x26a36631, 0xeae397b2, 0x3a6efa74, 0xdd5b4332, - 0x6841e7f7, 0xca7820fb, 0xfb0af54e, 0xd8feb397, 0x454056ac, 0xba489527, - 0x55533a3a, 0x20838d87, 0xfe6ba9b7, 0xd096954b, 0x55a867bc, 0xa1159a58, - 0xcca92963, 0x99e1db33, 0xa62a4a56, 0x3f3125f9, 0x5ef47e1c, 0x9029317c, - 0xfdf8e802, 0x04272f70, 0x80bb155c, 0x05282ce3, 0x95c11548, 0xe4c66d22, - 0x48c1133f, 0xc70f86dc, 0x07f9c9ee, 0x41041f0f, 0x404779a4, 0x5d886e17, - 0x325f51eb, 0xd59bc0d1, 0xf2bcc18f, 0x41113564, 0x257b7834, 0x602a9c60, - 0xdff8e8a3, 0x1f636c1b, 0x0e12b4c2, 0x02e1329e, 0xaf664fd1, 0xcad18115, - 0x6b2395e0, 0x333e92e1, 0x3b240b62, 0xeebeb922, 0x85b2a20e, 0xe6ba0d99, - 0xde720c8c, 0x2da2f728, 0xd0127845, 0x95b794fd, 0x647d0862, 0xe7ccf5f0, - 0x5449a36f, 0x877d48fa, 0xc39dfd27, 0xf33e8d1e, 0x0a476341, 0x992eff74, - 0x3a6f6eab, 0xf4f8fd37, 0xa812dc60, 0xa1ebddf8, 0x991be14c, 0xdb6e6b0d, - 0xc67b5510, 0x6d672c37, 0x2765d43b, 0xdcd0e804, 0xf1290dc7, 0xcc00ffa3, - 0xb5390f92, 0x690fed0b, 0x667b9ffb, 0xcedb7d9c, 0xa091cf0b, 0xd9155ea3, - 0xbb132f88, 0x515bad24, 0x7b9479bf, 0x763bd6eb, 0x37392eb3, 0xcc115979, - 0x8026e297, 0xf42e312d, 0x6842ada7, 0xc66a2b3b, 0x12754ccc, 0x782ef11c, - 0x6a124237, 0xb79251e7, 0x06a1bbe6, 0x4bfb6350, 0x1a6b1018, 0x11caedfa, - 0x3d25bdd8, 0xe2e1c3c9, 0x44421659, 0x0a121386, 0xd90cec6e, 0xd5abea2a, - 0x64af674e, 0xda86a85f, 0xbebfe988, 0x64e4c3fe, 0x9dbc8057, 0xf0f7c086, - 0x60787bf8, 0x6003604d, 0xd1fd8346, 0xf6381fb0, 0x7745ae04, 0xd736fccc, - 0x83426b33, 0xf01eab71, 0xb0804187, 0x3c005e5f, 0x77a057be, 0xbde8ae24, - 0x55464299, 0xbf582e61, 0x4e58f48f, 0xf2ddfda2, 0xf474ef38, 0x8789bdc2, - 0x5366f9c3, 0xc8b38e74, 0xb475f255, 0x46fcd9b9, 0x7aeb2661, 0x8b1ddf84, - 0x846a0e79, 0x915f95e2, 0x466e598e, 0x20b45770, 0x8cd55591, 0xc902de4c, - 0xb90bace1, 0xbb8205d0, 0x11a86248, 0x7574a99e, 0xb77f19b6, 0xe0a9dc09, - 0x662d09a1, 0xc4324633, 0xe85a1f02, 0x09f0be8c, 0x4a99a025, 0x1d6efe10, - 0x1ab93d1d, 0x0ba5a4df, 0xa186f20f, 0x2868f169, 0xdcb7da83, 0x573906fe, - 0xa1e2ce9b, 0x4fcd7f52, 0x50115e01, 0xa70683fa, 0xa002b5c4, 0x0de6d027, - 0x9af88c27, 0x773f8641, 0xc3604c06, 0x61a806b5, 0xf0177a28, 0xc0f586e0, - 0x006058aa, 0x30dc7d62, 0x11e69ed7, 0x2338ea63, 0x53c2dd94, 0xc2c21634, - 0xbbcbee56, 0x90bcb6de, 0xebfc7da1, 0xce591d76, 0x6f05e409, 0x4b7c0188, - 0x39720a3d, 0x7c927c24, 0x86e3725f, 0x724d9db9, 0x1ac15bb4, 0xd39eb8fc, - 0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4, 0x1e50ef5e, 0xb161e6f8, - 0xa28514d9, 0x6c51133c, 0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837, - 0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0, -} - -var s3 = [256]uint32{ - 0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b, 0x5cb0679e, 0x4fa33742, - 0xd3822740, 0x99bc9bbe, 0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b, - 0xb78c1b6b, 0x21a19045, 0xb26eb1be, 0x6a366eb4, 0x5748ab2f, 0xbc946e79, - 0xc6a376d2, 0x6549c2c8, 0x530ff8ee, 0x468dde7d, 0xd5730a1d, 0x4cd04dc6, - 0x2939bbdb, 0xa9ba4650, 0xac9526e8, 0xbe5ee304, 0xa1fad5f0, 0x6a2d519a, - 0x63ef8ce2, 0x9a86ee22, 0xc089c2b8, 0x43242ef6, 0xa51e03aa, 0x9cf2d0a4, - 0x83c061ba, 0x9be96a4d, 0x8fe51550, 0xba645bd6, 0x2826a2f9, 0xa73a3ae1, - 0x4ba99586, 0xef5562e9, 0xc72fefd3, 0xf752f7da, 0x3f046f69, 0x77fa0a59, - 0x80e4a915, 0x87b08601, 0x9b09e6ad, 0x3b3ee593, 0xe990fd5a, 0x9e34d797, - 0x2cf0b7d9, 0x022b8b51, 0x96d5ac3a, 0x017da67d, 0xd1cf3ed6, 0x7c7d2d28, - 0x1f9f25cf, 0xadf2b89b, 0x5ad6b472, 0x5a88f54c, 0xe029ac71, 0xe019a5e6, - 0x47b0acfd, 0xed93fa9b, 0xe8d3c48d, 0x283b57cc, 0xf8d56629, 0x79132e28, - 0x785f0191, 0xed756055, 0xf7960e44, 0xe3d35e8c, 0x15056dd4, 0x88f46dba, - 0x03a16125, 0x0564f0bd, 0xc3eb9e15, 0x3c9057a2, 0x97271aec, 0xa93a072a, - 0x1b3f6d9b, 0x1e6321f5, 0xf59c66fb, 0x26dcf319, 0x7533d928, 0xb155fdf5, - 0x03563482, 0x8aba3cbb, 0x28517711, 0xc20ad9f8, 0xabcc5167, 0xccad925f, - 0x4de81751, 0x3830dc8e, 0x379d5862, 0x9320f991, 0xea7a90c2, 0xfb3e7bce, - 0x5121ce64, 0x774fbe32, 0xa8b6e37e, 0xc3293d46, 0x48de5369, 0x6413e680, - 0xa2ae0810, 0xdd6db224, 0x69852dfd, 0x09072166, 0xb39a460a, 0x6445c0dd, - 0x586cdecf, 0x1c20c8ae, 0x5bbef7dd, 0x1b588d40, 0xccd2017f, 0x6bb4e3bb, - 0xdda26a7e, 0x3a59ff45, 0x3e350a44, 0xbcb4cdd5, 0x72eacea8, 0xfa6484bb, - 0x8d6612ae, 0xbf3c6f47, 0xd29be463, 0x542f5d9e, 0xaec2771b, 0xf64e6370, - 0x740e0d8d, 0xe75b1357, 0xf8721671, 0xaf537d5d, 0x4040cb08, 0x4eb4e2cc, - 0x34d2466a, 0x0115af84, 0xe1b00428, 0x95983a1d, 0x06b89fb4, 0xce6ea048, - 0x6f3f3b82, 0x3520ab82, 0x011a1d4b, 0x277227f8, 0x611560b1, 0xe7933fdc, - 0xbb3a792b, 0x344525bd, 0xa08839e1, 0x51ce794b, 0x2f32c9b7, 0xa01fbac9, - 0xe01cc87e, 0xbcc7d1f6, 0xcf0111c3, 0xa1e8aac7, 0x1a908749, 0xd44fbd9a, - 0xd0dadecb, 0xd50ada38, 0x0339c32a, 0xc6913667, 0x8df9317c, 0xe0b12b4f, - 0xf79e59b7, 0x43f5bb3a, 0xf2d519ff, 0x27d9459c, 0xbf97222c, 0x15e6fc2a, - 0x0f91fc71, 0x9b941525, 0xfae59361, 0xceb69ceb, 0xc2a86459, 0x12baa8d1, - 0xb6c1075e, 0xe3056a0c, 0x10d25065, 0xcb03a442, 0xe0ec6e0e, 0x1698db3b, - 0x4c98a0be, 0x3278e964, 0x9f1f9532, 0xe0d392df, 0xd3a0342b, 0x8971f21e, - 0x1b0a7441, 0x4ba3348c, 0xc5be7120, 0xc37632d8, 0xdf359f8d, 0x9b992f2e, - 0xe60b6f47, 0x0fe3f11d, 0xe54cda54, 0x1edad891, 0xce6279cf, 0xcd3e7e6f, - 0x1618b166, 0xfd2c1d05, 0x848fd2c5, 0xf6fb2299, 0xf523f357, 0xa6327623, - 0x93a83531, 0x56cccd02, 0xacf08162, 0x5a75ebb5, 0x6e163697, 0x88d273cc, - 0xde966292, 0x81b949d0, 0x4c50901b, 0x71c65614, 0xe6c6c7bd, 0x327a140a, - 0x45e1d006, 0xc3f27b9a, 0xc9aa53fd, 0x62a80f00, 0xbb25bfe2, 0x35bdd2f6, - 0x71126905, 0xb2040222, 0xb6cbcf7c, 0xcd769c2b, 0x53113ec0, 0x1640e3d3, - 0x38abbd60, 0x2547adf0, 0xba38209c, 0xf746ce76, 0x77afa1c5, 0x20756060, - 0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e, 0x1948c25c, 0x02fb8a8c, - 0x01c36ae4, 0xd6ebe1f9, 0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f, - 0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6, -} - -var p = [18]uint32{ - 0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344, 0xa4093822, 0x299f31d0, - 0x082efa98, 0xec4e6c89, 0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c, - 0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917, 0x9216d5d9, 0x8979fb1b, -}