...
1
15
16 package action
17
18 import (
19 "bytes"
20 "sort"
21 "time"
22
23 "github.com/pkg/errors"
24
25 "helm.sh/helm/v3/pkg/kube"
26 "helm.sh/helm/v3/pkg/release"
27 helmtime "helm.sh/helm/v3/pkg/time"
28 )
29
30
31 func (cfg *Configuration) execHook(rl *release.Release, hook release.HookEvent, timeout time.Duration) error {
32 executingHooks := []*release.Hook{}
33
34 for _, h := range rl.Hooks {
35 for _, e := range h.Events {
36 if e == hook {
37 executingHooks = append(executingHooks, h)
38 }
39 }
40 }
41
42
43 sort.Stable(hookByWeight(executingHooks))
44
45 for _, h := range executingHooks {
46
47 if h.DeletePolicies == nil || len(h.DeletePolicies) == 0 {
48
49
50
51
52 h.DeletePolicies = []release.HookDeletePolicy{release.HookBeforeHookCreation}
53 }
54
55 if err := cfg.deleteHookByPolicy(h, release.HookBeforeHookCreation, timeout); err != nil {
56 return err
57 }
58
59 resources, err := cfg.KubeClient.Build(bytes.NewBufferString(h.Manifest), true)
60 if err != nil {
61 return errors.Wrapf(err, "unable to build kubernetes object for %s hook %s", hook, h.Path)
62 }
63
64
65 h.LastRun = release.HookExecution{
66 StartedAt: helmtime.Now(),
67 Phase: release.HookPhaseRunning,
68 }
69 cfg.recordRelease(rl)
70
71
72
73
74 h.LastRun.Phase = release.HookPhaseUnknown
75
76
77 if _, err := cfg.KubeClient.Create(resources); err != nil {
78 h.LastRun.CompletedAt = helmtime.Now()
79 h.LastRun.Phase = release.HookPhaseFailed
80 return errors.Wrapf(err, "warning: Hook %s %s failed", hook, h.Path)
81 }
82
83
84 err = cfg.KubeClient.WatchUntilReady(resources, timeout)
85
86 h.LastRun.CompletedAt = helmtime.Now()
87
88 if err != nil {
89 h.LastRun.Phase = release.HookPhaseFailed
90
91
92 if err := cfg.deleteHookByPolicy(h, release.HookFailed, timeout); err != nil {
93 return err
94 }
95 return err
96 }
97 h.LastRun.Phase = release.HookPhaseSucceeded
98 }
99
100
101
102 for _, h := range executingHooks {
103 if err := cfg.deleteHookByPolicy(h, release.HookSucceeded, timeout); err != nil {
104 return err
105 }
106 }
107
108 return nil
109 }
110
111
112 type hookByWeight []*release.Hook
113
114 func (x hookByWeight) Len() int { return len(x) }
115 func (x hookByWeight) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
116 func (x hookByWeight) Less(i, j int) bool {
117 if x[i].Weight == x[j].Weight {
118 return x[i].Name < x[j].Name
119 }
120 return x[i].Weight < x[j].Weight
121 }
122
123
124 func (cfg *Configuration) deleteHookByPolicy(h *release.Hook, policy release.HookDeletePolicy, timeout time.Duration) error {
125
126
127 if h.Kind == "CustomResourceDefinition" {
128 return nil
129 }
130 if hookHasDeletePolicy(h, policy) {
131 resources, err := cfg.KubeClient.Build(bytes.NewBufferString(h.Manifest), false)
132 if err != nil {
133 return errors.Wrapf(err, "unable to build kubernetes object for deleting hook %s", h.Path)
134 }
135 _, errs := cfg.KubeClient.Delete(resources)
136 if len(errs) > 0 {
137 return errors.New(joinErrors(errs))
138 }
139
140
141 if kubeClient, ok := cfg.KubeClient.(kube.InterfaceExt); ok {
142 if err := kubeClient.WaitForDelete(resources, timeout); err != nil {
143 return err
144 }
145 }
146 }
147 return nil
148 }
149
150
151
152 func hookHasDeletePolicy(h *release.Hook, policy release.HookDeletePolicy) bool {
153 for _, v := range h.DeletePolicies {
154 if policy == v {
155 return true
156 }
157 }
158 return false
159 }
160
View as plain text