Skip to content

Commit b2a99e7

Browse files
committed
add 'spec.nativeAPIs' field to CSV and check that native APIs exist before install
1 parent f3faa4c commit b2a99e7

File tree

6 files changed

+90
-6
lines changed

6 files changed

+90
-6
lines changed

deploy/chart/templates/0000_30_02-clusterserviceversion.crd.yaml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,25 @@ spec:
180180
values:
181181
type: array
182182
description: set of values for the expression
183-
183+
nativeAPIs:
184+
type: array
185+
description: What resources are required by the Operator, but must be provided by the underlying cluster and not as an extension.
186+
items:
187+
type: object
188+
required:
189+
- group
190+
- version
191+
- kind
192+
properties:
193+
group:
194+
type: string
195+
description: Group of the API resource
196+
version:
197+
type: string
198+
description: Version of the API resource
199+
kind:
200+
type: string
201+
description: Kind of the API resource
184202
apiservicedefinitions:
185203
type: object
186204
properties:

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,15 @@ type APIServiceDefinitions struct {
102102
Required []APIServiceDescription `json:"required,omitempty"`
103103
}
104104

105-
// ClusterServiceVersionSpec declarations tell the OLM how to install an operator
106-
// that can manage apps for given version and AppType.
105+
// ClusterServiceVersionSpec declarations tell OLM how to install an operator
106+
// that can manage apps for a given version.
107107
type ClusterServiceVersionSpec struct {
108108
InstallStrategy NamedInstallStrategy `json:"install"`
109109
Version semver.Version `json:"version,omitempty"`
110110
Maturity string `json:"maturity,omitempty"`
111111
CustomResourceDefinitions CustomResourceDefinitions `json:"customresourcedefinitions,omitempty"`
112112
APIServiceDefinitions APIServiceDefinitions `json:"apiservicedefinitions,omitempty"`
113+
NativeAPIs []metav1.GroupVersionKind `json:"nativeAPIs,omitempty"`
113114
DisplayName string `json:"displayName"`
114115
Description string `json:"description,omitempty"`
115116
Keywords []string `json:"keywords,omitempty"`

pkg/api/apis/operators/v1alpha1/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.

pkg/controller/operators/olm/operator_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,12 @@ func installStrategy(deploymentName string, permissions []install.StrategyDeploy
212212
}
213213
}
214214

