Skip to content
This repository has been archived by the owner on Jun 26, 2024. It is now read-only.

Create an overall Ready to indicate whether the SBR reconcile is completed successfully #665 #681

Merged
merged 1 commit into from
Nov 3, 2020

Conversation

qibobo
Copy link
Contributor

@qibobo qibobo commented Sep 21, 2020

According to the discussion in #665, we need to add a overall Ready condition to show what is the status of the ServiceBinding CR.

@openshift-ci-robot
Copy link
Collaborator

Hi @qibobo. Thanks for your PR.

I'm waiting for a redhat-developer member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository.

Copy link
Contributor

@pedjak pedjak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

acceptance tests need to updated to reflect and check this new flag.

@qibobo
Copy link
Contributor Author

qibobo commented Sep 21, 2020

@isutton
Could you help review this PR?

@qibobo
Copy link
Contributor Author

qibobo commented Sep 22, 2020

@pedjak done

@isutton
Copy link
Contributor

isutton commented Sep 24, 2020

/ok-to-test

@qibobo
Copy link
Contributor Author

qibobo commented Sep 24, 2020

/retest

@@ -31,6 +36,10 @@ const (
EmptyApplicationReason = "EmptyApplication"
// ApplicationNotFoundReason is used when the application is not found.
ApplicationNotFoundReason = "ApplicationNotFound"
// FailedToGatherServiceInformationReason is used when the it is failed to fetch backend service information.
FailedToGatherServiceInformationReason = "FailedToGatherServiceInformation"
// FailedToSaveSecretReason is used when the it is failed to save intermediate secret.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this ? Could not find any reference to this particular FailedToSaveReason in this PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

@pmacik
Copy link
Contributor

pmacik commented Sep 24, 2020

/test 4.5-acceptance

@qibobo
Copy link
Contributor Author

qibobo commented Sep 25, 2020

@Avni-Sharma @isutton @pmacik @pedjak
The acceptance test is failed, but seems I did not modify the error part. Could you help confirm whether it is the acceptance test problem or the issue of my PR?

test/acceptance/features/steps/steps.py:225
      Assertion Failed: 
      Expected: not SBO jq result "{result}" should match "{json_value_regex}"
           but: was <None>

Copy link
Contributor

@pedjak pedjak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR should introduce new condition, but should alte the logic around the existing conditions.

conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line can be removed - the import already exists in line 10.

conditionsv1.Condition{
Type: BindingReady,
Status: corev1.ConditionFalse,
Reason: EmptyServiceSelectorsReason,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if we need to copy reasons here from other conditions. If we do that then we are back of the question if we really need to have other conditions.

BTW, we need to fill LastTransitionTime.

IMHO, In case when Ready=false we should look into other conditions if we want to know more details.

Comment on lines 181 to 192
conditionsv1.Condition{
Type: InjectionReady,
Status: corev1.ConditionFalse,
Reason: FailedToGatherServiceInformationReason,
Message: err.Error(),
},
conditionsv1.Condition{
Type: BindingReady,
Status: corev1.ConditionFalse,
Reason: FailedToGatherServiceInformationReason,
Message: err.Error(),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We did not even reach the state when we can say if something is injection ready or not, because we did not gather service data at all. Conditions must not exist at all. We should update them only if there is a change in status, and in that case we are going to update last transition time as well. In this PR, it looks like we have 3 conditions, but they all share value and reason. Why then not collapse it into single condition.

BTW, excellent read about conditions: https://dev.to/maelvls/what-the-heck-are-kubernetes-conditions-for-4je7

Comment on lines 203 to 221
_ = updateSBRConditions(r.dynClient, sbr,
conditionsv1.Condition{
Type: CollectionReady,
Status: corev1.ConditionFalse,
Reason: FailedToGatherServiceInformationReason,
Message: err.Error(),
},
conditionsv1.Condition{
Type: InjectionReady,
Status: corev1.ConditionFalse,
Reason: FailedToGatherServiceInformationReason,
Message: err.Error(),
},
conditionsv1.Condition{
Type: BindingReady,
Status: corev1.ConditionFalse,
Reason: FailedToGatherServiceInformationReason,
Message: err.Error(),
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comments as above. Error in buildServiceContexts or buildBinding does not move the process into the same condition.

Comment on lines 240 to 258
_ = updateSBRConditions(r.dynClient, sbr,
conditionsv1.Condition{
Type: CollectionReady,
Status: corev1.ConditionFalse,
Reason: FailedToGatherServiceInformationReason,
Message: err.Error(),
},
conditionsv1.Condition{
Type: InjectionReady,
Status: corev1.ConditionFalse,
Reason: FailedToGatherServiceInformationReason,
Message: err.Error(),
},
conditionsv1.Condition{
Type: BindingReady,
Status: corev1.ConditionFalse,
Reason: FailedToGatherServiceInformationReason,
Message: err.Error(),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above.

Comment on lines 109 to 120
func createFunc(logger *log.Log) func(event.CreateEvent) bool {
return func(e event.CreateEvent) bool {
return true
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need this?

@sbose78
Copy link
Member

sbose78 commented Sep 25, 2020

@qibobo Could you please add a description why this is needed :) ?

@@ -257,6 +259,63 @@ func TestReconcilerReconcileUsingVolumes(t *testing.T) {
})
}

func TestServiceNotFound(t *testing.T) {
backingServiceResourceRef := "backingService1"
matchLabels := map[string]string{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we require matchLabels?

}
f := mocks.NewFake(t, reconcilerNs)
f.AddMockedUnstructuredServiceBinding(reconcilerName, backingServiceResourceRef, "", deploymentsGVR, matchLabels)
f.AddMockedUnstructuredCSV("cluster-service-version-list")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CSV might not be necessary
depends whether we are checking via annotations on CRDs or via x-descriptors

@@ -273,14 +279,7 @@ func removeFinalizer(sbr *v1alpha1.ServiceBinding) {
// handleApplicationError handles scenarios when:
// 1. application not declared in the Service Binding
// 2. application not found
func (b *serviceBinder) handleApplicationError(reason string, applicationError error, sbrStatus *v1alpha1.ServiceBindingStatus) (reconcile.Result, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleApplicationError is for the reasons provided in the above comments. We can still keep this function's functionality. Any particular reason for modifying this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Avni-Sharma
Put the condition setting out of handleApplicationError function as there are two callers:
caller1:

if isApplicationEmpty(b.sbr.Spec.Application) {

caller2:
if errors.Is(err, errApplicationNotFound) {

caller1 is for application empty so InjectionReady is false and BindingReady is true.
caller2 is for application not found so both InjectionReady and BindingReady are false.
So here we need to put the condition setting out of this function.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. However, in order to improve readability of the code, and avoid copy/pasting conditionsv1.SetStatusCondition blocks around, how about to define InjectionReadyStatus(...), ReadyStatus, ... on ServiceBindingStatus struct and use them across the code? IMHO, it would improve readbility and reusability of the code. Also, Ready condition could even autoderived from other two conditions in that case.

@qibobo
Copy link
Contributor Author

qibobo commented Sep 28, 2020

@qibobo Could you please add a description why this is needed :) ?

@sbose78 Done. Add the issue that for the discussion of this PR.

pkg/controller/servicebinding/reconciler.go Show resolved Hide resolved
pkg/controller/servicebinding/reconciler.go Show resolved Hide resolved
Comment on lines 263 to 272
// backingServiceResourceRef := "backingService1"
// matchLabels := map[string]string{
// "connects-to": "database",
// "environment": "reconciler",
// }
// f := mocks.NewFake(t, reconcilerNs)
// f.AddMockedUnstructuredServiceBinding(reconcilerName, backingServiceResourceRef, "", deploymentsGVR, nil)
// f.AddMockedUnstructuredCSV("cluster-service-version-list")
// f.AddMockedUnstructuredDatabaseCRD()
// f.AddMockedUnstructuredDeployment(reconcilerName, nil)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not needed, please remove from the source code.

applicationResourceRef := "applicationRef"
f := mocks.NewFake(t, reconcilerNs)
f.AddMockedUnstructuredServiceBindingWithoutService(reconcilerName, applicationResourceRef, deploymentsGVR)
// f.AddMockedUnstructuredDatabaseCR(backingServiceResourceRef)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove if not needed anymore.

}

// TestEmptyServiceSelector tests that Status is successfully updated when ServiceSelector is empty
func TestEmptyServiceSelector(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please rename this function to reflect what the comment above says.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pedjak
What name should it be instead of TestEmptyServiceSelector?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the comment line above has a few hints how the test function name could look like. It should contain the context (empty selector) and the consequence (status is successfully updated)

@@ -145,6 +145,7 @@ func buildGVKPredicate(logger *log.Log) predicate.Funcs {
UpdateFunc: updateFunc(logger),
DeleteFunc: func(e event.DeleteEvent) bool {
// evaluates to false if the object has been confirmed deleted
logger.Debug("Resource update event received", "GVK", e.Object.GetObjectKind(), "name", e.Meta.GetName())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need this change in PR? BTW, the message is misleading, since we receive here delete event.

@pedjak
Copy link
Contributor

pedjak commented Oct 6, 2020

Does this PR include the work in #502 ?

@qibobo
Copy link
Contributor Author

qibobo commented Oct 6, 2020

Does this PR include the work in #502 ?

@pedjak
Both this PR and 502 are not merged yet, so we can not include each other.

@pedjak
Copy link
Contributor

pedjak commented Oct 6, 2020

Both this PR and 502 are not merged yet, so we can not include each other.

#502 is about handling situation when service is not found. Does your PR cover such situation?

@qibobo qibobo force-pushed the dev_qy_ready branch 4 times, most recently from 73d99f5 to 6b45175 Compare October 10, 2020 05:33
@qibobo
Copy link
Contributor Author

qibobo commented Oct 12, 2020

@pedjak @Avni-Sharma any more comments?

@Avni-Sharma
Copy link
Contributor

I also think that we can have acceptance tests for ready condition. For example https://github.com/redhat-developer/service-binding-operator/blob/master/test/acceptance/features/bindAppToService.feature#L70

@qibobo
Copy link
Contributor Author

qibobo commented Oct 23, 2020

@Avni-Sharma
updated.

@qibobo
Copy link
Contributor Author

qibobo commented Oct 23, 2020

I also think that we can have acceptance tests for ready condition. For example https://github.com/redhat-developer/service-binding-operator/blob/master/test/acceptance/features/bindAppToService.feature#L70

@Avni-Sharma I think they have been added.

@qibobo
Copy link
Contributor Author

qibobo commented Oct 23, 2020

/retest

@qibobo
Copy link
Contributor Author

qibobo commented Oct 28, 2020

/retest

@Avni-Sharma
Copy link
Contributor

I also think that we can have acceptance tests for ready condition. For example https://github.com/redhat-developer/service-binding-operator/blob/master/test/acceptance/features/bindAppToService.feature#L70

@Avni-Sharma I think they have been added.

Oh , I meant specifically checking for Ready under conditions

@qibobo
Copy link
Contributor Author

qibobo commented Nov 3, 2020

@Avni-Sharma squashed the commits.

@Avni-Sharma
Copy link
Contributor

@qibobo Please feel free to create an issue regarding #681 (comment) . You can perhaps take it up later

@Avni-Sharma
Copy link
Contributor

/lgtm
/approve

@openshift-ci-robot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: Avni-Sharma

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Create an overall Ready to indicate whether the SBR reconcile is completed successfully
8 participants