Skip to content

Commit 231fbd5

Browse files
authored
Merge pull request #400 from gianlucam76/sveltos-applier-upgrade
(feat) upgrade SveltosApplier
2 parents ca4d474 + af69bc9 commit 231fbd5

File tree

10 files changed

+481
-12
lines changed

10 files changed

+481
-12
lines changed

Makefile

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,7 @@ $(shell skopeo inspect --format '{{.Digest}}' "docker://projectsveltos/sveltos-a
429429
endef
430430

431431
define get-digest-sveltos-applier
432-
$(shell skopeo inspect --format '{{.Digest}}' "docker://projectsveltos/sveltos-applier:${TAG}" --override-os="linux" --override-arch="amd64" --override-variant="v8" 2>/dev/null)
432+
$(shell skopeo inspect --format '{{.Digest}}' "docker://projectsveltos/sveltos-applier:main" --override-os="linux" --override-arch="amd64" --override-variant="v8" 2>/dev/null)
433433
endef
434434

435435
sveltos-agent:
@@ -448,8 +448,11 @@ sveltos-applier:
448448
@echo "Downloading sveltos applier yaml"
449449
$(eval digest :=$(call get-digest-sveltos-applier))
450450
@echo "image digest is $(get-digest-sveltos-applier)"
451+
curl -L -H "Authorization: token $$GITHUB_PAT" https://raw.githubusercontent.com/projectsveltos/sveltos-applier/main/manifest/manifest.yaml -o ./pkg/agent/sveltos-applier.yaml
452+
sed -i '' -e "s#image: docker.io/projectsveltos/sveltos-applier:main#image: docker.io/projectsveltos/sveltos-applier@${digest}#g" ./pkg/agent/sveltos-applier.yaml
453+
cd pkg/agent; go generate
451454
curl -L -H "Authorization: token $$GITHUB_PAT" https://raw.githubusercontent.com/projectsveltos/sveltos-applier/main/manifest/manifest.yaml -o ./test/pullmode-sveltosapplier.yaml
452-
sed -i '' -e "s#image: docker.io/projectsveltos/sveltos-applier:${TAG}#image: docker.io/projectsveltos/sveltos-applier@${digest}#g" ./test/pullmode-sveltosapplier.yaml
455+
sed -i '' -e "s#image: docker.io/projectsveltos/sveltos-applier:main#image: docker.io/projectsveltos/sveltos-applier@${digest}#g" ./test/pullmode-sveltosapplier.yaml
453456
sed -i '' -e "s#cluster-namespace=#cluster-namespace=default#g" ./test/pullmode-sveltosapplier.yaml
454457
sed -i '' -e "s#cluster-name=#cluster-name=clusterapi-workload#g" ./test/pullmode-sveltosapplier.yaml
455458
sed -i '' -e "s#cluster-type=#cluster-type=sveltos#g" ./test/pullmode-sveltosapplier.yaml

controllers/classifier_deployer.go

Lines changed: 135 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ type feature struct {
6666
}
6767

6868
const (
69+
sveltosApplier = "sveltos-applier"
70+
6971
sveltosAgent = "sveltos-agent"
7072
sveltosAgentFeatureLabelKey = "feature"
7173
sveltosAgentClusterNamespaceLabel = "cluster-namespace"
@@ -540,6 +542,16 @@ func deployClassifierInCluster(ctx context.Context, c client.Client,
540542
if err != nil {
541543
return err
542544
}
545+
546+
// Initially, a user needs to manually deploy SveltosApplier in a managed cluster. After this initial
547+
// deployment, the classifier will automatically handle any necessary upgrades. The SveltosApplier
548+
// resources are passed to the SveltosApplier running in the managed cluster via ConfigurationGroups.
549+
// The SveltosApplier then applies these resources, effectively upgrading itself.
550+
err = upgradeSveltosApplierInManagedCluster(ctx, clusterNamespace, clusterName, applicant,
551+
clusterType, logger)
552+
if err != nil {
553+
return err
554+
}
543555
}
544556

545557
err = deployCRDs(ctx, clusterNamespace, clusterName, applicant, clusterType, isPullMode, logger)
@@ -851,7 +863,21 @@ func (r *ClassifierReconciler) getCurrentHash(ctx context.Context, classifierSco
851863
// If sveltos-agent configuration is in a ConfigMap. fetch ConfigMap and use its Data
852864
// section in the hash evaluation.
853865
if sveltosAgentConfigMap := getSveltosAgentConfigMap(); sveltosAgentConfigMap != "" {
854-
configMap, err := collectSveltosAgentConfigMap(ctx, sveltosAgentConfigMap)
866+
configMap, err := collectAgentConfigMap(ctx, sveltosAgentConfigMap)
867+
if err != nil {
868+
return nil, err
869+
}
870+
h := sha256.New()
871+
config := string(currentHash)
872+
config += render.AsCode(configMap.Data)
873+
h.Write([]byte(config))
874+
currentHash = h.Sum(nil)
875+
}
876+
877+
// If sveltos-applier configuration is in a ConfigMap. fetch ConfigMap and use its Data
878+
// section in the hash evaluation.
879+
if sveltosApplierConfigMap := getSveltosApplierConfigMap(); sveltosApplierConfigMap != "" {
880+
configMap, err := collectAgentConfigMap(ctx, sveltosApplierConfigMap)
855881
if err != nil {
856882
return nil, err
857883
}
@@ -1396,6 +1422,22 @@ func prepareSveltosAgentYAML(agentYAML, clusterNamespace, clusterName, mode stri
13961422
return agentYAML
13971423
}
13981424

1425+
func prepareSveltosApplierYAML(agentYAML, clusterNamespace, clusterName string,
1426+
clusterType libsveltosv1beta1.ClusterType) string {
1427+
1428+
agentYAML = strings.ReplaceAll(agentYAML, "cluster-namespace=", fmt.Sprintf("cluster-namespace=%s", clusterNamespace))
1429+
agentYAML = strings.ReplaceAll(agentYAML, "cluster-name=", fmt.Sprintf("cluster-name=%s", clusterName))
1430+
agentYAML = strings.ReplaceAll(agentYAML, "cluster-type=", fmt.Sprintf("cluster-type=%s", clusterType))
1431+
agentYAML = strings.ReplaceAll(agentYAML, "secret-with-kubeconfig=", fmt.Sprintf("secret-with-kubeconfig=%s-sveltos-kubeconfig", clusterName))
1432+
1433+
registry := GetSveltosAgentRegistry()
1434+
if registry != "" {
1435+
agentYAML = replaceRegistry(agentYAML, registry)
1436+
}
1437+
1438+
return agentYAML
1439+
}
1440+
13991441
// createSveltosAgentNamespaceInManagedCluster creates the namespace where sveltos-agent will
14001442
// store all its reports
14011443
func createSveltosAgentNamespaceInManagedCluster(ctx context.Context, c client.Client,
@@ -1488,6 +1530,23 @@ func deploySveltosAgentInManagedCluster(ctx context.Context, remoteRestConfig *r
14881530
remoteRestConfig, agentYAML, nil, patches, isPullMode, logger)
14891531
}
14901532

1533+
func upgradeSveltosApplierInManagedCluster(ctx context.Context, clusterNamespace, clusterName, classifierName string,
1534+
clusterType libsveltosv1beta1.ClusterType, logger logr.Logger) error {
1535+
1536+
logger.V(logs.LogDebug).Info("upgrade sveltos-applier in the managed cluster")
1537+
1538+
patches, err := getSveltosApplierPatches(ctx, getManagementClusterClient(), logger)
1539+
if err != nil {
1540+
return err
1541+
}
1542+
1543+
agentYAML := string(agent.GetSveltosApplierAML())
1544+
agentYAML = prepareSveltosApplierYAML(agentYAML, clusterNamespace, clusterName, clusterType)
1545+
1546+
return deploySveltosApplierResources(ctx, clusterNamespace, clusterName, classifierName,
1547+
agentYAML, patches, logger)
1548+
}
1549+
14911550
func deploySveltosAgentInManagementCluster(ctx context.Context, restConfig *rest.Config, c client.Client,
14921551
clusterNamespace, clusterName, classifierName, mode string, clusterType libsveltosv1beta1.ClusterType,
14931552
patches []libsveltosv1beta1.Patch, logger logr.Logger) error {
@@ -1512,7 +1571,7 @@ func deploySveltosAgentInManagementCluster(ctx context.Context, restConfig *rest
15121571
restConfig, agentYAML, lbls, patches, false, logger)
15131572
}
15141573

1515-
func deploySveltosAgentResources(ctx context.Context, clusterNamespace, clusterName, cliassifierName string,
1574+
func deploySveltosAgentResources(ctx context.Context, clusterNamespace, clusterName, classifierName string,
15161575
restConfig *rest.Config, agentYAML string, lbls map[string]string, patches []libsveltosv1beta1.Patch,
15171576
isPullMode bool, logger logr.Logger) error {
15181577

@@ -1527,7 +1586,7 @@ func deploySveltosAgentResources(ctx context.Context, clusterNamespace, clusterN
15271586
for i := range elements {
15281587
policy, err := k8s_utils.GetUnstructured([]byte(elements[i]))
15291588
if err != nil {
1530-
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to parse classifier agent yaml: %v", err))
1589+
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to parse sveltos agent yaml: %v", err))
15311590
return err
15321591
}
15331592

@@ -1579,7 +1638,7 @@ func deploySveltosAgentResources(ctx context.Context, clusterNamespace, clusterN
15791638
// This means SveltosCluster is in pull mode
15801639
if isPullMode {
15811640
err = pullmode.StageResourcesForDeployment(ctx, getManagementClusterClient(), clusterNamespace, clusterName,
1582-
libsveltosv1beta1.ClassifierKind, cliassifierName, libsveltosv1beta1.FeatureClassifier, resources, true, logger)
1641+
libsveltosv1beta1.ClassifierKind, classifierName, libsveltosv1beta1.FeatureClassifier, resources, true, logger)
15831642
if err != nil {
15841643
return err
15851644
}
@@ -1588,6 +1647,46 @@ func deploySveltosAgentResources(ctx context.Context, clusterNamespace, clusterN
15881647
return nil
15891648
}
15901649

1650+
func deploySveltosApplierResources(ctx context.Context, clusterNamespace, clusterName, classifierName string,
1651+
agentYAML string, patches []libsveltosv1beta1.Patch, logger logr.Logger) error {
1652+
1653+
resources := make(map[string][]unstructured.Unstructured)
1654+
index := sveltosApplier
1655+
resources[index] = []unstructured.Unstructured{}
1656+
1657+
elements, err := deployer.CustomSplit(agentYAML)
1658+
if err != nil {
1659+
return err
1660+
}
1661+
for i := range elements {
1662+
policy, err := k8s_utils.GetUnstructured([]byte(elements[i]))
1663+
if err != nil {
1664+
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to parse sveltos applier yaml: %v", err))
1665+
return err
1666+
}
1667+
1668+
var referencedUnstructured []*unstructured.Unstructured
1669+
if len(patches) > 0 {
1670+
logger.V(logs.LogInfo).Info("Patch sveltos-applier resources")
1671+
p := &patcher.CustomPatchPostRenderer{Patches: patches}
1672+
referencedUnstructured, err = p.RunUnstructured(
1673+
[]*unstructured.Unstructured{policy},
1674+
)
1675+
if err != nil {
1676+
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to patch sveltos-applier: %v", err))
1677+
return err
1678+
}
1679+
} else {
1680+
referencedUnstructured = append(referencedUnstructured, policy)
1681+
}
1682+
1683+
resources[index] = append(resources[index], convertPointerSliceToValueSlice(referencedUnstructured)...)
1684+
}
1685+
1686+
return pullmode.StageResourcesForDeployment(ctx, getManagementClusterClient(), clusterNamespace, clusterName,
1687+
libsveltosv1beta1.ClassifierKind, classifierName, libsveltosv1beta1.FeatureClassifier, resources, true, logger)
1688+
}
1689+
15911690
func deploySveltosAgentPatchedResources(ctx context.Context, restConfig *rest.Config,
15921691
referencedUnstructured []*unstructured.Unstructured, logger logr.Logger) error {
15931692

@@ -1785,6 +1884,38 @@ func getSveltosAgentPatches(ctx context.Context, c client.Client,
17851884
return patches, nil
17861885
}
17871886

1887+
func getSveltosApplierPatches(ctx context.Context, c client.Client,
1888+
logger logr.Logger) ([]libsveltosv1beta1.Patch, error) {
1889+
1890+
patches := make([]libsveltosv1beta1.Patch, 0)
1891+
configMapName := getSveltosApplierConfigMap()
1892+
configMap := &corev1.ConfigMap{}
1893+
if configMapName != "" {
1894+
err := c.Get(ctx,
1895+
types.NamespacedName{Namespace: projectsveltos, Name: configMapName},
1896+
configMap)
1897+
if err != nil {
1898+
logger.V(logs.LogInfo).Info(fmt.Sprintf("failed to get ConfigMap %s: %v",
1899+
configMapName, err))
1900+
return nil, err
1901+
}
1902+
}
1903+
1904+
for k := range configMap.Data {
1905+
// Only Deployment can be patched
1906+
patch := libsveltosv1beta1.Patch{
1907+
Patch: configMap.Data[k],
1908+
Target: &libsveltosv1beta1.PatchSelector{
1909+
Kind: "Deployment",
1910+
Group: "apps",
1911+
},
1912+
}
1913+
patches = append(patches, patch)
1914+
}
1915+
1916+
return patches, nil
1917+
}
1918+
17881919
func addTemplateSpecLabels(u *unstructured.Unstructured, lbls map[string]string) (*unstructured.Unstructured, error) {
17891920
var deployment appsv1.Deployment
17901921
err := runtime.DefaultUnstructuredConverter.FromUnstructured(u.UnstructuredContent(), &deployment)

controllers/management_cluster.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ var (
3030
managementClusterConfig *rest.Config
3131
managementClusterClient client.Client
3232
sveltosAgentConfigMap string
33+
sveltosApplierConfigMap string
3334
registry string
3435
agentInMgmtCluster bool
3536
)
@@ -43,6 +44,10 @@ func SetSveltosAgentConfigMap(name string) {
4344
sveltosAgentConfigMap = name
4445
}
4546

47+
func SetSveltosApplierConfigMap(name string) {
48+
sveltosApplierConfigMap = name
49+
}
50+
4651
func SetSveltosAgentRegistry(reg string) {
4752
registry = reg
4853
}
@@ -67,6 +72,10 @@ func getSveltosAgentConfigMap() string {
6772
return sveltosAgentConfigMap
6873
}
6974

75+
func getSveltosApplierConfigMap() string {
76+
return sveltosApplierConfigMap
77+
}
78+
7079
func GetSveltosAgentRegistry() string {
7180
return registry
7281
}
@@ -75,7 +84,7 @@ func getAgentInMgmtCluster() bool {
7584
return agentInMgmtCluster
7685
}
7786

78-
func collectSveltosAgentConfigMap(ctx context.Context, name string) (*corev1.ConfigMap, error) {
87+
func collectAgentConfigMap(ctx context.Context, name string) (*corev1.ConfigMap, error) {
7988
c := getManagementClusterClient()
8089
configMap := &corev1.ConfigMap{}
8190

generator.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
const (
2929
agentTemplate = `// Generated by *go generate* - DO NOT EDIT
3030
/*
31-
Copyright 2022-23. projectsveltos.io. All rights reserved.
31+
Copyright 2022-25. projectsveltos.io. All rights reserved.
3232
3333
Licensed under the Apache License, Version 2.0 (the "License");
3434
you may not use this file except in compliance with the License.
@@ -91,7 +91,9 @@ func main() {
9191
sveltosAgentFile := "../../pkg/agent/sveltos-agent.yaml"
9292
generate(sveltosAgentFile, "sveltos-agent", "sveltosAgent")
9393

94-
driftDetectionManagerInMgmtClusterFile := "../../pkg/agent/sveltos-agent-in-mgmt-cluster.yaml"
95-
generate(driftDetectionManagerInMgmtClusterFile, "sveltos-agent-in-mgmt-cluster", "sveltosAgentInMgmtCluster")
94+
sveltosAgentInMgmtClusterFile := "../../pkg/agent/sveltos-agent-in-mgmt-cluster.yaml"
95+
generate(sveltosAgentInMgmtClusterFile, "sveltos-agent-in-mgmt-cluster", "sveltosAgentInMgmtCluster")
9696

97+
sveltosApplierFile := "../../pkg/agent/sveltos-applier.yaml"
98+
generate(sveltosApplierFile, "sveltos-applier", "sveltosApplier")
9799
}

main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ var (
7878
version string
7979
healthAddr string
8080
sveltosAgentConfigMap string
81+
sveltosApplierConfigMap string
8182
capiOnboardAnnotation string
8283
registry string
8384
)
@@ -135,6 +136,7 @@ func main() {
135136

136137
controllers.SetManagementClusterAccess(mgr.GetConfig(), mgr.GetClient())
137138
controllers.SetSveltosAgentConfigMap(sveltosAgentConfigMap)
139+
controllers.SetSveltosApplierConfigMap(sveltosApplierConfigMap)
138140
controllers.SetSveltosAgentRegistry(registry)
139141
controllers.SetAgentInMgmtCluster(agentInMgmtCluster)
140142

@@ -227,6 +229,9 @@ func initFlags(fs *pflag.FlagSet) {
227229
fs.StringVar(&sveltosAgentConfigMap, "sveltos-agent-config", "",
228230
"The name of the ConfigMap in the projectsveltos namespace containing the sveltos-agent configuration")
229231

232+
fs.StringVar(&sveltosApplierConfigMap, "sveltos-applier-config", "",
233+
"The name of the ConfigMap in the projectsveltos namespace containing the sveltos-applier configuration")
234+
230235
fs.StringVar(&healthAddr, "health-addr", ":9440",
231236
"The address the health endpoint binds to.")
232237

pkg/agent/agent.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,7 @@ func GetSveltosAgentYAML() []byte {
2525
func GetSveltosAgentInMgmtClusterYAML() []byte {
2626
return sveltosAgentInMgmtClusterYAML
2727
}
28+
29+
func GetSveltosApplierAML() []byte {
30+
return sveltosApplierYAML
31+
}

pkg/agent/sveltos-agent-in-mgmt-cluster.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Generated by *go generate* - DO NOT EDIT
22
/*
3-
Copyright 2022-23. projectsveltos.io. All rights reserved.
3+
Copyright 2022-25. projectsveltos.io. All rights reserved.
44
55
Licensed under the Apache License, Version 2.0 (the "License");
66
you may not use this file except in compliance with the License.

pkg/agent/sveltos-agent.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Generated by *go generate* - DO NOT EDIT
22
/*
3-
Copyright 2022-23. projectsveltos.io. All rights reserved.
3+
Copyright 2022-25. projectsveltos.io. All rights reserved.
44
55
Licensed under the Apache License, Version 2.0 (the "License");
66
you may not use this file except in compliance with the License.

0 commit comments

Comments
 (0)