feat: labeling all resources created by a zarf package#4194
feat: labeling all resources created by a zarf package#4194brandtkeller merged 13 commits intozarf-dev:mainfrom
Conversation
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
✅ Deploy Preview for zarf-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Codecov Report❌ Patch coverage is
🚀 New features to boost your workflow:
|
AustinAbro321
left a comment
There was a problem hiding this comment.
Thanks for making this change, I think it will be a positive for the project. Added a few nits and questions around scope
| // PackageLabel is the label used to identify the owning of package. | ||
| PackageLabel string = "zarf.dev/package" | ||
| // NamespaceOverrideLabel is the label used to identify the namespace override. | ||
| NamespaceOverrideLabel string = "zarf.dev/namespace-override" |
There was a problem hiding this comment.
A better place to put these constants would be in this block https://github.com/zarf-dev/zarf/blob/main/src/pkg/cluster/cluster.go#L31-L38
| return nil, fmt.Errorf("action configuration required to run post renderer") | ||
| } | ||
| if variableConfig == nil { | ||
| if opts.VariableConfig == nil { |
There was a problem hiding this comment.
I'd rather not have this function take opts. While it's semantically nicer, generally opts shouldn't be required. Also one of the goals with opts is to avoid breaking changes in function signatures, but since this is private we don't have to worry about that.
There was a problem hiding this comment.
I initially had it that way then went to opts because of the signature size and the fact that it was basically all of the "ops". I'm fine to revert back to explicit fields though
| } | ||
| } | ||
|
|
||
| namespace.Labels = r.setPackageLabels(namespace.Labels) |
There was a problem hiding this comment.
One implication that I'm thinking about here is that if two packages deploy resources to the same namespace then whichever deploy was more recent will take over and the label will change. Also, Zarf and Helm do not delete namespaces as well so these labels will stick around after the packages are removed from the cluster. Helm for instance doesn't add the app.kubernetes.io/name label to namespaces it creates. Still, these aren't necessarily a deal breaker to adding labels to namespaces as these side effects are relatively inconsequential, but I would like to evaluate it.
Could you provide more info about your use case @sgettys @Racer159. Is having this label on a namespace useful?
There was a problem hiding this comment.
We don't actually need the namespaces - we were just trying to be complete here - I would be fine with just not labeling namespaces actually - the need we had was for tracking Pods / Pod Owner resources.
There was a problem hiding this comment.
My thought around this was this label would be useful to at least denote the latest zarf package to operate against that namespace assuming multiple packages operate against it. We also discussed having a list of packages and appending instead of replacing but that could be confusing especially since you'd have to manage the label removal on package remove. In general I'm a fan of "labeling everything" including namespaces and this will at the bare minimum be a highly visible way to know if zarf has operated against a namespace or not
There was a problem hiding this comment.
I'm still somewhat torn, I could see it being useful on occasion. While it'd be rare, the argument against adding the label to namespaces is to avoid a user doing something such as making a script where they grab the namespaces deployed by their package, but suddenly having that script break when another package is deployed to that namespace. I agree that adding and removing different packages from the label is not worth the complexity.
I'm curious what the other @zarf-dev/maintainers think.
There was a problem hiding this comment.
Now that we have this functionality available it will be very easy to add this in for namespaces down the road if the use cases start popping up. I'll remove for now
There was a problem hiding this comment.
My 2 cents are that it is easy to add back if we need to in the future and can be left out as @sgettys mentioned - I do like completeness but if there are unexpected side effects that folks need to take into account it is worth holding off until we see more usecases - a list would be more complete but has its own side effects (what happens when a package is removed and the namespace is owned by two packages?).
| stdOut, stdErr, err = e2e.Kubectl(t, "wait", "deployment", "-l", "zarf.dev/package=manifests", "--for=condition=Available", "--all-namespaces", "--timeout=1m") | ||
| require.NoError(t, err, stdOut, stdErr) |
There was a problem hiding this comment.
So this is a bit interesting, initially I was going to say that this is unnecessary since Zarf waits for resources to be ready by default, but it actually is necessary because the podinfo deployment has an hpa which usually doesn't start scaling until after the deployment is already considered ready by Zarf. Probably it would be fine, but I don't want the hpa to take too long and not get caught by this wait, or make a third pod and fail the test. I think it's simpler to just test what we want in the dos-games test above.
There was a problem hiding this comment.
I do at least like selecting multiple resources from the same package and since "package pods" is really what I'm getting at with this whole labeling thing IMO this is a good testcase. I can make it less restrictive on number of pods though to account for hpa!
There was a problem hiding this comment.
Sounds good, but you should check for one or more replicas. A flake happened here because the check occurred before the hpa bumped up the replica count to two. https://github.com/zarf-dev/zarf/actions/runs/18012570063/job/51253428537?pr=4194
There was a problem hiding this comment.
Yeah I added that. Getting ready to push
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
|
|
||
| // UpdateZarfRegistryValues updates the Zarf registry deployment with the new state values | ||
| func UpdateZarfRegistryValues(ctx context.Context, opts InstallUpgradeOptions) error { | ||
| pkg, err := opts.Cluster.GetDeployedPackage(ctx, "init") |
There was a problem hiding this comment.
To make this work with custom named init packages we could use cluster.GetDeployedZarfPackages and grab the first package with kind: ZarfInitConfig
There was a problem hiding this comment.
Can we guarantee only a single ZarfInitConfig type?
There was a problem hiding this comment.
I have seen before situations where there are multiple ZarfInitConfig packages deployed. The most complete thing to do would be check for a package with ZarfInitConfig and a component named zarf-registry. Same with the agent update, check for a package with ZarfInitConfig and a component named zarf-agent.
Technically still possible for there to be two packages with those component names deployed, but I can't imagine a use case for it.
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
| return nil, fmt.Errorf("variable configuration required to run post renderer") | ||
| } | ||
| if pkgName == "" { | ||
| return nil, fmt.Errorf("package required to run post renderer") |
There was a problem hiding this comment.
| return nil, fmt.Errorf("package required to run post renderer") | |
| return nil, fmt.Errorf("package name required to run post renderer") |
| if err := yaml.Unmarshal([]byte(resource.Content), rawData); err != nil { | ||
| return fmt.Errorf("failed to unmarshal manifest: %w", err) | ||
| } | ||
| // If the object is empty, it's a blank resource, so we skip it. If the package is nil, we're not in a package and we don't want to add labels. |
There was a problem hiding this comment.
| // If the object is empty, it's a blank resource, so we skip it. If the package is nil, we're not in a package and we don't want to add labels. | |
| // If the object is empty, it's a blank resource, so we skip it. If the package name is empty we don't add labels. |
|
|
||
| // StartInjection initializes a Zarf injection into the cluster. | ||
| func (c *Cluster) StartInjection(ctx context.Context, tmpDir, imagesDir string, injectorSeedSrcs []string, registryNodePort int) error { | ||
| func (c *Cluster) StartInjection(ctx context.Context, tmpDir, imagesDir string, injectorSeedSrcs []string, registryNodePort int, pkg *v1alpha1.ZarfPackage) error { |
There was a problem hiding this comment.
Lets also use a string for package name here
AustinAbro321
left a comment
There was a problem hiding this comment.
A few small comments, very close to good to go
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
|
|
||
| func findInitPackageWithComponent(pkgs []state.DeployedPackage, componentName string) string { | ||
| for _, pkg := range pkgs { | ||
| if pkg.Data.Kind == "ZarfInitConfig" { |
There was a problem hiding this comment.
| if pkg.Data.Kind == "ZarfInitConfig" { | |
| if pkg.Data.Kind == v1alpha1.ZarfInitConfig { |
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
brandtkeller
left a comment
There was a problem hiding this comment.
LGTM - Thanks @Racer159 & @AustinAbro321 for doing the heavy lifting on review.
| for _, serverNamespace := range namespaceList.Items { | ||
| if serverNamespace.Name == name { | ||
| existingNamespace = true | ||
| break |
Description
Adds labels to all resources created by a zarf package:
This will allow for easy filtering of resources associated with a zarf package using label selectors.
Related Issue
Fixes #3625
Checklist before merging