Skip to content

Commit eaeadc3

Browse files
authored
add flexibility around use of post-renderer (#195)
1 parent 891a88b commit eaeadc3

File tree

9 files changed

+407
-197
lines changed

9 files changed

+407
-197
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ jobs:
7676
- name: Set up Go
7777
uses: actions/setup-go@v3
7878
with:
79-
go-version: ~1.17
79+
go-version: ~1.18
8080
id: go
8181

8282
- name: Check out code into the Go module directory

.github/workflows/deploy.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ jobs:
2828
- name: Install Go
2929
uses: actions/setup-go@v3
3030
with:
31-
go-version: ~1.17
31+
go-version: ~1.18
3232

3333
- name: Create release
3434
run: |

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Build the manager binary
2-
FROM --platform=$BUILDPLATFORM golang:1.17 as builder
2+
FROM --platform=$BUILDPLATFORM golang:1.18 as builder
33
ARG TARGETOS
44
ARG TARGETARCH
55

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/operator-framework/helm-operator-plugins
22

3-
go 1.17
3+
go 1.18
44

55
require (
66
github.com/blang/semver/v4 v4.0.0

go.sum

Lines changed: 0 additions & 83 deletions
Large diffs are not rendered by default.

pkg/client/actionclient.go

Lines changed: 21 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -22,30 +22,21 @@ import (
2222
"errors"
2323
"fmt"
2424

25-
sdkhandler "github.com/operator-framework/operator-lib/handler"
2625
"gomodules.xyz/jsonpatch/v2"
2726
"helm.sh/helm/v3/pkg/action"
2827
"helm.sh/helm/v3/pkg/chart"
29-
"helm.sh/helm/v3/pkg/kube"
3028
helmkube "helm.sh/helm/v3/pkg/kube"
31-
"helm.sh/helm/v3/pkg/postrender"
3229
"helm.sh/helm/v3/pkg/release"
3330
"helm.sh/helm/v3/pkg/storage/driver"
3431
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
3532
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
3633
apierrors "k8s.io/apimachinery/pkg/api/errors"
37-
"k8s.io/apimachinery/pkg/api/meta"
3834
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
39-
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
4035
"k8s.io/apimachinery/pkg/runtime"
4136
apitypes "k8s.io/apimachinery/pkg/types"
4237
"k8s.io/apimachinery/pkg/util/strategicpatch"
4338
"k8s.io/cli-runtime/pkg/resource"
4439
"sigs.k8s.io/controller-runtime/pkg/client"
45-
"sigs.k8s.io/yaml"
46-
47-
"github.com/operator-framework/helm-operator-plugins/internal/sdk/controllerutil"
48-
"github.com/operator-framework/helm-operator-plugins/pkg/manifestutil"
4940
)
5041

5142
type ActionClientGetter interface {
@@ -90,20 +81,28 @@ func (hcg *actionClientGetter) ActionClientFor(obj client.Object) (ActionInterfa
9081
if err != nil {
9182
return nil, err
9283
}
93-
postRenderer := createPostRenderer(rm, actionConfig.KubeClient, obj)
94-
return &actionClient{actionConfig, postRenderer}, nil
84+
postRenderer := DefaultPostRendererFunc(rm, actionConfig.KubeClient, obj)
85+
return &actionClient{
86+
conf: actionConfig,
87+
defaultInstallOpts: []InstallOption{WithInstallPostRenderer(postRenderer)},
88+
defaultUpgradeOpts: []UpgradeOption{WithUpgradePostRenderer(postRenderer)},
89+
}, nil
9590
}
9691

9792
type actionClient struct {
98-
conf *action.Configuration
99-
postRenderer postrender.PostRenderer
93+
conf *action.Configuration
94+
95+
defaultGetOpts []GetOption
96+
defaultInstallOpts []InstallOption
97+
defaultUpgradeOpts []UpgradeOption
98+
defaultUninstallOpts []UninstallOption
10099
}
101100

102101
var _ ActionInterface = &actionClient{}
103102

104103
func (c *actionClient) Get(name string, opts ...GetOption) (*release.Release, error) {
105104
get := action.NewGet(c.conf)
106-
for _, o := range opts {
105+
for _, o := range concat(c.defaultGetOpts, opts...) {
107106
if err := o(get); err != nil {
108107
return nil, err
109108
}
@@ -113,8 +112,7 @@ func (c *actionClient) Get(name string, opts ...GetOption) (*release.Release, er
113112

114113
func (c *actionClient) Install(name, namespace string, chrt *chart.Chart, vals map[string]interface{}, opts ...InstallOption) (*release.Release, error) {
115114
install := action.NewInstall(c.conf)
116-
install.PostRenderer = c.postRenderer
117-
for _, o := range opts {
115+
for _, o := range concat(c.defaultInstallOpts, opts...) {
118116
if err := o(install); err != nil {
119117
return nil, err
120118
}
@@ -151,8 +149,7 @@ func (c *actionClient) Install(name, namespace string, chrt *chart.Chart, vals m
151149

152150
func (c *actionClient) Upgrade(name, namespace string, chrt *chart.Chart, vals map[string]interface{}, opts ...UpgradeOption) (*release.Release, error) {
153151
upgrade := action.NewUpgrade(c.conf)
154-
upgrade.PostRenderer = c.postRenderer
155-
for _, o := range opts {
152+
for _, o := range concat(c.defaultUpgradeOpts, opts...) {
156153
if err := o(upgrade); err != nil {
157154
return nil, err
158155
}
@@ -182,7 +179,7 @@ func (c *actionClient) Upgrade(name, namespace string, chrt *chart.Chart, vals m
182179

183180
func (c *actionClient) Uninstall(name string, opts ...UninstallOption) (*release.UninstallReleaseResponse, error) {
184181
uninstall := action.NewUninstall(c.conf)
185-
for _, o := range opts {
182+
for _, o := range concat(c.defaultUninstallOpts, opts...) {
186183
if err := o(uninstall); err != nil {
187184
return nil, err
188185
}
@@ -305,56 +302,9 @@ func createJSONMergePatch(existingJSON, expectedJSON []byte) ([]byte, error) {
305302
return json.Marshal(patchOps)
306303
}
307304

308-
func createPostRenderer(rm meta.RESTMapper, kubeClient kube.Interface, owner client.Object) postrender.PostRenderer {
309-
return &ownerPostRenderer{rm, kubeClient, owner}
310-
}
311-
312-
type ownerPostRenderer struct {
313-
rm meta.RESTMapper
314-
kubeClient kube.Interface
315-
owner client.Object
316-
}
317-
318-
func (pr *ownerPostRenderer) Run(in *bytes.Buffer) (*bytes.Buffer, error) {
319-
resourceList, err := pr.kubeClient.Build(in, false)
320-
if err != nil {
321-
return nil, err
322-
}
323-
out := bytes.Buffer{}
324-
325-
err = resourceList.Visit(func(r *resource.Info, err error) error {
326-
if err != nil {
327-
return err
328-
}
329-
objMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(r.Object)
330-
if err != nil {
331-
return err
332-
}
333-
u := &unstructured.Unstructured{Object: objMap}
334-
useOwnerRef, err := controllerutil.SupportsOwnerReference(pr.rm, pr.owner, u)
335-
if err != nil {
336-
return err
337-
}
338-
if useOwnerRef && !manifestutil.HasResourcePolicyKeep(u.GetAnnotations()) {
339-
ownerRef := metav1.NewControllerRef(pr.owner, pr.owner.GetObjectKind().GroupVersionKind())
340-
ownerRefs := append(u.GetOwnerReferences(), *ownerRef)
341-
u.SetOwnerReferences(ownerRefs)
342-
} else {
343-
if err := sdkhandler.SetOwnerAnnotations(pr.owner, u); err != nil {
344-
return err
345-
}
346-
}
347-
outData, err := yaml.Marshal(u.Object)
348-
if err != nil {
349-
return err
350-
}
351-
if _, err := out.WriteString("---\n" + string(outData)); err != nil {
352-
return err
353-
}
354-
return nil
355-
})
356-
if err != nil {
357-
return nil, err
358-
}
359-
return &out, nil
305+
func concat[T any](s1 []T, s2 ...T) []T {
306+
out := make([]T, 0, len(s1)+len(s2))
307+
out = append(out, s1...)
308+
out = append(out, s2...)
309+
return out
360310
}

pkg/client/actionclient_test.go

Lines changed: 21 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package client
1818

1919
import (
20-
"bytes"
2120
"context"
2221
"errors"
2322
"strconv"
@@ -27,7 +26,6 @@ import (
2726
. "github.com/onsi/gomega"
2827
"helm.sh/helm/v3/pkg/action"
2928
"helm.sh/helm/v3/pkg/chartutil"
30-
"helm.sh/helm/v3/pkg/kube"
3129
"helm.sh/helm/v3/pkg/release"
3230
"helm.sh/helm/v3/pkg/releaseutil"
3331
"helm.sh/helm/v3/pkg/storage/driver"
@@ -40,6 +38,7 @@ import (
4038
"k8s.io/apimachinery/pkg/runtime/schema"
4139
apitypes "k8s.io/apimachinery/pkg/types"
4240
"k8s.io/cli-runtime/pkg/resource"
41+
"k8s.io/utils/pointer"
4342
"sigs.k8s.io/controller-runtime/pkg/client"
4443
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
4544
"sigs.k8s.io/yaml"
@@ -141,7 +140,7 @@ var _ = Describe("ActionClient", func() {
141140
Expect(err).To(BeNil())
142141
Expect(rel).NotTo(BeNil())
143142
})
144-
verifyRelease(cl, obj.GetNamespace(), rel)
143+
verifyRelease(cl, obj, rel)
145144
})
146145
It("should uninstall a failed install", func() {
147146
By("failing to install the release", func() {
@@ -209,7 +208,7 @@ var _ = Describe("ActionClient", func() {
209208
Expect(err).To(BeNil())
210209
Expect(rel).NotTo(BeNil())
211210
})
212-
verifyRelease(cl, obj.GetNamespace(), rel)
211+
verifyRelease(cl, obj, rel)
213212
})
214213
When("using an option function that returns an error", func() {
215214
It("should fail", func() {
@@ -253,7 +252,7 @@ var _ = Describe("ActionClient", func() {
253252
Expect(err).To(BeNil())
254253
Expect(rel).NotTo(BeNil())
255254
})
256-
verifyRelease(cl, obj.GetNamespace(), rel)
255+
verifyRelease(cl, obj, rel)
257256
})
258257
It("should rollback a failed upgrade", func() {
259258
By("failing to install the release", func() {
@@ -265,7 +264,7 @@ var _ = Describe("ActionClient", func() {
265264
tmp := *installedRelease
266265
rollbackRelease := &tmp
267266
rollbackRelease.Version = installedRelease.Version + 2
268-
verifyRelease(cl, obj.GetNamespace(), rollbackRelease)
267+
verifyRelease(cl, obj, rollbackRelease)
269268
})
270269
When("using an option function that returns an error", func() {
271270
It("should fail", func() {
@@ -305,7 +304,7 @@ var _ = Describe("ActionClient", func() {
305304
err := ac.Reconcile(installedRelease)
306305
Expect(err).To(BeNil())
307306
})
308-
verifyRelease(cl, obj.GetNamespace(), installedRelease)
307+
verifyRelease(cl, obj, installedRelease)
309308
})
310309
It("should re-create deleted resources", func() {
311310
By("deleting the manifest resources", func() {
@@ -319,7 +318,7 @@ var _ = Describe("ActionClient", func() {
319318
err := ac.Reconcile(installedRelease)
320319
Expect(err).To(BeNil())
321320
})
322-
verifyRelease(cl, obj.GetNamespace(), installedRelease)
321+
verifyRelease(cl, obj, installedRelease)
323322
})
324323
It("should patch changed resources", func() {
325324
By("changing manifest resources", func() {
@@ -344,7 +343,7 @@ var _ = Describe("ActionClient", func() {
344343
err := ac.Reconcile(installedRelease)
345344
Expect(err).To(BeNil())
346345
})
347-
verifyRelease(cl, obj.GetNamespace(), installedRelease)
346+
verifyRelease(cl, obj, installedRelease)
348347
})
349348
})
350349
})
@@ -516,34 +515,6 @@ var _ = Describe("ActionClient", func() {
516515
Expect(patchType).To(Equal(apitypes.StrategicMergePatchType))
517516
})
518517
})
519-
520-
var _ = Describe("ownerPostRenderer", func() {
521-
var (
522-
pr ownerPostRenderer
523-
owner client.Object
524-
)
525-
526-
BeforeEach(func() {
527-
rm, err := apiutil.NewDynamicRESTMapper(cfg)
528-
Expect(err).To(BeNil())
529-
530-
owner = newTestUnstructured([]interface{}{
531-
map[string]interface{}{
532-
"name": "test1",
533-
},
534-
})
535-
pr = ownerPostRenderer{
536-
owner: owner,
537-
rm: rm,
538-
kubeClient: kube.New(newRESTClientGetter(cfg, rm, owner.GetNamespace())),
539-
}
540-
})
541-
542-
It("fails on invalid input", func() {
543-
_, err := pr.Run(bytes.NewBufferString("test"))
544-
Expect(err).NotTo(BeNil())
545-
})
546-
})
547518
})
548519

549520
func manifestToObjects(manifest string) []client.Object {
@@ -557,10 +528,10 @@ func manifestToObjects(manifest string) []client.Object {
557528
return objs
558529
}
559530

560-
func verifyRelease(cl client.Client, ns string, rel *release.Release) {
531+
func verifyRelease(cl client.Client, owner client.Object, rel *release.Release) {
561532
By("verifying release secret exists at release version", func() {
562533
releaseSecrets := &v1.SecretList{}
563-
err := cl.List(context.TODO(), releaseSecrets, client.InNamespace(ns), client.MatchingLabels{"owner": "helm", "name": rel.Name})
534+
err := cl.List(context.TODO(), releaseSecrets, client.InNamespace(owner.GetNamespace()), client.MatchingLabels{"owner": "helm", "name": rel.Name})
564535
Expect(err).To(BeNil())
565536
Expect(releaseSecrets.Items).To(HaveLen(rel.Version))
566537
Expect(releaseSecrets.Items[rel.Version-1].Type).To(Equal(v1.SecretType("helm.sh/release.v1")))
@@ -578,6 +549,17 @@ func verifyRelease(cl client.Client, ns string, rel *release.Release) {
578549
key := client.ObjectKeyFromObject(obj)
579550
err := cl.Get(context.TODO(), key, obj)
580551
Expect(err).To(BeNil())
552+
Expect(obj.GetOwnerReferences()).To(HaveLen(1))
553+
Expect(obj.GetOwnerReferences()[0]).To(Equal(
554+
metav1.OwnerReference{
555+
APIVersion: owner.GetObjectKind().GroupVersionKind().GroupVersion().String(),
556+
Kind: owner.GetObjectKind().GroupVersionKind().Kind,
557+
Name: owner.GetName(),
558+
UID: owner.GetUID(),
559+
Controller: pointer.Bool(true),
560+
BlockOwnerDeletion: pointer.Bool(true),
561+
}),
562+
)
581563
}
582564
})
583565
}

0 commit comments

Comments
 (0)