Skip to content

Commit 055fa8d

Browse files
authored
Merge pull request #630 from validatedpatterns/main
sync: main to rhdp-deploy
2 parents b3625a1 + ccf30d3 commit 055fa8d

14 files changed

Lines changed: 150 additions & 29 deletions

File tree

‎.claude/skills/pattern-author/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ When creating a new Pattern:
2626

2727
1. **Initialize** — Determine the Pattern name and whether secrets are needed. Run `pattern init` or `pattern init --with-secrets` in the Pattern directory.
2828
2. **Identify requirements** — What operators, applications, and custom helm charts does this Pattern need?
29-
3. **Define namespaces** — Add all required namespaces to the clustergroup values file (`values-<clusterGroupName>.yaml`). Include OperatorGroup configuration for operator namespaces.
29+
3. **Define namespaces** — Add all required namespaces to the clustergroup values file (`variants/<variant>/values-<variant>.yaml`). Include OperatorGroup configuration for operator namespaces.
3030
4. **Define subscriptions** — Add operator subscriptions with at minimum the operator `name`. Set `namespace`, `channel`, and `source` as needed.
3131
5. **Define applications** — Wire in helm charts as applications:
3232
- Local charts: set `path` to the chart location in the repository
@@ -234,7 +234,7 @@ Define a custom global variable and use `sharedValueFiles`:
234234
global:
235235
device: gpu
236236
237-
# values-<clustergroup>.yaml
237+
# variants/<variant>/values-<variant>.yaml
238238
clusterGroup:
239239
sharedValueFiles:
240240
- /overrides/values-{{ $.Values.global.device }}.yaml

‎.claude/skills/pattern-author/reference.md‎

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ global:
7979
secretLoader:
8080
disabled: false
8181
main:
82-
clusterGroupName: prod
82+
variant: prod
8383
multiSourceConfig:
8484
enabled: true
8585
clusterGroupChartVersion: 0.9.*
@@ -93,7 +93,7 @@ main:
9393

9494
`global.secretLoader.disabled` — When `true`, skip loading secrets. Useful for Patterns that don't use the secrets framework.
9595

