Skip to content

Commit 7e2e2de

Browse files
authored
install: improve detection for desired install mode when creating operator group (#54)
Signed-off-by: Joe Lanford <[email protected]>
1 parent 720400e commit 7e2e2de

File tree

3 files changed

+57
-161
lines changed

3 files changed

+57
-161
lines changed

internal/cmd/operator_install.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,4 @@ func bindOperatorInstallFlags(fs *pflag.FlagSet, i *internalaction.OperatorInsta
4242
fs.StringSliceVarP(&i.WatchNamespaces, "watch", "w", []string{}, "namespaces to watch")
4343
fs.DurationVar(&i.CleanupTimeout, "cleanup-timeout", time.Minute, "the amount of time to wait before cancelling cleanup")
4444
fs.BoolVarP(&i.CreateOperatorGroup, "create-operator-group", "C", false, "create operator group if necessary")
45-
46-
fs.VarP(&i.InstallMode, "install-mode", "i", "install mode")
47-
err := fs.MarkHidden("install-mode")
48-
if err != nil {
49-
panic(`requested flag "install-mode" missing`)
50-
}
5145
}

internal/pkg/action/operator_install.go

Lines changed: 57 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ type OperatorInstall struct {
2828
Version string
2929
Approval subscription.ApprovalValue
3030
WatchNamespaces []string
31-
InstallMode operator.InstallMode
3231
CleanupTimeout time.Duration
3332
CreateOperatorGroup bool
3433

@@ -43,13 +42,6 @@ func NewOperatorInstall(cfg *action.Configuration) *OperatorInstall {
4342
}
4443

4544
func (i *OperatorInstall) Run(ctx context.Context) (*v1alpha1.ClusterServiceVersion, error) {
46-
if len(i.WatchNamespaces) > 0 && !i.InstallMode.IsEmpty() {
47-
return nil, fmt.Errorf("WatchNamespaces and InstallMode options are mutually exclusive")
48-
}
49-
if i.InstallMode.IsEmpty() {
50-
i.configureInstallModeFromWatch()
51-
}
52-
5345
pm, err := i.getPackageManifest(ctx)
5446
if err != nil {
5547
return nil, fmt.Errorf("get package manifest: %v", err)
@@ -89,19 +81,20 @@ func (i *OperatorInstall) Run(ctx context.Context) (*v1alpha1.ClusterServiceVers
8981
return csv, nil
9082
}
9183

92-
func (i *OperatorInstall) configureInstallModeFromWatch() {
93-
i.InstallMode.TargetNamespaces = i.WatchNamespaces
94-
switch len(i.InstallMode.TargetNamespaces) {
84+
func (i *OperatorInstall) possibleInstallModes(watchNamespaces []string) sets.String {
85+
switch len(watchNamespaces) {
9586
case 0:
96-
i.InstallMode.InstallModeType = v1alpha1.InstallModeTypeAllNamespaces
87+
return sets.NewString(
88+
string(v1alpha1.InstallModeTypeAllNamespaces),
89+
string(v1alpha1.InstallModeTypeOwnNamespace),
90+
)
9791
case 1:
98-
if i.InstallMode.TargetNamespaces[0] == i.config.Namespace {
99-
i.InstallMode.InstallModeType = v1alpha1.InstallModeTypeOwnNamespace
100-
} else {
101-
i.InstallMode.InstallModeType = v1alpha1.InstallModeTypeSingleNamespace
92+
if watchNamespaces[0] == i.config.Namespace {
93+
return sets.NewString(string(v1alpha1.InstallModeTypeOwnNamespace))
10294
}
95+
return sets.NewString(string(v1alpha1.InstallModeTypeSingleNamespace))
10396
default:
104-
i.InstallMode.InstallModeType = v1alpha1.InstallModeTypeMultiNamespace
97+
return sets.NewString(string(v1alpha1.InstallModeTypeMultiNamespace))
10598
}
10699
}
107100

@@ -123,47 +116,66 @@ func (i *OperatorInstall) ensureOperatorGroup(ctx context.Context, pm *operator.
123116
return nil, err
124117
}
125118

126-
supported := pc.GetSupportedInstallModes()
127-
if supported.Len() == 0 {
128-
return nil, fmt.Errorf("operator %q is not installable: no supported install modes", pm.Name)
119+
operatorInstallModes := pc.GetSupportedInstallModes()
120+
if operatorInstallModes.Len() == 0 {
121+
return nil, fmt.Errorf("operator %q is not installable: operator defined no supported install modes", pm.Name)
129122
}
130123

131-
if !i.InstallMode.IsEmpty() {
132-
if i.InstallMode.InstallModeType == v1alpha1.InstallModeTypeSingleNamespace || i.InstallMode.InstallModeType == v1alpha1.InstallModeTypeMultiNamespace {
133-
targetNsSet := sets.NewString(i.InstallMode.TargetNamespaces...)
134-
if !supported.Has(string(v1alpha1.InstallModeTypeOwnNamespace)) && targetNsSet.Has(i.config.Namespace) {
135-
return nil, fmt.Errorf("cannot watch namespace %q: operator %q does not support install mode %q", i.config.Namespace, pm.Name, v1alpha1.InstallModeTypeOwnNamespace)
136-
}
137-
}
138-
if i.InstallMode.InstallModeType == v1alpha1.InstallModeTypeSingleNamespace && i.InstallMode.TargetNamespaces[0] == i.config.Namespace {
139-
return nil, fmt.Errorf("use install mode %q to watch operator's namespace %q", v1alpha1.InstallModeTypeOwnNamespace, i.config.Namespace)
140-
}
124+
desired := i.possibleInstallModes(i.WatchNamespaces)
141125

142-
supported = supported.Intersection(sets.NewString(string(i.InstallMode.InstallModeType)))
143-
if supported.Len() == 0 {
144-
return nil, fmt.Errorf("operator %q does not support install mode %q", pm.Name, i.InstallMode.InstallModeType)
145-
}
126+
supported := operatorInstallModes.Intersection(desired)
127+
if supported.Len() == 0 {
128+
return nil, fmt.Errorf("operator %q is not installable: install modes supported by operator (%q) not compatible with install modes supported by desired watches (%q)",
129+
pm.Name,
130+
strings.Join(operatorInstallModes.List(), ","),
131+
strings.Join(desired.List(), ","),
132+
)
146133
}
147134

148-
if og == nil {
135+
if og != nil {
136+
if err := i.validateOperatorGroup(*og, operatorInstallModes, desired); err != nil {
137+
return nil, fmt.Errorf("operator %q not installable: %v", pm.Name, err)
138+
}
139+
} else {
149140
if i.CreateOperatorGroup {
150-
targetNamespaces, err := i.getTargetNamespaces(supported)
151-
if err != nil {
152-
return nil, err
153-
}
141+
targetNamespaces := i.getTargetNamespaces(supported)
154142
if og, err = i.createOperatorGroup(ctx, targetNamespaces); err != nil {
155143
return nil, fmt.Errorf("create operator group: %v", err)
156144
}
157145
i.Logf("operatorgroup %q created", og.Name)
158146
} else {
159147
return nil, fmt.Errorf("namespace %q has no existing operator group; use --create-operator-group to create one automatically", i.config.Namespace)
160148
}
161-
} else if err := i.validateOperatorGroup(*og, supported); err != nil {
162-
return nil, err
163149
}
164150
return og, nil
165151
}
166152

153+
func (i OperatorInstall) validateOperatorGroup(og v1.OperatorGroup, operatorInstallModes, desired sets.String) error {
154+
ogSupported := i.possibleInstallModes(og.Status.Namespaces)
155+
156+
if operatorInstallModes.Intersection(ogSupported).Len() == 0 {
157+
return fmt.Errorf("install modes supported by operator (%q) not compatible with install modes supported by existing operator group (%q)",
158+
strings.Join(operatorInstallModes.List(), ","),
159+
strings.Join(ogSupported.List(), ","),
160+
)
161+
}
162+
163+
if desired.Intersection(ogSupported).Len() == 0 {
164+
return fmt.Errorf("install modes supported by desired watches (%q) not compatible with install modes supported by existing operator group (%q)",
165+
strings.Join(desired.List(), ","),
166+
strings.Join(ogSupported.List(), ","),
167+
)
168+
}
169+
supported := operatorInstallModes.Intersection(desired)
170+
if supported.Intersection(ogSupported).Len() == 0 {
171+
return fmt.Errorf("install modes supported by operator and desired watches (%q) not compatible with install modes supported by existing operator group (%q)",
172+
strings.Join(supported.List(), ","),
173+
strings.Join(ogSupported.List(), ","),
174+
)
175+
}
176+
return nil
177+
}
178+
167179
func (i OperatorInstall) getOperatorGroup(ctx context.Context) (*v1.OperatorGroup, error) {
168180
ogs := &v1.OperatorGroupList{}
169181
err := i.config.Client.List(ctx, ogs, client.InNamespace(i.config.Namespace))
@@ -181,24 +193,14 @@ func (i OperatorInstall) getOperatorGroup(ctx context.Context) (*v1.OperatorGrou
181193
}
182194
}
183195

184-
func (i *OperatorInstall) getTargetNamespaces(supported sets.String) ([]string, error) {
196+
func (i *OperatorInstall) getTargetNamespaces(supported sets.String) []string {
185197
switch {
186198
case supported.Has(string(v1alpha1.InstallModeTypeAllNamespaces)):
187-
return nil, nil
199+
return nil
188200
case supported.Has(string(v1alpha1.InstallModeTypeOwnNamespace)):
189-
return []string{i.config.Namespace}, nil
190-
case supported.Has(string(v1alpha1.InstallModeTypeSingleNamespace)):
191-
if len(i.InstallMode.TargetNamespaces) != 1 {
192-
return nil, fmt.Errorf("install mode %q requires explicit target namespace", v1alpha1.InstallModeTypeSingleNamespace)
193-
}
194-
return i.InstallMode.TargetNamespaces, nil
195-
case supported.Has(string(v1alpha1.InstallModeTypeMultiNamespace)):
196-
if len(i.InstallMode.TargetNamespaces) == 0 {
197-
return nil, fmt.Errorf("install mode %q requires explicit target namespaces", v1alpha1.InstallModeTypeMultiNamespace)
198-
}
199-
return i.InstallMode.TargetNamespaces, nil
201+
return []string{i.config.Namespace}
200202
default:
201-
return nil, fmt.Errorf("no supported install modes")
203+
return i.WatchNamespaces
202204
}
203205
}
204206

@@ -214,28 +216,6 @@ func (i *OperatorInstall) createOperatorGroup(ctx context.Context, targetNamespa
214216
return og, nil
215217
}
216218

217-
func (i *OperatorInstall) validateOperatorGroup(og v1.OperatorGroup, supported sets.String) error {
218-
ogTargetNs := sets.NewString(og.Spec.TargetNamespaces...)
219-
imTargetNs := sets.NewString(i.InstallMode.TargetNamespaces...)
220-
ownNamespaceNs := sets.NewString(i.config.Namespace)
221-
222-
if supported.Has(string(v1alpha1.InstallModeTypeAllNamespaces)) && len(og.Spec.TargetNamespaces) == 0 ||
223-
supported.Has(string(v1alpha1.InstallModeTypeOwnNamespace)) && ogTargetNs.Equal(ownNamespaceNs) ||
224-
supported.Has(string(v1alpha1.InstallModeTypeSingleNamespace)) && ogTargetNs.Equal(imTargetNs) ||
225-
supported.Has(string(v1alpha1.InstallModeTypeMultiNamespace)) && ogTargetNs.Equal(imTargetNs) {
226-
return nil
227-
}
228-
229-
switch i.InstallMode.InstallModeType {
230-
case v1alpha1.InstallModeTypeAllNamespaces, v1alpha1.InstallModeTypeOwnNamespace,
231-
v1alpha1.InstallModeTypeSingleNamespace, v1alpha1.InstallModeTypeMultiNamespace:
232-
return fmt.Errorf("existing operatorgroup %q is not compatible with install mode %q", og.Name, i.InstallMode)
233-
case "":
234-
return fmt.Errorf("existing operatorgroup %q is not compatible with any supported package install modes", og.Name)
235-
}
236-
panic(fmt.Sprintf("unknown install mode %q", i.InstallMode.InstallModeType))
237-
}
238-
239219
func (i *OperatorInstall) createSubscription(ctx context.Context, pm *operator.PackageManifest, pc *operator.PackageChannel) (*v1alpha1.Subscription, error) {
240220
opts := []subscription.Option{
241221
subscription.InstallPlanApproval(i.Approval.Approval),

internal/pkg/operator/install_mode.go

Lines changed: 0 additions & 78 deletions
This file was deleted.

0 commit comments

Comments
 (0)