Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions .github/workflows/test_chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ jobs:
kubectl --namespace cattle-system wait --for=create deployments/rancher-webhook --timeout=300s
kubectl --namespace cattle-system wait --for=condition=Available deployment/rancher-webhook --timeout=300s

- name: Set default registry
run: |
kubectl patch setting.management.cattle.io -n cattle-system system-default-registry \
--type merge \
--patch '{"value":"registry.suse.com"}'

- name: Run chart-testing (install)
run: helm install rancher-turtles out/charts/rancher-turtles/ -n rancher-turtles-system --set namespace=rancher-turtles-system --create-namespace --wait --debug

Expand Down Expand Up @@ -166,7 +172,7 @@ jobs:
- name: Check capi-controller-manager image is from kubernetes-sigs (community)
run: |
IMAGE=$(kubectl get deployment capi-controller-manager -n cattle-capi-system -o jsonpath='{.spec.template.spec.containers[0].image}')
if [[ "$IMAGE" != registry.k8s.io/cluster-api/cluster-api-controller* ]]; then
echo "capi-controller-manager does not use registry.k8s.io/cluster-api/cluster-api-controller based image"
if [[ "$IMAGE" != rancher/cluster-api-controller* ]]; then
echo "capi-controller-manager does not use rancher/cluster-api-controller based image"
exit 1
fi
2 changes: 1 addition & 1 deletion charts/rancher-turtles/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ spec:
containers:
- args:
- --leader-elect
- --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"}}
- --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"}}
{{- range .Values.managerArguments }}
- {{ . }}
{{- end }}
Expand Down
4 changes: 4 additions & 0 deletions charts/rancher-turtles/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ features:
no-cert-manager:
# enabled: Turn on or off.
enabled: false
# use-rancher-default-registry: Alpha feature to use Rancher's default registry for provider images.
use-rancher-default-registry:
# enabled: Turn on or off.
enabled: true
# volumes: Volumes for controller pods.
volumes:
- name: clusterctl-config
Expand Down
10 changes: 7 additions & 3 deletions feature/feature.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,18 @@ const (

// NoCertManager if enabled Turtles will remove cert-manager, including Certificate and Issuer.
NoCertManager featuregate.Feature = "no-cert-manager"

// UseRancherDefaultRegistry if enabled Turtles will use the Rancher default registry for pulling provider images.
UseRancherDefaultRegistry featuregate.Feature = "use-rancher-default-registry"
)

func init() {
utilruntime.Must(MutableGates.Add(defaultGates))
}

var defaultGates = map[featuregate.Feature]featuregate.FeatureSpec{
AgentTLSMode: {Default: true, PreRelease: featuregate.Beta},
UIPlugin: {Default: false, PreRelease: featuregate.Alpha},
NoCertManager: {Default: false, PreRelease: featuregate.Alpha},
AgentTLSMode: {Default: true, PreRelease: featuregate.Beta},
UIPlugin: {Default: false, PreRelease: featuregate.Alpha},
NoCertManager: {Default: false, PreRelease: featuregate.Alpha},
UseRancherDefaultRegistry: {Default: true, PreRelease: featuregate.Alpha},
}
2 changes: 1 addition & 1 deletion internal/controllers/clusterctl/config-community.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ data:
type: "CoreProvider"
images:
cluster-api:
repository: "registry.k8s.io/cluster-api"
repository: "rancher"
2 changes: 1 addition & 1 deletion internal/controllers/clusterctl/config-prime.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,5 +68,5 @@ data:
repository: "registry.suse.com/rancher"
infrastructure-vsphere:
repository: "registry.suse.com/rancher"
addon-fleet:
addon-rancher-fleet:
repository: "registry.suse.com/rancher"
46 changes: 46 additions & 0 deletions internal/controllers/clusterctl/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/yaml"

managementv3 "github.com/rancher/turtles/api/rancher/management/v3"
turtlesv1 "github.com/rancher/turtles/api/v1alpha1"
"github.com/rancher/turtles/feature"
)

var config *corev1.ConfigMap
Expand Down Expand Up @@ -146,16 +148,60 @@ func ClusterConfig(ctx context.Context, c client.Client) (*ConfigRepository, err
}
}

