Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set ownerReference to build->buildrun #409

Conversation

qu1queee
Copy link
Contributor

@qu1queee qu1queee commented Sep 25, 2020

Fixes #324

This PR is the continuation of #371 . I addressed all concerns there into this PR, and preserve @routerhan commits.

This PR replaces the finalizers approach we have in the Build -> BuildRun in favour of OwnerReferences for the same resources, aligning to the same approach as we have between BuildRuns -> TaskRuns. The PR have one commit for fixing go linters I found by using staticcheck ./...(I couldn´t avoid fixing this now)

@zhangtbj @HeavyWombat for your information:

Note: When dealing with OwnerReferences between the Build(owner) and BuildRun(owned), both controllers Build and BuildRun plays a role on ensuring that the BuildRun gets the Ownerreference or that the OwnerReference is removed. Following scenarios to consider:

When the Build have the build.build.dev/build-run-deletion annotation set to true

For the above case, the Ownerreference is added during the CREATION event of a BuildRun, meaning on the BuildRun controller side.

When the Build have the build.build.dev/build-run-deletion annotation set to true, but the user modifies the annotation and set this back to false.

For the above case, the Ownerreference needs to be removed during the UPDATE event of a Build, meaning we need logic on the Build controller reconciler side.

When the Build have the build.build.dev/build-run-deletion annotation set to true, but the user modifies the annotation and set this back to false, but then the user changes his mind and modify it one more time, and set it back to the original value, true.

For the above case, the Ownerreference needs to be removed or added during the UPDATE event of a Build, meaning we need logic on the Build controller reconciler side.

Also please consider that this PR have quite a lot of test cases, both unit-tests and integration-tests. I recommend you to read the integration tests ones.

@qu1queee qu1queee requested review from HeavyWombat and removed request for sbose78 September 25, 2020 13:35
@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch from 17150eb to 9a9340a Compare September 25, 2020 14:04
@qu1queee qu1queee removed the request for review from adambkaplan September 25, 2020 14:11
@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch from ea0f11c to 11845fc Compare September 28, 2020 09:51
Copy link
Contributor

@HeavyWombat HeavyWombat left a comment

Choose a reason for hiding this comment

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

Provided a couple of comments where I would like to see the feedback first.

@HeavyWombat HeavyWombat mentioned this pull request Oct 5, 2020
@openshift-ci-robot openshift-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 7, 2020
@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch from 2a9640a to 0194f75 Compare October 7, 2020 11:31
@openshift-ci-robot openshift-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 7, 2020
@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch from dd9ce65 to 3993240 Compare October 7, 2020 11:51
@qu1queee qu1queee requested a review from HeavyWombat October 7, 2020 11:55
@qu1queee qu1queee changed the title Set ownerReference to build->buildrun WIP: Set ownerReference to build->buildrun Oct 7, 2020
@openshift-ci-robot openshift-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 7, 2020
@qu1queee qu1queee added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. and removed do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. labels Oct 7, 2020
@openshift-ci-robot openshift-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 15, 2020
@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch 2 times, most recently from 74a12b4 to d5dcb1f Compare October 15, 2020 10:20
@openshift-ci-robot openshift-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Oct 15, 2020
@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch 4 times, most recently from f3a32b5 to 6d208fa Compare October 19, 2020 16:07
@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch from 6d208fa to 0fecde8 Compare October 20, 2020 20:07
@qu1queee
Copy link
Contributor Author

/retest

if err := r.client.Update(ctx, &buildRun); err != nil {
return err
}
ctxlog.Info(ctx, fmt.Sprintf("succesfully updated BuildRun %s", buildRun.Name), namespace, buildRun.Namespace, name, buildRun.Name)
}
}
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

if it is else, the end user may set the AnnotationBuildRunDeletion to yes or aha, then it will also enter this logic which is not good.

Copy link
Contributor

@HeavyWombat HeavyWombat Oct 21, 2020

Choose a reason for hiding this comment

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

Good point, I would suggest to rewrite the if/else to a switch:

switch b.GetAnnotations()[build.AnnotationBuildRunDeletion] {
	case "true":
		// ...

	case "false":
		// ...

	default:
		// error case ...
}

