diff --git a/go.mod b/go.mod index 2eb1a56771..ca17a73ef8 100644 --- a/go.mod +++ b/go.mod @@ -32,7 +32,7 @@ require ( github.com/hashicorp/golang-lru v0.5.3 // indirect github.com/imdario/mergo v0.3.8 // indirect github.com/onsi/gomega v1.7.1 // indirect - github.com/openshift/api v0.0.0-20200824151745-288e45a0adde + github.com/openshift/api v0.0.0-20200829102639-8a3a835f1acf github.com/openshift/build-machinery-go v0.0.0-20200819073603-48aa266c95f7 github.com/openshift/client-go v0.0.0-20200729195840-c2b1adc6bed6 github.com/openshift/crd-schema-gen v1.0.0 diff --git a/go.sum b/go.sum index cad08dde22..999e828ec1 100644 --- a/go.sum +++ b/go.sum @@ -430,8 +430,8 @@ github.com/openshift/api v0.0.0-20200722170803-0ba2c3658da6/go.mod h1:IXsT3F4NjL github.com/openshift/api v0.0.0-20200723134351-89de68875e7c h1:qsj/GaQ1sdT584yIcGmqqRpR5xtX5jTw5Gis3/09YI4= github.com/openshift/api v0.0.0-20200723134351-89de68875e7c/go.mod h1:IXsT3F4NjLtRzfnQvwU+g/oPWpoNsVV5vd5aaOMO8eU= github.com/openshift/api v0.0.0-20200728200559-811027b63048/go.mod h1:IXsT3F4NjLtRzfnQvwU+g/oPWpoNsVV5vd5aaOMO8eU= -github.com/openshift/api v0.0.0-20200824151745-288e45a0adde h1:8QdKXIB/cYQ5BlNSieOScfFL0Xq4pvIgtRV65w3eqYM= -github.com/openshift/api v0.0.0-20200824151745-288e45a0adde/go.mod h1:VxlbNnMs63PHurw9hgy1DKQKWmTmhRf3PULl7KwA5Kg= +github.com/openshift/api v0.0.0-20200829102639-8a3a835f1acf h1:KP/v5AGCaq1Sbe6QrlFGZM1fHBswiHuniMTC4/hgbVw= +github.com/openshift/api v0.0.0-20200829102639-8a3a835f1acf/go.mod h1:M3xexPhgM8DISzzRpuFUy+jfPjQPIcs9yqEYj17mXV8= github.com/openshift/build-machinery-go v0.0.0-20200713135615-1f43d26dccc7 h1:iP7TOaN+tEVNUQ0ODEbN1ukjLz918lsIt7Czf8giWlM= github.com/openshift/build-machinery-go v0.0.0-20200713135615-1f43d26dccc7/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= github.com/openshift/build-machinery-go v0.0.0-20200819073603-48aa266c95f7 h1:mOq7Mg1Q9d7nIDxe1SJ6pluMBQsbVxa6olyAGmfYWTg= @@ -490,6 +490,7 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= diff --git a/pkg/client/operatorclient.go b/pkg/client/operatorclient.go index 19d92177f6..0da0836bd2 100644 --- a/pkg/client/operatorclient.go +++ b/pkg/client/operatorclient.go @@ -48,8 +48,7 @@ func (c *ConfigOperatorClient) GetOperatorState() (spec *operatorv1.OperatorSpec return nil, nil, "", err } - // TODO(dmage): this should be updated when we add OperatorSpec to the config object - return &operatorv1.OperatorSpec{}, &config.Status.OperatorStatus, config.ResourceVersion, nil + return &config.Spec.OperatorSpec, &config.Status.OperatorStatus, config.ResourceVersion, nil } func (c *ConfigOperatorClient) UpdateOperatorSpec(oldResourceVersion string, in *operatorv1.OperatorSpec) (out *operatorv1.OperatorSpec, newResourceVersion string, err error) { diff --git a/pkg/operator/bootstrap.go b/pkg/operator/bootstrap.go index 865ab85043..2ff12b620e 100644 --- a/pkg/operator/bootstrap.go +++ b/pkg/operator/bootstrap.go @@ -78,8 +78,11 @@ func (c *Controller) Bootstrap() error { Finalizers: []string{defaults.ImageRegistryOperatorResourceFinalizer}, }, Spec: imageregistryv1.ImageRegistrySpec{ + OperatorSpec: operatorapi.OperatorSpec{ + LogLevel: operatorapi.Normal, + OperatorLogLevel: operatorapi.Normal, + }, ManagementState: mgmtState, - LogLevel: 2, Storage: platformStorage, Replicas: replicas, HTTPSecret: fmt.Sprintf("%x", string(secretBytes[:])), diff --git a/pkg/operator/bootstrap_test.go b/pkg/operator/bootstrap_test.go index 8cf9aaa21c..cc7a4e8e27 100644 --- a/pkg/operator/bootstrap_test.go +++ b/pkg/operator/bootstrap_test.go @@ -12,6 +12,7 @@ import ( configv1 "github.com/openshift/api/config/v1" imageregistryv1 "github.com/openshift/api/imageregistry/v1" + operatorv1 "github.com/openshift/api/operator/v1" configfakeclient "github.com/openshift/client-go/config/clientset/versioned/fake" configinformers "github.com/openshift/client-go/config/informers/externalversions" imageregistryfakeclient "github.com/openshift/client-go/imageregistry/clientset/versioned/fake" @@ -77,8 +78,11 @@ func TestBootstrapAWS(t *testing.T) { Storage: imageregistryv1.ImageRegistryConfigStorage{ S3: &imageregistryv1.ImageRegistryConfigStorageS3{}, }, + OperatorSpec: operatorv1.OperatorSpec{ + LogLevel: operatorv1.Normal, + OperatorLogLevel: operatorv1.Normal, + }, Replicas: 2, - LogLevel: 2, RolloutStrategy: "RollingUpdate", } if !reflect.DeepEqual(config.Spec, expected) { diff --git a/pkg/operator/starter.go b/pkg/operator/starter.go index fc708fce5a..3e9666c8a5 100644 --- a/pkg/operator/starter.go +++ b/pkg/operator/starter.go @@ -14,6 +14,8 @@ import ( imageregistryinformers "github.com/openshift/client-go/imageregistry/informers/externalversions" routeclient "github.com/openshift/client-go/route/clientset/versioned" routeinformers "github.com/openshift/client-go/route/informers/externalversions" + "github.com/openshift/library-go/pkg/operator/events" + "github.com/openshift/library-go/pkg/operator/loglevel" "github.com/openshift/cluster-image-registry-operator/pkg/client" "github.com/openshift/cluster-image-registry-operator/pkg/defaults" @@ -109,6 +111,11 @@ func RunOperator(ctx context.Context, kubeconfig *restclient.Config) error { imageregistryInformers, ) + loggingController := loglevel.NewClusterOperatorLoggingController( + configOperatorClient, + events.NewLoggingEventRecorder("image-registry"), + ) + kubeInformers.Start(ctx.Done()) kubeInformersForOpenShiftConfig.Start(ctx.Done()) kubeInformersForKubeSystem.Start(ctx.Done()) @@ -122,6 +129,7 @@ func RunOperator(ctx context.Context, kubeconfig *restclient.Config) error { go imageRegistryCertificatesController.Run(ctx.Done()) go imageConfigStatusController.Run(ctx.Done()) go imagePrunerController.Run(ctx.Done()) + go loggingController.Run(ctx, 1) <-ctx.Done() return nil diff --git a/pkg/resource/podtemplatespec.go b/pkg/resource/podtemplatespec.go index 43535a1e00..c1c869ff37 100644 --- a/pkg/resource/podtemplatespec.go +++ b/pkg/resource/podtemplatespec.go @@ -16,19 +16,25 @@ import ( configapiv1 "github.com/openshift/api/config/v1" v1 "github.com/openshift/api/imageregistry/v1" + operatorapiv1 "github.com/openshift/api/operator/v1" configlisters "github.com/openshift/client-go/config/listers/config/v1" "github.com/openshift/cluster-image-registry-operator/pkg/defaults" "github.com/openshift/cluster-image-registry-operator/pkg/storage" ) +// generateLogLevel returns the appropriate operand log level according to user +// provided configuration. func generateLogLevel(cr *v1.Config) string { switch cr.Spec.LogLevel { - case 0: - return "error" + case operatorapiv1.Debug, operatorapiv1.Trace, operatorapiv1.TraceAll: + return "debug" + } + + switch cr.Spec.Logging { case 1: return "warn" - case 2, 3: + case 0, 2, 3: return "info" } return "debug" diff --git a/vendor/github.com/openshift/api/go.mod b/vendor/github.com/openshift/api/go.mod index f71dd0427f..24b746a76f 100644 --- a/vendor/github.com/openshift/api/go.mod +++ b/vendor/github.com/openshift/api/go.mod @@ -6,9 +6,9 @@ require ( github.com/gogo/protobuf v1.3.1 github.com/openshift/build-machinery-go v0.0.0-20200819073603-48aa266c95f7 github.com/spf13/pflag v1.0.5 - golang.org/x/tools v0.0.0-20200602230032-c00d67ef29d0 - k8s.io/api v0.19.0-rc.2 - k8s.io/apimachinery v0.19.0-rc.2 - k8s.io/code-generator v0.19.0-rc.2 - k8s.io/klog v1.0.0 + golang.org/x/tools v0.0.0-20200616133436-c1934b75d054 + k8s.io/api v0.19.0 + k8s.io/apimachinery v0.19.0 + k8s.io/code-generator v0.19.0 + k8s.io/klog/v2 v2.2.0 ) diff --git a/vendor/github.com/openshift/api/go.sum b/vendor/github.com/openshift/api/go.sum index 1c8561fae2..c4f904ce57 100644 --- a/vendor/github.com/openshift/api/go.sum +++ b/vendor/github.com/openshift/api/go.sum @@ -20,7 +20,7 @@ github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.0.0-20190815234213-e83c0a1c26c8/go.mod h1:pmLOTb3x90VhIKxsA9yeQG5yfOkkKnkk1h+Ql8NDYDw= +github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= @@ -106,7 +106,6 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/openshift/build-machinery-go v0.0.0-20200819073603-48aa266c95f7 h1:mOq7Mg1Q9d7nIDxe1SJ6pluMBQsbVxa6olyAGmfYWTg= github.com/openshift/build-machinery-go v0.0.0-20200819073603-48aa266c95f7/go.mod h1:b1BuldmJlbA/xYtdZvKi+7j5YGB44qJUJDZ9zwiNCfE= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -119,13 +118,19 @@ github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoH github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8 h1:1wopBVtVdWnn03fZelqdXTqk7U7zPQCb+T4rbU9ZEoU= golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -135,13 +140,17 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e h1:3G+cUijn7XD+S4eJFddp53Pv7+slrESplyjG25HgL+k= golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgNrpq9mjcfDemuexIKsU= +golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -164,9 +173,11 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20200602230032-c00d67ef29d0 h1:6txNFSnY+tteYoO+hf01EpdYcYZiurdC9MDIrcUzEu4= -golang.org/x/tools v0.0.0-20200602230032-c00d67ef29d0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054 h1:HHeAlu5H9b71C+Fx0K+1dGgVFN1DM1/wz4aoGOA5qS8= +golang.org/x/tools v0.0.0-20200616133436-c1934b75d054/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= @@ -203,26 +214,23 @@ gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -k8s.io/api v0.19.0-rc.2 h1:Lq0owhvgpWXmMtz+t2AT/JJpIAPX9X8lK3oE2qslYCU= -k8s.io/api v0.19.0-rc.2/go.mod h1:9nHeM2gbqeaL7yN6UFvOxKzLG5gZ4v+DJ6bpavDetZo= -k8s.io/apimachinery v0.19.0-rc.2 h1:JScnJRuwKHT8RmdrsFMkE4Oi+SVI/QIWFGOOhNZJe/M= -k8s.io/apimachinery v0.19.0-rc.2/go.mod h1:eHbWZVMaaewmYBAUuRYnAmTTMtDhvpPNZuh8/6Yl7v0= -k8s.io/code-generator v0.19.0-rc.2 h1:ZSxniVYeSEv1vry0B2N+yqXAcWTJ4gzmIYadKoPNVFU= -k8s.io/code-generator v0.19.0-rc.2/go.mod h1:uR3gwQvtcOjBrvwXhFF1lw5kq9BOOAfSKl/pZZ1zW3I= +k8s.io/api v0.19.0 h1:XyrFIJqTYZJ2DU7FBE/bSPz7b1HvbVBuBf07oeo6eTc= +k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw= +k8s.io/apimachinery v0.19.0 h1:gjKnAda/HZp5k4xQYjL0K/Yb66IvNqjthCb03QlKpaQ= +k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= +k8s.io/code-generator v0.19.0 h1:r0BxYnttP/r8uyKd4+Njg0B57kKi8wLvwEzaaVy3iZ8= +k8s.io/code-generator v0.19.0/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14 h1:t4L10Qfx/p7ASH3gXCdIUtPbbIuegCoUJf3TMSFekjw= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= -k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0 h1:Foj74zO6RbjjP4hBEKjnYtjjAhGg4jNynUdYF6fJrok= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0 h1:XRvcwJozkgZ1UQJmfMGpvRthQHOvihEhYtDfAaxMz/A= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20200427153329-656914f816f9 h1:5NC2ITmvg8RoxoH0wgmL4zn4VZqXGsKbxrikjaQx6s4= -k8s.io/kube-openapi v0.0.0-20200427153329-656914f816f9/go.mod h1:bfCVj+qXcEaE5SCvzBaqpOySr6tuCcpPKqF6HD8nyCw= -sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v3 v3.0.1-0.20200706213357-43c19bbb7fba h1:AAbnc5KQuTWKuh2QSnyghKIOTFzB0Jayv7/OFDn3Cy4= -sigs.k8s.io/structured-merge-diff/v3 v3.0.1-0.20200706213357-43c19bbb7fba/go.mod h1:V06abazjHneE37ZdSY/UUwPVgcJMKI/jU5XGUjgIKoc= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6 h1:+WnxoVtG8TMiudHBSEtrVL1egv36TkkJm+bA8AxicmQ= +k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1 h1:YXTMot5Qz/X1iBRJhAt+vI+HVttY0WkSqqhKxQ0xVbA= +sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= diff --git a/vendor/github.com/openshift/api/helm/v1beta1/0000_10-helm-chart-repository.crd.yaml b/vendor/github.com/openshift/api/helm/v1beta1/0000_10-helm-chart-repository.crd.yaml index a7f8d994b6..75af27ec29 100644 --- a/vendor/github.com/openshift/api/helm/v1beta1/0000_10-helm-chart-repository.crd.yaml +++ b/vendor/github.com/openshift/api/helm/v1beta1/0000_10-helm-chart-repository.crd.yaml @@ -2,6 +2,8 @@ apiVersion: apiextensions.k8s.io/v1beta1 kind: CustomResourceDefinition metadata: name: helmchartrepositories.helm.openshift.io + annotations: + include.release.openshift.io/self-managed-high-availability: "true" spec: scope: Cluster preserveUnknownFields: false diff --git a/vendor/github.com/openshift/api/imageregistry/v1/00-crd.yaml b/vendor/github.com/openshift/api/imageregistry/v1/00-crd.yaml index 9afd80176a..14297e9ac3 100644 --- a/vendor/github.com/openshift/api/imageregistry/v1/00-crd.yaml +++ b/vendor/github.com/openshift/api/imageregistry/v1/00-crd.yaml @@ -1,1233 +1,1290 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: configs.imageregistry.operator.openshift.io spec: group: imageregistry.operator.openshift.io scope: Cluster - version: v1 - names: - kind: Config - listKind: ConfigList - plural: configs - singular: config - preserveUnknownFields: false - subresources: - status: {} - validation: - openAPIV3Schema: - description: Config is the configuration object for a registry instance managed - by the registry operator - type: object - required: - - metadata - - spec - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: ImageRegistrySpec defines the specs for the running registry. - type: object - required: - - logging - - managementState - - replicas - properties: - affinity: - description: affinity is a group of node affinity scheduling rules for - the image registry pod(s). - type: object - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the pod. - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes - that satisfy the affinity expressions specified by this field, - but it may choose a node that violates one or more of the - expressions. The node that is most preferred is the one with - the greatest sum of weights, i.e. for each node that meets - all of the scheduling requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating through - the elements of this field and adding "weight" to the sum - if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - type: array - items: - description: An empty preferred scheduling term matches all - objects with implicit weight 0 (i.e. it's a no-op). A null - preferred scheduling term matches no objects (i.e. is also - a no-op). - type: object - required: - - preference - - weight - properties: - preference: - description: A node selector term, associated with the - corresponding weight. - type: object - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - type: array - items: - description: A node selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the - operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be - empty. If the operator is Gt or Lt, the values - array must have a single element, which will - be interpreted as an integer. This array is - replaced during a strategic merge patch. - type: array - items: + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "schema": + "openAPIV3Schema": + description: Config is the configuration object for a registry instance managed + by the registry operator + type: object + required: + - metadata + - spec + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ImageRegistrySpec defines the specs for the running registry. + type: object + required: + - managementState + - replicas + properties: + affinity: + description: affinity is a group of node affinity scheduling rules + for the image registry pod(s). + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + type: array + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector + applies to. type: string - matchFields: - description: A list of node selector requirements - by node's fields. - type: array - items: - description: A node selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the - operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be - empty. If the operator is Gt or Lt, the values - array must have a single element, which will - be interpreted as an integer. This array is - replaced during a strategic merge patch. - type: array - items: + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. type: string - weight: - description: Weight associated with matching the corresponding - nodeSelectorTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this - field are not met at scheduling time, the pod will not be - scheduled onto the node. If the affinity requirements specified - by this field cease to be met at some point during pod execution - (e.g. due to an update), the system may or may not try to - eventually evict the pod from its node. - type: object - required: - - nodeSelectorTerms - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. The - terms are ORed. - type: array - items: - description: A null or empty node selector term matches - no objects. The requirements of them are ANDed. The - TopologySelectorTerm type implements a subset of the - NodeSelectorTerm. - type: object - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - type: array - items: - description: A node selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the - operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be - empty. If the operator is Gt or Lt, the values - array must have a single element, which will - be interpreted as an integer. This array is - replaced during a strategic merge patch. - type: array - items: + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements + by node's fields. + type: array + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector + applies to. type: string - matchFields: - description: A list of node selector requirements - by node's fields. - type: array - items: - description: A node selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the - operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be - empty. If the operator is Gt or Lt, the values - array must have a single element, which will - be interpreted as an integer. This array is - replaced during a strategic merge patch. - type: array - items: + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. type: string - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate - this pod in the same node, zone, etc. as some other pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes - that satisfy the affinity expressions specified by this field, - but it may choose a node that violates one or more of the - expressions. The node that is most preferred is the one with - the greatest sum of weights, i.e. for each node that meets - all of the scheduling requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating through - the elements of this field and adding "weight" to the sum - if the node has pods which matches the corresponding podAffinityTerm; - the node(s) with the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred node(s) + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + type: array + items: + type: string + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. type: object required: - - podAffinityTerm - - weight + - nodeSelectorTerms properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - type: array - items: - description: A label selector requirement is - a selector that contains values, a key, and - an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and DoesNotExist. + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + type: array + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + type: array + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + type: array + items: type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. If - the operator is Exists or DoesNotExist, - the values array must be empty. This array - is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is "In", - and the values array contains only "value". - The requirements are ANDed. + matchFields: + description: A list of node selector requirements + by node's fields. + type: array + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. type: object - additionalProperties: - type: string - namespaces: - description: namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey matches - that of any node on which any of the selected pods - is running. Empty topologyKey is not allowed. - type: string - weight: - description: weight associated with matching the corresponding - podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this - field are not met at scheduling time, the pod will not be - scheduled onto the node. If the affinity requirements specified - by this field cease to be met at some point during pod execution - (e.g. due to a pod label update), the system may or may not - try to eventually evict the pod from its node. When there - are multiple elements, the lists of nodes corresponding to - each podAffinityTerm are intersected, i.e. all terms must - be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) that - this pod should be co-located (affinity) or not co-located - (anti-affinity) with, where co-located is defined as running - on a node whose value of the label with key - matches that of any node on which a pod of the set of pods - is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in - this case pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. + required: + - key + - operator + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + type: array + items: + type: string + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. type: object - required: - - key - - operator properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values - array must be non-empty. If the operator is - Exists or DoesNotExist, the values array must - be empty. This array is replaced during a - strategic merge patch. + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. type: array items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + additionalProperties: type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - additionalProperties: + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. type: string - namespaces: - description: namespaces specifies which namespaces the - labelSelector applies to (matches against); null or - empty list means "this pod's namespace" - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where - co-located is defined as running on a node whose value - of the label with key topologyKey matches that of any - node on which any of the selected pods is running. Empty - topologyKey is not allowed. - type: string - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. - avoid putting this pod in the same node, zone, etc. as some other - pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes - that satisfy the anti-affinity expressions specified by this - field, but it may choose a node that violates one or more - of the expressions. The node that is most preferred is the - one with the greatest sum of weights, i.e. for each node that - meets all of the scheduling requirements (resource request, - requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field - and adding "weight" to the sum if the node has pods which - matches the corresponding podAffinityTerm; the node(s) with - the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred node(s) - type: object - required: - - podAffinityTerm - - weight - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - type: array - items: - description: A label selector requirement is - a selector that contains values, a key, and - an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. If - the operator is Exists or DoesNotExist, - the values array must be empty. This array - is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is "In", - and the values array contains only "value". - The requirements are ANDed. + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. type: object - additionalProperties: - type: string - namespaces: - description: namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey matches - that of any node on which any of the selected pods - is running. Empty topologyKey is not allowed. + required: + - key + - operator + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies which namespaces the + labelSelector applies to (matches against); null or + empty list means "this pod's namespace" + type: array + items: type: string - weight: - description: weight associated with matching the corresponding - podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by - this field are not met at scheduling time, the pod will not - be scheduled onto the node. If the anti-affinity requirements - specified by this field cease to be met at some point during - pod execution (e.g. due to a pod label update), the system - may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding - to each podAffinityTerm are intersected, i.e. all terms must - be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) that - this pod should be co-located (affinity) or not co-located - (anti-affinity) with, where co-located is defined as running - on a node whose value of the label with key - matches that of any node on which a pod of the set of pods - is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in - this case pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. type: object - required: - - key - - operator properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values - array must be non-empty. If the operator is - Exists or DoesNotExist, the values array must - be empty. This array is replaced during a - strategic merge patch. + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. type: array items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + additionalProperties: type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - additionalProperties: + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. type: string - namespaces: - description: namespaces specifies which namespaces the - labelSelector applies to (matches against); null or - empty list means "this pod's namespace" - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where - co-located is defined as running on a node whose value - of the label with key topologyKey matches that of any - node on which any of the selected pods is running. Empty - topologyKey is not allowed. - type: string - defaultRoute: - description: defaultRoute indicates whether an external facing route - for the registry should be created using the default generated hostname. - type: boolean - disableRedirect: - description: disableRedirect controls whether to route all data through - the Registry, rather than redirecting to the backend. - type: boolean - httpSecret: - description: httpSecret is the value needed by the registry to secure - uploads, generated by default. - type: string - logging: - description: logging determines the level of logging enabled in the - registry. - type: integer - format: int64 - managementState: - description: managementState indicates whether the registry instance - represented by this config instance is under operator management or - not. Valid values are Managed, Unmanaged, and Removed. - type: string - pattern: ^(Managed|Unmanaged|Force|Removed)$ - nodeSelector: - description: nodeSelector defines the node selection constraints for - the registry pod. - type: object - additionalProperties: - type: string - proxy: - description: proxy defines the proxy to be used when calling master - api, upstream registries, etc. - type: object - properties: - http: - description: http defines the proxy to be used by the image registry - when accessing HTTP endpoints. - type: string - https: - description: https defines the proxy to be used by the image registry - when accessing HTTPS endpoints. - type: string - noProxy: - description: noProxy defines a comma-separated list of host names - that shouldn't go through any proxy. - type: string - readOnly: - description: readOnly indicates whether the registry instance should - reject attempts to push new images or delete existing ones. - type: boolean - replicas: - description: replicas determines the number of registry instances to - run. - type: integer - format: int32 - requests: - description: requests controls how many parallel requests a given registry - instance will handle before queuing additional requests. - type: object - properties: - read: - description: read defines limits for image registry's reads. - type: object - properties: - maxInQueue: - description: maxInQueue sets the maximum queued api requests - to the registry. - type: integer - maxRunning: - description: maxRunning sets the maximum in flight api requests - to the registry. - type: integer - maxWaitInQueue: - description: maxWaitInQueue sets the maximum time a request - can wait in the queue before being rejected. - type: string - format: duration - write: - description: write defines limits for image registry's writes. - type: object - properties: - maxInQueue: - description: maxInQueue sets the maximum queued api requests - to the registry. - type: integer - maxRunning: - description: maxRunning sets the maximum in flight api requests - to the registry. - type: integer - maxWaitInQueue: - description: maxWaitInQueue sets the maximum time a request - can wait in the queue before being rejected. - type: string - format: duration - resources: - description: resources defines the resource requests+limits for the - registry pod. - type: object - properties: - limits: - description: 'Limits describes the maximum amount of compute resources - allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - additionalProperties: - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - requests: - description: 'Requests describes the minimum amount of compute resources - required. If Requests is omitted for a container, it defaults - to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - additionalProperties: - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - rolloutStrategy: - description: rolloutStrategy defines rollout strategy for the image - registry deployment. - type: string - pattern: ^(RollingUpdate|Recreate)$ - routes: - description: routes defines additional external facing routes which - should be created for the registry. - type: array - items: - description: ImageRegistryConfigRoute holds information on external - route access to image registry. - type: object - required: - - name - properties: - hostname: - description: hostname for the route. - type: string - name: - description: name of the route to be created. - type: string - secretName: - description: secretName points to secret containing the certificates - to be used by the route. - type: string - storage: - description: storage details for configuring registry storage, e.g. - S3 bucket coordinates. - type: object - properties: - azure: - description: azure represents configuration that uses Azure Blob - Storage. - type: object - properties: - accountName: - description: accountName defines the account to be used by the - registry. - type: string - cloudName: - description: cloudName is the name of the Azure cloud environment - to be used by the registry. If empty, the operator will set - it based on the infrastructure object. - type: string - container: - description: container defines Azure's container to be used - by registry. - type: string - maxLength: 63 - minLength: 3 - pattern: ^[0-9a-z]+(-[0-9a-z]+)*$ - emptyDir: - description: 'emptyDir represents ephemeral storage on the pod''s - host node. WARNING: this storage cannot be used with more than - 1 replica and is not suitable for production use. When the pod - is removed from a node for any reason, the data in the emptyDir - is deleted forever.' - type: object - gcs: - description: gcs represents configuration that uses Google Cloud - Storage. - type: object - properties: - bucket: - description: bucket is the bucket name in which you want to - store the registry's data. Optional, will be generated if - not provided. - type: string - keyID: - description: keyID is the KMS key ID to use for encryption. - Optional, buckets are encrypted by default on GCP. This allows - for the use of a custom encryption key. - type: string - projectID: - description: projectID is the Project ID of the GCP project - that this bucket should be associated with. - type: string - region: - description: region is the GCS location in which your bucket - exists. Optional, will be set based on the installed GCS Region. - type: string - managementState: - description: managementState indicates if the operator manages the - underlying storage unit. If Managed the operator will remove the - storage when this operator gets Removed. - type: string - pattern: ^(Managed|Unmanaged)$ - pvc: - description: pvc represents configuration that uses a PersistentVolumeClaim. - type: object - properties: - claim: - description: claim defines the Persisent Volume Claim's name - to be used. - type: string - s3: - description: s3 represents configuration that uses Amazon Simple - Storage Service. - type: object - properties: - bucket: - description: bucket is the bucket name in which you want to - store the registry's data. Optional, will be generated if - not provided. - type: string - cloudFront: - description: cloudFront configures Amazon Cloudfront as the - storage middleware in a registry. - type: object - required: - - baseURL - - keypairID - - privateKey - properties: - baseURL: - description: baseURL contains the SCHEME://HOST[/PATH] at - which Cloudfront is served. - type: string - duration: - description: duration is the duration of the Cloudfront - session. - type: string - format: duration - keypairID: - description: keypairID is key pair ID provided by AWS. - type: string - privateKey: - description: privateKey points to secret containing the - private key, provided by AWS. + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running type: object required: - - key + - topologyKey properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?' + labelSelector: + description: A label query over a set of resources, + in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies which namespaces the + labelSelector applies to (matches against); null or + empty list means "this pod's namespace" + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. type: string - optional: - description: Specify whether the Secret or its key must - be defined - type: boolean - encrypt: - description: encrypt specifies whether the registry stores the - image in encrypted format or not. Optional, defaults to false. - type: boolean - keyID: - description: keyID is the KMS key ID to use for encryption. - Optional, Encrypt must be true, or this parameter is ignored. - type: string - region: - description: region is the AWS region in which your bucket exists. - Optional, will be set based on the installed AWS Region. - type: string - regionEndpoint: - description: regionEndpoint is the endpoint for S3 compatible - storage services. Optional, defaults based on the Region that - is provided. - type: string - virtualHostedStyle: - description: virtualHostedStyle enables using S3 virtual hosted - style bucket paths with a custom RegionEndpoint Optional, - defaults to false. - type: boolean - swift: - description: swift represents configuration that uses OpenStack - Object Storage. - type: object - properties: - authURL: - description: authURL defines the URL for obtaining an authentication - token. - type: string - authVersion: - description: authVersion specifies the OpenStack Auth's version. - type: string - container: - description: container defines the name of Swift container where - to store the registry's data. - type: string - domain: - description: domain specifies Openstack's domain name for Identity - v3 API. - type: string - domainID: - description: domainID specifies Openstack's domain id for Identity - v3 API. - type: string - regionName: - description: regionName defines Openstack's region in which - container exists. - type: string - tenant: - description: tenant defines Openstack tenant name to be used - by registry. - type: string - tenantID: - description: tenant defines Openstack tenant id to be used by - registry. - type: string - tolerations: - description: tolerations defines the tolerations for the registry pod. - type: array - items: - description: The pod this Toleration is attached to tolerates any - taint that matches the triple using the matching - operator . + defaultRoute: + description: defaultRoute indicates whether an external facing route + for the registry should be created using the default generated hostname. + type: boolean + disableRedirect: + description: disableRedirect controls whether to route all data through + the Registry, rather than redirecting to the backend. + type: boolean + httpSecret: + description: httpSecret is the value needed by the registry to secure + uploads, generated by default. + type: string + logLevel: + description: "logLevel is an intent based logging for an overall component. + \ It does not give fine grained control, but it is a simple way + to manage coarse grained logging choices that operators have to + interpret for their operands. \n Valid values are: \"Normal\", \"Debug\", + \"Trace\", \"TraceAll\". Defaults to \"Normal\"." + type: string + default: Normal + logging: + description: logging is deprecated, use logLevel instead. + type: integer + format: int64 + managementState: + description: managementState indicates whether and how the operator + should manage the component + type: string + pattern: ^(Managed|Unmanaged|Force|Removed)$ + nodeSelector: + description: nodeSelector defines the node selection constraints for + the registry pod. + type: object + additionalProperties: + type: string + observedConfig: + description: observedConfig holds a sparse config that controller + has observed from the cluster state. It exists in spec because + it is an input to the level for the operator + type: object + nullable: true + x-kubernetes-preserve-unknown-fields: true + operatorLogLevel: + description: operatorLogLevel is an intent based logging for the operator + itself. It does not give fine grained control, but it is a simple + way to manage coarse grained logging choices that operators have + to interpret for themselves. + type: string + proxy: + description: proxy defines the proxy to be used when calling master + api, upstream registries, etc. type: object properties: - effect: - description: Effect indicates the taint effect to match. Empty - means match all taint effects. When specified, allowed values - are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, operator - must be Exists; this combination means to match all values and - all keys. + http: + description: http defines the proxy to be used by the image registry + when accessing HTTP endpoints. type: string - operator: - description: Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. Exists - is equivalent to wildcard for value, so that a pod can tolerate - all taints of a particular category. + https: + description: https defines the proxy to be used by the image registry + when accessing HTTPS endpoints. type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time the - toleration (which must be of effect NoExecute, otherwise this - field is ignored) tolerates the taint. By default, it is not - set, which means tolerate the taint forever (do not evict). - Zero and negative values will be treated as 0 (evict immediately) - by the system. - type: integer - format: int64 - value: - description: Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise - just a regular string. + noProxy: + description: noProxy defines a comma-separated list of host names + that shouldn't go through any proxy. type: string - status: - description: ImageRegistryStatus reports image registry operational status. - type: object - required: - - storage - - storageManaged - properties: - conditions: - description: conditions is a list of conditions and their status - type: array - items: - description: OperatorCondition is just the standard condition fields. + readOnly: + description: readOnly indicates whether the registry instance should + reject attempts to push new images or delete existing ones. + type: boolean + replicas: + description: replicas determines the number of registry instances + to run. + type: integer + format: int32 + requests: + description: requests controls how many parallel requests a given + registry instance will handle before queuing additional requests. type: object properties: - lastTransitionTime: - type: string - format: date-time - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - generations: - description: generations are used to determine when an item needs to - be reconciled or has changed in a way that needs a reaction. - type: array - items: - description: GenerationStatus keeps track of the generation for a - given resource so that decisions about forced updates can be made. + read: + description: read defines limits for image registry's reads. + type: object + properties: + maxInQueue: + description: maxInQueue sets the maximum queued api requests + to the registry. + type: integer + maxRunning: + description: maxRunning sets the maximum in flight api requests + to the registry. + type: integer + maxWaitInQueue: + description: maxWaitInQueue sets the maximum time a request + can wait in the queue before being rejected. + type: string + format: duration + write: + description: write defines limits for image registry's writes. + type: object + properties: + maxInQueue: + description: maxInQueue sets the maximum queued api requests + to the registry. + type: integer + maxRunning: + description: maxRunning sets the maximum in flight api requests + to the registry. + type: integer + maxWaitInQueue: + description: maxWaitInQueue sets the maximum time a request + can wait in the queue before being rejected. + type: string + format: duration + resources: + description: resources defines the resource requests+limits for the + registry pod. type: object properties: - group: - description: group is the group of the thing you're tracking - type: string - hash: - description: hash is an optional field set for resources without - generation that are content sensitive like secrets and configmaps - type: string - lastGeneration: - description: lastGeneration is the last generation of the workload - controller involved - type: integer - format: int64 - name: - description: name is the name of the thing you're tracking - type: string - namespace: - description: namespace is where the thing you're tracking is - type: string - resource: - description: resource is the resource type of the thing you're - tracking - type: string - observedGeneration: - description: observedGeneration is the last generation change you've - dealt with - type: integer - format: int64 - readyReplicas: - description: readyReplicas indicates how many replicas are ready and - at the desired state - type: integer - format: int32 - storage: - description: storage indicates the current applied storage configuration - of the registry. - type: object - properties: - azure: - description: azure represents configuration that uses Azure Blob - Storage. + limits: + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + additionalProperties: + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + requests: + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + additionalProperties: + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + rolloutStrategy: + description: rolloutStrategy defines rollout strategy for the image + registry deployment. + type: string + pattern: ^(RollingUpdate|Recreate)$ + routes: + description: routes defines additional external facing routes which + should be created for the registry. + type: array + items: + description: ImageRegistryConfigRoute holds information on external + route access to image registry. type: object + required: + - name properties: - accountName: - description: accountName defines the account to be used by the - registry. + hostname: + description: hostname for the route. type: string - cloudName: - description: cloudName is the name of the Azure cloud environment - to be used by the registry. If empty, the operator will set - it based on the infrastructure object. + name: + description: name of the route to be created. type: string - container: - description: container defines Azure's container to be used - by registry. + secretName: + description: secretName points to secret containing the certificates + to be used by the route. type: string - maxLength: 63 - minLength: 3 - pattern: ^[0-9a-z]+(-[0-9a-z]+)*$ - emptyDir: - description: 'emptyDir represents ephemeral storage on the pod''s - host node. WARNING: this storage cannot be used with more than - 1 replica and is not suitable for production use. When the pod - is removed from a node for any reason, the data in the emptyDir - is deleted forever.' - type: object - gcs: - description: gcs represents configuration that uses Google Cloud - Storage. + storage: + description: storage details for configuring registry storage, e.g. + S3 bucket coordinates. + type: object + properties: + azure: + description: azure represents configuration that uses Azure Blob + Storage. + type: object + properties: + accountName: + description: accountName defines the account to be used by + the registry. + type: string + cloudName: + description: cloudName is the name of the Azure cloud environment + to be used by the registry. If empty, the operator will + set it based on the infrastructure object. + type: string + container: + description: container defines Azure's container to be used + by registry. + type: string + maxLength: 63 + minLength: 3 + pattern: ^[0-9a-z]+(-[0-9a-z]+)*$ + emptyDir: + description: 'emptyDir represents ephemeral storage on the pod''s + host node. WARNING: this storage cannot be used with more than + 1 replica and is not suitable for production use. When the pod + is removed from a node for any reason, the data in the emptyDir + is deleted forever.' + type: object + gcs: + description: gcs represents configuration that uses Google Cloud + Storage. + type: object + properties: + bucket: + description: bucket is the bucket name in which you want to + store the registry's data. Optional, will be generated if + not provided. + type: string + keyID: + description: keyID is the KMS key ID to use for encryption. + Optional, buckets are encrypted by default on GCP. This + allows for the use of a custom encryption key. + type: string + projectID: + description: projectID is the Project ID of the GCP project + that this bucket should be associated with. + type: string + region: + description: region is the GCS location in which your bucket + exists. Optional, will be set based on the installed GCS + Region. + type: string + managementState: + description: managementState indicates if the operator manages + the underlying storage unit. If Managed the operator will remove + the storage when this operator gets Removed. + type: string + pattern: ^(Managed|Unmanaged)$ + pvc: + description: pvc represents configuration that uses a PersistentVolumeClaim. + type: object + properties: + claim: + description: claim defines the Persisent Volume Claim's name + to be used. + type: string + s3: + description: s3 represents configuration that uses Amazon Simple + Storage Service. + type: object + properties: + bucket: + description: bucket is the bucket name in which you want to + store the registry's data. Optional, will be generated if + not provided. + type: string + cloudFront: + description: cloudFront configures Amazon Cloudfront as the + storage middleware in a registry. + type: object + required: + - baseURL + - keypairID + - privateKey + properties: + baseURL: + description: baseURL contains the SCHEME://HOST[/PATH] + at which Cloudfront is served. + type: string + duration: + description: duration is the duration of the Cloudfront + session. + type: string + format: duration + keypairID: + description: keypairID is key pair ID provided by AWS. + type: string + privateKey: + description: privateKey points to secret containing the + private key, provided by AWS. + type: object + required: + - key + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + encrypt: + description: encrypt specifies whether the registry stores + the image in encrypted format or not. Optional, defaults + to false. + type: boolean + keyID: + description: keyID is the KMS key ID to use for encryption. + Optional, Encrypt must be true, or this parameter is ignored. + type: string + region: + description: region is the AWS region in which your bucket + exists. Optional, will be set based on the installed AWS + Region. + type: string + regionEndpoint: + description: regionEndpoint is the endpoint for S3 compatible + storage services. Optional, defaults based on the Region + that is provided. + type: string + virtualHostedStyle: + description: virtualHostedStyle enables using S3 virtual hosted + style bucket paths with a custom RegionEndpoint Optional, + defaults to false. + type: boolean + swift: + description: swift represents configuration that uses OpenStack + Object Storage. + type: object + properties: + authURL: + description: authURL defines the URL for obtaining an authentication + token. + type: string + authVersion: + description: authVersion specifies the OpenStack Auth's version. + type: string + container: + description: container defines the name of Swift container + where to store the registry's data. + type: string + domain: + description: domain specifies Openstack's domain name for + Identity v3 API. + type: string + domainID: + description: domainID specifies Openstack's domain id for + Identity v3 API. + type: string + regionName: + description: regionName defines Openstack's region in which + container exists. + type: string + tenant: + description: tenant defines Openstack tenant name to be used + by registry. + type: string + tenantID: + description: tenant defines Openstack tenant id to be used + by registry. + type: string + tolerations: + description: tolerations defines the tolerations for the registry + pod. + type: array + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . type: object properties: - bucket: - description: bucket is the bucket name in which you want to - store the registry's data. Optional, will be generated if - not provided. + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. type: string - keyID: - description: keyID is the KMS key ID to use for encryption. - Optional, buckets are encrypted by default on GCP. This allows - for the use of a custom encryption key. + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. type: string - projectID: - description: projectID is the Project ID of the GCP project - that this bucket should be associated with. + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. type: string - region: - description: region is the GCS location in which your bucket - exists. Optional, will be set based on the installed GCS Region. + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + type: integer + format: int64 + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. type: string - managementState: - description: managementState indicates if the operator manages the - underlying storage unit. If Managed the operator will remove the - storage when this operator gets Removed. - type: string - pattern: ^(Managed|Unmanaged)$ - pvc: - description: pvc represents configuration that uses a PersistentVolumeClaim. + unsupportedConfigOverrides: + description: 'unsupportedConfigOverrides holds a sparse config that + will override any previously set options. It only needs to be the + fields to override it will end up overlaying in the following order: + 1. hardcoded defaults 2. observedConfig 3. unsupportedConfigOverrides' + type: object + nullable: true + x-kubernetes-preserve-unknown-fields: true + status: + description: ImageRegistryStatus reports image registry operational status. + type: object + required: + - storage + - storageManaged + properties: + conditions: + description: conditions is a list of conditions and their status + type: array + items: + description: OperatorCondition is just the standard condition fields. type: object properties: - claim: - description: claim defines the Persisent Volume Claim's name - to be used. + lastTransitionTime: type: string - s3: - description: s3 represents configuration that uses Amazon Simple - Storage Service. - type: object - properties: - bucket: - description: bucket is the bucket name in which you want to - store the registry's data. Optional, will be generated if - not provided. + format: date-time + message: type: string - cloudFront: - description: cloudFront configures Amazon Cloudfront as the - storage middleware in a registry. - type: object - required: - - baseURL - - keypairID - - privateKey - properties: - baseURL: - description: baseURL contains the SCHEME://HOST[/PATH] at - which Cloudfront is served. - type: string - duration: - description: duration is the duration of the Cloudfront - session. - type: string - format: duration - keypairID: - description: keypairID is key pair ID provided by AWS. - type: string - privateKey: - description: privateKey points to secret containing the - private key, provided by AWS. - type: object - required: - - key - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid?' - type: string - optional: - description: Specify whether the Secret or its key must - be defined - type: boolean - encrypt: - description: encrypt specifies whether the registry stores the - image in encrypted format or not. Optional, defaults to false. - type: boolean - keyID: - description: keyID is the KMS key ID to use for encryption. - Optional, Encrypt must be true, or this parameter is ignored. + reason: type: string - region: - description: region is the AWS region in which your bucket exists. - Optional, will be set based on the installed AWS Region. + status: type: string - regionEndpoint: - description: regionEndpoint is the endpoint for S3 compatible - storage services. Optional, defaults based on the Region that - is provided. + type: type: string - virtualHostedStyle: - description: virtualHostedStyle enables using S3 virtual hosted - style bucket paths with a custom RegionEndpoint Optional, - defaults to false. - type: boolean - swift: - description: swift represents configuration that uses OpenStack - Object Storage. + generations: + description: generations are used to determine when an item needs + to be reconciled or has changed in a way that needs a reaction. + type: array + items: + description: GenerationStatus keeps track of the generation for + a given resource so that decisions about forced updates can be + made. type: object properties: - authURL: - description: authURL defines the URL for obtaining an authentication - token. - type: string - authVersion: - description: authVersion specifies the OpenStack Auth's version. - type: string - container: - description: container defines the name of Swift container where - to store the registry's data. - type: string - domain: - description: domain specifies Openstack's domain name for Identity - v3 API. + group: + description: group is the group of the thing you're tracking type: string - domainID: - description: domainID specifies Openstack's domain id for Identity - v3 API. + hash: + description: hash is an optional field set for resources without + generation that are content sensitive like secrets and configmaps type: string - regionName: - description: regionName defines Openstack's region in which - container exists. + lastGeneration: + description: lastGeneration is the last generation of the workload + controller involved + type: integer + format: int64 + name: + description: name is the name of the thing you're tracking type: string - tenant: - description: tenant defines Openstack tenant name to be used - by registry. + namespace: + description: namespace is where the thing you're tracking is type: string - tenantID: - description: tenant defines Openstack tenant id to be used by - registry. + resource: + description: resource is the resource type of the thing you're + tracking type: string - storageManaged: - description: storageManaged is deprecated, please refer to Storage.managementState - type: boolean - version: - description: version is the level this availability applies to - type: string + observedGeneration: + description: observedGeneration is the last generation change you've + dealt with + type: integer + format: int64 + readyReplicas: + description: readyReplicas indicates how many replicas are ready and + at the desired state + type: integer + format: int32 + storage: + description: storage indicates the current applied storage configuration + of the registry. + type: object + properties: + azure: + description: azure represents configuration that uses Azure Blob + Storage. + type: object + properties: + accountName: + description: accountName defines the account to be used by + the registry. + type: string + cloudName: + description: cloudName is the name of the Azure cloud environment + to be used by the registry. If empty, the operator will + set it based on the infrastructure object. + type: string + container: + description: container defines Azure's container to be used + by registry. + type: string + maxLength: 63 + minLength: 3 + pattern: ^[0-9a-z]+(-[0-9a-z]+)*$ + emptyDir: + description: 'emptyDir represents ephemeral storage on the pod''s + host node. WARNING: this storage cannot be used with more than + 1 replica and is not suitable for production use. When the pod + is removed from a node for any reason, the data in the emptyDir + is deleted forever.' + type: object + gcs: + description: gcs represents configuration that uses Google Cloud + Storage. + type: object + properties: + bucket: + description: bucket is the bucket name in which you want to + store the registry's data. Optional, will be generated if + not provided. + type: string + keyID: + description: keyID is the KMS key ID to use for encryption. + Optional, buckets are encrypted by default on GCP. This + allows for the use of a custom encryption key. + type: string + projectID: + description: projectID is the Project ID of the GCP project + that this bucket should be associated with. + type: string + region: + description: region is the GCS location in which your bucket + exists. Optional, will be set based on the installed GCS + Region. + type: string + managementState: + description: managementState indicates if the operator manages + the underlying storage unit. If Managed the operator will remove + the storage when this operator gets Removed. + type: string + pattern: ^(Managed|Unmanaged)$ + pvc: + description: pvc represents configuration that uses a PersistentVolumeClaim. + type: object + properties: + claim: + description: claim defines the Persisent Volume Claim's name + to be used. + type: string + s3: + description: s3 represents configuration that uses Amazon Simple + Storage Service. + type: object + properties: + bucket: + description: bucket is the bucket name in which you want to + store the registry's data. Optional, will be generated if + not provided. + type: string + cloudFront: + description: cloudFront configures Amazon Cloudfront as the + storage middleware in a registry. + type: object + required: + - baseURL + - keypairID + - privateKey + properties: + baseURL: + description: baseURL contains the SCHEME://HOST[/PATH] + at which Cloudfront is served. + type: string + duration: + description: duration is the duration of the Cloudfront + session. + type: string + format: duration + keypairID: + description: keypairID is key pair ID provided by AWS. + type: string + privateKey: + description: privateKey points to secret containing the + private key, provided by AWS. + type: object + required: + - key + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + TODO: Add other useful fields. apiVersion, kind, + uid?' + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + encrypt: + description: encrypt specifies whether the registry stores + the image in encrypted format or not. Optional, defaults + to false. + type: boolean + keyID: + description: keyID is the KMS key ID to use for encryption. + Optional, Encrypt must be true, or this parameter is ignored. + type: string + region: + description: region is the AWS region in which your bucket + exists. Optional, will be set based on the installed AWS + Region. + type: string + regionEndpoint: + description: regionEndpoint is the endpoint for S3 compatible + storage services. Optional, defaults based on the Region + that is provided. + type: string + virtualHostedStyle: + description: virtualHostedStyle enables using S3 virtual hosted + style bucket paths with a custom RegionEndpoint Optional, + defaults to false. + type: boolean + swift: + description: swift represents configuration that uses OpenStack + Object Storage. + type: object + properties: + authURL: + description: authURL defines the URL for obtaining an authentication + token. + type: string + authVersion: + description: authVersion specifies the OpenStack Auth's version. + type: string + container: + description: container defines the name of Swift container + where to store the registry's data. + type: string + domain: + description: domain specifies Openstack's domain name for + Identity v3 API. + type: string + domainID: + description: domainID specifies Openstack's domain id for + Identity v3 API. + type: string + regionName: + description: regionName defines Openstack's region in which + container exists. + type: string + tenant: + description: tenant defines Openstack tenant name to be used + by registry. + type: string + tenantID: + description: tenant defines Openstack tenant id to be used + by registry. + type: string + storageManaged: + description: storageManaged is deprecated, please refer to Storage.managementState + type: boolean + version: + description: version is the level this availability applies to + type: string + names: + kind: Config + listKind: ConfigList + plural: configs + singular: config diff --git a/vendor/github.com/openshift/api/imageregistry/v1/01-crd.yaml b/vendor/github.com/openshift/api/imageregistry/v1/01-crd.yaml index b0997a983b..a1f7cce99e 100644 --- a/vendor/github.com/openshift/api/imageregistry/v1/01-crd.yaml +++ b/vendor/github.com/openshift/api/imageregistry/v1/01-crd.yaml @@ -1,756 +1,778 @@ -apiVersion: apiextensions.k8s.io/v1beta1 +apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: name: imagepruners.imageregistry.operator.openshift.io spec: group: imageregistry.operator.openshift.io scope: Cluster - version: v1 - preserveUnknownFields: false - subresources: - status: {} - names: - kind: ImagePruner - listKind: ImagePrunerList - plural: imagepruners - singular: imagepruner - "validation": - "openAPIV3Schema": - description: ImagePruner is the configuration object for an image registry pruner - managed by the registry operator. - type: object - required: - - metadata - - spec - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: ImagePrunerSpec defines the specs for the running image pruner. - type: object - properties: - affinity: - description: affinity is a group of node affinity scheduling rules for - the image pruner pod. - type: object - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for the pod. - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes - that satisfy the affinity expressions specified by this field, - but it may choose a node that violates one or more of the - expressions. The node that is most preferred is the one with - the greatest sum of weights, i.e. for each node that meets - all of the scheduling requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating through - the elements of this field and adding "weight" to the sum - if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - type: array - items: - description: An empty preferred scheduling term matches all - objects with implicit weight 0 (i.e. it's a no-op). A null - preferred scheduling term matches no objects (i.e. is also - a no-op). - type: object - required: - - preference - - weight - properties: - preference: - description: A node selector term, associated with the - corresponding weight. - type: object - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - type: array - items: - description: A node selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the - operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be - empty. If the operator is Gt or Lt, the values - array must have a single element, which will - be interpreted as an integer. This array is - replaced during a strategic merge patch. - type: array - items: + versions: + - name: v1 + served: true + storage: true + subresources: + status: {} + "schema": + "openAPIV3Schema": + description: ImagePruner is the configuration object for an image registry + pruner managed by the registry operator. + type: object + required: + - metadata + - spec + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ImagePrunerSpec defines the specs for the running image pruner. + type: object + properties: + affinity: + description: affinity is a group of node affinity scheduling rules + for the image pruner pod. + type: object + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for the + pod. + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node matches + the corresponding matchExpressions; the node(s) with the + highest sum are the most preferred. + type: array + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects (i.e. + is also a no-op). + type: object + required: + - preference + - weight + properties: + preference: + description: A node selector term, associated with the + corresponding weight. + type: object + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + type: array + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector + applies to. type: string - matchFields: - description: A list of node selector requirements - by node's fields. - type: array - items: - description: A node selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the - operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be - empty. If the operator is Gt or Lt, the values - array must have a single element, which will - be interpreted as an integer. This array is - replaced during a strategic merge patch. - type: array - items: + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. type: string - weight: - description: Weight associated with matching the corresponding - nodeSelectorTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this - field are not met at scheduling time, the pod will not be - scheduled onto the node. If the affinity requirements specified - by this field cease to be met at some point during pod execution - (e.g. due to an update), the system may or may not try to - eventually evict the pod from its node. - type: object - required: - - nodeSelectorTerms - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. The - terms are ORed. - type: array - items: - description: A null or empty node selector term matches - no objects. The requirements of them are ANDed. The - TopologySelectorTerm type implements a subset of the - NodeSelectorTerm. - type: object - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - type: array - items: - description: A node selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the - operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be - empty. If the operator is Gt or Lt, the values - array must have a single element, which will - be interpreted as an integer. This array is - replaced during a strategic merge patch. - type: array - items: + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + type: array + items: + type: string + matchFields: + description: A list of node selector requirements + by node's fields. + type: array + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector + applies to. type: string - matchFields: - description: A list of node selector requirements - by node's fields. - type: array - items: - description: A node selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: Represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: An array of string values. If the - operator is In or NotIn, the values array - must be non-empty. If the operator is Exists - or DoesNotExist, the values array must be - empty. If the operator is Gt or Lt, the values - array must have a single element, which will - be interpreted as an integer. This array is - replaced during a strategic merge patch. - type: array - items: + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. type: string - podAffinity: - description: Describes pod affinity scheduling rules (e.g. co-locate - this pod in the same node, zone, etc. as some other pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes - that satisfy the affinity expressions specified by this field, - but it may choose a node that violates one or more of the - expressions. The node that is most preferred is the one with - the greatest sum of weights, i.e. for each node that meets - all of the scheduling requirements (resource request, requiredDuringScheduling - affinity expressions, etc.), compute a sum by iterating through - the elements of this field and adding "weight" to the sum - if the node has pods which matches the corresponding podAffinityTerm; - the node(s) with the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred node(s) + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + type: array + items: + type: string + weight: + description: Weight associated with matching the corresponding + nodeSelectorTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to an update), the system may or may not try to + eventually evict the pod from its node. type: object required: - - podAffinityTerm - - weight + - nodeSelectorTerms properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - type: array - items: - description: A label selector requirement is - a selector that contains values, a key, and - an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and DoesNotExist. + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + type: array + items: + description: A null or empty node selector term matches + no objects. The requirements of them are ANDed. The + TopologySelectorTerm type implements a subset of the + NodeSelectorTerm. + type: object + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + type: array + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + type: array + items: type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. If - the operator is Exists or DoesNotExist, - the values array must be empty. This array - is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is "In", - and the values array contains only "value". - The requirements are ANDed. + matchFields: + description: A list of node selector requirements + by node's fields. + type: array + items: + description: A node selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. type: object - additionalProperties: - type: string - namespaces: - description: namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey matches - that of any node on which any of the selected pods - is running. Empty topologyKey is not allowed. - type: string - weight: - description: weight associated with matching the corresponding - podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the affinity requirements specified by this - field are not met at scheduling time, the pod will not be - scheduled onto the node. If the affinity requirements specified - by this field cease to be met at some point during pod execution - (e.g. due to a pod label update), the system may or may not - try to eventually evict the pod from its node. When there - are multiple elements, the lists of nodes corresponding to - each podAffinityTerm are intersected, i.e. all terms must - be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) that - this pod should be co-located (affinity) or not co-located - (anti-affinity) with, where co-located is defined as running - on a node whose value of the label with key - matches that of any node on which a pod of the set of pods - is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in - this case pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. + required: + - key + - operator + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists, DoesNotExist. Gt, and + Lt. + type: string + values: + description: An array of string values. If + the operator is In or NotIn, the values + array must be non-empty. If the operator + is Exists or DoesNotExist, the values array + must be empty. If the operator is Gt or + Lt, the values array must have a single + element, which will be interpreted as an + integer. This array is replaced during a + strategic merge patch. + type: array + items: + type: string + podAffinity: + description: Describes pod affinity scheduling rules (e.g. co-locate + this pod in the same node, zone, etc. as some other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the affinity expressions specified by + this field, but it may choose a node that violates one or + more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. type: object - required: - - key - - operator properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values - array must be non-empty. If the operator is - Exists or DoesNotExist, the values array must - be empty. This array is replaced during a - strategic merge patch. + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. type: array items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + additionalProperties: type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - additionalProperties: + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. type: string - namespaces: - description: namespaces specifies which namespaces the - labelSelector applies to (matches against); null or - empty list means "this pod's namespace" - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where - co-located is defined as running on a node whose value - of the label with key topologyKey matches that of any - node on which any of the selected pods is running. Empty - topologyKey is not allowed. - type: string - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules (e.g. - avoid putting this pod in the same node, zone, etc. as some other - pod(s)). - type: object - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: The scheduler will prefer to schedule pods to nodes - that satisfy the anti-affinity expressions specified by this - field, but it may choose a node that violates one or more - of the expressions. The node that is most preferred is the - one with the greatest sum of weights, i.e. for each node that - meets all of the scheduling requirements (resource request, - requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field - and adding "weight" to the sum if the node has pods which - matches the corresponding podAffinityTerm; the node(s) with - the highest sum are the most preferred. - type: array - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred node(s) - type: object - required: - - podAffinityTerm - - weight - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, - in this case pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - type: array - items: - description: A label selector requirement is - a selector that contains values, a key, and - an operator that relates the key and values. - type: object - required: - - key - - operator - properties: - key: - description: key is the label key that the - selector applies to. - type: string - operator: - description: operator represents a key's - relationship to a set of values. Valid - operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string - values. If the operator is In or NotIn, - the values array must be non-empty. If - the operator is Exists or DoesNotExist, - the values array must be empty. This array - is replaced during a strategic merge patch. - type: array - items: - type: string - matchLabels: - description: matchLabels is a map of {key,value} - pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, - whose key field is "key", the operator is "In", - and the values array contains only "value". - The requirements are ANDed. + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by this + field are not met at scheduling time, the pod will not be + scheduled onto the node. If the affinity requirements specified + by this field cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may or may + not try to eventually evict the pod from its node. When + there are multiple elements, the lists of nodes corresponding + to each podAffinityTerm are intersected, i.e. all terms + must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. type: object - additionalProperties: - type: string - namespaces: - description: namespaces specifies which namespaces - the labelSelector applies to (matches against); - null or empty list means "this pod's namespace" - type: array - items: - type: string - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods - matching the labelSelector in the specified namespaces, - where co-located is defined as running on a node - whose value of the label with key topologyKey matches - that of any node on which any of the selected pods - is running. Empty topologyKey is not allowed. + required: + - key + - operator + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies which namespaces the + labelSelector applies to (matches against); null or + empty list means "this pod's namespace" + type: array + items: type: string - weight: - description: weight associated with matching the corresponding - podAffinityTerm, in the range 1-100. - type: integer - format: int32 - requiredDuringSchedulingIgnoredDuringExecution: - description: If the anti-affinity requirements specified by - this field are not met at scheduling time, the pod will not - be scheduled onto the node. If the anti-affinity requirements - specified by this field cease to be met at some point during - pod execution (e.g. due to a pod label update), the system - may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding - to each podAffinityTerm are intersected, i.e. all terms must - be satisfied. - type: array - items: - description: Defines a set of pods (namely those matching - the labelSelector relative to the given namespace(s)) that - this pod should be co-located (affinity) or not co-located - (anti-affinity) with, where co-located is defined as running - on a node whose value of the label with key - matches that of any node on which a pod of the set of pods - is running - type: object - required: - - topologyKey - properties: - labelSelector: - description: A label query over a set of resources, in - this case pods. - type: object - properties: - matchExpressions: - description: matchExpressions is a list of label selector - requirements. The requirements are ANDed. - type: array - items: - description: A label selector requirement is a selector - that contains values, a key, and an operator that - relates the key and values. + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules (e.g. + avoid putting this pod in the same node, zone, etc. as some + other pod(s)). + type: object + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods to + nodes that satisfy the anti-affinity expressions specified + by this field, but it may choose a node that violates one + or more of the expressions. The node that is most preferred + is the one with the greatest sum of weights, i.e. for each + node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, + etc.), compute a sum by iterating through the elements of + this field and adding "weight" to the sum if the node has + pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + type: array + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred node(s) + type: object + required: + - podAffinityTerm + - weight + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. type: object - required: - - key - - operator properties: - key: - description: key is the label key that the selector - applies to. - type: string - operator: - description: operator represents a key's relationship - to a set of values. Valid operators are In, - NotIn, Exists and DoesNotExist. - type: string - values: - description: values is an array of string values. - If the operator is In or NotIn, the values - array must be non-empty. If the operator is - Exists or DoesNotExist, the values array must - be empty. This array is replaced during a - strategic merge patch. + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. type: array items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + additionalProperties: type: string - matchLabels: - description: matchLabels is a map of {key,value} pairs. - A single {key,value} in the matchLabels map is equivalent - to an element of matchExpressions, whose key field - is "key", the operator is "In", and the values array - contains only "value". The requirements are ANDed. - type: object - additionalProperties: + namespaces: + description: namespaces specifies which namespaces + the labelSelector applies to (matches against); + null or empty list means "this pod's namespace" + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. type: string - namespaces: - description: namespaces specifies which namespaces the - labelSelector applies to (matches against); null or - empty list means "this pod's namespace" - type: array - items: + weight: + description: weight associated with matching the corresponding + podAffinityTerm, in the range 1-100. + type: integer + format: int32 + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the anti-affinity requirements + specified by this field cease to be met at some point during + pod execution (e.g. due to a pod label update), the system + may or may not try to eventually evict the pod from its + node. When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, i.e. + all terms must be satisfied. + type: array + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not co-located + (anti-affinity) with, where co-located is defined as running + on a node whose value of the label with key + matches that of any node on which a pod of the set of + pods is running + type: object + required: + - topologyKey + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + type: object + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are ANDed. + type: array + items: + description: A label selector requirement is a + selector that contains values, a key, and an + operator that relates the key and values. + type: object + required: + - key + - operator + properties: + key: + description: key is the label key that the + selector applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. If the + operator is Exists or DoesNotExist, the + values array must be empty. This array is + replaced during a strategic merge patch. + type: array + items: + type: string + matchLabels: + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is "In", + and the values array contains only "value". The + requirements are ANDed. + type: object + additionalProperties: + type: string + namespaces: + description: namespaces specifies which namespaces the + labelSelector applies to (matches against); null or + empty list means "this pod's namespace" + type: array + items: + type: string + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where + co-located is defined as running on a node whose value + of the label with key topologyKey matches that of + any node on which any of the selected pods is running. + Empty topologyKey is not allowed. type: string - topologyKey: - description: This pod should be co-located (affinity) - or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where - co-located is defined as running on a node whose value - of the label with key topologyKey matches that of any - node on which any of the selected pods is running. Empty - topologyKey is not allowed. - type: string - failedJobsHistoryLimit: - description: failedJobsHistoryLimit specifies how many failed image - pruner jobs to retain. Defaults to 3 if not set. - type: integer - format: int32 - ignoreInvalidImageReferences: - description: ignoreInvalidImageReferences indicates whether the pruner - can ignore errors while parsing image references. - type: boolean - keepTagRevisions: - description: keepTagRevisions specifies the number of image revisions - for a tag in an image stream that will be preserved. Defaults to 3. - type: integer - keepYoungerThan: - description: 'keepYoungerThan specifies the minimum age in nanoseconds - of an image and its referrers for it to be considered a candidate - for pruning. DEPRECATED: This field is deprecated in favor of keepYoungerThanDuration. - If both are set, this field is ignored and keepYoungerThanDuration - takes precedence.' - type: integer - format: int64 - keepYoungerThanDuration: - description: keepYoungerThanDuration specifies the minimum age of an - image and its referrers for it to be considered a candidate for pruning. - Defaults to 60m (60 minutes). - type: string - format: duration - nodeSelector: - description: nodeSelector defines the node selection constraints for - the image pruner pod. - type: object - additionalProperties: + failedJobsHistoryLimit: + description: failedJobsHistoryLimit specifies how many failed image + pruner jobs to retain. Defaults to 3 if not set. + type: integer + format: int32 + ignoreInvalidImageReferences: + description: ignoreInvalidImageReferences indicates whether the pruner + can ignore errors while parsing image references. + type: boolean + keepTagRevisions: + description: keepTagRevisions specifies the number of image revisions + for a tag in an image stream that will be preserved. Defaults to + 3. + type: integer + keepYoungerThan: + description: 'keepYoungerThan specifies the minimum age in nanoseconds + of an image and its referrers for it to be considered a candidate + for pruning. DEPRECATED: This field is deprecated in favor of keepYoungerThanDuration. + If both are set, this field is ignored and keepYoungerThanDuration + takes precedence.' + type: integer + format: int64 + keepYoungerThanDuration: + description: keepYoungerThanDuration specifies the minimum age of + an image and its referrers for it to be considered a candidate for + pruning. Defaults to 60m (60 minutes). type: string - resources: - description: resources defines the resource requests and limits for - the image pruner pod. - type: object - properties: - limits: - description: 'Limits describes the maximum amount of compute resources - allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - additionalProperties: - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - requests: - description: 'Requests describes the minimum amount of compute resources - required. If Requests is omitted for a container, it defaults - to Limits if that is explicitly specified, otherwise to an implementation-defined - value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' - type: object - additionalProperties: - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - anyOf: - - type: integer - - type: string - x-kubernetes-int-or-string: true - schedule: - description: 'schedule specifies when to execute the job using standard - cronjob syntax: https://wikipedia.org/wiki/Cron. Defaults to `0 0 - * * *`.' - type: string - successfulJobsHistoryLimit: - description: successfulJobsHistoryLimit specifies how many successful - image pruner jobs to retain. Defaults to 3 if not set. - type: integer - format: int32 - suspend: - description: suspend specifies whether or not to suspend subsequent - executions of this cronjob. Defaults to false. - type: boolean - tolerations: - description: tolerations defines the node tolerations for the image - pruner pod. - type: array - items: - description: The pod this Toleration is attached to tolerates any - taint that matches the triple using the matching - operator . + format: duration + nodeSelector: + description: nodeSelector defines the node selection constraints for + the image pruner pod. type: object - properties: - effect: - description: Effect indicates the taint effect to match. Empty - means match all taint effects. When specified, allowed values - are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: Key is the taint key that the toleration applies - to. Empty means match all taint keys. If the key is empty, operator - must be Exists; this combination means to match all values and - all keys. - type: string - operator: - description: Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. Exists - is equivalent to wildcard for value, so that a pod can tolerate - all taints of a particular category. - type: string - tolerationSeconds: - description: TolerationSeconds represents the period of time the - toleration (which must be of effect NoExecute, otherwise this - field is ignored) tolerates the taint. By default, it is not - set, which means tolerate the taint forever (do not evict). - Zero and negative values will be treated as 0 (evict immediately) - by the system. - type: integer - format: int64 - value: - description: Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise - just a regular string. - type: string - status: - description: ImagePrunerStatus reports image pruner operational status. - type: object - properties: - conditions: - description: conditions is a list of conditions and their status. - type: array - items: - description: OperatorCondition is just the standard condition fields. + additionalProperties: + type: string + resources: + description: resources defines the resource requests and limits for + the image pruner pod. type: object properties: - lastTransitionTime: - type: string - format: date-time - message: - type: string - reason: - type: string - status: - type: string - type: - type: string - observedGeneration: - description: observedGeneration is the last generation change that has - been applied. - type: integer - format: int64 + limits: + description: 'Limits describes the maximum amount of compute resources + allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + additionalProperties: + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + requests: + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/' + type: object + additionalProperties: + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + schedule: + description: 'schedule specifies when to execute the job using standard + cronjob syntax: https://wikipedia.org/wiki/Cron. Defaults to `0 + 0 * * *`.' + type: string + successfulJobsHistoryLimit: + description: successfulJobsHistoryLimit specifies how many successful + image pruner jobs to retain. Defaults to 3 if not set. + type: integer + format: int32 + suspend: + description: suspend specifies whether or not to suspend subsequent + executions of this cronjob. Defaults to false. + type: boolean + tolerations: + description: tolerations defines the node tolerations for the image + pruner pod. + type: array + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + type: object + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + type: integer + format: int64 + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + status: + description: ImagePrunerStatus reports image pruner operational status. + type: object + properties: + conditions: + description: conditions is a list of conditions and their status. + type: array + items: + description: OperatorCondition is just the standard condition fields. + type: object + properties: + lastTransitionTime: + type: string + format: date-time + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + observedGeneration: + description: observedGeneration is the last generation change that + has been applied. + type: integer + format: int64 + names: + kind: ImagePruner + listKind: ImagePrunerList + plural: imagepruners + singular: imagepruner diff --git a/vendor/github.com/openshift/api/imageregistry/v1/types.go b/vendor/github.com/openshift/api/imageregistry/v1/types.go index 9992bc12f5..a9988843a4 100644 --- a/vendor/github.com/openshift/api/imageregistry/v1/types.go +++ b/vendor/github.com/openshift/api/imageregistry/v1/types.go @@ -41,6 +41,8 @@ type Config struct { // ImageRegistrySpec defines the specs for the running registry. type ImageRegistrySpec struct { + // operatorSpec allows operator specific configuration to be made. + operatorv1.OperatorSpec `json:",inline"` // managementState indicates whether the registry instance represented // by this config instance is under operator management or not. Valid // values are Managed, Unmanaged, and Removed. @@ -78,8 +80,9 @@ type ImageRegistrySpec struct { Routes []ImageRegistryConfigRoute `json:"routes,omitempty"` // replicas determines the number of registry instances to run. Replicas int32 `json:"replicas"` - // logging determines the level of logging enabled in the registry. - LogLevel int64 `json:"logging"` + // logging is deprecated, use logLevel instead. + // +optional + Logging int64 `json:"logging"` // resources defines the resource requests+limits for the registry pod. // +optional Resources *corev1.ResourceRequirements `json:"resources,omitempty"` diff --git a/vendor/github.com/openshift/api/imageregistry/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/imageregistry/v1/zz_generated.deepcopy.go index a58aa3bc6d..87074c50c0 100644 --- a/vendor/github.com/openshift/api/imageregistry/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/imageregistry/v1/zz_generated.deepcopy.go @@ -463,6 +463,7 @@ func (in *ImageRegistryConfigStorageSwift) DeepCopy() *ImageRegistryConfigStorag // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImageRegistrySpec) DeepCopyInto(out *ImageRegistrySpec) { *out = *in + in.OperatorSpec.DeepCopyInto(&out.OperatorSpec) out.Proxy = in.Proxy in.Storage.DeepCopyInto(&out.Storage) out.Requests = in.Requests diff --git a/vendor/github.com/openshift/api/imageregistry/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/imageregistry/v1/zz_generated.swagger_doc_generated.go index 5955424e5d..0084cc3669 100644 --- a/vendor/github.com/openshift/api/imageregistry/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/imageregistry/v1/zz_generated.swagger_doc_generated.go @@ -180,7 +180,7 @@ var map_ImageRegistrySpec = map[string]string{ "defaultRoute": "defaultRoute indicates whether an external facing route for the registry should be created using the default generated hostname.", "routes": "routes defines additional external facing routes which should be created for the registry.", "replicas": "replicas determines the number of registry instances to run.", - "logging": "logging determines the level of logging enabled in the registry.", + "logging": "logging is deprecated, use logLevel instead.", "resources": "resources defines the resource requests+limits for the registry pod.", "nodeSelector": "nodeSelector defines the node selection constraints for the registry pod.", "tolerations": "tolerations defines the tolerations for the registry pod.", diff --git a/vendor/github.com/openshift/library-go/pkg/controller/factory/base_controller.go b/vendor/github.com/openshift/library-go/pkg/controller/factory/base_controller.go new file mode 100644 index 0000000000..95c7855160 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/controller/factory/base_controller.go @@ -0,0 +1,227 @@ +package factory + +import ( + "context" + "errors" + "fmt" + "sync" + "time" + + "github.com/robfig/cron" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + operatorv1 "github.com/openshift/api/operator/v1" + + "github.com/openshift/library-go/pkg/operator/v1helpers" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +// SyntheticRequeueError can be returned from sync() in case of forcing a sync() retry artificially. +// This can be also done by re-adding the key to queue, but this is cheaper and more convenient. +var SyntheticRequeueError = errors.New("synthetic requeue request") + +// baseController represents generic Kubernetes controller boiler-plate +type baseController struct { + name string + cachesToSync []cache.InformerSynced + sync func(ctx context.Context, controllerContext SyncContext) error + syncContext SyncContext + syncDegradedClient operatorv1helpers.OperatorClient + resyncEvery time.Duration + resyncSchedules []cron.Schedule + postStartHooks []PostStartHook +} + +var _ Controller = &baseController{} + +func (c baseController) Name() string { + return c.name +} + +type scheduledJob struct { + queue workqueue.RateLimitingInterface + name string +} + +func newScheduledJob(name string, queue workqueue.RateLimitingInterface) cron.Job { + return &scheduledJob{ + queue: queue, + name: name, + } +} + +func (s *scheduledJob) Run() { + klog.V(4).Infof("Triggering scheduled %q controller run", s.name) + s.queue.Add(DefaultQueueKey) +} + +func (c *baseController) Run(ctx context.Context, workers int) { + // HandleCrash recovers panics + defer utilruntime.HandleCrash() + if !cache.WaitForNamedCacheSync(c.name, ctx.Done(), c.cachesToSync...) { + panic("timeout waiting for informer cache") // this will be recovered using HandleCrash() + } + + var workerWg sync.WaitGroup + defer func() { + defer klog.Infof("All %s workers have been terminated", c.name) + workerWg.Wait() + }() + + // queueContext is used to track and initiate queue shutdown + queueContext, queueContextCancel := context.WithCancel(context.TODO()) + + for i := 1; i <= workers; i++ { + klog.Infof("Starting #%d worker of %s controller ...", i, c.name) + workerWg.Add(1) + go func() { + defer func() { + klog.Infof("Shutting down worker of %s controller ...", c.name) + workerWg.Done() + }() + c.runWorker(queueContext) + }() + } + + // if scheduled run is requested, run the cron scheduler + if c.resyncSchedules != nil { + scheduler := cron.New() + for _, s := range c.resyncSchedules { + scheduler.Schedule(s, newScheduledJob(c.name, c.syncContext.Queue())) + } + scheduler.Start() + defer scheduler.Stop() + } + + // runPeriodicalResync is independent from queue + if c.resyncEvery > 0 { + workerWg.Add(1) + go func() { + defer workerWg.Done() + c.runPeriodicalResync(ctx, c.resyncEvery) + }() + } + + // run post-start hooks (custom triggers, etc.) + if len(c.postStartHooks) > 0 { + var hookWg sync.WaitGroup + defer func() { + hookWg.Wait() // wait for the post-start hooks + klog.Infof("All %s post start hooks have been terminated", c.name) + }() + for i := range c.postStartHooks { + hookWg.Add(1) + go func(index int) { + defer hookWg.Done() + if err := c.postStartHooks[index](ctx, c.syncContext); err != nil { + klog.Warningf("%s controller post start hook error: %v", c.name, err) + } + }(i) + } + } + + // Handle controller shutdown + + <-ctx.Done() // wait for controller context to be cancelled + c.syncContext.Queue().ShutDown() // shutdown the controller queue first + queueContextCancel() // cancel the queue context, which tell workers to initiate shutdown + + // Wait for all workers to finish their job. + // at this point the Run() can hang and caller have to implement the logic that will kill + // this controller (SIGKILL). + klog.Infof("Shutting down %s ...", c.name) +} + +func (c *baseController) Sync(ctx context.Context, syncCtx SyncContext) error { + return c.sync(ctx, syncCtx) +} + +func (c *baseController) runPeriodicalResync(ctx context.Context, interval time.Duration) { + if interval == 0 { + return + } + go wait.UntilWithContext(ctx, func(ctx context.Context) { + c.syncContext.Queue().Add(DefaultQueueKey) + }, interval) +} + +// runWorker runs a single worker +// The worker is asked to terminate when the passed context is cancelled and is given terminationGraceDuration time +// to complete its shutdown. +func (c *baseController) runWorker(queueCtx context.Context) { + var workerWaitGroup sync.WaitGroup + workerWaitGroup.Add(1) + go func() { + defer utilruntime.HandleCrash() + defer workerWaitGroup.Done() + for { + select { + case <-queueCtx.Done(): + return + default: + c.processNextWorkItem(queueCtx) + } + } + }() + workerWaitGroup.Wait() +} + +// reconcile wraps the sync() call and if operator client is set, it handle the degraded condition if sync() returns an error. +func (c *baseController) reconcile(ctx context.Context, syncCtx SyncContext) error { + err := c.sync(ctx, syncCtx) + if c.syncDegradedClient == nil { + return err + } + if err != nil { + _, _, updateErr := v1helpers.UpdateStatus(c.syncDegradedClient, v1helpers.UpdateConditionFn(operatorv1.OperatorCondition{ + Type: c.name + "Degraded", + Status: operatorv1.ConditionTrue, + Reason: "SyncError", + Message: err.Error(), + })) + if updateErr != nil { + klog.Warningf("Updating status of %q failed: %v", c.Name(), updateErr) + } + return err + } + _, _, updateErr := v1helpers.UpdateStatus(c.syncDegradedClient, + v1helpers.UpdateConditionFn(operatorv1.OperatorCondition{ + Type: c.name + "Degraded", + Status: operatorv1.ConditionFalse, + Reason: "AsExpected", + })) + return updateErr +} + +func (c *baseController) processNextWorkItem(queueCtx context.Context) { + key, quit := c.syncContext.Queue().Get() + if quit { + return + } + defer c.syncContext.Queue().Done(key) + + syncCtx := c.syncContext.(syncContext) + var ok bool + syncCtx.queueKey, ok = key.(string) + if !ok { + utilruntime.HandleError(fmt.Errorf("%q controller failed to process key %q (not a string)", c.name, key)) + return + } + + if err := c.reconcile(queueCtx, syncCtx); err != nil { + if err == SyntheticRequeueError { + // logging this helps detecting wedged controllers with missing pre-requirements + klog.V(5).Infof("%q controller requested synthetic requeue with key %q", c.name, key) + } else { + utilruntime.HandleError(fmt.Errorf("%q controller failed to sync %q, err: %w", c.name, key, err)) + } + c.syncContext.Queue().AddRateLimited(key) + return + } + + c.syncContext.Queue().Forget(key) +} diff --git a/vendor/github.com/openshift/library-go/pkg/controller/factory/controller_context.go b/vendor/github.com/openshift/library-go/pkg/controller/factory/controller_context.go new file mode 100644 index 0000000000..67a1051844 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/controller/factory/controller_context.go @@ -0,0 +1,105 @@ +package factory + +import ( + "fmt" + "strings" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + + "github.com/openshift/library-go/pkg/operator/events" +) + +// syncContext implements SyncContext and provide user access to queue and object that caused +// the sync to be triggered. +type syncContext struct { + eventRecorder events.Recorder + queue workqueue.RateLimitingInterface + queueKey string +} + +var _ SyncContext = syncContext{} + +// NewSyncContext gives new sync context. +func NewSyncContext(name string, recorder events.Recorder) SyncContext { + return syncContext{ + queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), name), + eventRecorder: recorder.WithComponentSuffix(strings.ToLower(name)), + } +} + +func (c syncContext) Queue() workqueue.RateLimitingInterface { + return c.queue +} + +func (c syncContext) QueueKey() string { + return c.queueKey +} + +func (c syncContext) Recorder() events.Recorder { + return c.eventRecorder +} + +func (c syncContext) isInterestingNamespace(obj interface{}, interestingNamespaces sets.String) (bool, bool) { + ns, ok := obj.(*corev1.Namespace) + if !ok { + tombstone, ok := obj.(cache.DeletedFinalStateUnknown) + if ok { + if ns, ok := tombstone.Obj.(*corev1.Namespace); ok { + return true, interestingNamespaces.Has(ns.Name) + } + } + return false, false + } + return true, interestingNamespaces.Has(ns.Name) +} + +// eventHandler provides default event handler that is added to an informers passed to controller factory. +func (c syncContext) eventHandler(queueKeyFunc ObjectQueueKeyFunc, interestingNamespaces sets.String) cache.ResourceEventHandler { + return cache.ResourceEventHandlerFuncs{ + AddFunc: func(obj interface{}) { + isNamespace, isInteresting := c.isInterestingNamespace(obj, interestingNamespaces) + runtimeObj, ok := obj.(runtime.Object) + if !ok { + utilruntime.HandleError(fmt.Errorf("added object %+v is not runtime Object", obj)) + return + } + if !isNamespace || (isNamespace && isInteresting) { + c.Queue().Add(queueKeyFunc(runtimeObj)) + } + }, + UpdateFunc: func(old, new interface{}) { + isNamespace, isInteresting := c.isInterestingNamespace(new, interestingNamespaces) + runtimeObj, ok := new.(runtime.Object) + if !ok { + utilruntime.HandleError(fmt.Errorf("updated object %+v is not runtime Object", runtimeObj)) + return + } + if !isNamespace || (isNamespace && isInteresting) { + c.Queue().Add(queueKeyFunc(runtimeObj)) + } + }, + DeleteFunc: func(obj interface{}) { + isNamespace, isInteresting := c.isInterestingNamespace(obj, interestingNamespaces) + runtimeObj, ok := obj.(runtime.Object) + if !ok { + tombstone, ok := obj.(cache.DeletedFinalStateUnknown) + if ok { + if !isNamespace || (isNamespace && isInteresting) { + c.Queue().Add(queueKeyFunc(tombstone.Obj.(runtime.Object))) + } + return + } + utilruntime.HandleError(fmt.Errorf("updated object %+v is not runtime Object", runtimeObj)) + return + } + if !isNamespace || (isNamespace && isInteresting) { + c.Queue().Add(queueKeyFunc(runtimeObj)) + } + }, + } +} diff --git a/vendor/github.com/openshift/library-go/pkg/controller/factory/factory.go b/vendor/github.com/openshift/library-go/pkg/controller/factory/factory.go new file mode 100644 index 0000000000..a8b851023c --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/controller/factory/factory.go @@ -0,0 +1,231 @@ +package factory + +import ( + "context" + "fmt" + "time" + + "github.com/robfig/cron" + "k8s.io/apimachinery/pkg/runtime" + errorutil "k8s.io/apimachinery/pkg/util/errors" + "k8s.io/apimachinery/pkg/util/sets" + "k8s.io/client-go/tools/cache" + + "github.com/openshift/library-go/pkg/operator/events" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +// DefaultQueueKey is the queue key used for string trigger based controllers. +const DefaultQueueKey = "key" + +// Factory is generator that generate standard Kubernetes controllers. +// Factory is really generic and should be only used for simple controllers that does not require special stuff.. +type Factory struct { + sync SyncFunc + syncContext SyncContext + syncDegradedClient operatorv1helpers.OperatorClient + resyncInterval time.Duration + resyncSchedules []string + informers []Informer + informerQueueKeys []informersWithQueueKey + bareInformers []Informer + postStartHooks []PostStartHook + namespaceInformers []*namespaceInformer + cachesToSync []cache.InformerSynced + interestingNamespaces sets.String +} + +// Informer represents any structure that allow to register event handlers and informs if caches are synced. +// Any SharedInformer will comply. +type Informer interface { + AddEventHandler(handler cache.ResourceEventHandler) + HasSynced() bool +} + +type namespaceInformer struct { + informer Informer + namespaces sets.String +} + +type informersWithQueueKey struct { + informers []Informer + queueKeyFn ObjectQueueKeyFunc +} + +// PostStartHook specify a function that will run after controller is started. +// The context is cancelled when the controller is asked to shutdown and the post start hook should terminate as well. +// The syncContext allow access to controller queue and event recorder. +type PostStartHook func(ctx context.Context, syncContext SyncContext) error + +// ObjectQueueKeyFunc is used to make a string work queue key out of the runtime object that is passed to it. +// This can extract the "namespace/name" if you need to or just return "key" if you building controller that only use string +// triggers. +type ObjectQueueKeyFunc func(runtime.Object) string + +// New return new factory instance. +func New() *Factory { + return &Factory{} +} + +// Sync is used to set the controller synchronization function. This function is the core of the controller and is +// usually hold the main controller logic. +func (f *Factory) WithSync(syncFn SyncFunc) *Factory { + f.sync = syncFn + return f +} + +// WithInformers is used to register event handlers and get the caches synchronized functions. +// Pass informers you want to use to react to changes on resources. If informer event is observed, then the Sync() function +// is called. +func (f *Factory) WithInformers(informers ...Informer) *Factory { + f.informers = append(f.informers, informers...) + return f +} + +// WithBareInformers allow to register informer that already has custom event handlers registered and no additional +// event handlers will be added to this informer. +// The controller will wait for the cache of this informer to be synced. +// The existing event handlers will have to respect the queue key function or the sync() implementation will have to +// count with custom queue keys. +func (f *Factory) WithBareInformers(informers ...Informer) *Factory { + f.bareInformers = append(f.bareInformers, informers...) + return f +} + +// WithInformersQueueKeyFunc is used to register event handlers and get the caches synchronized functions. +// Pass informers you want to use to react to changes on resources. If informer event is observed, then the Sync() function +// is called. +// Pass the queueKeyFn you want to use to transform the informer runtime.Object into string key used by work queue. +func (f *Factory) WithInformersQueueKeyFunc(queueKeyFn ObjectQueueKeyFunc, informers ...Informer) *Factory { + f.informerQueueKeys = append(f.informerQueueKeys, informersWithQueueKey{ + informers: informers, + queueKeyFn: queueKeyFn, + }) + return f +} + +// WithPostStartHooks allows to register functions that will run asynchronously after the controller is started via Run command. +func (f *Factory) WithPostStartHooks(hooks ...PostStartHook) *Factory { + f.postStartHooks = append(f.postStartHooks, hooks...) + return f +} + +// WithNamespaceInformer is used to register event handlers and get the caches synchronized functions. +// The sync function will only trigger when the object observed by this informer is a namespace and its name matches the interestingNamespaces. +// Do not use this to register non-namespace informers. +func (f *Factory) WithNamespaceInformer(informer Informer, interestingNamespaces ...string) *Factory { + f.namespaceInformers = append(f.namespaceInformers, &namespaceInformer{ + informer: informer, + namespaces: sets.NewString(interestingNamespaces...), + }) + return f +} + +// ResyncEvery will cause the Sync() function to be called periodically, regardless of informers. +// This is useful when you want to refresh every N minutes or you fear that your informers can be stucked. +// If this is not called, no periodical resync will happen. +// Note: The controller context passed to Sync() function in this case does not contain the object metadata or object itself. +// This can be used to detect periodical resyncs, but normal Sync() have to be cautious about `nil` objects. +func (f *Factory) ResyncEvery(interval time.Duration) *Factory { + f.resyncInterval = interval + return f +} + +// ResyncSchedule allows to supply a Cron syntax schedule that will be used to schedule the sync() call runs. +// This allows more fine-tuned controller scheduling than ResyncEvery. +// Examples: +// +// factory.New().ResyncSchedule("@every 1s").ToController() // Every second +// factory.New().ResyncSchedule("@hourly").ToController() // Every hour +// factory.New().ResyncSchedule("30 * * * *").ToController() // Every hour on the half hour +// +// Note: The controller context passed to Sync() function in this case does not contain the object metadata or object itself. +// This can be used to detect periodical resyncs, but normal Sync() have to be cautious about `nil` objects. +func (f *Factory) ResyncSchedule(schedules ...string) *Factory { + f.resyncSchedules = append(f.resyncSchedules, schedules...) + return f +} + +// WithSyncContext allows to specify custom, existing sync context for this factory. +// This is useful during unit testing where you can override the default event recorder or mock the runtime objects. +// If this function not called, a SyncContext is created by the factory automatically. +func (f *Factory) WithSyncContext(ctx SyncContext) *Factory { + f.syncContext = ctx + return f +} + +// WithSyncDegradedOnError encapsulate the controller sync() function, so when this function return an error, the operator client +// is used to set the degraded condition to (eg. "ControllerFooDegraded"). The degraded condition name is set based on the controller name. +func (f *Factory) WithSyncDegradedOnError(operatorClient operatorv1helpers.OperatorClient) *Factory { + f.syncDegradedClient = operatorClient + return f +} + +// Controller produce a runnable controller. +func (f *Factory) ToController(name string, eventRecorder events.Recorder) Controller { + if f.sync == nil { + panic(fmt.Errorf("WithSync() must be used before calling ToController() in %q", name)) + } + + var ctx SyncContext + if f.syncContext != nil { + ctx = f.syncContext + } else { + ctx = NewSyncContext(name, eventRecorder) + } + + var cronSchedules []cron.Schedule + if len(f.resyncSchedules) > 0 { + var errors []error + for _, schedule := range f.resyncSchedules { + if s, err := cron.ParseStandard(schedule); err != nil { + errors = append(errors, err) + } else { + cronSchedules = append(cronSchedules, s) + } + } + if err := errorutil.NewAggregate(errors); err != nil { + panic(fmt.Errorf("failed to parse controller schedules for %q: %v", name, err)) + } + } + + c := &baseController{ + name: name, + syncDegradedClient: f.syncDegradedClient, + sync: f.sync, + resyncEvery: f.resyncInterval, + resyncSchedules: cronSchedules, + cachesToSync: append([]cache.InformerSynced{}, f.cachesToSync...), + syncContext: ctx, + postStartHooks: f.postStartHooks, + } + + for i := range f.informerQueueKeys { + for d := range f.informerQueueKeys[i].informers { + informer := f.informerQueueKeys[i].informers[d] + queueKeyFn := f.informerQueueKeys[i].queueKeyFn + informer.AddEventHandler(c.syncContext.(syncContext).eventHandler(queueKeyFn, sets.NewString())) + c.cachesToSync = append(c.cachesToSync, informer.HasSynced) + } + } + + for i := range f.informers { + f.informers[i].AddEventHandler(c.syncContext.(syncContext).eventHandler(func(runtime.Object) string { + return DefaultQueueKey + }, sets.NewString())) + c.cachesToSync = append(c.cachesToSync, f.informers[i].HasSynced) + } + + for i := range f.bareInformers { + c.cachesToSync = append(c.cachesToSync, f.bareInformers[i].HasSynced) + } + + for i := range f.namespaceInformers { + f.namespaceInformers[i].informer.AddEventHandler(c.syncContext.(syncContext).eventHandler(func(runtime.Object) string { + return DefaultQueueKey + }, f.namespaceInformers[i].namespaces)) + c.cachesToSync = append(c.cachesToSync, f.namespaceInformers[i].informer.HasSynced) + } + + return c +} diff --git a/vendor/github.com/openshift/library-go/pkg/controller/factory/interfaces.go b/vendor/github.com/openshift/library-go/pkg/controller/factory/interfaces.go new file mode 100644 index 0000000000..0ef98c6701 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/controller/factory/interfaces.go @@ -0,0 +1,47 @@ +package factory + +import ( + "context" + + "k8s.io/client-go/util/workqueue" + + "github.com/openshift/library-go/pkg/operator/events" +) + +// Controller interface represents a runnable Kubernetes controller. +// Cancelling the syncContext passed will cause the controller to shutdown. +// Number of workers determine how much parallel the job processing should be. +type Controller interface { + // Run runs the controller and blocks until the controller is finished. + // Number of workers can be specified via workers parameter. + // This function will return when all internal loops are finished. + // Note that having more than one worker usually means handing parallelization of Sync(). + Run(ctx context.Context, workers int) + + // Sync contain the main controller logic. + // This should not be called directly, but can be used in unit tests to exercise the sync. + Sync(ctx context.Context, controllerContext SyncContext) error + + // Name returns the controller name string. + Name() string +} + +// SyncContext interface represents a context given to the Sync() function where the main controller logic happen. +// SyncContext exposes controller name and give user access to the queue (for manual requeue). +// SyncContext also provides metadata about object that informers observed as changed. +type SyncContext interface { + // Queue gives access to controller queue. This can be used for manual requeue, although if a Sync() function return + // an error, the object is automatically re-queued. Use with caution. + Queue() workqueue.RateLimitingInterface + + // QueueKey represents the queue key passed to the Sync function. + QueueKey() string + + // Recorder provide access to event recorder. + Recorder() events.Recorder +} + +// SyncFunc is a function that contain main controller logic. +// The syncContext.syncContext passed is the main controller syncContext, when cancelled it means the controller is being shut down. +// The syncContext provides access to controller name, queue and event recorder. +type SyncFunc func(ctx context.Context, controllerContext SyncContext) error diff --git a/vendor/github.com/openshift/library-go/pkg/operator/loglevel/logging_controller.go b/vendor/github.com/openshift/library-go/pkg/operator/loglevel/logging_controller.go new file mode 100644 index 0000000000..8f166ce770 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/loglevel/logging_controller.go @@ -0,0 +1,77 @@ +package loglevel + +import ( + "context" + + operatorv1 "github.com/openshift/api/operator/v1" + "github.com/openshift/library-go/pkg/controller/factory" + "github.com/openshift/library-go/pkg/operator/events" + operatorv1helpers "github.com/openshift/library-go/pkg/operator/v1helpers" +) + +type LogLevelController struct { + operatorClient operatorv1helpers.OperatorClient + + // for unit tests only + setLogLevelFn func(operatorv1.LogLevel) error + getLogLevelFn func() (operatorv1.LogLevel, bool) + + defaultLogLevel operatorv1.LogLevel +} + +// NewClusterOperatorLoggingController sets a klog level for the operator based on the operator config. +// If the loglevel is not set the default "Normal" level will be used. +func NewClusterOperatorLoggingController(operatorClient operatorv1helpers.OperatorClient, recorder events.Recorder) factory.Controller { + return NewClusterOperatorLoggingControllerWithLogLevel(operatorClient, operatorv1.Normal, recorder) +} + +// NewClusterOperatorLoggingControllerWithLogLevel sets a klog level for the operator based on the operator config, using the given default log level if the operator config does not specify anything +func NewClusterOperatorLoggingControllerWithLogLevel(operatorClient operatorv1helpers.OperatorClient, defaultLogLevel operatorv1.LogLevel, recorder events.Recorder) factory.Controller { + c := &LogLevelController{ + operatorClient: operatorClient, + setLogLevelFn: SetLogLEvel, + getLogLevelFn: GetLogLevel, + defaultLogLevel: defaultLogLevel, + } + return factory.New().WithInformers(operatorClient.Informer()).WithSync(c.sync).ToController("LoggingSyncer", recorder) +} + +// sync reacts to a change in prereqs by finding information that is required to match another value in the cluster. This +// must be information that is logically "owned" by another component. +func (c LogLevelController) sync(ctx context.Context, syncCtx factory.SyncContext) error { + detailedSpec, _, _, err := c.operatorClient.GetOperatorState() + if err != nil { + return err + } + + currentLogLevel, isUnknown := c.getLogLevelFn() + desiredLogLevel := detailedSpec.OperatorLogLevel + + if len(desiredLogLevel) == 0 { + desiredLogLevel = c.defaultLogLevel + } + + // correct log level is set and it matches the expected log level from operator operatorSpec, do nothing. + if !isUnknown && currentLogLevel == desiredLogLevel { + return nil + } + + // log level is not specified in operatorSpec and the log verbosity is not set (0), default the log level to V(2). + if len(desiredLogLevel) == 0 { + desiredLogLevel = currentLogLevel + } + + // Set the new loglevel if the operator operatorSpec changed + if err := c.setLogLevelFn(desiredLogLevel); err != nil { + syncCtx.Recorder().Warningf("OperatorLogLevelChangeFailed", "Unable to change operator log level from %q to %q: %v", currentLogLevel, desiredLogLevel, err) + return err + } + + // Do not fire event on every restart. + if isUnknown { + return nil + } + + syncCtx.Recorder().Eventf("OperatorLogLevelChange", "Operator log level changed from %q to %q", currentLogLevel, desiredLogLevel) + return nil +} diff --git a/vendor/github.com/openshift/library-go/pkg/operator/loglevel/util.go b/vendor/github.com/openshift/library-go/pkg/operator/loglevel/util.go new file mode 100644 index 0000000000..be8fc69d91 --- /dev/null +++ b/vendor/github.com/openshift/library-go/pkg/operator/loglevel/util.go @@ -0,0 +1,90 @@ +package loglevel + +import ( + "flag" + "fmt" + + "k8s.io/klog/v2" + + operatorv1 "github.com/openshift/api/operator/v1" +) + +// LogLevelToVerbosity transforms operator log level to a klog numeric verbosity level. +func LogLevelToVerbosity(logLevel operatorv1.LogLevel) int { + switch logLevel { + case operatorv1.Normal: + return 2 + case operatorv1.Debug: + return 4 + case operatorv1.Trace: + return 6 + case operatorv1.TraceAll: + return 8 + default: + return 2 + } +} + +// verbosityFn is exported so it can be unit tested +var verbosityFn = klog.V + +// GetLogLevel attempts to guess the current log level that is used by klog. +// The bool value returned determine whether we were able to determine the current log level or not. +// We can use flags here as well, but this is less ugly ano more programmatically correct than flags. +func GetLogLevel() (operatorv1.LogLevel, bool) { + switch { + case verbosityFn(8).Enabled(): + return operatorv1.TraceAll, false + case verbosityFn(6).Enabled(): + return operatorv1.Trace, false + case verbosityFn(4).Enabled(): + return operatorv1.Debug, false + case verbosityFn(2).Enabled(): + return operatorv1.Normal, false + default: + // this is the default log level that will be set if the operator operatorSpec does not specify one (2). + return operatorv1.Normal, true + } +} + +// SetLogLEvel is a nasty hack and attempt to manipulate the global flags as klog does not expose +// a way to dynamically change the loglevel in runtime. +func SetLogLEvel(targetLevel operatorv1.LogLevel) error { + var level *klog.Level + + // Convert operator loglevel to klog numeric string + verbosity := fmt.Sprintf("%d", LogLevelToVerbosity(targetLevel)) + + // First, if the '-v' was specified in command line, attempt to acquire the level pointer from it. + if f := flag.CommandLine.Lookup("v"); f != nil { + if flagValue, ok := f.Value.(*klog.Level); ok { + level = flagValue + } + } + + // Second, if the '-v' was not set but is still present in flags defined for the command, attempt to acquire it + // by visiting all flags. + if level == nil { + flag.VisitAll(func(f *flag.Flag) { + if level != nil { + return + } + if levelFlag, ok := f.Value.(*klog.Level); ok { + level = levelFlag + } + }) + } + + if level != nil { + return level.Set(verbosity) + } + + // Third, if modifying the flag value (which is recommended by klog) fails, then fallback to modifying + // the internal state of klog using the empty new level. + var newLevel klog.Level + if err := newLevel.Set(verbosity); err != nil { + return fmt.Errorf("failed set klog.logging.verbosity %s: %v", verbosity, err) + } + + return nil +} diff --git a/vendor/github.com/robfig/cron/.gitignore b/vendor/github.com/robfig/cron/.gitignore new file mode 100644 index 0000000000..00268614f0 --- /dev/null +++ b/vendor/github.com/robfig/cron/.gitignore @@ -0,0 +1,22 @@ +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe diff --git a/vendor/github.com/robfig/cron/.travis.yml b/vendor/github.com/robfig/cron/.travis.yml new file mode 100644 index 0000000000..4f2ee4d973 --- /dev/null +++ b/vendor/github.com/robfig/cron/.travis.yml @@ -0,0 +1 @@ +language: go diff --git a/vendor/github.com/robfig/cron/LICENSE b/vendor/github.com/robfig/cron/LICENSE new file mode 100644 index 0000000000..3a0f627ffe --- /dev/null +++ b/vendor/github.com/robfig/cron/LICENSE @@ -0,0 +1,21 @@ +Copyright (C) 2012 Rob Figueiredo +All Rights Reserved. + +MIT LICENSE + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/vendor/github.com/robfig/cron/README.md b/vendor/github.com/robfig/cron/README.md new file mode 100644 index 0000000000..ec40c95fcb --- /dev/null +++ b/vendor/github.com/robfig/cron/README.md @@ -0,0 +1,6 @@ +[![GoDoc](http://godoc.org/github.com/robfig/cron?status.png)](http://godoc.org/github.com/robfig/cron) +[![Build Status](https://travis-ci.org/robfig/cron.svg?branch=master)](https://travis-ci.org/robfig/cron) + +# cron + +Documentation here: https://godoc.org/github.com/robfig/cron diff --git a/vendor/github.com/robfig/cron/constantdelay.go b/vendor/github.com/robfig/cron/constantdelay.go new file mode 100644 index 0000000000..cd6e7b1be9 --- /dev/null +++ b/vendor/github.com/robfig/cron/constantdelay.go @@ -0,0 +1,27 @@ +package cron + +import "time" + +// ConstantDelaySchedule represents a simple recurring duty cycle, e.g. "Every 5 minutes". +// It does not support jobs more frequent than once a second. +type ConstantDelaySchedule struct { + Delay time.Duration +} + +// Every returns a crontab Schedule that activates once every duration. +// Delays of less than a second are not supported (will round up to 1 second). +// Any fields less than a Second are truncated. +func Every(duration time.Duration) ConstantDelaySchedule { + if duration < time.Second { + duration = time.Second + } + return ConstantDelaySchedule{ + Delay: duration - time.Duration(duration.Nanoseconds())%time.Second, + } +} + +// Next returns the next time this should be run. +// This rounds so that the next activation time will be on the second. +func (schedule ConstantDelaySchedule) Next(t time.Time) time.Time { + return t.Add(schedule.Delay - time.Duration(t.Nanosecond())*time.Nanosecond) +} diff --git a/vendor/github.com/robfig/cron/cron.go b/vendor/github.com/robfig/cron/cron.go new file mode 100644 index 0000000000..2318aeb2e7 --- /dev/null +++ b/vendor/github.com/robfig/cron/cron.go @@ -0,0 +1,259 @@ +package cron + +import ( + "log" + "runtime" + "sort" + "time" +) + +// Cron keeps track of any number of entries, invoking the associated func as +// specified by the schedule. It may be started, stopped, and the entries may +// be inspected while running. +type Cron struct { + entries []*Entry + stop chan struct{} + add chan *Entry + snapshot chan []*Entry + running bool + ErrorLog *log.Logger + location *time.Location +} + +// Job is an interface for submitted cron jobs. +type Job interface { + Run() +} + +// The Schedule describes a job's duty cycle. +type Schedule interface { + // Return the next activation time, later than the given time. + // Next is invoked initially, and then each time the job is run. + Next(time.Time) time.Time +} + +// Entry consists of a schedule and the func to execute on that schedule. +type Entry struct { + // The schedule on which this job should be run. + Schedule Schedule + + // The next time the job will run. This is the zero time if Cron has not been + // started or this entry's schedule is unsatisfiable + Next time.Time + + // The last time this job was run. This is the zero time if the job has never + // been run. + Prev time.Time + + // The Job to run. + Job Job +} + +// byTime is a wrapper for sorting the entry array by time +// (with zero time at the end). +type byTime []*Entry + +func (s byTime) Len() int { return len(s) } +func (s byTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s byTime) Less(i, j int) bool { + // Two zero times should return false. + // Otherwise, zero is "greater" than any other time. + // (To sort it at the end of the list.) + if s[i].Next.IsZero() { + return false + } + if s[j].Next.IsZero() { + return true + } + return s[i].Next.Before(s[j].Next) +} + +// New returns a new Cron job runner, in the Local time zone. +func New() *Cron { + return NewWithLocation(time.Now().Location()) +} + +// NewWithLocation returns a new Cron job runner. +func NewWithLocation(location *time.Location) *Cron { + return &Cron{ + entries: nil, + add: make(chan *Entry), + stop: make(chan struct{}), + snapshot: make(chan []*Entry), + running: false, + ErrorLog: nil, + location: location, + } +} + +// A wrapper that turns a func() into a cron.Job +type FuncJob func() + +func (f FuncJob) Run() { f() } + +// AddFunc adds a func to the Cron to be run on the given schedule. +func (c *Cron) AddFunc(spec string, cmd func()) error { + return c.AddJob(spec, FuncJob(cmd)) +} + +// AddJob adds a Job to the Cron to be run on the given schedule. +func (c *Cron) AddJob(spec string, cmd Job) error { + schedule, err := Parse(spec) + if err != nil { + return err + } + c.Schedule(schedule, cmd) + return nil +} + +// Schedule adds a Job to the Cron to be run on the given schedule. +func (c *Cron) Schedule(schedule Schedule, cmd Job) { + entry := &Entry{ + Schedule: schedule, + Job: cmd, + } + if !c.running { + c.entries = append(c.entries, entry) + return + } + + c.add <- entry +} + +// Entries returns a snapshot of the cron entries. +func (c *Cron) Entries() []*Entry { + if c.running { + c.snapshot <- nil + x := <-c.snapshot + return x + } + return c.entrySnapshot() +} + +// Location gets the time zone location +func (c *Cron) Location() *time.Location { + return c.location +} + +// Start the cron scheduler in its own go-routine, or no-op if already started. +func (c *Cron) Start() { + if c.running { + return + } + c.running = true + go c.run() +} + +// Run the cron scheduler, or no-op if already running. +func (c *Cron) Run() { + if c.running { + return + } + c.running = true + c.run() +} + +func (c *Cron) runWithRecovery(j Job) { + defer func() { + if r := recover(); r != nil { + const size = 64 << 10 + buf := make([]byte, size) + buf = buf[:runtime.Stack(buf, false)] + c.logf("cron: panic running job: %v\n%s", r, buf) + } + }() + j.Run() +} + +// Run the scheduler. this is private just due to the need to synchronize +// access to the 'running' state variable. +func (c *Cron) run() { + // Figure out the next activation times for each entry. + now := c.now() + for _, entry := range c.entries { + entry.Next = entry.Schedule.Next(now) + } + + for { + // Determine the next entry to run. + sort.Sort(byTime(c.entries)) + + var timer *time.Timer + if len(c.entries) == 0 || c.entries[0].Next.IsZero() { + // If there are no entries yet, just sleep - it still handles new entries + // and stop requests. + timer = time.NewTimer(100000 * time.Hour) + } else { + timer = time.NewTimer(c.entries[0].Next.Sub(now)) + } + + for { + select { + case now = <-timer.C: + now = now.In(c.location) + // Run every entry whose next time was less than now + for _, e := range c.entries { + if e.Next.After(now) || e.Next.IsZero() { + break + } + go c.runWithRecovery(e.Job) + e.Prev = e.Next + e.Next = e.Schedule.Next(now) + } + + case newEntry := <-c.add: + timer.Stop() + now = c.now() + newEntry.Next = newEntry.Schedule.Next(now) + c.entries = append(c.entries, newEntry) + + case <-c.snapshot: + c.snapshot <- c.entrySnapshot() + continue + + case <-c.stop: + timer.Stop() + return + } + + break + } + } +} + +// Logs an error to stderr or to the configured error log +func (c *Cron) logf(format string, args ...interface{}) { + if c.ErrorLog != nil { + c.ErrorLog.Printf(format, args...) + } else { + log.Printf(format, args...) + } +} + +// Stop stops the cron scheduler if it is running; otherwise it does nothing. +func (c *Cron) Stop() { + if !c.running { + return + } + c.stop <- struct{}{} + c.running = false +} + +// entrySnapshot returns a copy of the current cron entry list. +func (c *Cron) entrySnapshot() []*Entry { + entries := []*Entry{} + for _, e := range c.entries { + entries = append(entries, &Entry{ + Schedule: e.Schedule, + Next: e.Next, + Prev: e.Prev, + Job: e.Job, + }) + } + return entries +} + +// now returns current time in c location +func (c *Cron) now() time.Time { + return time.Now().In(c.location) +} diff --git a/vendor/github.com/robfig/cron/doc.go b/vendor/github.com/robfig/cron/doc.go new file mode 100644 index 0000000000..d02ec2f3b5 --- /dev/null +++ b/vendor/github.com/robfig/cron/doc.go @@ -0,0 +1,129 @@ +/* +Package cron implements a cron spec parser and job runner. + +Usage + +Callers may register Funcs to be invoked on a given schedule. Cron will run +them in their own goroutines. + + c := cron.New() + c.AddFunc("0 30 * * * *", func() { fmt.Println("Every hour on the half hour") }) + c.AddFunc("@hourly", func() { fmt.Println("Every hour") }) + c.AddFunc("@every 1h30m", func() { fmt.Println("Every hour thirty") }) + c.Start() + .. + // Funcs are invoked in their own goroutine, asynchronously. + ... + // Funcs may also be added to a running Cron + c.AddFunc("@daily", func() { fmt.Println("Every day") }) + .. + // Inspect the cron job entries' next and previous run times. + inspect(c.Entries()) + .. + c.Stop() // Stop the scheduler (does not stop any jobs already running). + +CRON Expression Format + +A cron expression represents a set of times, using 6 space-separated fields. + + Field name | Mandatory? | Allowed values | Allowed special characters + ---------- | ---------- | -------------- | -------------------------- + Seconds | Yes | 0-59 | * / , - + Minutes | Yes | 0-59 | * / , - + Hours | Yes | 0-23 | * / , - + Day of month | Yes | 1-31 | * / , - ? + Month | Yes | 1-12 or JAN-DEC | * / , - + Day of week | Yes | 0-6 or SUN-SAT | * / , - ? + +Note: Month and Day-of-week field values are case insensitive. "SUN", "Sun", +and "sun" are equally accepted. + +Special Characters + +Asterisk ( * ) + +The asterisk indicates that the cron expression will match for all values of the +field; e.g., using an asterisk in the 5th field (month) would indicate every +month. + +Slash ( / ) + +Slashes are used to describe increments of ranges. For example 3-59/15 in the +1st field (minutes) would indicate the 3rd minute of the hour and every 15 +minutes thereafter. The form "*\/..." is equivalent to the form "first-last/...", +that is, an increment over the largest possible range of the field. The form +"N/..." is accepted as meaning "N-MAX/...", that is, starting at N, use the +increment until the end of that specific range. It does not wrap around. + +Comma ( , ) + +Commas are used to separate items of a list. For example, using "MON,WED,FRI" in +the 5th field (day of week) would mean Mondays, Wednesdays and Fridays. + +Hyphen ( - ) + +Hyphens are used to define ranges. For example, 9-17 would indicate every +hour between 9am and 5pm inclusive. + +Question mark ( ? ) + +Question mark may be used instead of '*' for leaving either day-of-month or +day-of-week blank. + +Predefined schedules + +You may use one of several pre-defined schedules in place of a cron expression. + + Entry | Description | Equivalent To + ----- | ----------- | ------------- + @yearly (or @annually) | Run once a year, midnight, Jan. 1st | 0 0 0 1 1 * + @monthly | Run once a month, midnight, first of month | 0 0 0 1 * * + @weekly | Run once a week, midnight between Sat/Sun | 0 0 0 * * 0 + @daily (or @midnight) | Run once a day, midnight | 0 0 0 * * * + @hourly | Run once an hour, beginning of hour | 0 0 * * * * + +Intervals + +You may also schedule a job to execute at fixed intervals, starting at the time it's added +or cron is run. This is supported by formatting the cron spec like this: + + @every + +where "duration" is a string accepted by time.ParseDuration +(http://golang.org/pkg/time/#ParseDuration). + +For example, "@every 1h30m10s" would indicate a schedule that activates after +1 hour, 30 minutes, 10 seconds, and then every interval after that. + +Note: The interval does not take the job runtime into account. For example, +if a job takes 3 minutes to run, and it is scheduled to run every 5 minutes, +it will have only 2 minutes of idle time between each run. + +Time zones + +All interpretation and scheduling is done in the machine's local time zone (as +provided by the Go time package (http://www.golang.org/pkg/time). + +Be aware that jobs scheduled during daylight-savings leap-ahead transitions will +not be run! + +Thread safety + +Since the Cron service runs concurrently with the calling code, some amount of +care must be taken to ensure proper synchronization. + +All cron methods are designed to be correctly synchronized as long as the caller +ensures that invocations have a clear happens-before ordering between them. + +Implementation + +Cron entries are stored in an array, sorted by their next activation time. Cron +sleeps until the next job is due to be run. + +Upon waking: + - it runs each entry that is active on that second + - it calculates the next run times for the jobs that were run + - it re-sorts the array of entries by next activation time. + - it goes to sleep until the soonest job. +*/ +package cron diff --git a/vendor/github.com/robfig/cron/parser.go b/vendor/github.com/robfig/cron/parser.go new file mode 100644 index 0000000000..a5e83c0a8d --- /dev/null +++ b/vendor/github.com/robfig/cron/parser.go @@ -0,0 +1,380 @@ +package cron + +import ( + "fmt" + "math" + "strconv" + "strings" + "time" +) + +// Configuration options for creating a parser. Most options specify which +// fields should be included, while others enable features. If a field is not +// included the parser will assume a default value. These options do not change +// the order fields are parse in. +type ParseOption int + +const ( + Second ParseOption = 1 << iota // Seconds field, default 0 + Minute // Minutes field, default 0 + Hour // Hours field, default 0 + Dom // Day of month field, default * + Month // Month field, default * + Dow // Day of week field, default * + DowOptional // Optional day of week field, default * + Descriptor // Allow descriptors such as @monthly, @weekly, etc. +) + +var places = []ParseOption{ + Second, + Minute, + Hour, + Dom, + Month, + Dow, +} + +var defaults = []string{ + "0", + "0", + "0", + "*", + "*", + "*", +} + +// A custom Parser that can be configured. +type Parser struct { + options ParseOption + optionals int +} + +// Creates a custom Parser with custom options. +// +// // Standard parser without descriptors +// specParser := NewParser(Minute | Hour | Dom | Month | Dow) +// sched, err := specParser.Parse("0 0 15 */3 *") +// +// // Same as above, just excludes time fields +// subsParser := NewParser(Dom | Month | Dow) +// sched, err := specParser.Parse("15 */3 *") +// +// // Same as above, just makes Dow optional +// subsParser := NewParser(Dom | Month | DowOptional) +// sched, err := specParser.Parse("15 */3") +// +func NewParser(options ParseOption) Parser { + optionals := 0 + if options&DowOptional > 0 { + options |= Dow + optionals++ + } + return Parser{options, optionals} +} + +// Parse returns a new crontab schedule representing the given spec. +// It returns a descriptive error if the spec is not valid. +// It accepts crontab specs and features configured by NewParser. +func (p Parser) Parse(spec string) (Schedule, error) { + if len(spec) == 0 { + return nil, fmt.Errorf("Empty spec string") + } + if spec[0] == '@' && p.options&Descriptor > 0 { + return parseDescriptor(spec) + } + + // Figure out how many fields we need + max := 0 + for _, place := range places { + if p.options&place > 0 { + max++ + } + } + min := max - p.optionals + + // Split fields on whitespace + fields := strings.Fields(spec) + + // Validate number of fields + if count := len(fields); count < min || count > max { + if min == max { + return nil, fmt.Errorf("Expected exactly %d fields, found %d: %s", min, count, spec) + } + return nil, fmt.Errorf("Expected %d to %d fields, found %d: %s", min, max, count, spec) + } + + // Fill in missing fields + fields = expandFields(fields, p.options) + + var err error + field := func(field string, r bounds) uint64 { + if err != nil { + return 0 + } + var bits uint64 + bits, err = getField(field, r) + return bits + } + + var ( + second = field(fields[0], seconds) + minute = field(fields[1], minutes) + hour = field(fields[2], hours) + dayofmonth = field(fields[3], dom) + month = field(fields[4], months) + dayofweek = field(fields[5], dow) + ) + if err != nil { + return nil, err + } + + return &SpecSchedule{ + Second: second, + Minute: minute, + Hour: hour, + Dom: dayofmonth, + Month: month, + Dow: dayofweek, + }, nil +} + +func expandFields(fields []string, options ParseOption) []string { + n := 0 + count := len(fields) + expFields := make([]string, len(places)) + copy(expFields, defaults) + for i, place := range places { + if options&place > 0 { + expFields[i] = fields[n] + n++ + } + if n == count { + break + } + } + return expFields +} + +var standardParser = NewParser( + Minute | Hour | Dom | Month | Dow | Descriptor, +) + +// ParseStandard returns a new crontab schedule representing the given standardSpec +// (https://en.wikipedia.org/wiki/Cron). It differs from Parse requiring to always +// pass 5 entries representing: minute, hour, day of month, month and day of week, +// in that order. It returns a descriptive error if the spec is not valid. +// +// It accepts +// - Standard crontab specs, e.g. "* * * * ?" +// - Descriptors, e.g. "@midnight", "@every 1h30m" +func ParseStandard(standardSpec string) (Schedule, error) { + return standardParser.Parse(standardSpec) +} + +var defaultParser = NewParser( + Second | Minute | Hour | Dom | Month | DowOptional | Descriptor, +) + +// Parse returns a new crontab schedule representing the given spec. +// It returns a descriptive error if the spec is not valid. +// +// It accepts +// - Full crontab specs, e.g. "* * * * * ?" +// - Descriptors, e.g. "@midnight", "@every 1h30m" +func Parse(spec string) (Schedule, error) { + return defaultParser.Parse(spec) +} + +// getField returns an Int with the bits set representing all of the times that +// the field represents or error parsing field value. A "field" is a comma-separated +// list of "ranges". +func getField(field string, r bounds) (uint64, error) { + var bits uint64 + ranges := strings.FieldsFunc(field, func(r rune) bool { return r == ',' }) + for _, expr := range ranges { + bit, err := getRange(expr, r) + if err != nil { + return bits, err + } + bits |= bit + } + return bits, nil +} + +// getRange returns the bits indicated by the given expression: +// number | number "-" number [ "/" number ] +// or error parsing range. +func getRange(expr string, r bounds) (uint64, error) { + var ( + start, end, step uint + rangeAndStep = strings.Split(expr, "/") + lowAndHigh = strings.Split(rangeAndStep[0], "-") + singleDigit = len(lowAndHigh) == 1 + err error + ) + + var extra uint64 + if lowAndHigh[0] == "*" || lowAndHigh[0] == "?" { + start = r.min + end = r.max + extra = starBit + } else { + start, err = parseIntOrName(lowAndHigh[0], r.names) + if err != nil { + return 0, err + } + switch len(lowAndHigh) { + case 1: + end = start + case 2: + end, err = parseIntOrName(lowAndHigh[1], r.names) + if err != nil { + return 0, err + } + default: + return 0, fmt.Errorf("Too many hyphens: %s", expr) + } + } + + switch len(rangeAndStep) { + case 1: + step = 1 + case 2: + step, err = mustParseInt(rangeAndStep[1]) + if err != nil { + return 0, err + } + + // Special handling: "N/step" means "N-max/step". + if singleDigit { + end = r.max + } + default: + return 0, fmt.Errorf("Too many slashes: %s", expr) + } + + if start < r.min { + return 0, fmt.Errorf("Beginning of range (%d) below minimum (%d): %s", start, r.min, expr) + } + if end > r.max { + return 0, fmt.Errorf("End of range (%d) above maximum (%d): %s", end, r.max, expr) + } + if start > end { + return 0, fmt.Errorf("Beginning of range (%d) beyond end of range (%d): %s", start, end, expr) + } + if step == 0 { + return 0, fmt.Errorf("Step of range should be a positive number: %s", expr) + } + + return getBits(start, end, step) | extra, nil +} + +// parseIntOrName returns the (possibly-named) integer contained in expr. +func parseIntOrName(expr string, names map[string]uint) (uint, error) { + if names != nil { + if namedInt, ok := names[strings.ToLower(expr)]; ok { + return namedInt, nil + } + } + return mustParseInt(expr) +} + +// mustParseInt parses the given expression as an int or returns an error. +func mustParseInt(expr string) (uint, error) { + num, err := strconv.Atoi(expr) + if err != nil { + return 0, fmt.Errorf("Failed to parse int from %s: %s", expr, err) + } + if num < 0 { + return 0, fmt.Errorf("Negative number (%d) not allowed: %s", num, expr) + } + + return uint(num), nil +} + +// getBits sets all bits in the range [min, max], modulo the given step size. +func getBits(min, max, step uint) uint64 { + var bits uint64 + + // If step is 1, use shifts. + if step == 1 { + return ^(math.MaxUint64 << (max + 1)) & (math.MaxUint64 << min) + } + + // Else, use a simple loop. + for i := min; i <= max; i += step { + bits |= 1 << i + } + return bits +} + +// all returns all bits within the given bounds. (plus the star bit) +func all(r bounds) uint64 { + return getBits(r.min, r.max, 1) | starBit +} + +// parseDescriptor returns a predefined schedule for the expression, or error if none matches. +func parseDescriptor(descriptor string) (Schedule, error) { + switch descriptor { + case "@yearly", "@annually": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: 1 << hours.min, + Dom: 1 << dom.min, + Month: 1 << months.min, + Dow: all(dow), + }, nil + + case "@monthly": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: 1 << hours.min, + Dom: 1 << dom.min, + Month: all(months), + Dow: all(dow), + }, nil + + case "@weekly": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: 1 << hours.min, + Dom: all(dom), + Month: all(months), + Dow: 1 << dow.min, + }, nil + + case "@daily", "@midnight": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: 1 << hours.min, + Dom: all(dom), + Month: all(months), + Dow: all(dow), + }, nil + + case "@hourly": + return &SpecSchedule{ + Second: 1 << seconds.min, + Minute: 1 << minutes.min, + Hour: all(hours), + Dom: all(dom), + Month: all(months), + Dow: all(dow), + }, nil + } + + const every = "@every " + if strings.HasPrefix(descriptor, every) { + duration, err := time.ParseDuration(descriptor[len(every):]) + if err != nil { + return nil, fmt.Errorf("Failed to parse duration %s: %s", descriptor, err) + } + return Every(duration), nil + } + + return nil, fmt.Errorf("Unrecognized descriptor: %s", descriptor) +} diff --git a/vendor/github.com/robfig/cron/spec.go b/vendor/github.com/robfig/cron/spec.go new file mode 100644 index 0000000000..aac9a60b95 --- /dev/null +++ b/vendor/github.com/robfig/cron/spec.go @@ -0,0 +1,158 @@ +package cron + +import "time" + +// SpecSchedule specifies a duty cycle (to the second granularity), based on a +// traditional crontab specification. It is computed initially and stored as bit sets. +type SpecSchedule struct { + Second, Minute, Hour, Dom, Month, Dow uint64 +} + +// bounds provides a range of acceptable values (plus a map of name to value). +type bounds struct { + min, max uint + names map[string]uint +} + +// The bounds for each field. +var ( + seconds = bounds{0, 59, nil} + minutes = bounds{0, 59, nil} + hours = bounds{0, 23, nil} + dom = bounds{1, 31, nil} + months = bounds{1, 12, map[string]uint{ + "jan": 1, + "feb": 2, + "mar": 3, + "apr": 4, + "may": 5, + "jun": 6, + "jul": 7, + "aug": 8, + "sep": 9, + "oct": 10, + "nov": 11, + "dec": 12, + }} + dow = bounds{0, 6, map[string]uint{ + "sun": 0, + "mon": 1, + "tue": 2, + "wed": 3, + "thu": 4, + "fri": 5, + "sat": 6, + }} +) + +const ( + // Set the top bit if a star was included in the expression. + starBit = 1 << 63 +) + +// Next returns the next time this schedule is activated, greater than the given +// time. If no time can be found to satisfy the schedule, return the zero time. +func (s *SpecSchedule) Next(t time.Time) time.Time { + // General approach: + // For Month, Day, Hour, Minute, Second: + // Check if the time value matches. If yes, continue to the next field. + // If the field doesn't match the schedule, then increment the field until it matches. + // While incrementing the field, a wrap-around brings it back to the beginning + // of the field list (since it is necessary to re-verify previous field + // values) + + // Start at the earliest possible time (the upcoming second). + t = t.Add(1*time.Second - time.Duration(t.Nanosecond())*time.Nanosecond) + + // This flag indicates whether a field has been incremented. + added := false + + // If no time is found within five years, return zero. + yearLimit := t.Year() + 5 + +WRAP: + if t.Year() > yearLimit { + return time.Time{} + } + + // Find the first applicable month. + // If it's this month, then do nothing. + for 1< 0 + dowMatch bool = 1< 0 + ) + if s.Dom&starBit > 0 || s.Dow&starBit > 0 { + return domMatch && dowMatch + } + return domMatch || dowMatch +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 814b7257ab..68c2a94fdb 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -217,7 +217,7 @@ github.com/modern-go/concurrent github.com/modern-go/reflect2 # github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 github.com/munnerz/goautoneg -# github.com/openshift/api v0.0.0-20200824151745-288e45a0adde +# github.com/openshift/api v0.0.0-20200829102639-8a3a835f1acf github.com/openshift/api github.com/openshift/api/apps github.com/openshift/api/apps/v1 @@ -324,10 +324,12 @@ github.com/openshift/library-go/pkg/config/configdefaults github.com/openshift/library-go/pkg/config/leaderelection github.com/openshift/library-go/pkg/config/serving github.com/openshift/library-go/pkg/controller/controllercmd +github.com/openshift/library-go/pkg/controller/factory github.com/openshift/library-go/pkg/controller/fileobserver github.com/openshift/library-go/pkg/controller/metrics github.com/openshift/library-go/pkg/crypto github.com/openshift/library-go/pkg/operator/events +github.com/openshift/library-go/pkg/operator/loglevel github.com/openshift/library-go/pkg/operator/resource/resourceapply github.com/openshift/library-go/pkg/operator/resource/resourcehelper github.com/openshift/library-go/pkg/operator/resource/resourcemerge @@ -354,6 +356,8 @@ github.com/prometheus/common/model github.com/prometheus/procfs github.com/prometheus/procfs/internal/fs github.com/prometheus/procfs/internal/util +# github.com/robfig/cron v1.2.0 +github.com/robfig/cron # github.com/sirupsen/logrus v1.6.0 github.com/sirupsen/logrus # github.com/spf13/cobra v1.0.0