diff --git a/.github/workflows/kindIntegTest.yml b/.github/workflows/kindIntegTest.yml index 4baae2c4..d013b276 100644 --- a/.github/workflows/kindIntegTest.yml +++ b/.github/workflows/kindIntegTest.yml @@ -88,7 +88,7 @@ jobs: strategy: matrix: version: - - "4.0.14" + - "4.0.15" integration_test: - cdc_successful # OSS only - config_fql @@ -117,12 +117,12 @@ jobs: strategy: matrix: version: - - "6.8.51" + - "6.8.52" integration_test: - cdc_successful include: - - version: 6.8.51 - serverImage: datastax/dse-mgmtapi-6_8:6.8.51-ubi8 # DSE 6.8.51 + - version: 6.8.52 + serverImage: datastax/dse-mgmtapi-6_8:6.8.52-ubi8 # DSE 6.8.51 serverType: dse integration_test: "cdc_successful" fail-fast: true @@ -155,7 +155,7 @@ jobs: strategy: matrix: version: - - "5.0.1" + - "5.0.2" integration_test: # Single worker tests: - additional_serviceoptions @@ -233,19 +233,19 @@ jobs: version: - "4.0.14" - "4.1.7" - - "5.0.1" - - "6.8.51" - - "6.9.2" + - "5.0.2" + - "6.8.52" + - "6.9.5" - "1.0.0" integration_test: - test_all_the_things - smoke_test_read_only_fs include: - version: 6.8.51 - serverImage: datastax/dse-mgmtapi-6_8:6.8.51-ubi8 # DSE 6.8.51 + serverImage: datastax/dse-mgmtapi-6_8:6.8.52-ubi8 # DSE 6.8.52 serverType: dse - version: 6.9.2 - serverImage: datastax/dse-mgmtapi-6_8:6.9.2-ubi # DSE 6.9.2 + serverImage: datastax/dse-mgmtapi-6_8:6.9.5-ubi # DSE 6.9.5 serverType: dse - version: 1.0.0 serverImage: datastax/hcd:1.0.0-ubi # HCD 1.0.0 @@ -283,7 +283,7 @@ jobs: strategy: matrix: version: - - "5.0.1" + - "5.0.2" integration_test: - pvc_expansion fail-fast: true @@ -306,7 +306,7 @@ jobs: with: repository: topolvm/topolvm path: topolvm - ref: topolvm-chart-v15.2.0 + ref: topolvm-chart-v15.5.0 - name: Create LVM from TopoLVM's example setup run: | cd topolvm/example diff --git a/.github/workflows/operatorBuildAndDeploy.yml b/.github/workflows/operatorBuildAndDeploy.yml index 7d554c13..e729fafd 100644 --- a/.github/workflows/operatorBuildAndDeploy.yml +++ b/.github/workflows/operatorBuildAndDeploy.yml @@ -3,7 +3,6 @@ on: push: branches: - master - - 1.10.x pull_request: branches: [ master ] jobs: diff --git a/Dockerfile b/Dockerfile index d06966bc..cbc794ea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Build the manager binary -FROM golang:1.22 AS builder +FROM golang:1.23 AS builder ARG TARGETOS ARG TARGETARCH @@ -21,7 +21,7 @@ COPY internal/ internal/ RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go # Build the UBI image -FROM redhat/ubi8-micro:latest +FROM redhat/ubi9-micro:latest ARG VERSION diff --git a/Makefile b/Makefile index 74b58f2c..b11663b0 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ IMG ?= $(IMAGE_TAG_BASE):v$(VERSION) # Produce CRDs that work back to Kubernetes 1.11 (no version conversion) CRD_OPTIONS ?= "crd:generateEmbeddedObjectMeta=true" # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. -ENVTEST_K8S_VERSION = 1.30.x +ENVTEST_K8S_VERSION = 1.31.x # Logger image LOG_IMG_BASE ?= $(ORG)/system-logger @@ -130,12 +130,16 @@ vet: ## Run go vet against code. lint: golangci-lint ## Run golangci-lint against code. $(GOLANGCI_LINT) run ./... +.PHONY: lint-fix +lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes + $(GOLANGCI_LINT) run --fix + .PHONY: test test: manifests generate fmt vet lint envtest ## Run tests. # Old unit tests first - these use mocked client / fakeclient go test ./pkg/... -coverprofile cover-pkg.out # Then the envtest ones - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test -v ./apis/... ./internal/controllers/... -coverprofile cover.out + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test -v ./apis/... ./internal/... -coverprofile cover.out .PHONY: integ-test integ-test: kustomize cert-manager helm ## Run integration tests from directory M_INTEG_DIR or set M_INTEG_DIR=all to run all the integration tests. @@ -184,6 +188,12 @@ docker-logger-push: ## Push system-logger-image docker-logger-kind: docker-logger-build ## Build system-logger image and load to kind cluster kind load docker-image ${LOG_IMG} +.PHONY: build-installer +build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment. + mkdir -p dist + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/deployments/cluster > dist/install.yaml + ##@ Deployment ifndef ignore-not-found @@ -202,11 +212,11 @@ uninstall: manifests ## Uninstall CRDs from the K8s cluster specified in ~/.kube deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} LOG_IMG=${LOG_IMG} yq eval -i '.images.system-logger = env(LOG_IMG)' config/manager/image_config.yaml - kubectl apply --force-conflicts --server-side -k config/deployments/default + kubectl apply --force-conflicts --server-side -k config/deployments/cluster .PHONY: undeploy undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. - kubectl delete --ignore-not-found=$(ignore-not-found) -k config/deployments/default + kubectl delete --ignore-not-found=$(ignore-not-found) -k config/deployments/cluster .PHONY: deploy-test deploy-test: kustomize @@ -241,13 +251,13 @@ HELM ?= $(LOCALBIN)/helm OPM ?= $(LOCALBIN)/opm ## Tool Versions -CERT_MANAGER_VERSION ?= v1.14.7 -KUSTOMIZE_VERSION ?= v5.4.2 -CONTROLLER_TOOLS_VERSION ?= v0.15.0 -OPERATOR_SDK_VERSION ?= 1.35.0 -HELM_VERSION ?= 3.14.2 -OPM_VERSION ?= 1.38.0 -GOLINT_VERSION ?= 1.60.3 +CERT_MANAGER_VERSION ?= v1.16.2 +KUSTOMIZE_VERSION ?= v5.5.0 +CONTROLLER_TOOLS_VERSION ?= v0.16.4 +OPERATOR_SDK_VERSION ?= 1.38.0 +HELM_VERSION ?= 3.17.0 +OPM_VERSION ?= 1.48.0 +GOLINT_VERSION ?= 1.62.2 .PHONY: cert-manager cert-manager: ## Install cert-manager to the cluster diff --git a/README.md b/README.md index ffe94c96..46ef6f51 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,6 @@ ignore the feature (components enabled in the default installation are marked wi | namespace | Create namespace before installation* | | webhook | Enable validation webhooks in cass-operator (requires cert-manager) * | | clusterscope | Install cass-operator in a cluster scope, monitoring all the namespaces | -| auth-proxy | Protect Prometheus /metrics endpoint with api-server authentication | And following resource. Apply ``github.com/k8ssandra/cass-operator/config/`` before resource name if using remote installation: diff --git a/apis/cassandra/v1beta1/cassandradatacenter_types.go b/apis/cassandra/v1beta1/cassandradatacenter_types.go index b7dd2add..167bce7d 100644 --- a/apis/cassandra/v1beta1/cassandradatacenter_types.go +++ b/apis/cassandra/v1beta1/cassandradatacenter_types.go @@ -10,9 +10,6 @@ import ( "strconv" "strings" - "github.com/Jeffail/gabs/v2" - "github.com/k8ssandra/cass-operator/pkg/serverconfig" - "github.com/pkg/errors" "golang.org/x/mod/semver" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -721,80 +718,6 @@ func (dc *CassandraDatacenter) GetSuperuserSecretNamespacedName() types.Namespac } } -// GetConfigAsJSON gets a JSON-encoded string suitable for passing to configBuilder -func (dc *CassandraDatacenter) GetConfigAsJSON(config []byte) (string, error) { - - // We use the cluster seed-service name here for the seed list as it will - // resolve to the seed nodes. This obviates the need to update the - // cassandra.yaml whenever the seed nodes change. - seeds := []string{dc.GetSeedServiceName(), dc.GetAdditionalSeedsServiceName()} - - graphEnabled := 0 - solrEnabled := 0 - sparkEnabled := 0 - - if dc.Spec.ServerType == "dse" && dc.Spec.DseWorkloads != nil { - if dc.Spec.DseWorkloads.AnalyticsEnabled { - sparkEnabled = 1 - } - if dc.Spec.DseWorkloads.GraphEnabled { - graphEnabled = 1 - } - if dc.Spec.DseWorkloads.SearchEnabled { - solrEnabled = 1 - } - } - - native := 0 - nativeSSL := 0 - internode := 0 - internodeSSL := 0 - if dc.IsNodePortEnabled() { - native = dc.Spec.Networking.NodePort.Native - nativeSSL = dc.Spec.Networking.NodePort.NativeSSL - internode = dc.Spec.Networking.NodePort.Internode - internodeSSL = dc.Spec.Networking.NodePort.InternodeSSL - } - - modelValues := serverconfig.GetModelValues( - seeds, - dc.Spec.ClusterName, - dc.DatacenterName(), - graphEnabled, - solrEnabled, - sparkEnabled, - native, - nativeSSL, - internode, - internodeSSL) - - var modelBytes []byte - - modelBytes, err := json.Marshal(modelValues) - if err != nil { - return "", err - } - - // Combine the model values with the user-specified values - modelParsed, err := gabs.ParseJSON(modelBytes) - if err != nil { - return "", errors.Wrap(err, "Model information for CassandraDatacenter resource was not properly configured") - } - - if config != nil { - configParsed, err := gabs.ParseJSON(config) - if err != nil { - return "", errors.Wrap(err, "Error parsing Spec.Config for CassandraDatacenter resource") - } - - if err := modelParsed.Merge(configParsed); err != nil { - return "", errors.Wrap(err, "Error merging Spec.Config for CassandraDatacenter resource") - } - } - - return modelParsed.String(), nil -} - // GetNodePortNativePort // Gets the defined CQL port for NodePort. // 0 will be returned if NodePort is not configured. @@ -951,37 +874,6 @@ func (dc *CassandraDatacenter) DeploymentSupportsFQL() bool { return true } -func (dc *CassandraDatacenter) LegacyInternodeEnabled() bool { - config, err := gabs.ParseJSON(dc.Spec.Config) - if err != nil { - return false - } - - hasOldKeyStore := func(gobContainer map[string]*gabs.Container) bool { - if gobContainer == nil { - return false - } - - if keystorePath, found := gobContainer["keystore"]; found { - if strings.TrimSpace(keystorePath.Data().(string)) == "/etc/encryption/node-keystore.jks" { - return true - } - } - return false - } - - if config.Exists("cassandra-yaml", "client_encryption_options") || config.Exists("cassandra-yaml", "server_encryption_options") { - serverContainer := config.Path("cassandra-yaml.server_encryption_options").ChildrenMap() - clientContainer := config.Path("cassandra-yaml.client_encryption_options").ChildrenMap() - - if hasOldKeyStore(clientContainer) || hasOldKeyStore(serverContainer) { - return true - } - } - - return false -} - func SplitRacks(nodeCount, rackCount int) []int { nodesPerRack, extraNodes := nodeCount/rackCount, nodeCount%rackCount diff --git a/apis/cassandra/v1beta1/cassandradatacenter_types_test.go b/apis/cassandra/v1beta1/cassandradatacenter_types_test.go index b3380fa0..6aba507b 100644 --- a/apis/cassandra/v1beta1/cassandradatacenter_types_test.go +++ b/apis/cassandra/v1beta1/cassandradatacenter_types_test.go @@ -1,63 +1,13 @@ package v1beta1 import ( - "encoding/json" "testing" - "github.com/Jeffail/gabs/v2" "github.com/stretchr/testify/assert" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" ) -var internodeEnabledAll = ` -{ - "cassandra-yaml": { - "server_encryption_options": { - "internode_encryption": "all", - "keystore": "/etc/encryption/node-keystore.jks", - "keystore_password": "dc2", - "truststore": "/etc/encryption/node-keystore.jks", - "truststore_password": "dc2" - } - } -} -` - -var internodeSomethingElse = ` -{ - "cassandra-yaml": { - "server_encryption_options": { - "internode_encryption": "all", - "keystore": "/etc/encryption/cert-manager.jks", - "keystore_password": "aaaaaa", - "truststore": "/etc/encryption/cert-manager.jks", - "truststore_password": "bbbbb" - } - } -} -` - -func TestLegacyInternodeEnabled(t *testing.T) { - dc := CassandraDatacenter{ - Spec: CassandraDatacenterSpec{ - Config: json.RawMessage(internodeEnabledAll), - }, - } - - assert.True(t, dc.LegacyInternodeEnabled()) -} - -func TestLegacyInternodeDisabled(t *testing.T) { - dc := CassandraDatacenter{ - Spec: CassandraDatacenterSpec{ - Config: json.RawMessage(internodeSomethingElse), - }, - } - - assert.False(t, dc.LegacyInternodeEnabled()) -} - func TestUseClientImage(t *testing.T) { assert := assert.New(t) @@ -191,50 +141,3 @@ func TestUseClientImageEnforce(t *testing.T) { assert.True(dc.UseClientImage()) } } - -func TestDatacenterNoOverrideConfig(t *testing.T) { - assert := assert.New(t) - dc := CassandraDatacenter{ - ObjectMeta: metav1.ObjectMeta{ - Name: "dc1", - }, - Spec: CassandraDatacenterSpec{ - ClusterName: "cluster1", - }, - } - - config, err := dc.GetConfigAsJSON(dc.Spec.Config) - assert.NoError(err) - - container, err := gabs.ParseJSON([]byte(config)) - assert.NoError(err) - - dataCenterInfo := container.ChildrenMap()["datacenter-info"] - assert.NotEmpty(dataCenterInfo) - assert.Equal(dc.Name, dataCenterInfo.ChildrenMap()["name"].Data().(string)) - assert.Equal(dc.DatacenterName(), dc.Name) -} - -func TestDatacenterOverrideInConfig(t *testing.T) { - assert := assert.New(t) - dc := CassandraDatacenter{ - ObjectMeta: metav1.ObjectMeta{ - Name: "dc1", - }, - Spec: CassandraDatacenterSpec{ - ClusterName: "cluster1", - DatacenterName: "Home_Dc", - }, - } - - config, err := dc.GetConfigAsJSON(dc.Spec.Config) - assert.NoError(err) - - container, err := gabs.ParseJSON([]byte(config)) - assert.NoError(err) - - dataCenterInfo := container.ChildrenMap()["datacenter-info"] - assert.NotEmpty(dataCenterInfo) - assert.Equal(dc.Spec.DatacenterName, dataCenterInfo.ChildrenMap()["name"].Data().(string)) - assert.Equal(dc.DatacenterName(), dc.Spec.DatacenterName) -} diff --git a/apis/cassandra/v1beta1/zz_generated.deepcopy.go b/apis/cassandra/v1beta1/zz_generated.deepcopy.go index 3eb2a944..752b690d 100644 --- a/apis/cassandra/v1beta1/zz_generated.deepcopy.go +++ b/apis/cassandra/v1beta1/zz_generated.deepcopy.go @@ -23,7 +23,7 @@ package v1beta1 import ( "encoding/json" "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/runtime" + runtime "k8s.io/apimachinery/pkg/runtime" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. diff --git a/apis/config/v1beta1/operatorconfig_types.go b/apis/config/v1beta1/operatorconfig_types.go index ea675edd..d0c0c5e2 100644 --- a/apis/config/v1beta1/operatorconfig_types.go +++ b/apis/config/v1beta1/operatorconfig_types.go @@ -18,7 +18,6 @@ package v1beta1 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - cfg "sigs.k8s.io/controller-runtime/pkg/config/v1alpha1" //nolint:staticcheck ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! @@ -30,9 +29,6 @@ import ( type OperatorConfig struct { metav1.TypeMeta `json:",inline"` - // ControllerManagerConfigurationSpec returns the configurations for controllers - cfg.ControllerManagerConfigurationSpec `json:",inline"` - // SkipValidatingWebhook replaces the old SKIP_VALIDATING_WEBHOOK env variable. If set to true, the webhooks are not initialized DisableWebhooks bool `json:"disableWebhooks,omitempty"` diff --git a/apis/config/v1beta1/zz_generated.deepcopy.go b/apis/config/v1beta1/zz_generated.deepcopy.go index 8559fadc..2af9c492 100644 --- a/apis/config/v1beta1/zz_generated.deepcopy.go +++ b/apis/config/v1beta1/zz_generated.deepcopy.go @@ -195,7 +195,6 @@ func (in *Images) DeepCopyObject() runtime.Object { func (in *OperatorConfig) DeepCopyInto(out *OperatorConfig) { *out = *in out.TypeMeta = in.TypeMeta - in.ControllerManagerConfigurationSpec.DeepCopyInto(&out.ControllerManagerConfigurationSpec) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperatorConfig. diff --git a/cmd/main.go b/cmd/main.go index 58bf99d2..4a4f71bd 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -17,7 +17,9 @@ limitations under the License. package main import ( + "crypto/tls" "flag" + "fmt" "os" "strings" @@ -27,18 +29,23 @@ import ( _ "k8s.io/client-go/plugin/pkg/client/auth" "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/serializer" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/metrics/filters" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" configv1beta1 "github.com/k8ssandra/cass-operator/apis/config/v1beta1" controlv1alpha1 "github.com/k8ssandra/cass-operator/apis/control/v1alpha1" controllers "github.com/k8ssandra/cass-operator/internal/controllers/cassandra" controlcontrollers "github.com/k8ssandra/cass-operator/internal/controllers/control" + apiwebhook "github.com/k8ssandra/cass-operator/internal/webhooks/cassandra/v1beta1" "github.com/k8ssandra/cass-operator/pkg/images" "github.com/k8ssandra/cass-operator/pkg/utils" ) @@ -57,9 +64,26 @@ func init() { } func main() { + + var metricsAddr string + var enableLeaderElection bool + var probeAddr string + var secureMetrics bool + var enableHTTP2 bool var configFile string + var tlsOpts []func(*tls.Config) + flag.StringVar(&metricsAddr, "metrics-bind-address", "0", "The address the metrics endpoint binds to. "+ + "Use :8443 for HTTPS or :8080 for HTTP, or leave as 0 to disable the metrics service.") + flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") + flag.BoolVar(&enableLeaderElection, "leader-elect", false, + "Enable leader election for controller manager. "+ + "Enabling this will ensure there is only one active controller manager.") + flag.BoolVar(&secureMetrics, "metrics-secure", true, + "If set, the metrics endpoint is served securely via HTTPS. Use --metrics-secure=false to use HTTP instead.") + flag.BoolVar(&enableHTTP2, "enable-http2", false, + "If set, HTTP/2 will be enabled for the metrics and webhook servers") flag.StringVar(&configFile, "config", "", - "The controller will load its initial configuration from this file. "+ + "The cass-operator will load its configuration from this file. "+ "Omit this flag to use the default configuration values. ") opts := zap.Options{ @@ -77,23 +101,59 @@ func main() { "the manager will watch and manage resources in all namespaces") } - operConfig := configv1beta1.OperatorConfig{} - options := ctrl.Options{Scheme: scheme} + disableHTTP2 := func(c *tls.Config) { + setupLog.Info("disabling http/2") + c.NextProtos = []string{"http/1.1"} + } + + if !enableHTTP2 { + tlsOpts = append(tlsOpts, disableHTTP2) + } + + webhookServer := webhook.NewServer(webhook.Options{ + TLSOpts: tlsOpts, + }) + + metricsServerOptions := metricsserver.Options{ + BindAddress: metricsAddr, + SecureServing: secureMetrics, + TLSOpts: tlsOpts, + } + + if secureMetrics { + // FilterProvider is used to protect the metrics endpoint with authn/authz. + // These configurations ensure that only authorized users and service accounts + // can access the metrics endpoint. The RBAC are configured in 'config/rbac/kustomization.yaml'. More info: + // https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.19.1/pkg/metrics/filters#WithAuthenticationAndAuthorization + metricsServerOptions.FilterProvider = filters.WithAuthenticationAndAuthorization + } + + operConfig := &configv1beta1.OperatorConfig{} + options := ctrl.Options{ + Scheme: scheme, + Metrics: metricsServerOptions, + WebhookServer: webhookServer, + HealthProbeBindAddress: probeAddr, + LeaderElection: enableLeaderElection, + LeaderElectionID: "b569adb7.cassandra.datastax.com", + } if configFile != "" { - //nolint:staticcheck - options, err = options.AndFrom(ctrl.ConfigFile().AtPath(configFile).OfKind(&operConfig)) + var err error + operConfig, err = readOperConfig(configFile) if err != nil { setupLog.Error(err, "unable to load the config file") os.Exit(1) } } - if operConfig.ImageConfigFile != "" { - err = images.ParseImageConfig(operConfig.ImageConfigFile) - if err != nil { - setupLog.Error(err, "unable to load the image config file") - os.Exit(1) - } + if operConfig.ImageConfigFile == "" { + operConfig.ImageConfigFile = "/configs/image_config.yaml" + } + + err = images.ParseImageConfig(operConfig.ImageConfigFile) + if err != nil { + setupLog.Error(err, "unable to load the image config file") + os.Exit(1) } options.Cache = cache.Options{ @@ -130,7 +190,7 @@ func main() { } if !operConfig.DisableWebhooks { - if err = (&api.CassandraDatacenter{}).SetupWebhookWithManager(mgr); err != nil { + if err = apiwebhook.SetupCassandraDatacenterWebhookWithManager(mgr); err != nil { setupLog.Error(err, "unable to create webhook", "webhook", "CassandraDatacenter") os.Exit(1) } @@ -158,3 +218,23 @@ func main() { os.Exit(1) } } + +func readOperConfig(configFile string) (*configv1beta1.OperatorConfig, error) { + operConfig := &configv1beta1.OperatorConfig{} + _, err := os.Stat(configFile) + if err != nil { + return nil, err + } + + content, err := os.ReadFile(configFile) + if err != nil { + return nil, err + } + + codecs := serializer.NewCodecFactory(scheme) + if err := runtime.DecodeInto(codecs.UniversalDecoder(), content, operConfig); err != nil { + return nil, fmt.Errorf("could not decode file into runtime.Object: %v", err) + } + + return operConfig, nil +} diff --git a/config/certmanager/certificate.yaml b/config/certmanager/certificate.yaml index 52d86618..954516f0 100644 --- a/config/certmanager/certificate.yaml +++ b/config/certmanager/certificate.yaml @@ -4,6 +4,9 @@ apiVersion: cert-manager.io/v1 kind: Issuer metadata: + labels: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize name: selfsigned-issuer namespace: system spec: @@ -12,13 +15,20 @@ spec: apiVersion: cert-manager.io/v1 kind: Certificate metadata: + labels: + app.kubernetes.io/name: certificate + app.kubernetes.io/instance: serving-cert + app.kubernetes.io/component: certificate + app.kubernetes.io/created-by: cass-operator + app.kubernetes.io/part-of: cass-operator + app.kubernetes.io/managed-by: kustomize name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml namespace: system spec: - # $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize + # SERVICE_NAME and SERVICE_NAMESPACE will be substituted by kustomize dnsNames: - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc - - $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local + - SERVICE_NAME.SERVICE_NAMESPACE.svc + - SERVICE_NAME.SERVICE_NAMESPACE.svc.cluster.local issuerRef: kind: Issuer name: selfsigned-issuer diff --git a/config/certmanager/kustomizeconfig.yaml b/config/certmanager/kustomizeconfig.yaml index 90d7c313..cf6f89e8 100644 --- a/config/certmanager/kustomizeconfig.yaml +++ b/config/certmanager/kustomizeconfig.yaml @@ -1,4 +1,4 @@ -# This configuration is for teaching kustomize how to update name ref and var substitution +# This configuration is for teaching kustomize how to update name ref substitution nameReference: - kind: Issuer group: cert-manager.io @@ -6,11 +6,3 @@ nameReference: - kind: Certificate group: cert-manager.io path: spec/issuerRef/name - -varReference: -- kind: Certificate - group: cert-manager.io - path: spec/commonName -- kind: Certificate - group: cert-manager.io - path: spec/dnsNames diff --git a/config/components/auth-proxy/kustomization.yaml b/config/components/auth-proxy/kustomization.yaml deleted file mode 100644 index e93e9117..00000000 --- a/config/components/auth-proxy/kustomization.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1alpha1 -kind: Component - -patchesStrategicMerge: -- patches/manager_auth_proxy_patch.yaml - -resources: -- rbac/auth_proxy_service.yaml -- rbac/auth_proxy_role.yaml -- rbac/auth_proxy_role_binding.yaml -- rbac/auth_proxy_client_clusterrole.yaml diff --git a/config/components/auth-proxy/patches/manager_auth_proxy_patch.yaml b/config/components/auth-proxy/patches/manager_auth_proxy_patch.yaml deleted file mode 100644 index 999d179c..00000000 --- a/config/components/auth-proxy/patches/manager_auth_proxy_patch.yaml +++ /dev/null @@ -1,26 +0,0 @@ -# This patch inject a sidecar container which is a HTTP proxy for the -# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. -apiVersion: apps/v1 -kind: Deployment -metadata: - name: controller-manager - namespace: system -spec: - template: - spec: - containers: - - name: kube-rbac-proxy - image: gcr.io/kubebuilder/kube-rbac-proxy:0.13.1 - args: - - "--secure-listen-address=0.0.0.0:8443" - - "--upstream=http://127.0.0.1:8080/" - - "--logtostderr=true" - - "--v=10" - ports: - - containerPort: 8443 - name: https - - name: manager - args: - - "--health-probe-bind-address=:8081" - - "--metrics-bind-address=127.0.0.1:8080" - - "--leader-elect" diff --git a/config/components/clusterscope/kustomization.yaml b/config/components/clusterscope/kustomization.yaml index f3b1820c..46b766b4 100644 --- a/config/components/clusterscope/kustomization.yaml +++ b/config/components/clusterscope/kustomization.yaml @@ -1,36 +1,31 @@ # Set WATCH_NAMESPACE to "" in the deployment to provide cluster-wide install apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component -patchesJson6902: -- target: - group: apps - version: v1 - name: controller-manager - kind: Deployment - patch: |- +patches: +- patch: |- - op: remove path: /spec/template/spec/containers/0/env/0/valueFrom - op: add path: /spec/template/spec/containers/0/env/0/value value: "" -- target: - group: rbac.authorization.k8s.io + target: + group: apps + kind: Deployment + name: controller-manager version: v1 - kind: Role - name: manager-role - patch: |- +- patch: |- - op: replace path: /metadata/name value: cass-operator-manager-crrole - op: replace path: /kind value: ClusterRole -- target: + target: group: rbac.authorization.k8s.io + kind: Role + name: manager-role version: v1 - kind: RoleBinding - name: manager-rolebinding - patch: |- +- patch: |- - op: replace path: /roleRef/kind value: ClusterRole @@ -46,3 +41,8 @@ patchesJson6902: - op: replace path: /kind value: ClusterRoleBinding + target: + group: rbac.authorization.k8s.io + kind: RoleBinding + name: manager-rolebinding + version: v1 diff --git a/config/components/namespace/ns.yaml b/config/components/namespace/ns.yaml index 8b55c3cd..dff74bdb 100644 --- a/config/components/namespace/ns.yaml +++ b/config/components/namespace/ns.yaml @@ -2,5 +2,7 @@ apiVersion: v1 kind: Namespace metadata: labels: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize control-plane: controller-manager name: system diff --git a/config/components/webhook/controller_manager_config.yaml b/config/components/webhook/controller_manager_config.yaml index 89e40ac8..8a4c532e 100644 --- a/config/components/webhook/controller_manager_config.yaml +++ b/config/components/webhook/controller_manager_config.yaml @@ -2,14 +2,5 @@ apiVersion: config.k8ssandra.io/v1beta1 kind: OperatorConfig metadata: name: operator-config -health: - healthProbeBindAddress: :8081 -metrics: - bindAddress: 127.0.0.1:8080 -webhook: - port: 9443 -leaderElection: - leaderElect: true - resourceName: b569adb7.cassandra.datastax.com disableWebhooks: false imageConfigFile: /configs/image_config.yaml diff --git a/config/components/webhook/kustomization.yaml b/config/components/webhook/kustomization.yaml index d7a245d0..77ea36fd 100644 --- a/config/components/webhook/kustomization.yaml +++ b/config/components/webhook/kustomization.yaml @@ -1,15 +1,10 @@ apiVersion: kustomize.config.k8s.io/v1alpha1 kind: Component -patchesStrategicMerge: -- patches/cainjection_in_cassandradatacenters.yaml -- patches/manager_webhook_patch.yaml -- patches/webhookcainjection_patch.yaml - configMapGenerator: -- files: +- behavior: merge + files: - controller_manager_config.yaml - behavior: merge name: manager-config resources: @@ -18,33 +13,5 @@ resources: configurations: - kustomizeconfig.yaml - -# the following config is for teaching kustomize how to do var substitution -vars: -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -- name: CERTIFICATE_NAMESPACE # namespace of the certificate CR - objref: - kind: Certificate - group: cert-manager.io - version: v1 - name: serving-cert # this name should match the one in certificate.yaml - fieldref: - fieldpath: metadata.namespace -- name: CERTIFICATE_NAME - objref: - kind: Certificate - group: cert-manager.io - version: v1 - name: serving-cert # this name should match the one in certificate.yaml -- name: SERVICE_NAMESPACE # namespace of the service - objref: - kind: Service - version: v1 - name: webhook-service - fieldref: - fieldpath: metadata.namespace -- name: SERVICE_NAME - objref: - kind: Service - version: v1 - name: webhook-service +patches: +- path: patches/manager_webhook_patch.yaml diff --git a/config/components/webhook/kustomizeconfig.yaml b/config/components/webhook/kustomizeconfig.yaml index ec5c150a..03ce5b78 100644 --- a/config/components/webhook/kustomizeconfig.yaml +++ b/config/components/webhook/kustomizeconfig.yaml @@ -14,6 +14,3 @@ namespace: group: apiextensions.k8s.io path: spec/conversion/webhook/clientConfig/service/namespace create: false - -varReference: -- path: metadata/annotations diff --git a/config/components/webhook/patches/cainjection_in_cassandradatacenters.yaml b/config/components/webhook/patches/cainjection_in_cassandradatacenters.yaml deleted file mode 100644 index afaedb9b..00000000 --- a/config/components/webhook/patches/cainjection_in_cassandradatacenters.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: cassandradatacenters.cassandra.datastax.com diff --git a/config/components/webhook/patches/manager_webhook_patch.yaml b/config/components/webhook/patches/manager_webhook_patch.yaml index 738de350..c4019d15 100644 --- a/config/components/webhook/patches/manager_webhook_patch.yaml +++ b/config/components/webhook/patches/manager_webhook_patch.yaml @@ -3,6 +3,9 @@ kind: Deployment metadata: name: controller-manager namespace: system + labels: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize spec: template: spec: diff --git a/config/components/webhook/patches/webhookcainjection_patch.yaml b/config/components/webhook/patches/webhookcainjection_patch.yaml deleted file mode 100644 index a350db40..00000000 --- a/config/components/webhook/patches/webhookcainjection_patch.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# This patch add annotation to admission webhook config and -# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. -# apiVersion: admissionregistration.k8s.io/v1 -# kind: MutatingWebhookConfiguration -# metadata: -# name: mutating-webhook-configuration -# annotations: -# cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) ---- -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: validating-webhook-configuration - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/config/crd/bases/cassandra.datastax.com_cassandradatacenters.yaml b/config/crd/bases/cassandra.datastax.com_cassandradatacenters.yaml index 6ae1bd4b..86e19e36 100644 --- a/config/crd/bases/cassandra.datastax.com_cassandradatacenters.yaml +++ b/config/crd/bases/cassandra.datastax.com_cassandradatacenters.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.4 name: cassandradatacenters.cassandra.datastax.com spec: group: cassandra.datastax.com @@ -229,11 +229,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -244,6 +242,12 @@ spec: the Pod where this field is used. It makes that resource available inside a container. type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string required: - name type: object @@ -282,7 +286,6 @@ spec: secret is expected to have a property named config whose value should be a JSON formatted string that should look like this: - config: |- { "cassandra-yaml": { @@ -293,7 +296,6 @@ spec: } } - ConfigSecret is mutually exclusive with Config. ConfigSecret takes precedence and will be used exclusively if both properties are set. The operator sets a watch such that an update to the secret will trigger an update of the StatefulSets. @@ -476,11 +478,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -508,11 +512,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic weight: @@ -526,6 +532,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -570,11 +577,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -602,14 +611,17 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array + x-kubernetes-list-type: atomic required: - nodeSelectorTerms type: object @@ -673,11 +685,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -692,13 +706,13 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -707,13 +721,13 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -754,11 +768,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -778,6 +794,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -800,6 +817,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -850,11 +868,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -869,13 +889,13 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -884,13 +904,13 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -930,11 +950,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -954,6 +976,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -966,6 +989,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object podAntiAffinity: description: Describes pod anti-affinity scheduling rules @@ -1025,11 +1049,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1044,13 +1070,13 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1059,13 +1085,13 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1106,11 +1132,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1130,6 +1158,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1152,6 +1181,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the anti-affinity requirements specified by this field are not met at @@ -1202,11 +1232,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1221,13 +1253,13 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1236,13 +1268,13 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -1282,11 +1314,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -1306,6 +1340,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -1318,6 +1353,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object type: object automountServiceAccountToken: @@ -1347,6 +1383,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic command: description: |- Entrypoint array. Not executed within a shell. @@ -1360,6 +1397,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic env: description: |- List of environment variables to set in the container. @@ -1395,10 +1433,13 @@ spec: description: The key to select. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 ConfigMap @@ -1461,10 +1502,13 @@ spec: key. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 @@ -1479,6 +1523,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map envFrom: description: |- List of sources to populate environment variables in the container. @@ -1495,10 +1542,13 @@ spec: description: The ConfigMap to select from properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 ConfigMap @@ -1514,10 +1564,13 @@ spec: description: The Secret to select from properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 must @@ -1527,6 +1580,7 @@ spec: x-kubernetes-map-type: atomic type: object type: array + x-kubernetes-list-type: atomic image: description: |- Container image name. @@ -1567,6 +1621,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http request @@ -1597,6 +1652,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -1678,6 +1734,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http request @@ -1708,6 +1765,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -1785,6 +1843,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -1802,11 +1861,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -1841,6 +1900,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -1998,6 +2058,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -2015,11 +2076,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -2054,6 +2115,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -2167,11 +2229,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -2183,6 +2243,12 @@ spec: the Pod where this field is used. It makes that resource available inside a container. type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string required: - name type: object @@ -2249,6 +2315,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -2262,6 +2352,7 @@ spec: type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -2269,6 +2360,7 @@ spec: type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -2280,7 +2372,7 @@ spec: procMount: description: |- procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for + The default value is Default which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. @@ -2362,7 +2454,6 @@ spec: type indicates which kind of seccomp profile will be applied. Valid options are: - Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied. @@ -2426,6 +2517,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -2443,11 +2535,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -2482,6 +2574,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -2624,6 +2717,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map volumeMounts: description: |- Pod volumes to mount into the container's filesystem. @@ -2643,6 +2739,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a Volume. @@ -2652,6 +2750,25 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -2669,6 +2786,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map workingDir: description: |- Container's working directory. @@ -2680,6 +2800,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map dnsConfig: description: |- Specifies the DNS parameters of a pod. @@ -2694,6 +2817,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic options: description: |- A list of DNS resolver options. @@ -2711,6 +2835,7 @@ spec: type: string type: object type: array + x-kubernetes-list-type: atomic searches: description: |- A list of DNS search domains for host-name lookup. @@ -2719,6 +2844,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object dnsPolicy: description: |- @@ -2749,7 +2875,6 @@ spec: removed or restarted. The kubelet may evict a Pod if an ephemeral container causes the Pod to exceed its resource allocation. - To add an ephemeral container, use the ephemeralcontainers subresource of an existing Pod. Ephemeral containers may not be removed or restarted. properties: @@ -2766,6 +2891,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic command: description: |- Entrypoint array. Not executed within a shell. @@ -2779,6 +2905,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic env: description: |- List of environment variables to set in the container. @@ -2814,10 +2941,13 @@ spec: description: The key to select. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 ConfigMap @@ -2880,10 +3010,13 @@ spec: key. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 @@ -2898,6 +3031,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map envFrom: description: |- List of sources to populate environment variables in the container. @@ -2914,10 +3050,13 @@ spec: description: The ConfigMap to select from properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 ConfigMap @@ -2933,10 +3072,13 @@ spec: description: The Secret to select from properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 must @@ -2946,6 +3088,7 @@ spec: x-kubernetes-map-type: atomic type: object type: array + x-kubernetes-list-type: atomic image: description: |- Container image name. @@ -2983,6 +3126,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http request @@ -3013,6 +3157,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -3094,6 +3239,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http request @@ -3124,6 +3270,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -3197,6 +3344,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -3214,11 +3362,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -3253,6 +3401,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -3398,6 +3547,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -3415,11 +3565,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -3454,6 +3604,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -3566,11 +3717,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -3582,6 +3731,12 @@ spec: the Pod where this field is used. It makes that resource available inside a container. type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string required: - name type: object @@ -3636,6 +3791,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -3649,6 +3828,7 @@ spec: type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -3656,6 +3836,7 @@ spec: type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -3667,7 +3848,7 @@ spec: procMount: description: |- procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for + The default value is Default which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. @@ -3749,7 +3930,6 @@ spec: type indicates which kind of seccomp profile will be applied. Valid options are: - Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied. @@ -3806,6 +3986,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -3823,11 +4004,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -3862,6 +4043,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -3964,7 +4146,6 @@ spec: The ephemeral container will be run in the namespaces (IPC, PID, etc) of this container. If not set then the ephemeral container uses the namespaces configured in the Pod spec. - The container runtime must implement support for this feature. If the runtime does not support namespace targeting then the result of setting this field is undefined. type: string @@ -4014,6 +4195,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map volumeMounts: description: |- Pod volumes to mount into the container's filesystem. Subpath mounts are not allowed for ephemeral containers. @@ -4033,6 +4217,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a Volume. @@ -4042,6 +4228,25 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -4059,6 +4264,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map workingDir: description: |- Container's working directory. @@ -4070,10 +4278,13 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map hostAliases: description: |- HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts - file if specified. This is only valid for non-hostNetwork pods. + file if specified. items: description: |- HostAlias holds the mapping between IP and hostnames that will be injected as an entry in the @@ -4084,11 +4295,17 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic ip: description: IP address of the host file entry. type: string + required: + - ip type: object type: array + x-kubernetes-list-map-keys: + - ip + x-kubernetes-list-type: map hostIPC: description: |- Use the host's ipc namespace. @@ -4133,14 +4350,20 @@ spec: referenced object inside the same namespace. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map initContainers: description: |- List of initialization containers belonging to the pod. @@ -4173,6 +4396,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic command: description: |- Entrypoint array. Not executed within a shell. @@ -4186,6 +4410,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic env: description: |- List of environment variables to set in the container. @@ -4221,10 +4446,13 @@ spec: description: The key to select. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 ConfigMap @@ -4287,10 +4515,13 @@ spec: key. type: string name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 @@ -4305,6 +4536,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map envFrom: description: |- List of sources to populate environment variables in the container. @@ -4321,10 +4555,13 @@ spec: description: The ConfigMap to select from properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 ConfigMap @@ -4340,10 +4577,13 @@ spec: description: The Secret to select from properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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 must @@ -4353,6 +4593,7 @@ spec: x-kubernetes-map-type: atomic type: object type: array + x-kubernetes-list-type: atomic image: description: |- Container image name. @@ -4393,6 +4634,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http request @@ -4423,6 +4665,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -4504,6 +4747,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object httpGet: description: HTTPGet specifies the http request @@ -4534,6 +4778,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. @@ -4611,6 +4856,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -4628,11 +4874,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -4667,6 +4913,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -4824,6 +5071,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -4841,11 +5089,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -4880,6 +5128,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -4993,11 +5242,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry @@ -5009,6 +5256,12 @@ spec: the Pod where this field is used. It makes that resource available inside a container. type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string required: - name type: object @@ -5075,6 +5328,30 @@ spec: 2) has CAP_SYS_ADMIN Note that this field cannot be set when spec.os.name is windows. type: boolean + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by this container. If set, this profile + overrides the pod's appArmorProfile. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object capabilities: description: |- The capabilities to add/drop when running containers. @@ -5088,6 +5365,7 @@ spec: type type: string type: array + x-kubernetes-list-type: atomic drop: description: Removed capabilities items: @@ -5095,6 +5373,7 @@ spec: type type: string type: array + x-kubernetes-list-type: atomic type: object privileged: description: |- @@ -5106,7 +5385,7 @@ spec: procMount: description: |- procMount denotes the type of proc mount to use for the containers. - The default is DefaultProcMount which uses the container runtime defaults for + The default value is Default which uses the container runtime defaults for readonly paths and masked paths. This requires the ProcMountType feature flag to be enabled. Note that this field cannot be set when spec.os.name is windows. @@ -5188,7 +5467,6 @@ spec: type indicates which kind of seccomp profile will be applied. Valid options are: - Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied. @@ -5252,6 +5530,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object failureThreshold: description: |- @@ -5269,11 +5548,11 @@ spec: format: int32 type: integer service: + default: "" description: |- Service is the name of the service to place in the gRPC HealthCheckRequest (see https://github.com/grpc/grpc/blob/master/doc/health-checking.md). - If this is not specified, the default behavior is defined by gRPC. type: string required: @@ -5308,6 +5587,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic path: description: Path to access on the HTTP server. type: string @@ -5450,6 +5730,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - devicePath + x-kubernetes-list-type: map volumeMounts: description: |- Pod volumes to mount into the container's filesystem. @@ -5469,6 +5752,8 @@ spec: to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10. + When RecursiveReadOnly is set to IfPossible or to Enabled, MountPropagation must be None or unspecified + (which defaults to None). type: string name: description: This must match the Name of a Volume. @@ -5478,6 +5763,25 @@ spec: Mounted read-only if true, read-write otherwise (false or unspecified). Defaults to false. type: boolean + recursiveReadOnly: + description: |- + RecursiveReadOnly specifies whether read-only mounts should be handled + recursively. + + If ReadOnly is false, this field has no meaning and must be unspecified. + + If ReadOnly is true, and this field is set to Disabled, the mount is not made + recursively read-only. If this field is set to IfPossible, the mount is made + recursively read-only, if it is supported by the container runtime. If this + field is set to Enabled, the mount is made recursively read-only if it is + supported by the container runtime, otherwise the pod will not be started and + an error will be generated to indicate the reason. + + If this field is set to IfPossible or Enabled, MountPropagation must be set to + None (or be unspecified, which defaults to None). + + If this field is not specified, it is treated as an equivalent of Disabled. + type: string subPath: description: |- Path within the volume from which the container's volume should be mounted. @@ -5495,6 +5799,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - mountPath + x-kubernetes-list-type: map workingDir: description: |- Container's working directory. @@ -5506,11 +5813,16 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map nodeName: description: |- - NodeName is a request to schedule this pod onto a specific node. If it is non-empty, - the scheduler simply schedules this pod onto that node, assuming that it fits resource - requirements. + NodeName indicates in which node this pod is scheduled. + If empty, this pod is a candidate for scheduling by the scheduler defined in schedulerName. + Once this field is set, the kubelet for this node becomes responsible for the lifecycle of this pod. + This field should not be used to express a desire for the pod to be scheduled on a specific node. + https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodename type: string nodeSelector: additionalProperties: @@ -5526,15 +5838,14 @@ spec: Specifies the OS of the containers in the pod. Some pod and container fields are restricted if this is set. - If the OS field is set to linux, the following fields must be unset: -securityContext.windowsOptions - If the OS field is set to windows, following fields must be unset: - spec.hostPID - spec.hostIPC - spec.hostUsers + - spec.securityContext.appArmorProfile - spec.securityContext.seLinuxOptions - spec.securityContext.seccompProfile - spec.securityContext.fsGroup @@ -5544,6 +5855,8 @@ spec: - spec.securityContext.runAsUser - spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups + - spec.securityContext.supplementalGroupsPolicy + - spec.containers[*].securityContext.appArmorProfile - spec.containers[*].securityContext.seLinuxOptions - spec.containers[*].securityContext.seccompProfile - spec.containers[*].securityContext.capabilities @@ -5622,6 +5935,7 @@ spec: - conditionType type: object type: array + x-kubernetes-list-type: atomic resourceClaims: description: |- ResourceClaims defines which ResourceClaims must be allocated @@ -5629,15 +5943,16 @@ spec: will be made available to those containers which consume them by name. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. items: description: |- - PodResourceClaim references exactly one ResourceClaim through a ClaimSource. + PodResourceClaim references exactly one ResourceClaim, either directly + or by naming a ResourceClaimTemplate which is then turned into a ResourceClaim + for the pod. + It adds a name to it that uniquely identifies the ResourceClaim inside the Pod. Containers that need access to the ResourceClaim reference it with this name. properties: @@ -5646,32 +5961,32 @@ spec: Name uniquely identifies this resource claim inside the pod. This must be a DNS_LABEL. type: string - source: - description: Source describes where to find the ResourceClaim. - properties: - resourceClaimName: - description: |- - ResourceClaimName is the name of a ResourceClaim object in the same - namespace as this pod. - type: string - resourceClaimTemplateName: - description: |- - ResourceClaimTemplateName is the name of a ResourceClaimTemplate - object in the same namespace as this pod. + resourceClaimName: + description: |- + ResourceClaimName is the name of a ResourceClaim object in the same + namespace as this pod. + Exactly one of ResourceClaimName and ResourceClaimTemplateName must + be set. + type: string + resourceClaimTemplateName: + description: |- + ResourceClaimTemplateName is the name of a ResourceClaimTemplate + object in the same namespace as this pod. - The template will be used to create a new ResourceClaim, which will - be bound to this pod. When this pod is deleted, the ResourceClaim - will also be deleted. The pod name and resource name, along with a - generated component, will be used to form a unique name for the - ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + The template will be used to create a new ResourceClaim, which will + be bound to this pod. When this pod is deleted, the ResourceClaim + will also be deleted. The pod name and resource name, along with a + generated component, will be used to form a unique name for the + ResourceClaim, which will be recorded in pod.status.resourceClaimStatuses. + This field is immutable and no changes will be made to the + corresponding ResourceClaim by the control plane after creating the + ResourceClaim. - This field is immutable and no changes will be made to the - corresponding ResourceClaim by the control plane after creating the - ResourceClaim. - type: string - type: object + Exactly one of ResourceClaimName and ResourceClaimTemplateName must + be set. + type: string required: - name type: object @@ -5705,11 +6020,7 @@ spec: If schedulingGates is not empty, the pod will stay in the SchedulingGated state and the scheduler will not attempt to schedule the pod. - SchedulingGates can only be set at pod creation time, and be removed only afterwards. - - - This is a beta feature enabled by the PodSchedulingReadiness feature gate. items: description: PodSchedulingGate is associated to a Pod to guard its scheduling. @@ -5731,18 +6042,39 @@ spec: SecurityContext holds pod-level security attributes and common container settings. Optional: Defaults to empty. See type description for default values of each field. properties: + appArmorProfile: + description: |- + appArmorProfile is the AppArmor options to use by the containers in this pod. + Note that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: |- + localhostProfile indicates a profile loaded on the node that should be used. + The profile must be preconfigured on the node to work. + Must match the loaded name of the profile. + Must be set if and only if type is "Localhost". + type: string + type: + description: |- + type indicates which kind of AppArmor profile will be applied. + Valid options are: + Localhost - a profile pre-loaded on the node. + RuntimeDefault - the container runtime's default profile. + Unconfined - no AppArmor enforcement. + type: string + required: + - type + type: object fsGroup: description: |- A special supplemental group that applies to all containers in a pod. Some volume types allow the Kubelet to change the ownership of that volume to be owned by the pod: - 1. The owning GID will be the FSGroup 2. The setgid bit is set (new files created in the volume will be owned by FSGroup) 3. The permission bits are OR'd with rw-rw---- - If unset, the Kubelet will not modify the ownership and permissions of any volume. Note that this field cannot be set when spec.os.name is windows. format: int64 @@ -5829,7 +6161,6 @@ spec: type indicates which kind of seccomp profile will be applied. Valid options are: - Localhost - a profile defined in a file on the node should be used. RuntimeDefault - the container runtime default profile should be used. Unconfined - no profile should be applied. @@ -5839,17 +6170,28 @@ spec: type: object supplementalGroups: description: |- - A list of groups applied to the first process run in each container, in addition - to the container's primary GID, the fsGroup (if specified), and group memberships - defined in the container image for the uid of the container process. If unspecified, - no additional groups are added to any container. Note that group memberships - defined in the container image for the uid of the container process are still effective, - even if they are not included in this list. + A list of groups applied to the first process run in each container, in + addition to the container's primary GID and fsGroup (if specified). If + the SupplementalGroupsPolicy feature is enabled, the + supplementalGroupsPolicy field determines whether these are in addition + to or instead of any group memberships defined in the container image. + If unspecified, no additional groups are added, though group memberships + defined in the container image may still be used, depending on the + supplementalGroupsPolicy field. Note that this field cannot be set when spec.os.name is windows. items: format: int64 type: integer type: array + x-kubernetes-list-type: atomic + supplementalGroupsPolicy: + description: |- + Defines how supplemental groups of the first container processes are calculated. + Valid values are "Merge" and "Strict". If not specified, "Merge" is used. + (Alpha) Using the field requires the SupplementalGroupsPolicy feature gate to be enabled + and the container runtime must implement support for this feature. + Note that this field cannot be set when spec.os.name is windows. + type: string sysctls: description: |- Sysctls hold a list of namespaced sysctls used for the pod. Pods with unsupported @@ -5870,6 +6212,7 @@ spec: - value type: object type: array + x-kubernetes-list-type: atomic windowsOptions: description: |- The Windows specific settings applied to all containers. @@ -5905,7 +6248,7 @@ spec: type: object serviceAccount: description: |- - DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. + DeprecatedServiceAccount is a deprecated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead. type: string serviceAccountName: @@ -5985,6 +6328,7 @@ spec: type: string type: object type: array + x-kubernetes-list-type: atomic topologySpreadConstraints: description: |- TopologySpreadConstraints describes how a group of pods ought to spread across topology @@ -6026,11 +6370,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6052,7 +6398,6 @@ spec: Keys that don't exist in the incoming pod labels will be ignored. A null or empty list means only match against labelSelector. - This is a beta field and requires the MatchLabelKeysInPodTopologySpread feature gate to be enabled (enabled by default). items: type: string @@ -6092,7 +6437,6 @@ spec: Valid values are integers greater than 0. When value is not nil, WhenUnsatisfiable must be DoNotSchedule. - For example, in a 3-zone cluster, MaxSkew is set to 2, MinDomains is set to 5 and pods with the same labelSelector spread as 2/2/2: | zone1 | zone2 | zone3 | @@ -6101,9 +6445,6 @@ spec: In this situation, new pod with the same labelSelector cannot be scheduled, because computed skew will be 3(3 - 0) if new Pod is scheduled to any of the three zones, it will violate MaxSkew. - - - This is a beta field and requires the MinDomainsInPodTopologySpread feature gate to be enabled (enabled by default). format: int32 type: integer nodeAffinityPolicy: @@ -6113,7 +6454,6 @@ spec: - Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations. - Ignore: nodeAffinity/nodeSelector are ignored. All nodes are included in the calculations. - If this value is nil, the behavior is equivalent to the Honor policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -6125,7 +6465,6 @@ spec: has a toleration, are included. - Ignore: node taints are ignored. All nodes are included. - If this value is nil, the behavior is equivalent to the Ignore policy. This is a beta-level feature default enabled by the NodeInclusionPolicyInPodTopologySpread feature flag. type: string @@ -6193,7 +6532,6 @@ spec: Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - TODO: how do we prevent errors in the filesystem from compromising the machine type: string partition: description: |- @@ -6233,6 +6571,7 @@ spec: the blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -6246,6 +6585,7 @@ spec: set). defaults to shared' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -6285,6 +6625,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic path: description: 'path is Optional: Used as the mounted root, rather than the full Ceph tree, default @@ -6307,10 +6648,13 @@ spec: More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -6346,10 +6690,13 @@ spec: to OpenStack. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -6414,11 +6761,15 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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: optional specify whether the ConfigMap @@ -6451,10 +6802,13 @@ spec: secret object contains more than one secret, all secret references are passed. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -6499,8 +6853,8 @@ spec: properties: fieldRef: description: 'Required: Selects a field of - the pod: only annotations, labels, name - and namespace are supported.' + the pod: only annotations, labels, name, + namespace and uid are supported.' properties: apiVersion: description: Version of the schema the @@ -6561,6 +6915,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object emptyDir: description: |- @@ -6594,7 +6949,6 @@ spec: The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, and deleted when the pod is removed. - Use this if: a) the volume is only needed while the pod runs, b) features of normal volumes like restoring from snapshot or capacity @@ -6605,17 +6959,14 @@ spec: information on the connection between this volume type and PersistentVolumeClaim). - Use PersistentVolumeClaim or one of the vendor-specific APIs for volumes that persist for longer than the lifecycle of an individual pod. - Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to be used that way - see the documentation of the driver for more information. - A pod can use both types of ephemeral volumes and persistent volumes at the same time. properties: @@ -6629,7 +6980,6 @@ spec: entry. Pod validation will reject the pod if the concatenated name is not valid for a PVC (for example, too long). - An existing PVC with that name that is not owned by the pod will *not* be used for the pod to avoid using an unrelated volume by mistake. Starting the pod is then blocked until @@ -6639,11 +6989,9 @@ spec: this should not be necessary, but it may be useful when manually reconstructing a broken cluster. - This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. - Required, must not be nil. properties: metadata: @@ -6683,6 +7031,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic dataSource: description: |- dataSource field can be used to specify either: @@ -6828,11 +7177,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -6860,8 +7211,8 @@ spec: If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass - (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -6887,7 +7238,6 @@ spec: fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - TODO: how do we prevent errors in the filesystem from compromising the machine type: string lun: description: 'lun is Optional: FC target lun number' @@ -6904,6 +7254,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic wwids: description: |- wwids Optional: FC volume world wide identifiers (wwids) @@ -6911,6 +7262,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object flexVolume: description: |- @@ -6947,10 +7299,13 @@ spec: scripts. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -6984,7 +7339,6 @@ spec: Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - TODO: how do we prevent errors in the filesystem from compromising the machine type: string partition: description: |- @@ -7065,9 +7419,6 @@ spec: used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - --- - TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not - mount host directories as read/write. properties: path: description: |- @@ -7084,6 +7435,41 @@ spec: required: - path type: object + image: + description: |- + image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. + The volume is resolved at pod startup depending on which PullPolicy value is provided: + + - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. + - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. + - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. + + The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. + A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. + The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. + The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. + The volume will be mounted read-only (ro) and non-executable files (noexec). + Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath). + The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. + Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. + IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -7104,7 +7490,6 @@ spec: Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - TODO: how do we prevent errors in the filesystem from compromising the machine type: string initiatorName: description: |- @@ -7116,6 +7501,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -7131,6 +7517,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic readOnly: description: |- readOnly here will force the ReadOnly setting in VolumeMounts. @@ -7141,10 +7528,13 @@ spec: target and initiator authentication properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -7263,24 +7653,24 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected - along with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: |- ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -7322,11 +7712,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -7405,11 +7797,15 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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: optional specify whether @@ -7432,8 +7828,8 @@ spec: fieldRef: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace are - supported.' + labels, name, namespace and uid + are supported.' properties: apiVersion: description: Version of the @@ -7499,6 +7895,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object secret: description: secret information about the @@ -7542,11 +7939,15 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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: optional field specify whether @@ -7585,6 +7986,7 @@ spec: type: object type: object type: array + x-kubernetes-list-type: atomic type: object quobyte: description: quobyte represents a Quobyte mount on the @@ -7635,7 +8037,6 @@ spec: Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - TODO: how do we prevent errors in the filesystem from compromising the machine type: string image: description: |- @@ -7643,6 +8044,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -7655,7 +8057,9 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -7675,14 +8079,18 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -7697,6 +8105,7 @@ spec: volume attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -7722,10 +8131,13 @@ spec: sensitive information. If this is not provided, Login operation will fail. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -7734,6 +8146,7 @@ spec: communication with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: |- storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. @@ -7810,6 +8223,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic optional: description: optional field specify whether the Secret or its keys must be defined @@ -7841,10 +8255,13 @@ spec: credentials. If not specified, default values will be attempted. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -7893,6 +8310,9 @@ spec: - name type: object type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map required: - containers type: object @@ -7961,11 +8381,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -7993,11 +8415,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic weight: @@ -8011,6 +8435,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -8055,11 +8480,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchFields: description: A list of node selector requirements by node's fields. @@ -8087,14 +8514,17 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic type: object x-kubernetes-map-type: atomic type: array + x-kubernetes-list-type: atomic required: - nodeSelectorTerms type: object @@ -8157,11 +8587,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8176,13 +8608,13 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8191,13 +8623,13 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8237,11 +8669,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8261,6 +8695,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -8283,6 +8718,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the affinity requirements specified by this field are not met at @@ -8333,11 +8769,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8352,13 +8790,13 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8367,13 +8805,13 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8413,11 +8851,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8437,6 +8877,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -8449,6 +8890,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object podAntiAffinity: description: Describes pod anti-affinity scheduling rules @@ -8507,11 +8949,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8526,13 +8970,13 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8541,13 +8985,13 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8587,11 +9031,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8611,6 +9057,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -8633,6 +9080,7 @@ spec: - weight type: object type: array + x-kubernetes-list-type: atomic requiredDuringSchedulingIgnoredDuringExecution: description: |- If the anti-affinity requirements specified by this field are not met at @@ -8683,11 +9131,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8702,13 +9152,13 @@ spec: description: |- MatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key in (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MatchLabelKeys and LabelSelector. - Also, MatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8717,13 +9167,13 @@ spec: description: |- MismatchLabelKeys is a set of pod label keys to select which pods will be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `LabelSelector` as `key notin (value)` + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` to select the group of existing pods which pods will be taken into consideration for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both MismatchLabelKeys and LabelSelector. - Also, MismatchLabelKeys cannot be set when LabelSelector isn't set. - This is an alpha field and requires enabling MatchLabelKeysInPodAffinity feature gate. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + This is a beta field and requires enabling MatchLabelKeysInPodAffinity feature gate (enabled by default). items: type: string type: array @@ -8763,11 +9213,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -8787,6 +9239,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic topologyKey: description: |- This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching @@ -8799,6 +9252,7 @@ spec: - topologyKey type: object type: array + x-kubernetes-list-type: atomic type: object type: object name: @@ -8838,11 +9292,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -8853,6 +9305,12 @@ spec: the Pod where this field is used. It makes that resource available inside a container. type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string required: - name type: object @@ -8956,6 +9414,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic dataSource: description: |- dataSource field can be used to specify either: @@ -9099,11 +9558,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -9131,8 +9592,8 @@ spec: If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass - (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -9160,7 +9621,6 @@ spec: Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#awselasticblockstore - TODO: how do we prevent errors in the filesystem from compromising the machine type: string partition: description: |- @@ -9200,6 +9660,7 @@ spec: the blob storage type: string fsType: + default: ext4 description: |- fsType is Filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -9213,6 +9674,7 @@ spec: set). defaults to shared' type: string readOnly: + default: false description: |- readOnly Defaults to false (read/write). ReadOnly here will force the ReadOnly setting in VolumeMounts. @@ -9252,6 +9714,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic path: description: 'path is Optional: Used as the mounted root, rather than the full Ceph tree, default @@ -9274,10 +9737,13 @@ spec: More info: https://examples.k8s.io/volumes/cephfs/README.md#how-to-use-it properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -9313,10 +9779,13 @@ spec: to OpenStack. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -9381,11 +9850,15 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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: optional specify whether the ConfigMap @@ -9418,10 +9891,13 @@ spec: secret object contains more than one secret, all secret references are passed. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -9466,8 +9942,8 @@ spec: properties: fieldRef: description: 'Required: Selects a field of - the pod: only annotations, labels, name - and namespace are supported.' + the pod: only annotations, labels, name, + namespace and uid are supported.' properties: apiVersion: description: Version of the schema the @@ -9528,6 +10004,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object emptyDir: description: |- @@ -9561,7 +10038,6 @@ spec: The volume's lifecycle is tied to the pod that defines it - it will be created before the pod starts, and deleted when the pod is removed. - Use this if: a) the volume is only needed while the pod runs, b) features of normal volumes like restoring from snapshot or capacity @@ -9572,17 +10048,14 @@ spec: information on the connection between this volume type and PersistentVolumeClaim). - Use PersistentVolumeClaim or one of the vendor-specific APIs for volumes that persist for longer than the lifecycle of an individual pod. - Use CSI for light-weight local ephemeral volumes if the CSI driver is meant to be used that way - see the documentation of the driver for more information. - A pod can use both types of ephemeral volumes and persistent volumes at the same time. properties: @@ -9596,7 +10069,6 @@ spec: entry. Pod validation will reject the pod if the concatenated name is not valid for a PVC (for example, too long). - An existing PVC with that name that is not owned by the pod will *not* be used for the pod to avoid using an unrelated volume by mistake. Starting the pod is then blocked until @@ -9606,11 +10078,9 @@ spec: this should not be necessary, but it may be useful when manually reconstructing a broken cluster. - This field is read-only and no changes will be made by Kubernetes to the PVC after it has been created. - Required, must not be nil. properties: metadata: @@ -9650,6 +10120,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic dataSource: description: |- dataSource field can be used to specify either: @@ -9795,11 +10266,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -9827,8 +10300,8 @@ spec: If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass - (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -9854,7 +10327,6 @@ spec: fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. Ex. "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. - TODO: how do we prevent errors in the filesystem from compromising the machine type: string lun: description: 'lun is Optional: FC target lun number' @@ -9871,6 +10343,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic wwids: description: |- wwids Optional: FC volume world wide identifiers (wwids) @@ -9878,6 +10351,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic type: object flexVolume: description: |- @@ -9914,10 +10388,13 @@ spec: scripts. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -9951,7 +10428,6 @@ spec: Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#gcepersistentdisk - TODO: how do we prevent errors in the filesystem from compromising the machine type: string partition: description: |- @@ -10032,9 +10508,6 @@ spec: used for system agents or other privileged things that are allowed to see the host machine. Most containers will NOT need this. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath - --- - TODO(jonesdl) We need to restrict who can use host directory mounts and who can/can not - mount host directories as read/write. properties: path: description: |- @@ -10051,6 +10524,41 @@ spec: required: - path type: object + image: + description: |- + image represents an OCI object (a container image or artifact) pulled and mounted on the kubelet's host machine. + The volume is resolved at pod startup depending on which PullPolicy value is provided: + + - Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. + - Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. + - IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. + + The volume gets re-resolved if the pod gets deleted and recreated, which means that new remote content will become available on pod recreation. + A failure to resolve or pull the image during pod startup will block containers from starting and may add significant latency. Failures will be retried using normal volume backoff and will be reported on the pod reason and message. + The types of objects that may be mounted by this volume are defined by the container runtime implementation on a host machine and at minimum must include all valid types supported by the container image field. + The OCI object gets mounted in a single directory (spec.containers[*].volumeMounts.mountPath) by merging the manifest layers in the same way as for container images. + The volume will be mounted read-only (ro) and non-executable files (noexec). + Sub path mounts for containers are not supported (spec.containers[*].volumeMounts.subpath). + The field spec.securityContext.fsGroupChangePolicy has no effect on this volume type. + properties: + pullPolicy: + description: |- + Policy for pulling OCI objects. Possible values are: + Always: the kubelet always attempts to pull the reference. Container creation will fail If the pull fails. + Never: the kubelet never pulls the reference and only uses a local image or artifact. Container creation will fail if the reference isn't present. + IfNotPresent: the kubelet pulls if the reference isn't already present on disk. Container creation will fail if the reference isn't present and the pull fails. + Defaults to Always if :latest tag is specified, or IfNotPresent otherwise. + type: string + reference: + description: |- + Required: Image or artifact reference to be used. + Behaves in the same way as pod.spec.containers[*].image. + Pull secrets will be assembled in the same way as for the container image by looking up node credentials, SA image pull secrets, and pod spec image pull secrets. + More info: https://kubernetes.io/docs/concepts/containers/images + This field is optional to allow higher level config management to default or override + container images in workload controllers like Deployments and StatefulSets. + type: string + type: object iscsi: description: |- iscsi represents an ISCSI Disk resource that is attached to a @@ -10071,7 +10579,6 @@ spec: Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#iscsi - TODO: how do we prevent errors in the filesystem from compromising the machine type: string initiatorName: description: |- @@ -10083,6 +10590,7 @@ spec: description: iqn is the target iSCSI Qualified Name. type: string iscsiInterface: + default: default description: |- iscsiInterface is the interface Name that uses an iSCSI transport. Defaults to 'default' (tcp). @@ -10098,6 +10606,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic readOnly: description: |- readOnly here will force the ReadOnly setting in VolumeMounts. @@ -10108,10 +10617,13 @@ spec: target and initiator authentication properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -10224,24 +10736,24 @@ spec: format: int32 type: integer sources: - description: sources is the list of volume projections + description: |- + sources is the list of volume projections. Each entry in this list + handles one source. items: - description: Projection that may be projected - along with other supported volume types + description: |- + Projection that may be projected along with other supported volume types. + Exactly one of these fields must be set. properties: clusterTrustBundle: description: |- ClusterTrustBundle allows a pod to access the `.spec.trustBundle` field of ClusterTrustBundle objects in an auto-updating file. - Alpha, gated by the ClusterTrustBundleProjection feature gate. - ClusterTrustBundle objects can either be selected by name, or by the combination of signer name and a label selector. - Kubelet performs aggressive normalization of the PEM contents written into the pod filesystem. Esoteric PEM features such as inter-block comments and block headers are stripped. Certificates are deduplicated. @@ -10283,11 +10795,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -10366,11 +10880,15 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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: optional specify whether @@ -10393,8 +10911,8 @@ spec: fieldRef: description: 'Required: Selects a field of the pod: only annotations, - labels, name and namespace are - supported.' + labels, name, namespace and uid + are supported.' properties: apiVersion: description: Version of the @@ -10460,6 +10978,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic type: object secret: description: secret information about the @@ -10503,11 +11022,15 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. 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: optional field specify whether @@ -10546,6 +11069,7 @@ spec: type: object type: object type: array + x-kubernetes-list-type: atomic type: object quobyte: description: quobyte represents a Quobyte mount on the @@ -10596,7 +11120,6 @@ spec: Tip: Ensure that the filesystem type is supported by the host operating system. Examples: "ext4", "xfs", "ntfs". Implicitly inferred to be "ext4" if unspecified. More info: https://kubernetes.io/docs/concepts/storage/volumes#rbd - TODO: how do we prevent errors in the filesystem from compromising the machine type: string image: description: |- @@ -10604,6 +11127,7 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it type: string keyring: + default: /etc/ceph/keyring description: |- keyring is the path to key ring for RBDUser. Default is /etc/ceph/keyring. @@ -10616,7 +11140,9 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic pool: + default: rbd description: |- pool is the rados pool name. Default is rbd. @@ -10636,14 +11162,18 @@ spec: More info: https://examples.k8s.io/volumes/rbd/README.md#how-to-use-it properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic user: + default: admin description: |- user is the rados user name. Default is admin. @@ -10658,6 +11188,7 @@ spec: volume attached and mounted on Kubernetes nodes. properties: fsType: + default: xfs description: |- fsType is the filesystem type to mount. Must be a filesystem type supported by the host operating system. @@ -10683,10 +11214,13 @@ spec: sensitive information. If this is not provided, Login operation will fail. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -10695,6 +11229,7 @@ spec: communication with Gateway, default false type: boolean storageMode: + default: ThinProvisioned description: |- storageMode indicates whether the storage for a volume should be ThickProvisioned or ThinProvisioned. Default is ThinProvisioned. @@ -10771,6 +11306,7 @@ spec: - path type: object type: array + x-kubernetes-list-type: atomic optional: description: optional field specify whether the Secret or its keys must be defined @@ -10802,10 +11338,13 @@ spec: credentials. If not specified, default values will be attempted. properties: name: + default: "" description: |- Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - TODO: Add other useful fields. apiVersion, kind, uid? type: string type: object x-kubernetes-map-type: atomic @@ -10868,6 +11407,7 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic dataSource: description: |- dataSource field can be used to specify either: @@ -11007,11 +11547,13 @@ spec: items: type: string type: array + x-kubernetes-list-type: atomic required: - key - operator type: object type: array + x-kubernetes-list-type: atomic matchLabels: additionalProperties: type: string @@ -11039,8 +11581,8 @@ spec: If the resource referred to by volumeAttributesClass does not exist, this PersistentVolumeClaim will be set to a Pending state, as reflected by the modifyVolumeStatus field, until such as a resource exists. - More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#volumeattributesclass - (Alpha) Using this field requires the VolumeAttributesClass feature gate to be enabled. + More info: https://kubernetes.io/docs/concepts/storage/volume-attributes-classes/ + (Beta) Using this field requires the VolumeAttributesClass feature gate to be enabled (off by default). type: string volumeMode: description: |- @@ -11071,11 +11613,9 @@ spec: Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. - This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. - This field is immutable. It can only be set for containers. items: description: ResourceClaim references one entry in PodSpec.ResourceClaims. @@ -11086,6 +11626,12 @@ spec: the Pod where this field is used. It makes that resource available inside a container. type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string required: - name type: object @@ -11255,24 +11801,8 @@ spec: description: TrackedTasks tracks the tasks for completion that were created by the cass-operator items: - description: |- - ObjectReference contains enough information to let you inspect or modify the referred object. - --- - New uses of this type are discouraged because of difficulty describing its usage when embedded in APIs. - 1. Ignored fields. It includes many fields which are not generally honored. For instance, ResourceVersion and FieldPath are both very rarely valid in actual usage. - 2. Invalid usage help. It is impossible to add specific help for individual usage. In most embedded usages, there are particular - restrictions like, "must refer only to types A and B" or "UID not honored" or "name must be restricted". - Those cannot be well described when embedded. - 3. Inconsistent validation. Because the usages are different, the validation rules are different by usage, which makes it hard for users to predict what will happen. - 4. The fields are both imprecise and overly precise. Kind is not a precise mapping to a URL. This can produce ambiguity - during interpretation and require a REST mapping. In most cases, the dependency is on the group,resource tuple - and the version of the actual struct is irrelevant. - 5. We cannot easily change it. Because this type is embedded in many locations, updates to this type - will affect numerous schemas. Don't make new APIs embed an underspecified API type they do not control. - - - Instead of using this type, create a locally provided and used type that is well-focused on your reference. - For example, ServiceReferences for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533 . + description: ObjectReference contains enough information to let + you inspect or modify the referred object. properties: apiVersion: description: API version of the referent. @@ -11286,7 +11816,6 @@ spec: the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. type: string kind: description: |- diff --git a/config/crd/bases/control.k8ssandra.io_cassandratasks.yaml b/config/crd/bases/control.k8ssandra.io_cassandratasks.yaml index a0dc841c..320d4723 100644 --- a/config/crd/bases/control.k8ssandra.io_cassandratasks.yaml +++ b/config/crd/bases/control.k8ssandra.io_cassandratasks.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.15.0 + controller-gen.kubebuilder.io/version: v0.16.4 name: cassandratasks.control.k8ssandra.io spec: group: control.k8ssandra.io @@ -84,7 +84,6 @@ spec: the event) or if no container name is specified "spec.containers[2]" (container with index 2 in this pod). This syntax is chosen only to have some well-defined way of referencing a part of an object. - TODO: this design is not final and this field is subject to change in the future. type: string kind: description: |- @@ -210,16 +209,8 @@ spec: type "Complete" and status true. More info: https://kubernetes.io/docs/concepts/workloads/controllers/jobs-run-to-completion/ items: - description: "Condition contains details for one aspect of the current - state of this API Resource.\n---\nThis struct is intended for - direct use as an array at the field path .status.conditions. For - example,\n\n\n\ttype FooStatus struct{\n\t // Represents the - observations of a foo's current state.\n\t // Known .status.conditions.type - are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // - +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t - \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" - patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t - \ // other fields\n\t}" + description: Condition contains details for one aspect of the current + state of this API Resource. properties: lastTransitionTime: description: |- @@ -260,12 +251,7 @@ spec: - Unknown type: string type: - description: |- - type of condition in CamelCase or in foo.example.com/CamelCase. - --- - Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be - useful (see .node.status.conditions), the ability to deconflict is important. - The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + description: type of condition in CamelCase or in foo.example.com/CamelCase. maxLength: 316 pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ type: string diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 781b36dd..44a81dda 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -6,19 +6,6 @@ resources: - bases/control.k8ssandra.io_cassandratasks.yaml #+kubebuilder:scaffold:crdkustomizeresource -patchesJson6902: -- target: - group: apiextensions.k8s.io - version: v1 - kind: CustomResourceDefinition - name: cassandradatacenters.cassandra.datastax.com - path: patches/config_removal.yaml -- target: - group: apiextensions.k8s.io - version: v1 - kind: CustomResourceDefinition - name: cassandradatacenters.cassandra.datastax.com - path: patches/remove_xkeys.yaml # name: controller-manager # namespace: system # patch: |- @@ -28,7 +15,6 @@ patchesJson6902: # path: /spec/template/spec/containers/1/volumeMounts/0 -patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD #- patches/webhook_in_cassandradatacenters.yaml @@ -44,3 +30,18 @@ patchesStrategicMerge: # the following config is for teaching kustomize how to do kustomization for CRDs. configurations: - kustomizeconfig.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +patches: +- path: patches/config_removal.yaml + target: + group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: cassandradatacenters.cassandra.datastax.com + version: v1 +- path: patches/remove_xkeys.yaml + target: + group: apiextensions.k8s.io + kind: CustomResourceDefinition + name: cassandradatacenters.cassandra.datastax.com + version: v1 diff --git a/config/crd/kustomizeconfig.yaml b/config/crd/kustomizeconfig.yaml index d12e601e..ec5c150a 100644 --- a/config/crd/kustomizeconfig.yaml +++ b/config/crd/kustomizeconfig.yaml @@ -1,19 +1,19 @@ -# # This file is for teaching kustomize how to substitute name and namespace reference in CRD -# nameReference: -# - kind: Service -# version: v1 -# fieldSpecs: -# - kind: CustomResourceDefinition -# version: v1 -# group: apiextensions.k8s.io -# path: spec/conversion/webhook/clientConfig/service/name +# This file is for teaching kustomize how to substitute name and namespace reference in CRD +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/name -# namespace: -# - kind: CustomResourceDefinition -# version: v1 -# group: apiextensions.k8s.io -# path: spec/conversion/webhook/clientConfig/service/namespace -# create: false +namespace: +- kind: CustomResourceDefinition + version: v1 + group: apiextensions.k8s.io + path: spec/conversion/webhook/clientConfig/service/namespace + create: false varReference: - path: metadata/annotations diff --git a/config/crd/patches/cainjection_in_cassandradatacenters.yaml b/config/crd/patches/cainjection_in_cassandradatacenters.yaml deleted file mode 100644 index afaedb9b..00000000 --- a/config/crd/patches/cainjection_in_cassandradatacenters.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: cassandradatacenters.cassandra.datastax.com diff --git a/config/crd/patches/cainjection_in_cassandratasks.yaml b/config/crd/patches/cainjection_in_cassandratasks.yaml deleted file mode 100644 index d9caf204..00000000 --- a/config/crd/patches/cainjection_in_cassandratasks.yaml +++ /dev/null @@ -1,7 +0,0 @@ -# The following patch adds a directive for certmanager to inject CA into the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) - name: cassandrajobs.control.k8ssandra.io diff --git a/config/crd/patches/webhook_in_cassandradatacenters.yaml b/config/crd/patches/webhook_in_cassandradatacenters.yaml deleted file mode 100644 index 07d7aba0..00000000 --- a/config/crd/patches/webhook_in_cassandradatacenters.yaml +++ /dev/null @@ -1,14 +0,0 @@ -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: cassandradatacenters.cassandra.datastax.com -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert diff --git a/config/crd/patches/webhook_in_cassandratasks.yaml b/config/crd/patches/webhook_in_cassandratasks.yaml deleted file mode 100644 index 7b271a2b..00000000 --- a/config/crd/patches/webhook_in_cassandratasks.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# The following patch enables a conversion webhook for the CRD -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - name: cassandrajobs.control.k8ssandra.io -spec: - conversion: - strategy: Webhook - webhook: - clientConfig: - service: - namespace: system - name: webhook-service - path: /convert - conversionReviewVersions: - - v1 diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 43a9b2f0..b73e0444 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -1,74 +1,23 @@ -# Adds namespace to all resources. -# namespace: cass-operator - -# Value of this field is prepended to the -# names of all resources, e.g. a deployment named -# "wordpress" becomes "alices-wordpress". -# Note that it should also match with the prefix (text before '-') of the namespace -# field above. -# namePrefix: cass-operator- - # Labels to add to all resources and selectors. -#commonLabels: -# someName: someValue +labels: + - includeSelectors: false + pairs: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize -bases: +resources: - ../crd - ../rbac - ../manager -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -# - ../webhook -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. -# - ../certmanager -# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. -#- ../prometheus - -patchesStrategicMerge: -# Protect the /metrics endpoint by putting it behind auth. -# If you want your controller-manager to expose the /metrics -# endpoint w/o any authn/z, please comment the following line. -#- manager_auth_proxy_patch.yaml - -# Mount the controller config file for loading manager configurations -# through a ComponentConfig type -- manager_config_patch.yaml - -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -# - manager_webhook_patch.yaml - -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. -# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. -# 'CERTMANAGER' needs to be enabled to use ca injection -# - webhookcainjection_patch.yaml - -# # the following config is for teaching kustomize how to do var substitution -# vars: -# # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. -# - name: CERTIFICATE_NAMESPACE # namespace of the certificate CR -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# fieldref: -# fieldpath: metadata.namespace -# - name: CERTIFICATE_NAME -# objref: -# kind: Certificate -# group: cert-manager.io -# version: v1 -# name: serving-cert # this name should match the one in certificate.yaml -# - name: SERVICE_NAMESPACE # namespace of the service -# objref: -# kind: Service -# version: v1 -# name: webhook-service -# fieldref: -# fieldpath: metadata.namespace -# - name: SERVICE_NAME -# objref: -# kind: Service -# version: v1 -# name: webhook-service +- metrics_service.yaml + +# Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager +patches: +# [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443. +# More info: https://book.kubebuilder.io/reference/metrics +- path: manager_metrics_patch.yaml + target: + kind: Deployment +- path: manager_config_patch.yaml + target: + kind: Deployment diff --git a/config/default/manager_metrics_patch.yaml b/config/default/manager_metrics_patch.yaml new file mode 100644 index 00000000..2aaef653 --- /dev/null +++ b/config/default/manager_metrics_patch.yaml @@ -0,0 +1,4 @@ +# This patch adds the args to allow exposing the metrics endpoint using HTTPS +- op: add + path: /spec/template/spec/containers/0/args/0 + value: --metrics-bind-address=:8443 diff --git a/config/components/auth-proxy/rbac/auth_proxy_service.yaml b/config/default/metrics_service.yaml similarity index 66% rename from config/components/auth-proxy/rbac/auth_proxy_service.yaml rename to config/default/metrics_service.yaml index 6cf656be..f7e62068 100644 --- a/config/components/auth-proxy/rbac/auth_proxy_service.yaml +++ b/config/default/metrics_service.yaml @@ -3,12 +3,15 @@ kind: Service metadata: labels: control-plane: controller-manager + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize name: controller-manager-metrics-service namespace: system spec: ports: - name: https port: 8443 - targetPort: https + protocol: TCP + targetPort: 8443 selector: control-plane: controller-manager diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml deleted file mode 100644 index a350db40..00000000 --- a/config/default/webhookcainjection_patch.yaml +++ /dev/null @@ -1,15 +0,0 @@ -# This patch add annotation to admission webhook config and -# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. -# apiVersion: admissionregistration.k8s.io/v1 -# kind: MutatingWebhookConfiguration -# metadata: -# name: mutating-webhook-configuration -# annotations: -# cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) ---- -apiVersion: admissionregistration.k8s.io/v1 -kind: ValidatingWebhookConfiguration -metadata: - name: validating-webhook-configuration - annotations: - cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/config/deployments/default/kustomization.yaml b/config/deployments/default/kustomization.yaml index 8510cf2a..d4c41431 100644 --- a/config/deployments/default/kustomization.yaml +++ b/config/deployments/default/kustomization.yaml @@ -10,3 +10,101 @@ resources: components: - ../../components/namespace - ../../components/webhook + +replacements: +- source: # Uncomment the following block if you have any webhook + kind: Service + version: v1 + name: webhook-service + fieldPath: .metadata.name # Name of the service + targets: + - select: + kind: Certificate + group: cert-manager.io + version: v1 + fieldPaths: + - .spec.dnsNames.0 + - .spec.dnsNames.1 + options: + delimiter: '.' + index: 0 + create: true +- source: + kind: Service + version: v1 + name: webhook-service + fieldPath: .metadata.namespace # Namespace of the service + targets: + - select: + kind: Certificate + group: cert-manager.io + version: v1 + fieldPaths: + - .spec.dnsNames.0 + - .spec.dnsNames.1 + options: + delimiter: '.' + index: 1 + create: true + +- source: # Uncomment the following block if you have a ValidatingWebhook (--programmatic-validation) + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # This name should match the one in certificate.yaml + fieldPath: .metadata.namespace # Namespace of the certificate CR + targets: + - select: + kind: ValidatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + create: true +- source: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # This name should match the one in certificate.yaml + fieldPath: .metadata.name + targets: + - select: + kind: ValidatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 1 + create: true + +- source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting ) + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # This name should match the one in certificate.yaml + fieldPath: .metadata.namespace # Namespace of the certificate CR + targets: + - select: + kind: MutatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + create: true +- source: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # This name should match the one in certificate.yaml + fieldPath: .metadata.name + targets: + - select: + kind: MutatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 1 + create: true diff --git a/config/manager/controller_manager_config.yaml b/config/manager/controller_manager_config.yaml index 095232db..372e1f87 100644 --- a/config/manager/controller_manager_config.yaml +++ b/config/manager/controller_manager_config.yaml @@ -2,14 +2,5 @@ apiVersion: config.k8ssandra.io/v1beta1 kind: OperatorConfig metadata: name: operator-config -health: - healthProbeBindAddress: :8081 -metrics: - bindAddress: 127.0.0.1:8080 -webhook: - port: 9443 -leaderElection: - leaderElect: true - resourceName: b569adb7.cassandra.datastax.com disableWebhooks: true imageConfigFile: /configs/image_config.yaml diff --git a/config/manager/image_config.yaml b/config/manager/image_config.yaml index 60542c60..ed7a3647 100644 --- a/config/manager/image_config.yaml +++ b/config/manager/image_config.yaml @@ -3,9 +3,9 @@ kind: ImageConfig metadata: name: image-config images: - system-logger: "k8ssandra/system-logger:latest" + system-logger: "k8ssandra/system-logger:v1.24.0-dev.a8fa96c-20241219" config-builder: "datastax/cass-config-builder:1.0-ubi8" - k8ssandra-client: "k8ssandra/k8ssandra-client:v0.5.0" + k8ssandra-client: "k8ssandra/k8ssandra-client:v0.6.0" # cassandra: # "4.0.0": "k8ssandra/cassandra-ubi:latest" # dse: diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index 7621efda..20bb3bb5 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -14,4 +14,4 @@ kind: Kustomization images: - name: controller newName: k8ssandra/cass-operator - newTag: latest + newTag: v1.24.0-dev.a8fa96c-20241219 diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index fe822651..6604eebe 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -6,6 +6,8 @@ metadata: namespace: system labels: control-plane: controller-manager + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize spec: selector: matchLabels: @@ -14,22 +16,30 @@ spec: replicas: 1 template: metadata: + annotations: + kubectl.kubernetes.io/default-container: manager labels: name: cass-operator control-plane: controller-manager spec: securityContext: runAsNonRoot: true + seccompProfile: + type: RuntimeDefault containers: - command: - /manager args: - - --leader-elect + - --leader-elect + - --health-probe-bind-address=:8081 image: controller:latest name: manager imagePullPolicy: IfNotPresent securityContext: allowPrivilegeEscalation: false + capabilities: + drop: + - "ALL" livenessProbe: httpGet: path: /healthz @@ -44,11 +54,11 @@ spec: periodSeconds: 10 resources: limits: - cpu: 200m - memory: 100Mi + cpu: 500m + memory: 128Mi requests: cpu: 100m - memory: 20Mi + memory: 64Mi env: - name: WATCH_NAMESPACE valueFrom: diff --git a/config/network-policy/allow-metrics-traffic.yaml b/config/network-policy/allow-metrics-traffic.yaml new file mode 100644 index 00000000..6b9453b2 --- /dev/null +++ b/config/network-policy/allow-metrics-traffic.yaml @@ -0,0 +1,26 @@ +# This NetworkPolicy allows ingress traffic +# with Pods running on namespaces labeled with 'metrics: enabled'. Only Pods on those +# namespaces are able to gathering data from the metrics endpoint. +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize + name: allow-metrics-traffic + namespace: system +spec: + podSelector: + matchLabels: + control-plane: controller-manager + policyTypes: + - Ingress + ingress: + # This allows ingress traffic from any namespace with the label metrics: enabled + - from: + - namespaceSelector: + matchLabels: + metrics: enabled # Only from namespaces with this label + ports: + - port: 8443 + protocol: TCP diff --git a/config/network-policy/allow-webhook-traffic.yaml b/config/network-policy/allow-webhook-traffic.yaml new file mode 100644 index 00000000..225868e7 --- /dev/null +++ b/config/network-policy/allow-webhook-traffic.yaml @@ -0,0 +1,26 @@ +# This NetworkPolicy allows ingress traffic to your webhook server running +# as part of the controller-manager from specific namespaces and pods. CR(s) which uses webhooks +# will only work when applied in namespaces labeled with 'webhook: enabled' +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + labels: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize + name: allow-webhook-traffic + namespace: system +spec: + podSelector: + matchLabels: + control-plane: controller-manager + policyTypes: + - Ingress + ingress: + # This allows ingress traffic from any namespace with the label webhook: enabled + - from: + - namespaceSelector: + matchLabels: + webhook: enabled # Only from namespaces with this label + ports: + - port: 443 + protocol: TCP diff --git a/config/network-policy/kustomization.yaml b/config/network-policy/kustomization.yaml new file mode 100644 index 00000000..0872bee1 --- /dev/null +++ b/config/network-policy/kustomization.yaml @@ -0,0 +1,3 @@ +resources: +- allow-webhook-traffic.yaml +- allow-metrics-traffic.yaml diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml index d19136ae..f578506f 100644 --- a/config/prometheus/monitor.yaml +++ b/config/prometheus/monitor.yaml @@ -4,16 +4,22 @@ apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: labels: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize control-plane: controller-manager name: controller-manager-metrics-monitor namespace: system spec: endpoints: - path: /metrics - port: https + port: https # Ensure this is the name of the port that exposes HTTPS metrics scheme: https bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token tlsConfig: + # Please use the following options for secure configurations: + # caFile: /etc/metrics-certs/ca.crt + # certFile: /etc/metrics-certs/tls.crt + # keyFile: /etc/metrics-certs/tls.key insecureSkipVerify: true selector: matchLabels: diff --git a/config/components/auth-proxy/rbac/auth_proxy_role.yaml b/config/rbac/metrics_auth_role.yaml similarity index 50% rename from config/components/auth-proxy/rbac/auth_proxy_role.yaml rename to config/rbac/metrics_auth_role.yaml index 618f5e41..32d2e4ec 100644 --- a/config/components/auth-proxy/rbac/auth_proxy_role.yaml +++ b/config/rbac/metrics_auth_role.yaml @@ -1,13 +1,17 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: - name: proxy-role + name: metrics-auth-role rules: -- apiGroups: ["authentication.k8s.io"] +- apiGroups: + - authentication.k8s.io resources: - tokenreviews - verbs: ["create"] -- apiGroups: ["authorization.k8s.io"] + verbs: + - create +- apiGroups: + - authorization.k8s.io resources: - subjectaccessreviews - verbs: ["create"] + verbs: + - create diff --git a/config/components/auth-proxy/rbac/auth_proxy_role_binding.yaml b/config/rbac/metrics_auth_role_binding.yaml similarity index 79% rename from config/components/auth-proxy/rbac/auth_proxy_role_binding.yaml rename to config/rbac/metrics_auth_role_binding.yaml index ec7acc0a..e775d67f 100644 --- a/config/components/auth-proxy/rbac/auth_proxy_role_binding.yaml +++ b/config/rbac/metrics_auth_role_binding.yaml @@ -1,11 +1,11 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: proxy-rolebinding + name: metrics-auth-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: proxy-role + name: metrics-auth-role subjects: - kind: ServiceAccount name: controller-manager diff --git a/config/components/auth-proxy/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/metrics_reader_role.yaml similarity index 66% rename from config/components/auth-proxy/rbac/auth_proxy_client_clusterrole.yaml rename to config/rbac/metrics_reader_role.yaml index bd4af137..51a75db4 100644 --- a/config/components/auth-proxy/rbac/auth_proxy_client_clusterrole.yaml +++ b/config/rbac/metrics_reader_role.yaml @@ -3,5 +3,7 @@ kind: ClusterRole metadata: name: metrics-reader rules: -- nonResourceURLs: ["/metrics"] - verbs: ["get"] +- nonResourceURLs: + - "/metrics" + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index b59de614..9082f7b5 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -27,6 +27,30 @@ metadata: name: manager-role namespace: cass-operator rules: +- apiGroups: + - "" + resources: + - configmaps + - endpoints + - events + - persistentvolumeclaims + - pods + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get - apiGroups: - apps resources: @@ -101,43 +125,6 @@ rules: - get - patch - update -- apiGroups: - - "" - resources: - - configmaps - - endpoints - - events - - persistentvolumeclaims - - pods - - secrets - - services - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - events - - pods - verbs: - - create - - delete - - get - - list - - patch - - update - - watch -- apiGroups: - - "" - resources: - - namespaces - verbs: - - get - apiGroups: - policy resources: diff --git a/config/rbac/service_account.yaml b/config/rbac/service_account.yaml index 69ece2e4..bf638788 100644 --- a/config/rbac/service_account.yaml +++ b/config/rbac/service_account.yaml @@ -1,4 +1,7 @@ apiVersion: v1 kind: ServiceAccount metadata: + labels: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize name: controller-manager diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml index 25e21e3c..30293f0f 100644 --- a/config/webhook/kustomizeconfig.yaml +++ b/config/webhook/kustomizeconfig.yaml @@ -20,6 +20,3 @@ namespace: group: admissionregistration.k8s.io path: webhooks/clientConfig/service/namespace create: true - -varReference: -- path: metadata/annotations diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 8a34529f..99172d68 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -1,12 +1,37 @@ --- apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-cassandra-datastax-com-v1beta1-cassandradatacenter + failurePolicy: Fail + name: mcassandradatacenter.kb.io + rules: + - apiGroups: + - cassandra.datastax.com + apiVersions: + - v1beta1 + operations: + - CREATE + - UPDATE + resources: + - cassandradatacenters + sideEffects: None +--- +apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration metadata: name: validating-webhook-configuration webhooks: - admissionReviewVersions: - v1 - - v1beta1 clientConfig: service: name: webhook-service diff --git a/config/webhook/service.yaml b/config/webhook/service.yaml index 31e0f829..b004f001 100644 --- a/config/webhook/service.yaml +++ b/config/webhook/service.yaml @@ -4,6 +4,9 @@ kind: Service metadata: name: webhook-service namespace: system + labels: + app.kubernetes.io/name: cass-operator + app.kubernetes.io/managed-by: kustomize spec: ports: - port: 443 diff --git a/go.mod b/go.mod index 33ba1003..996bff04 100644 --- a/go.mod +++ b/go.mod @@ -1,82 +1,110 @@ module github.com/k8ssandra/cass-operator -go 1.22 +go 1.23.0 + +toolchain go1.23.4 require ( - github.com/davecgh/go-spew v1.1.1 - github.com/go-logr/logr v1.4.1 - github.com/google/uuid v1.3.0 + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc + github.com/go-logr/logr v1.4.2 + github.com/google/uuid v1.6.0 github.com/onsi/gomega v1.33.1 github.com/pavel-v-chernykh/keystore-go v2.1.0+incompatible github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.8.4 - golang.org/x/oauth2 v0.12.0 // indirect - golang.org/x/term v0.20.0 + github.com/stretchr/testify v1.9.0 + golang.org/x/oauth2 v0.21.0 // indirect + golang.org/x/term v0.21.0 gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.29.2 - k8s.io/apimachinery v0.29.2 - k8s.io/client-go v0.29.2 - sigs.k8s.io/controller-runtime v0.17.4 + k8s.io/api v0.31.0 + k8s.io/apimachinery v0.31.0 + k8s.io/client-go v0.31.0 + sigs.k8s.io/controller-runtime v0.19.3 ) require ( github.com/Jeffail/gabs/v2 v2.7.0 github.com/google/go-cmp v0.6.0 github.com/onsi/ginkgo/v2 v2.19.0 - github.com/prometheus/client_golang v1.18.0 + github.com/prometheus/client_golang v1.19.1 go.uber.org/zap v1.26.0 golang.org/x/mod v0.17.0 - k8s.io/utils v0.0.0-20230726121419-3b25d923346b + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 ) require ( + github.com/antlr4-go/antlr/v4 v4.13.0 // indirect + github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/blang/semver/v4 v4.0.0 // indirect + github.com/cenkalti/backoff/v4 v4.3.0 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/emicklei/go-restful/v3 v3.11.0 // indirect github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.8.0 // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/zapr v1.3.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/go-task/slim-sprig/v3 v3.0.0 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.3 // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/cel-go v0.20.1 // indirect github.com/google/gnostic-models v0.6.8 // indirect github.com/google/gofuzz v1.2.0 // indirect - github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 // indirect + github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af // indirect + github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect github.com/imdario/mergo v0.3.15 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_model v0.5.0 // indirect - github.com/prometheus/common v0.45.0 // indirect - github.com/prometheus/procfs v0.12.0 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect + github.com/spf13/cobra v1.8.1 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.5.0 // indirect + github.com/stoewer/go-strcase v1.2.0 // indirect + github.com/stretchr/objx v0.5.2 // indirect + github.com/x448/float16 v0.8.4 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect + go.opentelemetry.io/otel v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect + go.opentelemetry.io/otel/metric v1.28.0 // indirect + go.opentelemetry.io/otel/sdk v1.28.0 // indirect + go.opentelemetry.io/otel/trace v1.28.0 // indirect + go.opentelemetry.io/proto/otlp v1.3.1 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect + golang.org/x/net v0.26.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.21.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.33.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect + google.golang.org/grpc v1.65.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect + gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.29.2 // indirect - k8s.io/component-base v0.29.2 // indirect - k8s.io/klog/v2 v2.110.1 // indirect - k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/apiserver v0.31.0 // indirect + k8s.io/component-base v0.31.0 // indirect + k8s.io/klog/v2 v2.130.1 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect sigs.k8s.io/yaml v1.4.0 // indirect diff --git a/go.sum b/go.sum index 0eab4311..b1ea960c 100644 --- a/go.sum +++ b/go.sum @@ -1,57 +1,77 @@ github.com/Jeffail/gabs/v2 v2.7.0 h1:Y2edYaTcE8ZpRsR2AtmPu5xQdFDIthFG0jYhu5PY8kg= github.com/Jeffail/gabs/v2 v2.7.0/go.mod h1:dp5ocw1FvBBQYssgHsG7I1WYsiLRtkUaB1FEtSwvNUw= +github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI= +github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA= +github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM= +github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= +github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= +github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.8.0 h1:lRj6N9Nci7MvzrXuX6HFzU8XjmhPiXPlsKEy1u0KQro= -github.com/evanphx/json-patch/v5 v5.8.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= +github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= +github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= -github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= +github.com/google/cel-go v0.20.1 h1:nDx9r8S3L4pE61eDdt8igGj8rf5kjYR3ILxWIpWNi84= +github.com/google/cel-go v0.20.1/go.mod h1:kWcIzTsPX0zmQ+H3TirHstLLf9ep5QTsZBN9u4dOYLg= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6 h1:k7nVchz72niMH6YLQNvHSdIE7iqsQxK1P41mySCvssg= -github.com/google/pprof v0.0.0-20240424215950-a892ee059fd6/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0= +github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k= github.com/imdario/mergo v0.3.15 h1:M8XP7IuFNsqUx6VPK2P9OSmsYsI/YFaGil0uD21V3dM= github.com/imdario/mergo v0.3.15/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -67,8 +87,6 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= -github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -84,32 +102,58 @@ github.com/pavel-v-chernykh/keystore-go v2.1.0+incompatible h1:Jd6xfriVlJ6hWPvYO github.com/pavel-v-chernykh/keystore-go v2.1.0+incompatible/go.mod h1:xlUlxe/2ItGlQyMTstqeDv9r3U4obH7xYd26TbDQutY= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 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= -github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= -github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= -github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 h1:4K4tsIXefpVJtvA/8srF4V4y0akAoPHkIslgAkjixJA= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0/go.mod h1:jjdQuTGVsXV4vSs+CJ2qYDeDPf9yIJV23qlIzBm73Vg= +go.opentelemetry.io/otel v1.28.0 h1:/SqNcYk+idO0CxKEUOtKQClMK/MimZihKYMruSMViUo= +go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIjUIX9z4= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY= +go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 h1:qFffATk0X+HD+f1Z8lswGiOQYKHRlzfmdJm0wEaVrFA= +go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0/go.mod h1:MOiCmryaYtc+V0Ei+Tx9o5S1ZjA7kzLucuVuyzBZloQ= +go.opentelemetry.io/otel/metric v1.28.0 h1:f0HGvSl1KRAU1DLgLGFjrwVyismPlnuU6JD6bOeuA5Q= +go.opentelemetry.io/otel/metric v1.28.0/go.mod h1:Fb1eVBFZmLVTMb6PPohq3TO9IIhUisDsbJoL/+uQW4s= +go.opentelemetry.io/otel/sdk v1.28.0 h1:b9d7hIry8yZsgtbmM0DKyPWMMUMlK9NEKuIG4aBqWyE= +go.opentelemetry.io/otel/sdk v1.28.0/go.mod h1:oYj7ClPUA7Iw3m+r7GeEjz0qckQRJK2B8zjcZEfu7Pg= +go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+lkx9g= +go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI= +go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0= +go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -119,85 +163,94 @@ go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 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-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= -golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= 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/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= -golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 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/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157 h1:7whR9kGa5LUwFtpLm2ArCEejtnxlGeLbAyjFY8sGNFw= +google.golang.org/genproto/googleapis/api v0.0.0-20240528184218-531527333157/go.mod h1:99sLkeliLXfdj2J75X3Ho+rrVCaJze0uwN7zDDkjPVU= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 h1:BwIjyKYGsK9dMCBOorzRri8MQwmi7mT9rGHsCEinZkA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/grpc v1.65.0 h1:bs/cUb4lp1G5iImFFd3u5ixQzweKizoZJAwBNLR42lc= +google.golang.org/grpc v1.65.0/go.mod h1:WgYC2ypjlB0EiQi6wdKixMqukr6lBc0Vo+oOgjrM5ZQ= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= -k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= -k8s.io/apiextensions-apiserver v0.29.2 h1:UK3xB5lOWSnhaCk0RFZ0LUacPZz9RY4wi/yt2Iu+btg= -k8s.io/apiextensions-apiserver v0.29.2/go.mod h1:aLfYjpA5p3OwtqNXQFkhJ56TB+spV8Gc4wfMhUA3/b8= -k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= -k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= -k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= -k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= -k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8= -k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.17.4 h1:AMf1E0+93/jLQ13fb76S6Atwqp24EQFCmNbG84GJxew= -sigs.k8s.io/controller-runtime v0.17.4/go.mod h1:N0jpP5Lo7lMTF9aL56Z/B2oWBJjey6StQM0jRbKQXtY= +k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo= +k8s.io/api v0.31.0/go.mod h1:0YiFF+JfFxMM6+1hQei8FY8M7s1Mth+z/q7eF1aJkTE= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= +k8s.io/apimachinery v0.31.0 h1:m9jOiSr3FoSSL5WO9bjm1n6B9KROYYgNZOb4tyZ1lBc= +k8s.io/apimachinery v0.31.0/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= +k8s.io/apiserver v0.31.0 h1:p+2dgJjy+bk+B1Csz+mc2wl5gHwvNkC9QJV+w55LVrY= +k8s.io/apiserver v0.31.0/go.mod h1:KI9ox5Yu902iBnnyMmy7ajonhKnkeZYJhTZ/YI+WEMk= +k8s.io/client-go v0.31.0 h1:QqEJzNjbN2Yv1H79SsS+SWnXkBgVu4Pj3CJQgbx0gI8= +k8s.io/client-go v0.31.0/go.mod h1:Y9wvC76g4fLjmU0BA+rV+h2cncoadjvjjkkIGoTLcGU= +k8s.io/component-base v0.31.0 h1:/KIzGM5EvPNQcYgwq5NwoQBaOlVFrghoVGr8lG6vNRs= +k8s.io/component-base v0.31.0/go.mod h1:TYVuzI1QmN4L5ItVdMSXKvH7/DtvIuas5/mm8YT3rTo= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3 h1:2770sDpzrjjsAtVhSeUFseziht227YAWYHLGNM8QPwY= +sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.30.3/go.mod h1:Ve9uj1L+deCXFrPOk1LpFXqTg7LCFzFso6PA48q/XZw= +sigs.k8s.io/controller-runtime v0.19.3 h1:XO2GvC9OPftRst6xWCpTgBZO04S2cbp0Qqkj8bX1sPw= +sigs.k8s.io/controller-runtime v0.19.3/go.mod h1:j4j87DqtsThvwTv5/Tc5NFRyyF/RF0ip4+62tbTSIUM= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= diff --git a/apis/cassandra/v1beta1/cassandradatacenter_webhook.go b/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook.go similarity index 68% rename from apis/cassandra/v1beta1/cassandradatacenter_webhook.go rename to internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook.go index 20b16292..8fa299dd 100644 --- a/apis/cassandra/v1beta1/cassandradatacenter_webhook.go +++ b/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook.go @@ -1,5 +1,5 @@ /* -Copyright 2021. +Copyright 2024 Just Me. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,13 +17,11 @@ limitations under the License. package v1beta1 import ( + "context" "encoding/json" - "errors" "fmt" "strings" - "github.com/google/go-cmp/cmp" - "github.com/k8ssandra/cass-operator/pkg/images" apiequality "k8s.io/apimachinery/pkg/api/equality" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -31,53 +29,96 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + "github.com/google/go-cmp/cmp" + api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" + "github.com/k8ssandra/cass-operator/pkg/images" ) +// log is for logging in this package. const ( datastaxPrefix string = "cassandra.datastax.com" ) var log = logf.Log.WithName("api") -func (dc *CassandraDatacenter) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(dc). +// SetupCassandraDatacenterWebhookWithManager registers the webhook for CassandraDatacenter in the manager. +func SetupCassandraDatacenterWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr).For(&api.CassandraDatacenter{}). + WithValidator(&CassandraDatacenterCustomValidator{}). + WithDefaulter(&CassandraDatacenterCustomDefaulter{}). Complete() } -// kubebuilder:webhook:path=/mutate-cassandra-datastax-com-v1beta1-cassandradatacenter,mutating=true,failurePolicy=fail,sideEffects=None,groups=cassandra.datastax.com,resources=cassandradatacenters,verbs=create;update,versions=v1beta1,name=mcassandradatacenter.kb.io,admissionReviewVersions={v1,v1beta1} -// +kubebuilder:webhook:path=/validate-cassandra-datastax-com-v1beta1-cassandradatacenter,mutating=false,failurePolicy=fail,sideEffects=None,groups=cassandra.datastax.com,resources=cassandradatacenters,verbs=create;update,versions=v1beta1,name=vcassandradatacenter.kb.io,admissionReviewVersions={v1,v1beta1} +// +kubebuilder:webhook:path=/mutate-cassandra-datastax-com-v1beta1-cassandradatacenter,mutating=true,failurePolicy=fail,sideEffects=None,groups=cassandra.datastax.com,resources=cassandradatacenters,verbs=create;update,versions=v1beta1,name=mcassandradatacenter.kb.io,admissionReviewVersions=v1 +// +kubebuilder:webhook:path=/validate-cassandra-datastax-com-v1beta1-cassandradatacenter,mutating=false,failurePolicy=fail,sideEffects=None,groups=cassandra.datastax.com,resources=cassandradatacenters,verbs=create;update,versions=v1beta1,name=vcassandradatacenter.kb.io,admissionReviewVersions=v1 -var _ webhook.Defaulter = &CassandraDatacenter{} +// CassandraDatacenterCustomDefaulter struct is responsible for setting default values on the custom resource of the +// Kind CassandraDatacenter when those are created or updated. +type CassandraDatacenterCustomDefaulter struct { +} -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (dc *CassandraDatacenter) Default() { - // No mutations at this point +var _ webhook.CustomDefaulter = &CassandraDatacenterCustomDefaulter{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the Kind CassandraDatacenter. +func (d *CassandraDatacenterCustomDefaulter) Default(ctx context.Context, obj runtime.Object) error { + return nil } -func attemptedTo(action string, actionStrArgs ...interface{}) error { - var msg string - if actionStrArgs != nil { - msg = fmt.Sprintf(action, actionStrArgs...) - } else { - msg = action +// CassandraDatacenterCustomValidator struct is responsible for validating the CassandraDatacenter resource +// when it is created, updated, or deleted. +type CassandraDatacenterCustomValidator struct { +} + +var _ webhook.CustomValidator = &CassandraDatacenterCustomValidator{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type CassandraDatacenter. +func (v *CassandraDatacenterCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { + dc, ok := obj.(*api.CassandraDatacenter) + if !ok { + return nil, fmt.Errorf("expected a CassandraDatacenter object but got %T", obj) } - return fmt.Errorf("CassandraDatacenter write rejected, attempted to %s", msg) + log.Info("Validation for CassandraDatacenter upon creation", "name", dc.GetName()) + + if err := ValidateSingleDatacenter(dc); err != nil { + return admission.Warnings{}, err + } + + return ValidateDeprecatedFieldUsage(dc), nil } -func deprecatedWarning(field, instead, extra string) string { - warning := "CassandraDatacenter is using deprecated field '%s'" - if instead != "" { - warning += fmt.Sprintf(", use '%s' instead", instead) +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type CassandraDatacenter. +func (v *CassandraDatacenterCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + dc, ok := newObj.(*api.CassandraDatacenter) + if !ok { + return nil, fmt.Errorf("expected a CassandraDatacenter object for the newObj but got %T", newObj) } - if extra != "" { - warning += ". %s" + + oldDc, ok := oldObj.(*api.CassandraDatacenter) + if !ok { + return nil, fmt.Errorf("expected a CassandraDatacenter object for the oldObj but got %T", oldObj) } - return warning + + log.Info("Validation for CassandraDatacenter upon update", "name", dc.GetName()) + + if err := ValidateSingleDatacenter(dc); err != nil { + return nil, err + } + + if err := ValidateDatacenterFieldChanges(oldDc, dc); err != nil { + return nil, err + } + + return ValidateDeprecatedFieldUsage(dc), nil +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type CassandraDatacenter. +func (v *CassandraDatacenterCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) { + return nil, nil } // ValidateSingleDatacenter checks that no values are improperly set on a CassandraDatacenter -func ValidateSingleDatacenter(dc CassandraDatacenter) error { +func ValidateSingleDatacenter(dc *api.CassandraDatacenter) error { // Ensure serverVersion and serverType are compatible if dc.Spec.ServerType == "dse" { @@ -150,7 +191,7 @@ func ValidateSingleDatacenter(dc CassandraDatacenter) error { // ValidateDatacenterFieldChanges checks that no values are improperly changing while updating // a CassandraDatacenter -func ValidateDatacenterFieldChanges(oldDc CassandraDatacenter, newDc CassandraDatacenter) error { +func ValidateDatacenterFieldChanges(oldDc *api.CassandraDatacenter, newDc *api.CassandraDatacenter) error { if oldDc.Spec.ClusterName != newDc.Spec.ClusterName { return attemptedTo("change clusterName") @@ -176,7 +217,7 @@ func ValidateDatacenterFieldChanges(oldDc CassandraDatacenter, newDc CassandraDa newClaimSpec := newDc.Spec.StorageConfig.CassandraDataVolumeClaimSpec.DeepCopy() // CassandraDataVolumeClaimSpec changes are disallowed - if metav1.HasAnnotation(newDc.ObjectMeta, AllowStorageChangesAnnotation) && newDc.Annotations[AllowStorageChangesAnnotation] == "true" { + if metav1.HasAnnotation(newDc.ObjectMeta, api.AllowStorageChangesAnnotation) && newDc.Annotations[api.AllowStorageChangesAnnotation] == "true" { // If the AllowStorageChangesAnnotation is set, we allow changes to the CassandraDataVolumeClaimSpec sizes, but not other fields oldClaimSpec.Resources.Requests = newClaimSpec.Resources.Requests } @@ -202,7 +243,7 @@ func ValidateDatacenterFieldChanges(oldDc CassandraDatacenter, newDc CassandraDa newRackCount := len(newRacks) - len(oldRacks) if newRackCount > 0 { newSizeDifference := newDc.Spec.Size - oldDc.Spec.Size - oldRackNodeSplit := SplitRacks(int(oldDc.Spec.Size), len(oldRacks)) + oldRackNodeSplit := api.SplitRacks(int(oldDc.Spec.Size), len(oldRacks)) minNodesFromOldRacks := oldRackNodeSplit[len(oldRackNodeSplit)-1] minSizeAdjustment := minNodesFromOldRacks * newRackCount @@ -239,7 +280,7 @@ func ValidateDatacenterFieldChanges(oldDc CassandraDatacenter, newDc CassandraDa } // ValidateDeprecatedFieldUsage prevents adding fields that are deprecated -func ValidateDeprecatedFieldUsage(dc CassandraDatacenter) admission.Warnings { +func ValidateDeprecatedFieldUsage(dc *api.CassandraDatacenter) admission.Warnings { warnings := admission.Warnings{} for _, rack := range dc.GetRacks() { if rack.DeprecatedZone != "" { @@ -254,7 +295,7 @@ func ValidateDeprecatedFieldUsage(dc CassandraDatacenter) admission.Warnings { return warnings } -func ValidateAdditionalVolumes(dc CassandraDatacenter) error { +func ValidateAdditionalVolumes(dc *api.CassandraDatacenter) error { for _, volume := range dc.Spec.StorageConfig.AdditionalVolumes { if volume.PVCSpec != nil && volume.VolumeSource != nil { return attemptedTo("create a volume with both PVCSpec and VolumeSource") @@ -268,46 +309,11 @@ func ValidateAdditionalVolumes(dc CassandraDatacenter) error { return nil } -// +kubebuilder:webhook:path=/validate-cassandra-datastax-com-v1beta1-cassandradatacenter,mutating=false,failurePolicy=ignore,sideEffects=None,groups=cassandra.datastax.com,resources=cassandradatacenters,verbs=create;update,versions=v1beta1,name=vcassandradatacenter.kb.io,admissionReviewVersions={v1,v1beta1} -// +kubebuilder:webhook:path=/validate-cassandradatacenter,mutating=false,failurePolicy=ignore,groups=cassandra.datastax.com,resources=cassandradatacenters,verbs=create;update,versions=v1beta1,name=validate-cassandradatacenter-webhook -var _ webhook.Validator = &CassandraDatacenter{} - -func (dc *CassandraDatacenter) ValidateCreate() (admission.Warnings, error) { - log.Info("Validating webhook called for create") - if err := ValidateSingleDatacenter(*dc); err != nil { - return admission.Warnings{}, err - } - - return ValidateDeprecatedFieldUsage(*dc), nil -} - -func (dc *CassandraDatacenter) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - log.Info("Validating webhook called for update") - oldDc, ok := old.(*CassandraDatacenter) - if !ok { - return nil, errors.New("old object in ValidateUpdate cannot be cast to CassandraDatacenter") - } - - if err := ValidateSingleDatacenter(*dc); err != nil { - return nil, err - } - - if err := ValidateDatacenterFieldChanges(*oldDc, *dc); err != nil { - return nil, err - } - - return ValidateDeprecatedFieldUsage(*dc), nil -} - -func (dc *CassandraDatacenter) ValidateDelete() (admission.Warnings, error) { - return nil, nil -} - var ( ErrFQLNotSupported = fmt.Errorf("full query logging is only supported on OSS Cassandra 4.0+") ) -func ValidateFQLConfig(dc CassandraDatacenter) error { +func ValidateFQLConfig(dc *api.CassandraDatacenter) error { if dc.Spec.Config != nil { enabled, err := dc.FullQueryEnabled() if err != nil { @@ -322,7 +328,7 @@ func ValidateFQLConfig(dc CassandraDatacenter) error { return nil } -func ValidateServiceLabelsAndAnnotations(dc CassandraDatacenter) error { +func ValidateServiceLabelsAndAnnotations(dc *api.CassandraDatacenter) error { // check each service addSeedSvc := dc.Spec.AdditionalServiceConfig.AdditionalSeedService allPodsSvc := dc.Spec.AdditionalServiceConfig.AllPodsService @@ -330,7 +336,7 @@ func ValidateServiceLabelsAndAnnotations(dc CassandraDatacenter) error { nodePortSvc := dc.Spec.AdditionalServiceConfig.NodePortService seedSvc := dc.Spec.AdditionalServiceConfig.SeedService - services := map[string]ServiceConfigAdditions{ + services := map[string]api.ServiceConfigAdditions{ "AdditionalSeedService": addSeedSvc, "AllPOdsService": allPodsSvc, "DatacenterService": dcSvc, @@ -344,21 +350,21 @@ func ValidateServiceLabelsAndAnnotations(dc CassandraDatacenter) error { } } - if metav1.HasAnnotation(dc.ObjectMeta, UpdateAllowedAnnotation) { - updateType := AllowUpdateType(dc.Annotations[UpdateAllowedAnnotation]) - if updateType != AllowUpdateAlways && updateType != AllowUpdateOnce { - return attemptedTo("use %s annotation with value other than 'once' or 'always'", UpdateAllowedAnnotation) + if metav1.HasAnnotation(dc.ObjectMeta, api.UpdateAllowedAnnotation) { + updateType := api.AllowUpdateType(dc.Annotations[api.UpdateAllowedAnnotation]) + if updateType != api.AllowUpdateAlways && updateType != api.AllowUpdateOnce { + return attemptedTo("use %s annotation with value other than 'once' or 'always'", api.UpdateAllowedAnnotation) } } return nil } -func containsReservedAnnotations(config ServiceConfigAdditions) bool { +func containsReservedAnnotations(config api.ServiceConfigAdditions) bool { return containsReservedPrefixes(config.Annotations) } -func containsReservedLabels(config ServiceConfigAdditions) bool { +func containsReservedLabels(config api.ServiceConfigAdditions) bool { return containsReservedPrefixes(config.Labels) } @@ -371,3 +377,24 @@ func containsReservedPrefixes(config map[string]string) bool { } return false } + +func attemptedTo(action string, actionStrArgs ...interface{}) error { + var msg string + if actionStrArgs != nil { + msg = fmt.Sprintf(action, actionStrArgs...) + } else { + msg = action + } + return fmt.Errorf("CassandraDatacenter write rejected, attempted to %s", msg) +} + +func deprecatedWarning(field, instead, extra string) string { + warning := "CassandraDatacenter is using deprecated field '%s'" + if instead != "" { + warning += fmt.Sprintf(", use '%s' instead", instead) + } + if extra != "" { + warning += ". %s" + } + return warning +} diff --git a/apis/cassandra/v1beta1/webhook_test.go b/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook_test.go similarity index 79% rename from apis/cassandra/v1beta1/webhook_test.go rename to internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook_test.go index 68bc2fe0..c0f2778b 100644 --- a/apis/cassandra/v1beta1/webhook_test.go +++ b/internal/webhooks/cassandra/v1beta1/cassandradatacenter_webhook_test.go @@ -8,6 +8,7 @@ import ( "strings" "testing" + api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/api/resource" "k8s.io/utils/ptr" @@ -19,16 +20,16 @@ import ( func Test_ValidateSingleDatacenter(t *testing.T) { tests := []struct { name string - dc *CassandraDatacenter + dc *api.CassandraDatacenter errString string }{ { name: "DSE Valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.8.0", }, @@ -37,11 +38,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "DSE 6.8.4 Valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.8.4", }, @@ -50,11 +51,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "DSE 6.9.1 Valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.9.1", }, @@ -63,11 +64,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "HCD 1.0.0 Valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "hcd", ServerVersion: "1.0.0", }, @@ -76,11 +77,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "DSE 7.0.0 invalid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "7.0.0", }, @@ -89,11 +90,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "DSE Invalid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "4.8.0", }, @@ -102,11 +103,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "DSE 5 Invalid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "5.0.0", }, @@ -115,11 +116,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Cassandra valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "3.11.7", }, @@ -128,11 +129,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Cassandra 4.0.x must be valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "4.0.3", }, @@ -141,11 +142,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Cassandra 4.1 must be valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "4.1.0", }, @@ -154,11 +155,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Cassandra 5.0.0 must be valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "5.0.0", }, @@ -167,11 +168,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Cassandra Invalid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "6.8.0", }, @@ -180,11 +181,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Cassandra Invalid too", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "7.0.0", }, @@ -193,14 +194,14 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Dse Workloads in Cassandra Invalid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "6.8.0", - DseWorkloads: &DseWorkloads{ + DseWorkloads: &api.DseWorkloads{ AnalyticsEnabled: true, }, }, @@ -209,14 +210,14 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Dse Workloads in Dse valid", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.8.4", - DseWorkloads: &DseWorkloads{ + DseWorkloads: &api.DseWorkloads{ AnalyticsEnabled: true, }, }, @@ -225,11 +226,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Cassandra 3.11 invalid config file dse-yaml", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "3.11.7", Config: json.RawMessage(` @@ -246,11 +247,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Cassandra 3.11 invalid config file jvm-server-options", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "3.11.7", Config: json.RawMessage(` @@ -267,11 +268,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "DSE 6.8 invalid config file jvm-options", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.8.4", Config: json.RawMessage(` @@ -288,11 +289,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Allow multiple nodes per worker requires resource requests", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.8.4", Config: json.RawMessage(`{}`), @@ -313,11 +314,11 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Allow multiple nodes per worker requires resource requests", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.8.4", Config: json.RawMessage(`{}`), @@ -328,15 +329,15 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Prevent user specified cassandra.datastax.com Service labels and annotations", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "4.0.4", - AdditionalServiceConfig: ServiceConfig{ - DatacenterService: ServiceConfigAdditions{ + AdditionalServiceConfig: api.ServiceConfig{ + DatacenterService: api.ServiceConfigAdditions{ Labels: map[string]string{"cassandra.datastax.com/key1": "val1"}, Annotations: map[string]string{"cassandra.datastax.com/key2": "val2"}, }, @@ -347,15 +348,15 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Allow user specified k8ssandra.io Service labels and annotations", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "cassandra", ServerVersion: "4.0.4", - AdditionalServiceConfig: ServiceConfig{ - DatacenterService: ServiceConfigAdditions{ + AdditionalServiceConfig: api.ServiceConfig{ + DatacenterService: api.ServiceConfigAdditions{ Labels: map[string]string{"k8ssandra.io/key1": "val1"}, Annotations: map[string]string{"k8ssandra.io/key2": "val2"}, }, @@ -366,14 +367,14 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Allow upgrade should not accept invalid values", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", Annotations: map[string]string{ "cassandra.datastax.com/autoupdate-spec": "invalid", }, }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.8.42", }, @@ -382,14 +383,14 @@ func Test_ValidateSingleDatacenter(t *testing.T) { }, { name: "Allow upgrade should accept once value", - dc: &CassandraDatacenter{ + dc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", Annotations: map[string]string{ "cassandra.datastax.com/autoupdate-spec": "once", }, }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: "dse", ServerVersion: "6.8.42", }, @@ -400,7 +401,7 @@ func Test_ValidateSingleDatacenter(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := ValidateSingleDatacenter(*tt.dc) + err := ValidateSingleDatacenter(tt.dc) if err == nil { if tt.errString != "" { t.Errorf("ValidateSingleDatacenter() err = %v, want %v", err, tt.errString) @@ -422,22 +423,22 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { tests := []struct { name string - oldDc *CassandraDatacenter - newDc *CassandraDatacenter + oldDc *api.CassandraDatacenter + newDc *api.CassandraDatacenter errString string }{ { name: "No significant changes", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ClusterName: "oldname", AllowMultipleNodesPerWorker: false, SuperuserSecretName: "hush", DeprecatedServiceAccount: "admin", - StorageConfig: StorageConfig{ + StorageConfig: api.StorageConfig{ CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ StorageClassName: storageName, AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, @@ -446,7 +447,7 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, }, }, - Racks: []Rack{{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -455,16 +456,16 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }}, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ClusterName: "oldname", AllowMultipleNodesPerWorker: false, SuperuserSecretName: "hush", DeprecatedServiceAccount: "admin", - StorageConfig: StorageConfig{ + StorageConfig: api.StorageConfig{ CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ StorageClassName: storageName, AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, @@ -473,7 +474,7 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, }, }, - Racks: []Rack{{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -486,19 +487,19 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "Clustername changed", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ClusterName: "oldname", }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ClusterName: "newname", }, }, @@ -506,19 +507,19 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "DatacenterName changed", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ DatacenterName: "oldname", }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ DatacenterName: "newname", }, }, @@ -526,19 +527,19 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "AllowMultipleNodesPerWorker changed", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ AllowMultipleNodesPerWorker: false, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ AllowMultipleNodesPerWorker: true, }, }, @@ -546,19 +547,19 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "SuperuserSecretName changed", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ SuperuserSecretName: "hush", }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ SuperuserSecretName: "newsecret", }, }, @@ -566,19 +567,19 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "ServiceAccount changed", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ DeprecatedServiceAccount: "admin", }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ DeprecatedServiceAccount: "newadmin", }, }, @@ -586,12 +587,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "StorageConfig changes", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - StorageConfig: StorageConfig{ + Spec: api.CassandraDatacenterSpec{ + StorageConfig: api.StorageConfig{ CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ StorageClassName: storageName, AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, @@ -602,12 +603,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - StorageConfig: StorageConfig{ + Spec: api.CassandraDatacenterSpec{ + StorageConfig: api.StorageConfig{ CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ StorageClassName: storageName, AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteMany"}, @@ -622,12 +623,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "StorageClassName changes with storageConfig changes allowed", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - StorageConfig: StorageConfig{ + Spec: api.CassandraDatacenterSpec{ + StorageConfig: api.StorageConfig{ CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ StorageClassName: storageName, AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, @@ -638,15 +639,15 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", Annotations: map[string]string{ - AllowStorageChangesAnnotation: "true", + api.AllowStorageChangesAnnotation: "true", }, }, - Spec: CassandraDatacenterSpec{ - StorageConfig: StorageConfig{ + Spec: api.CassandraDatacenterSpec{ + StorageConfig: api.StorageConfig{ CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ StorageClassName: ptr.To[string]("new-server-data"), AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, @@ -661,12 +662,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "storage requests size changes with storageConfig changes allowed", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - StorageConfig: StorageConfig{ + Spec: api.CassandraDatacenterSpec{ + StorageConfig: api.StorageConfig{ CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ StorageClassName: storageName, AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, @@ -677,15 +678,15 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", Annotations: map[string]string{ - AllowStorageChangesAnnotation: "true", + api.AllowStorageChangesAnnotation: "true", }, }, - Spec: CassandraDatacenterSpec{ - StorageConfig: StorageConfig{ + Spec: api.CassandraDatacenterSpec{ + StorageConfig: api.StorageConfig{ CassandraDataVolumeClaimSpec: &corev1.PersistentVolumeClaimSpec{ StorageClassName: storageName, AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, @@ -700,12 +701,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "Removing a rack", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - Racks: []Rack{{ + Spec: api.CassandraDatacenterSpec{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -714,12 +715,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }}, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - Racks: []Rack{{ + Spec: api.CassandraDatacenterSpec{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack2", @@ -730,23 +731,23 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "Scaling down", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - Racks: []Rack{{ + Spec: api.CassandraDatacenterSpec{ + Racks: []api.Rack{{ Name: "rack0", }}, Size: 6, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - Racks: []Rack{{ + Spec: api.CassandraDatacenterSpec{ + Racks: []api.Rack{{ Name: "rack0", }}, Size: 3, @@ -756,12 +757,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "Changed a rack name", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - Racks: []Rack{{ + Spec: api.CassandraDatacenterSpec{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -770,12 +771,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }}, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - Racks: []Rack{{ + Spec: api.CassandraDatacenterSpec{ + Racks: []api.Rack{{ Name: "rack0-changed", }, { Name: "rack1", @@ -788,13 +789,13 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "Adding a rack is allowed if size increases", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ Size: 3, - Racks: []Rack{{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -803,13 +804,13 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }}, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ Size: 4, - Racks: []Rack{{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -824,12 +825,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "Adding a rack is not allowed if size doesn't increase", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - Racks: []Rack{{ + Spec: api.CassandraDatacenterSpec{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -838,12 +839,12 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }}, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ - Racks: []Rack{{ + Spec: api.CassandraDatacenterSpec{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -858,26 +859,26 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "Adding a rack is not allowed if size doesn't increase enough to prevent moving nodes from existing racks", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ Size: 9, - Racks: []Rack{{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", }}, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ Size: 11, - Racks: []Rack{{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -890,26 +891,26 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { }, { name: "Adding multiple racks is not allowed if size doesn't increase enough to prevent moving nodes from existing racks", - oldDc: &CassandraDatacenter{ + oldDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ Size: 9, - Racks: []Rack{{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", }}, }, }, - newDc: &CassandraDatacenter{ + newDc: &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ Size: 16, - Racks: []Rack{{ + Racks: []api.Rack{{ Name: "rack0", }, { Name: "rack1", @@ -926,7 +927,7 @@ func Test_ValidateDatacenterFieldChanges(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - err := ValidateDatacenterFieldChanges(*tt.oldDc, *tt.newDc) + err := ValidateDatacenterFieldChanges(tt.oldDc, tt.newDc) if err == nil { if tt.errString != "" { t.Errorf("ValidateDatacenterFieldChanges() err = %v, want %v", err, tt.errString) @@ -950,12 +951,12 @@ var fqlEnabledConfig string = `{"cassandra-yaml": { } ` -func CreateCassDc(serverType string) CassandraDatacenter { - dc := CassandraDatacenter{ +func CreateCassDc(serverType string) *api.CassandraDatacenter { + dc := &api.CassandraDatacenter{ ObjectMeta: metav1.ObjectMeta{ Name: "exampleDC", }, - Spec: CassandraDatacenterSpec{ + Spec: api.CassandraDatacenterSpec{ ServerType: serverType, }, } diff --git a/apis/cassandra/v1beta1/webhook_suite_test.go b/internal/webhooks/cassandra/v1beta1/webhook_suite_test.go similarity index 61% rename from apis/cassandra/v1beta1/webhook_suite_test.go rename to internal/webhooks/cassandra/v1beta1/webhook_suite_test.go index 5689f9ea..59991254 100644 --- a/apis/cassandra/v1beta1/webhook_suite_test.go +++ b/internal/webhooks/cassandra/v1beta1/webhook_suite_test.go @@ -1,5 +1,5 @@ /* -Copyright 2021. +Copyright 2024 Just Me. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -22,33 +22,43 @@ import ( "fmt" "net" "path/filepath" + "runtime" "testing" "time" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - //+kubebuilder:scaffold:imports - "k8s.io/apimachinery/pkg/runtime" + admissionv1 "k8s.io/api/admission/v1" + + api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" + + // +kubebuilder:scaffold:imports + apimachineryruntime "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" - webhookserver "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook" ) // These tests use Ginkgo (BDD-style Go testing framework). Refer to // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. -var k8sClient client.Client -var testEnv *envtest.Environment -var ctx context.Context -var cancel context.CancelFunc +var ( + cancel context.CancelFunc + cfg *rest.Config + ctx context.Context + k8sClient client.Client + testEnv *envtest.Environment +) func TestAPIs(t *testing.T) { RegisterFailHandler(Fail) + RunSpecs(t, "Webhook Suite") } @@ -61,53 +71,65 @@ var _ = BeforeSuite(func() { testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{filepath.Join("..", "..", "..", "config", "crd", "bases")}, ErrorIfCRDPathMissing: false, + + // The BinaryAssetsDirectory is only required if you want to run the tests directly + // without call the makefile target test. If not informed it will look for the + // default path defined in controller-runtime which is /usr/local/kubebuilder/. + // Note that you must have the required binaries setup under the bin directory to perform + // the tests directly. When we run make test it will be setup and used automatically. + BinaryAssetsDirectory: filepath.Join("..", "..", "..", "bin", "k8s", + fmt.Sprintf("1.31.0-%s-%s", runtime.GOOS, runtime.GOARCH)), + WebhookInstallOptions: envtest.WebhookInstallOptions{ Paths: []string{filepath.Join("..", "..", "..", "config", "webhook")}, }, } - cfg, err := testEnv.Start() + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() Expect(err).NotTo(HaveOccurred()) Expect(cfg).NotTo(BeNil()) - scheme := runtime.NewScheme() - err = AddToScheme(scheme) + scheme := apimachineryruntime.NewScheme() + err = api.AddToScheme(scheme) + Expect(err).NotTo(HaveOccurred()) + + err = admissionv1.AddToScheme(scheme) Expect(err).NotTo(HaveOccurred()) - //+kubebuilder:scaffold:scheme + // +kubebuilder:scaffold:scheme k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) Expect(err).NotTo(HaveOccurred()) Expect(k8sClient).NotTo(BeNil()) - // start webhook server using Manager + // start webhook server using Manager. webhookInstallOptions := &testEnv.WebhookInstallOptions mgr, err := ctrl.NewManager(cfg, ctrl.Options{ Scheme: scheme, - WebhookServer: webhookserver.NewServer(webhookserver.Options{ - Port: testEnv.WebhookInstallOptions.LocalServingPort, - Host: testEnv.WebhookInstallOptions.LocalServingHost, - CertDir: testEnv.WebhookInstallOptions.LocalServingCertDir, - TLSOpts: []func(*tls.Config){func(config *tls.Config) {}}, + WebhookServer: webhook.NewServer(webhook.Options{ + Host: webhookInstallOptions.LocalServingHost, + Port: webhookInstallOptions.LocalServingPort, + CertDir: webhookInstallOptions.LocalServingCertDir, }), LeaderElection: false, Metrics: metricsserver.Options{BindAddress: "0"}, }) Expect(err).NotTo(HaveOccurred()) - err = (&CassandraDatacenter{}).SetupWebhookWithManager(mgr) + err = SetupCassandraDatacenterWebhookWithManager(mgr) Expect(err).NotTo(HaveOccurred()) - //+kubebuilder:scaffold:webhook + // +kubebuilder:scaffold:webhook go func() { + defer GinkgoRecover() err = mgr.Start(ctx) - if err != nil { - Expect(err).NotTo(HaveOccurred()) - } + Expect(err).NotTo(HaveOccurred()) }() - // wait for the webhook server to get ready + // wait for the webhook server to get ready. dialer := &net.Dialer{Timeout: time.Second} addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort) Eventually(func() error { @@ -115,15 +137,14 @@ var _ = BeforeSuite(func() { if err != nil { return err } - conn.Close() - return nil - }).Should(Succeed()) + return conn.Close() + }).Should(Succeed()) }) var _ = AfterSuite(func() { - cancel() By("tearing down the test environment") + cancel() err := testEnv.Stop() Expect(err).NotTo(HaveOccurred()) }) diff --git a/logger.Dockerfile b/logger.Dockerfile index fd7c5f2a..6cef79b6 100644 --- a/logger.Dockerfile +++ b/logger.Dockerfile @@ -1,16 +1,16 @@ -FROM redhat/ubi8:latest AS builder +FROM redhat/ubi9:latest AS builder ARG VERSION ARG TARGETPLATFORM # Install Vector -ENV VECTOR_VERSION=0.39.0 +ENV VECTOR_VERSION=0.43.1 RUN case ${TARGETPLATFORM} in \ "linux/amd64") VECTOR_ARCH=x86_64 ;; \ "linux/arm64") VECTOR_ARCH=aarch64 ;; \ esac \ && rpm -i https://packages.timber.io/vector/${VECTOR_VERSION}/vector-${VECTOR_VERSION}-1.${VECTOR_ARCH}.rpm -FROM redhat/ubi8-micro:latest +FROM redhat/ubi9-micro:latest ARG VERSION ARG TARGETPLATFORM diff --git a/pkg/reconciliation/construct_podtemplatespec.go b/pkg/reconciliation/construct_podtemplatespec.go index 537299d4..0339c540 100644 --- a/pkg/reconciliation/construct_podtemplatespec.go +++ b/pkg/reconciliation/construct_podtemplatespec.go @@ -19,6 +19,7 @@ import ( "github.com/k8ssandra/cass-operator/pkg/httphelper" "github.com/k8ssandra/cass-operator/pkg/images" "github.com/k8ssandra/cass-operator/pkg/oplabels" + "github.com/k8ssandra/cass-operator/pkg/serverconfig" "github.com/k8ssandra/cass-operator/pkg/utils" corev1 "k8s.io/api/core/v1" @@ -622,7 +623,7 @@ func getConfigDataEnVars(dc *api.CassandraDatacenter) ([]corev1.EnvVar, error) { return nil, fmt.Errorf("datacenter %s is missing %s annotation", dc.LabelResourceName(), api.ConfigHashAnnotation) } - configData, err := dc.GetConfigAsJSON(dc.Spec.Config) + configData, err := serverconfig.GetConfigAsJSON(dc, dc.Spec.Config) if err != nil { return envVars, err } diff --git a/pkg/reconciliation/construct_statefulset.go b/pkg/reconciliation/construct_statefulset.go index 7a53516b..29fad825 100644 --- a/pkg/reconciliation/construct_statefulset.go +++ b/pkg/reconciliation/construct_statefulset.go @@ -11,6 +11,7 @@ import ( api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" "github.com/k8ssandra/cass-operator/pkg/httphelper" "github.com/k8ssandra/cass-operator/pkg/oplabels" + "github.com/k8ssandra/cass-operator/pkg/serverconfig" "github.com/k8ssandra/cass-operator/pkg/utils" logf "sigs.k8s.io/controller-runtime/pkg/log" @@ -181,7 +182,7 @@ func newStatefulSetForCassandraDatacenter( } func legacyInternodeMount(dc *api.CassandraDatacenter, sts *appsv1.StatefulSet) bool { - if dc.LegacyInternodeEnabled() { + if serverconfig.LegacyInternodeEnabled(dc) { return true } diff --git a/pkg/reconciliation/handler.go b/pkg/reconciliation/handler.go index 772c78dd..113b2648 100644 --- a/pkg/reconciliation/handler.go +++ b/pkg/reconciliation/handler.go @@ -14,6 +14,7 @@ import ( api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" "github.com/k8ssandra/cass-operator/internal/result" + apiwebhook "github.com/k8ssandra/cass-operator/internal/webhooks/cassandra/v1beta1" "github.com/k8ssandra/cass-operator/pkg/httphelper" ) @@ -103,10 +104,10 @@ func (rc *ReconciliationContext) IsValid(dc *api.CassandraDatacenter) error { errs = append(errs, rc.validateCassandraUserSecrets()...) // Validate FQL config - errs = append(errs, api.ValidateFQLConfig(*dc)) + errs = append(errs, apiwebhook.ValidateFQLConfig(dc)) // Validate Service labels and annotations - errs = append(errs, api.ValidateServiceLabelsAndAnnotations(*dc)) + errs = append(errs, apiwebhook.ValidateServiceLabelsAndAnnotations(dc)) // Validate Management API config errs = append(errs, httphelper.ValidateManagementApiConfig(dc, rc.Client, rc.Ctx)...) diff --git a/pkg/reconciliation/reconcile_configsecret.go b/pkg/reconciliation/reconcile_configsecret.go index 2c9bfa01..259c80e6 100644 --- a/pkg/reconciliation/reconcile_configsecret.go +++ b/pkg/reconciliation/reconcile_configsecret.go @@ -10,6 +10,7 @@ import ( api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" "github.com/k8ssandra/cass-operator/internal/result" "github.com/k8ssandra/cass-operator/pkg/cdc" + "github.com/k8ssandra/cass-operator/pkg/serverconfig" "github.com/k8ssandra/cass-operator/pkg/utils" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -115,7 +116,7 @@ func (rc *ReconciliationContext) updateConfigHashAnnotation(secret *corev1.Secre // getConfigFromConfigSecret Generates the JSON with properties added by cass-operator. func getConfigFromConfigSecret(dc *api.CassandraDatacenter, secret *corev1.Secret) ([]byte, error) { if b, found := secret.Data["config"]; found { - jsonConfig, err := dc.GetConfigAsJSON(b) + jsonConfig, err := serverconfig.GetConfigAsJSON(dc, b) if err != nil { return nil, err } diff --git a/pkg/reconciliation/reconcile_racks.go b/pkg/reconciliation/reconcile_racks.go index 963be49f..0396cae8 100644 --- a/pkg/reconciliation/reconcile_racks.go +++ b/pkg/reconciliation/reconcile_racks.go @@ -29,6 +29,7 @@ import ( "github.com/k8ssandra/cass-operator/pkg/httphelper" "github.com/k8ssandra/cass-operator/pkg/monitoring" "github.com/k8ssandra/cass-operator/pkg/oplabels" + "github.com/k8ssandra/cass-operator/pkg/serverconfig" "github.com/k8ssandra/cass-operator/pkg/utils" pkgerrors "github.com/pkg/errors" ) @@ -118,7 +119,7 @@ func (rc *ReconciliationContext) CheckSuperuserSecretCreation() result.Reconcile func (rc *ReconciliationContext) CheckInternodeCredentialCreation() result.ReconcileResult { rc.ReqLogger.Info("reconcile_racks::CheckInternodeCredentialCreation") - if !rc.Datacenter.LegacyInternodeEnabled() { + if !serverconfig.LegacyInternodeEnabled(rc.Datacenter) { return result.Continue() } diff --git a/pkg/reconciliation/reconcile_racks_test.go b/pkg/reconciliation/reconcile_racks_test.go index bf062e87..1681bae4 100644 --- a/pkg/reconciliation/reconcile_racks_test.go +++ b/pkg/reconciliation/reconcile_racks_test.go @@ -39,6 +39,7 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/reconcile" ) @@ -270,7 +271,7 @@ func TestCheckRackPodTemplate_SetControllerRefOnStatefulSet(t *testing.T) { var actualOwner, actualObject metav1.Object invocations := 0 - setControllerReference = func(owner, object metav1.Object, scheme *runtime.Scheme) error { + setControllerReference = func(owner, object metav1.Object, scheme *runtime.Scheme, opts ...controllerutil.OwnerReferenceOption) error { actualOwner = owner actualObject = object invocations++ diff --git a/pkg/reconciliation/testing.go b/pkg/reconciliation/testing.go index c4d9ec98..a2071545 100644 --- a/pkg/reconciliation/testing.go +++ b/pkg/reconciliation/testing.go @@ -26,6 +26,7 @@ import ( "k8s.io/client-go/tools/record" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" log2 "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -41,7 +42,8 @@ func MockSetControllerReference() func() { setControllerReference = func( owner, object metav1.Object, - scheme *runtime.Scheme) error { + scheme *runtime.Scheme, + opts ...controllerutil.OwnerReferenceOption) error { return nil } diff --git a/pkg/serverconfig/configgen.go b/pkg/serverconfig/configgen.go index fe735c5f..bfd132bd 100644 --- a/pkg/serverconfig/configgen.go +++ b/pkg/serverconfig/configgen.go @@ -4,7 +4,12 @@ package serverconfig import ( + "encoding/json" "strings" + + "github.com/Jeffail/gabs/v2" + api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" + "github.com/pkg/errors" ) // This needs to be outside of the apis package or else code-gen fails @@ -54,3 +59,80 @@ func GetModelValues( return modelValues } + +// GetConfigAsJSON gets a JSON-encoded string suitable for passing to configBuilder +func GetConfigAsJSON(dc *api.CassandraDatacenter, config []byte) (string, error) { + if config == nil { + config = dc.Spec.Config + } + + // We use the cluster seed-service name here for the seed list as it will + // resolve to the seed nodes. This obviates the need to update the + // cassandra.yaml whenever the seed nodes change. + seeds := []string{dc.GetSeedServiceName(), dc.GetAdditionalSeedsServiceName()} + + graphEnabled := 0 + solrEnabled := 0 + sparkEnabled := 0 + + if dc.Spec.ServerType == "dse" && dc.Spec.DseWorkloads != nil { + if dc.Spec.DseWorkloads.AnalyticsEnabled { + sparkEnabled = 1 + } + if dc.Spec.DseWorkloads.GraphEnabled { + graphEnabled = 1 + } + if dc.Spec.DseWorkloads.SearchEnabled { + solrEnabled = 1 + } + } + + native := 0 + nativeSSL := 0 + internode := 0 + internodeSSL := 0 + if dc.IsNodePortEnabled() { + native = dc.Spec.Networking.NodePort.Native + nativeSSL = dc.Spec.Networking.NodePort.NativeSSL + internode = dc.Spec.Networking.NodePort.Internode + internodeSSL = dc.Spec.Networking.NodePort.InternodeSSL + } + + modelValues := GetModelValues( + seeds, + dc.Spec.ClusterName, + dc.DatacenterName(), + graphEnabled, + solrEnabled, + sparkEnabled, + native, + nativeSSL, + internode, + internodeSSL) + + var modelBytes []byte + + modelBytes, err := json.Marshal(modelValues) + if err != nil { + return "", err + } + + // Combine the model values with the user-specified values + modelParsed, err := gabs.ParseJSON(modelBytes) + if err != nil { + return "", errors.Wrap(err, "Model information for CassandraDatacenter resource was not properly configured") + } + + if config != nil { + configParsed, err := gabs.ParseJSON(config) + if err != nil { + return "", errors.Wrap(err, "Error parsing Spec.Config for CassandraDatacenter resource") + } + + if err := modelParsed.Merge(configParsed); err != nil { + return "", errors.Wrap(err, "Error merging Spec.Config for CassandraDatacenter resource") + } + } + + return modelParsed.String(), nil +} diff --git a/pkg/serverconfig/parsing.go b/pkg/serverconfig/parsing.go new file mode 100644 index 00000000..797f93a3 --- /dev/null +++ b/pkg/serverconfig/parsing.go @@ -0,0 +1,39 @@ +package serverconfig + +import ( + "strings" + + "github.com/Jeffail/gabs/v2" + api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" +) + +func LegacyInternodeEnabled(dc *api.CassandraDatacenter) bool { + config, err := gabs.ParseJSON(dc.Spec.Config) + if err != nil { + return false + } + + hasOldKeyStore := func(gobContainer map[string]*gabs.Container) bool { + if gobContainer == nil { + return false + } + + if keystorePath, found := gobContainer["keystore"]; found { + if strings.TrimSpace(keystorePath.Data().(string)) == "/etc/encryption/node-keystore.jks" { + return true + } + } + return false + } + + if config.Exists("cassandra-yaml", "client_encryption_options") || config.Exists("cassandra-yaml", "server_encryption_options") { + serverContainer := config.Path("cassandra-yaml.server_encryption_options").ChildrenMap() + clientContainer := config.Path("cassandra-yaml.client_encryption_options").ChildrenMap() + + if hasOldKeyStore(clientContainer) || hasOldKeyStore(serverContainer) { + return true + } + } + + return false +} diff --git a/pkg/serverconfig/parsing_test.go b/pkg/serverconfig/parsing_test.go new file mode 100644 index 00000000..167fbc73 --- /dev/null +++ b/pkg/serverconfig/parsing_test.go @@ -0,0 +1,106 @@ +package serverconfig + +import ( + "encoding/json" + "testing" + + "github.com/Jeffail/gabs/v2" + api "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1" + "github.com/stretchr/testify/assert" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var internodeEnabledAll = ` +{ + "cassandra-yaml": { + "server_encryption_options": { + "internode_encryption": "all", + "keystore": "/etc/encryption/node-keystore.jks", + "keystore_password": "dc2", + "truststore": "/etc/encryption/node-keystore.jks", + "truststore_password": "dc2" + } + } +} +` + +var internodeSomethingElse = ` +{ + "cassandra-yaml": { + "server_encryption_options": { + "internode_encryption": "all", + "keystore": "/etc/encryption/cert-manager.jks", + "keystore_password": "aaaaaa", + "truststore": "/etc/encryption/cert-manager.jks", + "truststore_password": "bbbbb" + } + } +} +` + +func TestLegacyInternodeEnabled(t *testing.T) { + dc := &api.CassandraDatacenter{ + Spec: api.CassandraDatacenterSpec{ + Config: json.RawMessage(internodeEnabledAll), + }, + } + + assert.True(t, LegacyInternodeEnabled(dc)) +} + +func TestLegacyInternodeDisabled(t *testing.T) { + dc := &api.CassandraDatacenter{ + Spec: api.CassandraDatacenterSpec{ + Config: json.RawMessage(internodeSomethingElse), + }, + } + + assert.False(t, LegacyInternodeEnabled(dc)) +} + +func TestDatacenterNoOverrideConfig(t *testing.T) { + assert := assert.New(t) + dc := &api.CassandraDatacenter{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dc1", + }, + Spec: api.CassandraDatacenterSpec{ + ClusterName: "cluster1", + }, + } + + config, err := GetConfigAsJSON(dc, dc.Spec.Config) + assert.NoError(err) + + container, err := gabs.ParseJSON([]byte(config)) + assert.NoError(err) + + dataCenterInfo := container.ChildrenMap()["datacenter-info"] + assert.NotEmpty(dataCenterInfo) + assert.Equal(dc.Name, dataCenterInfo.ChildrenMap()["name"].Data().(string)) + assert.Equal(dc.DatacenterName(), dc.Name) +} + +func TestDatacenterOverrideInConfig(t *testing.T) { + assert := assert.New(t) + dc := &api.CassandraDatacenter{ + ObjectMeta: metav1.ObjectMeta{ + Name: "dc1", + }, + Spec: api.CassandraDatacenterSpec{ + ClusterName: "cluster1", + DatacenterName: "Home_Dc", + }, + } + + config, err := GetConfigAsJSON(dc, dc.Spec.Config) + assert.NoError(err) + + container, err := gabs.ParseJSON([]byte(config)) + assert.NoError(err) + + dataCenterInfo := container.ChildrenMap()["datacenter-info"] + assert.NotEmpty(dataCenterInfo) + assert.Equal(dc.Spec.DatacenterName, dataCenterInfo.ChildrenMap()["name"].Data().(string)) + assert.Equal(dc.DatacenterName(), dc.Spec.DatacenterName) +} diff --git a/tests/kustomize/kustomization.yaml b/tests/kustomize/kustomization.yaml index 2b5ee667..894e8a89 100644 --- a/tests/kustomize/kustomization.yaml +++ b/tests/kustomize/kustomization.yaml @@ -5,3 +5,101 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - ../../config/deployments/default + +replacements: +- source: # Uncomment the following block if you have any webhook + kind: Service + version: v1 + name: webhook-service + fieldPath: .metadata.name # Name of the service + targets: + - select: + kind: Certificate + group: cert-manager.io + version: v1 + fieldPaths: + - .spec.dnsNames.0 + - .spec.dnsNames.1 + options: + delimiter: '.' + index: 0 + create: true +- source: + kind: Service + version: v1 + name: webhook-service + fieldPath: .metadata.namespace # Namespace of the service + targets: + - select: + kind: Certificate + group: cert-manager.io + version: v1 + fieldPaths: + - .spec.dnsNames.0 + - .spec.dnsNames.1 + options: + delimiter: '.' + index: 1 + create: true + +- source: # Uncomment the following block if you have a ValidatingWebhook (--programmatic-validation) + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # This name should match the one in certificate.yaml + fieldPath: .metadata.namespace # Namespace of the certificate CR + targets: + - select: + kind: ValidatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + create: true +- source: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # This name should match the one in certificate.yaml + fieldPath: .metadata.name + targets: + - select: + kind: ValidatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 1 + create: true + +- source: # Uncomment the following block if you have a DefaultingWebhook (--defaulting ) + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # This name should match the one in certificate.yaml + fieldPath: .metadata.namespace # Namespace of the certificate CR + targets: + - select: + kind: MutatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 0 + create: true +- source: + kind: Certificate + group: cert-manager.io + version: v1 + name: serving-cert # This name should match the one in certificate.yaml + fieldPath: .metadata.name + targets: + - select: + kind: MutatingWebhookConfiguration + fieldPaths: + - .metadata.annotations.[cert-manager.io/inject-ca-from] + options: + delimiter: '/' + index: 1 + create: true