Skip to content

Commit

Permalink
Verify CRD's condition to ensure it's registered with k8s API
Browse files Browse the repository at this point in the history
OLM needs to verify CRD's condition to make sure it is registered
with k8s API during CSV control loop before installing operator.
This verification will help to avoid errors related to the
unavailability of an API when installing an operator via OLM.

Jira: https://jira.coreos.com/browse/ALM-775

Signed-off-by: Vu Dinh <vdinh@redhat.com>
  • Loading branch information
dinhxuanvu committed Nov 12, 2018
1 parent 99edec4 commit 8b1152a
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 0 deletions.
18 changes: 18 additions & 0 deletions pkg/controller/operators/olm/requirements.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
olmErrors "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/errors"
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
log "github.com/sirupsen/logrus"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -59,6 +60,23 @@ func (a *Operator) requirementStatus(strategyDetailsDeployment *install.Strategy
met = false
statuses = append(statuses, status)
}

// Check if CRD has succes registered with k8s API
registered := false
for _, cdt := range crd.Status.Conditions {
switch cdt.Type {
case v1beta1.Established:
if cdt.Status == v1beta1.ConditionTrue {
registered = true
}
}
}

if !registered {
status.Status = v1alpha1.RequirementStatusReasonNotPresent
met = false
statuses = append(statuses, status)
}
}

// Check for required API services
Expand Down
79 changes: 79 additions & 0 deletions test/e2e/csv_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions"
extv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -312,6 +313,84 @@ func TestCreateCSVWithUnmetPermissionsCRD(t *testing.T) {

}

func TestCreateCSVWithNotReadyCRD(t *testing.T) {
defer cleaner.NotifyTestComplete(t, true)

c := newKubeClient(t)
crc := newCRClient(t)

depName := genName("dep-")

// Create dependency first (CRD)
crdPlural := genName("ins2")
crdName := crdPlural + ".cluster.com"
crd := extv1beta1.CustomResourceDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: crdName,
},
Spec: extv1beta1.CustomResourceDefinitionSpec{
Group: "cluster.com",
Version: "v1alpha1",
Names: extv1beta1.CustomResourceDefinitionNames{
Plural: crdPlural,
Singular: crdPlural,
Kind: crdPlural,
ListKind: "list" + crdPlural,
},
Scope: "Namespaced",
},
}
cleanupCRD, err := createCRD(c, crd)
require.NoError(t, err)
defer cleanupCRD()

// Update CRD status to Established false
establishedCondition := apiextensions.CustomResourceDefinitionCondition{
Type: apiextensions.Established,
Status: apiextensions.ConditionTrue,
Reason: "InitialNamesAccepted",
Message: "The initial names have been accepted",

apiextensions.SetCRDCondition(crd, establishedCondition)
_, err = c.ApiextensionsV1beta1Interface().ApiextensionsV1beta1().CustomResourceDefinitions().UpdateStatus(crd)
require.NoError(t, err)

csv := v1alpha1.ClusterServiceVersion{
TypeMeta: metav1.TypeMeta{
Kind: v1alpha1.ClusterServiceVersionKind,
APIVersion: v1alpha1.ClusterServiceVersionAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: genName("csv"),
},
Spec: v1alpha1.ClusterServiceVersionSpec{
InstallStrategy: newNginxInstallStrategy(depName, nil, nil),
CustomResourceDefinitions: v1alpha1.CustomResourceDefinitions{
Owned: []v1alpha1.CRDDescription{
{
Name: crdName,
Version: "v1alpha1",
Kind: crdPlural,
DisplayName: crdName,
Description: "In the cluster",
},
},
},
},
}

cleanupCSV, err := createCSV(t, c, crc, csv, testNamespace, true)
require.NoError(t, err)
defer cleanupCSV()

_, err = fetchCSV(t, crc, csv.Name, csvPendingChecker)
require.NoError(t, err)

// Shouldn't create deployment
_, err = c.GetDeployment(testNamespace, depName)
require.Error(t, err)
}

func TestCreateCSVWithUnmetRequirementsAPIService(t *testing.T) {
defer cleaner.NotifyTestComplete(t, true)

Expand Down

0 comments on commit 8b1152a

Please sign in to comment.