Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add status controller to sync manifestwork status feedback back to hub Application status #4

Merged
merged 1 commit into from
Feb 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,14 @@ make run
...
INFO controller.application Starting EventSource {"reconciler group": "argoproj.io", "reconciler kind": "Application", "source": "kind source: *v1alpha1.Application"}
INFO controller.application Starting Controller {"reconciler group": "argoproj.io", "reconciler kind": "Application"}
INFO controller.manifestwork Starting EventSource {"reconciler group": "work.open-cluster-management.io", "reconciler kind": "ManifestWork", "source": "kind source: *v1.ManifestWork"}
INFO controller.manifestwork Starting Controller {"reconciler group": "work.open-cluster-management.io", "reconciler kind": "ManifestWork"}
INFO controller.application Starting workers {"reconciler group": "argoproj.io", "reconciler kind": "Application", "worker count": 1}
INFO controller.manifestwork Starting workers {"reconciler group": "work.open-cluster-management.io", "reconciler kind": "ManifestWork", "worker count": 1}
...
```

6. On the Hub cluster, create an ArgoCD cluster secret that represent the managed cluster. This step can be automated with [OCM auto import controller](https://github.com/open-cluster-management-io/multicloud-integrations/tree/enable-pull-model-import).
6. On the Hub cluster, create an ArgoCD cluster secret that represent the managed cluster. This step can be automated with [OCM auto import controller](https://github.com/open-cluster-management-io/multicloud-integrations/).
**Note** replace the `cluster-name` with the registered managed cluster name.
```
cat <<EOF | kubectl apply -f -
Expand Down Expand Up @@ -126,12 +129,19 @@ cluster1-guestbook-app-d0e5 2m41s
```
$ kubectl -n argocd get app
NAME SYNC STATUS HEALTH STATUS
cluster2-guestbook-app Synced Healthy
cluster1-guestbook-app Synced Healthy
$ kubectl -n guestbook get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
guestbook-ui 1/1 1 1 7m36s
```

13. On the Hub cluster, the status controller will sync the dormant Application with the ManifestWork status feedback. For example:
```
$ kubectl -n argocd get app
NAME SYNC STATUS HEALTH STATUS
cluster1-guestbook-app Synced Healthy
```

## Community, discussion, contribution, and support

