Skip to content

Commit 0fda80d

Browse files
authored
✨ Add feature gate for preflight permissions (#1666)
* Add feature gate for preflight permissions * Add no-op to satisfy linter Signed-off-by: Brett Tofel <[email protected]> * Make the feature gate PreAlpha Signed-off-by: Brett Tofel <[email protected]> * Make the feature gate Alpha b/c PreAlpha cannot be toggled Signed-off-by: Brett Tofel <[email protected]> --------- Signed-off-by: Brett Tofel <[email protected]>
1 parent 068fd48 commit 0fda80d

File tree

3 files changed

+80
-2
lines changed

3 files changed

+80
-2
lines changed

internal/applier/helm.go

+5
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
2525

2626
ocv1 "github.com/operator-framework/operator-controller/api/v1"
27+
"github.com/operator-framework/operator-controller/internal/features"
2728
"github.com/operator-framework/operator-controller/internal/rukpak/convert"
2829
"github.com/operator-framework/operator-controller/internal/rukpak/preflights/crdupgradesafety"
2930
"github.com/operator-framework/operator-controller/internal/rukpak/util"
@@ -160,6 +161,10 @@ func (h *Helm) getReleaseState(cl helmclient.ActionInterface, ext *ocv1.ClusterE
160161
return nil
161162
}, helmclient.AppendInstallPostRenderer(post))
162163
if err != nil {
164+
if features.OperatorControllerFeatureGate.Enabled(features.PreflightPermissions) {
165+
_ = struct{}{} // minimal no-op to satisfy linter
166+
// probably need to break out this error as it's the one for helm dry-run as opposed to any returned later
167+
}
163168
return nil, nil, StateError, err
164169
}
165170
return nil, desiredRelease, StateNeedsInstall, nil

internal/applier/helm_test.go

+67
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,14 @@ import (
1313
"helm.sh/helm/v3/pkg/chart"
1414
"helm.sh/helm/v3/pkg/release"
1515
"helm.sh/helm/v3/pkg/storage/driver"
16+
featuregatetesting "k8s.io/component-base/featuregate/testing"
1617
"sigs.k8s.io/controller-runtime/pkg/client"
1718

1819
helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
1920

2021
v1 "github.com/operator-framework/operator-controller/api/v1"
2122
"github.com/operator-framework/operator-controller/internal/applier"
23+
"github.com/operator-framework/operator-controller/internal/features"
2224
)
2325

2426
type mockPreflight struct {
@@ -226,6 +228,71 @@ func TestApply_Installation(t *testing.T) {
226228
})
227229
}
228230

231+
func TestApply_InstallationWithPreflightPermissionsEnabled(t *testing.T) {
232+
featuregatetesting.SetFeatureGateDuringTest(t, features.OperatorControllerFeatureGate, features.PreflightPermissions, true)
233+
234+
t.Run("fails during dry-run installation", func(t *testing.T) {
235+
mockAcg := &mockActionGetter{
236+
getClientErr: driver.ErrReleaseNotFound,
237+
dryRunInstallErr: errors.New("failed attempting to dry-run install chart"),
238+
}
239+
helmApplier := applier.Helm{ActionClientGetter: mockAcg}
240+
241+
objs, state, err := helmApplier.Apply(context.TODO(), validFS, testCE, testObjectLabels, testStorageLabels)
242+
require.Error(t, err)
243+
require.ErrorContains(t, err, "attempting to dry-run install chart")
244+
require.Nil(t, objs)
245+
require.Empty(t, state)
246+
})
247+
248+
t.Run("fails during pre-flight installation", func(t *testing.T) {
249+
mockAcg := &mockActionGetter{
250+
getClientErr: driver.ErrReleaseNotFound,
251+
installErr: errors.New("failed installing chart"),
252+
}
253+
mockPf := &mockPreflight{installErr: errors.New("failed during install pre-flight check")}
254+
helmApplier := applier.Helm{ActionClientGetter: mockAcg, Preflights: []applier.Preflight{mockPf}}
255+
256+
objs, state, err := helmApplier.Apply(context.TODO(), validFS, testCE, testObjectLabels, testStorageLabels)
257+
require.Error(t, err)
258+
require.ErrorContains(t, err, "install pre-flight check")
259+
require.Equal(t, applier.StateNeedsInstall, state)
260+
require.Nil(t, objs)
261+
})
262+
263+
t.Run("fails during installation", func(t *testing.T) {
264+
mockAcg := &mockActionGetter{
265+
getClientErr: driver.ErrReleaseNotFound,
266+
installErr: errors.New("failed installing chart"),
267+
}
268+
helmApplier := applier.Helm{ActionClientGetter: mockAcg}
269+
270+
objs, state, err := helmApplier.Apply(context.TODO(), validFS, testCE, testObjectLabels, testStorageLabels)
271+
require.Error(t, err)
272+
require.ErrorContains(t, err, "installing chart")
273+
require.Equal(t, applier.StateNeedsInstall, state)
274+
require.Nil(t, objs)
275+
})
276+
277+
t.Run("successful installation", func(t *testing.T) {
278+
mockAcg := &mockActionGetter{
279+
getClientErr: driver.ErrReleaseNotFound,
280+
desiredRel: &release.Release{
281+
Info: &release.Info{Status: release.StatusDeployed},
282+
Manifest: validManifest,
283+
},
284+
}
285+
helmApplier := applier.Helm{ActionClientGetter: mockAcg}
286+
287+
objs, state, err := helmApplier.Apply(context.TODO(), validFS, testCE, testObjectLabels, testStorageLabels)
288+
require.NoError(t, err)
289+
require.Equal(t, applier.StateNeedsInstall, state)
290+
require.NotNil(t, objs)
291+
assert.Equal(t, "service-a", objs[0].GetName())
292+
assert.Equal(t, "service-b", objs[1].GetName())
293+
})
294+
}
295+
229296
func TestApply_Upgrade(t *testing.T) {
230297
testCurrentRelease := &release.Release{
231298
Info: &release.Info{Status: release.StatusDeployed},

internal/features/features.go

+8-2
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,19 @@ import (
66
)
77

88
const (
9-
// Add new feature gates constants (strings)
10-
// Ex: SomeFeature featuregate.Feature = "SomeFeature"
9+
// Add new feature gates constants (strings)
10+
// Ex: SomeFeature featuregate.Feature = "SomeFeature"
11+
PreflightPermissions featuregate.Feature = "PreflightPermissions"
1112
)
1213

1314
var operatorControllerFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{
1415
// Add new feature gate definitions
1516
// Ex: SomeFeature: {...}
17+
PreflightPermissions: {
18+
Default: false,
19+
PreRelease: featuregate.Alpha,
20+
LockToDefault: false,
21+
},
1622
}
1723

1824
var OperatorControllerFeatureGate featuregate.MutableFeatureGate = featuregate.NewFeatureGate()

0 commit comments

Comments
 (0)