From bbb62855f156159730b5b2228379fddc5ede3287 Mon Sep 17 00:00:00 2001 From: Kyle Squizzato Date: Wed, 28 Aug 2024 14:08:10 -0700 Subject: [PATCH 1/3] Add defaultRegistryURL and defaultRepoType for non-oci HelmRepository This patch renames the existing 'defaultOCIRegistry' flag and associated Helm values to 'defaultRegistryURL' and introduces a new type: 'defaultRepoType' which allows for modification of the previously hardcoded 'oci' type for chart repositories. Signed-off-by: Kyle Squizzato --- cmd/main.go | 38 +++++++++++++--------- internal/controller/release_controller.go | 10 ++++-- internal/controller/template_controller.go | 4 +-- templates/hmc/templates/deployment.yaml | 3 +- templates/hmc/values.yaml | 3 +- 5 files changed, 34 insertions(+), 24 deletions(-) diff --git a/cmd/main.go b/cmd/main.go index 7bdab0a6a..314f6f8b9 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -56,20 +56,23 @@ func init() { } func main() { - var metricsAddr string - var probeAddr string - var secureMetrics bool - var enableHTTP2 bool - var defaultOCIRegistry string - var insecureRegistry bool - var registryCredentialsSecret string - var createManagement bool - var createTemplates bool - var hmcTemplatesChartName string - var enableTelemetry bool - var enableWebhook bool - var webhookPort int - var webhookCertDir string + var ( + metricsAddr string + probeAddr string + secureMetrics bool + enableHTTP2 bool + defaultRegistryURL string + defaultRepoType string + insecureRegistry bool + registryCredentialsSecret string + createManagement bool + createTemplates bool + hmcTemplatesChartName string + enableTelemetry bool + enableWebhook bool + webhookPort int + webhookCertDir string + ) flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") @@ -77,8 +80,10 @@ func main() { "If set the metrics endpoint is served securely") flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers") - flag.StringVar(&defaultOCIRegistry, "default-oci-registry", "oci://ghcr.io/mirantis/hmc/charts", + flag.StringVar(&defaultRegistryURL, "default-registry-url", "oci://ghcr.io/mirantis/hmc/charts", "The default OCI registry to download Helm charts from.") + flag.StringVar(&defaultRepoType, "default-repo-type", "oci", + "The default repository type to download Helm charts from specify 'default' for http/https or 'oci' for oci.") flag.StringVar(®istryCredentialsSecret, "registry-creds-secret", "", "Secret containing authentication credentials for the registry.") flag.BoolVar(&insecureRegistry, "insecure-registry", false, "Allow connecting to an HTTP registry.") @@ -180,7 +185,8 @@ func main() { Config: mgr.GetConfig(), CreateManagement: createManagement, CreateTemplates: createTemplates, - DefaultOCIRegistry: defaultOCIRegistry, + DefaultRegistryURL: defaultRegistryURL, + DefaultRepoType: defaultRepoType, RegistryCredentialsSecret: registryCredentialsSecret, InsecureRegistry: insecureRegistry, HMCTemplatesChartName: hmcTemplatesChartName, diff --git a/internal/controller/release_controller.go b/internal/controller/release_controller.go index db819ffa3..2324b89f3 100644 --- a/internal/controller/release_controller.go +++ b/internal/controller/release_controller.go @@ -57,7 +57,11 @@ type Poller struct { CreateManagement bool CreateTemplates bool - DefaultOCIRegistry string + // DefaultRepoType is the type specified by default in HelmRepository + // objects. Valid types are 'default' for http/https repositories, and + // 'oci' for OCI repositories. + DefaultRepoType string + DefaultRegistryURL string RegistryCredentialsSecret string InsecureRegistry bool HMCTemplatesChartName string @@ -183,8 +187,8 @@ func (p *Poller) reconcileDefaultHelmRepo(ctx context.Context) error { } helmRepo.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue helmRepo.Spec = sourcev1.HelmRepositorySpec{ - Type: defaultRepoType, - URL: p.DefaultOCIRegistry, + Type: p.DefaultRepoType, + URL: p.DefaultRegistryURL, Interval: metav1.Duration{Duration: defaultReconcileInterval}, Insecure: p.InsecureRegistry, } diff --git a/internal/controller/template_controller.go b/internal/controller/template_controller.go index 0fe5ca869..eb0ffe0c4 100644 --- a/internal/controller/template_controller.go +++ b/internal/controller/template_controller.go @@ -39,9 +39,7 @@ import ( ) const ( - defaultRepoName = "hmc-templates" - defaultRepoType = "oci" - + defaultRepoName = "hmc-templates" defaultReconcileInterval = 10 * time.Minute ) diff --git a/templates/hmc/templates/deployment.yaml b/templates/hmc/templates/deployment.yaml index 028835a1a..67468df60 100644 --- a/templates/hmc/templates/deployment.yaml +++ b/templates/hmc/templates/deployment.yaml @@ -21,7 +21,8 @@ spec: spec: containers: - args: - - --default-oci-registry={{ .Values.controller.defaultOCIRegistry }} + - --default-registry-url={{ .Values.controller.defaultRegistryURL }} + - --default-repo-type={{ .Values.controller.defaultRepoType}} - --insecure-registry={{ .Values.controller.insecureRegistry }} {{- if .Values.controller.registryCredsSecret }} - --registry-creds-secret={{ .Values.controller.registryCredsSecret }} diff --git a/templates/hmc/values.yaml b/templates/hmc/values.yaml index a0ee6dac7..1c01884fe 100644 --- a/templates/hmc/values.yaml +++ b/templates/hmc/values.yaml @@ -7,7 +7,8 @@ admissionWebhook: certDir: "/tmp/k8s-webhook-server/serving-certs/" controller: - defaultOCIRegistry: "oci://ghcr.io/mirantis/hmc/charts" + defaultRegistryURL: "oci://ghcr.io/mirantis/hmc/charts" + defaultRepoType: "oci" registryCredsSecret: "" insecureRegistry: false createManagement: true From 8265662328286dd5583a3023e357fe7b520df0fa Mon Sep 17 00:00:00 2001 From: Kyle Squizzato Date: Tue, 3 Sep 2024 08:59:02 -0700 Subject: [PATCH 2/3] Update flag description Signed-off-by: Kyle Squizzato --- cmd/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/main.go b/cmd/main.go index 314f6f8b9..426090ed1 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -81,7 +81,7 @@ func main() { flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers") flag.StringVar(&defaultRegistryURL, "default-registry-url", "oci://ghcr.io/mirantis/hmc/charts", - "The default OCI registry to download Helm charts from.") + "The default registry to download Helm charts from.") flag.StringVar(&defaultRepoType, "default-repo-type", "oci", "The default repository type to download Helm charts from specify 'default' for http/https or 'oci' for oci.") flag.StringVar(®istryCredentialsSecret, "registry-creds-secret", "", From 9769233aa8f5c1e586fa45c638f3f423510cedea Mon Sep 17 00:00:00 2001 From: Kyle Squizzato Date: Tue, 3 Sep 2024 13:29:06 -0700 Subject: [PATCH 3/3] Determine DefaultRepoType based on URL scheme Signed-off-by: Kyle Squizzato --- cmd/main.go | 15 +++++--- config/dev/hmc_values.yaml | 2 +- internal/controller/release_controller.go | 4 +- internal/utils/helm.go | 41 ++++++++++++++++++++ internal/utils/helm_test.go | 47 +++++++++++++++++++++++ templates/hmc/templates/deployment.yaml | 1 - 6 files changed, 102 insertions(+), 8 deletions(-) create mode 100644 internal/utils/helm.go create mode 100644 internal/utils/helm_test.go diff --git a/cmd/main.go b/cmd/main.go index 426090ed1..125e6d60f 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -21,6 +21,7 @@ import ( // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) // to ensure that exec-entrypoint and run can make use of them. + _ "k8s.io/client-go/plugin/pkg/client/auth" hcv2 "github.com/fluxcd/helm-controller/api/v2" @@ -37,6 +38,7 @@ import ( hmcmirantiscomv1alpha1 "github.com/Mirantis/hmc/api/v1alpha1" "github.com/Mirantis/hmc/internal/controller" "github.com/Mirantis/hmc/internal/telemetry" + "github.com/Mirantis/hmc/internal/utils" hmcwebhook "github.com/Mirantis/hmc/internal/webhook" //+kubebuilder:scaffold:imports ) @@ -62,7 +64,6 @@ func main() { secureMetrics bool enableHTTP2 bool defaultRegistryURL string - defaultRepoType string insecureRegistry bool registryCredentialsSecret string createManagement bool @@ -81,9 +82,7 @@ func main() { flag.BoolVar(&enableHTTP2, "enable-http2", false, "If set, HTTP/2 will be enabled for the metrics and webhook servers") flag.StringVar(&defaultRegistryURL, "default-registry-url", "oci://ghcr.io/mirantis/hmc/charts", - "The default registry to download Helm charts from.") - flag.StringVar(&defaultRepoType, "default-repo-type", "oci", - "The default repository type to download Helm charts from specify 'default' for http/https or 'oci' for oci.") + "The default registry to download Helm charts from, prefix with oci:// for OCI registries.") flag.StringVar(®istryCredentialsSecret, "registry-creds-secret", "", "Secret containing authentication credentials for the registry.") flag.BoolVar(&insecureRegistry, "insecure-registry", false, "Allow connecting to an HTTP registry.") @@ -104,6 +103,12 @@ func main() { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + determinedRepositoryType, err := utils.DetermineDefaultRepositoryType(defaultRegistryURL) + if err != nil { + setupLog.Error(err, "failed to determine default repository type") + os.Exit(1) + } + // if the enable-http2 flag is false (the default), http/2 should be disabled // due to its vulnerabilities. More specifically, disabling http/2 will // prevent from being vulnerable to the HTTP/2 Stream Cancellation and @@ -186,7 +191,7 @@ func main() { CreateManagement: createManagement, CreateTemplates: createTemplates, DefaultRegistryURL: defaultRegistryURL, - DefaultRepoType: defaultRepoType, + DefaultRepoType: determinedRepositoryType, RegistryCredentialsSecret: registryCredentialsSecret, InsecureRegistry: insecureRegistry, HMCTemplatesChartName: hmcTemplatesChartName, diff --git a/config/dev/hmc_values.yaml b/config/dev/hmc_values.yaml index cf79fffa1..e81bfc3dc 100644 --- a/config/dev/hmc_values.yaml +++ b/config/dev/hmc_values.yaml @@ -1,6 +1,6 @@ image: repository: hmc/controller controller: - defaultOCIRegistry: oci://hmc-local-registry:5000/charts + defaultRegistryURL: oci://hmc-local-registry:5000/charts insecureRegistry: true createTemplates: false diff --git a/internal/controller/release_controller.go b/internal/controller/release_controller.go index 2324b89f3..bf26d848b 100644 --- a/internal/controller/release_controller.go +++ b/internal/controller/release_controller.go @@ -59,7 +59,8 @@ type Poller struct { // DefaultRepoType is the type specified by default in HelmRepository // objects. Valid types are 'default' for http/https repositories, and - // 'oci' for OCI repositories. + // 'oci' for OCI repositories. The RepositoryType is set in main based on + // the URI scheme of the DefaultRegistryURL. DefaultRepoType string DefaultRegistryURL string RegistryCredentialsSecret string @@ -185,6 +186,7 @@ func (p *Poller) reconcileDefaultHelmRepo(ctx context.Context) error { if helmRepo.Labels == nil { helmRepo.Labels = make(map[string]string) } + helmRepo.Labels[hmc.HMCManagedLabelKey] = hmc.HMCManagedLabelValue helmRepo.Spec = sourcev1.HelmRepositorySpec{ Type: p.DefaultRepoType, diff --git a/internal/utils/helm.go b/internal/utils/helm.go new file mode 100644 index 000000000..6ed9bfa56 --- /dev/null +++ b/internal/utils/helm.go @@ -0,0 +1,41 @@ +// Copyright 2024 +// +// 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 utils + +import ( + "fmt" + "net/url" +) + +const ( + registryTypeOCI = "oci" + registryTypeDefault = "default" +) + +func DetermineDefaultRepositoryType(defaultRegistryURL string) (string, error) { + parsedRegistryURL, err := url.Parse(defaultRegistryURL) + if err != nil { + return "", fmt.Errorf("failed to parse default registry URL: %w", err) + } + + switch parsedRegistryURL.Scheme { + case "oci": + return registryTypeOCI, nil + case "http", "https": + return registryTypeDefault, nil + default: + return "", fmt.Errorf("invalid default registry URL scheme: %s must be 'oci://', 'http://', or 'https://'", parsedRegistryURL.Scheme) + } +} diff --git a/internal/utils/helm_test.go b/internal/utils/helm_test.go new file mode 100644 index 000000000..027dbdeab --- /dev/null +++ b/internal/utils/helm_test.go @@ -0,0 +1,47 @@ +// Copyright 2024 +// +// 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 utils + +import ( + "testing" +) + +func TestDetermineDefaultRepositoryType(t *testing.T) { + for _, tc := range []struct { + url string + expectErr bool + expectedScheme string + }{ + {url: "oci://hmc-local-registry:5000/charts", expectErr: false, expectedScheme: "oci"}, + {url: "https://registry.example.com", expectErr: false, expectedScheme: "default"}, + {url: "http://docker.io", expectErr: false, expectedScheme: "default"}, + {url: "ftp://ftp.example.com", expectErr: true}, + {url: "not-a-url", expectErr: true}, + } { + t.Run(tc.url, func(t *testing.T) { + actual, err := DetermineDefaultRepositoryType(tc.url) + if tc.expectErr && err == nil { + t.Errorf("expected error, got nil") + } + if !tc.expectErr && err != nil { + t.Errorf("unexpected error: %v", err) + + if actual != tc.expectedScheme { + t.Errorf("expected scheme %q, got %q", tc.expectedScheme, actual) + } + } + }) + } +} diff --git a/templates/hmc/templates/deployment.yaml b/templates/hmc/templates/deployment.yaml index 67468df60..925c9d491 100644 --- a/templates/hmc/templates/deployment.yaml +++ b/templates/hmc/templates/deployment.yaml @@ -22,7 +22,6 @@ spec: containers: - args: - --default-registry-url={{ .Values.controller.defaultRegistryURL }} - - --default-repo-type={{ .Values.controller.defaultRepoType}} - --insecure-registry={{ .Values.controller.insecureRegistry }} {{- if .Values.controller.registryCredsSecret }} - --registry-creds-secret={{ .Values.controller.registryCredsSecret }}