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

[WIP] feat(resolver): add namespace and channel awareness #402

Merged
merged 4 commits into from
Aug 8, 2018

Conversation

njhale
Copy link
Member

@njhale njhale commented Jul 31, 2018

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

@@ -41,10 +41,10 @@ type Operator struct {
*queueinformer.Operator
client versioned.Interface
namespace string
sources map[registry.SourceKey]registry.Source
Copy link
Member

@ecordell ecordell Aug 2, 2018

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.

Copy link
Member Author

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.

Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

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

@njhale njhale force-pushed the namespace-aware-resolution branch from a5bb9ce to 788a510 Compare August 3, 2018 11:49
// 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})
Copy link
Member

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{})
Copy link
Member

@ecordell ecordell Aug 7, 2018

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 {
Copy link
Member

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)
Copy link
Member

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
@njhale njhale force-pushed the namespace-aware-resolution branch from 6402ae4 to 1cc9fe2 Compare August 7, 2018 22:17
@@ -2,380 +2,487 @@


[[projects]]
digest = "1:d8ebbd207f3d3266d4423ce4860c9f3794956306ded6c7ba312ecc69cdfbf04c"
Copy link
Member

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?

Copy link
Member

@ecordell ecordell left a 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")
Copy link
Member

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 {
Copy link
Member

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
}

Copy link
Member

@ecordell ecordell left a comment

Choose a reason for hiding this comment

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

LGTM

@njhale njhale merged commit bed2541 into operator-framework:master Aug 8, 2018
@njhale njhale deleted the namespace-aware-resolution branch August 15, 2018 22:55
njhale added a commit to njhale/operator-lifecycle-manager that referenced this pull request Sep 10, 2018
…-resolution

feat(resolver): add namespace and channel awareness
ecordell pushed a commit to ecordell/operator-lifecycle-manager that referenced this pull request Mar 8, 2019
…-resolution

feat(resolver): add namespace and channel awareness
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants