Skip to content

Commit 43ffc70

Browse files
authored
test(bdd): prepare named Helmfile environments (#1101)
Signed-off-by: Stephanie Baum <sbaum@nvidia.com>
1 parent 39c8449 commit 43ffc70

17 files changed

Lines changed: 271 additions & 50 deletions

tests/bdd/PLAN.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ refactor in every consumer; that is a feature.
105105
|------|-------|
106106
| `And I copy the file {string} to {string}` | Both paths are repo-relative. |
107107
| `And I update yaml file {string} with keys:` (two-column table of dotted-path and value) | Path supports dotted notation and `[n]` indices (e.g. `global.imagePullSecrets[0].name`). Missing intermediate maps and missing list indices are upserted: writing `global.imagePullSecrets[0].name` against a file that has neither `global.imagePullSecrets` nor any list entry creates both. Existing scalars at intermediate positions cause the step to fail rather than silently overwrite a non-map. Value cells expand `${VAR}` from `os.Environ`. |
108+
| `And I prepare Helmfile environment {string} for stack {string} from fixture {string} with values:` (two-column table of dotted-path and value) | Validates the stack and environment names, derives `deploy/stacks/<stack>/environments/<environment>.yaml` from the absolute repository root, copies the explicit fixture, and applies the visible values table with the same YAML update and `${VAR}` interpolation behavior. Supported stacks are `self-managed`, `observability`, and `nvcf-compute-plane`. The destination is ledger-backed. |
108109
| `And I prepare self-managed secrets file {string} from template {string} using the current NGC registry credential` | The destination and template are explicit repo-relative paths with `${VAR}` interpolation. Replaces the template's registry credential placeholder with base64 of the current `$oauthtoken:<NGC_API_KEY>` credential and writes the destination with mode `0600`. The destination is ledger-backed, and secret material never enters Gherkin, command logs, or failure messages. |
109110
| `And I substitute a block in file {string}:` (docstring) | The docstring contains an old block and replacement block separated by exactly one `---` line. `${VAR}` interpolation applies before an exact, ledger-backed replacement. Missing or malformed old blocks fail. |
110111

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
package dsl
19+
20+
import (
21+
"fmt"
22+
"path/filepath"
23+
"regexp"
24+
)
25+
26+
var helmfileEnvironmentName = regexp.MustCompile(`^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$`)
27+
28+
var helmfileStacks = map[string]struct{}{
29+
"nvcf-compute-plane": {},
30+
"observability": {},
31+
"self-managed": {},
32+
}
33+
34+
// HelmfileEnvironmentPath validates a named stack environment and returns its
35+
// destination beneath an absolute repository root. It never depends on the
36+
// process working directory.
37+
func HelmfileEnvironmentPath(repoRoot, stack, environment string) (string, error) {
38+
if !filepath.IsAbs(repoRoot) {
39+
return "", fmt.Errorf("repository root must be absolute")
40+
}
41+
if _, ok := helmfileStacks[stack]; !ok {
42+
return "", fmt.Errorf("unsupported Helmfile stack %q", stack)
43+
}
44+
if !helmfileEnvironmentName.MatchString(environment) {
45+
return "", fmt.Errorf("invalid Helmfile environment name %q", environment)
46+
}
47+
return filepath.Join(repoRoot, "deploy", "stacks", stack, "environments", environment+".yaml"), nil
48+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
SPDX-FileCopyrightText: Copyright (c) NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3+
SPDX-License-Identifier: Apache-2.0
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
*/
17+
18+
package dsl
19+
20+
import (
21+
"path/filepath"
22+
"strings"
23+
"testing"
24+
)
25+
26+
func TestHelmfileEnvironmentPathSupportsKnownStacks(t *testing.T) {
27+
repoRoot := t.TempDir()
28+
for _, stack := range []string{"self-managed", "observability", "nvcf-compute-plane"} {
29+
t.Run(stack, func(t *testing.T) {
30+
got, err := HelmfileEnvironmentPath(repoRoot, stack, "local-bdd")
31+
if err != nil {
32+
t.Fatalf("environment path: %v", err)
33+
}
34+
want := filepath.Join(repoRoot, "deploy", "stacks", stack, "environments", "local-bdd.yaml")
35+
if got != want {
36+
t.Fatalf("path = %q, want %q", got, want)
37+
}
38+
})
39+
}
40+
}
41+
42+
func TestHelmfileEnvironmentPathRejectsInvalidInput(t *testing.T) {
43+
repoRoot := t.TempDir()
44+
tests := []struct {
45+
name string
46+
root string
47+
stack string
48+
environment string
49+
want string
50+
}{
51+
{name: "relative root", root: "repo", stack: "self-managed", environment: "local", want: "repository root must be absolute"},
52+
{name: "unknown stack", root: repoRoot, stack: "other", environment: "local", want: `unsupported Helmfile stack "other"`},
53+
{name: "empty environment", root: repoRoot, stack: "self-managed", environment: "", want: `invalid Helmfile environment name ""`},
54+
{name: "path traversal", root: repoRoot, stack: "self-managed", environment: "../local", want: `invalid Helmfile environment name "../local"`},
55+
{name: "path separator", root: repoRoot, stack: "self-managed", environment: "team/local", want: `invalid Helmfile environment name "team/local"`},
56+
}
57+
for _, tc := range tests {
58+
t.Run(tc.name, func(t *testing.T) {
59+
_, err := HelmfileEnvironmentPath(tc.root, tc.stack, tc.environment)
60+
if err == nil || !strings.Contains(err.Error(), tc.want) {
61+
t.Fatalf("err = %v, want containing %q", err, tc.want)
62+
}
63+
})
64+
}
65+
}

tests/bdd/features/multi-cluster-eks-helmfile.feature

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,7 @@ Feature: Install a multi-cluster NVCF stack across two pre-provisioned EKS clust
132132
# the agent config. The agent dials the bare-ELB service URLs
133133
# (which DNS-resolve) and sends these hostnames as the HTTP Host
134134
# header so the control-plane gateway HTTPRoutes match.
135-
When I copy the file "deploy/stacks/self-managed/environments/base.yaml" to "deploy/stacks/self-managed/environments/eks-bdd-multi.yaml"
136-
And I update yaml file "deploy/stacks/self-managed/environments/eks-bdd-multi.yaml" with keys:
135+
When I prepare Helmfile environment "eks-bdd-multi" for stack "self-managed" from fixture "deploy/stacks/self-managed/environments/base.yaml" with values:
137136
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
138137
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
139138
| global.imagePullSecrets[0].name | nvcr-pull-secret |
@@ -164,8 +163,7 @@ Feature: Install a multi-cluster NVCF stack across two pre-provisioned EKS clust
164163
| openbao.migrations.issuerDiscovery.enabled | true |
165164
Then yaml file "deploy/stacks/self-managed/environments/eks-bdd-multi.yaml" key "global.domain" should equal "${EKS_GATEWAY_DOMAIN}"
166165

167-
When I copy the file "deploy/stacks/nvcf-compute-plane/environments/base.yaml" to "deploy/stacks/nvcf-compute-plane/environments/eks-bdd-multi.yaml"
168-
And I update yaml file "deploy/stacks/nvcf-compute-plane/environments/eks-bdd-multi.yaml" with keys:
166+
When I prepare Helmfile environment "eks-bdd-multi" for stack "nvcf-compute-plane" from fixture "deploy/stacks/nvcf-compute-plane/environments/base.yaml" with values:
169167
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
170168
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
171169
| global.imagePullSecrets[0].name | nvcr-pull-secret |

tests/bdd/features/multi-cluster-helmfile.feature

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,13 @@ Feature: Install a local multi-cluster NVCF stack with Helmfile
3737
# operator-specific registry values before the first Helmfile
3838
# install. Later scenarios reuse that install instead of
3939
# reinstalling with different secrets or URLs.
40-
And I copy the file "tests/bdd/fixtures/self-managed-local-bdd-multi.yaml" to "deploy/stacks/self-managed/environments/local-bdd.yaml"
41-
And I update yaml file "deploy/stacks/self-managed/environments/local-bdd.yaml" with keys:
40+
And I prepare Helmfile environment "local-bdd" for stack "self-managed" from fixture "tests/bdd/fixtures/self-managed-local-bdd-multi.yaml" with values:
4241
| global.imagePullSecrets[0].name | nvcr-pull-secret |
4342
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
4443
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
4544
| api.env.NVCF_SIDECARS_LLM_ROUTER_CLIENT_IMAGE | nvcr.io/${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM}/stargate-client:0.2.0 |
4645
| observability.profile | disabled |
47-
And I copy the file "tests/bdd/fixtures/nvcf-compute-plane-local-bdd-multi.yaml" to "deploy/stacks/nvcf-compute-plane/environments/local-bdd.yaml"
48-
And I update yaml file "deploy/stacks/nvcf-compute-plane/environments/local-bdd.yaml" with keys:
46+
And I prepare Helmfile environment "local-bdd" for stack "nvcf-compute-plane" from fixture "tests/bdd/fixtures/nvcf-compute-plane-local-bdd-multi.yaml" with values:
4947
| global.imagePullSecrets[0].name | nvcr-pull-secret |
5048
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
5149
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |

tests/bdd/features/multi-cluster-up.feature

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,12 @@ Feature: Bring up a local multi-cluster NVCF stack with the CLI
3838
# on a fresh cluster the ServiceMonitor CRDs do not exist yet and
3939
# the diff fails before anything installs. The Helmfile workflow
4040
# (helmfile sync) has no diff phase and keeps the default profile.
41-
And I copy the file "tests/bdd/fixtures/self-managed-local-bdd-multi.yaml" to "deploy/stacks/self-managed/environments/local.yaml"
42-
And I update yaml file "deploy/stacks/self-managed/environments/local.yaml" with keys:
41+
And I prepare Helmfile environment "local" for stack "self-managed" from fixture "tests/bdd/fixtures/self-managed-local-bdd-multi.yaml" with values:
4342
| global.imagePullSecrets[0].name | nvcr-pull-secret |
4443
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
4544
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
4645
| observability.profile | disabled |
47-
And I copy the file "tests/bdd/fixtures/nvcf-compute-plane-local-bdd-multi.yaml" to "deploy/stacks/nvcf-compute-plane/environments/local.yaml"
48-
And I update yaml file "deploy/stacks/nvcf-compute-plane/environments/local.yaml" with keys:
46+
And I prepare Helmfile environment "local" for stack "nvcf-compute-plane" from fixture "tests/bdd/fixtures/nvcf-compute-plane-local-bdd-multi.yaml" with values:
4947
| global.imagePullSecrets[0].name | nvcr-pull-secret |
5048
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
5149
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |

tests/bdd/features/observability-all.feature

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,23 +20,20 @@ Feature: Install local Helmfile observability for both planes
2020
bash -c 'set -eo pipefail; printf %s "$NGC_API_KEY" | helm registry login nvcr.io --username "\$oauthtoken" --password-stdin'
2121
"""
2222
# Configure the control-plane stack and its shared observability child.
23-
And I copy the file "tests/bdd/fixtures/self-managed-local-bdd.yaml" to "deploy/stacks/self-managed/environments/local-bdd-observability-all.yaml"
24-
And I update yaml file "deploy/stacks/self-managed/environments/local-bdd-observability-all.yaml" with keys:
23+
And I prepare Helmfile environment "local-bdd-observability-all" for stack "self-managed" from fixture "tests/bdd/fixtures/self-managed-local-bdd.yaml" with values:
2524
| global.imagePullSecrets[0].name | nvcr-pull-secret |
2625
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
2726
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
2827
| observability.profile | all |
2928
| functionAutoscaler.image.tag | 1.18.10 |
3029
# Give the shared observability Helmfile the same named environment.
31-
And I copy the file "tests/bdd/fixtures/self-managed-local-bdd.yaml" to "deploy/stacks/observability/environments/local-bdd-observability-all.yaml"
32-
And I update yaml file "deploy/stacks/observability/environments/local-bdd-observability-all.yaml" with keys:
30+
And I prepare Helmfile environment "local-bdd-observability-all" for stack "observability" from fixture "tests/bdd/fixtures/self-managed-local-bdd.yaml" with values:
3331
| global.imagePullSecrets[0].name | nvcr-pull-secret |
3432
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
3533
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
3634
| observability.profile | all |
3735
# Configure NVCA to join the same cluster and enable its collector.
38-
And I copy the file "tests/bdd/fixtures/nvcf-compute-plane-local-bdd.yaml" to "deploy/stacks/nvcf-compute-plane/environments/local-bdd-observability-all.yaml"
39-
And I update yaml file "deploy/stacks/nvcf-compute-plane/environments/local-bdd-observability-all.yaml" with keys:
36+
And I prepare Helmfile environment "local-bdd-observability-all" for stack "nvcf-compute-plane" from fixture "tests/bdd/fixtures/nvcf-compute-plane-local-bdd.yaml" with values:
4037
| global.imagePullSecrets[0].name | nvcr-pull-secret |
4138
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
4239
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |

tests/bdd/features/observability-compute.feature

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,20 @@ Feature: Install local Helmfile observability with the compute profile
2222
"""
2323
# Install only control-plane prerequisites on ncp-local-cp. Shared
2424
# observability is installed separately on the compute cluster below.
25-
And I copy the file "tests/bdd/fixtures/self-managed-local-bdd-multi.yaml" to "deploy/stacks/self-managed/environments/local-bdd-observability-compute.yaml"
26-
And I update yaml file "deploy/stacks/self-managed/environments/local-bdd-observability-compute.yaml" with keys:
25+
And I prepare Helmfile environment "local-bdd-observability-compute" for stack "self-managed" from fixture "tests/bdd/fixtures/self-managed-local-bdd-multi.yaml" with values:
2726
| global.imagePullSecrets[0].name | nvcr-pull-secret |
2827
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
2928
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
3029
| addons.llm.enabled | false |
3130
| observability.profile | disabled |
3231
# Configure the shared observability stack for compute-plane monitors.
33-
And I copy the file "tests/bdd/fixtures/self-managed-local-bdd-multi.yaml" to "deploy/stacks/observability/environments/local-bdd-observability-compute.yaml"
34-
And I update yaml file "deploy/stacks/observability/environments/local-bdd-observability-compute.yaml" with keys:
32+
And I prepare Helmfile environment "local-bdd-observability-compute" for stack "observability" from fixture "tests/bdd/fixtures/self-managed-local-bdd-multi.yaml" with values:
3533
| global.imagePullSecrets[0].name | nvcr-pull-secret |
3634
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
3735
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
3836
| observability.profile | compute |
3937
# Configure NVCA to use the same compute observability profile.
40-
And I copy the file "tests/bdd/fixtures/nvcf-compute-plane-local-bdd-multi.yaml" to "deploy/stacks/nvcf-compute-plane/environments/local-bdd-observability-compute.yaml"
41-
And I update yaml file "deploy/stacks/nvcf-compute-plane/environments/local-bdd-observability-compute.yaml" with keys:
38+
And I prepare Helmfile environment "local-bdd-observability-compute" for stack "nvcf-compute-plane" from fixture "tests/bdd/fixtures/nvcf-compute-plane-local-bdd-multi.yaml" with values:
4239
| global.imagePullSecrets[0].name | nvcr-pull-secret |
4340
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
4441
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |

tests/bdd/features/observability-control.feature

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,14 @@ Feature: Install local Helmfile observability with the control profile
1717
bash -c 'set -eo pipefail; printf %s "$NGC_API_KEY" | helm registry login nvcr.io --username "\$oauthtoken" --password-stdin'
1818
"""
1919
# Set the self-managed stack environment.
20-
And I copy the file "tests/bdd/fixtures/self-managed-local-bdd.yaml" to "deploy/stacks/self-managed/environments/local-bdd-observability-control.yaml"
21-
And I update yaml file "deploy/stacks/self-managed/environments/local-bdd-observability-control.yaml" with keys:
20+
And I prepare Helmfile environment "local-bdd-observability-control" for stack "self-managed" from fixture "tests/bdd/fixtures/self-managed-local-bdd.yaml" with values:
2221
| global.imagePullSecrets[0].name | nvcr-pull-secret |
2322
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
2423
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
2524
| observability.profile | control |
2625
| functionAutoscaler.image.tag | 1.18.10 |
2726
# Set the shared observability stack environment.
28-
And I copy the file "tests/bdd/fixtures/self-managed-local-bdd.yaml" to "deploy/stacks/observability/environments/local-bdd-observability-control.yaml"
29-
And I update yaml file "deploy/stacks/observability/environments/local-bdd-observability-control.yaml" with keys:
27+
And I prepare Helmfile environment "local-bdd-observability-control" for stack "observability" from fixture "tests/bdd/fixtures/self-managed-local-bdd.yaml" with values:
3028
| global.imagePullSecrets[0].name | nvcr-pull-secret |
3129
| global.helm.sources.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |
3230
| global.image.repository | ${SAMPLE_NGC_ORG}/${SAMPLE_NGC_TEAM} |

0 commit comments

Comments
 (0)