Skip to content

Commit 1891366

Browse files
authored
Merge pull request #469 from gianlucam76/namespace
(feat) allow configurable namespace for Sveltos
2 parents 5191ca6 + 1fbee01 commit 1891366

29 files changed

Lines changed: 318 additions & 122 deletions

.github/workflows/main.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,18 @@ jobs:
9292
go-version: 1.26.3
9393
- name: fv-pullmode
9494
run: make create-cluster-pullmode fv-pullmode
95+
env:
96+
FV: true
97+
FV-NAMESPACE:
98+
runs-on: ubuntu-latest
99+
steps:
100+
- name: checkout
101+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
102+
- name: Set up Go
103+
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
104+
with:
105+
go-version: 1.26.3
106+
- name: fv
107+
run: make create-cluster-infra fv-namespace
95108
env:
96109
FV: true

Makefile

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ ARCH ?= $(shell go env GOARCH)
4545
OS ?= $(shell uname -s | tr A-Z a-z)
4646
K8S_LATEST_VER ?= $(shell curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)
4747
export CONTROLLER_IMG ?= $(REGISTRY)/$(IMAGE_NAME)
48-
TAG ?= v1.10.0
48+
TAG ?= main
4949

5050
## Tool Binaries
5151
CONTROLLER_GEN := $(TOOLS_BIN_DIR)/controller-gen
@@ -186,6 +186,9 @@ NUM_NODES ?= 5
186186
.PHONY: kind-test
187187
kind-test: test create-cluster fv ## Build docker image; start kind cluster; load docker image; install all cluster api components and run fv
188188

189+
.PHONY: kind-test-namespace
190+
kind-test-namespace: test create-cluster-infra fv-namespace ## Build docker image; start kind cluster; deploy Sveltos in a random namespace and run fv
191+
189192
.PHONY: fv
190193
fv: $(GINKGO) ## Run Sveltos Controller tests using existing cluster
191194
cd test/fv; $(GINKGO) -nodes $(NUM_NODES) --label-filter='FV' --v --trace --randomize-all
@@ -212,13 +215,44 @@ fv-agentless: $(KUBECTL) $(GINKGO) ## Run Sveltos Controller tests using existin
212215
fv-pullmode: $(GINKGO) ## Run Sveltos Controller tests using existing cluster
213216
cd test/fv; $(GINKGO) -nodes $(NUM_NODES) --label-filter='PULLMODE' --v --trace --randomize-all
214217

218+
.PHONY: deploy-crds
219+
deploy-crds: $(KUBECTL) ## Install all required Sveltos CRDs
220+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_debuggingconfigurations.lib.projectsveltos.io.yaml
221+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_classifiers.lib.projectsveltos.io.yaml
222+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_classifierreports.lib.projectsveltos.io.yaml
223+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_accessrequests.lib.projectsveltos.io.yaml
224+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_rolerequests.lib.projectsveltos.io.yaml
225+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_sveltosclusters.lib.projectsveltos.io.yaml
226+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_configurationgroups.lib.projectsveltos.io.yaml
227+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_configurationbundles.lib.projectsveltos.io.yaml
228+
229+
.PHONY: fv-namespace
230+
fv-namespace: $(GINKGO) $(KUBECTL) $(KUSTOMIZE) $(ENVSUBST) ## Run FV tests with Sveltos deployed in a random namespace
231+
$(MAKE) load-image
232+
$(MAKE) deploy-crds
233+
234+
@echo "Deploying access manager"
235+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/access-manager/$(TAG)/manifest/manifest.yaml
236+
@echo "wait for cluster to be provisioned"
237+
$(KUBECTL) wait cluster $(WORKLOAD_CLUSTER_NAME) -n default --for=jsonpath='{.status.phase}'=Provisioned --timeout=$(TIMEOUT)
238+
239+
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
240+
SVELTOS_NS="sveltos-$$(openssl rand -hex 4)"; \
241+
echo "Deploying Sveltos classifier in namespace: $$SVELTOS_NS"; \
242+
$(KUSTOMIZE) build config/default | $(ENVSUBST) | \
243+
sed -E 's/^([[:space:]]+)(name|namespace): projectsveltos$$/\1\2: '"$$SVELTOS_NS"'/' | \
244+
$(KUBECTL) apply -f-; \
245+
echo "Waiting for classifier-manager to be available in namespace $$SVELTOS_NS..."; \
246+
$(KUBECTL) wait --for=condition=Available deployment/classifier-manager -n "$$SVELTOS_NS" --timeout=$(TIMEOUT); \
247+
cd test/fv && SVELTOS_NAMESPACE="$$SVELTOS_NS" $(GINKGO) -nodes $(NUM_NODES) --label-filter='FV' --v --trace --randomize-all
248+
215249