96-
`main.clusterGroupName` — The name of the primary clustergroup. Determines which `values-<name>.yaml` file defines the main cluster. If you change this value, the next `pattern init` run creates the corresponding values file (you would need to manually delete the old unused one).
96+
`main.variant` — The name of the primary clustergroup. Determines which `values-<variant>.yaml` file defines the main cluster, located at `variants/<variant>/values-<variant>.yaml` (see [Variants folder structure](#variants-folder-structure)). If you change this value, the next `pattern init` run creates the corresponding values file (you would need to manually delete the old unused one). This replaces the deprecated `main.clusterGroupName` field (deprecated by the Validated Patterns operator in version 0.0.78); patternizer automatically migrates `main.clusterGroupName` to `main.variant` on `init`.
9797

9898
`main.multiSourceConfig.enabled` — Enable ArgoCD multi-source applications. Should always be `true` for modern Patterns.
9999

@@ -111,6 +111,27 @@ There are also some global options that can be set in `values-global.yaml` but a
111111

112112
`values-prod.yaml` is the values file that defines the main clustergroup of the Pattern. In hub/spoke Patterns (see [Spoke clusters](#spoke-clusters)) this would be the hub cluster. In single cluster Patterns this defines the solitary cluster. If there is one file to look at which defines the Pattern, it is this one. Its contents are explored in [The clustergroup values](#the-clustergroup-values) section.
113113

114+
With the [variants folder structure](#variants-folder-structure) (the layout patternizer now generates), this file lives at `variants/<variant>/values-<variant>.yaml` (e.g. `variants/prod/values-prod.yaml`) rather than at the repository root.
115+
116+
### Variants folder structure
117+
118+
Per-cluster (per-variant) values files live under a top-level `variants/` directory, with one subfolder per variant named after the variant:
119+
120+
```console
121+
.
122+
├── values-global.yaml
123+
├── charts/
124+
└── variants/
125+
├── prod/
126+
│ └── values-prod.yaml
127+
└── standalone/
128+
└── values-standalone.yaml
129+
```
130+
131+
The Validated Patterns operator auto-detects a top-level `variants/` directory and, when `main.variant` is set, looks for per-cluster values files under `variants/<variant>/` instead of the repository root. This keeps the root uncluttered as you add more variants. This structure was introduced in operator version 0.0.78; see the [variants folder structure blog post](https://validatedpatterns.io/blog/2026-08-04-variants-folder-structure/) for details.
132+
133+
`patternizer init` creates and uses this structure automatically, migrating a legacy root-level `values-<variant>.yaml` into `variants/<variant>/` when present. The flat (root-level) layout is still supported by the operator; `patternizer upgrade` does not move files but prints a deprecation warning when the variant's file is missing from the variants folder.
134+
114135
### The Pattern CR
115136

116137
When you run `./pattern.sh make install` to deploy the Pattern, the values in `values-global.yaml` are passed to the [pattern-install chart](https://github.com/validatedpatterns/pattern-install-chart) by the [rhvp.cluster_utils.install](https://github.com/validatedpatterns/rhvp.cluster_utils/blob/main/playbooks/install.yml) playbook. This chart creates a subscription for the Validated Patterns Operator, a configmap with default operator configuration, and the Pattern CR:
@@ -152,6 +173,8 @@ The following values files are automatically included for each application, in t
152173

153174
ArgoCD is configured with `ignoreMissingValueFiles: true`, so it silently skips any of these files that do not exist. Only create the files you actually need.
154175

176+
When the [variants folder structure](#variants-folder-structure) is in use, the variant-specific files above (those named after the clustergroup/variant, such as `values-<variant>.yaml`) are resolved from `variants/<variant>/` instead of the repository root.
177+
155178
In multi-source mode (the default), values files from the Pattern repository are prefixed with `$patternref/` to tell ArgoCD which source they come from. This is handled automatically by the clustergroup chart.
156179

157180
Some of these values files are cross-clustergroup. For example, `values-AWS.yaml` would apply to both hub and spoke clustergroups running on AWS.
@@ -184,7 +207,7 @@ global:
184207
pattern: ai-quickstart-rag
185208
device: cpu # one of 'cpu' (no GPU) or 'gpu' (NVIDIA GPU)
186209
main:
187-
clusterGroupName: prod
210+
variant: prod
188211
multiSourceConfig:
189212
enabled: true
190213
clusterGroupChartVersion: 0.9.*

‎.cursor/skills/pattern-author/SKILL.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ When creating a new Pattern:
2626

2727
1. **Initialize** — Determine the Pattern name and whether secrets are needed. Run `pattern init` or `pattern init --with-secrets` in the Pattern directory.
2828
2. **Identify requirements** — What operators, applications, and custom helm charts does this Pattern need?
29-
3. **Define namespaces** — Add all required namespaces to the clustergroup values file (`values-<clusterGroupName>.yaml`). Include OperatorGroup configuration for operator namespaces.
29+
3. **Define namespaces** — Add all required namespaces to the clustergroup values file (`variants/<variant>/values-<variant>.yaml`). Include OperatorGroup configuration for operator namespaces.
3030
4. **Define subscriptions** — Add operator subscriptions with at minimum the operator `name`. Set `namespace`, `channel`, and `source` as needed.
3131
5. **Define applications** — Wire in helm charts as applications:
3232
- Local charts: set `path` to the chart location in the repository
@@ -234,7 +234,7 @@ Define a custom global variable and use `sharedValueFiles`:
234234
global:
235235
device: gpu
236236
237-
# values-<clustergroup>.yaml
237+
# variants/<variant>/values-<variant>.yaml
238238
clusterGroup:
239239
sharedValueFiles:
240240
- /overrides/values-{{ $.Values.global.device }}.yaml

‎.cursor/skills/pattern-author/reference.md‎

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ global:
7979
secretLoader:
8080
disabled: false
8181
main:
82-
clusterGroupName: prod
82+
variant: prod
8383
multiSourceConfig:
8484
enabled: true
8585
clusterGroupChartVersion: 0.9.*
@@ -93,7 +93,7 @@ main:
9393

9494
`global.secretLoader.disabled` — When `true`, skip loading secrets. Useful for Patterns that don't use the secrets framework.
9595

96-
`main.clusterGroupName` — The name of the primary clustergroup. Determines which `values-<name>.yaml` file defines the main cluster. If you change this value, the next `pattern init` run creates the corresponding values file (you would need to manually delete the old unused one).
96+
`main.variant` — The name of the primary clustergroup. Determines which `values-<variant>.yaml` file defines the main cluster, located at `variants/<variant>/values-<variant>.yaml` (see [Variants folder structure](#variants-folder-structure)). If you change this value, the next `pattern init` run creates the corresponding values file (you would need to manually delete the old unused one). This replaces the deprecated `main.clusterGroupName` field (deprecated by the Validated Patterns operator in version 0.0.78); patternizer automatically migrates `main.clusterGroupName` to `main.variant` on `init`.
9797

9898
`main.multiSourceConfig.enabled` — Enable ArgoCD multi-source applications. Should always be `true` for modern Patterns.
9999

@@ -111,6 +111,27 @@ There are also some global options that can be set in `values-global.yaml` but a
111111

112112
`values-prod.yaml` is the values file that defines the main clustergroup of the Pattern. In hub/spoke Patterns (see [Spoke clusters](#spoke-clusters)) this would be the hub cluster. In single cluster Patterns this defines the solitary cluster. If there is one file to look at which defines the Pattern, it is this one. Its contents are explored in [The clustergroup values](#the-clustergroup-values) section.
113113

114+
With the [variants folder structure](#variants-folder-structure) (the layout patternizer now generates), this file lives at `variants/<variant>/values-<variant>.yaml` (e.g. `variants/prod/values-prod.yaml`) rather than at the repository root.
115+
116+
### Variants folder structure
117+
118+
Per-cluster (per-variant) values files live under a top-level `variants/` directory, with one subfolder per variant named after the variant:
119+
120+
```console
121+
.
122+
├── values-global.yaml
123+
├── charts/
124+
└── variants/
125+
├── prod/
126+
│ └── values-prod.yaml
127+
└── standalone/
128+
└── values-standalone.yaml
129+
```
130+
131+
The Validated Patterns operator auto-detects a top-level `variants/` directory and, when `main.variant` is set, looks for per-cluster values files under `variants/<variant>/` instead of the repository root. This keeps the root uncluttered as you add more variants. This structure was introduced in operator version 0.0.78; see the [variants folder structure blog post](https://validatedpatterns.io/blog/2026-08-04-variants-folder-structure/) for details.
132+
133+
`patternizer init` creates and uses this structure automatically, migrating a legacy root-level `values-<variant>.yaml` into `variants/<variant>/` when present. The flat (root-level) layout is still supported by the operator; `patternizer upgrade` does not move files but prints a deprecation warning when the variant's file is missing from the variants folder.
134+
114135
### The Pattern CR
115136

116137
When you run `./pattern.sh make install` to deploy the Pattern, the values in `values-global.yaml` are passed to the [pattern-install chart](https://github.com/validatedpatterns/pattern-install-chart) by the [rhvp.cluster_utils.install](https://github.com/validatedpatterns/rhvp.cluster_utils/blob/main/playbooks/install.yml) playbook. This chart creates a subscription for the Validated Patterns Operator, a configmap with default operator configuration, and the Pattern CR:
@@ -152,6 +173,8 @@ The following values files are automatically included for each application, in t
152173

153174
ArgoCD is configured with `ignoreMissingValueFiles: true`, so it silently skips any of these files that do not exist. Only create the files you actually need.
154175

176+
When the [variants folder structure](#variants-folder-structure) is in use, the variant-specific files above (those named after the clustergroup/variant, such as `values-<variant>.yaml`) are resolved from `variants/<variant>/` instead of the repository root.
177+
155178
In multi-source mode (the default), values files from the Pattern repository are prefixed with `$patternref/` to tell ArgoCD which source they come from. This is handled automatically by the clustergroup chart.
156179

157180
Some of these values files are cross-clustergroup. For example, `values-AWS.yaml` would apply to both hub and spoke clustergroups running on AWS.
@@ -184,7 +207,7 @@ global:
184207
pattern: ai-quickstart-rag
185208
device: cpu # one of 'cpu' (no GPU) or 'gpu' (NVIDIA GPU)
186209
main:
187-
clusterGroupName: prod
210+
variant: prod
188211
multiSourceConfig:
189212
enabled: true
190213
clusterGroupChartVersion: 0.9.*

‎.github/workflows/ansible-lint.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ jobs:
1515
persist-credentials: false
1616

1717
- name: Lint Ansible Playbook
18-
uses: ansible/ansible-lint@262624cd0ab22a4221293216856c59671ce7aa5e
18+
uses: ansible/ansible-lint@fac2489f3e4ccffa83a40b839770abbf4ab52327

‎.github/workflows/superlinter.yml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
# Run Linter against code base #
2626
################################
2727
- name: Lint Code Base
28-
uses: super-linter/super-linter/slim@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0
28+
uses: super-linter/super-linter/slim@2da136927bd4a73596db63044b504547c62cb854 # v9.0.0
2929
env:
3030
VALIDATE_ALL_CODEBASE: true
3131
DEFAULT_BRANCH: main
@@ -37,6 +37,7 @@ jobs:
3737
VALIDATE_JSCPD: false
3838
VALIDATE_JSON_PRETTIER: false
3939
VALIDATE_MARKDOWN_PRETTIER: false
40+
VALIDATE_PYTHON_ISORT: false
4041
VALIDATE_PYTHON_PYLINT: false
4142
VALIDATE_SHELL_SHFMT: false
4243
VALIDATE_YAML: false

‎.github/workflows/sync-rhdp-branch.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ jobs:
2222
with:
2323
persist-credentials: false
2424
- name: Set up Node
25-
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
25+
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
2626
with:
2727
node-version: 20
2828
- name: Opening pull request

‎Makefile-common‎

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ operator-deploy operator-upgrade: ## Installs/updates the pattern on a cluster (
1818
@$(ANSIBLE_RUN) rhvp.cluster_utils.operator_deploy
1919

2020
.PHONY: install
21-
install: pattern-install ## Installs the pattern onto a cluster (Loads secrets as well if configured)
21+
install: ## Installs the pattern onto a cluster (Loads secrets as well if configured)
22+
@$(ANSIBLE_RUN) rhvp.cluster_utils.install
2223

2324
.PHONY: uninstall
2425
uninstall: ## (EXPERIMENTAL) See https://validatedpatterns.io/blog/2026-02-16-pattern-uninstall/.
@@ -32,6 +33,11 @@ pattern-install:
3233
load-secrets: ## Loads secrets onto the cluster (unless explicitly disabled in values-global.yaml)
3334
@$(ANSIBLE_RUN) rhvp.cluster_utils.load_secrets
3435

36+
##@ Debug Tasks
37+
.PHONY: display-secrets-info
38+
display-secrets-info: ## Display your secret material on terminal or show secret loading error. Use with caution!
39+
@$(ANSIBLE_RUN) rhvp.cluster_utils.display_secrets_info
40+
3541
##@ Validation Tasks
3642
.PHONY: validate-prereq
3743
validate-prereq: ## verify pre-requisites
@@ -53,6 +59,7 @@ validate-schema: ## validates values files against schema in common/clustergroup
5359
argo-healthcheck: ## Checks if all argo applications are synced
5460
@$(ANSIBLE_RUN) rhvp.cluster_utils.argo_healthcheck
5561

62+
##@ Testing (CI) Tasks
5663
.PHONY: run-ci-tests
5764
run-ci-tests: ## To run ci-tests, set any needed env vars
5865
@$(ANSIBLE_RUN) rhvp.cluster_utils.run_ci_tests

‎pattern-metadata.yaml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ requirements:
2323
type: n1-standard-8
2424
azure:
2525
replicas: 3
26-
type: Standard_D8s_v3
26+
type: Standard_D8s_v4
2727
aws:
2828
replicas: 3
2929
type: m5.2xlarge
@@ -34,7 +34,7 @@ requirements:
3434
type: n1-standard-4
3535
azure:
3636
replicas: 3
37-
type: Standard_D4s_v3
37+
type: Standard_D4s_v4
3838
aws:
3939
replicas: 3
4040
type: m5.xlarge

‎pattern.sh‎

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,46 @@ function is_container() {
1717
return 1
1818
}
1919

20+
function verify_image() {
21+
local image="$1"
22+
23+
case "${image}" in
24+
quay.io/validatedpatterns/*|quay.io/hybridcloudpatterns/*)
25+
;;
26+
*)
27+
echo "Skipping image verification for third-party registry"
28+
return 0
29+
;;
30+
esac
31+
32+
if ! command -v cosign >/dev/null 2>&1; then
33+
echo "WARNING: cosign is not installed, cannot verify image signature"
34+
echo "Install cosign to enable image verification: https://docs.sigstore.dev/cosign/system_config/installation/"
35+
return 0
36+
fi
37+
38+
echo "Verifying image signature for ${image}..."
39+
local output rc
40+
local oidc_issuer="${VP_COSIGN_OIDC_ISSUER:-https://token.actions.githubusercontent.com}"
41+
local cert_identity="${VP_COSIGN_CERT_IDENTITY:-https://github.com/validatedpatterns/utility-container/.*}"
42+
output=$(cosign verify \
43+
--certificate-oidc-issuer "${oidc_issuer}" \
44+
--certificate-identity-regexp "${cert_identity}" \
45+
"${image}" 2>&1) && rc=$? || rc=$?
46+
47+
if [ "${rc}" -eq 0 ]; then
48+
echo "Image signature verified successfully"
49+
elif [ "${rc}" -ge 10 ] && [ "${rc}" -le 13 ]; then
50+
echo "ERROR: Image signature verification failed for ${image} (exit code ${rc})"
51+
echo "${output}"
52+
echo "Set VP_VERIFY_IMAGE=false to skip this check"
53+
exit 1
54+
else
55+
echo "WARNING: Could not verify image signature for ${image} (likely a network issue)"
56+
echo "Set VP_VERIFY_IMAGE=false to skip this check"
57+
fi
58+
}
59+
2060
if is_container; then
2161
echo "Already running in a container"
2262
exec "$@"
@@ -99,6 +139,10 @@ if [ -n "${EXTRA_ARGS:-}" ]; then
99139
EXTRA_ARGS_ARRAY=(${EXTRA_ARGS})
100140
fi
101141

142+
if [ "${VP_VERIFY_IMAGE:-true}" != "false" ]; then
143+
verify_image "$PATTERN_UTILITY_CONTAINER"
144+
fi
145+
102146
# Copy Kubeconfig from current environment. The utilities will pick up ~/.kube/config if set so it's not mandatory
103147
# $HOME is mounted as itself for any files that are referenced with absolute paths
104148
# $HOME is mounted to /root because the UID in the container is 0 and that's where SSH looks for credentials
@@ -129,12 +173,12 @@ podman run -it --rm --pull=newer \
129173
-e UUID_FILE \
130174
-e VALUES_SECRET \
131175
-e 'VP_*' \
132-
"${PKI_HOST_MOUNT_ARGS[@]}" \
176+
${PKI_HOST_MOUNT_ARGS[@]+"${PKI_HOST_MOUNT_ARGS[@]}"} \
133177
-v "$(pwd -P)":"$(pwd -P)" \
134178
-v "${HOME}":"${HOME}" \
135179
-v "${HOME}":/pattern-home \
136180
"${PODMAN_ARGS[@]}" \
137-
"${EXTRA_ARGS_ARRAY[@]}" \
181+
${EXTRA_ARGS_ARRAY[@]+"${EXTRA_ARGS_ARRAY[@]}"} \
138182
-w "$(pwd -P)" \
139183
"$PATTERN_UTILITY_CONTAINER" \
140184
"$@"

0 commit comments

Comments
 (0)