215-
func csv(name, namespace, replaces string, installStrategy v1alpha1.NamedInstallStrategy, owned, required []*v1beta1.CustomResourceDefinition, phase v1alpha1.ClusterServiceVersionPhase) *v1alpha1.ClusterServiceVersion {
215+
func csv(
216+
name, namespace, replaces string,
217+
installStrategy v1alpha1.NamedInstallStrategy,
218+
owned, required []*v1beta1.CustomResourceDefinition,
219+
phase v1alpha1.ClusterServiceVersionPhase,
220+
) *v1alpha1.ClusterServiceVersion {
216221
requiredCRDDescs := make([]v1alpha1.CRDDescription, 0)
217222
for _, crd := range required {
218223
requiredCRDDescs = append(requiredCRDDescs, v1alpha1.CRDDescription{Name: crd.GetName(), Version: crd.Spec.Versions[0].Name, Kind: crd.Spec.Names.Kind})

pkg/controller/operators/olm/requirements.go

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ import (
1212
)
1313

1414
func (a *Operator) requirementStatus(strategyDetailsDeployment *install.StrategyDetailsDeployment, crdDescs []v1alpha1.CRDDescription,
15-
ownedAPIServiceDescs []v1alpha1.APIServiceDescription, requiredAPIServiceDescs []v1alpha1.APIServiceDescription) (met bool, statuses []v1alpha1.RequirementStatus) {
15+
ownedAPIServiceDescs []v1alpha1.APIServiceDescription, requiredAPIServiceDescs []v1alpha1.APIServiceDescription,
16+
requiredNativeAPIs []metav1.GroupVersionKind) (met bool, statuses []v1alpha1.RequirementStatus) {
1617
met = true
1718

1819
// Check for CRDs
@@ -125,6 +126,27 @@ func (a *Operator) requirementStatus(strategyDetailsDeployment *install.Strategy
125126
}
126127
}
127128

129+
for _, r := range requiredNativeAPIs {
130+
name := fmt.Sprintf("%s.%s", r.Version, r.Group)
131+
status := v1alpha1.RequirementStatus{
132+
Group: r.Group,
133+
Version: r.Version,
134+
Kind: r.Kind,
135+
Name: name,
136+
}
137+
138+
if err := a.isGVKRegistered(r.Group, r.Version, r.Kind); err != nil {
139+
status.Status = v1alpha1.RequirementStatusReasonNotPresent
140+
met = false
141+
statuses = append(statuses, status)
142+
continue
143+
} else {
144+
status.Status = v1alpha1.RequirementStatusReasonPresent
145+
statuses = append(statuses, status)
146+
continue
147+
}
148+
}
149+
128150
return
129151
}
130152

@@ -238,7 +260,7 @@ func (a *Operator) requirementAndPermissionStatus(csv *v1alpha1.ClusterServiceVe
238260
return false, nil, fmt.Errorf("could not cast install strategy as type %T", strategyDetailsDeployment)
239261
}
240262

241-
reqMet, reqStatuses := a.requirementStatus(strategyDetailsDeployment, csv.GetAllCRDDescriptions(), csv.GetOwnedAPIServiceDescriptions(), csv.GetRequiredAPIServiceDescriptions())
263+
reqMet, reqStatuses := a.requirementStatus(strategyDetailsDeployment, csv.GetAllCRDDescriptions(), csv.GetOwnedAPIServiceDescriptions(), csv.GetRequiredAPIServiceDescriptions(), csv.Spec.NativeAPIs)
242264

243265
rbacLister := a.lister.RbacV1()
244266
roleLister := rbacLister.RoleLister()

test/e2e/csv_e2e_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,39 @@ func TestCreateCSVWithUnmetPermissionsAPIService(t *testing.T) {
426426
require.Error(t, err)
427427
}
428428

429+
func TestCreateCSVWithUnmetRequirementsNativeAPI(t *testing.T) {
430+
defer cleaner.NotifyTestComplete(t, true)
431+
432+
c := newKubeClient(t)
433+
crc := newCRClient(t)
434+
435+
depName := genName("dep-")
436+
csv := v1alpha1.ClusterServiceVersion{
437+
TypeMeta: metav1.TypeMeta{
438+
Kind: v1alpha1.ClusterServiceVersionKind,
439+
APIVersion: v1alpha1.ClusterServiceVersionAPIVersion,
440+
},
441+
ObjectMeta: metav1.ObjectMeta{
442+
Name: genName("csv"),
443+
},
444+
Spec: v1alpha1.ClusterServiceVersionSpec{
445+
InstallStrategy: newNginxInstallStrategy(depName, nil, nil),
446+
NativeAPIs: []metav1.GroupVersionKind{{Group: "kubenative.io", Version: "v1", Kind: "Native"}},
447+
},
448+
}
449+
450+
cleanupCSV, err := createCSV(t, c, crc, csv, testNamespace, false)
451+
require.NoError(t, err)
452+
defer cleanupCSV()
453+
454+
_, err = fetchCSV(t, crc, csv.Name, csvPendingChecker)
455+
require.NoError(t, err)
456+
457+
// Shouldn't create deployment
458+
_, err = c.GetDeployment(testNamespace, depName)
459+
require.Error(t, err)
460+
}
461+
429462
// TODO: same test but create serviceaccount instead
430463
func TestCreateCSVRequirementsMetCRD(t *testing.T) {
431464
defer cleaner.NotifyTestComplete(t, true)

0 commit comments

Comments
 (0)