diff --git a/pkg/infrastructure/cluster.go b/pkg/infrastructure/cluster.go index 702d6e1ab..82e86c510 100644 --- a/pkg/infrastructure/cluster.go +++ b/pkg/infrastructure/cluster.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2019-2025 Red Hat, Inc. +// Copyright (c) 2019-2026 Red Hat, Inc. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -35,8 +35,9 @@ const ( var ( // current is the infrastructure that we're currently running on. - current Type - initialized = false + current Type + certManagerDetected bool + initialized = false ) // Initialize attempts to determine the type of cluster its currently running on (OpenShift or Kubernetes). This function @@ -57,6 +58,14 @@ func Initialize() error { // InitializeForTesting is used to mock running on a specific type of cluster (Kubernetes, OpenShift) in testing code. func InitializeForTesting(currentInfrastructure Type) { current = currentInfrastructure + certManagerDetected = false + initialized = true +} + +// InitializeForTestingWithCertManager is used to mock running on a cluster with cert-manager installed. +func InitializeForTestingWithCertManager(currentInfrastructure Type) { + current = currentInfrastructure + certManagerDetected = true initialized = true } @@ -72,6 +81,14 @@ func IsOpenShift() bool { return current == OpenShiftv4 } +// CertManagerDetected returns true if the cert-manager API group was detected on the cluster. +func CertManagerDetected() bool { + if !initialized { + panic("Attempting to determine information about the cluster without initializing first") + } + return certManagerDetected +} + func detect() (Type, error) { kubeCfg, err := config.GetConfig() if err != nil { @@ -85,6 +102,7 @@ func detect() (Type, error) { if err != nil { return Unsupported, fmt.Errorf("could not read API groups: %w", err) } + certManagerDetected = findAPIGroup(apiList.Groups, "cert-manager.io") != nil if findAPIGroup(apiList.Groups, "route.openshift.io") == nil { return Kubernetes, nil } else { diff --git a/webhook/workspace/annotations.go b/webhook/workspace/annotations.go new file mode 100644 index 000000000..9495b6fe6 --- /dev/null +++ b/webhook/workspace/annotations.go @@ -0,0 +1,32 @@ +// +// Copyright (c) 2019-2026 Red Hat, Inc. +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +package workspace + +import ( + "fmt" + + "github.com/devfile/devworkspace-operator/pkg/infrastructure" +) + +func getWebhookAnnotations(namespace string) map[string]string { + annotations := map[string]string{} + if infrastructure.CertManagerDetected() { + annotations["cert-manager.io/inject-ca-from"] = fmt.Sprintf("%s/devworkspace-controller-serving-cert", namespace) + } else if infrastructure.IsOpenShift() { + annotations["service.beta.openshift.io/inject-cabundle"] = "true" + } + return annotations +} diff --git a/webhook/workspace/mutating_cfg.go b/webhook/workspace/mutating_cfg.go index c7433c8c4..6a6e6d143 100644 --- a/webhook/workspace/mutating_cfg.go +++ b/webhook/workspace/mutating_cfg.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2019-2025 Red Hat, Inc. +// Copyright (c) 2019-2026 Red Hat, Inc. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -153,8 +153,9 @@ func BuildMutateWebhookCfg(namespace string) *admregv1.MutatingWebhookConfigurat return &admregv1.MutatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{ - Name: MutateWebhookCfgName, - Labels: server.WebhookServerAppLabels(), + Name: MutateWebhookCfgName, + Labels: server.WebhookServerAppLabels(), + Annotations: getWebhookAnnotations(namespace), }, Webhooks: []admregv1.MutatingWebhook{ workspaceMutateWebhook, diff --git a/webhook/workspace/validating_cfg.go b/webhook/workspace/validating_cfg.go index 86c22f15b..4c95cad7c 100644 --- a/webhook/workspace/validating_cfg.go +++ b/webhook/workspace/validating_cfg.go @@ -1,5 +1,5 @@ // -// Copyright (c) 2019-2025 Red Hat, Inc. +// Copyright (c) 2019-2026 Red Hat, Inc. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at @@ -34,8 +34,9 @@ func buildValidatingWebhookCfg(namespace string) *admregv1.ValidatingWebhookConf sideEffectsNone := admregv1.SideEffectClassNone return &admregv1.ValidatingWebhookConfiguration{ ObjectMeta: metav1.ObjectMeta{ - Name: ValidateWebhookCfgName, - Labels: server.WebhookServerAppLabels(), + Name: ValidateWebhookCfgName, + Labels: server.WebhookServerAppLabels(), + Annotations: getWebhookAnnotations(namespace), }, Webhooks: []admregv1.ValidatingWebhook{ {