@@ -18,7 +18,7 @@ package runner
18
18
19
19
import (
20
20
"errors"
21
- "fmt "
21
+ "sync "
22
22
23
23
"github.com/go-logr/logr"
24
24
"helm.sh/helm/v3/pkg/action"
@@ -32,21 +32,39 @@ import (
32
32
v2 "github.com/fluxcd/helm-controller/api/v2beta1"
33
33
)
34
34
35
+ type ActionError struct {
36
+ Err error
37
+ CapturedLogs string
38
+ }
39
+
40
+ func (e ActionError ) Error () string {
41
+ return e .Err .Error ()
42
+ }
43
+
44
+ func (e ActionError ) Unwrap () error {
45
+ return e .Err
46
+ }
47
+
35
48
// Runner represents a Helm action runner capable of performing Helm
36
49
// operations for a v2beta1.HelmRelease.
37
50
type Runner struct {
38
- config * action.Configuration
51
+ mu sync.Mutex
52
+ config * action.Configuration
53
+ logBuffer * LogBuffer
39
54
}
40
55
41
56
// NewRunner constructs a new Runner configured to run Helm actions with the
42
57
// given genericclioptions.RESTClientGetter, and the release and storage
43
58
// namespace configured to the provided values.
44
59
func NewRunner (getter genericclioptions.RESTClientGetter , storageNamespace string , logger logr.Logger ) (* Runner , error ) {
45
- cfg := new (action.Configuration )
46
- if err := cfg .Init (getter , storageNamespace , "secret" , debugLogger (logger )); err != nil {
60
+ runner := & Runner {
61
+ logBuffer : NewLogBuffer (NewDebugLog (logger ).Log , 0 ),
62
+ }
63
+ runner .config = new (action.Configuration )
64
+ if err := runner .config .Init (getter , storageNamespace , "secret" , runner .logBuffer .Log ); err != nil {
47
65
return nil , err
48
66
}
49
- return & Runner { config : cfg } , nil
67
+ return runner , nil
50
68
}
51
69
52
70
// Create post renderer instances from HelmRelease and combine them into
@@ -67,6 +85,10 @@ func postRenderers(hr v2.HelmRelease) (postrender.PostRenderer, error) {
67
85
68
86
// Install runs an Helm install action for the given v2beta1.HelmRelease.
69
87
func (r * Runner ) Install (hr v2.HelmRelease , chart * chart.Chart , values chartutil.Values ) (* release.Release , error ) {
88
+ r .mu .Lock ()
89
+ defer r .mu .Unlock ()
90
+ defer r .logBuffer .Reset ()
91
+
70
92
install := action .NewInstall (r .config )
71
93
install .ReleaseName = hr .GetReleaseName ()
72
94
install .Namespace = hr .GetReleaseNamespace ()
@@ -86,11 +108,16 @@ func (r *Runner) Install(hr v2.HelmRelease, chart *chart.Chart, values chartutil
86
108
install .CreateNamespace = hr .Spec .GetInstall ().CreateNamespace
87
109
}
88
110
89
- return install .Run (chart , values .AsMap ())
111
+ rel , err := install .Run (chart , values .AsMap ())
112
+ return rel , wrapActionErr (r .logBuffer , err )
90
113
}
91
114
92
115
// Upgrade runs an Helm upgrade action for the given v2beta1.HelmRelease.
93
116
func (r * Runner ) Upgrade (hr v2.HelmRelease , chart * chart.Chart , values chartutil.Values ) (* release.Release , error ) {
117
+ r .mu .Lock ()
118
+ defer r .mu .Unlock ()
119
+ defer r .logBuffer .Reset ()
120
+
94
121
upgrade := action .NewUpgrade (r .config )
95
122
upgrade .Namespace = hr .GetReleaseNamespace ()
96
123
upgrade .ResetValues = ! hr .Spec .GetUpgrade ().PreserveValues
@@ -108,20 +135,30 @@ func (r *Runner) Upgrade(hr v2.HelmRelease, chart *chart.Chart, values chartutil
108
135
}
109
136
upgrade .PostRenderer = renderer
110
137
111
- return upgrade .Run (hr .GetReleaseName (), chart , values .AsMap ())
138
+ rel , err := upgrade .Run (hr .GetReleaseName (), chart , values .AsMap ())
139
+ return rel , wrapActionErr (r .logBuffer , err )
112
140
}
113
141
114
142
// Test runs an Helm test action for the given v2beta1.HelmRelease.
115
143
func (r * Runner ) Test (hr v2.HelmRelease ) (* release.Release , error ) {
144
+ r .mu .Lock ()
145
+ defer r .mu .Unlock ()
146
+ defer r .logBuffer .Reset ()
147
+
116
148
test := action .NewReleaseTesting (r .config )
117
149
test .Namespace = hr .GetReleaseNamespace ()
118
150
test .Timeout = hr .Spec .GetTest ().GetTimeout (hr .GetTimeout ()).Duration
119
151
120
- return test .Run (hr .GetReleaseName ())
152
+ rel , err := test .Run (hr .GetReleaseName ())
153
+ return rel , wrapActionErr (r .logBuffer , err )
121
154
}
122
155
123
156
// Rollback runs an Helm rollback action for the given v2beta1.HelmRelease.
124
157
func (r * Runner ) Rollback (hr v2.HelmRelease ) error {
158
+ r .mu .Lock ()
159
+ defer r .mu .Unlock ()
160
+ defer r .logBuffer .Reset ()
161
+
125
162
rollback := action .NewRollback (r .config )
126
163
rollback .Timeout = hr .Spec .GetRollback ().GetTimeout (hr .GetTimeout ()).Duration
127
164
rollback .Wait = ! hr .Spec .GetRollback ().DisableWait
@@ -130,18 +167,23 @@ func (r *Runner) Rollback(hr v2.HelmRelease) error {
130
167
rollback .Recreate = hr .Spec .GetRollback ().Recreate
131
168
rollback .CleanupOnFail = hr .Spec .GetRollback ().CleanupOnFail
132
169
133
- return rollback .Run (hr .GetReleaseName ())
170
+ err := rollback .Run (hr .GetReleaseName ())
171
+ return wrapActionErr (r .logBuffer , err )
134
172
}
135
173
136
174
// Uninstall runs an Helm uninstall action for the given v2beta1.HelmRelease.
137
175
func (r * Runner ) Uninstall (hr v2.HelmRelease ) error {
176
+ r .mu .Lock ()
177
+ defer r .mu .Unlock ()
178
+ defer r .logBuffer .Reset ()
179
+
138
180
uninstall := action .NewUninstall (r .config )
139
181
uninstall .Timeout = hr .Spec .GetUninstall ().GetTimeout (hr .GetTimeout ()).Duration
140
182
uninstall .DisableHooks = hr .Spec .GetUninstall ().DisableHooks
141
183
uninstall .KeepHistory = hr .Spec .GetUninstall ().KeepHistory
142
184
143
185
_ , err := uninstall .Run (hr .GetReleaseName ())
144
- return err
186
+ return wrapActionErr ( r . logBuffer , err )
145
187
}
146
188
147
189
// ObserveLastRelease observes the last revision, if there is one,
@@ -154,8 +196,13 @@ func (r *Runner) ObserveLastRelease(hr v2.HelmRelease) (*release.Release, error)
154
196
return rel , err
155
197
}
156
198
157
- func debugLogger (logger logr.Logger ) func (format string , v ... interface {}) {
158
- return func (format string , v ... interface {}) {
159
- logger .V (1 ).Info (fmt .Sprintf (format , v ... ))
199
+ func wrapActionErr (log * LogBuffer , err error ) error {
200
+ if err == nil {
201
+ return err
202
+ }
203
+ err = & ActionError {
204
+ Err : err ,
205
+ CapturedLogs : log .String (),
160
206
}
207
+ return err
161
208
}
0 commit comments