Skip to content

Commit 339287a

Browse files
authored
Merge pull request #482 from gianlucam76/mgmt-classifier
(feat) classify managed clusters from management-cluster resources
2 parents 1ef62a9 + 8f70168 commit 339287a

29 files changed

Lines changed: 2407 additions & 105 deletions

.github/workflows/main.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- name: checkout
1717
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
1818
- name: Set up Go
19-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
19+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
2020
with:
2121
go-version: 1.26.4
2222
- name: Build
@@ -35,7 +35,7 @@ jobs:
3535
- name: checkout
3636
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
3737
- name: Set up Go
38-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
38+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
3939
with:
4040
go-version: 1.26.4
4141
- name: ut
@@ -48,7 +48,7 @@ jobs:
4848
- name: checkout
4949
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
5050
- name: Set up Go
51-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
51+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
5252
with:
5353
go-version: 1.26.4
5454
- name: fv
@@ -61,7 +61,7 @@ jobs:
6161
- name: checkout
6262
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
6363
- name: Set up Go
64-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
64+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
6565
with:
6666
go-version: 1.26.4
6767
- name: fv-sharding
@@ -74,7 +74,7 @@ jobs:
7474
- name: checkout
7575
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
7676
- name: Set up Go
77-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
77+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
7878
with:
7979
go-version: 1.26.4
8080
- name: fv-agentless
@@ -87,7 +87,7 @@ jobs:
8787
- name: checkout
8888
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
8989
- name: Set up Go
90-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
90+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
9191
with:
9292
go-version: 1.26.4
9393
- name: fv-pullmode
@@ -100,7 +100,7 @@ jobs:
100100
- name: checkout
101101
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
102102
- name: Set up Go
103-
uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
103+
uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6.5.0
104104
with:
105105
go-version: 1.26.4
106106
- name: fv

Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ KUBECTL := $(TOOLS_BIN_DIR)/kubectl
6060
CLUSTERCTL := $(TOOLS_BIN_DIR)/clusterctl
6161

6262
GOLANGCI_LINT_VERSION := "v2.12.1"
63-
CLUSTERCTL_VERSION := v1.13.2
63+
CLUSTERCTL_VERSION := v1.13.3
6464

6565
KUSTOMIZE_VER := v5.8.0
6666
KUSTOMIZE_BIN := kustomize
@@ -221,6 +221,8 @@ deploy-crds: $(KUBECTL) ## Install all required Sveltos CRDs
221221
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_debuggingconfigurations.lib.projectsveltos.io.yaml
222222
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_classifiers.lib.projectsveltos.io.yaml
223223
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_classifierreports.lib.projectsveltos.io.yaml
224+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_managementclusterclassifiers.lib.projectsveltos.io.yaml
225+
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_managementclusterclassifierreports.lib.projectsveltos.io.yaml
224226
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_accessrequests.lib.projectsveltos.io.yaml
225227
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_rolerequests.lib.projectsveltos.io.yaml
226228
$(KUBECTL) apply -f https://raw.githubusercontent.com/projectsveltos/libsveltos/$(TAG)/manifests/apiextensions.k8s.io_v1_customresourcedefinition_sveltosclusters.lib.projectsveltos.io.yaml

config/manager/manager.yaml

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,8 @@ spec:
2626
spec:
2727
securityContext:
2828
runAsNonRoot: true
29-
# TODO(user): For common cases that do not require escalating privileges
30-
# it is recommended to ensure that all your Pods/Containers are restrictive.
31-
# More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted
32-
# Please uncomment the following code if your project does NOT have to work on old Kubernetes
33-
# versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ).
34-
# seccompProfile:
35-
# type: RuntimeDefault
29+
seccompProfile:
30+
type: RuntimeDefault
3631
initContainers:
3732
- name: migrate
3833
command:

config/rbac/kustomization.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ resources:
77
- service_account.yaml
88
- role.yaml
99
- role_binding.yaml
10+
- role_extra.yaml
1011
# Comment the following 4 lines if you want to disable
1112
# the auth proxy (https://github.com/brancz/kube-rbac-proxy)
1213
# which protects your /metrics endpoint.