Could also improve readability.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was on purpose, the important value was "false", but I agree it should be more strict. Fixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hold on, I didnt see @HeavyWombat comment, enhancing

Copy link
Contributor Author

@qu1queee qu1queee Oct 21, 2020

Choose a reason for hiding this comment

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

@HeavyWombat so I added this in

switch b.GetAnnotations()[build.AnnotationBuildRunDeletion] {
case "true":
// if the buildRun does not have an ownerreference to the Build, lets add it.
for _, buildRun := range buildRunList.Items {
if index := r.validateBuildOwnerReference(buildRun.OwnerReferences, b); index == -1 {
if err := r.setOwnerReferenceFunc(b, &buildRun, r.scheme); err != nil {
b.Status.Reason = fmt.Sprintf("unexpected error when trying to set the ownerreference: %v", err)
if err := r.client.Status().Update(ctx, b); err != nil {
return err
}
}
if err = r.client.Update(ctx, &buildRun); err != nil {
return err
}
ctxlog.Info(ctx, fmt.Sprintf("succesfully updated BuildRun %s", buildRun.Name), namespace, buildRun.Namespace, name, buildRun.Name)
}
}
case "false":
// if the buildRun have an ownerreference to the Build, lets remove it
for _, buildRun := range buildRunList.Items {
if index := r.validateBuildOwnerReference(buildRun.OwnerReferences, b); index != -1 {
buildRun.OwnerReferences = removeOwnerReferenceByIndex(buildRun.OwnerReferences, index)
if err := r.client.Update(ctx, &buildRun); err != nil {
return err
}
ctxlog.Info(ctx, fmt.Sprintf("succesfully updated BuildRun %s", buildRun.Name), namespace, buildRun.Namespace, name, buildRun.Name)
}
}
default:
ctxlog.Info(ctx, fmt.Sprintf("the annotation %s was not properly defined, supported values are true or false", build.AnnotationBuildRunDeletion), namespace, b.Namespace, name, b.Name)
return fmt.Errorf("the annotation %s was not properly defined, supported values are true or false", build.AnnotationBuildRunDeletion)
}

There is one caveat, if the user defines a wrong annotation value (not true or false), then the logic will return an error (ignored in the reconcile parent func) and we will get an INFO log (that illustrates the problem). Ideally I think we want the Build to reflect this issue in its Status.Reason and fail the Build Registration.

But I will prefer to do the above in a second pr, mainly because this use-case was not supported before. Opinions?

Copy link
Member

Choose a reason for hiding this comment

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

Agree, an annotation value that is neither true nor false is good to be reflected in the build status.I am okay doing this separately.

@zhangtbj
Copy link
Contributor

zhangtbj commented Oct 21, 2020

I am thinking if dynamically update the buildrun in build is a good way for the ownerReference way.

In the new solution, we need to get all buildrun every time no matter if we need to update the buildrun or not in each reconciliation. if there are lots of buildrun or once the build controller is restart, it may be slow.

So our goal is we can provide an option to allow end user:

  • delete the buildrun with build during the build deletion
  • keep all buildrun during the build deletion

So not sure if we can:

  • Set ALL new create buildrun with ownerReference DIRECTLY and BY DEFAULT
  • Do not update the buildrun in build to improve performance
  • Remove the AnnotationBuildRunDeletion and control it from UX level
  • When deleting the build, by default, all related buildrun will be deleted together. But if the user want to keep the buildruns by using UI or CLI/kubectl, we use the orphan delete policy:
curl -X DELETE 
<KUBE_API_SERVER>/.../<BUILD>...
-d '{
  "kind":"DeleteOptions",
  "apiVersion":"v1",
  "propagationPolicy":"Orphan"
}' 
-H "Content-Type: application/json"

or use kubectl delete --cascade=false to delete the build but keep all buildruns

Copy link
Contributor

@HeavyWombat HeavyWombat left a comment

Choose a reason for hiding this comment

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

Added comments where I see where we could further improve.

@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch 2 times, most recently from d5f6e9a to bead38a Compare October 21, 2020 07:59
@qu1queee
Copy link
Contributor Author

