Resolve and unpack operators from bundle images#1081
Resolve and unpack operators from bundle images#1081jpeeler wants to merge 9 commits intooperator-framework:masterfrom
Conversation
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: jpeeler The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
njhale
left a comment
There was a problem hiding this comment.
Looks promising! Here's the feedback/questions I have so far:
| // Generation represents a set of operators and their required/provided API surfaces at a point in time. | ||
| type Generation interface { | ||
| AddOperator(o OperatorSurface) error | ||
| AddPendingOperator(l LaunchBundleImageInfo) |
There was a problem hiding this comment.
The other methods take an interface as input, which is a classic go idiom. Is there some way we can use OperatorSurface without changing its API (e.g. tack new fields on OperatorSourceInfo, for which there is already a getter)? If not, does it make sense to define a new interface?
b192cb9 to
1f749ec
Compare
1f749ec to
c4d3879
Compare
c4d3879 to
6b025da
Compare
6b025da to
7a35d3b
Compare
| lister: lister, | ||
| namespace: operatorNamespace, | ||
| resolver: resolver.NewOperatorsV1alpha1Resolver(lister, crClient), | ||
| resolver: resolver.NewOperatorsV1alpha1Resolver(lister, crClient, opClient.KubernetesInterface(), operatorNamespace), |
There was a problem hiding this comment.
It's used for launching the bundle image (LaunchBundleImage).
| return nil, nil, nil, err | ||
| } | ||
| for _, ip := range ips { | ||
| for _, lookup := range ip.Status.BundleLookups { |
There was a problem hiding this comment.
I think I'm missing why this is needed - can't you just return the whole set of pending operators as BundleLookups that the installplan should unpack?
There was a problem hiding this comment.
I do have a TODO here to investigate improving. Without it install plans get duplicated due to the next loop doing a resolve (again) and repeating. The only way that I can see to avoid this is by checking all the install plans for the image.
| for bundleImageInfo := range gen.PendingOperators() { | ||
| // TODO: switch image to standalone image, but this image can be used upstream as well | ||
| // change to use configmapRegistryImage | ||
| //configmap, job, err := configmap.LaunchBundleImage(r.kubeclient, bundleImageInfo.image, "quay.io/openshift/origin-operator-registry:latest", r.operatorNamespace) |
There was a problem hiding this comment.
to clarify our discussion last night, you should use the actual variable "configmapRegistryImage" from pkg/catalogoperator.go NewOperator, not quay.io/openshift/origin-operator-registry:latest
|
|
||
| // TODO: this may not actually be required if the requeue is done on the namespace rather than the installplan | ||
| // RequeueAfter requeues the resource in the set with the given name and namespace (just like Requeue), but only does so after duration has passed | ||
| func (r *ResourceQueueSet) RequeueAfter(namespace, name string, duration time.Duration) error { |
There was a problem hiding this comment.
Can we watch Jobs and requeue owner installplans when we see them?
There was a problem hiding this comment.
Yeah it's a good idea and is something I was considering.
| // change to use configmapRegistryImage | ||
| //configmap, job, err := configmap.LaunchBundleImage(r.kubeclient, bundleImageInfo.image, "quay.io/openshift/origin-operator-registry:latest", r.operatorNamespace) | ||
|
|
||
| configmap, job, err := configmap.LaunchBundleImage(r.kubeclient, bundleImageInfo.image, "quay.io/jpeeler/bundle-init-image:latest", r.operatorNamespace) |
There was a problem hiding this comment.
where do these get cleaned up?
(this is not necessarily blocking, we can follow up with GC)
There was a problem hiding this comment.
we could return the pending operators from the resolver without launching them?
then when we create the installplan, write the "bundlelookups" into it
then when we process the installplan, launch jobs for any bundlelookups that don't have corresponding jobs?
this would also mean that when we launch, we have an installplan, so we can add ownerrefs, so we can watch jobs and requeue based on ownerref 😄
There was a problem hiding this comment.
you are correct that they aren't yet
7a35d3b to
ff053aa
Compare
|
This isn't merge-able 😩 The e2e currently has exactly double steps, which seems like resources are getting added from the bundle (which in this case has a CSV) and the bundle image. Code generation has not been done, unit tests aren't updated. |
a0ce61c to
98c5c60
Compare
98c5c60 to
c92e933
Compare
|
/hold This is a blocking PR that needs to be merged first (but could possibly change due to feedback received here): |
7ff60a6 to
0f9ef8d
Compare
0f9ef8d to
f287292
Compare
e750321 to
bc0b9e0
Compare
bc0b9e0 to
8f29811
Compare
8f29811 to
530adf5
Compare
530adf5 to
69ece0d
Compare
Specifically, pulls in v1.5.5.
This extracts bundle data from an image and uses that data to populate the installplan. (The code here depends on later commits.)
WIP: this is currently using a local custom image.
Instead use image that is pullable from quay. Test data has been updated to include image building files.
The test data for generating this custom image uses a go script to generate and populate an operator registry database that references a bundle image.
69ece0d to
9707998
Compare
|
/retest |
|
@jpeeler: The following tests failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. DetailsInstructions 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. I understand the commands that are listed here. |
| } | ||
|
|
||
| func (o *Operator) checkBundleLookups(plan *v1alpha1.InstallPlan) (bool, error) { | ||
| for _, bundleLookup := range plan.Status.BundleLookups { |
There was a problem hiding this comment.
Over the course of our work on OLM, we've developed an idiomatic way of reconciling resources:
- Build state from cluster
- Inform cluster action from state; or
- Update resource status from state
I think that we can run into trouble if we jump straight to 2. without first performing 1., or by coupling 2. and 3.
In this case, do you think we can:
- build the state before actioning on it; i.e. Check for
ConfigMaps/Jobsbefore creating them - update the
InstallPlanobject once per reconciliation
There was a problem hiding this comment.
This is a good plan - we just need a deterministic way to name the configmaps/jobs from the installplan. InstallPlanName + image name would make sense, or a hash of that info.
| catalogSubscriberIndexer map[string]cache.Indexer | ||
| clientAttenuator *scoped.ClientAttenuator | ||
| serviceAccountQuerier *scoped.UserDefinedServiceAccountQuerier | ||
| bundleLoader *configmap.BundleLoader |
There was a problem hiding this comment.
I think in an ideal world this would be an interface. It would be nice if we had other options than unpacking into a configmap in the future. But we can do that as a separate refactoring after this merges.
| serviceAccountQuerier: scoped.NewUserDefinedServiceAccountQuerier(logger, crClient), | ||
| clientAttenuator: scoped.NewClientAttenuator(logger, config, opClient, crClient), | ||
| bundleLoader: configmap.NewBundleLoader(), | ||
| configmapRegistryImage: configmapRegistryImage, |
There was a problem hiding this comment.
We probably want a separate variable for "bundleUnpackerImage". In OpenShift this will end up the same image (registry image) but they do different things and there's no reason they should have to be the same.
| } | ||
|
|
||
| func (o *Operator) checkBundleLookups(plan *v1alpha1.InstallPlan) (bool, error) { | ||
| for _, bundleLookup := range plan.Status.BundleLookups { |
There was a problem hiding this comment.
This is a good plan - we just need a deterministic way to name the configmaps/jobs from the installplan. InstallPlanName + image name would make sense, or a hash of that info.
| } | ||
|
|
||
| // extract data from configmap and write to install plan | ||
| bundle, err := o.bundleLoader.Load(configmap) |
There was a problem hiding this comment.
That makes sense but is not critical, IMO. Installing via installplan steps ensures we install via a well-tested path. But, this would be a great followup and will enable installplans to install larger sets of objects.
|
Superseded by #1215, which has now merged. |
|
@jpeeler: PR needs rebase. DetailsInstructions 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. |
No description provided.