argo-cd

Форк
0
158 строк · 4.7 Кб
1
package controller
2

3
import (
4
	"context"
5

6
	"github.com/argoproj/gitops-engine/pkg/health"
7
	"github.com/argoproj/gitops-engine/pkg/sync/common"
8
	"github.com/argoproj/gitops-engine/pkg/sync/hook"
9
	"github.com/argoproj/gitops-engine/pkg/utils/kube"
10
	log "github.com/sirupsen/logrus"
11
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
13
	"k8s.io/client-go/rest"
14

15
	"github.com/argoproj/argo-cd/v2/util/lua"
16

17
	"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
18
)
19

20
var (
21
	postDeleteHook  = "PostDelete"
22
	postDeleteHooks = map[string]string{
23
		"argocd.argoproj.io/hook": postDeleteHook,
24
		"helm.sh/hook":            "post-delete",
25
	}
26
)
27

28
func isHook(obj *unstructured.Unstructured) bool {
29
	return hook.IsHook(obj) || isPostDeleteHook(obj)
30
}
31

32
func isPostDeleteHook(obj *unstructured.Unstructured) bool {
33
	if obj == nil || obj.GetAnnotations() == nil {
34
		return false
35
	}
36
	for k, v := range postDeleteHooks {
37
		if val, ok := obj.GetAnnotations()[k]; ok && val == v {
38
			return true
39
		}
40
	}
41
	return false
42
}
43

44
func (ctrl *ApplicationController) executePostDeleteHooks(app *v1alpha1.Application, proj *v1alpha1.AppProject, liveObjs map[kube.ResourceKey]*unstructured.Unstructured, config *rest.Config, logCtx *log.Entry) (bool, error) {
45
	appLabelKey, err := ctrl.settingsMgr.GetAppInstanceLabelKey()
46
	if err != nil {
47
		return false, err
48
	}
49
	var revisions []string
50
	for _, src := range app.Spec.GetSources() {
51
		revisions = append(revisions, src.TargetRevision)
52
	}
53

54
	targets, _, err := ctrl.appStateManager.GetRepoObjs(app, app.Spec.GetSources(), appLabelKey, revisions, false, false, false, proj)
55
	if err != nil {
56
		return false, err
57
	}
58
	runningHooks := map[kube.ResourceKey]*unstructured.Unstructured{}
59
	for key, obj := range liveObjs {
60
		if isPostDeleteHook(obj) {
61
			runningHooks[key] = obj
62
		}
63
	}
64

65
	expectedHook := map[kube.ResourceKey]*unstructured.Unstructured{}
66
	for _, obj := range targets {
67
		if obj.GetNamespace() == "" {
68
			obj.SetNamespace(app.Spec.Destination.Namespace)
69
		}
70
		if !isPostDeleteHook(obj) {
71
			continue
72
		}
73
		if runningHook := runningHooks[kube.GetResourceKey(obj)]; runningHook == nil {
74
			expectedHook[kube.GetResourceKey(obj)] = obj
75
		}
76
	}
77
	createdCnt := 0
78
	for _, obj := range expectedHook {
79
		_, err = ctrl.kubectl.CreateResource(context.Background(), config, obj.GroupVersionKind(), obj.GetName(), obj.GetNamespace(), obj, v1.CreateOptions{})
80
		if err != nil {
81
			return false, err
82
		}
83
		createdCnt++
84
	}
85
	if createdCnt > 0 {
86
		logCtx.Infof("Created %d post-delete hooks", createdCnt)
87
		return false, nil
88
	}
89
	resourceOverrides, err := ctrl.settingsMgr.GetResourceOverrides()
90
	if err != nil {
91
		return false, err
92
	}
93
	healthOverrides := lua.ResourceHealthOverrides(resourceOverrides)
94

95
	progressingHooksCnt := 0
96
	for _, obj := range runningHooks {
97
		hookHealth, err := health.GetResourceHealth(obj, healthOverrides)
98
		if err != nil {
99
			return false, err
100
		}
101
		if hookHealth.Status == health.HealthStatusProgressing {
102
			progressingHooksCnt++
103
		}
104
	}
105
	if progressingHooksCnt > 0 {
106
		logCtx.Infof("Waiting for %d post-delete hooks to complete", progressingHooksCnt)
107
		return false, nil
108
	}
109

110
	return true, nil
111
}
112

113
func (ctrl *ApplicationController) cleanupPostDeleteHooks(liveObjs map[kube.ResourceKey]*unstructured.Unstructured, config *rest.Config, logCtx *log.Entry) (bool, error) {
114
	resourceOverrides, err := ctrl.settingsMgr.GetResourceOverrides()
115
	if err != nil {
116
		return false, err
117
	}
118
	healthOverrides := lua.ResourceHealthOverrides(resourceOverrides)
119

120
	pendingDeletionCount := 0
121
	aggregatedHealth := health.HealthStatusHealthy
122
	var hooks []*unstructured.Unstructured
123
	for _, obj := range liveObjs {
124
		if !isPostDeleteHook(obj) {
125
			continue
126
		}
127
		hookHealth, err := health.GetResourceHealth(obj, healthOverrides)
128
		if err != nil {
129
			return false, err
130
		}
131
		if health.IsWorse(aggregatedHealth, hookHealth.Status) {
132
			aggregatedHealth = hookHealth.Status
133
		}
134
		hooks = append(hooks, obj)
135
	}
136

137
	for _, obj := range hooks {
138
		for _, policy := range hook.DeletePolicies(obj) {
139
			if policy == common.HookDeletePolicyHookFailed && aggregatedHealth == health.HealthStatusDegraded || policy == common.HookDeletePolicyHookSucceeded && aggregatedHealth == health.HealthStatusHealthy {
140
				pendingDeletionCount++
141
				if obj.GetDeletionTimestamp() != nil {
142
					continue
143
				}
144
				logCtx.Infof("Deleting post-delete hook %s/%s", obj.GetNamespace(), obj.GetName())
145
				err = ctrl.kubectl.DeleteResource(context.Background(), config, obj.GroupVersionKind(), obj.GetName(), obj.GetNamespace(), v1.DeleteOptions{})
146
				if err != nil {
147
					return false, err
148
				}
149
			}
150
		}
151

152
	}
153
	if pendingDeletionCount > 0 {
154
		logCtx.Infof("Waiting for %d post-delete hooks to be deleted", pendingDeletionCount)
155
		return false, nil
156
	}
157
	return true, nil
158
}
159

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.