@@ -66,6 +66,8 @@ type feature struct {
6666}
6767
6868const (
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
14011443func 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+
14911550func 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+
15911690func 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+
17881919func addTemplateSpecLabels (u * unstructured.Unstructured , lbls map [string ]string ) (* unstructured.Unstructured , error ) {
17891920 var deployment appsv1.Deployment
17901921 err := runtime .DefaultUnstructuredConverter .FromUnstructured (u .UnstructuredContent (), & deployment )
0 commit comments