216250
.PHONY: test
217251
test: manifests generate fmt vet $(SETUP_ENVTEST) ## Run uts.
218252
KUBEBUILDER_ASSETS="$(KUBEBUILDER_ASSETS)" go test $(shell go list ./... |grep -v test/fv |grep -v test/helpers) $(TEST_ARGS) -coverprofile cover.out
219253

220-
.PHONY: create-cluster
221-
create-cluster: $(KIND) $(CLUSTERCTL) $(KUBECTL) $(ENVSUBST) ## Create a new kind cluster designed for development
254+
.PHONY: create-cluster-infra
255+
create-cluster-infra: $(KIND) $(CLUSTERCTL) $(KUBECTL) $(ENVSUBST) ## Create kind cluster and workload cluster without deploying Sveltos
222256
$(MAKE) create-control-cluster
223257

224258
@echo "sleep allowing webhook to be ready"
@@ -227,17 +261,12 @@ create-cluster: $(KIND) $(CLUSTERCTL) $(KUBECTL) $(ENVSUBST) ## Create a new kin
227261
@echo "Create a workload cluster"
228262
$(KUBECTL) apply -f $(KIND_CLUSTER_YAML)
229263

230-
@echo "Start projectsveltos classifier"
231-
$(MAKE) deploy-projectsveltos
264+
@echo "sleep allowing control plane to be ready"
265+
sleep 60
232266

233-
@echo "Deploying access manager"
234-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/access-manager/$(TAG)/manifest/manifest.yaml
235267
@echo "wait for cluster to be provisioned"
236268
$(KUBECTL) wait cluster $(WORKLOAD_CLUSTER_NAME) -n default --for=jsonpath='{.status.phase}'=Provisioned --timeout=$(TIMEOUT)
237269

238-
@echo "sleep allowing control plane to be ready"
239-
sleep 60
240-
241270
@echo "get kubeconfig to access workload cluster"
242271
$(KIND) get kubeconfig --name $(WORKLOAD_CLUSTER_NAME) > test/fv/workload_kubeconfig
243272

@@ -247,6 +276,11 @@ create-cluster: $(KIND) $(CLUSTERCTL) $(KUBECTL) $(ENVSUBST) ## Create a new kin
247276
@echo wait for calico pod
248277
$(KUBECTL) --kubeconfig=./test/fv/workload_kubeconfig wait --for=condition=Available deployment/calico-kube-controllers -n kube-system --timeout=$(TIMEOUT)
249278

279+
.PHONY: create-cluster
280+
create-cluster: create-cluster-infra ## Create a new kind cluster designed for development
281+
@echo "Start projectsveltos classifier"
282+
$(MAKE) deploy-projectsveltos
283+
250284
create-cluster-pullmode: $(KIND) $(KUBECTL) $(ENVSUBST) $(KUSTOMIZE)
251285
docker network rm $(SVELTOS_NETWORK_NAME) 2>/dev/null || true
252286
docker network create $(SVELTOS_NETWORK_NAME)
@@ -406,14 +440,10 @@ deploy-projectsveltos: $(KUSTOMIZE)
406440
$(MAKE) load-image
407441

408442
@echo 'Install libsveltos CRDs'
409-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_debuggingconfigurations.lib.projectsveltos.io.yaml
410-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_classifiers.lib.projectsveltos.io.yaml
411-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_classifierreports.lib.projectsveltos.io.yaml
412-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_accessrequests.lib.projectsveltos.io.yaml
413-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_rolerequests.lib.projectsveltos.io.yaml
414-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_sveltosclusters.lib.projectsveltos.io.yaml
415-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_configurationgroups.lib.projectsveltos.io.yaml
416-
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_configurationbundles.lib.projectsveltos.io.yaml
443+
$(MAKE) deploy-crds
444+
445+
@echo "Deploying access manager"
446+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/access-manager/$(TAG)/manifest/manifest.yaml
417447

418448
# Install projectsveltos classifier components
419449
@echo 'Install projectsveltos classifier components'

config/default/manager_auth_proxy_patch.yaml

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,19 @@ spec:
1616
- "--shard-key="
1717
- --capi-onboard-annotation=
1818
- "--v=5"
19-
- "--version=v1.10.0"
19+
- "--version=main"
2020
- "--registry="
2121
- "--agent-in-mgmt-cluster=false"
22+
env:
23+
- name: TOTAL_MEMORY_LIMIT
24+
valueFrom:
25+
resourceFieldRef:
26+
resource: limits.memory
27+
- name: GOMAXPROCS
28+
valueFrom:
29+
resourceFieldRef:
30+
resource: limits.cpu
31+
- name: NAMESPACE
32+
valueFrom:
33+
fieldRef:
34+
fieldPath: metadata.namespace