if feature.Gates.Enabled(feature.UseRancherDefaultRegistry) {
log.Info("Turtles configured to use Rancher default registry for images")

setting := &managementv3.Setting{}
if err := c.Get(ctx, client.ObjectKey{Name: "system-default-registry"}, setting); err != nil {
log.Error(err, "Unable to get system-default-registry setting")
return nil, err
}

registry := setting.Value
if registry != "" {
log.Info("Rancher default registry has been set", "registry", registry)

if !strings.HasSuffix(registry, "/") {
registry += "/"
}

// Iterate through all images for the supported providers and override
// the repository to use Rancher's system default registry
for image, url := range clusterctlConfig.Images {
namespace := extractNamespace(url.Repository)

clusterctlConfig.Images[image] = ConfigImage{
Tag: url.Tag,
Repository: registry + namespace,
}
log.Info("Overridden provider image to use Rancher default registry", "image", image,
"repository", clusterctlConfig.Images[image].Repository, "tag", url.Tag)
}
}
}

// Override images from ClusterctlConfig
for _, image := range config.Spec.Images {
clusterctlConfig.Images[image.Name] = ConfigImage{
Tag: image.Tag,
Repository: image.Repository,
}

log.Info("Overridden provider image from ClusterctlConfig", "image", image.Name, "repository", image.Repository, "tag", image.Tag)
}

return clusterctlConfig, nil
}

func extractNamespace(imageURI string) string {
parts := strings.Split(imageURI, "/")
if len(parts) > 1 {
return strings.Join(parts[1:], "/")
}

return imageURI
}

