-
Notifications
You must be signed in to change notification settings - Fork 545
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
[WIP] feat(resolver): add namespace and channel awareness #402
[WIP] feat(resolver): add namespace and channel awareness #402
Conversation
@@ -41,10 +41,10 @@ type Operator struct { | |||
*queueinformer.Operator | |||
client versioned.Interface | |||
namespace string | |||
sources map[registry.SourceKey]registry.Source |
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.
This is a bigger wrench than I intended to throw when I started looking at this PR...
But it strikes me that this type of tracking (for both "sources" and "subscriptions") is exactly what the cache and indexers are supposed to do for you in client-go.
We already have SharedIndexInformers for all of this available to the operator, so we can probably just use the index provided there.
Take a look at the cache tooling and see if you agree: https://github.com/kubernetes/client-go/tree/master/tools/cache
I would guess that it's as simple as keeping track of the SharedIndexInformers by namespace and then querying those.
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 think this makes a lot of sense when dealing with subscriptions since we don't need to do any additional work to pull it from the indexer's cache/store. Sources however, need an InMem instance constructed from the catalog source object and its config map before they are useful.
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.
Good point!
A future optimization to consider would be to disallow "internal" catalogsources (replacing them with pods that expose an API over the network), which would let us do the same caching for sources and remove the need to parse and keep all the contents in memory.
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.
Thanks!
Also, it's questionable at this point whether knowing about subscriptions at resolution time matters as much as knowing what's in the target namespace.
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.
Tracked in ALM-679, ignore this for this PR
a5bb9ce
to
788a510
Compare
// getExistingCSVNames returns a set of existing CSV names for the given namespace | ||
func (o *Operator) getExistingCSVNames(namespace string) (map[string]struct{}, error) { | ||
// Get a list of CSV CRs in the namespace | ||
csvList, err := o.client.OperatorsV1alpha1().ClusterServiceVersions(namespace).List(metav1.ListOptions{Watch: false}) |
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.
pretty sure Watch
is default false
} | ||
|
||
// Create a set of CSV names from the list | ||
existing := make(map[string]struct{}) |
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.
There's an edge case with this (and the consumer side in resolveCRDDescription
). There can be more than one CSV in a namespace that owns a CRD for a couple of reasons:
- Could be in the middle of upgrading
- Could have attempted to create one and failed (so status is failed but owner is still there)
- Anyone with
csv
create
permission can write arbitrary owned CRDs (they won't be accepted, but they can write them).
The simplest way to fix this would be to just fail the installplan if we see two csvs that own the CRD already in the namespace (we can't tell which to resolve). Ideally we would just retry the resolution after a bit, and only mark the installplan as truly "Failed" if we've tried a few times and never got a single owner for a CRD (which indicates a bad namespace state - something on the CSV side got stuck).
We could try to detect the upgrading states of the CSVs and watch them directly, but I'd rather keep things more decoupled between catalog/olm.
Anyway, this is returning a list of existing CSVs in the namespace, but I think what you actually want is a map from a CRDName to the CSVName in the namespace that owns it (then you don't have to loop both here and in resolveCRDDescription
). Depending on where it makes sense to have the failing logic, it may need to map crdname to a list of owners.
}, | ||
} | ||
|
||
for _, tt := range table { |
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.
want some test cases for when there are multiple CSVs that own the CRD in the namespace
@@ -399,10 +496,10 @@ func TestMultiSourceResolveInstallPlan(t *testing.T) { | |||
resolver := &MultiSourceResolver{} | |||
|
|||
// Test single catalog source resolution | |||
resolveInstallPlan(t, resolver) | |||
// resolveInstallPlan(t, resolver) |
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.
what's going on here?
This change enables dependency resolution to choose a (namespace) prexisting CSV to add as a step resource or if one does not exist, choose the CSV belonging to the package's default channel. This change also introduces wait for delete logic in installplan, csv, and crd cleanup functions. refactor(registry): export InMem.addPackageManifest method refactor(resolver): add awareness of prexisting CRD owners in target namespace Sends a mapping of CRD to existing owners in namespace as parameter to resolver. This allows the resolver to return an error if more than one preexisting CSV is discovered for a given dependent CRD. chore(vendor): stop tracking vendor directory
6402ae4
to
1cc9fe2
Compare
@@ -2,380 +2,487 @@ | |||
|
|||
|
|||
[[projects]] | |||
digest = "1:d8ebbd207f3d3266d4423ce4860c9f3794956306ded6c7ba312ecc69cdfbf04c" |
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 you re-vendor with dep
stable?
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.
looks really good! one small thing
crdKey := registry.CRDKey{ | ||
Kind: crdDesc.Kind, | ||
Name: crdDesc.Name, | ||
Version: crdDesc.Version, | ||
} | ||
logger.Debug("resolving") |
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.
thanks for cleaning up logs!
logger.WithField("owner", csvs[0].CSV.Name).Info("found owner") | ||
return v1alpha1.StepResource{}, csvs[0].CSV.Name, nil | ||
var ownerName string | ||
if owners, ok := existingCRDOwners[crdKey.Name]; ok && len(owners) > 0 { |
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.
could we make this control flow clearer?
doesn't have to be this, but something that removes the nesting:
owners, ok := existingCRDOwners[crdKey.Name]
if !ok {
ownerCount = 0
} else {
ownerCount = len(owners)
}
switch len(owners):
case 0:
// get default channel
case 1:
// found an owner
case >1:
// error
}
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.
LGTM
…-resolution feat(resolver): add namespace and channel awareness
…-resolution feat(resolver): add namespace and channel awareness
Description
Makes dependency resolution aware of default package channels and preexisting CSVs in an install plan's namespace.
Roughly addresses ALM-641 and ALM-469