diff --git a/packages/system/cilium-networkpolicy/tests/networkpolicy_test.yaml b/packages/system/cilium-networkpolicy/tests/networkpolicy_test.yaml index b16f6fa70..e21003e04 100644 --- a/packages/system/cilium-networkpolicy/tests/networkpolicy_test.yaml +++ b/packages/system/cilium-networkpolicy/tests/networkpolicy_test.yaml @@ -81,7 +81,35 @@ tests: # bound by anything cozystack ships, so listing it in the deny rule is # misleading. asserts: + # Anchor the rule before asserting about it. notContains passes whenever + # its path resolves to something that lacks the content, and a different + # deny rule at [0] qualifies, so reordering spec.ingressDeny would leave + # this green while 7473 came back on the rule it names. A deny rule has no + # name, so the anchor is its selector, which is what identifies it rather + # than one of the ports it happens to list. + # + # The selector identifies it only while there is one rule to identify: a + # second world-scoped deny inserted ahead of this one would satisfy the + # selector and shift the real rule to [1], which is the reordering above. + # lengthEqual is what makes the selector sufficient. + # Both indexes in the path, not just the outer one. A second toPorts entry + # on the same rule carries its own ports list, so 7473 could come back + # there with the rule count and the selector both still satisfied. + - lengthEqual: + path: spec.ingressDeny + count: 1 + - lengthEqual: + path: spec.ingressDeny[0].toPorts + count: 1 + - contains: + path: spec.ingressDeny[0].fromEntities + content: world + # any: true matches on the port alone. Without it the comparison is a + # deep-equal against the whole entry, so 7473 re-added with a protocol + # beside it, which is how the neighbouring 7946 entry is written, would + # slip past a guard that looks like it forbids the port outright. - notContains: path: spec.ingressDeny[0].toPorts[0].ports + any: true content: port: "7473" diff --git a/packages/system/flux-shard-operator/tests/workload_test.yaml b/packages/system/flux-shard-operator/tests/workload_test.yaml index a7c3166fc..6d2ddd26c 100644 --- a/packages/system/flux-shard-operator/tests/workload_test.yaml +++ b/packages/system/flux-shard-operator/tests/workload_test.yaml @@ -17,48 +17,31 @@ tests: - equal: path: spec.template.spec.serviceAccountName value: flux-shard-operator - - contains: + # The whole list, so the pin fails on an argument added, removed or + # swapped rather than only on the ones someone thought to enumerate. + # This template is first-party, so a failure here is a deliberate change + # asking to be read, not upstream churn arriving on its own schedule. + # + # --metrics-bind-address and --metrics-secure are load-bearing among + # these: the README-advertised cozy_flux_shard_* gauges, autosizing + # recommendation included, are the operator's observability surface. + - equal: path: spec.template.spec.containers[0].args - content: --leader-elect - - contains: - path: spec.template.spec.containers[0].args - content: --flux-namespace=cozy-fluxcd - - contains: - path: spec.template.spec.containers[0].args - content: --shard-count=auto - - contains: - path: spec.template.spec.containers[0].args - content: --shard-concurrent=5 - - contains: - path: spec.template.spec.containers[0].args - content: --rebalance-threshold=0.25 - - contains: - path: spec.template.spec.containers[0].args - content: --shard-cpu-request=100m - - contains: - path: spec.template.spec.containers[0].args - content: --shard-memory-request=64Mi - - contains: - path: spec.template.spec.containers[0].args - content: --shard-memory-limit=1Gi - - notContains: - path: spec.template.spec.containers[0].args - content: --shard-cpu-limit= - - contains: - path: spec.template.spec.containers[0].args - content: --zap-log-level=info + value: + - --leader-elect + - --metrics-bind-address=:8080 + - --metrics-secure=false + - --flux-namespace=cozy-fluxcd + - --shard-count=auto + - --shard-concurrent=5 + - --rebalance-threshold=0.25 + - --shard-cpu-request=100m + - --shard-memory-request=64Mi + - --shard-memory-limit=1Gi + - --zap-log-level=info - equal: path: spec.template.spec.volumes[0].secret.secretName value: flux-shard-operator-cert - # The metrics endpoint must stay reachable: the README-advertised - # cozy_flux_shard_* gauges (incl. the autosizing recommendation) are the - # operator's observability surface. - - contains: - path: spec.template.spec.containers[0].args - content: --metrics-bind-address=:8080 - - contains: - path: spec.template.spec.containers[0].args - content: --metrics-secure=false - equal: path: spec.template.metadata.annotations["prometheus.io/scrape"] value: "true" @@ -72,9 +55,16 @@ tests: - it: does not render --pinned-tenants by default template: templates/workload.yaml asserts: - - notContains: - path: spec.template.spec.containers[0].args - content: --pinned-tenants= + - equal: + path: spec.template.spec.containers[0].name + value: flux-shard-operator + # Match the flag name per element, not one whole element against one + # value: contains and notContains compare elements for equality, so + # `--pinned-tenants=` never equals a rendered + # `--pinned-tenants=tenant-a=shard0` and the negative could not fail. + - notMatchRegex: + path: spec.template.spec.containers[0].args[*] + pattern: "^--pinned-tenants" - it: renders shardCount and pinned tenants from values template: templates/workload.yaml diff --git a/packages/system/keycloak/tests/encryption_test.yaml b/packages/system/keycloak/tests/encryption_test.yaml index f2b400503..94d4a0b8e 100644 --- a/packages/system/keycloak/tests/encryption_test.yaml +++ b/packages/system/keycloak/tests/encryption_test.yaml @@ -445,6 +445,13 @@ tests: root-host: example.org cluster-domain: cozy.local asserts: + # Anchor the index before asserting on it. notContains passes whenever its + # path resolves to something that lacks the content, and a different + # container at [0] qualifies, so without this the guard goes green if a + # sidecar is ever placed ahead of the proxy. + - equal: + path: spec.template.spec.containers[0].name + value: proxy - notContains: path: spec.template.spec.containers[0].env any: true diff --git a/packages/system/kilo/tests/kilo_test.yaml b/packages/system/kilo/tests/kilo_test.yaml index d12e3a4ef..d9d311b49 100644 --- a/packages/system/kilo/tests/kilo_test.yaml +++ b/packages/system/kilo/tests/kilo_test.yaml @@ -61,6 +61,19 @@ tests: - it: "no --compatibility arg in the default render" asserts: - - notContains: - path: spec.template.spec.containers[0].args - content: "--compatibility=cilium" + # Anchor the index before asserting on it. A negative assert passes + # whenever its path resolves to something that does not match, and a + # different container at [0] qualifies — as does an index resolving to + # nothing at all — so without this the guard goes green if a sidecar is + # ever placed ahead of kilo. + - equal: + path: spec.template.spec.containers[0].name + value: kilo + # Match the flag name per element, not one whole element against one + # value: contains and notContains compare elements for equality, and the + # chart renders --compatibility= off a single values key, so an + # equality check against the cilium value leaves every other value + # unforbidden. + - notMatchRegex: + path: spec.template.spec.containers[0].args[*] + pattern: "^--compatibility" diff --git a/packages/system/monitoring/tests/oidc_test.yaml b/packages/system/monitoring/tests/oidc_test.yaml index 3f6d25817..7c694d990 100644 --- a/packages/system/monitoring/tests/oidc_test.yaml +++ b/packages/system/monitoring/tests/oidc_test.yaml @@ -79,12 +79,25 @@ tests: asserts: - notExists: path: spec.config["auth.generic_oauth"] + # Anchor the index before asserting on it. notContains passes whenever its + # path resolves to something that lacks the content, and a different + # container at [0] qualifies, so without this both guards go green if a + # sidecar is ever placed ahead of grafana in the CR's deployment spec. + - equal: + path: spec.deployment.spec.template.spec.containers[0].name + value: grafana + # any: true matches on the element name alone. Without it the comparison + # is a deep-equal against the whole entry, and the real ones carry a + # valueFrom or a value alongside the name, so {name: ...} matches nothing + # and the guard passes whether or not the variable is rendered. - notContains: path: spec.deployment.spec.template.spec.containers[0].env + any: true content: name: GF_AUTH_GENERIC_OAUTH_CLIENT_SECRET - notContains: path: spec.deployment.spec.template.spec.containers[0].env + any: true content: name: GF_PATHS_CUSTOM_INI diff --git a/packages/system/ouroboros/tests/controller_test.yaml b/packages/system/ouroboros/tests/controller_test.yaml index 273effe61..3329cb66e 100644 --- a/packages/system/ouroboros/tests/controller_test.yaml +++ b/packages/system/ouroboros/tests/controller_test.yaml @@ -22,16 +22,32 @@ tests: - contains: path: spec.template.spec.containers[0].args content: --proxy-service-namespace=cozy-ouroboros - - notContains: - path: spec.template.spec.containers[0].args - content: --proxy-fqdn=ouroboros-proxy.cozy-ouroboros.svc.cluster.local. + # Match the flag name per element, not one whole element against one + # value: contains and notContains compare elements for equality, and the + # baked FQDN carries whatever controller.clusterDomain is set to, so an + # equality check against the form the default cluster-domain produces + # leaves every other value unforbidden. + - notMatchRegex: + path: spec.template.spec.containers[0].args[*] + pattern: "^--proxy-fqdn" - it: leaves Gateway-API watching off at the parent default (consumer enables) template: charts/ouroboros/templates/controller-deployment.yaml asserts: - - notContains: - path: spec.template.spec.containers[0].args - content: --gateway-api + # Anchor the index before asserting on it. A negative assert passes + # whenever its path resolves to something that does not match, and a + # different container at [0] qualifies — as does an index resolving to + # nothing at all — so without this the guard goes green if a sidecar is + # ever placed ahead of the controller. + - equal: + path: spec.template.spec.containers[0].name + value: controller + # Match the flag name per element. An equality check against the bare + # form the chart renders today would go on passing if it ever rendered + # --gateway-api=true, with watching on. + - notMatchRegex: + path: spec.template.spec.containers[0].args[*] + pattern: "^--gateway-api" - it: emits chart-default --resync=30s — host scenario inherits the upstream chart default (changed from 10m in upstream v0.7.x). The reduction is the controller's only recovery path when an Ingress watch silently dies, and 30s caps worst-case event-to-reconcile latency under broken-watch conditions. Pinning here catches a future upstream bump back to the longer value before it lands as a CI surprise. template: charts/ouroboros/templates/controller-deployment.yaml @@ -151,15 +167,15 @@ tests: # too — this is the mode tenants actually run, so a future refactor # in the upstream controller-deployment template that drops the # composition block from this branch only would break tenants - # silently. The negative-assert pins that --proxy-fqdn does NOT - # bake the cluster-domain at render time when no clusterDomain is - # configured (the platform-agnostic default). + # silently. The negative assert pins that no --proxy-fqdn is baked at + # render time when no clusterDomain is configured (the + # platform-agnostic default). - contains: path: spec.template.spec.containers[0].args content: --proxy-service-name=ouroboros-proxy - contains: path: spec.template.spec.containers[0].args content: --proxy-service-namespace=cozy-ouroboros - - notContains: - path: spec.template.spec.containers[0].args - content: --proxy-fqdn=ouroboros-proxy.cozy-ouroboros.svc.cluster.local. + - notMatchRegex: + path: spec.template.spec.containers[0].args[*] + pattern: "^--proxy-fqdn" diff --git a/packages/system/ouroboros/tests/cozystack_overrides_test.yaml b/packages/system/ouroboros/tests/cozystack_overrides_test.yaml index cfafd95e8..f90f23858 100644 --- a/packages/system/ouroboros/tests/cozystack_overrides_test.yaml +++ b/packages/system/ouroboros/tests/cozystack_overrides_test.yaml @@ -27,9 +27,15 @@ tests: - contains: path: spec.template.spec.containers[0].args content: --target-service-namespace=cozy-ingress-nginx - - notContains: - path: spec.template.spec.containers[0].args - content: --target-host= + # Match the flag name per element, not one whole element against one + # value: contains and notContains compare elements for equality, so + # `--target-host=` never equals a rendered `--target-host=` and + # that negative could not fail. A length assertion would not do either, + # since an upstream bump that adds the flag while consolidating another + # argument keeps the count. + - notMatchRegex: + path: spec.template.spec.containers[0].args[*] + pattern: "^--target-host" - it: controller image is pinned to the digest the values.yaml ships template: charts/ouroboros/templates/controller-deployment.yaml