diff --git a/go.mod b/go.mod index 93390bad4..8b66f0465 100644 --- a/go.mod +++ b/go.mod @@ -157,6 +157,6 @@ require ( // github.com/operator-framework/operator-sdk. replace ( bitbucket.org/ww/goautoneg => github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d - github.com/openshift/api => github.com/openshift/api v0.0.0-20241004095111-b1f700bdd8d2 + github.com/openshift/api => github.com/openshift/api v0.0.0-20241018083007-4f6053f954b0 k8s.io/client-go => k8s.io/client-go v0.31.1 ) diff --git a/go.sum b/go.sum index ee46611f2..74e90f7af 100644 --- a/go.sum +++ b/go.sum @@ -993,8 +993,8 @@ github.com/opencontainers/runtime-spec v0.1.2-0.20190507144316-5b71a03e2700/go.m github.com/opencontainers/runtime-spec v0.1.2-0.20190618234442-a950415649c7/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-tools v0.0.0-20181011054405-1d69bd0f9c39/go.mod h1:r3f7wjNzSs2extwzU3Y+6pKfobzPh+kKFJ3ofN+3nfs= -github.com/openshift/api v0.0.0-20241004095111-b1f700bdd8d2 h1:wCRdyt+nHnJsfuLMJF9RW1JK8G4Gvo//gBy6bZI5USE= -github.com/openshift/api v0.0.0-20241004095111-b1f700bdd8d2/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo= +github.com/openshift/api v0.0.0-20241018083007-4f6053f954b0 h1:9CBNaPGycU2dDzq0XoRIqxH0vHZezKDfbINx8e5zH0I= +github.com/openshift/api v0.0.0-20241018083007-4f6053f954b0/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo= github.com/openshift/build-machinery-go v0.0.0-20200211121458-5e3d6e570160/go.mod h1:1CkcsT3aVebzRBzVTSbiKSkJMsC/CASqxesfqEMfJEc= github.com/openshift/client-go v0.0.0-20200116152001-92a2713fa240/go.mod h1:4riOwdj99Hd/q+iAcJZfNCsQQQMwURnZV6RL4WHYS5w= github.com/openshift/client-go v0.0.0-20240405120947-c67c8325cdd8 h1:HGfbllzRcrJBSiwzNjBCs7sExLUxC5/1evnvlNGB0Cg= diff --git a/pkg/operator/controller/ingress/controller.go b/pkg/operator/controller/ingress/controller.go index 184f433fb..f3cf3c3f5 100644 --- a/pkg/operator/controller/ingress/controller.go +++ b/pkg/operator/controller/ingress/controller.go @@ -209,6 +209,7 @@ type Config struct { RouteExternalCertificateEnabled bool IngressControllerLBSubnetsAWSEnabled bool IngressControllerEIPAllocationsAWSEnabled bool + IngressControllerDCMEnabled bool } // reconciler handles the actual ingress reconciliation logic in response to diff --git a/pkg/operator/controller/ingress/deployment.go b/pkg/operator/controller/ingress/deployment.go index 5df994e60..9bfcdf729 100644 --- a/pkg/operator/controller/ingress/deployment.go +++ b/pkg/operator/controller/ingress/deployment.go @@ -84,6 +84,11 @@ const ( RouterHAProxyConfigManager = "ROUTER_HAPROXY_CONFIG_MANAGER" + RouterHAProxyMaxDynamicServers = "ROUTER_MAX_DYNAMIC_SERVERS" + RouterHAProxyMaxDynamicServersDefaultValue = 1 + + RouterHAProxyBlueprintRoutePoolSize = "ROUTER_BLUEPRINT_ROUTE_POOL_SIZE" + RouterHAProxyContstats = "ROUTER_HAPROXY_CONTSTATS" RouterHAProxyThreadsEnvName = "ROUTER_THREADS" @@ -121,7 +126,7 @@ func (r *reconciler) ensureRouterDeployment(ci *operatorv1.IngressController, in if err != nil { return false, nil, fmt.Errorf("failed to determine if proxy protocol is needed for ingresscontroller %s/%s: %v", ci.Namespace, ci.Name, err) } - desired, err := desiredRouterDeployment(ci, r.config.IngressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, haveClientCAConfigmap, clientCAConfigmap, clusterProxyConfig, r.config.RouteExternalCertificateEnabled) + desired, err := desiredRouterDeployment(ci, r.config.IngressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, haveClientCAConfigmap, clientCAConfigmap, clusterProxyConfig, r.config.RouteExternalCertificateEnabled, r.config.IngressControllerDCMEnabled) if err != nil { return haveDepl, current, fmt.Errorf("failed to build router deployment: %v", err) } @@ -243,7 +248,7 @@ func headerValues(values []operatorv1.IngressControllerHTTPHeader) string { } // desiredRouterDeployment returns the desired router deployment. -func desiredRouterDeployment(ci *operatorv1.IngressController, ingressControllerImage string, ingressConfig *configv1.Ingress, infraConfig *configv1.Infrastructure, apiConfig *configv1.APIServer, networkConfig *configv1.Network, proxyNeeded bool, haveClientCAConfigmap bool, clientCAConfigmap *corev1.ConfigMap, clusterProxyConfig *configv1.Proxy, routeExternalCertificateEnabled bool) (*appsv1.Deployment, error) { +func desiredRouterDeployment(ci *operatorv1.IngressController, ingressControllerImage string, ingressConfig *configv1.Ingress, infraConfig *configv1.Infrastructure, apiConfig *configv1.APIServer, networkConfig *configv1.Network, proxyNeeded bool, haveClientCAConfigmap bool, clientCAConfigmap *corev1.ConfigMap, clusterProxyConfig *configv1.Proxy, routeExternalCertificateEnabled, ingressControllerDCMEnabled bool) (*appsv1.Deployment, error) { deployment := manifests.RouterDeployment() name := controller.RouterDeploymentName(ci) deployment.Name = name.Name @@ -523,6 +528,15 @@ func desiredRouterDeployment(ci *operatorv1.IngressController, ingressController LoadBalancingAlgorithm string `json:"loadBalancingAlgorithm"` DynamicConfigManager string `json:"dynamicConfigManager"` ContStats string `json:"contStats"` + // maxDynamicServers specifies the number of dynamic server slots that will be added to each route. + // This setting can only be configured if dynamicConfigManager is `true`. + // The default value is 1, with a maximum of 10. + // Dynamic server slots help to avoid reloads during endpoint scale-ups. The more dynamic servers + // added, the fewer reloads required when scaling up. + // Note, however, that dynamic servers consume memory even when not enabled. + // Use this analysis of the memory usage to assess the impact of different numbers of servers: + // https://gist.github.com/frobware/2b527ce3f040797909eff482a4776e0b + MaxDynamicServers string `json:"maxDynamicServers"` } if len(ci.Spec.UnsupportedConfigOverrides.Raw) > 0 { if err := json.Unmarshal(ci.Spec.UnsupportedConfigOverrides.Raw, &unsupportedConfigOverrides); err != nil { @@ -567,13 +581,36 @@ func desiredRouterDeployment(ci *operatorv1.IngressController, ingressController }) } + enableDCM := false + if ingressControllerDCMEnabled { + enableDCM = true + } dynamicConfigOverride := unsupportedConfigOverrides.DynamicConfigManager - if v, err := strconv.ParseBool(dynamicConfigOverride); err == nil && v { + if v, err := strconv.ParseBool(dynamicConfigOverride); err == nil { + // Config override can still be used to opt out from DCM. + enableDCM = v + } + + if enableDCM { env = append(env, corev1.EnvVar{ Name: RouterHAProxyConfigManager, Value: "true", + }, corev1.EnvVar{ + Name: RouterHAProxyBlueprintRoutePoolSize, + Value: "0", + }) + + // Max dynamic servers override is only taken into account when DCM is enabled. + routerHAProxyMaxDynamicServersValue := RouterHAProxyMaxDynamicServersDefaultValue + if v, err := strconv.Atoi(unsupportedConfigOverrides.MaxDynamicServers); err == nil && v > 0 { + routerHAProxyMaxDynamicServersValue = v + } + env = append(env, corev1.EnvVar{ + Name: RouterHAProxyMaxDynamicServers, + Value: strconv.Itoa(routerHAProxyMaxDynamicServersValue), }) } + contStats := unsupportedConfigOverrides.ContStats if v, err := strconv.ParseBool(contStats); err == nil && v { env = append(env, corev1.EnvVar{ diff --git a/pkg/operator/controller/ingress/deployment_test.go b/pkg/operator/controller/ingress/deployment_test.go index 2defacffb..c192bab92 100644 --- a/pkg/operator/controller/ingress/deployment_test.go +++ b/pkg/operator/controller/ingress/deployment_test.go @@ -174,7 +174,7 @@ func TestTuningOptions(t *testing.T) { ic.Spec.TuningOptions.HealthCheckInterval = &metav1.Duration{Duration: 15 * time.Second} ic.Spec.TuningOptions.ReloadInterval = metav1.Duration{Duration: 30 * time.Second} - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -203,7 +203,7 @@ func TestTuningOptions(t *testing.T) { func TestClusterProxy(t *testing.T) { ic, ingressConfig, infraConfig, apiConfig, networkConfig, _, clusterProxyConfig := getRouterDeploymentComponents(t) - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -227,7 +227,7 @@ func TestClusterProxy(t *testing.T) { clusterProxyConfig.Status.HTTPSProxy = "bar" clusterProxyConfig.Status.NoProxy = "baz" - deployment, err = desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false) + deployment, err = desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -392,7 +392,7 @@ func getRouterDeploymentComponents(t *testing.T) (*operatorv1.IngressController, func Test_desiredRouterDeployment(t *testing.T) { ic, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, clusterProxyConfig := getRouterDeploymentComponents(t) - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -447,6 +447,8 @@ func Test_desiredRouterDeployment(t *testing.T) { {"ROUTER_ERRORFILE_503", false, ""}, {"ROUTER_ERRORFILE_404", false, ""}, {"ROUTER_HAPROXY_CONFIG_MANAGER", false, ""}, + {"ROUTER_MAX_DYNAMIC_SERVERS", false, ""}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", false, ""}, {"ROUTER_H1_CASE_ADJUST", false, ""}, {"ROUTER_INSPECT_DELAY", false, ""}, {"ROUTER_IP_V4_V6_MODE", false, ""}, @@ -544,7 +546,7 @@ func checkProbes(t *testing.T, container *corev1.Container, useLocalhost bool) { func TestDesiredRouterDeploymentSpecTemplate(t *testing.T) { ic, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, clusterProxyConfig := getRouterDeploymentComponents(t) - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -685,7 +687,7 @@ func TestDesiredRouterDeploymentSpecAndNetwork(t *testing.T) { if err != nil { t.Errorf("failed to determine infrastructure platform status for ingresscontroller %s/%s: %v", ic.Namespace, ic.Name, err) } - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -728,6 +730,8 @@ func TestDesiredRouterDeploymentSpecAndNetwork(t *testing.T) { tests := []envData{ {"ROUTER_HAPROXY_CONFIG_MANAGER", false, ""}, {"ROUTER_LOAD_BALANCE_ALGORITHM", true, "leastconn"}, + {"ROUTER_MAX_DYNAMIC_SERVERS", false, ""}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", false, ""}, {"ROUTER_TCP_BALANCE_SCHEME", true, "source"}, {"ROUTER_MAX_CONNECTIONS", true, "auto"}, {RouterReloadIntervalEnvName, true, "5s"}, @@ -781,7 +785,7 @@ func TestDesiredRouterDeploymentSpecAndNetwork(t *testing.T) { if err != nil { t.Errorf("failed to determine infrastructure platform status for ingresscontroller %s/%s: %v", ic.Namespace, ic.Name, err) } - deployment, err = desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false) + deployment, err = desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -796,6 +800,8 @@ func TestDesiredRouterDeploymentSpecAndNetwork(t *testing.T) { tests = []envData{ {"ROUTER_HAPROXY_CONFIG_MANAGER", true, "true"}, {"ROUTER_LOAD_BALANCE_ALGORITHM", true, "random"}, + {"ROUTER_MAX_DYNAMIC_SERVERS", true, "1"}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", true, "0"}, {"ROUTER_TCP_BALANCE_SCHEME", true, "source"}, {"ROUTER_MAX_CONNECTIONS", true, "40000"}, {RouterReloadIntervalEnvName, true, "5s"}, @@ -889,7 +895,7 @@ func TestDesiredRouterDeploymentVariety(t *testing.T) { if err != nil { t.Errorf("failed to determine infrastructure platform status for ingresscontroller %s/%s: %v", ic.Namespace, ic.Name, err) } - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -1007,7 +1013,7 @@ func TestDesiredRouterDeploymentHostNetworkNil(t *testing.T) { if err != nil { t.Fatal(err) } - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, proxyNeeded, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatal(err) } @@ -1038,7 +1044,7 @@ func TestDesiredRouterDeploymentSingleReplica(t *testing.T) { }, } - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -1073,7 +1079,7 @@ func TestDesiredRouterDeploymentClientTLS(t *testing.T) { }, } clientCAConfigmap := &corev1.ConfigMap{} - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, true, clientCAConfigmap, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, true, clientCAConfigmap, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router deployment: %v", err) } @@ -1109,6 +1115,115 @@ func TestDesiredRouterDeploymentClientTLS(t *testing.T) { } } +// TestDesiredRouterDeploymentDynamicConfigManager verifies that desiredRouterDeployment +// returns the expected deployment when DCM featuregate is involved. +func TestDesiredRouterDeploymentDynamicConfigManager(t *testing.T) { + testCases := []struct { + name string + unsupportedConfigOverrides string + dcmEnabled bool + expectedEnv []envData + }{ + { + name: "featuregate-enabled-default-values", + dcmEnabled: true, + expectedEnv: []envData{ + {"ROUTER_HAPROXY_CONFIG_MANAGER", true, "true"}, + {"ROUTER_MAX_DYNAMIC_SERVERS", true, "1"}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", true, "0"}, + }, + }, + { + name: "featuregate-enabled-max-servers", + unsupportedConfigOverrides: `{"maxDynamicServers":"7"}`, + dcmEnabled: true, + expectedEnv: []envData{ + {"ROUTER_HAPROXY_CONFIG_MANAGER", true, "true"}, + {"ROUTER_MAX_DYNAMIC_SERVERS", true, "7"}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", true, "0"}, + }, + }, + { + name: "featuregate-enabled-max-servers-lower-limit", + unsupportedConfigOverrides: `{"maxDynamicServers":"0"}`, + dcmEnabled: true, + expectedEnv: []envData{ + {"ROUTER_HAPROXY_CONFIG_MANAGER", true, "true"}, + {"ROUTER_MAX_DYNAMIC_SERVERS", true, "1"}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", true, "0"}, + }, + }, + { + name: "featuregate-enabled-dcm-override", + unsupportedConfigOverrides: `{"dynamicConfigManager":"false","maxDynamicServers":"7"}`, + dcmEnabled: true, + expectedEnv: []envData{ + {"ROUTER_HAPROXY_CONFIG_MANAGER", false, ""}, + {"ROUTER_MAX_DYNAMIC_SERVERS", false, ""}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", false, ""}, + }, + }, + { + name: "featuregate-disabled-default-values", + dcmEnabled: false, + expectedEnv: []envData{ + {"ROUTER_HAPROXY_CONFIG_MANAGER", false, ""}, + {"ROUTER_MAX_DYNAMIC_SERVERS", false, ""}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", false, ""}, + }, + }, + { + name: "featuregate-disabled-max-servers", + unsupportedConfigOverrides: `{"maxDynamicServers":"7"}`, + dcmEnabled: false, + expectedEnv: []envData{ + {"ROUTER_HAPROXY_CONFIG_MANAGER", false, ""}, + {"ROUTER_MAX_DYNAMIC_SERVERS", false, ""}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", false, ""}, + }, + }, + { + name: "featuregate-disabled-dcm-override", + unsupportedConfigOverrides: `{"dynamicConfigManager":"true","maxDynamicServers":"100"}`, + dcmEnabled: false, + expectedEnv: []envData{ + {"ROUTER_HAPROXY_CONFIG_MANAGER", true, "true"}, + {"ROUTER_MAX_DYNAMIC_SERVERS", true, "100"}, + {"ROUTER_BLUEPRINT_ROUTE_POOL_SIZE", true, "0"}, + }, + }, + } + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + ic := &operatorv1.IngressController{ + ObjectMeta: metav1.ObjectMeta{ + Name: "default", + }, + Spec: operatorv1.IngressControllerSpec{ + UnsupportedConfigOverrides: runtime.RawExtension{ + Raw: []byte(tc.unsupportedConfigOverrides), + }, + }, + // The status does not matter in the context of this test, just use a dummy value. + Status: operatorv1.IngressControllerStatus{ + EndpointPublishingStrategy: &operatorv1.EndpointPublishingStrategy{ + Type: operatorv1.PrivateStrategyType, + }, + }, + } + + deployment, err := desiredRouterDeployment(ic, "dummy", &configv1.Ingress{}, &configv1.Infrastructure{}, &configv1.APIServer{}, &configv1.Network{}, false, false, nil, &configv1.Proxy{}, false, tc.dcmEnabled) + if err != nil { + t.Error(err) + } + + if err := checkDeploymentEnvironment(t, deployment, tc.expectedEnv); err != nil { + t.Error(err) + } + }) + } +} + func checkContainerPort(t *testing.T, d *appsv1.Deployment, portName string, port int32) { t.Helper() for _, p := range d.Spec.Template.Spec.Containers[0].Ports { @@ -2398,7 +2513,7 @@ func TestDesiredRouterDeploymentDefaultPlacement(t *testing.T) { // This value does not matter in the context of this test, just use a dummy value dummyProxyNeeded := true - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, tc.ingressConfig, tc.infraConfig, apiConfig, networkConfig, dummyProxyNeeded, false, nil, &configv1.Proxy{}, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, tc.ingressConfig, tc.infraConfig, apiConfig, networkConfig, dummyProxyNeeded, false, nil, &configv1.Proxy{}, false, false) if err != nil { t.Error(err) } @@ -2419,7 +2534,7 @@ func TestDesiredRouterDeploymentDefaultPlacement(t *testing.T) { func TestDesiredRouterDeploymentRouterExternalCertificate(t *testing.T) { ic, ingressConfig, infraConfig, apiConfig, networkConfig, _, clusterProxyConfig := getRouterDeploymentComponents(t) - deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false) + deployment, err := desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, false, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } @@ -2433,7 +2548,7 @@ func TestDesiredRouterDeploymentRouterExternalCertificate(t *testing.T) { t.Error(err) } - deployment, err = desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, true) + deployment, err = desiredRouterDeployment(ic, ingressControllerImage, ingressConfig, infraConfig, apiConfig, networkConfig, false, false, nil, clusterProxyConfig, true, false) if err != nil { t.Fatalf("invalid router Deployment: %v", err) } diff --git a/pkg/operator/operator.go b/pkg/operator/operator.go index 5c36e2db5..b4448c8fd 100644 --- a/pkg/operator/operator.go +++ b/pkg/operator/operator.go @@ -135,6 +135,7 @@ func New(config operatorconfig.Config, kubeConfig *rest.Config) (*Operator, erro routeExternalCertificateEnabled := featureGates.Enabled(features.FeatureGateRouteExternalCertificate) ingressControllerLBSubnetsAWSEnabled := featureGates.Enabled(features.FeatureGateIngressControllerLBSubnetsAWS) ingressControllerEIPAllocationsAWSEnabled := featureGates.Enabled(features.FeatureGateSetEIPForNLBIngressController) + ingressControllerDCMEnabled := featureGates.Enabled(features.FeatureGateIngressControllerDynamicConfigurationManager) // Set up an operator manager for the operator namespace. mgr, err := manager.New(kubeConfig, manager.Options{ @@ -172,6 +173,7 @@ func New(config operatorconfig.Config, kubeConfig *rest.Config) (*Operator, erro RouteExternalCertificateEnabled: routeExternalCertificateEnabled, IngressControllerLBSubnetsAWSEnabled: ingressControllerLBSubnetsAWSEnabled, IngressControllerEIPAllocationsAWSEnabled: ingressControllerEIPAllocationsAWSEnabled, + IngressControllerDCMEnabled: ingressControllerDCMEnabled, }); err != nil { return nil, fmt.Errorf("failed to create ingress controller: %v", err) } diff --git a/test/e2e/operator_test.go b/test/e2e/operator_test.go index ed17be552..b9fb0d818 100644 --- a/test/e2e/operator_test.go +++ b/test/e2e/operator_test.go @@ -27,6 +27,7 @@ import ( "gopkg.in/yaml.v2" configv1 "github.com/openshift/api/config/v1" + "github.com/openshift/api/features" operatorv1 "github.com/openshift/api/operator/v1" iov1 "github.com/openshift/api/operatoringress/v1" routev1 "github.com/openshift/api/route/v1" @@ -3508,11 +3509,32 @@ func TestLoadBalancingAlgorithmUnsupportedConfigOverride(t *testing.T) { func TestUnsupportedConfigOverride(t *testing.T) { t.Parallel() + var ( + dcmDefaultValue = "" + dcmUpdateValue = "true" + dcmExpectedValue = "true" + maxServersDefaultValue = "" + maxServersUpdateValue = "2" + maxServersExpectedValue = "" // max dynamic servers cannot be set if DCM is off + ) + + if dcmEnabled, err := isFeatureGateEnabled(features.FeatureGateIngressControllerDynamicConfigurationManager); err != nil { + t.Fatalf("failed to get dynamic config manager feature gate: %v", err) + } else if dcmEnabled { + dcmDefaultValue = "true" + dcmUpdateValue = "false" + dcmExpectedValue = "" + maxServersDefaultValue = "1" + maxServersUpdateValue = "2" + maxServersExpectedValue = "2" + } + var tests = []struct { - name, unsupportedConfigOverride, env string + name, unsupportedConfigOverride, env, defaultValue, updateValue, expectedValue string }{ - {"dynamic-config-manager", "dynamicConfigManager", "ROUTER_HAPROXY_CONFIG_MANAGER"}, - {"contstats", "contStats", "ROUTER_HAPROXY_CONTSTATS"}, + {"dynamic-config-manager", "dynamicConfigManager", "ROUTER_HAPROXY_CONFIG_MANAGER", dcmDefaultValue, dcmUpdateValue, dcmExpectedValue}, + {"contstats", "contStats", "ROUTER_HAPROXY_CONTSTATS", "", "true", "true"}, + {"max-dynamic-servers", "maxDynamicServers", "ROUTER_MAX_DYNAMIC_SERVERS", maxServersDefaultValue, maxServersUpdateValue, maxServersExpectedValue}, } for _, tt := range tests { @@ -3533,22 +3555,21 @@ func TestUnsupportedConfigOverride(t *testing.T) { if err := kclient.Get(context.TODO(), controller.RouterDeploymentName(ic), deployment); err != nil { t.Fatalf("failed to get ingresscontroller deployment: %v", err) } - if err := waitForDeploymentEnvVar(t, kclient, deployment, 30*time.Second, tt.env, ""); err != nil { - t.Fatalf("expected initial deployment not to set %s=true: %v", tt.env, err) + if err := waitForDeploymentEnvVar(t, kclient, deployment, 30*time.Second, tt.env, tt.defaultValue); err != nil { + t.Fatalf("expected initial deployment not to set %s=%s: %v", tt.env, tt.defaultValue, err) } if err := updateIngressControllerWithRetryOnConflict(t, icName, timeout, func(ic *operatorv1.IngressController) { ic.Spec.UnsupportedConfigOverrides = runtime.RawExtension{ - Raw: []byte(fmt.Sprintf(`{"%s":"true"}`, tt.unsupportedConfigOverride)), + Raw: []byte(fmt.Sprintf(`{"%s":"%s"}`, tt.unsupportedConfigOverride, tt.updateValue)), } }); err != nil { t.Fatalf("failed to update ingresscontroller: %v", err) } - if err := waitForDeploymentEnvVar(t, kclient, deployment, 1*time.Minute, tt.env, "true"); err != nil { - t.Fatalf("expected updated deployment to set %s=true: %v", tt.env, err) + if err := waitForDeploymentEnvVar(t, kclient, deployment, 1*time.Minute, tt.env, tt.expectedValue); err != nil { + t.Fatalf("expected updated deployment to set %s=%s: %v", tt.env, tt.expectedValue, err) } }) - } } diff --git a/vendor/github.com/openshift/api/config/v1/types_infrastructure.go b/vendor/github.com/openshift/api/config/v1/types_infrastructure.go index 392d128c1..0daa62d30 100644 --- a/vendor/github.com/openshift/api/config/v1/types_infrastructure.go +++ b/vendor/github.com/openshift/api/config/v1/types_infrastructure.go @@ -507,6 +507,20 @@ type AWSPlatformStatus struct { // +listType=atomic // +optional ResourceTags []AWSResourceTag `json:"resourceTags,omitempty"` + + // cloudLoadBalancerConfig holds configuration related to DNS and cloud + // load balancers. It allows configuration of in-cluster DNS as an alternative + // to the platform default DNS implementation. + // When using the ClusterHosted DNS type, Load Balancer IP addresses + // must be provided for the API and internal API load balancers as well as the + // ingress load balancer. + // + // +default={"dnsType": "PlatformDefault"} + // +kubebuilder:default={"dnsType": "PlatformDefault"} + // +openshift:enable:FeatureGate=AWSClusterHostedDNS + // +optional + // +nullable + CloudLoadBalancerConfig *CloudLoadBalancerConfig `json:"cloudLoadBalancerConfig,omitempty"` } // AWSResourceTag is a tag to apply to AWS resources created for the cluster. @@ -647,12 +661,12 @@ type GCPPlatformStatus struct { // Tombstone the field as a reminder. // ClusterHostedDNS ClusterHostedDNS `json:"clusterHostedDNS,omitempty"` - // cloudLoadBalancerConfig is a union that contains the IP addresses of API, - // API-Int and Ingress Load Balancers created on the cloud platform. These - // values would not be populated on on-prem platforms. These Load Balancer - // IPs are used to configure the in-cluster DNS instances for API, API-Int - // and Ingress services. `dnsType` is expected to be set to `ClusterHosted` - // when these Load Balancer IP addresses are populated and used. + // cloudLoadBalancerConfig holds configuration related to DNS and cloud + // load balancers. It allows configuration of in-cluster DNS as an alternative + // to the platform default DNS implementation. + // When using the ClusterHosted DNS type, Load Balancer IP addresses + // must be provided for the API and internal API load balancers as well as the + // ingress load balancer. // // +default={"dnsType": "PlatformDefault"} // +kubebuilder:default={"dnsType": "PlatformDefault"} diff --git a/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go index 069346998..1b7fa44aa 100644 --- a/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.go @@ -245,6 +245,11 @@ func (in *AWSPlatformStatus) DeepCopyInto(out *AWSPlatformStatus) { *out = make([]AWSResourceTag, len(*in)) copy(*out, *in) } + if in.CloudLoadBalancerConfig != nil { + in, out := &in.CloudLoadBalancerConfig, &out.CloudLoadBalancerConfig + *out = new(CloudLoadBalancerConfig) + (*in).DeepCopyInto(*out) + } return } diff --git a/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml b/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml index fa5dd4e31..6b8dfd3f0 100644 --- a/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml +++ b/vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yaml @@ -310,6 +310,7 @@ infrastructures.config.openshift.io: Capability: "" Category: "" FeatureGates: + - AWSClusterHostedDNS - BareMetalLoadBalancer - GCPClusterHostedDNS - GCPLabelsTags diff --git a/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go index c580bd834..ea3a42404 100644 --- a/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.go @@ -1184,10 +1184,11 @@ func (AWSPlatformSpec) SwaggerDoc() map[string]string { } var map_AWSPlatformStatus = map[string]string{ - "": "AWSPlatformStatus holds the current status of the Amazon Web Services infrastructure provider.", - "region": "region holds the default AWS region for new AWS resources created by the cluster.", - "serviceEndpoints": "ServiceEndpoints list contains custom endpoints which will override default service endpoint of AWS Services. There must be only one ServiceEndpoint for a service.", - "resourceTags": "resourceTags is a list of additional tags to apply to AWS resources created for the cluster. See https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for information on tagging AWS resources. AWS supports a maximum of 50 tags per resource. OpenShift reserves 25 tags for its use, leaving 25 tags available for the user.", + "": "AWSPlatformStatus holds the current status of the Amazon Web Services infrastructure provider.", + "region": "region holds the default AWS region for new AWS resources created by the cluster.", + "serviceEndpoints": "ServiceEndpoints list contains custom endpoints which will override default service endpoint of AWS Services. There must be only one ServiceEndpoint for a service.", + "resourceTags": "resourceTags is a list of additional tags to apply to AWS resources created for the cluster. See https://docs.aws.amazon.com/general/latest/gr/aws_tagging.html for information on tagging AWS resources. AWS supports a maximum of 50 tags per resource. OpenShift reserves 25 tags for its use, leaving 25 tags available for the user.", + "cloudLoadBalancerConfig": "cloudLoadBalancerConfig holds configuration related to DNS and cloud load balancers. It allows configuration of in-cluster DNS as an alternative to the platform default DNS implementation. When using the ClusterHosted DNS type, Load Balancer IP addresses must be provided for the API and internal API load balancers as well as the ingress load balancer.", } func (AWSPlatformStatus) SwaggerDoc() map[string]string { @@ -1389,7 +1390,7 @@ var map_GCPPlatformStatus = map[string]string{ "region": "region holds the region for new GCP resources created for the cluster.", "resourceLabels": "resourceLabels is a list of additional labels to apply to GCP resources created for the cluster. See https://cloud.google.com/compute/docs/labeling-resources for information on labeling GCP resources. GCP supports a maximum of 64 labels per resource. OpenShift reserves 32 labels for internal use, allowing 32 labels for user configuration.", "resourceTags": "resourceTags is a list of additional tags to apply to GCP resources created for the cluster. See https://cloud.google.com/resource-manager/docs/tags/tags-overview for information on tagging GCP resources. GCP supports a maximum of 50 tags per resource.", - "cloudLoadBalancerConfig": "cloudLoadBalancerConfig is a union that contains the IP addresses of API, API-Int and Ingress Load Balancers created on the cloud platform. These values would not be populated on on-prem platforms. These Load Balancer IPs are used to configure the in-cluster DNS instances for API, API-Int and Ingress services. `dnsType` is expected to be set to `ClusterHosted` when these Load Balancer IP addresses are populated and used.", + "cloudLoadBalancerConfig": "cloudLoadBalancerConfig holds configuration related to DNS and cloud load balancers. It allows configuration of in-cluster DNS as an alternative to the platform default DNS implementation. When using the ClusterHosted DNS type, Load Balancer IP addresses must be provided for the API and internal API load balancers as well as the ingress load balancer.", } func (GCPPlatformStatus) SwaggerDoc() map[string]string { diff --git a/vendor/github.com/openshift/api/config/v1alpha1/types_cluster_image_policy.go b/vendor/github.com/openshift/api/config/v1alpha1/types_cluster_image_policy.go index e3670f03e..14650fd48 100644 --- a/vendor/github.com/openshift/api/config/v1alpha1/types_cluster_image_policy.go +++ b/vendor/github.com/openshift/api/config/v1alpha1/types_cluster_image_policy.go @@ -41,6 +41,7 @@ type ClusterImagePolicySpec struct { // If multiple scopes match a given image, only the policy requirements for the most specific scope apply. The policy requirements for more general scopes are ignored. // In addition to setting a policy appropriate for your own deployed applications, make sure that a policy on the OpenShift image repositories // quay.io/openshift-release-dev/ocp-release, quay.io/openshift-release-dev/ocp-v4.0-art-dev (or on a more general scope) allows deployment of the OpenShift images required for cluster operation. + // If a scope is configured in both the ClusterImagePolicy and the ImagePolicy, or if the scope in ImagePolicy is nested under one of the scopes from the ClusterImagePolicy, only the policy from the ClusterImagePolicy will be applied. // For additional details about the format, please refer to the document explaining the docker transport field, // which can be found at: https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md#docker // +kubebuilder:validation:Required diff --git a/vendor/github.com/openshift/api/config/v1alpha1/types_image_policy.go b/vendor/github.com/openshift/api/config/v1alpha1/types_image_policy.go index 7031110ff..a177ddb0d 100644 --- a/vendor/github.com/openshift/api/config/v1alpha1/types_image_policy.go +++ b/vendor/github.com/openshift/api/config/v1alpha1/types_image_policy.go @@ -40,6 +40,7 @@ type ImagePolicySpec struct { // If multiple scopes match a given image, only the policy requirements for the most specific scope apply. The policy requirements for more general scopes are ignored. // In addition to setting a policy appropriate for your own deployed applications, make sure that a policy on the OpenShift image repositories // quay.io/openshift-release-dev/ocp-release, quay.io/openshift-release-dev/ocp-v4.0-art-dev (or on a more general scope) allows deployment of the OpenShift images required for cluster operation. + // If a scope is configured in both the ClusterImagePolicy and the ImagePolicy, or if the scope in ImagePolicy is nested under one of the scopes from the ClusterImagePolicy, only the policy from the ClusterImagePolicy will be applied. // For additional details about the format, please refer to the document explaining the docker transport field, // which can be found at: https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md#docker // +kubebuilder:validation:Required diff --git a/vendor/github.com/openshift/api/config/v1alpha1/zz_generated.swagger_doc_generated.go b/vendor/github.com/openshift/api/config/v1alpha1/zz_generated.swagger_doc_generated.go index 9da086efc..55468f38d 100644 --- a/vendor/github.com/openshift/api/config/v1alpha1/zz_generated.swagger_doc_generated.go +++ b/vendor/github.com/openshift/api/config/v1alpha1/zz_generated.swagger_doc_generated.go @@ -102,7 +102,7 @@ func (ClusterImagePolicyList) SwaggerDoc() map[string]string { var map_ClusterImagePolicySpec = map[string]string{ "": "CLusterImagePolicySpec is the specification of the ClusterImagePolicy custom resource.", - "scopes": "scopes defines the list of image identities assigned to a policy. Each item refers to a scope in a registry implementing the \"Docker Registry HTTP API V2\". Scopes matching individual images are named Docker references in the fully expanded form, either using a tag or digest. For example, docker.io/library/busybox:latest (not busybox:latest). More general scopes are prefixes of individual-image scopes, and specify a repository (by omitting the tag or digest), a repository namespace, or a registry host (by only specifying the host name and possibly a port number) or a wildcard expression starting with `*.`, for matching all subdomains (not including a port number). Wildcards are only supported for subdomain matching, and may not be used in the middle of the host, i.e. *.example.com is a valid case, but example*.*.com is not. If multiple scopes match a given image, only the policy requirements for the most specific scope apply. The policy requirements for more general scopes are ignored. In addition to setting a policy appropriate for your own deployed applications, make sure that a policy on the OpenShift image repositories quay.io/openshift-release-dev/ocp-release, quay.io/openshift-release-dev/ocp-v4.0-art-dev (or on a more general scope) allows deployment of the OpenShift images required for cluster operation. For additional details about the format, please refer to the document explaining the docker transport field, which can be found at: https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md#docker", + "scopes": "scopes defines the list of image identities assigned to a policy. Each item refers to a scope in a registry implementing the \"Docker Registry HTTP API V2\". Scopes matching individual images are named Docker references in the fully expanded form, either using a tag or digest. For example, docker.io/library/busybox:latest (not busybox:latest). More general scopes are prefixes of individual-image scopes, and specify a repository (by omitting the tag or digest), a repository namespace, or a registry host (by only specifying the host name and possibly a port number) or a wildcard expression starting with `*.`, for matching all subdomains (not including a port number). Wildcards are only supported for subdomain matching, and may not be used in the middle of the host, i.e. *.example.com is a valid case, but example*.*.com is not. If multiple scopes match a given image, only the policy requirements for the most specific scope apply. The policy requirements for more general scopes are ignored. In addition to setting a policy appropriate for your own deployed applications, make sure that a policy on the OpenShift image repositories quay.io/openshift-release-dev/ocp-release, quay.io/openshift-release-dev/ocp-v4.0-art-dev (or on a more general scope) allows deployment of the OpenShift images required for cluster operation. If a scope is configured in both the ClusterImagePolicy and the ImagePolicy, or if the scope in ImagePolicy is nested under one of the scopes from the ClusterImagePolicy, only the policy from the ClusterImagePolicy will be applied. For additional details about the format, please refer to the document explaining the docker transport field, which can be found at: https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md#docker", "policy": "policy contains configuration to allow scopes to be verified, and defines how images not matching the verification policy will be treated.", } @@ -151,7 +151,7 @@ func (ImagePolicyList) SwaggerDoc() map[string]string { var map_ImagePolicySpec = map[string]string{ "": "ImagePolicySpec is the specification of the ImagePolicy CRD.", - "scopes": "scopes defines the list of image identities assigned to a policy. Each item refers to a scope in a registry implementing the \"Docker Registry HTTP API V2\". Scopes matching individual images are named Docker references in the fully expanded form, either using a tag or digest. For example, docker.io/library/busybox:latest (not busybox:latest). More general scopes are prefixes of individual-image scopes, and specify a repository (by omitting the tag or digest), a repository namespace, or a registry host (by only specifying the host name and possibly a port number) or a wildcard expression starting with `*.`, for matching all subdomains (not including a port number). Wildcards are only supported for subdomain matching, and may not be used in the middle of the host, i.e. *.example.com is a valid case, but example*.*.com is not. If multiple scopes match a given image, only the policy requirements for the most specific scope apply. The policy requirements for more general scopes are ignored. In addition to setting a policy appropriate for your own deployed applications, make sure that a policy on the OpenShift image repositories quay.io/openshift-release-dev/ocp-release, quay.io/openshift-release-dev/ocp-v4.0-art-dev (or on a more general scope) allows deployment of the OpenShift images required for cluster operation. For additional details about the format, please refer to the document explaining the docker transport field, which can be found at: https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md#docker", + "scopes": "scopes defines the list of image identities assigned to a policy. Each item refers to a scope in a registry implementing the \"Docker Registry HTTP API V2\". Scopes matching individual images are named Docker references in the fully expanded form, either using a tag or digest. For example, docker.io/library/busybox:latest (not busybox:latest). More general scopes are prefixes of individual-image scopes, and specify a repository (by omitting the tag or digest), a repository namespace, or a registry host (by only specifying the host name and possibly a port number) or a wildcard expression starting with `*.`, for matching all subdomains (not including a port number). Wildcards are only supported for subdomain matching, and may not be used in the middle of the host, i.e. *.example.com is a valid case, but example*.*.com is not. If multiple scopes match a given image, only the policy requirements for the most specific scope apply. The policy requirements for more general scopes are ignored. In addition to setting a policy appropriate for your own deployed applications, make sure that a policy on the OpenShift image repositories quay.io/openshift-release-dev/ocp-release, quay.io/openshift-release-dev/ocp-v4.0-art-dev (or on a more general scope) allows deployment of the OpenShift images required for cluster operation. If a scope is configured in both the ClusterImagePolicy and the ImagePolicy, or if the scope in ImagePolicy is nested under one of the scopes from the ClusterImagePolicy, only the policy from the ClusterImagePolicy will be applied. For additional details about the format, please refer to the document explaining the docker transport field, which can be found at: https://github.com/containers/image/blob/main/docs/containers-policy.json.5.md#docker", "policy": "policy contains configuration to allow scopes to be verified, and defines how images not matching the verification policy will be treated.", } diff --git a/vendor/github.com/openshift/api/features.md b/vendor/github.com/openshift/api/features.md index e668fc88b..863039fcb 100644 --- a/vendor/github.com/openshift/api/features.md +++ b/vendor/github.com/openshift/api/features.md @@ -7,6 +7,7 @@ | MachineAPIOperatorDisableMachineHealthCheckController| | | | | | | | MultiArchInstallAzure| | | | | | | | GatewayAPI| | | Enabled | Enabled | | | +| AWSClusterHostedDNS| | | Enabled | Enabled | Enabled | Enabled | | AdditionalRoutingCapabilities| | | Enabled | Enabled | Enabled | Enabled | | AutomatedEtcdBackup| | | Enabled | Enabled | Enabled | Enabled | | BootcNodeManagement| | | Enabled | Enabled | Enabled | Enabled | @@ -18,6 +19,7 @@ | Example| | | Enabled | Enabled | Enabled | Enabled | | GCPClusterHostedDNS| | | Enabled | Enabled | Enabled | Enabled | | ImageStreamImportMode| | | Enabled | Enabled | Enabled | Enabled | +| IngressControllerDynamicConfigurationManager| | | Enabled | Enabled | Enabled | Enabled | | InsightsConfig| | | Enabled | Enabled | Enabled | Enabled | | InsightsConfigAPI| | | Enabled | Enabled | Enabled | Enabled | | InsightsOnDemandDataGather| | | Enabled | Enabled | Enabled | Enabled | diff --git a/vendor/github.com/openshift/api/features/features.go b/vendor/github.com/openshift/api/features/features.go index 7f4962395..2119c6cf6 100644 --- a/vendor/github.com/openshift/api/features/features.go +++ b/vendor/github.com/openshift/api/features/features.go @@ -313,6 +313,13 @@ var ( enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() + FeatureGateAWSClusterHostedDNS = newFeatureGate("AWSClusterHostedDNS"). + reportProblemsToJiraComponent("Installer"). + contactPerson("barbacbd"). + productScope(ocpSpecific). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() + FeatureGateMixedCPUsAllocation = newFeatureGate("MixedCPUsAllocation"). reportProblemsToJiraComponent("NodeTuningOperator"). contactPerson("titzhak"). @@ -569,4 +576,11 @@ var ( productScope(ocpSpecific). enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). mustRegister() + + FeatureGateIngressControllerDynamicConfigurationManager = newFeatureGate("IngressControllerDynamicConfigurationManager"). + reportProblemsToJiraComponent("Networking/router"). + contactPerson("miciah"). + productScope(ocpSpecific). + enableIn(configv1.DevPreviewNoUpgrade, configv1.TechPreviewNoUpgrade). + mustRegister() ) diff --git a/vendor/github.com/openshift/api/operator/v1/types.go b/vendor/github.com/openshift/api/operator/v1/types.go index 8d6f4b748..f04b6846a 100644 --- a/vendor/github.com/openshift/api/operator/v1/types.go +++ b/vendor/github.com/openshift/api/operator/v1/types.go @@ -147,17 +147,27 @@ type GenerationStatus struct { // group is the group of the thing you're tracking // +kubebuilder:validation:Required Group string `json:"group"` + // resource is the resource type of the thing you're tracking // +kubebuilder:validation:Required Resource string `json:"resource"` + // namespace is where the thing you're tracking is // +kubebuilder:validation:Required Namespace string `json:"namespace"` + // name is the name of the thing you're tracking // +kubebuilder:validation:Required Name string `json:"name"` + + // TODO: Add validation for lastGeneration. The value for this field should generally increase, except when the associated + // resource has been deleted and re-created. To accurately validate this field, we should introduce a new UID field and only + // enforce an increasing value in lastGeneration when the UID remains unchanged. A change in the UID indicates that the resource + // was re-created, allowing the lastGeneration value to reset or decrease. + // lastGeneration is the last generation of the workload controller involved LastGeneration int64 `json:"lastGeneration"` + // hash is an optional field set for resources without generation that are content sensitive like secrets and configmaps Hash string `json:"hash"` } diff --git a/vendor/modules.txt b/vendor/modules.txt index 355caca15..77b16ec66 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -410,7 +410,7 @@ github.com/mxk/go-flowrate/flowrate # github.com/oklog/ulid v1.3.1 ## explicit github.com/oklog/ulid -# github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible => github.com/openshift/api v0.0.0-20241004095111-b1f700bdd8d2 +# github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible => github.com/openshift/api v0.0.0-20241018083007-4f6053f954b0 ## explicit; go 1.22.0 github.com/openshift/api github.com/openshift/api/annotations @@ -1397,5 +1397,5 @@ sigs.k8s.io/structured-merge-diff/v4/value sigs.k8s.io/yaml sigs.k8s.io/yaml/goyaml.v2 # bitbucket.org/ww/goautoneg => github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d -# github.com/openshift/api => github.com/openshift/api v0.0.0-20241004095111-b1f700bdd8d2 +# github.com/openshift/api => github.com/openshift/api v0.0.0-20241018083007-4f6053f954b0 # k8s.io/client-go => k8s.io/client-go v0.31.1