diff --git a/data/data/install.openshift.io_installconfigs.yaml b/data/data/install.openshift.io_installconfigs.yaml index 4cc5cc24036..52c7f3083e6 100644 --- a/data/data/install.openshift.io_installconfigs.yaml +++ b/data/data/install.openshift.io_installconfigs.yaml @@ -4989,6 +4989,23 @@ spec: - cidr type: object type: array + networkObservability: + description: |- + NetworkObservability is an optional field that configures network observability installation + during cluster deployment (day-0). + When omitted, network observability will be installed unless this is a SNO cluster. + properties: + installationPolicy: + description: |- + InstallationPolicy controls whether network observability is installed during cluster deployment. + Valid values are "InstallAndEnable" and "NoAction". + When set to "InstallAndEnable", network observability will be installed and enabled. + When set to "NoAction", nothing will be done regarding network observability. + enum: + - InstallAndEnable + - NoAction + type: string + type: object networkType: default: OVNKubernetes description: |- diff --git a/pkg/asset/manifests/network.go b/pkg/asset/manifests/network.go index b79e7bb4896..cfcc3afd1b7 100644 --- a/pkg/asset/manifests/network.go +++ b/pkg/asset/manifests/network.go @@ -70,6 +70,23 @@ func (no *Networking) Generate(_ context.Context, dependencies asset.Parents) er serviceNet = append(serviceNet, sn.String()) } + networkSpec := configv1.NetworkSpec{ + ClusterNetwork: clusterNet, + ServiceNetwork: serviceNet, + NetworkType: netConfig.NetworkType, + // Block all Service.ExternalIPs by default + ExternalIP: &configv1.ExternalIPConfig{ + Policy: &configv1.ExternalIPPolicy{}, + }, + } + + // Set networkObservability from the install config + if netConfig.NetworkObservability != nil && netConfig.NetworkObservability.InstallationPolicy != nil { + networkSpec.NetworkObservability = configv1.NetworkObservabilitySpec{ + InstallationPolicy: configv1.NetworkObservabilityInstallationPolicy(*netConfig.NetworkObservability.InstallationPolicy), + } + } + no.Config = &configv1.Network{ TypeMeta: metav1.TypeMeta{ APIVersion: configv1.SchemeGroupVersion.String(), @@ -79,15 +96,7 @@ func (no *Networking) Generate(_ context.Context, dependencies asset.Parents) er Name: "cluster", // not namespaced }, - Spec: configv1.NetworkSpec{ - ClusterNetwork: clusterNet, - ServiceNetwork: serviceNet, - NetworkType: netConfig.NetworkType, - // Block all Service.ExternalIPs by default - ExternalIP: &configv1.ExternalIPConfig{ - Policy: &configv1.ExternalIPPolicy{}, - }, - }, + Spec: networkSpec, } configData, err := yaml.Marshal(no.Config) diff --git a/pkg/types/defaults/installconfig.go b/pkg/types/defaults/installconfig.go index 1652b45b11b..391809b5b8e 100644 --- a/pkg/types/defaults/installconfig.go +++ b/pkg/types/defaults/installconfig.go @@ -59,7 +59,6 @@ func SetInstallConfigDefaults(c *types.InstallConfig) { }, } } - if c.Publish == "" { c.Publish = types.ExternalPublishingStrategy } diff --git a/pkg/types/installconfig.go b/pkg/types/installconfig.go index c4fe6a7475d..64feeeee08b 100644 --- a/pkg/types/installconfig.go +++ b/pkg/types/installconfig.go @@ -531,6 +531,13 @@ type Networking struct { // pod network when NetworkType is set to OVNKubernetes. OVNKubernetesConfig *OVNKubernetesConfig `json:"ovnKubernetesConfig,omitempty"` + // NetworkObservability is an optional field that configures network observability installation + // during cluster deployment (day-0). + // When omitted, network observability will be installed unless this is a SNO cluster. + // + // +optional + NetworkObservability *NetworkObservability `json:"networkObservability,omitempty"` + // Deprecated types, scheduled to be removed // Deprecated way to configure an IP address pool for machines. @@ -797,3 +804,25 @@ func OSImageStreamValues() []OSImageStream { OSImageStreamRHCOS10, } } + +// NetworkObservabilityInstallationPolicy is an enumeration of the available network observability installation policies +// Valid values are "InstallAndEnable", "NoAction". +// +kubebuilder:validation:Enum=InstallAndEnable;NoAction +type NetworkObservabilityInstallationPolicy string + +const ( + // NetworkObservabilityInstallAndEnable means that network observability should be installed and enabled during cluster deployment. + NetworkObservabilityInstallAndEnable NetworkObservabilityInstallationPolicy = "InstallAndEnable" + // NetworkObservabilityNoAction means that nothing will be done regarding network observability. + NetworkObservabilityNoAction NetworkObservabilityInstallationPolicy = "NoAction" +) + +// NetworkObservability defines the configuration for network observability installation. +type NetworkObservability struct { + // InstallationPolicy controls whether network observability is installed during cluster deployment. + // Valid values are "InstallAndEnable" and "NoAction". + // When set to "InstallAndEnable", network observability will be installed and enabled. + // When set to "NoAction", nothing will be done regarding network observability. + // +optional + InstallationPolicy *NetworkObservabilityInstallationPolicy `json:"installationPolicy,omitempty"` +} diff --git a/pkg/types/validation/installconfig.go b/pkg/types/validation/installconfig.go index 2cb5689fd6d..220181f9e58 100644 --- a/pkg/types/validation/installconfig.go +++ b/pkg/types/validation/installconfig.go @@ -566,6 +566,20 @@ func validateNetworking(n *types.Networking, fldPath *field.Path) field.ErrorLis allErrs = append(allErrs, validateClusterNetwork(n, &cn, i, fldPath.Child("clusterNetwork").Index(i))...) } + if n.NetworkObservability != nil { + if n.NetworkObservability.InstallationPolicy == nil { + allErrs = append(allErrs, field.Required(fldPath.Child("networkObservability", "installationPolicy"), "installationPolicy is required when networkObservability is specified")) + } else { + validPolicies := map[types.NetworkObservabilityInstallationPolicy]bool{ + types.NetworkObservabilityInstallAndEnable: true, + types.NetworkObservabilityNoAction: true, + } + if !validPolicies[*n.NetworkObservability.InstallationPolicy] { + allErrs = append(allErrs, field.NotSupported(fldPath.Child("networkObservability", "installationPolicy"), *n.NetworkObservability.InstallationPolicy, []string{string(types.NetworkObservabilityInstallAndEnable), string(types.NetworkObservabilityNoAction)})) + } + } + } + return allErrs } diff --git a/pkg/types/validation/installconfig_test.go b/pkg/types/validation/installconfig_test.go index 93b3d3ac94e..5732d1f4988 100644 --- a/pkg/types/validation/installconfig_test.go +++ b/pkg/types/validation/installconfig_test.go @@ -406,6 +406,69 @@ func TestValidateInstallConfig(t *testing.T) { }(), expectedError: `^networking\.networkType: Invalid value: "OpenShiftSDN": networkType OpenShiftSDN is not supported, please use OVNKubernetes$`, }, + { + name: "invalid networkObservability installationPolicy", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + invalidPolicy := types.NetworkObservabilityInstallationPolicy("test") + c.Networking.NetworkObservability = &types.NetworkObservability{ + InstallationPolicy: &invalidPolicy, + } + return c + }(), + expectedError: `^networking\.networkObservability\.installationPolicy: Unsupported value: "test": supported values: "InstallAndEnable", "NoAction"$`, + }, + { + name: "missing networkObservability installationPolicy", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + c.Networking.NetworkObservability = &types.NetworkObservability{} + return c + }(), + expectedError: `^networking\.networkObservability\.installationPolicy: Required value: installationPolicy is required when networkObservability is specified$`, + }, + { + name: "blank networkObservability installationPolicy", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + blankPolicy := types.NetworkObservabilityInstallationPolicy("") + c.Networking.NetworkObservability = &types.NetworkObservability{ + InstallationPolicy: &blankPolicy, + } + return c + }(), + expectedError: `^networking\.networkObservability\.installationPolicy: Unsupported value: "": supported values: "InstallAndEnable", "NoAction"$`, + }, + { + name: "valid networkObservability InstallAndEnable", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + policy := types.NetworkObservabilityInstallAndEnable + c.Networking.NetworkObservability = &types.NetworkObservability{ + InstallationPolicy: &policy, + } + return c + }(), + }, + { + name: "valid networkObservability NoAction", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + policy := types.NetworkObservabilityNoAction + c.Networking.NetworkObservability = &types.NetworkObservability{ + InstallationPolicy: &policy, + } + return c + }(), + }, + { + name: "valid networkObservability absent", + installConfig: func() *types.InstallConfig { + c := validInstallConfig() + c.Networking.NetworkObservability = nil + return c + }(), + }, { name: "missing service network", installConfig: func() *types.InstallConfig { diff --git a/pkg/types/zz_generated.deepcopy.go b/pkg/types/zz_generated.deepcopy.go index 0cf5571f75a..22fa4b709df 100644 --- a/pkg/types/zz_generated.deepcopy.go +++ b/pkg/types/zz_generated.deepcopy.go @@ -690,6 +690,27 @@ func (in MirrorConfig) DeepCopy() MirrorConfig { return *out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkObservability) DeepCopyInto(out *NetworkObservability) { + *out = *in + if in.InstallationPolicy != nil { + in, out := &in.InstallationPolicy, &out.InstallationPolicy + *out = new(NetworkObservabilityInstallationPolicy) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkObservability. +func (in *NetworkObservability) DeepCopy() *NetworkObservability { + if in == nil { + return nil + } + out := new(NetworkObservability) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Networking) DeepCopyInto(out *Networking) { *out = *in @@ -719,6 +740,11 @@ func (in *Networking) DeepCopyInto(out *Networking) { *out = new(OVNKubernetesConfig) (*in).DeepCopyInto(*out) } + if in.NetworkObservability != nil { + in, out := &in.NetworkObservability, &out.NetworkObservability + *out = new(NetworkObservability) + (*in).DeepCopyInto(*out) + } if in.DeprecatedMachineCIDR != nil { in, out := &in.DeprecatedMachineCIDR, &out.DeprecatedMachineCIDR *out = (*in).DeepCopy()