@zhangtbj thanks for the feedback.

In the new solution, we need to get all buildrun every time no matter if we need to update the buildrun or not in each reconciliation. if there are lots of buildrun or once the build controller is restart, it may be slow.

The above is a valid concern but is not fully accurate. It is correct that the Build controller will be looking for BuildRuns on every reconcile, however some key things to know are:

  • Build controller only reconciles on CREATE/UPDATE events.
  • For a CREATE event, a Build have 0 BuildRuns, therefore is not a concern in terms of performance. Actually listing is not that expensive for the amount of BuildRuns a Build can have.
  • For an UPDATE event where none BuildRuns are associated to a Build , listing BuildRuns is almost a no-op.
  • For an UPDATE event where BuildRuns are associated to a Build. During reconciliations, all associated BuildRuns will be listed(which is the only use case relate to what you mentioned). I dont think this is a concern in terms of performance. We have a selective filter for listing,only associated BuildRuns which are usually few.

Set ALL new create buildrun with ownerReference DIRECTLY and BY DEFAULT

This is already done in the buildrun controller, during the BuildRun creation only if the annotation is set to true.

Do not update the buildrun in build to improve performance

This is not possible at this point in time. The annotation belongs to the Build, and we watch for events of Build objects only in the Build controller.

Remove the AnnotationBuildRunDeletion and control it from UX level

I´m not sure what you mean.

When deleting the build, by default, all related buildrun will be deleted together. But if the user want to keep the buildruns by using UI or CLI/kubectl, we use the orphan delete policy

Not sure if I understand your point. If you want to keep the associated BuildRuns then do not use the "annotation". If you use the annotation all dependent objects will be deleted.

@zhangtbj
Copy link
Contributor

What I mean is:

  • We drop the annotation AnnotationBuildRunDeletion and do not use it any more, and for each new created buildrun, we set the OwnerReferences by default
  • The end user decide to delete all or keep all buildruns on UX side during the Build deletion:
    1. If end user wants to delete all buildruns, the OwnerReferences is set by default, so once delete the build, all buildruns will be deleted together
    2. If end user wants to keep all buildruns, they can operate on UI, like [x] Keep all buildruns, then during the build deletion, the UI can have a magic to call the kube api with orphan delete policy then all buildruns will be kept. Or from cli/kubectl level, just use a similar command kubectl delete --cascade=false can keep the all buildruns

It can keep our logic more easy and clear, I think.

@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch from bead38a to 5d00b09 Compare October 21, 2020 08:37
@qu1queee
Copy link
Contributor Author

qu1queee commented Oct 21, 2020

@zhangtbj can u take this requirement as a separate issue then? this pr is about replacing finalizers in favor of ownerreferenes, by keeping the same behaviour and more importantly adding test cases for the initial feature.

I honestly do not understand the UX rational you are saying. But as I said, please open another issue, this is not the right PR for it.

@zhangtbj
Copy link
Contributor

Sure thing.

Let me open another new issue to track the improvement for that.

routerhan and others added 3 commits October 21, 2020 11:37
This replace finalizers logic.

Add unit-test for the new ownerReference behaviour

Update documentation to illustrate the new approach
The above func is not longer needed, we assert for the behaviour
of an automatic deletion of a BuildRun in the integration test for
builds_and_buildruns.
@qu1queee qu1queee force-pushed the qu1queee/ownerreferences_build branch from 5d00b09 to 98b81eb Compare October 21, 2020 09:38
Copy link
Contributor

@HeavyWombat HeavyWombat left a comment

Choose a reason for hiding this comment

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

/lgtm

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Oct 21, 2020
Copy link
Member

@SaschaSchwarze0 SaschaSchwarze0 left a comment

Choose a reason for hiding this comment

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

/approve

@openshift-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: HeavyWombat, SaschaSchwarze0

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

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 21, 2020
@openshift-merge-robot openshift-merge-robot merged commit 95365d1 into shipwright-io:master Oct 21, 2020
@qu1queee qu1queee deleted the qu1queee/ownerreferences_build branch October 21, 2020 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Align with a single approach to delete owned objects
7 participants