Skip to content

Commit de6c15d

Browse files
committed
feat(installmode): add InstallModeSet
1 parent 7f9ab4e commit de6c15d

15 files changed

+970
-112
lines changed

deploy/chart/templates/_packageserver.clusterserviceversion.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@
1616
links:
1717
- name: Package Server
1818
url: https://github.com/operator-framework/operator-lifecycle-manager/tree/master/pkg/packageserver
19+
installModes:
20+
- type: OwnNamespace
21+
supported: true
22+
- type: SingleNamespace
23+
supported: true
24+
- type: MultiNamespace
25+
supported: true
26+
- type: AllNamespaces
27+
supported: true
1928
install:
2029
strategy: deployment
2130
spec:

pkg/api/apis/operators/v1alpha1/clusterserviceversion.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package v1alpha1
22

33
import (
4+
"fmt"
5+
46
v1 "k8s.io/api/core/v1"
57
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
68
"k8s.io/client-go/tools/record"
@@ -68,3 +70,38 @@ func (c *ClusterServiceVersion) IsObsolete() bool {
6870
}
6971
return false
7072
}
73+
74+
// NewInstallModeSet returns an InstallModeSet instantiated from the given list of InstallModes.
75+
// If the given list is not a set, an error is returned.
76+
func NewInstallModeSet(modes []InstallMode) (InstallModeSet, error) {
77+
set := InstallModeSet{}
78+
for _, mode := range modes {
79+
if _, exists := set[mode.Type]; exists {
80+
return nil, fmt.Errorf("InstallMode list contains duplicates, cannot make set: %v", modes)
81+
}
82+
set[mode.Type] = mode.Supported
83+
}
84+
85+
return set, nil
86+
}
87+
88+
// Supports returns an error if the InstallModeSet does not support configuration for
89+
// the given list of namespaces.
90+
func (set InstallModeSet) Supports(namespaces []string) error {
91+
// Return an error if set contains incompatible supported modes
92+
// for the number of namespaces given.
93+
numNamespaces := len(namespaces)
94+
if !set[InstallModeTypeAllNamespaces] && numNamespaces == 1 && namespaces[0] == v1.NamespaceAll {
95+
return fmt.Errorf("%s InstallModeType not supported, cannot configure to watch all namespaces", InstallModeTypeAllNamespaces)
96+
}
97+
98+
if !set[InstallModeTypeSingleNamespace] && numNamespaces == 1 && namespaces[0] != v1.NamespaceAll {
99+
return fmt.Errorf("%s InstallModeType not supported, cannot configure to watch one namespace", InstallModeTypeSingleNamespace)
100+
}
101+
102+
if !set[InstallModeTypeMultiNamespace] && numNamespaces > 1 {
103+
return fmt.Errorf("%s InstallModeType not supported, cannot configure to watch %d namespaces", InstallModeTypeMultiNamespace, numNamespaces)
104+
}
105+
106+
return nil
107+
}

pkg/api/apis/operators/v1alpha1/clusterserviceversion_test.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package v1alpha1
22

33
import (
4+
"fmt"
45
"testing"
56

67
"github.com/stretchr/testify/require"
8+
corev1 "k8s.io/api/core/v1"
79
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
810
)
911

