Skip to content

Commit 52121f2

Browse files
committed
fix: Prefix image repository with Rancher image registry when pulling provider images
1 parent ef284d1 commit 52121f2

File tree

10 files changed

+101
-12
lines changed

10 files changed

+101
-12
lines changed

.github/workflows/test_chart.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ jobs:
8383
kubectl --namespace cattle-system wait --for=create deployments/rancher-webhook --timeout=300s
8484
kubectl --namespace cattle-system wait --for=condition=Available deployment/rancher-webhook --timeout=300s
8585
86+
- name: Set default registry
87+
run: |
88+
kubectl patch setting.management.cattle.io -n cattle-system system-default-registry \
89+
--type merge \
90+
--patch '{"value":"registry.suse.com"}'
91+
8692
- name: Run chart-testing (install)
8793
run: helm install rancher-turtles out/charts/rancher-turtles/ -n rancher-turtles-system --set namespace=rancher-turtles-system --create-namespace --wait --debug
8894

charts/rancher-turtles/templates/deployment.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ spec:
2626
containers:
2727
- args:
2828
- --leader-elect
29-
- --feature-gates=agent-tls-mode={{ index .Values "features" "agent-tls-mode" "enabled"}},ui-plugin={{ index .Values "turtlesUI" "enabled"}},no-cert-manager={{ index .Values "features" "no-cert-manager" "enabled"}}
29+
- --feature-gates=agent-tls-mode={{ index .Values "features" "agent-tls-mode" "enabled"}},ui-plugin={{ index .Values "turtlesUI" "enabled"}},no-cert-manager={{ index .Values "features" "no-cert-manager" "enabled"}},use-rancher-default-registry={{ index .Values "features" "use-rancher-default-registry" "enabled"}}
3030
{{- range .Values.managerArguments }}
3131
- {{ . }}
3232
{{- end }}

charts/rancher-turtles/values.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ features:
3939
no-cert-manager:
4040
# enabled: Turn on or off.
4141
enabled: false
42+
# use-rancher-default-registry: Alpha feature to use Rancher's default registry for provider images.
43+
use-rancher-default-registry:
44+
# enabled: Turn on or off.
45+
enabled: true
4246
# volumes: Volumes for controller pods.
4347
volumes:
4448
- name: clusterctl-config

feature/feature.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,18 @@ const (
3131

3232
// NoCertManager if enabled Turtles will remove cert-manager, including Certificate and Issuer.
3333
NoCertManager featuregate.Feature = "no-cert-manager"
34+
35+
// UseRancherDefaultRegistry if enabled Turtles will use the Rancher default registry for pulling provider images.
36+
UseRancherDefaultRegistry featuregate.Feature = "use-rancher-default-registry"
3437
)
3538

3639
func init() {
3740
utilruntime.Must(MutableGates.Add(defaultGates))
3841
}
3942

4043
var defaultGates = map[featuregate.Feature]featuregate.FeatureSpec{
41-
AgentTLSMode: {Default: true, PreRelease: featuregate.Beta},
42-
UIPlugin: {Default: false, PreRelease: featuregate.Alpha},
43-
NoCertManager: {Default: false, PreRelease: featuregate.Alpha},
44+
AgentTLSMode: {Default: true, PreRelease: featuregate.Beta},
45+
UIPlugin: {Default: false, PreRelease: featuregate.Alpha},
46+
NoCertManager: {Default: false, PreRelease: featuregate.Alpha},
47+
UseRancherDefaultRegistry: {Default: true, PreRelease: featuregate.Alpha},
4448
}

internal/controllers/clusterctl/config.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ import (
3131
"sigs.k8s.io/controller-runtime/pkg/log"
3232
"sigs.k8s.io/yaml"
3333

34+
managementv3 "github.com/rancher/turtles/api/rancher/management/v3"
3435
turtlesv1 "github.com/rancher/turtles/api/v1alpha1"
36+
"github.com/rancher/turtles/feature"
3537
)
3638

3739
var config *corev1.ConfigMap
@@ -146,6 +148,37 @@ func ClusterConfig(ctx context.Context, c client.Client) (*ConfigRepository, err
146148
}
147149
}
148150