config/default/manager_image_patch.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ spec:
88
spec:
99
containers:
1010
# Change the value of image field below to your controller image URL
11-
- image: docker.io/projectsveltos/classifier:v1.10.0
11+
- image: docker.io/projectsveltos/classifier:main
1212
name: manager

controllers/classifier_controller.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ const (
7777

7878
controlplaneendpoint = "controlplaneendpoint-key"
7979
configurationHash = "configurationHash"
80-
81-
projectsveltos = "projectsveltos"
8280
)
8381

8482
// ClassifierReconciler reconciles a Classifier object

controllers/classifier_deployer.go

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ const (
108108
sveltosApplierOverrideAnnotation = "sveltosapplier.projectsveltos.io/config-override-ref"
109109
)
110110

111-
func getSveltosAgentNamespace() string {
112-
return projectsveltos
111+
func getSveltosAgentNamespace(sveltosNamespace string) string {
112+
return sveltosNamespace
113113
}
114114

115115
func (r *ClassifierReconciler) deployClassifier(ctx context.Context, classifierScope *scope.ClassifierScope,
@@ -374,10 +374,10 @@ func getKubeconfigFromAccessRequest(ctx context.Context, c client.Client, cluste
374374

375375
func createSecretNamespace(ctx context.Context, c client.Client) error {
376376
ns := &corev1.Namespace{}
377-
err := c.Get(ctx, types.NamespacedName{Name: libsveltosv1beta1.ClassifierSecretNamespace}, ns)
377+
err := c.Get(ctx, types.NamespacedName{Name: getSveltosNamespace()}, ns)
378378
if err != nil {
379379
if apierrors.IsNotFound(err) {
380-
ns.Name = libsveltosv1beta1.ClassifierSecretNamespace
380+
ns.Name = getSveltosNamespace()
381381
return c.Create(ctx, ns)
382382
}
383383
return err
@@ -406,14 +406,14 @@ func updateSecretWithAccessManagementKubeconfig(ctx context.Context, c client.Cl
406406

407407
secret := &corev1.Secret{}
408408
key := client.ObjectKey{
409-
Namespace: libsveltosv1beta1.ClassifierSecretNamespace,
409+
Namespace: getSveltosNamespace(),
410410
Name: libsveltosv1beta1.ClassifierSecretName,
411411
}
412412

413413
dataKey := "kubeconfig"
414414
err = remoteClient.Get(ctx, key, secret)
415415
if err != nil {
416-
secret.Namespace = libsveltosv1beta1.ClassifierSecretNamespace
416+
secret.Namespace = getSveltosNamespace()
417417
secret.Name = libsveltosv1beta1.ClassifierSecretName
418418
secret.Data = map[string][]byte{
419419
dataKey: kubeconfig,
@@ -1553,7 +1553,7 @@ func createSveltosAgentNamespaceInManagedCluster(ctx context.Context, c client.C
15531553

15541554
ns := &corev1.Namespace{
15551555
ObjectMeta: metav1.ObjectMeta{
1556-
Name: getSveltosAgentNamespace(),
1556+
Name: getSveltosAgentNamespace(getSveltosNamespace()),
15571557
},
15581558
}
15591559

@@ -1671,6 +1671,40 @@ func deploySveltosAgentInManagementCluster(ctx context.Context, restConfig *rest
16711671
restConfig, agentYAML, lbls, patches, false, logger)
16721672
}
16731673

1674+
// updateResourceNamespace sets the namespace on a resource that requires it.
1675+
// For namespaced resources the object metadata namespace is updated.
1676+
// For ClusterRoleBinding the subjects are also patched: the resource is cluster-scoped so
1677+
// GetNamespace() returns "" and the plain SetNamespace call would not reach it, but each
1678+
// ServiceAccount subject still carries an explicit namespace that must match the actual
1679+
// location of the ServiceAccount.
1680+
func updateResourceNamespace(policy *unstructured.Unstructured, namespace string) error {
1681+
if policy.GetNamespace() != "" {
1682+
policy.SetNamespace(namespace)
1683+
}
1684+
1685+
if policy.GetKind() != "ClusterRoleBinding" {
1686+
return nil
1687+
}
1688+
1689+
subjects, found, err := unstructured.NestedSlice(policy.Object, "subjects")
1690+
if err != nil || !found {
1691+
return err
1692+
}
1693+
1694+
for i := range subjects {
1695+
subject, ok := subjects[i].(map[string]interface{})
1696+
if !ok {
1697+
continue
1698+
}
1699+
if subject["kind"] == "ServiceAccount" {
1700+
subject["namespace"] = namespace
1701+
subjects[i] = subject
1702+
}
1703+
}
1704+
1705+
return unstructured.SetNestedSlice(policy.Object, subjects, "subjects")
1706+
}
1707+
16741708
func deploySveltosAgentResources(ctx context.Context, clusterNamespace, clusterName, classifierName string,
16751709
restConfig *rest.Config, agentYAML string, lbls map[string]string, patches []libsveltosv1beta1.Patch,
16761710
isPullMode bool, logger logr.Logger) error {
@@ -1710,6 +1744,11 @@ func deploySveltosAgentResources(ctx context.Context, clusterNamespace, clusterN
17101744
}
17111745
}
17121746

1747+
if err := updateResourceNamespace(policy, getSveltosNamespace()); err != nil {
1748+
logger.V(logs.LogInfo).Error(err, "failed to update resource namespace")
1749+
return err
1750+
}
1751+
17131752
var referencedUnstructured []*unstructured.Unstructured
17141753
if len(patches) > 0 {
17151754
logger.V(logs.LogInfo).Info("Patch sveltos-agent resources")
@@ -1765,6 +1804,11 @@ func deploySveltosApplierResources(ctx context.Context, clusterNamespace, cluste
17651804
return err
17661805
}
17671806

1807+
if err := updateResourceNamespace(policy, getSveltosNamespace()); err != nil {
1808+
logger.V(logs.LogInfo).Error(err, "failed to update resource namespace")
1809+
return err
1810+
}
1811+
17681812
var referencedUnstructured []*unstructured.Unstructured
17691813
if len(patches) > 0 {
17701814
logger.V(logs.LogDebug).Info("Patch sveltos-applier resources")
@@ -1851,7 +1895,8 @@ func getSveltosAgentDeploymentName(ctx context.Context, restConfig *rest.Config,
18511895
}
18521896

18531897
// using client and a List would require permission at cluster level. So using clientset instead
1854-
deployments, err := clientset.AppsV1().Deployments(getSveltosAgentNamespace()).List(ctx, listOptions)
1898+
deployments, err := clientset.AppsV1().Deployments(getSveltosAgentNamespace(getSveltosNamespace())).
1899+
List(ctx, listOptions)
18551900
if err != nil {
18561901
return "", err
18571902
}
@@ -1930,6 +1975,10 @@ func removeSveltosAgentFromManagementCluster(ctx context.Context,
19301975
return err
19311976
}
19321977

1978+
if policy.GetNamespace() != "" {
1979+
policy.SetNamespace(getSveltosNamespace())
1980+
}
1981+
19331982
dr, err := k8s_utils.GetDynamicResourceInterface(restConfig, policy.GroupVersionKind(), policy.GetNamespace())
19341983
if err != nil {
19351984
logger.V(logs.LogInfo).Error(err, "failed to get dynamic client")
@@ -2028,7 +2077,7 @@ func getSveltosAgentPatchesOld(ctx context.Context, c client.Client,
20282077
configMap := &corev1.ConfigMap{}
20292078
if configMapName != "" {
20302079
err := c.Get(ctx,
2031-
types.NamespacedName{Namespace: projectsveltos, Name: configMapName},
2080+
types.NamespacedName{Namespace: getSveltosNamespace(), Name: configMapName},
20322081
configMap)
20332082
if err != nil {
20342083
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to get ConfigMap %s: %v",
@@ -2060,7 +2109,7 @@ func getSveltosApplierPatchesOld(ctx context.Context, c client.Client,
20602109
configMap := &corev1.ConfigMap{}
20612110
if configMapName != "" {
20622111
err := c.Get(ctx,
2063-
types.NamespacedName{Namespace: projectsveltos, Name: configMapName},
2112+
types.NamespacedName{Namespace: getSveltosNamespace(), Name: configMapName},
20642113
configMap)
20652114
if err != nil {
20662115
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to get ConfigMap %s: %v",
@@ -2098,7 +2147,7 @@ func getSveltosAgentPatches(ctx context.Context, c client.Client,
20982147
}
20992148

21002149
configMapName := getSveltosAgentConfigMap()
2101-
patches, err = getSveltosAgentPatchesNew(ctx, c, projectsveltos, configMapName, logger)
2150+
patches, err = getSveltosAgentPatchesNew(ctx, c, getSveltosNamespace(), configMapName, logger)
21022151
if err == nil {
21032152
return patches, nil
21042153
}
@@ -2120,7 +2169,7 @@ func getSveltosApplierPatches(ctx context.Context, c client.Client,
21202169
}
21212170

21222171
configMapName := getSveltosApplierConfigMap()
2123-
patches, err = getSveltosApplierPatchesNew(ctx, c, projectsveltos, configMapName, logger)
2172+
patches, err = getSveltosApplierPatchesNew(ctx, c, getSveltosNamespace(), configMapName, logger)
21242173
if err == nil {
21252174
return patches, nil
21262175
}

0 commit comments

Comments
 (0)