Skip to content
This repository was archived by the owner on Apr 17, 2025. It is now read-only.

Commit 8202889

Browse files
committed
adding new --exclude-resources-with-label manager CLI argument. Changed default exclusion by label mechanism to use this CLI argument instead of a hardcoded list of labels. Moved the default Rancher label exclusion to be a default CLI argument on the manager
Tested: made sure the current test for default exclusion fails after my change, changed the test to reflect the changes, test now passes as expected. Executed e2e tests and they pass. Manually tested running the manager with the new CLI argument and with that my labeled resource was skipped, then removed the argument and it was propagated. Did the same with two different annotations specified together as two CLI arguments, and resources that had any of those labels were skipped as expected.
1 parent 168dd7e commit 8202889

File tree

7 files changed

+69
-18
lines changed

7 files changed

+69
-18
lines changed

cmd/manager/main.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package main
1818
import (
1919
"errors"
2020
"flag"
21+
"fmt"
2122
"net/http"
2223
"os"
2324
"strings"
@@ -50,8 +51,9 @@ import (
5051
)
5152

5253
var (
53-
scheme = runtime.NewScheme()
54-
setupLog = zap.New().WithName("setup")
54+
scheme = runtime.NewScheme()
55+
setupLog = zap.New().WithName("setup")
56+
excludeResourcesWithLabel = make(mapArg)
5557
)
5658

5759
var (
@@ -156,10 +158,18 @@ func parseFlags() {
156158
flag.BoolVar(&enableHRQ, "enable-hrq", false, "Enables hierarchical resource quotas")
157159
flag.StringVar(&hncNamespace, "namespace", "hnc-system", "Namespace where hnc-manager and hnc resources deployed")
158160
flag.DurationVar(&hrqSyncInterval, "hrq-sync-interval", 1*time.Minute, "Frequency to double-check that all HRQ usages are up-to-date (shouldn't be needed)")
161+
flag.Var(excludeResourcesWithLabel, "exclude-objects-with-label", "An annotation specified as key=val that, if present, will cause HNC to skip objects that match this label. May be specified multiple times, with each instance specifying one label. See the user guide for more information.")
159162
flag.Parse()
160163

161164
// Assign the array args to the configuration variables after the args are parsed.
162165
config.UnpropagatedAnnotations = unpropagatedAnnotations
166+
167+
// Assign the exclusion label args to the configuration
168+
for key, value := range excludeResourcesWithLabel {
169+
setupLog.Info(fmt.Sprintf("Will exclude objects that match label %s=%s", key, value))
170+
config.ExclusionByLabels = append(config.ExclusionByLabels, config.ExclusionByLabelsSpec{Key: key, Value: value})
171+
}
172+
163173
config.SetNamespaces(includedNamespacesRegex, excludedNamespaces...)
164174
if err := config.SetManagedMeta(managedNamespaceLabels, managedNamespaceAnnots); err != nil {
165175
setupLog.Error(err, "Illegal flag values")
@@ -333,3 +343,29 @@ func (a *arrayArg) Set(val string) error {
333343
*a = append(*a, val)
334344
return nil
335345
}
346+
347+
// mapArg is an arg that can be specified multiple times. All usages are
348+
// merged into this single map. Should be used by specifying `key=val`.
349+
type mapArg map[string]string
350+
351+
func (m mapArg) String() string {
352+
var items []string
353+
354+
for key, value := range m {
355+
items = append(items, fmt.Sprintf("%s=\"%s\"", key, value))
356+
}
357+
358+
return strings.Join(items, ", ")
359+
}
360+
361+
func (m mapArg) Set(val string) error {
362+
if !strings.Contains(val, "=") {
363+
return errors.New("a map entry must be a key=val pair")
364+
}
365+
keyVal := strings.Split(val, "=")
366+
if len(keyVal[0]) == 0 {
367+
return errors.New("a map key must not be empty")
368+
}
369+
m[keyVal[0]] = keyVal[1]
370+
return nil
371+
}

config/manager/manager.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ spec:
4949
- "--excluded-namespace=kube-public"
5050
- "--excluded-namespace=hnc-system"
5151
- "--excluded-namespace=kube-node-lease"
52+
- "--exclude-objects-with-label=cattle.io/creator=norman"
5253
ports:
5354
- containerPort: 9443
5455
name: webhook-server

docs/user-guide/concepts.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,10 @@ objects from being propagated by HNC.
378378
auto-created in new namespaces by Istio and Kubernetes respectively
379379
* Any objects with the label
380380
`cattle.io/creator:norman`, which are [inserted by Rancher to support
381-
Projects](https://rancher.com/docs/rancher/v2.6/en/system-tools/#remove))
381+
Projects](https://rancher.com/docs/rancher/v2.6/en/system-tools/#remove)).
382+
Can be disabled by removing the default command line argument on the manager
383+
`--exclude-objects-with-label=cattle.io/creator=norman`. Refer to [How-to:
384+
Modify command-line arguments](how-to.md#modify-command-line-arguments) for more details.
382385
* *HNC v1.1+:* Secrets with type `helm.sh/release.v1`, which is auto-created in
383386
the namespaces where their respective Helm releases are deployed to.
384387

docs/user-guide/how-to.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,3 +956,10 @@ Interesting parameters include:
956956
load on your metrics database (through increased metric cardinality) and also
957957
by increasing how carefully you need to guard your metrics against
958958
unauthorized viewers.
959+
* `--exclude-objects-with-label`: present by default with label
960+
`cattle.io/creator=norman` in order to exclude objects created by Rancher
961+
(refer to [Concepts: built in exceptions](concepts.md#built-in-exceptions)
962+
for more information).
963+
This argument may be specified multiple times, with each parameter representing
964+
a pair of key and value that represent a label that should exclude an object from
965+
propagation. Must have the `key=val` format.

internal/config/default_config.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,14 @@ package config
88
// This value is controlled by the --unpropagated-annotation command line, which may be set multiple
99
// times.
1010
var UnpropagatedAnnotations []string
11+
12+
// ExclusionByLabelsSpec specifies a label Key and Value which will cause an object to be excluded
13+
// from propagation if the object defines that label with this specific value.
14+
type ExclusionByLabelsSpec struct {
15+
Key string
16+
Value string
17+
}
18+
19+
// ExclusionByLabels is a configuration slice that contains all ExclusionByLabelSpec labels that should
20+
// cause objects to be ignored from propagation.
21+
var ExclusionByLabels []ExclusionByLabelsSpec

internal/objects/reconciler_test.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,15 +446,20 @@ var _ = Describe("Basic propagation", func() {
446446
Eventually(HasObject(ctx, "secrets", barName, "helm-secret")).Should(BeFalse())
447447
})
448448

449-
It("should not propagate builtin exclusions by labels", func() {
449+
It("should not propagate objects excluded by labels", func() {
450450
SetParent(ctx, barName, fooName)
451+
config.ExclusionByLabels = append(config.ExclusionByLabels, config.ExclusionByLabelsSpec{Key: "cattle.io/creator", Value: "norman"})
452+
config.ExclusionByLabels = append(config.ExclusionByLabels, config.ExclusionByLabelsSpec{Key: "ignore-label", Value: "label"})
453+
451454
MakeObjectWithLabels(ctx, "roles", fooName, "role-with-labels-blocked", map[string]string{"cattle.io/creator": "norman"})
455+
MakeObjectWithLabels(ctx, "roles", fooName, "role-with-labels-blocked-2", map[string]string{"ignore-label": "label"})
452456
MakeObjectWithLabels(ctx, "roles", fooName, "role-with-labels-wrong-value", map[string]string{"cattle.io/creator": "testme"})
453457
MakeObjectWithLabels(ctx, "roles", fooName, "role-with-labels-something", map[string]string{"app": "hello-world"})
454458
AddToHNCConfig(ctx, api.RBACGroup, api.RoleKind, api.Propagate)
455459

456460
// the first one should not propagate, everything else should
457461
Consistently(HasObject(ctx, "roles", barName, "role-with-labels-blocked")).Should(BeFalse())
462+
Consistently(HasObject(ctx, "roles", barName, "role-with-labels-blocked-2")).Should(BeFalse())
458463
Eventually(HasObject(ctx, "roles", barName, "role-with-labels-wrong-value")).Should(BeTrue())
459464
Eventually(HasObject(ctx, "roles", barName, "role-with-labels-something")).Should(BeTrue())
460465

internal/selectors/selectors.go

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"k8s.io/apimachinery/pkg/util/validation"
1414

1515
api "sigs.k8s.io/hierarchical-namespaces/api/v1alpha2"
16+
"sigs.k8s.io/hierarchical-namespaces/internal/config"
1617
)
1718

1819
// ShouldPropagate returns true if the given object should be propagated
@@ -197,19 +198,6 @@ func GetAllSelector(inst *unstructured.Unstructured) (bool, error) {
197198
// cmExclusionsByName are known (istio and kube-root) CA configmap which are excluded from propagation
198199
var cmExclusionsByName = []string{"istio-ca-root-cert", "kube-root-ca.crt"}
199200

200-
// A label as a key, value pair, used to exclude resources matching this label (both key and value).
201-
type ExclusionByLabelsSpec struct {
202-
Key string
203-
Value string
204-
}
205-
206-
// ExclusionByLabelsSpec are known label key-value pairs which are excluded from propagation. Right
207-
// now only used to exclude resources created by Rancher, see "System Tools > Remove"
208-
// (https://rancher.com/docs/rancher/v2.6/en/system-tools/#remove)
209-
var exclusionByLabels = []ExclusionByLabelsSpec{
210-
{Key: "cattle.io/creator", Value: "norman"},
211-
}
212-
213201
// A annotation as a key, value pair, used to exclude resources matching this annotation
214202
type ExclusionByAnnotationsSpec struct {
215203
Key string
@@ -246,7 +234,7 @@ func isExcluded(inst *unstructured.Unstructured) (bool, error) {
246234
}
247235

248236
// exclusion by labels
249-
for _, res := range exclusionByLabels {
237+
for _, res := range config.ExclusionByLabels {
250238
gotLabelValue, ok := inst.GetLabels()[res.Key]
251239
// check for presence has to be explicit, as empty label values are allowed and a
252240
// nonexisting key in the `labels` map will also return an empty string ("") - potentially

0 commit comments

Comments
 (0)