mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-03-06 16:38:46 +01:00
176 lines
5.2 KiB
Go
176 lines
5.2 KiB
Go
package controller
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/argoproj/gitops-engine/pkg/health"
|
|
"github.com/argoproj/gitops-engine/pkg/sync/common"
|
|
"github.com/argoproj/gitops-engine/pkg/sync/hook"
|
|
"github.com/argoproj/gitops-engine/pkg/utils/kube"
|
|
log "github.com/sirupsen/logrus"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/client-go/rest"
|
|
|
|
"github.com/argoproj/argo-cd/v3/util/lua"
|
|
|
|
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
|
|
)
|
|
|
|
var (
|
|
postDeleteHook = "PostDelete"
|
|
postDeleteHooks = map[string]string{
|
|
"argocd.argoproj.io/hook": postDeleteHook,
|
|
"helm.sh/hook": "post-delete",
|
|
}
|
|
)
|
|
|
|
func isHook(obj *unstructured.Unstructured) bool {
|
|
return hook.IsHook(obj) || isPostDeleteHook(obj)
|
|
}
|
|
|
|
func isPostDeleteHook(obj *unstructured.Unstructured) bool {
|
|
if obj == nil || obj.GetAnnotations() == nil {
|
|
return false
|
|
}
|
|
for k, v := range postDeleteHooks {
|
|
if val, ok := obj.GetAnnotations()[k]; ok && val == v {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func (ctrl *ApplicationController) executePostDeleteHooks(app *v1alpha1.Application, proj *v1alpha1.AppProject, liveObjs map[kube.ResourceKey]*unstructured.Unstructured, config *rest.Config, logCtx *log.Entry) (bool, error) {
|
|
appLabelKey, err := ctrl.settingsMgr.GetAppInstanceLabelKey()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
var revisions []string
|
|
for _, src := range app.Spec.GetSources() {
|
|
revisions = append(revisions, src.TargetRevision)
|
|
}
|
|
|
|
targets, _, _, err := ctrl.appStateManager.GetRepoObjs(context.Background(), app, app.Spec.GetSources(), appLabelKey, revisions, false, false, false, proj, true)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
runningHooks := map[kube.ResourceKey]*unstructured.Unstructured{}
|
|
for key, obj := range liveObjs {
|
|
if isPostDeleteHook(obj) {
|
|
runningHooks[key] = obj
|
|
}
|
|
}
|
|
|
|
expectedHook := map[kube.ResourceKey]*unstructured.Unstructured{}
|
|
for _, obj := range targets {
|
|
if obj.GetNamespace() == "" {
|
|
obj.SetNamespace(app.Spec.Destination.Namespace)
|
|
}
|
|
if !isPostDeleteHook(obj) {
|
|
continue
|
|
}
|
|
if runningHook := runningHooks[kube.GetResourceKey(obj)]; runningHook == nil {
|
|
expectedHook[kube.GetResourceKey(obj)] = obj
|
|
}
|
|
}
|
|
createdCnt := 0
|
|
for _, obj := range expectedHook {
|
|
_, err = ctrl.kubectl.CreateResource(context.Background(), config, obj.GroupVersionKind(), obj.GetName(), obj.GetNamespace(), obj, metav1.CreateOptions{})
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
createdCnt++
|
|
}
|
|
if createdCnt > 0 {
|
|
logCtx.Infof("Created %d post-delete hooks", createdCnt)
|
|
return false, nil
|
|
}
|
|
resourceOverrides, err := ctrl.settingsMgr.GetResourceOverrides()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
healthOverrides := lua.ResourceHealthOverrides(resourceOverrides)
|
|
|
|
progressingHooksCnt := 0
|
|
for _, obj := range runningHooks {
|
|
hookHealth, err := health.GetResourceHealth(obj, healthOverrides)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if hookHealth == nil {
|
|
logCtx.WithFields(log.Fields{
|
|
"group": obj.GroupVersionKind().Group,
|
|
"version": obj.GroupVersionKind().Version,
|
|
"kind": obj.GetKind(),
|
|
"name": obj.GetName(),
|
|
"namespace": obj.GetNamespace(),
|
|
}).Info("No health check defined for resource, considering it healthy")
|
|
hookHealth = &health.HealthStatus{
|
|
Status: health.HealthStatusHealthy,
|
|
}
|
|
}
|
|
if hookHealth.Status == health.HealthStatusProgressing {
|
|
progressingHooksCnt++
|
|
}
|
|
}
|
|
if progressingHooksCnt > 0 {
|
|
logCtx.Infof("Waiting for %d post-delete hooks to complete", progressingHooksCnt)
|
|
return false, nil
|
|
}
|
|
|
|
return true, nil
|
|
}
|
|
|
|
func (ctrl *ApplicationController) cleanupPostDeleteHooks(liveObjs map[kube.ResourceKey]*unstructured.Unstructured, config *rest.Config, logCtx *log.Entry) (bool, error) {
|
|
resourceOverrides, err := ctrl.settingsMgr.GetResourceOverrides()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
healthOverrides := lua.ResourceHealthOverrides(resourceOverrides)
|
|
|
|
pendingDeletionCount := 0
|
|
aggregatedHealth := health.HealthStatusHealthy
|
|
var hooks []*unstructured.Unstructured
|
|
for _, obj := range liveObjs {
|
|
if !isPostDeleteHook(obj) {
|
|
continue
|
|
}
|
|
hookHealth, err := health.GetResourceHealth(obj, healthOverrides)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
if hookHealth == nil {
|
|
hookHealth = &health.HealthStatus{
|
|
Status: health.HealthStatusHealthy,
|
|
}
|
|
}
|
|
if health.IsWorse(aggregatedHealth, hookHealth.Status) {
|
|
aggregatedHealth = hookHealth.Status
|
|
}
|
|
hooks = append(hooks, obj)
|
|
}
|
|
|
|
for _, obj := range hooks {
|
|
for _, policy := range hook.DeletePolicies(obj) {
|
|
if (policy != common.HookDeletePolicyHookFailed || aggregatedHealth != health.HealthStatusDegraded) && (policy != common.HookDeletePolicyHookSucceeded || aggregatedHealth != health.HealthStatusHealthy) {
|
|
continue
|
|
}
|
|
pendingDeletionCount++
|
|
if obj.GetDeletionTimestamp() != nil {
|
|
continue
|
|
}
|
|
logCtx.Infof("Deleting post-delete hook %s/%s", obj.GetNamespace(), obj.GetName())
|
|
err = ctrl.kubectl.DeleteResource(context.Background(), config, obj.GroupVersionKind(), obj.GetName(), obj.GetNamespace(), metav1.DeleteOptions{})
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
}
|
|
}
|
|
if pendingDeletionCount > 0 {
|
|
logCtx.Infof("Waiting for %d post-delete hooks to be deleted", pendingDeletionCount)
|
|
return false, nil
|
|
}
|
|
return true, nil
|
|
}
|