@@ -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
4544func (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+
167179func (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-
239219func (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 ),
0 commit comments