@@ -102,3 +104,110 @@ func TestIsObsolete(t *testing.T) {
102104
})
103105
}
104106
}
107+
108+
func TestSupports(t *testing.T) {
109+
tests := []struct {
110+
description string
111+
installModeSet InstallModeSet
112+
namespaces []string
113+
expectedErr error
114+
}{
115+
{
116+
description: "NoNamespaces",
117+
installModeSet: InstallModeSet{
118+
InstallModeTypeOwnNamespace: true,
119+
InstallModeTypeSingleNamespace: true,
120+
InstallModeTypeMultiNamespace: true,
121+
InstallModeTypeAllNamespaces: true,
122+
},
123+
namespaces: []string{},
124+
expectedErr: nil,
125+
},
126+
{
127+
description: "OneNamespace",
128+
installModeSet: InstallModeSet{
129+
InstallModeTypeOwnNamespace: true,
130+
InstallModeTypeSingleNamespace: true,
131+
InstallModeTypeMultiNamespace: true,
132+
InstallModeTypeAllNamespaces: true,
133+
},
134+
namespaces: []string{"ns-0"},
135+
expectedErr: nil,
136+
},
137+
{
138+
description: "MultipleNamespaces/MultiNamespaceUnsupported",
139+
installModeSet: InstallModeSet{
140+
InstallModeTypeOwnNamespace: true,
141+
InstallModeTypeSingleNamespace: true,
142+
InstallModeTypeMultiNamespace: false,
143+
InstallModeTypeAllNamespaces: true,
144+
},
145+
namespaces: []string{"ns-0", "ns-1"},
146+
expectedErr: fmt.Errorf("%s InstallModeType not supported, cannot configure to watch 2 namespaces", InstallModeTypeMultiNamespace),
147+
},
148+
{
149+
description: "SingleNamespace/SingleNamespaceUnsupported",
150+
installModeSet: InstallModeSet{
151+
InstallModeTypeOwnNamespace: true,
152+
InstallModeTypeSingleNamespace: false,
153+
InstallModeTypeMultiNamespace: true,
154+
InstallModeTypeAllNamespaces: true,
155+
},
156+
namespaces: []string{"ns-0"},
157+
expectedErr: fmt.Errorf("%s InstallModeType not supported, cannot configure to watch one namespace", InstallModeTypeSingleNamespace),
158+
},
159+
{
160+
description: "AllNamespaces/AllNamespacesSupported",
161+
installModeSet: InstallModeSet{
162+
InstallModeTypeOwnNamespace: true,
163+
InstallModeTypeSingleNamespace: true,
164+
InstallModeTypeMultiNamespace: true,
165+
InstallModeTypeAllNamespaces: true,
166+
},
167+
namespaces: []string{corev1.NamespaceAll},
168+
expectedErr: nil,
169+
},
170+
{
171+
description: "AllNamespaces/AllNamespacesUnsupported",
172+
installModeSet: InstallModeSet{
173+
InstallModeTypeOwnNamespace: true,
174+
InstallModeTypeSingleNamespace: true,
175+
InstallModeTypeMultiNamespace: true,
176+
InstallModeTypeAllNamespaces: false,
177+
},
178+
namespaces: []string{corev1.NamespaceAll},
179+
expectedErr: fmt.Errorf("%s InstallModeType not supported, cannot configure to watch all namespaces", InstallModeTypeAllNamespaces),
180+
},
181+
{
182+
description: "NoNamespaces/EmptyInstallModeSet",
183+
installModeSet: InstallModeSet{},
184+
namespaces: []string{},
185+
expectedErr: nil,
186+
},
187+
{
188+
description: "MultipleNamespaces/EmptyInstallModeSet",
189+
installModeSet: InstallModeSet{},
190+
namespaces: []string{"ns-0", "ns-1"},
191+
expectedErr: fmt.Errorf("%s InstallModeType not supported, cannot configure to watch 2 namespaces", InstallModeTypeMultiNamespace),
192+
},
193+
{
194+
description: "SingleNamespace/EmptyInstallModeSet",
195+
installModeSet: InstallModeSet{},
196+
namespaces: []string{"ns-0"},
197+
expectedErr: fmt.Errorf("%s InstallModeType not supported, cannot configure to watch one namespace", InstallModeTypeSingleNamespace),
198+
},
199+
{
200+
description: "AllNamespaces/EmptyInstallModeSet",
201+
installModeSet: InstallModeSet{},
202+
namespaces: []string{corev1.NamespaceAll},
203+
expectedErr: fmt.Errorf("%s InstallModeType not supported, cannot configure to watch all namespaces", InstallModeTypeAllNamespaces),
204+
},
205+
}
206+
207+
for _, test := range tests {
208+
t.Run(test.description, func(t *testing.T) {
209+
err := test.installModeSet.Supports(test.namespaces)
210+
require.Equal(t, err, test.expectedErr)
211+
})
212+
}
213+
}

pkg/api/apis/operators/v1alpha1/clusterserviceversion_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ type InstallMode struct {
3333
Supported bool `json:"supported"`
3434
}
3535

36+
// InstallModeSet is a mapping of unique InstallModeTypes to whether they are supported.
37+
type InstallModeSet map[InstallModeType]bool
38+
3639
// NamedInstallStrategy represents the block of an ClusterServiceVersion resource
3740
// where the install strategy is specified.
3841
type NamedInstallStrategy struct {
@@ -223,6 +226,7 @@ const (
223226
CSVReasonAPIServiceResourcesNeedReinstall ConditionReason = "APIServiceResourcesNeedReinstall"
224227
CSVReasonAPIServiceInstallFailed ConditionReason = "APIServiceInstallFailed"
225228
CSVReasonCopied ConditionReason = "Copied"
229+
CSVReasonInstallModeNotSupported ConditionReason = "InstallModeNotSupported"
226230
)
227231

228232
// Conditions appear in the status as a record of state transitions on the ClusterServiceVersion

pkg/api/apis/operators/v1alpha1/zz_generated.deepcopy.go

Lines changed: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/api/apis/operators/v1alpha2/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)