1
1
package applier
2
2
3
3
import (
4
+ "bytes"
4
5
"context"
5
6
"errors"
6
7
"fmt"
8
+ "io"
7
9
"io/fs"
8
10
"strings"
9
11
10
12
"helm.sh/helm/v3/pkg/action"
11
13
"helm.sh/helm/v3/pkg/chart"
12
14
"helm.sh/helm/v3/pkg/chartutil"
15
+ "helm.sh/helm/v3/pkg/postrender"
13
16
"helm.sh/helm/v3/pkg/release"
14
17
"helm.sh/helm/v3/pkg/storage/driver"
15
18
corev1 "k8s.io/api/core/v1"
19
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
20
+ apimachyaml "k8s.io/apimachinery/pkg/util/yaml"
16
21
"sigs.k8s.io/controller-runtime/pkg/client"
17
22
18
23
helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
@@ -51,7 +56,7 @@ type Helm struct {
51
56
Preflights []Preflight
52
57
}
53
58
54
- func (h * Helm ) Apply (ctx context.Context , contentFS fs.FS , ext * ocv1alpha1.ClusterExtension , labels map [string ]string ) ([]client.Object , string , error ) {
59
+ func (h * Helm ) Apply (ctx context.Context , contentFS fs.FS , ext * ocv1alpha1.ClusterExtension , objectLabels map [ string ] string , storageLabels map [string ]string ) ([]client.Object , string , error ) {
55
60
chrt , err := convert .RegistryV1ToHelmChart (ctx , contentFS , ext .Spec .Install .Namespace , []string {corev1 .NamespaceAll })
56
61
if err != nil {
57
62
return nil , "" , err
@@ -63,7 +68,11 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
63
68
return nil , "" , err
64
69
}
65
70
66
- rel , desiredRel , state , err := h .getReleaseState (ac , ext , chrt , values , labels )
71
+ post := & postrenderer {
72
+ labels : objectLabels ,
73
+ }
74
+
75
+ rel , desiredRel , state , err := h .getReleaseState (ac , ext , chrt , values , post )
67
76
if err != nil {
68
77
return nil , "" , err
69
78
}
@@ -94,18 +103,18 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
94
103
case StateNeedsInstall :
95
104
rel , err = ac .Install (ext .GetName (), ext .Spec .Install .Namespace , chrt , values , func (install * action.Install ) error {
96
105
install .CreateNamespace = false
97
- install .Labels = labels
106
+ install .Labels = storageLabels
98
107
return nil
99
- })
108
+ }, helmclient . AppendInstallPostRenderer ( post ) )
100
109
if err != nil {
101
110
return nil , state , err
102
111
}
103
112
case StateNeedsUpgrade :
104
113
rel , err = ac .Upgrade (ext .GetName (), ext .Spec .Install .Namespace , chrt , values , func (upgrade * action.Upgrade ) error {
105
114
upgrade .MaxHistory = maxHelmReleaseHistory
106
- upgrade .Labels = labels
115
+ upgrade .Labels = storageLabels
107
116
return nil
108
- })
117
+ }, helmclient . AppendUpgradePostRenderer ( post ) )
109
118
if err != nil {
110
119
return nil , state , err
111
120
}
@@ -125,7 +134,7 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
125
134
return relObjects , state , nil
126
135
}
127
136
128
- func (h * Helm ) getReleaseState (cl helmclient.ActionInterface , ext * ocv1alpha1.ClusterExtension , chrt * chart.Chart , values chartutil.Values , labels map [ string ] string ) (* release.Release , * release.Release , string , error ) {
137
+ func (h * Helm ) getReleaseState (cl helmclient.ActionInterface , ext * ocv1alpha1.ClusterExtension , chrt * chart.Chart , values chartutil.Values , post postrender. PostRenderer ) (* release.Release , * release.Release , string , error ) {
129
138
currentRelease , err := cl .Get (ext .GetName ())
130
139
if err != nil && ! errors .Is (err , driver .ErrReleaseNotFound ) {
131
140
return nil , nil , StateError , err
@@ -138,9 +147,8 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1alpha1.Cl
138
147
desiredRelease , err := cl .Install (ext .GetName (), ext .Spec .Install .Namespace , chrt , values , func (i * action.Install ) error {
139
148
i .DryRun = true
140
149
i .DryRunOption = "server"
141
- i .Labels = labels
142
150
return nil
143
- })
151
+ }, helmclient . AppendInstallPostRenderer ( post ) )
144
152
if err != nil {
145
153
return nil , nil , StateError , err
146
154
}
@@ -150,9 +158,8 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1alpha1.Cl
150
158
upgrade .MaxHistory = maxHelmReleaseHistory
151
159
upgrade .DryRun = true
152
160
upgrade .DryRunOption = "server"
153
- upgrade .Labels = labels
154
161
return nil
155
- })
162
+ }, helmclient . AppendUpgradePostRenderer ( post ) )
156
163
if err != nil {
157
164
return currentRelease , nil , StateError , err
158
165
}
@@ -164,3 +171,33 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1alpha1.Cl
164
171
}
165
172
return currentRelease , desiredRelease , relState , nil
166
173
}
174
+
175
+ type postrenderer struct {
176
+ labels map [string ]string
177
+ cascade postrender.PostRenderer
178
+ }
179
+
180
+ func (p * postrenderer ) Run (renderedManifests * bytes.Buffer ) (* bytes.Buffer , error ) {
181
+ var buf bytes.Buffer
182
+ dec := apimachyaml .NewYAMLOrJSONDecoder (renderedManifests , 1024 )
183
+ for {
184
+ obj := unstructured.Unstructured {}
185
+ err := dec .Decode (& obj )
186
+ if errors .Is (err , io .EOF ) {
187
+ break
188
+ }
189
+ if err != nil {
190
+ return nil , err
191
+ }
192
+ obj .SetLabels (util .MergeMaps (obj .GetLabels (), p .labels ))
193
+ b , err := obj .MarshalJSON ()
194
+ if err != nil {
195
+ return nil , err
196
+ }
197
+ buf .Write (b )
198
+ }
199
+ if p .cascade != nil {
200
+ return p .cascade .Run (& buf )
201
+ }
202
+ return & buf , nil
203
+ }
0 commit comments