diff --git a/api/v1beta1/hostedcluster_types.go b/api/v1beta1/hostedcluster_types.go index 474b09ac186..27b52b90d4e 100644 --- a/api/v1beta1/hostedcluster_types.go +++ b/api/v1beta1/hostedcluster_types.go @@ -133,6 +133,14 @@ const ( // SilenceClusterAlertsLabel is a label that can be used by consumers to indicate // alerts from a cluster can be silenced or ignored SilenceClusterAlertsLabel = "hypershift.openshift.io/silence-cluster-alerts" + + // InfraIDLabel is a label that indicates the hosted cluster's infra id + // that the resource is associated with. + InfraIDLabel = "hypershift.openshift.io/infra-id" + + // NodePoolNameLabel is a label that indicates the name of the node pool + // a resource is associated with + NodePoolNameLabel = "hypershift.openshift.io/nodepool-name" ) // HostedClusterSpec is the desired behavior of a HostedCluster. @@ -683,6 +691,14 @@ type KubevirtPlatformSpec struct { // +optional // +immutable BaseDomainPassthrough *bool `json:"baseDomainPassthrough,omitempty"` + + // GenerateID is used to uniquely apply a name postfix to resources associated with + // kubevirt infrastructure resources + // +kubebuilder:validation:Optional + // +kubebuilder:validation:XValidation:rule="self == oldSelf",message="Value is immutable" + // +kubebuilder:validation:MaxLength=11 + // +optional + GenerateID string `json:"generateID,omitempty"` } // AgentPlatformSpec specifies configuration for agent-based installations. diff --git a/cmd/install/assets/hypershift-operator/hypershift.openshift.io_hostedclusters.yaml b/cmd/install/assets/hypershift-operator/hypershift.openshift.io_hostedclusters.yaml index f874b45d65e..f28fd5f2477 100644 --- a/cmd/install/assets/hypershift-operator/hypershift.openshift.io_hostedclusters.yaml +++ b/cmd/install/assets/hypershift-operator/hypershift.openshift.io_hostedclusters.yaml @@ -6260,6 +6260,14 @@ spec: Cluster: guest.apps.mgmt-cluster.example.com Apps: *.apps.guest.apps.mgmt-cluster.example.com \n This is possible using OCP wildcard routes" type: boolean + generateID: + description: GenerateID is used to uniquely apply a name postfix + to resources associated with kubevirt infrastructure resources + maxLength: 11 + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf type: object powervs: description: PowerVS specifies configuration for clusters running diff --git a/cmd/install/assets/hypershift-operator/hypershift.openshift.io_hostedcontrolplanes.yaml b/cmd/install/assets/hypershift-operator/hypershift.openshift.io_hostedcontrolplanes.yaml index 5daead1606b..478aa9458b8 100644 --- a/cmd/install/assets/hypershift-operator/hypershift.openshift.io_hostedcontrolplanes.yaml +++ b/cmd/install/assets/hypershift-operator/hypershift.openshift.io_hostedcontrolplanes.yaml @@ -6249,6 +6249,14 @@ spec: Cluster: guest.apps.mgmt-cluster.example.com Apps: *.apps.guest.apps.mgmt-cluster.example.com \n This is possible using OCP wildcard routes" type: boolean + generateID: + description: GenerateID is used to uniquely apply a name postfix + to resources associated with kubevirt infrastructure resources + maxLength: 11 + type: string + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf type: object powervs: description: PowerVS specifies configuration for clusters running diff --git a/control-plane-operator/controllers/hostedcontrolplane/cloud/kubevirt/providerconfig.go b/control-plane-operator/controllers/hostedcontrolplane/cloud/kubevirt/providerconfig.go index 8012b8a89a1..929cdd64ce7 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/cloud/kubevirt/providerconfig.go +++ b/control-plane-operator/controllers/hostedcontrolplane/cloud/kubevirt/providerconfig.go @@ -1,6 +1,7 @@ package kubevirt import ( + hyperv1 "github.com/openshift/hypershift/api/v1beta1" "gopkg.in/yaml.v2" ) @@ -15,6 +16,7 @@ type CloudConfig struct { LoadBalancer LoadBalancerConfig `yaml:"loadBalancer"` InstancesV2 InstancesV2Config `yaml:"instancesV2"` Namespace string `yaml:"namespace"` + InfraLabels map[string]string `yaml:"infraLabels"` } type LoadBalancerConfig struct { @@ -39,7 +41,7 @@ func (c *CloudConfig) serialize() (string, error) { return string(out), nil } -func cloudConfig(namespace string) CloudConfig { +func cloudConfig(hcp *hyperv1.HostedControlPlane) CloudConfig { return CloudConfig{ LoadBalancer: LoadBalancerConfig{ Enabled: true, @@ -48,6 +50,9 @@ func cloudConfig(namespace string) CloudConfig { Enabled: true, ZoneAndRegionEnabled: false, }, - Namespace: namespace, + Namespace: hcp.Namespace, + InfraLabels: map[string]string{ + hyperv1.InfraIDLabel: hcp.Spec.InfraID, + }, } } diff --git a/control-plane-operator/controllers/hostedcontrolplane/cloud/kubevirt/reconcile.go b/control-plane-operator/controllers/hostedcontrolplane/cloud/kubevirt/reconcile.go index ec119151d2a..ba050da94ce 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/cloud/kubevirt/reconcile.go +++ b/control-plane-operator/controllers/hostedcontrolplane/cloud/kubevirt/reconcile.go @@ -16,7 +16,7 @@ import ( ) func ReconcileCloudConfig(cm *corev1.ConfigMap, hcp *hyperv1.HostedControlPlane) error { - cfg := cloudConfig(hcp.Namespace) + cfg := cloudConfig(hcp) serializedCfg, err := cfg.serialize() if err != nil { return fmt.Errorf("failed to serialize cloudconfig: %w", err) diff --git a/control-plane-operator/controllers/hostedcontrolplane/csi/kubevirt/kubevirt.go b/control-plane-operator/controllers/hostedcontrolplane/csi/kubevirt/kubevirt.go index ca270a996c8..301b605f4fb 100644 --- a/control-plane-operator/controllers/hostedcontrolplane/csi/kubevirt/kubevirt.go +++ b/control-plane-operator/controllers/hostedcontrolplane/csi/kubevirt/kubevirt.go @@ -121,10 +121,10 @@ func getContentsOrDie(file string) []byte { return b } -func reconcileInfraConfigMap(cm *corev1.ConfigMap) error { +func reconcileInfraConfigMap(cm *corev1.ConfigMap, infraID string) error { cm.Data = map[string]string{ "infraClusterNamespace": cm.Namespace, - "infraClusterLabels": "", + "infraClusterLabels": fmt.Sprintf("%s=%s", hyperv1.InfraIDLabel, infraID), } return nil } @@ -420,7 +420,7 @@ func ReconcileInfra(client crclient.Client, hcp *hyperv1.HostedControlPlane, ctx infraConfigMap := manifests.KubevirtCSIDriverInfraConfigMap(infraNamespace) _, err = createOrUpdate(ctx, client, infraConfigMap, func() error { - return reconcileInfraConfigMap(infraConfigMap) + return reconcileInfraConfigMap(infraConfigMap, hcp.Spec.InfraID) }) if err != nil { return err diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/ingress/reconcile.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/ingress/reconcile.go index f9e642ff375..434f5470469 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/ingress/reconcile.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/ingress/reconcile.go @@ -112,6 +112,9 @@ func ReconcileDefaultIngressPassthroughService(service *corev1.Service, defaultN return fmt.Errorf("unable to detect default ingress NodePort https port") } + if service.Labels == nil { + service.Labels = map[string]string{} + } service.Spec.Ports = []corev1.ServicePort{ { Name: "https-443", @@ -121,10 +124,13 @@ func ReconcileDefaultIngressPassthroughService(service *corev1.Service, defaultN }, } service.Spec.Selector = map[string]string{ - "kubevirt.io": "virt-launcher", + "kubevirt.io": "virt-launcher", + hyperv1.InfraIDLabel: hcp.Spec.InfraID, } service.Spec.Type = corev1.ServiceTypeClusterIP + service.Labels[hyperv1.InfraIDLabel] = hcp.Spec.InfraID + ownerRef.ApplyTo(service) return nil @@ -133,6 +139,9 @@ func ReconcileDefaultIngressPassthroughService(service *corev1.Service, defaultN func ReconcileDefaultIngressPassthroughRoute(route *routev1.Route, cpService *corev1.Service, hcp *hyperv1.HostedControlPlane) error { ownerRef := config.OwnerRefFrom(hcp) + if route.Labels == nil { + route.Labels = map[string]string{} + } route.Spec.WildcardPolicy = routev1.WildcardPolicySubdomain route.Spec.Host = fmt.Sprintf("https.apps.%s.%s", hcp.Name, hcp.Spec.DNS.BaseDomain) route.Spec.TLS = &routev1.TLSConfig{ @@ -142,6 +151,7 @@ func ReconcileDefaultIngressPassthroughRoute(route *routev1.Route, cpService *co Kind: "Service", Name: cpService.Name, } + route.Labels[hyperv1.InfraIDLabel] = hcp.Spec.InfraID ownerRef.ApplyTo(route) diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/manifests/ingress.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/manifests/ingress.go index 30a9490af37..13aec3a4ce7 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/manifests/ingress.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/manifests/ingress.go @@ -35,19 +35,21 @@ func IngressDefaultIngressNodePortService() *corev1.Service { } } +const IngressDefaultIngressPassthroughServiceName = "default-ingress-passthrough-service" + func IngressDefaultIngressPassthroughService(namespace string) *corev1.Service { return &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: "default-ingress-passthrough-service", Namespace: namespace, }, } } +const IngressDefaultIngressPassthroughRouteName = "default-ingress-passthrough-route" + func IngressDefaultIngressPassthroughRoute(namespace string) *routev1.Route { return &routev1.Route{ ObjectMeta: metav1.ObjectMeta{ - Name: "default-ingress-passthrough-route", Namespace: namespace, }, } diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go index 67cda892bae..09cd685a5da 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/resources.go @@ -775,9 +775,17 @@ func (r *reconciler) reconcileIngressController(ctx context.Context, hcp *hyperv // Manifests for infra/mgmt cluster passthrough service cpService := manifests.IngressDefaultIngressPassthroughService(hcpNamespace) + cpService.Name = fmt.Sprintf("%s-%s", + manifests.IngressDefaultIngressPassthroughServiceName, + hcp.Spec.Platform.Kubevirt.GenerateID) + // Manifests for infra/mgmt cluster passthrough routes cpPassthroughRoute := manifests.IngressDefaultIngressPassthroughRoute(hcpNamespace) + cpPassthroughRoute.Name = fmt.Sprintf("%s-%s", + manifests.IngressDefaultIngressPassthroughRouteName, + hcp.Spec.Platform.Kubevirt.GenerateID) + if _, err := r.CreateOrUpdate(ctx, r.cpClient, cpService, func() error { return ingress.ReconcileDefaultIngressPassthroughService(cpService, defaultIngressNodePortService, hcp) }); err != nil { diff --git a/docs/content/reference/api.md b/docs/content/reference/api.md index 956c3fddc7b..aa4290d3f5c 100644 --- a/docs/content/reference/api.md +++ b/docs/content/reference/api.md @@ -4944,6 +4944,19 @@ Apps: *.apps.guest.apps.mgmt-cluster.example.com
This is possible using OCP wildcard routes
+generateID
+
+string
+
+GenerateID is used to uniquely apply a name postfix to resources associated with +kubevirt infrastructure resources
+