Skip to content

Commit 75bb03d

Browse files
authored
(bugfix): rewrite the contentmanager implementation (#1119)
to fix bugs associated with insufficient permissions resulting in halting reconciliation of all ClusterExtension and informer sync errors not being reported via the ClusterExtension status conditions. Signed-off-by: everettraven <[email protected]>
1 parent c53453b commit 75bb03d

16 files changed

+1415
-430
lines changed

Diff for: api/v1alpha1/clusterextension_types.go

+5
Original file line numberDiff line numberDiff line change
@@ -414,6 +414,7 @@ const (
414414
// TODO(user): add more Types, here and into init()
415415
TypeInstalled = "Installed"
416416
TypeResolved = "Resolved"
417+
TypeHealthy = "Healthy"
417418

418419
// TypeDeprecated is a rollup condition that is present when
419420
// any of the deprecated conditions are present.
@@ -438,6 +439,8 @@ const (
438439

439440
ReasonErrorGettingReleaseState = "ErrorGettingReleaseState"
440441

442+
ReasonUnverifiable = "Unverifiable"
443+
441444
CRDUpgradeSafetyPolicyEnabled CRDUpgradeSafetyPolicy = "Enabled"
442445
CRDUpgradeSafetyPolicyDisabled CRDUpgradeSafetyPolicy = "Disabled"
443446
)
@@ -452,6 +455,7 @@ func init() {
452455
TypeChannelDeprecated,
453456
TypeBundleDeprecated,
454457
TypeUnpacked,
458+
TypeHealthy,
455459
)
456460
// TODO(user): add Reasons from above
457461
conditionsets.ConditionReasons = append(conditionsets.ConditionReasons,
@@ -465,6 +469,7 @@ func init() {
465469
ReasonUnpackSuccess,
466470
ReasonUnpackFailed,
467471
ReasonErrorGettingReleaseState,
472+
ReasonUnverifiable,
468473
)
469474
}
470475

Diff for: cmd/manager/main.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -249,14 +249,25 @@ func main() {
249249
Preflights: preflights,
250250
}
251251

252+
cm := contentmanager.NewManager(clientRestConfigMapper, mgr.GetConfig(), mgr.GetRESTMapper())
253+
err = clusterExtensionFinalizers.Register(controllers.ClusterExtensionCleanupContentManagerCacheFinalizer, finalizerFunc(func(ctx context.Context, obj client.Object) (crfinalizer.Result, error) {
254+
ext := obj.(*ocv1alpha1.ClusterExtension)
255+
err := cm.Delete(ext)
256+
return crfinalizer.Result{}, err
257+
}))
258+
if err != nil {
259+
setupLog.Error(err, "unable to register content manager cleanup finalizer")
260+
os.Exit(1)
261+
}
262+
252263
if err = (&controllers.ClusterExtensionReconciler{
253264
Client: cl,
254265
Resolver: resolver,
255266
Unpacker: unpacker,
256267
Applier: applier,
257268
InstalledBundleGetter: &controllers.DefaultInstalledBundleGetter{ActionClientGetter: acg},
258269
Finalizers: clusterExtensionFinalizers,
259-
Watcher: contentmanager.New(clientRestConfigMapper, mgr.GetConfig(), mgr.GetRESTMapper()),
270+
Manager: cm,
260271
}).SetupWithManager(mgr); err != nil {
261272
setupLog.Error(err, "unable to create controller", "controller", "ClusterExtension")
262273
os.Exit(1)

Diff for: config/samples/olm_v1alpha1_clusterextension.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,10 @@ rules:
3636
# Manage ArgoCD CRDs
3737
- apiGroups: [apiextensions.k8s.io]
3838
resources: [customresourcedefinitions]
39-
verbs: [create]
39+
verbs: [create, list, watch]
4040
- apiGroups: [apiextensions.k8s.io]
4141
resources: [customresourcedefinitions]
42-
verbs: [get, list, watch, update, patch, delete]
42+
verbs: [get, update, patch, delete]
4343
resourceNames:
4444
- appprojects.argoproj.io
4545
- argocds.argoproj.io

Diff for: internal/applier/helm.go

+48-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
package applier
22

33
import (
4+
"bytes"
45
"context"
56
"errors"
67
"fmt"
8+
"io"
79
"io/fs"
810
"strings"
911

1012
"helm.sh/helm/v3/pkg/action"
1113
"helm.sh/helm/v3/pkg/chart"
1214
"helm.sh/helm/v3/pkg/chartutil"
15+
"helm.sh/helm/v3/pkg/postrender"
1316
"helm.sh/helm/v3/pkg/release"
1417
"helm.sh/helm/v3/pkg/storage/driver"
1518
corev1 "k8s.io/api/core/v1"
19+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
20+
apimachyaml "k8s.io/apimachinery/pkg/util/yaml"
1621
"sigs.k8s.io/controller-runtime/pkg/client"
1722

1823
helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
@@ -51,7 +56,7 @@ type Helm struct {
5156
Preflights []Preflight
5257
}
5358

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) {
5560
chrt, err := convert.RegistryV1ToHelmChart(ctx, contentFS, ext.Spec.Install.Namespace, []string{corev1.NamespaceAll})
5661
if err != nil {
5762
return nil, "", err
@@ -63,7 +68,11 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
6368
return nil, "", err
6469
}
6570

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)
6776
if err != nil {
6877
return nil, "", err
6978
}
@@ -94,18 +103,18 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
94103
case StateNeedsInstall:
95104
rel, err = ac.Install(ext.GetName(), ext.Spec.Install.Namespace, chrt, values, func(install *action.Install) error {
96105
install.CreateNamespace = false
97-
install.Labels = labels
106+
install.Labels = storageLabels
98107
return nil
99-
})
108+
}, helmclient.AppendInstallPostRenderer(post))
100109
if err != nil {
101110
return nil, state, err
102111
}
103112
case StateNeedsUpgrade:
104113
rel, err = ac.Upgrade(ext.GetName(), ext.Spec.Install.Namespace, chrt, values, func(upgrade *action.Upgrade) error {
105114
upgrade.MaxHistory = maxHelmReleaseHistory
106-
upgrade.Labels = labels
115+
upgrade.Labels = storageLabels
107116
return nil
108-
})
117+
}, helmclient.AppendUpgradePostRenderer(post))
109118
if err != nil {
110119
return nil, state, err
111120
}
@@ -125,7 +134,7 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1alpha1.Clust
125134
return relObjects, state, nil
126135
}
127136

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) {
129138
currentRelease, err := cl.Get(ext.GetName())
130139
if err != nil && !errors.Is(err, driver.ErrReleaseNotFound) {
131140
return nil, nil, StateError, err
@@ -138,9 +147,8 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1alpha1.Cl
138147
desiredRelease, err := cl.Install(ext.GetName(), ext.Spec.Install.Namespace, chrt, values, func(i *action.Install) error {
139148
i.DryRun = true
140149
i.DryRunOption = "server"
141-
i.Labels = labels
142150
return nil
143-
})
151+
}, helmclient.AppendInstallPostRenderer(post))
144152
if err != nil {
145153
return nil, nil, StateError, err
146154
}
@@ -150,9 +158,8 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1alpha1.Cl
150158
upgrade.MaxHistory = maxHelmReleaseHistory
151159
upgrade.DryRun = true
152160
upgrade.DryRunOption = "server"
153-
upgrade.Labels = labels
154161
return nil
155-
})
162+
}, helmclient.AppendUpgradePostRenderer(post))
156163
if err != nil {
157164
return currentRelease, nil, StateError, err
158165
}
@@ -164,3 +171,33 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1alpha1.Cl
164171
}
165172
return currentRelease, desiredRelease, relState, nil
166173
}
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

Comments
 (0)