-
Notifications
You must be signed in to change notification settings - Fork 231
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
create DownstreamPackage controller #3684
create DownstreamPackage controller #3684
Conversation
1771f69
to
7cd6edd
Compare
porch/controllers/downstreampackages/api/v1alpha1/downstreampackage_types.go
Outdated
Show resolved
Hide resolved
|
||
type Upstream struct { | ||
Repo string `json:"repo,omitempty"` | ||
Package string `json:"package,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like this essentially identifies a single PackageRevision resource. Should we use the name of the resource instead of Package
and Revision
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that the resource name of package revisions is auto-generated, that would make this resource very hard to create and read for users, and would require the creation of the package revision prior to the creation of this resource. Generally that's probably going to be the case, but frankly the package revision name is more like a machine generated pointer than something useful. Of course, if this resource is being generated by a controller, this is not really an issue. Usually that is probably the case.
The expected general use of this would be to update the Revision number and trigger upgrades (or downgrades). So keeping these separate makes that easier. This does raise the issue of what happens if someone points this resource at a completely different upstream package, with respect to updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see @johnbelamaric's point that if someone is trying to manage a DownstreamPackage resource manually, looking up the package revision resource name for each update can be tedious and perhaps error prone, since it is an auto-generated hash. But the DownstreamPackage is generally going to be created by the UpstreamPolicy controller when it is ready, so this will be less of an issue.
Having the repo/package/revision separate means that the DownstreamPackage controller has put a little more effort into looking up the upstream package revision. If it instead takes the name of the packagerevision resource, the UpstreamPolicy controller will have to do the lookup and pass that to the DownstreamPackage. Either way, we will need to have that lookup somewhere; I think the question is just which controller should we put it in. Personally I don't think that it matters too much, but since the UpstreamPolicy controller is already going to be somewhat complex, maybe it makes sense to delegate the lookup to the DownstreamPackage, and keep the repo/package/revision separate here. That said, I don't mind changing it if you feel differently.
This does raise the issue of what happens if someone points this resource at a completely different upstream package, with respect to updates.
IIRC porch doesn't let you update a package to a completely different package. We started discussing what that means here. I think that in order to completely change the upstream package of the DownstreamPackage, you'd also have to change (or delete) the downstream package target, essentially resulting in a brand new deployment package.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm ok with using Package
and Revision
. We should see if we can use field selectors to be able to do the filtering server-side instead of client-side.
I don't actually remember if kpt errors out if the new upstream is a completely different package. We should probably verify the behavior here. Regardless we need to be prepared for situations where the automatic update fails, since there might be conflicts that can't be automatically resolved.
...rollers/downstreampackages/pkg/controllers/downstreampackage/downstreampackage_controller.go
Outdated
Show resolved
Hide resolved
...rollers/downstreampackages/pkg/controllers/downstreampackage/downstreampackage_controller.go
Show resolved
Hide resolved
func (r *DownstreamPackageReconciler) isUpToDate(dp *api.DownstreamPackage, downstream *porchapi.PackageRevision) bool { | ||
upstreamLock := downstream.Status.UpstreamLock | ||
lastIndex := strings.LastIndex(upstreamLock.Git.Ref, "/") | ||
if strings.HasPrefix(upstreamLock.Git.Ref, "drafts") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't we just check the lifecycle
field on the PackageRevision for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have the target upstream package revision (the one we want to update to), and the current downstream package revision. But we don't have the upstream package that the current downstream package is currently based on - which is what we need in order to determine if downstream package revision is up to date.
All we have is the reference to that current upstream package revision in the downstream package's upstreamLock.Git.Ref
- so no, we don't have a PackageRevision.Lifecycle field to refer to here.
Fetching that current upstream package revision involves tedious loops and string parsing of upstreamLock.Git.Ref
(and somewhere in that logic would still include checking for the drafts
prefix so we can parse the ref properly), so IMO just checking for the drafts
prefix is the best thing to do here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we could use the lifecycle field for checking if the PackageRevision is a draft, but agree we would still need to parse the upstreamLock to determine the current upstream packagerevision it is based on. So I think doing it this way is fine.
Long term we need to figure out a better way to expose information about the upstream of a package in PackageRevision API. If we want this controller to also support OCI, this would get pretty complicated.
...rollers/downstreampackages/pkg/controllers/downstreampackage/downstreampackage_controller.go
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just two small nits, but overall looks good.
We also need to find a pattern for how we want to test the controllers, but that is an issue with all of them at the moment.
AdoptionPolicyAdoptNone AdoptionPolicy = "adoptNone" | ||
|
||
DeletionPolicyDelete DeletionPolicy = "delete" | ||
DeletionPolicyDisown DeletionPolicy = "orphan" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: We should also update the variable name to use the term orphan
.
|
||
type Upstream struct { | ||
Repo string `json:"repo,omitempty"` | ||
Package string `json:"package,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I'm ok with using Package
and Revision
. We should see if we can use field selectors to be able to do the filtering server-side instead of client-side.
I don't actually remember if kpt errors out if the new upstream is a completely different package. We should probably verify the behavior here. Regardless we need to be prepared for situations where the automatic update fails, since there might be conflicts that can't be automatically resolved.
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRoleBinding | ||
metadata: | ||
name: porch-system:porch-controllers-downstreampackage |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The convention I've been trying to follow with the other controllers is that the suffix here should match the name of the directory for the controller. So we should make this porch-controllers-downstreampackages
.
func (r *DownstreamPackageReconciler) isUpToDate(dp *api.DownstreamPackage, downstream *porchapi.PackageRevision) bool { | ||
upstreamLock := downstream.Status.UpstreamLock | ||
lastIndex := strings.LastIndex(upstreamLock.Git.Ref, "/") | ||
if strings.HasPrefix(upstreamLock.Git.Ref, "drafts") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So we could use the lifecycle field for checking if the PackageRevision is a draft, but agree we would still need to parse the upstreamLock to determine the current upstream packagerevision it is based on. So I think doing it this way is fine.
Long term we need to figure out a better way to expose information about the upstream of a package in PackageRevision API. If we want this controller to also support OCI, this would get pretty complicated.
Yeah, I think we'll need to raise an error in the package revision status. |
4bc787a
to
ec996c8
Compare
What this PR does:
DownstreamPackage
controller as discussed in Porch: BaseRevision controller aka Fan Out controller - but more #3488What this PR does not do (will be coming in a followup PR):