Check the [CONTRIBUTING Doc](CONTRIBUTING.md) for how to contribute to the repo.
Expand Down
2 changes: 1 addition & 1 deletion assets/argocd diagram.drawio
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<mxfile host="app.diagrams.net" modified="2022-10-19T22:26:40.365Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36" etag="x0KpHfZ4gVKLoPElA7Ec" version="14.6.6" type="device"><diagram id="HKpmZh6TvUXBQ2md0Phn" name="Page-1">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</diagram></mxfile>
<mxfile host="app.diagrams.net" modified="2023-02-27T20:50:02.100Z" agent="5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36" etag="saKatjcWupIVjUr0iXFx" version="20.8.23" type="device"><diagram id="HKpmZh6TvUXBQ2md0Phn" name="Page-1">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</diagram></mxfile>
Binary file modified assets/pull.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions controllers/application/application_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const (
AnnotationKeyAppSet = "apps.open-cluster-management.io/hosting-applicationset"
// Application annotation that enables the skip reconcilation of an application
AnnotationKeyAppSkipReconcile = "argocd.argoproj.io/skip-reconcile"
// ManifestWork annotation that shows the namespace of the hub Application.
AnnotationKeyHubApplicationNamespace = "apps.open-cluster-management.io/hub-application-namespace"
// ManifestWork annotation that shows the name of the hub Application.
AnnotationKeyHubApplicationName = "apps.open-cluster-management.io/hub-application-name"
// Application and ManifestWork label that shows that ApplicationSet is the grand parent of this work
LabelKeyAppSet = "apps.open-cluster-management.io/application-set"
// Application label that enables the pull controller to wrap the Application in ManifestWork payload
Expand Down
137 changes: 137 additions & 0 deletions controllers/application/application_status_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/*
Copyright 2023.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicationlicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package application

import (
"context"
"fmt"

"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/predicate"

argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
"github.com/argoproj/gitops-engine/pkg/health"
workv1 "open-cluster-management.io/api/work/v1"
)

// ApplicationStatusReconciler reconciles a Application object
type ApplicationStatusReconciler struct {
client.Client
Scheme *runtime.Scheme
}

//+kubebuilder:rbac:groups=argoproj.io,resources=applications,verbs=get;list;watch;update;patch
//+kubebuilder:rbac:groups=work.open-cluster-management.io,resources=manifestworks,verbs=get;list;watch

// ManifestWorkPredicateFunctions defines which ManifestWork this controller should watch
var ManifestWorkPredicateFunctions = predicate.Funcs{
UpdateFunc: func(e event.UpdateEvent) bool {
newManifestWork := e.ObjectNew.(*workv1.ManifestWork)
return containsValidManifestWorkHubApplicationAnnotations(*newManifestWork)

},
CreateFunc: func(e event.CreateEvent) bool {
manifestWork := e.Object.(*workv1.ManifestWork)
return containsValidManifestWorkHubApplicationAnnotations(*manifestWork)
},

DeleteFunc: func(e event.DeleteEvent) bool {
return false
},
}

// SetupWithManager sets up the controller with the Manager.
func (re *ApplicationStatusReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&workv1.ManifestWork{}).
WithEventFilter(ManifestWorkPredicateFunctions).
Complete(re)
}

// Reconcile populates the Application status based on the associated ManifestWork's status feedback
func (r *ApplicationStatusReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
log.Info("reconciling Application for status update..")
defer log.Info("done reconciling Application for status update")

var manifestWork workv1.ManifestWork
if err := r.Get(ctx, req.NamespacedName, &manifestWork); err != nil {
log.Error(err, "unable to fetch ManifestWork")
return ctrl.Result{}, client.IgnoreNotFound(err)
}

if manifestWork.ObjectMeta.DeletionTimestamp != nil {
return ctrl.Result{}, nil
}

resourceManifests := manifestWork.Status.ResourceStatus.Manifests

healthStatus := ""
syncStatus := ""
if len(resourceManifests) > 0 {
statusFeedbacks := resourceManifests[0].StatusFeedbacks.Values
if len(statusFeedbacks) > 0 {
for _, statusFeedback := range statusFeedbacks {
if statusFeedback.Name == "healthStatus" {
healthStatus = *statusFeedback.Value.String
}
if statusFeedback.Name == "syncStatus" {
syncStatus = *statusFeedback.Value.String
}
}
}
}

if len(healthStatus) == 0 || len(syncStatus) == 0 {
log.Info("healthStatus and syncStatus are both not in ManifestWork status feedback yet")
return ctrl.Result{}, nil
}

applicationNamespace := manifestWork.Annotations[AnnotationKeyHubApplicationNamespace]
applicationName := manifestWork.Annotations[AnnotationKeyHubApplicationName]

application := argov1alpha1.Application{}
if err := r.Get(ctx, types.NamespacedName{Namespace: applicationNamespace, Name: applicationName}, &application); err != nil {
log.Error(err, "unable to fetch Application")
return ctrl.Result{}, err
}

application.Status.Sync.Status = argov1alpha1.SyncStatusCode(syncStatus)
application.Status.Health.Status = health.HealthStatusCode(healthStatus)
log.Info("updating Application status with ManifestWork status feedbacks")

appSetName := getAppSetOwnerName(application)
if appSetName != "" && len(application.Status.Conditions) == 0 {
application.Status.Conditions = []argov1alpha1.ApplicationCondition{{
Type: "AdditionalStatusReport",
Message: fmt.Sprintf("kubectl get multiclusterapplicationsetreports -n %s %s", application.Namespace, appSetName),
}}
}

err := r.Client.Update(ctx, &application)
if err != nil {
log.Error(err, "unable to update Application")
return ctrl.Result{}, err
}

return ctrl.Result{}, nil
}
21 changes: 19 additions & 2 deletions controllers/application/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,18 @@ func containsValidPullAnnotation(application argov1alpha1.Application) bool {
return ok && len(managedClusterName) > 0
}

func containsValidManifestWorkHubApplicationAnnotations(manifestWork workv1.ManifestWork) bool {
annos := manifestWork.GetAnnotations()
if len(annos) == 0 {
return false
}

namespace, ok := annos[AnnotationKeyHubApplicationNamespace]
name, ok2 := annos[AnnotationKeyHubApplicationName]

return ok && ok2 && len(namespace) > 0 && len(name) > 0
}

// generateAppNamespace returns the intended namespace for the Application in the following priority
// 1) Annotation specified custom namespace
// 2) Application's namespace value
Expand Down Expand Up @@ -152,12 +164,16 @@ func prepareApplicationForWorkPayload(application argov1alpha1.Application) argo
// If the Application is generated from an ApplicationSet, custom label and annotation are inserted.
func generateManifestWork(name, namespace string, application argov1alpha1.Application) *workv1.ManifestWork {
var workLabels map[string]string
var workAnnos map[string]string

workAnnos := map[string]string{
AnnotationKeyHubApplicationNamespace: application.Namespace,
AnnotationKeyHubApplicationName: application.Name,
}

appSetOwnerName := getAppSetOwnerName(application)
if appSetOwnerName != "" {
workLabels = map[string]string{LabelKeyAppSet: strconv.FormatBool(true)}
workAnnos = map[string]string{AnnotationKeyAppSet: application.Namespace + "/" + appSetOwnerName}
workAnnos[AnnotationKeyAppSet] = application.Namespace + "/" + appSetOwnerName
}

application = prepareApplicationForWorkPayload(application)
Expand Down Expand Up @@ -186,6 +202,7 @@ func generateManifestWork(name, namespace string, application argov1alpha1.Appli
{Type: workv1.JSONPathsType, JsonPaths: []workv1.JsonPath{{Name: "healthStatus", Path: ".status.health.status"}}},
{Type: workv1.JSONPathsType, JsonPaths: []workv1.JsonPath{{Name: "syncStatus", Path: ".status.sync.status"}}},
},
UpdateStrategy: &workv1.UpdateStrategy{Type: workv1.UpdateStrategyTypeUpdate},
},
},
},
Expand Down
Loading