config/rbac/role.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ rules:
6565
- classifiers
6666
- configurationbundles
6767
- configurationgroups
68+
- managementclusterclassifiers
6869
verbs:
6970
- create
7071
- delete
@@ -77,6 +78,7 @@ rules:
7778
- lib.projectsveltos.io
7879
resources:
7980
- classifierreports
81+
- managementclusterclassifierreports
8082
verbs:
8183
- create
8284
- delete
@@ -89,6 +91,8 @@ rules:
8991
resources:
9092
- classifierreports/status
9193
- classifiers/status
94+
- managementclusterclassifierreports/status
95+
- managementclusterclassifiers/status
9296
verbs:
9397
- get
9498
- patch
@@ -97,6 +101,7 @@ rules:
97101
- lib.projectsveltos.io
98102
resources:
99103
- classifiers/finalizers
104+
- managementclusterclassifiers/finalizers
100105
verbs:
101106
- update
102107
- apiGroups:

config/rbac/role_binding.yaml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,16 @@ subjects:
1010
- kind: ServiceAccount
1111
name: manager
1212
namespace: system
13+
---
14+
apiVersion: rbac.authorization.k8s.io/v1
15+
kind: ClusterRoleBinding
16+
metadata:
17+
name: manager-rolebinding-extra
18+
roleRef:
19+
apiGroup: rbac.authorization.k8s.io
20+
kind: ClusterRole
21+
name: controller-role-extra
22+
subjects:
23+
- kind: ServiceAccount
24+
name: manager
25+
namespace: system

config/rbac/role_extra.yaml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
# ManagementClusterClassifier evaluates resources on the management cluster
3+
# to classify managed clusters and apply labels to them.
4+
# Grant this ClusterRole the verbs (get, list, watch) on whatever API groups
5+
# and resources your ManagementClusterClassifier instances reference in
6+
# spec.matchResources. A ClusterRoleBinding tying this role to the classifier
7+
# ServiceAccount is created automatically when Sveltos is installed.
8+
# Example: to allow watching ConfigMaps and ScanResult CRs add
9+
#
10+
# rules:
11+
# - apiGroups: [""]
12+
# resources: ["configmaps"]
13+
# verbs: ["get", "list", "watch"]
14+
# - apiGroups: ["compliance.example.io"]
15+
# resources: ["scanresults"]
16+
# verbs: ["get", "list", "watch"]
17+
apiVersion: rbac.authorization.k8s.io/v1
18+
kind: ClusterRole
19+
metadata:
20+
name: controller-role-extra

