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

Improved namespace handling for manifest reporting #1423

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

APErebus
Copy link
Contributor

@APErebus APErebus commented Jan 15, 2025

Currently, for non-namespaced resource types (such as a PersistentVolume, or ClusterRoleBinding), they are reported with the implicit namespace.

This is a less than ideal solution as it gives an incorrect impression of the namespace of the resources, especially for manifest inspection.

This PR updates the manifest reporting to make a kubectl call to api-resources which returns an output that contains all the know resource types and if they are namespaced are not. Unfortunately it's a shitty format and can't be outputted as json, so we have a specific parser.

If we can't load that info, we then have a preset list of known values as a fallback.

We then use this lookup to work out if we need to remove any namespace information.

We only remove namespace information for resources where we know they are non-namespaced

A large chunk of this PR is cribbed from @liam-mackie's previous work.

EDIT:

As the helm KOS code performs a similar action for resolving the namespace, I have coalesced this logic into a new class, the KubernetesManifestNamespaceResolver. This code is responsible for the logic around what namespace to resolve based on the manifest, the variables and if we know if it's a namespaced resource or not (via the new cli call above)

Further info

There are a number of scenario's that can occur. In the following scenario's, "known" or "unknown" refers to if the cluster knows about the resource type and can tell us if it's namespaced or not.

A namespaced resource has the namespace in the manifest

✔️ The namespace in the manifest is used

A namespaced resouce does not have a namespace in the manifest

✔️ The implicit namespace is used

A unknown namespaced resource has a namespace in the manifest

✔️ The namespace in the manifest is used

A unknown namespaced resource does not have a namespace in the manifest

✔️ The implicit namespace is used

A known non-namespaced resource does not have a namespace in the manifest

✔️ The namespace is null

A known non-namespaced resource has a namespace in the manifest

✔️ The namespace in the manifest is ignored and the namespace is null

A unknown non-namespaced resource has a namespace in the manifest

❓ The namespace in the manifest is used. This is incorrect, but we can't know any different.

A unknown non-namespaced resource does not have a namespace in the manifest

❓ The implicit namespace in the manifest is used. This is incorrect, but we can't know any different.

{
List<string> outputLines = new List<string>
{
"NAME SHORTNAMES APIVERSION NAMESPACED KIND VERBS CATEGORIES",
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sample output

var activeColumn = new Column();

var previousChar = SpaceChar;
for (var i = 0; i < headerRow.Length; i++)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

we use the width of the headers as to dictate how we substring each row

Comment on lines +43 to +44
log.Warn("Unable to retrieve resource scoping using kubectl api-resources. Using default resource scopes.");
return DefaultResourceScopeLookup;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Any error here is warned, but we fallback to our defaults

source/Calamari/Kubernetes/ManifestReporter.cs Outdated Show resolved Hide resolved
//we check to see if there is an explicit helm namespace defined first
//then fallback on the action/target default namespace
//otherwise fallback on default
return variables.Get(SpecialVariables.Helm.Namespace) ?? variables.Get(SpecialVariables.Namespace) ?? "default";
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Helm steps can have their own default namespace, so fallback on that first, then the target/action namespace, then the cluster default

string ResolveNamespace(YamlMappingNode rootManifestNode, IVariables variables);
}

public class KubernetesManifestNamespaceResolver : IKubernetesManifestNamespaceResolver
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the new class that contains all the logic for resolving a namespace for a given manifest root node.

@@ -83,63 +92,31 @@ public void GivenInValidManifest_ShouldNotPostServiceMessage(string enabledFeatu

[TestCase(nameof(FeatureToggle.KubernetesLiveObjectStatusFeatureToggle))]
[TestCase(OctopusFeatureToggles.KnownSlugs.KubernetesObjectManifestInspection)]
public void GivenNamespaceInManifest_ShouldReportManifestNamespace(string enabledFeatureToggle)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We don't test this kind of logic in the manifest reporter as this is the responsibility of the KubernetesManifestNamespaceResolver

Copy link
Contributor

@eddymoulton eddymoulton left a comment

Choose a reason for hiding this comment

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

Just a test I think could be better, but otherwise looks solid.

Comment on lines +45 to +46
parsedResult.Should()
.NotBeEmpty();
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be worth asserting that the output is as expected - I'd be happy with a really cut down list compared to what you've got to save the typing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah yeah, I meant to do that. I think the original reason it was like this was I was using the test to debug and fix it... Good catch!

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