Skip to content

Commit 3052d13

Browse files
authored
Merge pull request #1076 from gianlucam76/auo-deploy-dependencies
Auto deploy dependencies: enable automatic deployment of prerequisites
2 parents 6641cf4 + 026763e commit 3052d13

22 files changed

Lines changed: 1259 additions & 125 deletions

api/v1beta1/status.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,8 @@ type Status struct {
3737
// Spec
3838
// +optional
3939
UpdatedClusters Clusters `json:"updatedClusters,omitempty"`
40+
41+
// DependenciesHash is a hash representing the set of clusters where this ClusterProfile
42+
// must be deployed, based on the combined configuration of its dependencies.
43+
DependenciesHash []byte `json:"dependenciesHash,omitempty"`
4044
}

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cmd/main.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import (
5959
configv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1"
6060
"github.com/projectsveltos/addon-controller/api/v1beta1/index"
6161
"github.com/projectsveltos/addon-controller/controllers"
62+
"github.com/projectsveltos/addon-controller/controllers/dependencymanager"
6263
"github.com/projectsveltos/addon-controller/internal/telemetry"
6364
libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1"
6465
"github.com/projectsveltos/libsveltos/lib/crd"
@@ -91,6 +92,7 @@ var (
9192
capiOnboardAnnotation string
9293
disableCaching bool
9394
disableTelemetry bool
95+
autoDeployDependencies bool
9496
)
9597

9698
const (
@@ -177,6 +179,8 @@ func main() {
177179
controllers.SetDriftdetectionConfigMap(driftDetectionConfigMap)
178180
controllers.SetLuaConfigMap(luaConfigMap)
179181
controllers.SetCAPIOnboardAnnotation(capiOnboardAnnotation)
182+
// Start dependency manager
183+
dependencymanager.InitializeManagerInstance(ctx, mgr.GetClient(), autoDeployDependencies, ctrl.Log.WithName("dependency_manager"))
180184

181185
logsettings.RegisterForLogSettings(ctx,
182186
libsveltosv1beta1.ComponentAddonManager, ctrl.Log.WithName("log-setter"),
@@ -277,6 +281,27 @@ func initFlags(fs *pflag.FlagSet) {
277281
fs.DurationVar(&conflictRetryTime, "conflict-retry-time", defaultConflictRetryTime*time.Second,
278282
fmt.Sprintf("The minimum interval at which watched ClusterProfile with conflicts are retried. Defaul: %d seconds",
279283
defaultConflictRetryTime))
284+
285+
// AutoDeployDependencies enables automatic deployment of prerequisite profiles.
286+
//
287+
// Profile instances can specify dependencies on other profiles using the
288+
// DependsOn field, forming a directed acyclic graph (DAG) of dependencies.
289+
//
290+
// When AutoDeployDependencies is set to true, Sveltos automatically resolves and deploys
291+
// the prerequisite profiles listed in the DependsOn field. This automation
292+
// ensures that all required dependencies are deployed to the same managed clusters
293+
// as the dependent profile. Sveltos analyzes the dependency graph to identify
294+
// and deploy prerequisites in the correct order.
295+
//
296+
// By default, AutoDeployDependencies is enabled (true). When disabled, administrators
297+
// are responsible for ensuring that both the dependent and prerequisite profiles
298+
// target the same set of managed clusters through matching cluster selectors.
299+
//
300+
// Enabling AutoDeployDependencies simplifies multi-cluster management by automating
301+
// dependency resolution, reducing manual effort, and minimizing the risk of
302+
// configuration inconsistencies.
303+
fs.BoolVar(&autoDeployDependencies, "auto-deploy-dependencies", true,
304+
" When AutoDeployDependencies is set to true, Sveltos will automatically resolve and deploy the prerequisite profiles specified in the DependsOn field")
280305
}
281306

282307
func setupIndexes(ctx context.Context, mgr ctrl.Manager) {

config/crd/bases/config.projectsveltos.io_clusterprofiles.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,12 @@ spec:
10581058
status:
10591059
description: Status defines the observed state of ClusterProfile/Profile
10601060
properties:
1061+
dependenciesHash:
1062+
description: |-
1063+
DependenciesHash is a hash representing the set of clusters where this ClusterProfile
1064+
must be deployed, based on the combined configuration of its dependencies.
1065+
format: byte
1066+
type: string
10611067
matchingClusters:
10621068
description: |-
10631069
MatchingClusterRefs reference all the clusters currently matching

config/crd/bases/config.projectsveltos.io_profiles.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1058,6 +1058,12 @@ spec:
10581058
status:
10591059
description: Status defines the observed state of ClusterProfile/Profile
10601060
properties:
1061+
dependenciesHash:
1062+
description: |-
1063+
DependenciesHash is a hash representing the set of clusters where this ClusterProfile
1064+
must be deployed, based on the combined configuration of its dependencies.
1065+
format: byte
1066+
type: string
10611067
matchingClusters:
10621068
description: |-
10631069
MatchingClusterRefs reference all the clusters currently matching

controllers/clusterprofile_controller.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"sigs.k8s.io/controller-runtime/pkg/source"
3939

4040
configv1beta1 "github.com/projectsveltos/addon-controller/api/v1beta1"
41+
"github.com/projectsveltos/addon-controller/controllers/dependencymanager"
4142
"github.com/projectsveltos/addon-controller/pkg/scope"
4243
libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1"
4344
logs "github.com/projectsveltos/libsveltos/lib/logsettings"
@@ -172,6 +173,15 @@ func (r *ClusterProfileReconciler) reconcileNormal(
172173
}
173174
matchingCluster = append(matchingCluster, clusterSetClusters...)
174175

176+
// Get all clusters where deployment is required based on dependent ClusterProfile instances
177+
depManager, err := dependencymanager.GetManagerInstance()
178+
if err != nil {
179+
return reconcile.Result{Requeue: true, RequeueAfter: normalRequeueAfter}
180+
}
181+
profileRef := getKeyFromObject(r.Scheme, profileScope.Profile)
182+
depClusters := depManager.GetClusterDeployments(profileRef)
183+
matchingCluster = append(matchingCluster, depClusters...)
184+
175185
profileScope.SetMatchingClusterRefs(removeDuplicates(matchingCluster))
176186

177187
r.updateMaps(profileScope)
Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +0,0 @@
1-
apiVersion: apps/v1
2-
kind: Deployment
3-
metadata:
4-
name: my-depl
5-
namespace: foo
6-
labels:
7-
app: my-app
8-
spec:
9-
replicas: 3
10-
selector:
11-
matchLabels:
12-
app: my-app
13-
template:
14-
metadata:
15-
labels:
16-
app: my-app
17-
spec:
18-
containers:
19-
- name: my-container
20-
image: hello-world
21-
---
22-
apiVersion: autoscaling/v1
23-
kind: HorizontalPodAutoscaler
24-
metadata:
25-
name: my-autoscaler
26-
namespace: foo
27-
spec:
28-
scaleTargetRef:
29-
apiVersion: apps/v1
30-
kind: Deployment
31-
name: not-my-depl
32-
minReplicas: 1
33-
maxReplicas: 5
34-
targetCPUUtilizationPercentage: 80
Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +0,0 @@
1-
# This Lua policies validate that in namespace "foo"
2-
# each deployment has an associated HorizontalPodAutoscaler
3-
4-
function evaluate()
5-
local hs = {}
6-
hs.valid = true
7-
hs.message = ""
8-
9-
local deployments = {}
10-
local autoscalers = {}
11-
12-
-- Separate deployments and services from the resources
13-
for _, resource in ipairs(resources) do
14-
local kind = resource.kind
15-
if resource.metadata.namespace == "foo" then
16-
if kind == "Deployment" then
17-
table.insert(deployments, resource)
18-
elseif kind == "HorizontalPodAutoscaler" then
19-
table.insert(autoscalers, resource)
20-
end
21-
end
22-
end
23-
24-
-- Check for each deployment if there is a matching HorizontalPodAutoscaler
25-
for _, deployment in ipairs(deployments) do
26-
local deploymentName = deployment.metadata.name
27-
local matchingAutoscaler = false
28-
29-
for _, autoscaler in ipairs(autoscalers) do
30-
if autoscaler.spec.scaleTargetRef.name == deployment.metadata.name then
31-
matchingAutoscaler = true
32-
break
33-
end
34-
end
35-
36-
if not matchingAutoscaler then
37-
hs.valid = false
38-
hs.message = "No matching autoscaler found for deployment: " .. deploymentName
39-
break
40-
end
41-
end
42-
43-
return hs
44-
end
Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +0,0 @@
1-
apiVersion: apps/v1
2-
kind: Deployment
3-
metadata:
4-
name: my-depl
5-
namespace: foo
6-
labels:
7-
app: my-app
8-
spec:
9-
replicas: 3
10-
selector:
11-
matchLabels:
12-
app: my-app
13-
template:
14-
metadata:
15-
labels:
16-
app: my-app
17-
spec:
18-
containers:
19-
- name: my-container
20-
image: hello-world
21-
---
22-
apiVersion: autoscaling/v1
23-
kind: HorizontalPodAutoscaler
24-
metadata:
25-
name: my-autoscaler
26-
namespace: foo
27-
spec:
28-
scaleTargetRef:
29-
apiVersion: apps/v1
30-
kind: Deployment
31-
name: my-depl
32-
minReplicas: 1
33-
maxReplicas: 5
34-
targetCPUUtilizationPercentage: 80

controllers/controllers_suite_test.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838

3939
"github.com/projectsveltos/addon-controller/api/v1beta1/index"
4040
"github.com/projectsveltos/addon-controller/controllers"
41+
"github.com/projectsveltos/addon-controller/controllers/dependencymanager"
4142
"github.com/projectsveltos/addon-controller/internal/test/helpers"
4243
libsveltosv1beta1 "github.com/projectsveltos/libsveltos/api/v1beta1"
4344
"github.com/projectsveltos/libsveltos/lib/clusterproxy"
@@ -150,6 +151,8 @@ var _ = BeforeSuite(func() {
150151
_, err = clusterproxy.GetListOfClusters(context.TODO(), testEnv.Client, "", "",
151152
textlogger.NewLogger(textlogger.NewConfig()))
152153
Expect(err).To(BeNil())
154+
155+
dependencymanager.InitializeManagerInstance(context.TODO(), testEnv.Client, false, ctrl.Log.WithName("controller_test_suite"))
153156
})
154157

155158
var _ = AfterSuite(func() {

0 commit comments

Comments
 (0)