151+
if feature.Gates.Enabled(feature.UseRancherDefaultRegistry) {
152+
log.Info("Turtles configured to use Rancher default registry for images")
153+
154+
setting := &managementv3.Setting{}
155+
if err := c.Get(ctx, client.ObjectKey{Name: "system-default-registry"}, setting); err != nil {
156+
log.Error(err, "Unable to get system-default-registry setting")
157+
return nil, err
158+
}
159+
160+
registry := setting.Value
161+
if registry == "" {
162+
log.Info("Rancher default registry is not set, defaulting to DockerHub", "registry", registry)
163+
} else {
164+
log.Info("Rancher default registry has been set", "registry", registry)
165+
}
166+
167+
if registry != "" && !strings.HasSuffix(registry, "/") {
168+
registry += "/"
169+
}
170+
171+
for image, url := range clusterctlConfig.Images {
172+
namespace := extractNamespace(url.Repository)
173+
174+
clusterctlConfig.Images[image] = ConfigImage{
175+
Tag: url.Tag,
176+
Repository: registry + namespace,
177+
}
178+
}
179+
}
180+
181+
// Overwrite images from ClusterctlConfig
149182
for _, image := range config.Spec.Images {
150183
clusterctlConfig.Images[image.Name] = ConfigImage{
151184
Tag: image.Tag,
@@ -156,6 +189,15 @@ func ClusterConfig(ctx context.Context, c client.Client) (*ConfigRepository, err
156189
return clusterctlConfig, nil
157190
}
158191

192+
func extractNamespace(imageURI string) string {
193+
parts := strings.Split(imageURI, "/")
194+
if len(parts) > 1 {
195+
return strings.Join(parts[1:], "/")
196+
}
197+
198+
return imageURI
199+
}
200+
159201
// GetProviderVersion collects version of the collected provider overrides state.
160202
// Returns latest if the version is not found.
161203
func (r *ConfigRepository) GetProviderVersion(ctx context.Context, name, providerType string) (version string, providerKnown bool) {

internal/controllers/clusterctl/config_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
. "github.com/onsi/ginkgo/v2"
2424
. "github.com/onsi/gomega"
2525

26+
managementv3 "github.com/rancher/turtles/api/rancher/management/v3"
2627
"github.com/rancher/turtles/api/v1alpha1"
2728
corev1 "k8s.io/api/core/v1"
2829
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -52,6 +53,9 @@ var _ = Describe("ClusterConfig Tests", func() {
5253
// Register the v1alpha1.ClusterctlConfig type
5354
Expect(v1alpha1.AddToScheme(scheme)).To(Succeed())
5455

56+
// Register the management.Setting type
57+
Expect(managementv3.AddToScheme(scheme)).To(Succeed())
58+
5559
// Override the configDefault variable to provide custom data for the test
5660
configDefault := []byte(`
5761
data:
@@ -111,6 +115,12 @@ data:
111115
},
112116
},
113117
},
118+
&managementv3.Setting{
119+
ObjectMeta: metav1.ObjectMeta{
120+
Name: "system-default-registry",
121+
},
122+
Value: "registry.example.com",
123+
},
114124
).
115125
Build()
116126
})

internal/controllers/clusterctlconfig_controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ func (r *ClusterctlConfigReconciler) SetupWithManager(_ context.Context, mgr ctr
7676
//+kubebuilder:rbac:groups=turtles-capi.cattle.io,resources=clusterctlconfigs/status,verbs=get;list;watch;patch
7777
//+kubebuilder:rbac:groups=turtles-capi.cattle.io,resources=clusterctlconfigs/finalizers,verbs=get;list;watch;patch;update
7878
//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;patch
79+
//+kubebuilder:rbac:groups="management.cattle.io",resources=settings,verbs=get;list;watch
7980

8081
// Reconcile reconciles the ClusterctlConfig object.
8182
func (r *ClusterctlConfigReconciler) Reconcile(ctx context.Context, _ reconcile.Request) (ctrl.Result, error) {

internal/controllers/operator_reconciler_test.go

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
. "github.com/onsi/ginkgo/v2"
2323
. "github.com/onsi/gomega"
24+
managementv3 "github.com/rancher/turtles/api/rancher/management/v3"
2425
turtlesv1 "github.com/rancher/turtles/api/v1alpha1"
2526
"github.com/rancher/turtles/internal/provider"
2627
corev1 "k8s.io/api/core/v1"
@@ -50,6 +51,7 @@ var _ = Describe("Provider sync", func() {
5051
capiProviderAzure *turtlesv1.CAPIProvider
5152
capiProviderGCP *turtlesv1.CAPIProvider
5253
clusterctlconfig *turtlesv1.ClusterctlConfig
54+
setting *managementv3.Setting
5355
)
5456

5557
BeforeEach(func() {
@@ -103,6 +105,13 @@ var _ = Describe("Provider sync", func() {
103105
},
104106
}
105107

108+
setting = &managementv3.Setting{
109+
ObjectMeta: metav1.ObjectMeta{
110+
Name: "system-default-registry",
111+
},
112+
Value: "",
113+
}
114+
106115
os.Setenv("POD_NAMESPACE", ns.Name)
107116
})
108117

@@ -113,7 +122,7 @@ var _ = Describe("Provider sync", func() {
113122
It("Should sync spec down and leave version to latest", func() {
114123
origin := capiProvider.DeepCopy()
115124
origin.Spec.EnableAutomaticUpdate = true
116-
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
125+
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
117126
r := &CAPIProviderReconciler{
118127
Client: fakeClient,
119128
GenericProviderReconciler: controller.GenericProviderReconciler{
@@ -135,7 +144,7 @@ var _ = Describe("Provider sync", func() {
135144

136145
It("Should use unknown provider to clusterctl override with unchanged 'latest' version", func() {
137146
origin := unknownCAPIProvider.DeepCopy()
138-
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
147+
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
139148
r := &CAPIProviderReconciler{
140149
Client: fakeClient,
141150
GenericProviderReconciler: controller.GenericProviderReconciler{
@@ -162,7 +171,7 @@ var _ = Describe("Provider sync", func() {
162171
It("Should reconcile unknown provider to clusterctl override with a specified version unchanged", func() {
163172
origin := unknownCAPIProvider.DeepCopy()
164173
origin.Spec.Version = "v1.0.0"
165-
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
174+
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
166175
r := &CAPIProviderReconciler{
167176
Client: fakeClient,
168177
GenericProviderReconciler: controller.GenericProviderReconciler{
@@ -190,7 +199,7 @@ var _ = Describe("Provider sync", func() {
190199
It("Should set custom provider version to latest according to clusterctlconfig override", func() {
191200
origin := customCAPIProvider.DeepCopy()
192201
origin.Spec.EnableAutomaticUpdate = true
193-
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, clusterctlconfig).Build()
202+
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, clusterctlconfig, setting).Build()
194203
r := &CAPIProviderReconciler{
195204
Client: fakeClient,
196205
GenericProviderReconciler: controller.GenericProviderReconciler{
@@ -218,7 +227,7 @@ var _ = Describe("Provider sync", func() {
218227
It("Should not change custom provider version even if it is in the clusterctlconfig override", func() {
219228
origin := customCAPIProvider.DeepCopy()
220229
origin.Spec.Version = "v1.0.0"
221-
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, clusterctlconfig).Build()
230+
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, clusterctlconfig, setting).Build()
222231
r := &CAPIProviderReconciler{
223232
Client: fakeClient,
224233
GenericProviderReconciler: controller.GenericProviderReconciler{
@@ -243,7 +252,7 @@ var _ = Describe("Provider sync", func() {
243252

244253
It("Should sync azure spec", func() {
245254
origin := capiProviderAzure.DeepCopy()
246-
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
255+
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
247256
r := &CAPIProviderReconciler{
248257
Client: fakeClient,
249258
GenericProviderReconciler: controller.GenericProviderReconciler{
@@ -261,7 +270,7 @@ var _ = Describe("Provider sync", func() {
261270

262271
It("Should sync gcp spec", func() {
263272
origin := capiProviderGCP.DeepCopy()
264-
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
273+
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
265274
r := &CAPIProviderReconciler{
266275
Client: fakeClient,
267276
GenericProviderReconciler: controller.GenericProviderReconciler{
@@ -280,7 +289,7 @@ var _ = Describe("Provider sync", func() {
280289
It("Should sync status up and set provisioning state", func() {
281290
origin := capiProvider.DeepCopy()
282291
origin.Spec.EnableAutomaticUpdate = true
283-
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
292+
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
284293
r := &CAPIProviderReconciler{
285294
Client: fakeClient,
286295
GenericProviderReconciler: controller.GenericProviderReconciler{

internal/controllers/sync_controller_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121

2222
. "github.com/onsi/ginkgo/v2"
2323
. "github.com/onsi/gomega"
24+
managementv3 "github.com/rancher/turtles/api/rancher/management/v3"
2425
turtlesv1 "github.com/rancher/turtles/api/v1alpha1"
2526
"github.com/rancher/turtles/internal/sync"
2627
corev1 "k8s.io/api/core/v1"
@@ -71,10 +72,21 @@ var _ = Describe("Reconcile CAPIProvider", Ordered, func() {
7172

7273
ns, err = testEnv.CreateNamespace(ctx, "capiprovider")
7374
Expect(err).ToNot(HaveOccurred())
75+
testEnv.Create(ctx, &managementv3.Setting{
76+
ObjectMeta: metav1.ObjectMeta{
77+
Name: "system-default-registry",
78+
},
79+
Value: "",
80+
})
7481
})
7582

7683
AfterEach(func() {
7784
Expect(testEnv.Delete(ctx, ns)).Should(Succeed())
85+
Expect(testEnv.Delete(ctx, &managementv3.Setting{
86+
ObjectMeta: metav1.ObjectMeta{
87+
Name: "system-default-registry",
88+
},
89+
})).Should(Succeed())
7890
})
7991

8092
It("Should create CAPIProvider secret", func() {

tilt/project/Tiltfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ def update_manager(yaml, containerName, debug, env, name, project):
149149
debugArgs.append(arg)
150150
if debug_verbose:
151151
debugArgs.append("--v=5")
152+
debugArgs.append("--feature-gates=agent-tls-mode=true,no-cert-manager=false,use-rancher-default-registry=true")
152153
c["command"] = cmd
153154
print(cmd)
154155
if len(debugArgs) == 0:

0 commit comments

Comments
 (0)