diff --git a/Gopkg.lock b/Gopkg.lock index 03c1165f008..6c428d6fd23 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -212,7 +212,7 @@ version = "v18" [[projects]] - digest = "1:fb5b2aed0d774e210c1f2c0893e620cb3fa98957d3b925d0378f93b9613eb605" + digest = "1:b3ff820a2b867b5140ac8e6c84a1124affe7d671296b7648d06b61d0834617cf" name = "github.com/coreos/ignition" packages = [ "config/shared/errors", @@ -226,15 +226,16 @@ "config/v2_1/types", "config/v2_2", "config/v2_2/types", - "config/v2_3_experimental/types", + "config/v2_4/types", + "config/v2_5_experimental/types", "config/validate", "config/validate/astjson", "config/validate/astnode", "config/validate/report", ] pruneopts = "NUT" - revision = "76107251acd117c6d3e5b4dae2b47f82f944984b" - version = "v0.26.0" + revision = "7afbeba044a8bf5762609fbb5f352291eeb7ad9a" + version = "v0.35.0" [[projects]] digest = "1:ffe9824d294da03b391f44e1ae8281281b4afc1bdaa9588c9097785e3af10cec" @@ -395,7 +396,7 @@ [[projects]] branch = "master" - digest = "1:67551c599e04b31fe799b4bd4de0e101d3c022057213ef7af014bdce5f525b18" + digest = "1:6854db1bc54bfbd6630f32715a75f2850d3f4c4750bbe91e36666fd12a88299e" name = "github.com/gophercloud/gophercloud" packages = [ ".", @@ -409,6 +410,7 @@ "openstack/identity/v2/tenants", "openstack/identity/v2/tokens", "openstack/identity/v3/tokens", + "openstack/imageservice/v2/imagedata", "openstack/imageservice/v2/images", "openstack/loadbalancer/v2/apiversions", "openstack/loadbalancer/v2/l7policies", @@ -433,7 +435,7 @@ "pagination", ] pruneopts = "NUT" - revision = "6ad562af8c1fd8a69397a13caf58fa184d115b56" + revision = "46fdd1830e9a58a60f7489b973ed3789a48cb1f1" [[projects]] branch = "master" @@ -521,14 +523,6 @@ revision = "1455def202f6e05b95cc7bfc7e8ae67ae5141eba" version = "v0.1.0" -[[projects]] - branch = "master" - digest = "1:c26b841ff18d8b7fa1606f869ec66eedd6327469e33f9ee3dcb8bef800fdad50" - name = "github.com/kubernetes/apimachinery" - packages = ["pkg/util/rand"] - pruneopts = "NUT" - revision = "af6325b3a843fc0c4c448b1bd770ebab40e9acc4" - [[projects]] digest = "1:1da9aa83870a429ce7127ced903a0b583012ed934682a5d5acaa12d74b92ebdc" name = "github.com/libvirt/libvirt-go" @@ -1396,6 +1390,7 @@ "github.com/containers/image/pkg/sysregistriesv2", "github.com/coreos/ignition/config/util", "github.com/coreos/ignition/config/v2_2/types", + "github.com/coreos/ignition/config/v2_4/types", "github.com/ghodss/yaml", "github.com/golang/mock/gomock", "github.com/gophercloud/gophercloud", @@ -1404,6 +1399,7 @@ "github.com/gophercloud/gophercloud/openstack/compute/v2/flavors", "github.com/gophercloud/gophercloud/openstack/compute/v2/servers", "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", + "github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata", "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images", "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/apiversions", "github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers", @@ -1419,7 +1415,6 @@ "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers", "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects", "github.com/gophercloud/utils/openstack/clientconfig", - "github.com/kubernetes/apimachinery/pkg/util/rand", "github.com/libvirt/libvirt-go", "github.com/metal3-io/baremetal-operator/pkg/apis/metal3/v1alpha1", "github.com/metal3-io/baremetal-operator/pkg/bmc", diff --git a/Gopkg.toml b/Gopkg.toml index 70006f6775c..53d01af46fa 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -27,7 +27,7 @@ required = [ [[constraint]] name = "github.com/coreos/ignition" - version = "0.26.0" + version = "0.35.0" [[constraint]] name = "github.com/libvirt/libvirt-go" diff --git a/pkg/destroy/bootstrap/bootstrap.go b/pkg/destroy/bootstrap/bootstrap.go index 22e73168b05..005bb20e610 100644 --- a/pkg/destroy/bootstrap/bootstrap.go +++ b/pkg/destroy/bootstrap/bootstrap.go @@ -74,9 +74,10 @@ func Destroy(dir string) (err error) { return errors.Wrap(err, "Terraform apply") } case openstack.Name: - err = osp.DeleteSwiftContainer(metadata.InfraID, metadata.OpenStack.Cloud) + imageName := metadata.InfraID + "-ignition" + err = osp.DeleteGlanceImage(imageName, metadata.OpenStack.Cloud) if err != nil { - return errors.Wrapf(err, "Failed to delete swift container %s", metadata.InfraID) + return errors.Wrapf(err, "Failed to delete glance image %s", imageName) } } diff --git a/pkg/destroy/openstack/glance.go b/pkg/destroy/openstack/glance.go new file mode 100644 index 00000000000..a94525934e4 --- /dev/null +++ b/pkg/destroy/openstack/glance.go @@ -0,0 +1,40 @@ +package openstack + +import ( + "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" + "github.com/gophercloud/utils/openstack/clientconfig" +) + +// DeleteGlanceImage deletes the image with the specified name +func DeleteGlanceImage(name string, cloud string) error { + opts := clientconfig.ClientOpts{ + Cloud: cloud, + } + + conn, err := clientconfig.NewServiceClient("image", &opts) + if err != nil { + return err + } + + listOpts := images.ListOpts{ + Name: name, + } + + allPages, err := images.List(conn, listOpts).AllPages() + if err != nil { + return err + } + + allImages, err := images.ExtractImages(allPages) + if err != nil { + return err + } + + for _, image := range allImages { + err := images.Delete(conn, image.ID).ExtractErr() + if err != nil { + return err + } + } + return nil +} diff --git a/pkg/destroy/openstack/openstack.go b/pkg/destroy/openstack/openstack.go index 7b722dd2914..f842deb4348 100644 --- a/pkg/destroy/openstack/openstack.go +++ b/pkg/destroy/openstack/openstack.go @@ -544,6 +544,10 @@ func deleteContainers(opts *clientconfig.ClientOpts, filter Filter, logger logru conn, err := clientconfig.NewServiceClient("object-store", opts) if err != nil { + if _, ok := err.(*gophercloud.ErrEndpointNotFound); ok { + logger.Debug("Swift endpoint is not found") + return true, nil + } logger.Errorf("%v", err) return false, nil } diff --git a/pkg/destroy/openstack/swift.go b/pkg/destroy/openstack/swift.go deleted file mode 100644 index b390ab0ddcb..00000000000 --- a/pkg/destroy/openstack/swift.go +++ /dev/null @@ -1,43 +0,0 @@ -package openstack - -import ( - "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers" - "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects" - "github.com/gophercloud/utils/openstack/clientconfig" -) - -// DeleteSwiftContainer deletes a container and all of its objects. -func DeleteSwiftContainer(name string, cloud string) error { - opts := clientconfig.ClientOpts{ - Cloud: cloud, - } - - swiftClient, err := clientconfig.NewServiceClient("object-store", &opts) - if err != nil { - return err - } - - listOpts := objects.ListOpts{ - Full: false, - } - - allPages, err := objects.List(swiftClient, name, listOpts).AllPages() - if err != nil { - return err - } - - allObjects, err := objects.ExtractNames(allPages) - if err != nil { - return err - } - - for _, object := range allObjects { - _, err := objects.Delete(swiftClient, name, object, objects.DeleteOpts{}).Extract() - if err != nil { - return err - } - } - - _, err = containers.Delete(swiftClient, name).Extract() - return err -} diff --git a/pkg/tfvars/openstack/bootstrap_ignition.go b/pkg/tfvars/openstack/bootstrap_ignition.go index 29a96afe105..0ed53c5b6a6 100644 --- a/pkg/tfvars/openstack/bootstrap_ignition.go +++ b/pkg/tfvars/openstack/bootstrap_ignition.go @@ -6,59 +6,49 @@ import ( "fmt" "strings" - ignition "github.com/coreos/ignition/config/v2_2/types" - "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/containers" - "github.com/gophercloud/gophercloud/openstack/objectstorage/v1/objects" + ignition "github.com/coreos/ignition/config/v2_4/types" + "github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata" + "github.com/gophercloud/gophercloud/openstack/imageservice/v2/images" "github.com/gophercloud/utils/openstack/clientconfig" - "github.com/kubernetes/apimachinery/pkg/util/rand" "github.com/sirupsen/logrus" "github.com/vincent-petithory/dataurl" ) -// createBootstrapSwiftObject creates a container and object in swift with the bootstrap ignition config. -func createBootstrapSwiftObject(cloud string, bootstrapIgn string, clusterID string) (string, error) { - logrus.Debugln("Creating a Swift container for your bootstrap ignition...") +// uploadBootstrapConfig uploads the bootstrap Ignition config in Glance and returns its location +func uploadBootstrapConfig(cloud string, bootstrapIgn string, clusterID string) (string, error) { + logrus.Debugln("Creating a Glance image for your bootstrap ignition config...") opts := clientconfig.ClientOpts{ Cloud: cloud, } - conn, err := clientconfig.NewServiceClient("object-store", &opts) + conn, err := clientconfig.NewServiceClient("image", &opts) if err != nil { return "", err } - containerCreateOpts := containers.CreateOpts{ - ContainerRead: ".r:*", - - // "kubernetes.io/cluster/${var.cluster_id}" = "owned" - Metadata: map[string]string{ - "Name": fmt.Sprintf("%s-ignition", clusterID), - "openshiftClusterID": clusterID, - }, + imageCreateOpts := images.CreateOpts{ + Name: fmt.Sprintf("%s-ignition", clusterID), + ContainerFormat: "bare", + DiskFormat: "raw", + Tags: []string{fmt.Sprintf("openshiftClusterID=%s", clusterID)}, + // TODO(mfedosin): add Description when gophercloud supports it. } - _, err = containers.Create(conn, clusterID, containerCreateOpts).Extract() + img, err := images.Create(conn, imageCreateOpts).Extract() if err != nil { return "", err } - logrus.Debugf("Container %s was created.", clusterID) - - logrus.Debugf("Creating a Swift object in container %s containing your bootstrap ignition...", clusterID) - objectCreateOpts := objects.CreateOpts{ - ContentType: "text/plain", - Content: strings.NewReader(bootstrapIgn), - DeleteAfter: 3600, - } - - objID := rand.String(16) + logrus.Debugf("Image %s was created.", img.Name) - _, err = objects.Create(conn, clusterID, objID, objectCreateOpts).Extract() - if err != nil { + logrus.Debugf("Uploading bootstrap config to the image %v with ID %v", img.Name, img.ID) + res := imagedata.Upload(conn, img.ID, strings.NewReader(bootstrapIgn)) + if res.Err != nil { return "", err } - logrus.Debugf("The object was created.") + logrus.Debugf("The config was uploaded.") - return objID, nil + // img.File contains location of the uploaded data + return img.File, nil } // To allow Ignition to download its config on the bootstrap machine from a location secured by a @@ -70,7 +60,7 @@ func createBootstrapSwiftObject(cloud string, bootstrapIgn string, clusterID str // generateIgnitionShim is used to generate an ignition file that contains a user ca bundle // in its Security section. -func generateIgnitionShim(userCA string, clusterID string, swiftObject string) (string, error) { +func generateIgnitionShim(userCA string, clusterID string, bootstrapConfigURL string, tokenID string) (string, error) { fileMode := 420 // DHCP Config @@ -134,6 +124,13 @@ prepend domain-name-servers 127.0.0.1;` } } + headers := []ignition.HTTPHeader{ + { + Name: "X-Auth-Token", + Value: tokenID, + }, + } + ign := ignition.Config{ Ignition: ignition.Ignition{ Version: ignition.MaxVersion.String(), @@ -141,7 +138,8 @@ prepend domain-name-servers 127.0.0.1;` Config: ignition.IgnitionConfig{ Append: []ignition.ConfigReference{ { - Source: swiftObject, + Source: bootstrapConfigURL, + HTTPHeaders: headers, }, }, }, @@ -162,3 +160,22 @@ prepend domain-name-servers 127.0.0.1;` return string(data), nil } + +// getAuthToken fetches valid OpenStack authentication token ID +func getAuthToken(cloud string) (string, error) { + opts := &clientconfig.ClientOpts{ + Cloud: cloud, + } + + conn, err := clientconfig.NewServiceClient("identity", opts) + if err != nil { + return "", err + } + + token, err := conn.GetAuthResult().ExtractTokenID() + if err != nil { + return "", err + } + + return token, nil +} diff --git a/pkg/tfvars/openstack/openstack.go b/pkg/tfvars/openstack/openstack.go index 734070f4675..ef004ce13e9 100644 --- a/pkg/tfvars/openstack/openstack.go +++ b/pkg/tfvars/openstack/openstack.go @@ -72,18 +72,23 @@ func TFVars(masterConfig *v1alpha1.OpenstackProviderSpec, cloud string, external } } - swiftPublicURL, err := getSwiftPublicURL(cloud) + glancePublicURL, err := getGlancePublicURL(cloud) if err != nil { return nil, err } - objectID, err := createBootstrapSwiftObject(cloud, bootstrapIgn, infraID) + configLocation, err := uploadBootstrapConfig(cloud, bootstrapIgn, infraID) if err != nil { return nil, err } - objectAddress := fmt.Sprintf("%s/%s/%s", swiftPublicURL, infraID, objectID) - userCAIgnition, err := generateIgnitionShim(userCA, infraID, objectAddress) + tokenID, err := getAuthToken(cloud) + if err != nil { + return nil, err + } + + bootstrapConfigURL := fmt.Sprintf("%s%s", glancePublicURL, configLocation) + userCAIgnition, err := generateIgnitionShim(userCA, infraID, bootstrapConfigURL, tokenID) if err != nil { return nil, err } @@ -133,7 +138,7 @@ func validateOverriddenImageName(imageName, cloud string) error { return nil } -// We need to obtain Swift public endpoint that will be used by Ignition to download bootstrap ignition files. +// We need to obtain Glance public endpoint that will be used by Ignition to download bootstrap ignition files. // By design this should be done by using https://www.terraform.io/docs/providers/openstack/d/identity_endpoint_v3.html // but OpenStack default policies forbid to use this API for regular users. // On the other hand when a user authenticates in OpenStack (i.e. gets a token), it includes the whole service @@ -143,21 +148,21 @@ func validateOverriddenImageName(imageName, cloud string) error { // We do next: // 1. In "getServiceCatalog" we authenticate in OpenStack (tokens.Create(..)), // parse the token and extract the service catalog: (ExtractServiceCatalog()) -// 2. In getSwiftPublicURL we iterate through the catalog and find "public" endpoint for "object-store". +// 2. In getGlancePublicURL we iterate through the catalog and find "public" endpoint for "image". -// getSwiftPublicURL obtains Swift public endpoint URL -func getSwiftPublicURL(cloud string) (string, error) { - var swiftPublicURL string +// getGlancePublicURL obtains Glance public endpoint URL +func getGlancePublicURL(cloud string) (string, error) { + var glancePublicURL string serviceCatalog, err := getServiceCatalog(cloud) if err != nil { return "", err } for _, svc := range serviceCatalog.Entries { - if svc.Type == "object-store" { + if svc.Type == "image" { for _, e := range svc.Endpoints { if e.Interface == "public" { - swiftPublicURL = e.URL + glancePublicURL = e.URL break } } @@ -165,11 +170,11 @@ func getSwiftPublicURL(cloud string) (string, error) { } } - if swiftPublicURL == "" { - return "", errors.Errorf("cannot retrieve Swift URL from the service catalog") + if glancePublicURL == "" { + return "", errors.Errorf("cannot retrieve Glance URL from the service catalog") } - return swiftPublicURL, nil + return glancePublicURL, nil } // getServiceCatalog fetches OpenStack service catalog with service endpoints diff --git a/vendor/github.com/coreos/ignition/config/shared/errors/errors.go b/vendor/github.com/coreos/ignition/config/shared/errors/errors.go index f2d1ddf2866..f2b47cf9079 100644 --- a/vendor/github.com/coreos/ignition/config/shared/errors/errors.go +++ b/vendor/github.com/coreos/ignition/config/shared/errors/errors.go @@ -64,6 +64,9 @@ var ( ErrUnrecognizedRaidLevel = errors.New("unrecognized raid level") ErrShouldNotExistWithOthers = errors.New("shouldExist specified false with other options also specified") ErrZeroesWithShouldNotExist = errors.New("shouldExist is false for a partition and other partition(s) has start or size 0") + ErrPartitionsUnitsMismatch = errors.New("cannot mix MBs and sectors within a disk") + ErrSizeDeprecated = errors.New("size is deprecated; use sizeMB instead") + ErrStartDeprecated = errors.New("start is deprecated; use startMB instead") // Passwd section errors ErrPasswdCreateDeprecated = errors.New("the create object has been deprecated in favor of user-level options") @@ -85,11 +88,18 @@ var ( 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") + ErrInvalidScheme = errors.New("invalid url scheme") + ErrInvalidUrl = errors.New("unable to parse url") + ErrEmptyHTTPHeaderName = errors.New("HTTP header name can't be empty") + ErrDuplicateHTTPHeaders = errors.New("all header names in the list must be unique") + ErrUnsupportedSchemeForHTTPHeaders = errors.New("cannot use HTTP headers with this source scheme") + ErrHashMalformed = errors.New("malformed hash specifier") + ErrHashWrongSize = errors.New("incorrect size for hash sum") + ErrHashUnrecognized = errors.New("unrecognized hash function") + ErrEngineConfiguration = errors.New("engine incorrectly configured") + + // AWS S3 specific errors + ErrInvalidS3ObjectVersionId = errors.New("invalid S3 object VersionId") ) // NewNoInstallSectionError produces an error indicating the given unit, named diff --git a/vendor/github.com/coreos/ignition/config/util/parsingErrors.go b/vendor/github.com/coreos/ignition/config/util/parsingErrors.go index 6b6b114dafc..d51fc1f3e02 100644 --- a/vendor/github.com/coreos/ignition/config/util/parsingErrors.go +++ b/vendor/github.com/coreos/ignition/config/util/parsingErrors.go @@ -19,7 +19,7 @@ import ( "errors" configErrors "github.com/coreos/ignition/config/shared/errors" - "github.com/coreos/ignition/config/v2_3_experimental/types" + "github.com/coreos/ignition/config/v2_5_experimental/types" "github.com/coreos/ignition/config/validate/report" json "github.com/ajeddeloh/go-json" diff --git a/vendor/github.com/coreos/ignition/config/v1/types/config.go b/vendor/github.com/coreos/ignition/config/v1/types/config.go index f9215699cbd..3a369e4f3e8 100644 --- a/vendor/github.com/coreos/ignition/config/v1/types/config.go +++ b/vendor/github.com/coreos/ignition/config/v1/types/config.go @@ -14,10 +14,18 @@ package types +import "github.com/coreos/go-semver/semver" + const ( Version = 1 ) +var ( + MaxVersion = semver.Version{ + Major: Version, + } +) + type Config struct { Version int `json:"ignitionVersion"` Storage Storage `json:"storage,omitempty"` diff --git a/vendor/github.com/coreos/ignition/config/v2_0/append.go b/vendor/github.com/coreos/ignition/config/v2_0/append.go index cee6bc412e2..b005734b1e8 100644 --- a/vendor/github.com/coreos/ignition/config/v2_0/append.go +++ b/vendor/github.com/coreos/ignition/config/v2_0/append.go @@ -36,11 +36,10 @@ func Append(oldConfig, newConfig types.Config) types.Config { // appendStruct is an internal helper function to AppendConfig. Given two values // of structures (assumed to be the same type), recursively iterate over every // field in the struct, appending slices, recursively appending structs, and -// overwriting old values with the new for all other types. Individual fields -// are able to override their merge strategy using the "merge" tag. Accepted -// values are "new" or "old": "new" uses the new value, "old" uses the old -// value. These are currently only used for "ignition.config" and -// "ignition.version". +// overwriting old values with the new for all other types. Some individual +// struct fields have alternate merge strategies, determined by the field name. +// Currently these fields are "ignition.version", which uses the old value, and +// "ignition.config" which uses the new value. func appendStruct(vOld, vNew reflect.Value) reflect.Value { tOld := vOld.Type() vRes := reflect.New(tOld) @@ -50,11 +49,11 @@ func appendStruct(vOld, vNew reflect.Value) reflect.Value { vfNew := vNew.Field(i) vfRes := vRes.Elem().Field(i) - switch tOld.Field(i).Tag.Get("merge") { - case "old": + switch tOld.Field(i).Name { + case "Version": vfRes.Set(vfOld) continue - case "new": + case "Config": vfRes.Set(vfNew) continue } @@ -65,7 +64,11 @@ func appendStruct(vOld, vNew reflect.Value) reflect.Value { case reflect.Slice: vfRes.Set(reflect.AppendSlice(vfOld, vfNew)) default: - vfRes.Set(vfNew) + if vfNew.Kind() == reflect.Ptr && vfNew.IsNil() { + vfRes.Set(vfOld) + } else { + vfRes.Set(vfNew) + } } } diff --git a/vendor/github.com/coreos/ignition/config/v2_1/append.go b/vendor/github.com/coreos/ignition/config/v2_1/append.go index b1517b73106..9c8821e132d 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/append.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/append.go @@ -64,7 +64,11 @@ func appendStruct(vOld, vNew reflect.Value) reflect.Value { case reflect.Slice: vfRes.Set(reflect.AppendSlice(vfOld, vfNew)) default: - vfRes.Set(vfNew) + if vfNew.Kind() == reflect.Ptr && vfNew.IsNil() { + vfRes.Set(vfOld) + } else { + vfRes.Set(vfNew) + } } } diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/url.go b/vendor/github.com/coreos/ignition/config/v2_1/types/url.go index 0fdc4a170ef..648328acb17 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/url.go +++ b/vendor/github.com/coreos/ignition/config/v2_1/types/url.go @@ -32,7 +32,14 @@ func validateURL(s string) error { } switch u.Scheme { - case "http", "https", "oem", "tftp", "s3": + case "http", "https", "oem", "tftp": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } return nil case "data": if _, err := dataurl.DecodeString(s); err != nil { 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 index 2e90ff6d07b..11148fc0824 100644 --- a/vendor/github.com/coreos/ignition/config/v2_2/types/url.go +++ b/vendor/github.com/coreos/ignition/config/v2_2/types/url.go @@ -33,7 +33,14 @@ func validateURL(s string) error { } switch u.Scheme { - case "http", "https", "oem", "tftp", "s3": + case "http", "https", "oem", "tftp": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } return nil case "data": if _, err := dataurl.DecodeString(s); err != nil { diff --git a/vendor/github.com/coreos/ignition/config/v2_4/types/ca.go b/vendor/github.com/coreos/ignition/config/v2_4/types/ca.go new file mode 100644 index 00000000000..5a1f7663bc5 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4/types/ca.go @@ -0,0 +1,58 @@ +// Copyright 2018 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "net/url" + + "github.com/coreos/ignition/config/shared/errors" + "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{} +} + +func (c CaReference) ValidateHTTPHeaders() report.Report { + r := report.Report{} + + if len(c.HTTPHeaders) < 1 { + return r + } + + u, err := url.Parse(c.Source) + if err != nil { + r.Add(report.Entry{ + Message: errors.ErrInvalidUrl.Error(), + Kind: report.EntryError, + }) + return r + } + + switch u.Scheme { + case "http", "https": + default: + r.Add(report.Entry{ + Message: errors.ErrUnsupportedSchemeForHTTPHeaders.Error(), + Kind: report.EntryError, + }) + } + + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_4/types/config.go b/vendor/github.com/coreos/ignition/config/v2_4/types/config.go new file mode 100644 index 00000000000..c0e028fc721 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_4/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: 4, + } +) + +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_3_experimental/types/directory.go b/vendor/github.com/coreos/ignition/config/v2_4/types/directory.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/directory.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/directory.go diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_4/types/disk.go similarity index 90% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/disk.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/disk.go index ebffc2cd674..1430b0fde01 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/disk.go +++ b/vendor/github.com/coreos/ignition/config/v2_4/types/disk.go @@ -59,6 +59,12 @@ func (n Disk) ValidatePartitions() report.Report { Kind: report.EntryError, }) } + if n.partitionsUnitsMismatch() { + r.Add(report.Entry{ + Message: errors.ErrPartitionsUnitsMismatch.Error(), + Kind: report.EntryError, + }) + } // Disks which have no errors at this point will likely succeed in sgdisk return r } @@ -142,3 +148,17 @@ func (n Disk) partitionsMixZeroesAndNonexistence() bool { } return hasZero && hasShouldNotExist } + +func (n Disk) partitionsUnitsMismatch() bool { + partsInMb := false + partsNotInMb := false + for _, p := range n.Partitions { + if p.Size != nil || p.Start != nil { + partsNotInMb = true + } + if p.SizeMiB != nil || p.StartMiB != nil { + partsInMb = true + } + } + return partsInMb && partsNotInMb +} diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/file.go b/vendor/github.com/coreos/ignition/config/v2_4/types/file.go similarity index 78% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/file.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/file.go index 1897dc42c80..d5ca8d18e68 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/file.go +++ b/vendor/github.com/coreos/ignition/config/v2_4/types/file.go @@ -16,6 +16,7 @@ package types import ( "fmt" + "net/url" "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" @@ -69,3 +70,31 @@ func (fc FileContents) ValidateSource() report.Report { } return r } + +func (fc FileContents) ValidateHTTPHeaders() report.Report { + r := report.Report{} + + if len(fc.HTTPHeaders) < 1 { + return r + } + + u, err := url.Parse(fc.Source) + if err != nil { + r.Add(report.Entry{ + Message: errors.ErrInvalidUrl.Error(), + Kind: report.EntryError, + }) + return r + } + + switch u.Scheme { + case "http", "https": + default: + r.Add(report.Entry{ + Message: errors.ErrUnsupportedSchemeForHTTPHeaders.Error(), + Kind: report.EntryError, + }) + } + + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_4/types/filesystem.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/filesystem.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/filesystem.go diff --git a/vendor/github.com/coreos/ignition/config/v2_2/types/link.go b/vendor/github.com/coreos/ignition/config/v2_4/types/headers.go similarity index 56% rename from vendor/github.com/coreos/ignition/config/v2_2/types/link.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/headers.go index f0284425282..8dd25ffd96e 100644 --- a/vendor/github.com/coreos/ignition/config/v2_2/types/link.go +++ b/vendor/github.com/coreos/ignition/config/v2_4/types/headers.go @@ -1,4 +1,4 @@ -// Copyright 2017 CoreOS, Inc. +// Copyright 2020 Red Hat, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,19 +15,33 @@ package types import ( + "fmt" + + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -func (s LinkEmbedded1) ValidateTarget() report.Report { +func (h HTTPHeaders) Validate() report.Report { r := report.Report{} - if !s.Hard { - err := validatePath(s.Target) - if err != nil { + found := make(map[string]struct{}) + for _, header := range h { + // Header name can't be empty + if header.Name == "" { + r.Add(report.Entry{ + Message: errors.ErrEmptyHTTPHeaderName.Error(), + Kind: report.EntryError, + }) + continue + } + // Header names must be unique + if _, ok := found[header.Name]; ok { r.Add(report.Entry{ - Message: err.Error(), + Message: fmt.Sprintf("Found duplicate HTTP header: %q", header.Name), Kind: report.EntryError, }) + continue } + found[header.Name] = struct{}{} } return r } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_4/types/ignition.go similarity index 75% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ignition.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/ignition.go index bddf4958338..de7c2027571 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ignition.go +++ b/vendor/github.com/coreos/ignition/config/v2_4/types/ignition.go @@ -15,6 +15,8 @@ package types import ( + "net/url" + "github.com/coreos/go-semver/semver" "github.com/coreos/ignition/config/shared/errors" @@ -33,6 +35,34 @@ func (c ConfigReference) ValidateSource() report.Report { return r } +func (c ConfigReference) ValidateHTTPHeaders() report.Report { + r := report.Report{} + + if len(c.HTTPHeaders) < 1 { + return r + } + + u, err := url.Parse(c.Source) + if err != nil { + r.Add(report.Entry{ + Message: errors.ErrInvalidUrl.Error(), + Kind: report.EntryError, + }) + return r + } + + switch u.Scheme { + case "http", "https": + default: + r.Add(report.Entry{ + Message: errors.ErrUnsupportedSchemeForHTTPHeaders.Error(), + Kind: report.EntryError, + }) + } + + return r +} + func (v Ignition) Semver() (*semver.Version, error) { return semver.NewVersion(v.Version) } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/mode.go b/vendor/github.com/coreos/ignition/config/v2_4/types/mode.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/mode.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/mode.go diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/node.go b/vendor/github.com/coreos/ignition/config/v2_4/types/node.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/node.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/node.go diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_4/types/partition.go similarity index 77% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/partition.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/partition.go index 4e962b6391a..dbe38adcbca 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/partition.go +++ b/vendor/github.com/coreos/ignition/config/v2_4/types/partition.go @@ -28,9 +28,33 @@ const ( ) func (p Partition) Validate() report.Report { + r := report.Report{} + if (p.Start != nil || p.Size != nil) && (p.StartMiB != nil || p.SizeMiB != nil) { + r.Add(report.Entry{ + Message: errors.ErrPartitionsUnitsMismatch.Error(), + Kind: report.EntryError, + }) + } if p.ShouldExist != nil && !*p.ShouldExist && (p.Label != nil || p.TypeGUID != "" || p.GUID != "" || p.Start != nil || p.Size != nil) { - return report.ReportFromError(errors.ErrShouldNotExistWithOthers, report.EntryError) + r.Add(report.Entry{ + Message: errors.ErrShouldNotExistWithOthers.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (p Partition) ValidateSize() report.Report { + if p.Size != nil { + return report.ReportFromError(errors.ErrSizeDeprecated, report.EntryDeprecated) + } + return report.Report{} +} + +func (p Partition) ValidateStart() report.Report { + if p.Start != nil { + return report.ReportFromError(errors.ErrStartDeprecated, report.EntryDeprecated) } return report.Report{} } diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_4/types/passwd.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/passwd.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/passwd.go diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/path.go b/vendor/github.com/coreos/ignition/config/v2_4/types/path.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/path.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/path.go diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_4/types/raid.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/raid.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/raid.go diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/schema.go b/vendor/github.com/coreos/ignition/config/v2_4/types/schema.go similarity index 83% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/schema.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/schema.go index 73424c546ef..4bf7ec84174 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/schema.go +++ b/vendor/github.com/coreos/ignition/config/v2_4/types/schema.go @@ -3,7 +3,8 @@ package types // generated by "schematyper --package=types schema/ignition.json -o internal/config/types/schema.go --root-type=Config" -- DO NOT EDIT type CaReference struct { - Source string `json:"source,omitempty"` + HTTPHeaders HTTPHeaders `json:"httpHeaders,omitempty"` + Source string `json:"source"` Verification Verification `json:"verification,omitempty"` } @@ -16,7 +17,8 @@ type Config struct { } type ConfigReference struct { - Source string `json:"source,omitempty"` + HTTPHeaders HTTPHeaders `json:"httpHeaders,omitempty"` + Source string `json:"source"` Verification Verification `json:"verification,omitempty"` } @@ -39,7 +41,7 @@ type DirectoryEmbedded1 struct { } type Disk struct { - Device string `json:"device,omitempty"` + Device string `json:"device"` Partitions []Partition `json:"partitions,omitempty"` WipeTable bool `json:"wipeTable,omitempty"` } @@ -51,6 +53,7 @@ type File struct { type FileContents struct { Compression string `json:"compression,omitempty"` + HTTPHeaders HTTPHeaders `json:"httpHeaders,omitempty"` Source string `json:"source,omitempty"` Verification Verification `json:"verification,omitempty"` } @@ -69,8 +72,16 @@ type Filesystem struct { type Group string +type HTTPHeader struct { + Name string `json:"name"` + Value string `json:"value"` +} + +type HTTPHeaders []HTTPHeader + type Ignition struct { Config IgnitionConfig `json:"config,omitempty"` + Proxy Proxy `json:"proxy,omitempty"` Security Security `json:"security,omitempty"` Timeouts Timeouts `json:"timeouts,omitempty"` Version string `json:"version,omitempty"` @@ -88,13 +99,13 @@ type Link struct { type LinkEmbedded1 struct { Hard bool `json:"hard,omitempty"` - Target string `json:"target,omitempty"` + Target string `json:"target"` } type Mount struct { Create *Create `json:"create,omitempty"` - Device string `json:"device,omitempty"` - Format string `json:"format,omitempty"` + Device string `json:"device"` + Format string `json:"format"` Label *string `json:"label,omitempty"` Options []MountOption `json:"options,omitempty"` UUID *string `json:"uuid,omitempty"` @@ -109,20 +120,22 @@ type Networkd struct { type NetworkdDropin struct { Contents string `json:"contents,omitempty"` - Name string `json:"name,omitempty"` + Name string `json:"name"` } type Networkdunit struct { Contents string `json:"contents,omitempty"` Dropins []NetworkdDropin `json:"dropins,omitempty"` - Name string `json:"name,omitempty"` + Name string `json:"name"` } +type NoProxyItem string + type Node struct { - Filesystem string `json:"filesystem,omitempty"` + Filesystem string `json:"filesystem"` Group *NodeGroup `json:"group,omitempty"` Overwrite *bool `json:"overwrite,omitempty"` - Path string `json:"path,omitempty"` + Path string `json:"path"` User *NodeUser `json:"user,omitempty"` } @@ -142,7 +155,9 @@ type Partition struct { Number int `json:"number,omitempty"` ShouldExist *bool `json:"shouldExist,omitempty"` Size *int `json:"size,omitempty"` + SizeMiB *int `json:"sizeMiB,omitempty"` Start *int `json:"start,omitempty"` + StartMiB *int `json:"startMiB,omitempty"` TypeGUID string `json:"typeGuid,omitempty"` WipePartitionEntry bool `json:"wipePartitionEntry,omitempty"` } @@ -154,7 +169,7 @@ type Passwd struct { type PasswdGroup struct { Gid *int `json:"gid,omitempty"` - Name string `json:"name,omitempty"` + Name string `json:"name"` PasswordHash string `json:"passwordHash,omitempty"` System bool `json:"system,omitempty"` } @@ -164,7 +179,7 @@ type PasswdUser struct { Gecos string `json:"gecos,omitempty"` Groups []Group `json:"groups,omitempty"` HomeDir string `json:"homeDir,omitempty"` - Name string `json:"name,omitempty"` + Name string `json:"name"` NoCreateHome bool `json:"noCreateHome,omitempty"` NoLogInit bool `json:"noLogInit,omitempty"` NoUserGroup bool `json:"noUserGroup,omitempty"` @@ -176,10 +191,16 @@ type PasswdUser struct { UID *int `json:"uid,omitempty"` } +type Proxy struct { + HTTPProxy string `json:"httpProxy,omitempty"` + HTTPSProxy string `json:"httpsProxy,omitempty"` + NoProxy []NoProxyItem `json:"noProxy,omitempty"` +} + type Raid struct { - Devices []Device `json:"devices,omitempty"` - Level string `json:"level,omitempty"` - Name string `json:"name,omitempty"` + Devices []Device `json:"devices"` + Level string `json:"level"` + Name string `json:"name"` Options []RaidOption `json:"options,omitempty"` Spares int `json:"spares,omitempty"` } @@ -207,7 +228,7 @@ type Systemd struct { type SystemdDropin struct { Contents string `json:"contents,omitempty"` - Name string `json:"name,omitempty"` + Name string `json:"name"` } type TLS struct { @@ -225,7 +246,7 @@ type Unit struct { Enable bool `json:"enable,omitempty"` Enabled *bool `json:"enabled,omitempty"` Mask bool `json:"mask,omitempty"` - Name string `json:"name,omitempty"` + Name string `json:"name"` } type Usercreate struct { diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_4/types/unit.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/unit.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/unit.go diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/url.go b/vendor/github.com/coreos/ignition/config/v2_4/types/url.go similarity index 84% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/url.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/url.go index 2e90ff6d07b..11148fc0824 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/url.go +++ b/vendor/github.com/coreos/ignition/config/v2_4/types/url.go @@ -33,7 +33,14 @@ func validateURL(s string) error { } switch u.Scheme { - case "http", "https", "oem", "tftp", "s3": + case "http", "https", "oem", "tftp": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } return nil case "data": if _, err := dataurl.DecodeString(s); err != nil { diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_4/types/verification.go similarity index 100% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/verification.go rename to vendor/github.com/coreos/ignition/config/v2_4/types/verification.go diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/ca.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/ca.go new file mode 100644 index 00000000000..5a1f7663bc5 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/ca.go @@ -0,0 +1,58 @@ +// Copyright 2018 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "net/url" + + "github.com/coreos/ignition/config/shared/errors" + "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{} +} + +func (c CaReference) ValidateHTTPHeaders() report.Report { + r := report.Report{} + + if len(c.HTTPHeaders) < 1 { + return r + } + + u, err := url.Parse(c.Source) + if err != nil { + r.Add(report.Entry{ + Message: errors.ErrInvalidUrl.Error(), + Kind: report.EntryError, + }) + return r + } + + switch u.Scheme { + case "http", "https": + default: + r.Add(report.Entry{ + Message: errors.ErrUnsupportedSchemeForHTTPHeaders.Error(), + Kind: report.EntryError, + }) + } + + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/config.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/config.go similarity index 99% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/config.go rename to vendor/github.com/coreos/ignition/config/v2_5_experimental/types/config.go index cfef0ed9dac..601330d2ce1 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/config.go +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/config.go @@ -25,7 +25,7 @@ import ( var ( MaxVersion = semver.Version{ Major: 2, - Minor: 3, + Minor: 5, PreRelease: "experimental", } ) diff --git a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/link.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/directory.go similarity index 66% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/link.go rename to vendor/github.com/coreos/ignition/config/v2_5_experimental/types/directory.go index f0284425282..9fdc732a644 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/link.go +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/directory.go @@ -15,19 +15,23 @@ package types import ( + "github.com/coreos/ignition/config/shared/errors" "github.com/coreos/ignition/config/validate/report" ) -func (s LinkEmbedded1) ValidateTarget() report.Report { +func (d Directory) ValidateMode() report.Report { r := report.Report{} - if !s.Hard { - err := validatePath(s.Target) - if err != nil { - r.Add(report.Entry{ - Message: err.Error(), - Kind: report.EntryError, - }) - } + if err := validateMode(d.Mode); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + if d.Mode == nil { + r.Add(report.Entry{ + Message: errors.ErrPermissionsUnset.Error(), + Kind: report.EntryWarning, + }) } return r } diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/disk.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/disk.go new file mode 100644 index 00000000000..1430b0fde01 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/disk.go @@ -0,0 +1,164 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (n Disk) Validate() report.Report { + return report.Report{} +} + +func (n Disk) ValidateDevice() report.Report { + if len(n.Device) == 0 { + return report.ReportFromError(errors.ErrDiskDeviceRequired, report.EntryError) + } + if err := validatePath(string(n.Device)); err != nil { + return report.ReportFromError(err, report.EntryError) + } + return report.Report{} +} + +func (n Disk) ValidatePartitions() report.Report { + r := report.Report{} + if n.partitionNumbersCollide() { + r.Add(report.Entry{ + Message: errors.ErrPartitionNumbersCollide.Error(), + Kind: report.EntryError, + }) + } + if n.partitionsOverlap() { + r.Add(report.Entry{ + Message: errors.ErrPartitionsOverlap.Error(), + Kind: report.EntryError, + }) + } + if n.partitionsMisaligned() { + r.Add(report.Entry{ + Message: errors.ErrPartitionsMisaligned.Error(), + Kind: report.EntryError, + }) + } + if n.partitionsMixZeroesAndNonexistence() { + r.Add(report.Entry{ + Message: errors.ErrZeroesWithShouldNotExist.Error(), + Kind: report.EntryError, + }) + } + if n.partitionsUnitsMismatch() { + r.Add(report.Entry{ + Message: errors.ErrPartitionsUnitsMismatch.Error(), + Kind: report.EntryError, + }) + } + // Disks which have no errors at this point will likely succeed in sgdisk + return r +} + +// partitionNumbersCollide returns true if partition numbers in n.Partitions are not unique. +func (n Disk) partitionNumbersCollide() bool { + m := map[int][]Partition{} + for _, p := range n.Partitions { + if p.Number != 0 { + // a number of 0 means next available number, multiple devices can specify this + m[p.Number] = append(m[p.Number], p) + } + } + for _, n := range m { + if len(n) > 1 { + // TODO(vc): return information describing the collision for logging + return true + } + } + return false +} + +// end returns the last sector of a partition. Only used by partitionsOverlap. Requires non-nil Start and Size. +func (p Partition) end() int { + if *p.Size == 0 { + // a size of 0 means "fill available", just return the start as the end for those. + return *p.Start + } + return *p.Start + *p.Size - 1 +} + +// partitionsOverlap returns true if any explicitly dimensioned partitions overlap +func (n Disk) partitionsOverlap() bool { + for _, p := range n.Partitions { + // Starts of 0 are placed by sgdisk into the "largest available block" at that time. + // We aren't going to check those for overlap since we don't have the disk geometry. + if p.Start == nil || p.Size == nil || *p.Start == 0 { + continue + } + + for _, o := range n.Partitions { + if o.Start == nil || o.Size == nil || p == o || *o.Start == 0 { + continue + } + + // is p.Start within o? + if *p.Start >= *o.Start && *p.Start <= o.end() { + return true + } + + // is p.end() within o? + if p.end() >= *o.Start && p.end() <= o.end() { + return true + } + + // do p.Start and p.end() straddle o? + if *p.Start < *o.Start && p.end() > o.end() { + return true + } + } + } + return false +} + +// partitionsMisaligned returns true if any of the partitions don't start on a 2048-sector (1MiB) boundary. +func (n Disk) partitionsMisaligned() bool { + for _, p := range n.Partitions { + if p.Start != nil && ((*p.Start & (2048 - 1)) != 0) { + return true + } + } + return false +} + +func (n Disk) partitionsMixZeroesAndNonexistence() bool { + hasZero := false + hasShouldNotExist := false + for _, p := range n.Partitions { + hasShouldNotExist = hasShouldNotExist || (p.ShouldExist != nil && !*p.ShouldExist) + hasZero = hasZero || (p.Number == 0) + } + return hasZero && hasShouldNotExist +} + +func (n Disk) partitionsUnitsMismatch() bool { + partsInMb := false + partsNotInMb := false + for _, p := range n.Partitions { + if p.Size != nil || p.Start != nil { + partsNotInMb = true + } + if p.SizeMiB != nil || p.StartMiB != nil { + partsInMb = true + } + } + return partsInMb && partsNotInMb +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/file.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/file.go new file mode 100644 index 00000000000..d5ca8d18e68 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/file.go @@ -0,0 +1,100 @@ +// 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" + "net/url" + + "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: fmt.Sprintf("invalid url %q: %v", fc.Source, err), + Kind: report.EntryError, + }) + } + return r +} + +func (fc FileContents) ValidateHTTPHeaders() report.Report { + r := report.Report{} + + if len(fc.HTTPHeaders) < 1 { + return r + } + + u, err := url.Parse(fc.Source) + if err != nil { + r.Add(report.Entry{ + Message: errors.ErrInvalidUrl.Error(), + Kind: report.EntryError, + }) + return r + } + + switch u.Scheme { + case "http", "https": + default: + r.Add(report.Entry{ + Message: errors.ErrUnsupportedSchemeForHTTPHeaders.Error(), + Kind: report.EntryError, + }) + } + + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/filesystem.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/filesystem.go new file mode 100644 index 00000000000..2e847da69d0 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/filesystem.go @@ -0,0 +1,146 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + + "github.com/coreos/ignition/config/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: fmt.Sprintf("filesystem %q: path not absolute", f.Name), + Kind: report.EntryError, + }) + } + return r +} + +func (m Mount) Validate() report.Report { + r := report.Report{} + switch m.Format { + case "ext4", "btrfs", "xfs", "swap", "vfat": + default: + r.Add(report.Entry{ + Message: 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_5_experimental/types/headers.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/headers.go new file mode 100644 index 00000000000..8dd25ffd96e --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/headers.go @@ -0,0 +1,47 @@ +// Copyright 2020 Red Hat, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (h HTTPHeaders) Validate() report.Report { + r := report.Report{} + found := make(map[string]struct{}) + for _, header := range h { + // Header name can't be empty + if header.Name == "" { + r.Add(report.Entry{ + Message: errors.ErrEmptyHTTPHeaderName.Error(), + Kind: report.EntryError, + }) + continue + } + // Header names must be unique + if _, ok := found[header.Name]; ok { + r.Add(report.Entry{ + Message: fmt.Sprintf("Found duplicate HTTP header: %q", header.Name), + Kind: report.EntryError, + }) + continue + } + found[header.Name] = struct{}{} + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/ignition.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/ignition.go new file mode 100644 index 00000000000..de7c2027571 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/ignition.go @@ -0,0 +1,82 @@ +// 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 ( + "net/url" + + "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 (c ConfigReference) ValidateHTTPHeaders() report.Report { + r := report.Report{} + + if len(c.HTTPHeaders) < 1 { + return r + } + + u, err := url.Parse(c.Source) + if err != nil { + r.Add(report.Entry{ + Message: errors.ErrInvalidUrl.Error(), + Kind: report.EntryError, + }) + return r + } + + switch u.Scheme { + case "http", "https": + default: + r.Add(report.Entry{ + Message: errors.ErrUnsupportedSchemeForHTTPHeaders.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_3_experimental/types/ca.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/mode.go similarity index 69% rename from vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ca.go rename to vendor/github.com/coreos/ignition/config/v2_5_experimental/types/mode.go index 7440e1e2f3b..d06045d6753 100644 --- a/vendor/github.com/coreos/ignition/config/v2_3_experimental/types/ca.go +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/mode.go @@ -1,4 +1,4 @@ -// Copyright 2018 CoreOS, Inc. +// Copyright 2017 CoreOS, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -15,13 +15,12 @@ package types import ( - "github.com/coreos/ignition/config/validate/report" + "github.com/coreos/ignition/config/shared/errors" ) -func (c CaReference) ValidateSource() report.Report { - err := validateURL(c.Source) - if err != nil { - return report.ReportFromError(err, report.EntryError) +func validateMode(m *int) error { + if m != nil && (*m < 0 || *m > 07777) { + return errors.ErrFileIllegalMode } - return report.Report{} + return nil } diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/node.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/node.go new file mode 100644 index 00000000000..50badfdfb92 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/node.go @@ -0,0 +1,73 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "path/filepath" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (n Node) ValidateFilesystem() report.Report { + r := report.Report{} + if n.Filesystem == "" { + r.Add(report.Entry{ + Message: errors.ErrNoFilesystem.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (n Node) ValidatePath() report.Report { + r := report.Report{} + if err := validatePath(n.Path); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (n Node) Depth() int { + count := 0 + for p := filepath.Clean(string(n.Path)); p != "/"; count++ { + p = filepath.Dir(p) + } + return count +} + +func (nu NodeUser) Validate() report.Report { + r := report.Report{} + if nu.ID != nil && nu.Name != "" { + r.Add(report.Entry{ + Message: errors.ErrBothIDAndNameSet.Error(), + Kind: report.EntryError, + }) + } + return r +} +func (ng NodeGroup) Validate() report.Report { + r := report.Report{} + if ng.ID != nil && ng.Name != "" { + r.Add(report.Entry{ + Message: errors.ErrBothIDAndNameSet.Error(), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/partition.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/partition.go new file mode 100644 index 00000000000..dbe38adcbca --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/partition.go @@ -0,0 +1,112 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "regexp" + "strings" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +const ( + guidRegexStr = "^(|[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$" +) + +func (p Partition) Validate() report.Report { + r := report.Report{} + if (p.Start != nil || p.Size != nil) && (p.StartMiB != nil || p.SizeMiB != nil) { + r.Add(report.Entry{ + Message: errors.ErrPartitionsUnitsMismatch.Error(), + Kind: report.EntryError, + }) + } + if p.ShouldExist != nil && !*p.ShouldExist && + (p.Label != nil || p.TypeGUID != "" || p.GUID != "" || p.Start != nil || p.Size != nil) { + r.Add(report.Entry{ + Message: errors.ErrShouldNotExistWithOthers.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (p Partition) ValidateSize() report.Report { + if p.Size != nil { + return report.ReportFromError(errors.ErrSizeDeprecated, report.EntryDeprecated) + } + return report.Report{} +} + +func (p Partition) ValidateStart() report.Report { + if p.Start != nil { + return report.ReportFromError(errors.ErrStartDeprecated, report.EntryDeprecated) + } + return report.Report{} +} + +func (p Partition) ValidateLabel() report.Report { + r := report.Report{} + if p.Label == nil { + return r + } + // http://en.wikipedia.org/wiki/GUID_Partition_Table#Partition_entries: + // 56 (0x38) 72 bytes Partition name (36 UTF-16LE code units) + + // XXX(vc): note GPT calls it a name, we're using label for consistency + // with udev naming /dev/disk/by-partlabel/*. + if len(*p.Label) > 36 { + r.Add(report.Entry{ + Message: errors.ErrLabelTooLong.Error(), + Kind: report.EntryError, + }) + } + + // sgdisk uses colons for delimitting compound arguments and does not allow escaping them. + if strings.Contains(*p.Label, ":") { + r.Add(report.Entry{ + Message: errors.ErrLabelContainsColon.Error(), + Kind: report.EntryWarning, + }) + } + return r +} + +func (p Partition) ValidateTypeGUID() report.Report { + return validateGUID(p.TypeGUID) +} + +func (p Partition) ValidateGUID() report.Report { + return validateGUID(p.GUID) +} + +func validateGUID(guid string) report.Report { + r := report.Report{} + ok, err := regexp.MatchString(guidRegexStr, guid) + if err != nil { + r.Add(report.Entry{ + Message: fmt.Sprintf("error matching guid regexp: %v", err), + Kind: report.EntryError, + }) + } else if !ok { + r.Add(report.Entry{ + Message: errors.ErrDoesntMatchGUIDRegex.Error(), + Kind: report.EntryError, + }) + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/passwd.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/passwd.go new file mode 100644 index 00000000000..10508c56c06 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/passwd.go @@ -0,0 +1,67 @@ +// Copyright 2017 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (p PasswdUser) Validate() report.Report { + r := report.Report{} + if p.Create != nil { + r.Add(report.Entry{ + Message: errors.ErrPasswdCreateDeprecated.Error(), + Kind: report.EntryWarning, + }) + addErr := func(err error) { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + if p.Gecos != "" { + addErr(errors.ErrPasswdCreateAndGecos) + } + if len(p.Groups) > 0 { + addErr(errors.ErrPasswdCreateAndGroups) + } + if p.HomeDir != "" { + addErr(errors.ErrPasswdCreateAndHomeDir) + } + if p.NoCreateHome { + addErr(errors.ErrPasswdCreateAndNoCreateHome) + } + if p.NoLogInit { + addErr(errors.ErrPasswdCreateAndNoLogInit) + } + if p.NoUserGroup { + addErr(errors.ErrPasswdCreateAndNoUserGroup) + } + if p.PrimaryGroup != "" { + addErr(errors.ErrPasswdCreateAndPrimaryGroup) + } + if p.Shell != "" { + addErr(errors.ErrPasswdCreateAndShell) + } + if p.System { + addErr(errors.ErrPasswdCreateAndSystem) + } + if p.UID != nil { + addErr(errors.ErrPasswdCreateAndUID) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_1/types/link.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/path.go similarity index 64% rename from vendor/github.com/coreos/ignition/config/v2_1/types/link.go rename to vendor/github.com/coreos/ignition/config/v2_5_experimental/types/path.go index f0284425282..780607c31ab 100644 --- a/vendor/github.com/coreos/ignition/config/v2_1/types/link.go +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/path.go @@ -1,4 +1,4 @@ -// Copyright 2017 CoreOS, Inc. +// 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. @@ -15,19 +15,14 @@ package types import ( - "github.com/coreos/ignition/config/validate/report" + "path" + + "github.com/coreos/ignition/config/shared/errors" ) -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, - }) - } +func validatePath(p string) error { + if !path.IsAbs(p) { + return errors.ErrPathRelative } - return r + return nil } diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/raid.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/raid.go new file mode 100644 index 00000000000..3aceaa9faa1 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/raid.go @@ -0,0 +1,57 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +func (n Raid) ValidateLevel() report.Report { + r := report.Report{} + switch n.Level { + case "linear", "raid0", "0", "stripe": + if n.Spares != 0 { + r.Add(report.Entry{ + Message: errors.ErrSparesUnsupportedForLevel.Error(), + Kind: report.EntryError, + }) + } + case "raid1", "1", "mirror": + case "raid4", "4": + case "raid5", "5": + case "raid6", "6": + case "raid10", "10": + default: + r.Add(report.Entry{ + Message: errors.ErrUnrecognizedRaidLevel.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (n Raid) ValidateDevices() report.Report { + r := report.Report{} + for _, d := range n.Devices { + if err := validatePath(string(d)); err != nil { + r.Add(report.Entry{ + Message: errors.ErrPathRelative.Error(), + Kind: report.EntryError, + }) + } + } + return r +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/schema.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/schema.go new file mode 100644 index 00000000000..4bf7ec84174 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/schema.go @@ -0,0 +1,269 @@ +package types + +// generated by "schematyper --package=types schema/ignition.json -o internal/config/types/schema.go --root-type=Config" -- DO NOT EDIT + +type CaReference struct { + HTTPHeaders HTTPHeaders `json:"httpHeaders,omitempty"` + Source string `json:"source"` + Verification Verification `json:"verification,omitempty"` +} + +type Config struct { + Ignition Ignition `json:"ignition"` + Networkd Networkd `json:"networkd,omitempty"` + Passwd Passwd `json:"passwd,omitempty"` + Storage Storage `json:"storage,omitempty"` + Systemd Systemd `json:"systemd,omitempty"` +} + +type ConfigReference struct { + HTTPHeaders HTTPHeaders `json:"httpHeaders,omitempty"` + Source string `json:"source"` + Verification Verification `json:"verification,omitempty"` +} + +type Create struct { + Force bool `json:"force,omitempty"` + Options []CreateOption `json:"options,omitempty"` +} + +type CreateOption string + +type Device string + +type Directory struct { + Node + DirectoryEmbedded1 +} + +type DirectoryEmbedded1 struct { + Mode *int `json:"mode,omitempty"` +} + +type Disk struct { + Device string `json:"device"` + Partitions []Partition `json:"partitions,omitempty"` + WipeTable bool `json:"wipeTable,omitempty"` +} + +type File struct { + Node + FileEmbedded1 +} + +type FileContents struct { + Compression string `json:"compression,omitempty"` + HTTPHeaders HTTPHeaders `json:"httpHeaders,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 HTTPHeader struct { + Name string `json:"name"` + Value string `json:"value"` +} + +type HTTPHeaders []HTTPHeader + +type Ignition struct { + Config IgnitionConfig `json:"config,omitempty"` + Proxy Proxy `json:"proxy,omitempty"` + Security Security `json:"security,omitempty"` + Timeouts Timeouts `json:"timeouts,omitempty"` + Version string `json:"version,omitempty"` +} + +type IgnitionConfig struct { + Append []ConfigReference `json:"append,omitempty"` + Replace *ConfigReference `json:"replace,omitempty"` +} + +type Link struct { + Node + LinkEmbedded1 +} + +type LinkEmbedded1 struct { + Hard bool `json:"hard,omitempty"` + Target string `json:"target"` +} + +type Mount struct { + Create *Create `json:"create,omitempty"` + Device string `json:"device"` + Format string `json:"format"` + Label *string `json:"label,omitempty"` + Options []MountOption `json:"options,omitempty"` + UUID *string `json:"uuid,omitempty"` + WipeFilesystem bool `json:"wipeFilesystem,omitempty"` +} + +type MountOption string + +type Networkd struct { + Units []Networkdunit `json:"units,omitempty"` +} + +type NetworkdDropin struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name"` +} + +type Networkdunit struct { + Contents string `json:"contents,omitempty"` + Dropins []NetworkdDropin `json:"dropins,omitempty"` + Name string `json:"name"` +} + +type NoProxyItem string + +type Node struct { + Filesystem string `json:"filesystem"` + Group *NodeGroup `json:"group,omitempty"` + Overwrite *bool `json:"overwrite,omitempty"` + Path string `json:"path"` + User *NodeUser `json:"user,omitempty"` +} + +type NodeGroup struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type NodeUser struct { + ID *int `json:"id,omitempty"` + Name string `json:"name,omitempty"` +} + +type Partition struct { + GUID string `json:"guid,omitempty"` + Label *string `json:"label,omitempty"` + Number int `json:"number,omitempty"` + ShouldExist *bool `json:"shouldExist,omitempty"` + Size *int `json:"size,omitempty"` + SizeMiB *int `json:"sizeMiB,omitempty"` + Start *int `json:"start,omitempty"` + StartMiB *int `json:"startMiB,omitempty"` + TypeGUID string `json:"typeGuid,omitempty"` + WipePartitionEntry bool `json:"wipePartitionEntry,omitempty"` +} + +type Passwd struct { + Groups []PasswdGroup `json:"groups,omitempty"` + Users []PasswdUser `json:"users,omitempty"` +} + +type PasswdGroup struct { + Gid *int `json:"gid,omitempty"` + Name string `json:"name"` + PasswordHash string `json:"passwordHash,omitempty"` + System bool `json:"system,omitempty"` +} + +type PasswdUser struct { + Create *Usercreate `json:"create,omitempty"` + Gecos string `json:"gecos,omitempty"` + Groups []Group `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + Name string `json:"name"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PasswordHash *string `json:"passwordHash,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + SSHAuthorizedKeys []SSHAuthorizedKey `json:"sshAuthorizedKeys,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type Proxy struct { + HTTPProxy string `json:"httpProxy,omitempty"` + HTTPSProxy string `json:"httpsProxy,omitempty"` + NoProxy []NoProxyItem `json:"noProxy,omitempty"` +} + +type Raid struct { + Devices []Device `json:"devices"` + Level string `json:"level"` + Name string `json:"name"` + Options []RaidOption `json:"options,omitempty"` + Spares int `json:"spares,omitempty"` +} + +type RaidOption string + +type SSHAuthorizedKey string + +type Security struct { + TLS TLS `json:"tls,omitempty"` +} + +type Storage struct { + Directories []Directory `json:"directories,omitempty"` + Disks []Disk `json:"disks,omitempty"` + Files []File `json:"files,omitempty"` + Filesystems []Filesystem `json:"filesystems,omitempty"` + Links []Link `json:"links,omitempty"` + Raid []Raid `json:"raid,omitempty"` +} + +type Systemd struct { + Units []Unit `json:"units,omitempty"` +} + +type SystemdDropin struct { + Contents string `json:"contents,omitempty"` + Name string `json:"name"` +} + +type TLS struct { + CertificateAuthorities []CaReference `json:"certificateAuthorities,omitempty"` +} + +type Timeouts struct { + HTTPResponseHeaders *int `json:"httpResponseHeaders,omitempty"` + HTTPTotal *int `json:"httpTotal,omitempty"` +} + +type Unit struct { + Contents string `json:"contents,omitempty"` + Dropins []SystemdDropin `json:"dropins,omitempty"` + Enable bool `json:"enable,omitempty"` + Enabled *bool `json:"enabled,omitempty"` + Mask bool `json:"mask,omitempty"` + Name string `json:"name"` +} + +type Usercreate struct { + Gecos string `json:"gecos,omitempty"` + Groups []UsercreateGroup `json:"groups,omitempty"` + HomeDir string `json:"homeDir,omitempty"` + NoCreateHome bool `json:"noCreateHome,omitempty"` + NoLogInit bool `json:"noLogInit,omitempty"` + NoUserGroup bool `json:"noUserGroup,omitempty"` + PrimaryGroup string `json:"primaryGroup,omitempty"` + Shell string `json:"shell,omitempty"` + System bool `json:"system,omitempty"` + UID *int `json:"uid,omitempty"` +} + +type UsercreateGroup string + +type Verification struct { + Hash *string `json:"hash,omitempty"` +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/unit.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/unit.go new file mode 100644 index 00000000000..70fe1179a45 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/unit.go @@ -0,0 +1,131 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "fmt" + "path" + "strings" + + "github.com/coreos/go-systemd/unit" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/shared/validations" + "github.com/coreos/ignition/config/validate/report" +) + +func (u Unit) ValidateContents() report.Report { + r := report.Report{} + opts, err := validateUnitContent(u.Contents) + if err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + isEnabled := u.Enable || (u.Enabled != nil && *u.Enabled) + r.Merge(validations.ValidateInstallSection(u.Name, isEnabled, u.Contents == "", opts)) + + return r +} + +func (u Unit) ValidateName() report.Report { + r := report.Report{} + switch path.Ext(u.Name) { + case ".service", ".socket", ".device", ".mount", ".automount", ".swap", ".target", ".path", ".timer", ".snapshot", ".slice", ".scope": + default: + r.Add(report.Entry{ + Message: errors.ErrInvalidSystemdExt.Error(), + Kind: report.EntryError, + }) + } + return r +} + +func (d SystemdDropin) Validate() report.Report { + r := report.Report{} + + if _, err := validateUnitContent(d.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + switch path.Ext(d.Name) { + case ".conf": + default: + r.Add(report.Entry{ + Message: errors.ErrInvalidSystemdDropinExt.Error(), + Kind: report.EntryError, + }) + } + + return r +} + +func (u Networkdunit) Validate() report.Report { + r := report.Report{} + + if _, err := validateUnitContent(u.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + switch path.Ext(u.Name) { + case ".link", ".netdev", ".network": + default: + r.Add(report.Entry{ + Message: errors.ErrInvalidNetworkdExt.Error(), + Kind: report.EntryError, + }) + } + + return r +} + +func (d NetworkdDropin) Validate() report.Report { + r := report.Report{} + + if _, err := validateUnitContent(d.Contents); err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + } + + switch path.Ext(d.Name) { + case ".conf": + default: + r.Add(report.Entry{ + Message: errors.ErrInvalidNetworkdDropinExt.Error(), + Kind: report.EntryError, + }) + } + + return r +} + +func validateUnitContent(content string) ([]*unit.UnitOption, error) { + c := strings.NewReader(content) + opts, err := unit.Deserialize(c) + if err != nil { + return nil, fmt.Errorf("invalid unit content: %s", err) + } + return opts, nil +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/url.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/url.go new file mode 100644 index 00000000000..11148fc0824 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/url.go @@ -0,0 +1,53 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "net/url" + + "github.com/vincent-petithory/dataurl" + + "github.com/coreos/ignition/config/shared/errors" +) + +func validateURL(s string) error { + // Empty url is valid, indicates an empty file + if s == "" { + return nil + } + u, err := url.Parse(s) + if err != nil { + return errors.ErrInvalidUrl + } + + switch u.Scheme { + case "http", "https", "oem", "tftp": + return nil + case "s3": + if v, ok := u.Query()["versionId"]; ok { + if len(v) == 0 || v[0] == "" { + return errors.ErrInvalidS3ObjectVersionId + } + } + return nil + case "data": + if _, err := dataurl.DecodeString(s); err != nil { + return err + } + return nil + default: + return errors.ErrInvalidScheme + } +} diff --git a/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/verification.go b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/verification.go new file mode 100644 index 00000000000..51e7d1550a3 --- /dev/null +++ b/vendor/github.com/coreos/ignition/config/v2_5_experimental/types/verification.go @@ -0,0 +1,77 @@ +// Copyright 2016 CoreOS, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package types + +import ( + "crypto" + "encoding/hex" + "strings" + + "github.com/coreos/ignition/config/shared/errors" + "github.com/coreos/ignition/config/validate/report" +) + +// HashParts will return the sum and function (in that order) of the hash stored +// in this Verification, or an error if there is an issue during parsing. +func (v Verification) HashParts() (string, string, error) { + if v.Hash == nil { + // The hash can be nil + return "", "", nil + } + parts := strings.SplitN(*v.Hash, "-", 2) + if len(parts) != 2 { + return "", "", errors.ErrHashMalformed + } + + return parts[0], parts[1], nil +} + +func (v Verification) Validate() report.Report { + r := report.Report{} + + if v.Hash == nil { + // The hash can be nil + return r + } + + function, sum, err := v.HashParts() + if err != nil { + r.Add(report.Entry{ + Message: err.Error(), + Kind: report.EntryError, + }) + return r + } + var hash crypto.Hash + switch function { + case "sha512": + hash = crypto.SHA512 + default: + r.Add(report.Entry{ + Message: errors.ErrHashUnrecognized.Error(), + Kind: report.EntryError, + }) + return r + } + + if len(sum) != hex.EncodedLen(hash.Size()) { + r.Add(report.Entry{ + Message: errors.ErrHashWrongSize.Error(), + Kind: report.EntryError, + }) + } + + return r +} diff --git a/vendor/github.com/gophercloud/gophercloud/errors.go b/vendor/github.com/gophercloud/gophercloud/errors.go index 0bcb3af7f00..eb899a4a08b 100644 --- a/vendor/github.com/gophercloud/gophercloud/errors.go +++ b/vendor/github.com/gophercloud/gophercloud/errors.go @@ -92,6 +92,23 @@ func (e ErrUnexpectedResponseCode) Error() string { return e.choseErrString() } +// GetStatusCode returns the actual status code of the error. +func (e ErrUnexpectedResponseCode) GetStatusCode() int { + return e.Actual +} + +// StatusCodeError is a convenience interface to easily allow access to the +// status code field of the various ErrDefault* types. +// +// By using this interface, you only have to make a single type cast of +// the returned error to err.(StatusCodeError) and then call GetStatusCode() +// instead of having a large switch statement checking for each of the +// ErrDefault* types. +type StatusCodeError interface { + Error() string + GetStatusCode() int +} + // ErrDefault400 is the default error type returned on a 400 HTTP response code. type ErrDefault400 struct { ErrUnexpectedResponseCode diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/client.go b/vendor/github.com/gophercloud/gophercloud/openstack/client.go index e77584157f8..0b21beef93d 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/client.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/client.go @@ -3,6 +3,7 @@ package openstack import ( "fmt" "reflect" + "strings" "github.com/gophercloud/gophercloud" tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens" @@ -432,7 +433,11 @@ func NewImageServiceV2(client *gophercloud.ProviderClient, eo gophercloud.Endpoi // load balancer service. func NewLoadBalancerV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { sc, err := initClientOpts(client, eo, "load-balancer") - sc.ResourceBase = sc.Endpoint + "v2.0/" + + // Fixes edge case having an OpenStack lb endpoint with trailing version number. + endpoint := strings.Replace(sc.Endpoint, "v2.0/", "", -1) + + sc.ResourceBase = endpoint + "v2.0/" return sc, err } @@ -473,3 +478,8 @@ func NewContainerInfraV1(client *gophercloud.ProviderClient, eo gophercloud.Endp func NewWorkflowV2(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { return initClientOpts(client, eo, "workflowv2") } + +// NewPlacementV1 creates a ServiceClient that may be used with the placement package. +func NewPlacementV1(client *gophercloud.ProviderClient, eo gophercloud.EndpointOpts) (*gophercloud.ServiceClient, error) { + return initClientOpts(client, eo, "placement") +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/endpoint_location.go b/vendor/github.com/gophercloud/gophercloud/openstack/endpoint_location.go index 12c8aebcf77..509700790ef 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/endpoint_location.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/endpoint_location.go @@ -29,11 +29,12 @@ func V2EndpointURL(catalog *tokens2.ServiceCatalog, opts gophercloud.EndpointOpt } } - // Report an error if the options were ambiguous. + // If multiple endpoints were found, use the first result + // and disregard the other endpoints. + // + // This behavior matches the Python library. See GH-1764. if len(endpoints) > 1 { - err := &ErrMultipleMatchingEndpointsV2{} - err.Endpoints = endpoints - return "", err + endpoints = endpoints[0:1] } // Extract the appropriate URL from the matching Endpoint. @@ -91,9 +92,12 @@ func V3EndpointURL(catalog *tokens3.ServiceCatalog, opts gophercloud.EndpointOpt } } - // Report an error if the options were ambiguous. + // If multiple endpoints were found, use the first result + // and disregard the other endpoints. + // + // This behavior matches the Python library. See GH-1764. if len(endpoints) > 1 { - return "", ErrMultipleMatchingEndpointsV3{Endpoints: endpoints} + endpoints = endpoints[0:1] } // Extract the URL from the matching Endpoint. diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/errors.go b/vendor/github.com/gophercloud/gophercloud/openstack/errors.go index df410b1c611..cba6ae5f00c 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/errors.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/errors.go @@ -4,8 +4,6 @@ import ( "fmt" "github.com/gophercloud/gophercloud" - tokens2 "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens" - tokens3 "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens" ) // ErrEndpointNotFound is the error when no suitable endpoint can be found @@ -24,28 +22,6 @@ func (e ErrInvalidAvailabilityProvided) Error() string { return fmt.Sprintf("Unexpected availability in endpoint query: %s", e.Value) } -// ErrMultipleMatchingEndpointsV2 is the error when more than one endpoint -// for the given options is found in the v2 catalog -type ErrMultipleMatchingEndpointsV2 struct { - gophercloud.BaseError - Endpoints []tokens2.Endpoint -} - -func (e ErrMultipleMatchingEndpointsV2) Error() string { - return fmt.Sprintf("Discovered %d matching endpoints: %#v", len(e.Endpoints), e.Endpoints) -} - -// ErrMultipleMatchingEndpointsV3 is the error when more than one endpoint -// for the given options is found in the v3 catalog -type ErrMultipleMatchingEndpointsV3 struct { - gophercloud.BaseError - Endpoints []tokens3.Endpoint -} - -func (e ErrMultipleMatchingEndpointsV3) Error() string { - return fmt.Sprintf("Discovered %d matching endpoints: %#v", len(e.Endpoints), e.Endpoints) -} - // ErrNoAuthURL is the error when the OS_AUTH_URL environment variable is not // found type ErrNoAuthURL struct{ gophercloud.ErrInvalidInput } diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/doc.go new file mode 100644 index 00000000000..0c12bf2e077 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/doc.go @@ -0,0 +1,48 @@ +/* +Package imagedata enables management of image data. + +Example to Upload Image Data + + imageID := "da3b75d9-3f4a-40e7-8a2c-bfab23927dea" + + imageData, err := os.Open("/path/to/image/file") + if err != nil { + panic(err) + } + defer imageData.Close() + + err = imagedata.Upload(imageClient, imageID, imageData).ExtractErr() + if err != nil { + panic(err) + } + +Example to Stage Image Data + + imageID := "da3b75d9-3f4a-40e7-8a2c-bfab23927dea" + + imageData, err := os.Open("/path/to/image/file") + if err != nil { + panic(err) + } + defer imageData.Close() + + err = imagedata.Stage(imageClient, imageID, imageData).ExtractErr() + if err != nil { + panic(err) + } + +Example to Download Image Data + + imageID := "da3b75d9-3f4a-40e7-8a2c-bfab23927dea" + + image, err := imagedata.Download(imageClient, imageID).Extract() + if err != nil { + panic(err) + } + + imageData, err := ioutil.ReadAll(image) + if err != nil { + panic(err) + } +*/ +package imagedata diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/requests.go new file mode 100644 index 00000000000..545c561f366 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/requests.go @@ -0,0 +1,39 @@ +package imagedata + +import ( + "io" + "net/http" + + "github.com/gophercloud/gophercloud" +) + +// Upload uploads an image file. +func Upload(client *gophercloud.ServiceClient, id string, data io.Reader) (r UploadResult) { + _, r.Err = client.Put(uploadURL(client, id), data, nil, &gophercloud.RequestOpts{ + MoreHeaders: map[string]string{"Content-Type": "application/octet-stream"}, + OkCodes: []int{204}, + }) + return +} + +// Stage performs PUT call on the existing image object in the Imageservice with +// the provided file. +// Existing image object must be in the "queued" status. +func Stage(client *gophercloud.ServiceClient, id string, data io.Reader) (r StageResult) { + _, r.Err = client.Put(stageURL(client, id), data, nil, &gophercloud.RequestOpts{ + MoreHeaders: map[string]string{"Content-Type": "application/octet-stream"}, + OkCodes: []int{204}, + }) + return +} + +// Download retrieves an image. +func Download(client *gophercloud.ServiceClient, id string) (r DownloadResult) { + var resp *http.Response + resp, r.Err = client.Get(downloadURL(client, id), nil, nil) + if resp != nil { + r.Body = resp.Body + r.Header = resp.Header + } + return +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/results.go new file mode 100644 index 00000000000..17a3f0e0f7e --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/results.go @@ -0,0 +1,34 @@ +package imagedata + +import ( + "fmt" + "io" + + "github.com/gophercloud/gophercloud" +) + +// UploadResult is the result of an upload image operation. Call its ExtractErr +// method to determine if the request succeeded or failed. +type UploadResult struct { + gophercloud.ErrResult +} + +// StageResult is the result of a stage image operation. Call its ExtractErr +// method to determine if the request succeeded or failed. +type StageResult struct { + gophercloud.ErrResult +} + +// DownloadResult is the result of a download image operation. Call its Extract +// method to gain access to the image data. +type DownloadResult struct { + gophercloud.Result +} + +// Extract builds images model from io.Reader +func (r DownloadResult) Extract() (io.Reader, error) { + if r, ok := r.Body.(io.Reader); ok { + return r, nil + } + return nil, fmt.Errorf("Expected io.Reader but got: %T(%#v)", r.Body, r.Body) +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/urls.go b/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/urls.go new file mode 100644 index 00000000000..d9615ba7fb8 --- /dev/null +++ b/vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/imagedata/urls.go @@ -0,0 +1,23 @@ +package imagedata + +import "github.com/gophercloud/gophercloud" + +const ( + rootPath = "images" + uploadPath = "file" + stagePath = "stage" +) + +// `imageDataURL(c,i)` is the URL for the binary image data for the +// image identified by ID `i` in the service `c`. +func uploadURL(c *gophercloud.ServiceClient, imageID string) string { + return c.ServiceURL(rootPath, imageID, uploadPath) +} + +func stageURL(c *gophercloud.ServiceClient, imageID string) string { + return c.ServiceURL(rootPath, imageID, stagePath) +} + +func downloadURL(c *gophercloud.ServiceClient, imageID string) string { + return uploadURL(c, imageID) +} diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/doc.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/doc.go index 6ed8c8fb5ff..b191b45e9c0 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/doc.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/doc.go @@ -25,14 +25,15 @@ Example to List Monitors Example to Create a Monitor createOpts := monitors.CreateOpts{ - Type: "HTTP", - Name: "db", - PoolID: "84f1b61f-58c4-45bf-a8a9-2dafb9e5214d", - Delay: 20, - Timeout: 10, - MaxRetries: 5, - URLPath: "/check", - ExpectedCodes: "200-299", + Type: "HTTP", + Name: "db", + PoolID: "84f1b61f-58c4-45bf-a8a9-2dafb9e5214d", + Delay: 20, + Timeout: 10, + MaxRetries: 5, + MaxRetriesDown: 4, + URLPath: "/check", + ExpectedCodes: "200-299", } monitor, err := monitors.Create(networkClient, createOpts).Extract() @@ -45,12 +46,13 @@ Example to Update a Monitor monitorID := "d67d56a6-4a86-4688-a282-f46444705c64" updateOpts := monitors.UpdateOpts{ - Name: "NewHealthmonitorName", - Delay: 3, - Timeout: 20, - MaxRetries: 10, - URLPath: "/another_check", - ExpectedCodes: "301", + Name: "NewHealthmonitorName", + Delay: 3, + Timeout: 20, + MaxRetries: 10, + MaxRetriesDown: 8, + URLPath: "/another_check", + ExpectedCodes: "301", } monitor, err := monitors.Update(networkClient, monitorID, updateOpts).Extract() diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/requests.go index c05289504c7..1a7e8b8f48a 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/requests.go @@ -19,24 +19,25 @@ type ListOptsBuilder interface { // sort by a particular Monitor attribute. SortDir sets the direction, and is // either `asc' or `desc'. Marker and Limit are used for pagination. type ListOpts struct { - ID string `q:"id"` - Name string `q:"name"` - TenantID string `q:"tenant_id"` - ProjectID string `q:"project_id"` - PoolID string `q:"pool_id"` - Type string `q:"type"` - Delay int `q:"delay"` - Timeout int `q:"timeout"` - MaxRetries int `q:"max_retries"` - HTTPMethod string `q:"http_method"` - URLPath string `q:"url_path"` - ExpectedCodes string `q:"expected_codes"` - AdminStateUp *bool `q:"admin_state_up"` - Status string `q:"status"` - Limit int `q:"limit"` - Marker string `q:"marker"` - SortKey string `q:"sort_key"` - SortDir string `q:"sort_dir"` + ID string `q:"id"` + Name string `q:"name"` + TenantID string `q:"tenant_id"` + ProjectID string `q:"project_id"` + PoolID string `q:"pool_id"` + Type string `q:"type"` + Delay int `q:"delay"` + Timeout int `q:"timeout"` + MaxRetries int `q:"max_retries"` + MaxRetriesDown int `q:"max_retries_down"` + HTTPMethod string `q:"http_method"` + URLPath string `q:"url_path"` + ExpectedCodes string `q:"expected_codes"` + AdminStateUp *bool `q:"admin_state_up"` + Status string `q:"status"` + Limit int `q:"limit"` + Marker string `q:"marker"` + SortKey string `q:"sort_key"` + SortDir string `q:"sort_dir"` } // ToMonitorListQuery formats a ListOpts into a query string. @@ -107,6 +108,10 @@ type CreateOpts struct { // status to INACTIVE. Must be a number between 1 and 10. MaxRetries int `json:"max_retries" required:"true"` + // Number of permissible ping failures befor changing the member's + // status to ERROR. Must be a number between 1 and 10. + MaxRetriesDown int `json:"max_retries_down,omitempty"` + // URI path that will be accessed if Monitor type is HTTP or HTTPS. URLPath string `json:"url_path,omitempty"` @@ -191,6 +196,10 @@ type UpdateOpts struct { // status to INACTIVE. Must be a number between 1 and 10. MaxRetries int `json:"max_retries,omitempty"` + // Number of permissible ping failures befor changing the member's + // status to ERROR. Must be a number between 1 and 10. + MaxRetriesDown int `json:"max_retries_down,omitempty"` + // URI path that will be accessed if Monitor type is HTTP or HTTPS. // Required for HTTP(S) types. URLPath string `json:"url_path,omitempty"` diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/results.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/results.go index 2c3a815bae8..dec9395192b 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/results.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/monitors/results.go @@ -50,6 +50,10 @@ type Monitor struct { // member to INACTIVE. A valid value is from 1 to 10. MaxRetries int `json:"max_retries"` + // Number of allowed connection failures before changing the status of the + // member to Error. A valid value is from 1 to 10. + MaxRetriesDown int `json:"max_retries_down"` + // The HTTP method that the monitor uses for requests. HTTPMethod string `json:"http_method"` diff --git a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/requests.go b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/requests.go index 79265d9bb5c..04df4ddb859 100644 --- a/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/requests.go +++ b/vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools/requests.go @@ -275,6 +275,15 @@ type CreateMemberOpts struct { // The administrative state of the Pool. A valid value is true (UP) // or false (DOWN). AdminStateUp *bool `json:"admin_state_up,omitempty"` + + // Is the member a backup? Backup members only receive traffic when all non-backup members are down. + Backup *bool `json:"backup,omitempty"` + + // An alternate IP address used for health monitoring a backend member. + MonitorAddress string `json:"monitor_address,omitempty"` + + // An alternate protocol port used for health monitoring a backend member. + MonitorPort *int `json:"monitor_port,omitempty"` } // ToMemberCreateMap builds a request body from CreateMemberOpts. @@ -283,7 +292,7 @@ func (opts CreateMemberOpts) ToMemberCreateMap() (map[string]interface{}, error) } // CreateMember will create and associate a Member with a particular Pool. -func CreateMember(c *gophercloud.ServiceClient, poolID string, opts CreateMemberOpts) (r CreateMemberResult) { +func CreateMember(c *gophercloud.ServiceClient, poolID string, opts CreateMemberOptsBuilder) (r CreateMemberResult) { b, err := opts.ToMemberCreateMap() if err != nil { r.Err = err diff --git a/vendor/github.com/kubernetes/apimachinery/LICENSE b/vendor/github.com/kubernetes/apimachinery/LICENSE deleted file mode 100644 index d6456956733..00000000000 --- a/vendor/github.com/kubernetes/apimachinery/LICENSE +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. diff --git a/vendor/github.com/kubernetes/apimachinery/pkg/util/rand/rand.go b/vendor/github.com/kubernetes/apimachinery/pkg/util/rand/rand.go deleted file mode 100644 index 82a473bb146..00000000000 --- a/vendor/github.com/kubernetes/apimachinery/pkg/util/rand/rand.go +++ /dev/null @@ -1,127 +0,0 @@ -/* -Copyright 2015 The Kubernetes Authors. - -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 rand provides utilities related to randomization. -package rand - -import ( - "math/rand" - "sync" - "time" -) - -var rng = struct { - sync.Mutex - rand *rand.Rand -}{ - rand: rand.New(rand.NewSource(time.Now().UnixNano())), -} - -// Int returns a non-negative pseudo-random int. -func Int() int { - rng.Lock() - defer rng.Unlock() - return rng.rand.Int() -} - -// Intn generates an integer in range [0,max). -// By design this should panic if input is invalid, <= 0. -func Intn(max int) int { - rng.Lock() - defer rng.Unlock() - return rng.rand.Intn(max) -} - -// IntnRange generates an integer in range [min,max). -// By design this should panic if input is invalid, <= 0. -func IntnRange(min, max int) int { - rng.Lock() - defer rng.Unlock() - return rng.rand.Intn(max-min) + min -} - -// IntnRange generates an int64 integer in range [min,max). -// By design this should panic if input is invalid, <= 0. -func Int63nRange(min, max int64) int64 { - rng.Lock() - defer rng.Unlock() - return rng.rand.Int63n(max-min) + min -} - -// Seed seeds the rng with the provided seed. -func Seed(seed int64) { - rng.Lock() - defer rng.Unlock() - - rng.rand = rand.New(rand.NewSource(seed)) -} - -// Perm returns, as a slice of n ints, a pseudo-random permutation of the integers [0,n) -// from the default Source. -func Perm(n int) []int { - rng.Lock() - defer rng.Unlock() - return rng.rand.Perm(n) -} - -const ( - // We omit vowels from the set of available characters to reduce the chances - // of "bad words" being formed. - alphanums = "bcdfghjklmnpqrstvwxz2456789" - // No. of bits required to index into alphanums string. - alphanumsIdxBits = 5 - // Mask used to extract last alphanumsIdxBits of an int. - alphanumsIdxMask = 1<>= alphanumsIdxBits - remaining-- - } - return string(b) -} - -// SafeEncodeString encodes s using the same characters as rand.String. This reduces the chances of bad words and -// ensures that strings generated from hash functions appear consistent throughout the API. -func SafeEncodeString(s string) string { - r := make([]byte, len(s)) - for i, b := range []rune(s) { - r[i] = alphanums[(int(b) % len(alphanums))] - } - return string(r) -}