controllers/controllers_suite_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@ var _ = BeforeSuite(func() {
129129
Expect(err).To(BeNil())
130130
Expect(testEnv.Create(ctx, classifierReportCRD)).To(Succeed())
131131

132+
mgmtClusterClassifierCRD, err := k8s_utils.GetUnstructured(crd.GetManagementClusterClassifierCRDYAML())
133+
Expect(err).To(BeNil())
134+
Expect(testEnv.Create(ctx, mgmtClusterClassifierCRD)).To(Succeed())
135+
136+
mgmtClusterClassifierReportCRD, err := k8s_utils.GetUnstructured(crd.GetManagementClusterClassifierReportCRDYAML())
137+
Expect(err).To(BeNil())
138+
Expect(testEnv.Create(ctx, mgmtClusterClassifierReportCRD)).To(Succeed())
139+
132140
ns := &corev1.Namespace{
133141
ObjectMeta: metav1.ObjectMeta{
134142
Name: sveltosNamespace,

controllers/export_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,19 @@ var (
9090
const (
9191
Controlplaneendpoint = controlplaneendpoint
9292
)
93+
94+
// ManagementClusterClassifier exports for unit tests.
95+
var (
96+
DoesMatchLabelFilters = doesMatchLabelFilters
97+
RunClassificationLua = runClassificationLua
98+
ClusterTypeFromKind = clusterTypeFromKind
99+
MgmtClassifierAsClassifier = mgmtClassifierAsClassifier
100+
EnsureMgmtClassifierReport = ensureMgmtClassifierReport
101+
ClassifierLabelKeys = classifierLabelKeys
102+
FetchResourcesForSelector = fetchResourcesForSelector
103+
ListMgmtClassifierReports = listMgmtClassifierReports
104+
GetMgmtClassifierReport = getMgmtClassifierReport
105+
DeleteMgmtClassifierReport = deleteMgmtClassifierReport
106+
ApplyLabelsToCluster = applyLabelsToCluster
107+
RemoveLabelsFromCluster = removeLabelsFromCluster
108+
)

controllers/keymanager/keymanager.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,7 @@ func isClassifierAlreadyRegistered(classifiers []string, classifierKey string) b
354354

355355
// rebuildRegistrations rebuilds internal structures to identify Classifiers managing
356356
// labels and Classifiers currently just registered but not managing.
357-
// Reads from ClassifierReport.Status (the authoritative post-migration location).
357+
// Reads from ClassifierReport.Status and ManagementClusterClassifierReport.Status.
358358
func (m *instance) rebuildRegistrations(ctx context.Context, c client.Client) error {
359359
// Lock here
360360
m.chartMux.Lock()
@@ -389,6 +389,47 @@ func (m *instance) rebuildRegistrations(ctx context.Context, c client.Client) er
389389
m.addManagedLabelsInCluster(classifierKey, clusterKey, unManagedKeys)
390390
}
391391

392+
// Also rebuild registrations from ManagementClusterClassifierReports.
393+
// ManagementClusterClassifier names are stored with the "mgmt:" prefix to avoid
394+
// collision with regular Classifier names.
395+
if err := m.rebuildMgmtClassifierRegistrations(ctx, c); err != nil {
396+
return err
397+
}
398+
399+
return nil
400+
}
401+
402+
// rebuildMgmtClassifierRegistrations reads ManagementClusterClassifierReports and registers
403+
// each ManagementClusterClassifier's label ownership using the "mgmt:" prefix.
404+
func (m *instance) rebuildMgmtClassifierRegistrations(ctx context.Context, c client.Client) error {
405+
mgmtReportList := &libsveltosv1beta1.ManagementClusterClassifierReportList{}
406+
if err := c.List(ctx, mgmtReportList); err != nil {
407+
return err
408+
}
409+
410+
// First pass: managed labels (primary managers).
411+
for i := range mgmtReportList.Items {
412+
report := &mgmtReportList.Items[i]
413+
if report.Spec.ClusterNamespace == "" || len(report.Status.ManagedLabels) == 0 {
414+
continue
415+
}
416+
clusterKey := m.getClusterKey(report.Spec.ClusterNamespace, report.Spec.ClusterName, report.Spec.ClusterType)
417+
classifierKey := m.getClassifierKey("mgmt:" + report.Spec.ClassifierName)
418+
m.addManagedLabelsInCluster(classifierKey, clusterKey, report.Status.ManagedLabels)
419+
}
420+
421+
// Second pass: unmanaged labels (waiting to take over).
422+
for i := range mgmtReportList.Items {
423+
report := &mgmtReportList.Items[i]
424+
if report.Spec.ClusterNamespace == "" || len(report.Status.UnManagedLabels) == 0 {
425+
continue
426+
}
427+
clusterKey := m.getClusterKey(report.Spec.ClusterNamespace, report.Spec.ClusterName, report.Spec.ClusterType)
428+
classifierKey := m.getClassifierKey("mgmt:" + report.Spec.ClassifierName)
429+
unManagedKeys := m.buildSliceOfUnManagedLabels(report.Status.UnManagedLabels)
430+
m.addManagedLabelsInCluster(classifierKey, clusterKey, unManagedKeys)
431+
}
432+
392433
return nil
393434
}
394435

0 commit comments

Comments
 (0)