Skip to content

feat: labeling all resources created by a zarf package#4194

Merged
brandtkeller merged 13 commits intozarf-dev:mainfrom
sgettys:3625_label_zarf_resources_with_package_name
Sep 26, 2025
Merged

feat: labeling all resources created by a zarf package#4194
brandtkeller merged 13 commits intozarf-dev:mainfrom
sgettys:3625_label_zarf_resources_with_package_name

Conversation

@sgettys
Copy link
Copy Markdown
Contributor

@sgettys sgettys commented Sep 17, 2025

Description

Adds labels to all resources created by a zarf package:

zarf.dev/package: <package name>
zarf.dev/namespace-override: <namespace if provided>

This will allow for easy filtering of resources associated with a zarf package using label selectors.

Related Issue

Fixes #3625

Checklist before merging

Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented Sep 17, 2025

Deploy Preview for zarf-docs ready!

Name Link
🔨 Latest commit f0b64fe
🔍 Latest deploy log https://app.netlify.com/projects/zarf-docs/deploys/68d6ea92095b530008b585f4
😎 Deploy Preview https://deploy-preview-4194--zarf-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@sgettys sgettys marked this pull request as ready for review September 17, 2025 22:23
@sgettys sgettys requested review from a team as code owners September 17, 2025 22:23
Comment thread src/api/v1alpha1/package.go Outdated
Comment thread src/internal/packager/helm/chart.go Outdated
Comment thread src/internal/packager/helm/chart.go Outdated
Comment thread src/internal/packager/helm/post-render.go Outdated
Comment thread src/test/e2e/26_simple_packages_test.go Outdated
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Comment thread src/internal/packager/helm/post-render.go Outdated
sgettys and others added 3 commits September 23, 2025 08:43
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
@codecov
Copy link
Copy Markdown

codecov Bot commented Sep 24, 2025

Codecov Report

❌ Patch coverage is 17.89474% with 78 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/internal/packager/helm/post-render.go 0.00% 45 Missing ⚠️
src/internal/packager/helm/zarf.go 0.00% 26 Missing ⚠️
src/pkg/packager/deploy.go 0.00% 5 Missing ⚠️
src/internal/packager/helm/chart.go 0.00% 2 Missing ⚠️
Files with missing lines Coverage Δ
src/pkg/cluster/cluster.go 36.57% <ø> (ø)
src/pkg/cluster/injector.go 65.62% <100.00%> (+0.69%) ⬆️
src/internal/packager/helm/chart.go 1.32% <0.00%> (ø)
src/pkg/packager/deploy.go 0.00% <0.00%> (ø)
src/internal/packager/helm/zarf.go 0.00% <0.00%> (ø)
src/internal/packager/helm/post-render.go 0.00% <0.00%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Member

@AustinAbro321 AustinAbro321 left a comment

Choose a reason for hiding this comment

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

Thanks for making this change, I think it will be a positive for the project. Added a few nits and questions around scope

Comment thread src/api/v1alpha1/package.go Outdated
Comment on lines +50 to +53
// 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"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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

@AustinAbro321 AustinAbro321 Sep 24, 2025

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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

@AustinAbro321 AustinAbro321 Sep 24, 2025

Choose a reason for hiding this comment

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

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?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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?).

Comment thread src/test/e2e/26_simple_packages_test.go Outdated
Comment on lines +100 to +101
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)
Copy link
Copy Markdown
Member

@AustinAbro321 AustinAbro321 Sep 24, 2025

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yeah I added that. Getting ready to push

Comment thread src/pkg/packager/deploy.go Outdated
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Comment thread src/internal/packager/helm/zarf.go Outdated

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

Choose a reason for hiding this comment

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

To make this work with custom named init packages we could use cluster.GetDeployedZarfPackages and grab the first package with kind: ZarfInitConfig

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Can we guarantee only a single ZarfInitConfig type?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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.

Comment thread src/internal/packager/helm/chart.go Outdated
Comment thread src/pkg/cluster/cluster.go Outdated
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")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
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.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// 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.

Comment thread src/pkg/cluster/injector.go Outdated

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

Choose a reason for hiding this comment

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

Lets also use a string for package name here

Copy link
Copy Markdown
Member

@AustinAbro321 AustinAbro321 left a comment

Choose a reason for hiding this comment

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

A few small comments, very close to good to go

sgettys and others added 2 commits September 26, 2025 09:35
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Comment thread src/internal/packager/helm/zarf.go Outdated

func findInitPackageWithComponent(pkgs []state.DeployedPackage, componentName string) string {
for _, pkg := range pkgs {
if pkg.Data.Kind == "ZarfInitConfig" {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
if pkg.Data.Kind == "ZarfInitConfig" {
if pkg.Data.Kind == v1alpha1.ZarfInitConfig {

sgettys and others added 2 commits September 26, 2025 12:32
Signed-off-by: Steven Gettys <steven.gettys@defenseunicorns.com>
Copy link
Copy Markdown
Member

@AustinAbro321 AustinAbro321 left a comment

Choose a reason for hiding this comment

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

LGTM, nice work

Copy link
Copy Markdown
Member

@brandtkeller brandtkeller left a comment

Choose a reason for hiding this comment

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

LGTM - Thanks @Racer159 & @AustinAbro321 for doing the heavy lifting on review.

for _, serverNamespace := range namespaceList.Items {
if serverNamespace.Name == name {
existingNamespace = true
break
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

++ good catch

@brandtkeller brandtkeller added this pull request to the merge queue Sep 26, 2025
Merged via the queue into zarf-dev:main with commit 6c4aa24 Sep 26, 2025
27 checks passed
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.

Add zarf label to all resources created by a package deploy

4 participants