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

Skip resources that are NotFound for dependency calculation #1519

Merged
merged 5 commits into from
May 14, 2020

Conversation

ANeumann82
Copy link
Member

@ANeumann82 ANeumann82 commented May 14, 2020

What this PR does / why we need it:
The easiest fix for the referenced issue is to simply ignore resources that are reported as "NotFound" from the API server. The deployment/statefulset/etc can still be applied, and k8s will correctly use the referenced config maps/secrets as soon as they are available, therefore not blocking KUDO.

The downside is that the next time the deployment/statefulset/etc gets deployed the hash changes and triggers a pod reload, but I think that's an acceptable downside.

Additionally, we can't rely on the LastAppliedTemplateAnnotation, as this annotation is only available on resources deployed by KUDO. We may encounter references that are applied either manually or by other controllers that don't have this annotation.

The fix for this is to fall back to the object itself if the annotation is not available, and nil most fields on the Unstructured object that may affect the hash calculation.

Fixes #1517 #1521

Signed-off-by: Andreas Neumann aneumann@mesosphere.com

Signed-off-by: Andreas Neumann <aneumann@mesosphere.com>
Copy link
Contributor

@zen-dog zen-dog left a comment

Choose a reason for hiding this comment

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

Nice solution 👏 And I agree that the downside is reasonable. Would you mind adding a regression test?

Signed-off-by: Andreas Neumann <aneumann@mesosphere.com>
Copy link
Member

@zmalik zmalik left a comment

Choose a reason for hiding this comment

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

let's also skip when there is no LastAppliedConfigAnnotation annotation

annotations, _, _ := unstructured.NestedMap(unstructMap, "spec", "template", "metadata", "annotations")
assert.NotNil(t, annotations, "Statefulset pod template spec contains no annotations")

hash := annotations[kudo.DependenciesHashAnnotation]
Copy link
Member

Choose a reason for hiding this comment

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

👏

…nal object

Signed-off-by: Andreas Neumann <aneumann@mesosphere.com>
Copy link
Member

@kensipe kensipe left a comment

Choose a reason for hiding this comment

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

I have questions and things I would prefer to have addressed

but it does look like this fixes an issue and is reasonable...

@@ -138,16 +139,25 @@ func (de *dependencyCalculator) getHashForDependency(d resourceDependency) (hash
if err != nil {
return hashBytes{}, fmt.Errorf("failed to get dependeny %s/%s: %v", d.namespace, d.name, err)
}

if dep == nil {
Copy link
Member

Choose a reason for hiding this comment

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

usually there is an apierrors.IsNotFound(err) or the like... how do we know that dep==nil is NotFound?
It isn't clear if the message below is correct

pkg/engine/renderer/dependencies.go Outdated Show resolved Hide resolved
// we may encounter objects that are not deployed by KUDO and therefore do not have the LastAppliedConfigAnnotation.
// This is a best effort attempt to make the hash as stable as possible
v := int64(0)
obj.SetResourceVersion("")
Copy link
Member

Choose a reason for hiding this comment

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

I would be interesting in how to created this list
It is unclear to me if this "overkill" , "insufficient" or "just right"

Copy link
Member Author

Choose a reason for hiding this comment

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

It's certainly overkill :) I basically went through all setters on Unstructured...

pkg/engine/renderer/dependencies.go Outdated Show resolved Hide resolved
@@ -190,6 +222,9 @@ func (de *dependencyCalculator) resourceDependency(d resourceDependency) (*unstr
}

err := de.Client.Get(context.TODO(), key, dep)
if apierrors.IsNotFound(err) {
Copy link
Member

Choose a reason for hiding this comment

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

this is semantics or opinion (so not blocking to me) but I would rather have the isNotFound(err) by the calling client than pass a (nil, nil) as something meaningful

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've decided against it. I've tried it, and i'd have to either:

return err here, without adding an fmt.Errorf("some nice message %w", err). At least it's a non-public func.

or I have to do

if (apierrors.IsNotFound(errors.Unwrap(err)) { on the caller side.

Both solutions don't really sit well with me.

I get where you're coming from, but in this case I prefer the nil, nil return.

Signed-off-by: Andreas Neumann <aneumann@mesosphere.com>
Signed-off-by: Andreas Neumann <aneumann@mesosphere.com>
@ANeumann82 ANeumann82 merged commit fdfe356 into master May 14, 2020
@ANeumann82 ANeumann82 deleted the an/skip-404-resources-for-dependencies branch May 14, 2020 16:06
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.

KUDO can get stuck in plan when indirect resource is referenced
4 participants