// GetProviderVersion collects version of the collected provider overrides state.
// Returns latest if the version is not found.
func (r *ConfigRepository) GetProviderVersion(ctx context.Context, name, providerType string) (version string, providerKnown bool) {
Expand Down
10 changes: 10 additions & 0 deletions internal/controllers/clusterctl/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

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

// Register the management.Setting type
Expect(managementv3.AddToScheme(scheme)).To(Succeed())

// Override the configDefault variable to provide custom data for the test
configDefault := []byte(`
data:
Expand Down Expand Up @@ -111,6 +115,12 @@ data:
},
},
},
&managementv3.Setting{
ObjectMeta: metav1.ObjectMeta{
Name: "system-default-registry",
},
Value: "registry.example.com",
},
).
Build()
})
Expand Down
1 change: 1 addition & 0 deletions internal/controllers/clusterctlconfig_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ func (r *ClusterctlConfigReconciler) SetupWithManager(_ context.Context, mgr ctr
//+kubebuilder:rbac:groups=turtles-capi.cattle.io,resources=clusterctlconfigs/status,verbs=get;list;watch;patch
//+kubebuilder:rbac:groups=turtles-capi.cattle.io,resources=clusterctlconfigs/finalizers,verbs=get;list;watch;patch;update
//+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;patch
//+kubebuilder:rbac:groups="management.cattle.io",resources=settings,verbs=get;list;watch

// Reconcile reconciles the ClusterctlConfig object.
func (r *ClusterctlConfigReconciler) Reconcile(ctx context.Context, _ reconcile.Request) (ctrl.Result, error) {
Expand Down
25 changes: 17 additions & 8 deletions internal/controllers/operator_reconciler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
managementv3 "github.com/rancher/turtles/api/rancher/management/v3"
turtlesv1 "github.com/rancher/turtles/api/v1alpha1"
"github.com/rancher/turtles/internal/provider"
corev1 "k8s.io/api/core/v1"
Expand Down Expand Up @@ -50,6 +51,7 @@ var _ = Describe("Provider sync", func() {
capiProviderAzure *turtlesv1.CAPIProvider
capiProviderGCP *turtlesv1.CAPIProvider
clusterctlconfig *turtlesv1.ClusterctlConfig
setting *managementv3.Setting
)

BeforeEach(func() {
Expand Down Expand Up @@ -103,6 +105,13 @@ var _ = Describe("Provider sync", func() {
},
}

setting = &managementv3.Setting{
ObjectMeta: metav1.ObjectMeta{
Name: "system-default-registry",
},
Value: "",
}

os.Setenv("POD_NAMESPACE", ns.Name)
})

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

It("Should use unknown provider to clusterctl override with unchanged 'latest' version", func() {
origin := unknownCAPIProvider.DeepCopy()
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
r := &CAPIProviderReconciler{
Client: fakeClient,
GenericProviderReconciler: controller.GenericProviderReconciler{
Expand All @@ -162,7 +171,7 @@ var _ = Describe("Provider sync", func() {
It("Should reconcile unknown provider to clusterctl override with a specified version unchanged", func() {
origin := unknownCAPIProvider.DeepCopy()
origin.Spec.Version = "v1.0.0"
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
r := &CAPIProviderReconciler{
Client: fakeClient,
GenericProviderReconciler: controller.GenericProviderReconciler{
Expand Down Expand Up @@ -190,7 +199,7 @@ var _ = Describe("Provider sync", func() {
It("Should set custom provider version to latest according to clusterctlconfig override", func() {
origin := customCAPIProvider.DeepCopy()
origin.Spec.EnableAutomaticUpdate = true
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, clusterctlconfig).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, clusterctlconfig, setting).Build()
r := &CAPIProviderReconciler{
Client: fakeClient,
GenericProviderReconciler: controller.GenericProviderReconciler{
Expand Down Expand Up @@ -218,7 +227,7 @@ var _ = Describe("Provider sync", func() {
It("Should not change custom provider version even if it is in the clusterctlconfig override", func() {
origin := customCAPIProvider.DeepCopy()
origin.Spec.Version = "v1.0.0"
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, clusterctlconfig).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, clusterctlconfig, setting).Build()
r := &CAPIProviderReconciler{
Client: fakeClient,
GenericProviderReconciler: controller.GenericProviderReconciler{
Expand All @@ -243,7 +252,7 @@ var _ = Describe("Provider sync", func() {

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

It("Should sync gcp spec", func() {
origin := capiProviderGCP.DeepCopy()
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
r := &CAPIProviderReconciler{
Client: fakeClient,
GenericProviderReconciler: controller.GenericProviderReconciler{
Expand All @@ -280,7 +289,7 @@ var _ = Describe("Provider sync", func() {
It("Should sync status up and set provisioning state", func() {
origin := capiProvider.DeepCopy()
origin.Spec.EnableAutomaticUpdate = true
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin).Build()
fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(origin, setting).Build()
r := &CAPIProviderReconciler{
Client: fakeClient,
GenericProviderReconciler: controller.GenericProviderReconciler{
Expand Down
12 changes: 12 additions & 0 deletions internal/controllers/sync_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

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

ns, err = testEnv.CreateNamespace(ctx, "capiprovider")
Expect(err).ToNot(HaveOccurred())
testEnv.Create(ctx, &managementv3.Setting{
ObjectMeta: metav1.ObjectMeta{
Name: "system-default-registry",
},
Value: "",
})
})

AfterEach(func() {
Expect(testEnv.Delete(ctx, ns)).Should(Succeed())
Expect(testEnv.Delete(ctx, &managementv3.Setting{
ObjectMeta: metav1.ObjectMeta{
Name: "system-default-registry",
},
})).Should(Succeed())
})

It("Should create CAPIProvider secret", func() {
Expand Down
4 changes: 4 additions & 0 deletions test/e2e/data/capi-operator/clusterctlconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ spec:
images:
- name: infrastructure-docker
repository: "gcr.io/k8s-staging-cluster-api"
- name: infrastructure-aws
repository: "registry.k8s.io/cluster-api-aws"
- name: infrastructure-gcp
repository: "registry.k8s.io/cluster-api-gcp"
1 change: 1 addition & 0 deletions tilt/project/Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ def update_manager(yaml, containerName, debug, env, name, project):
debugArgs.append(arg)
if debug_verbose:
debugArgs.append("--v=5")
debugArgs.append("--feature-gates=agent-tls-mode=true,no-cert-manager=false,use-rancher-default-registry=true")
c["command"] = cmd
print(cmd)
if len(debugArgs) == 0:
Expand Down