Skip to content

Commit 342d09a

Browse files
Add MetricOps struct and reflection-based flag parsing
1 parent b4d1d78 commit 342d09a

File tree

6 files changed

+56
-34
lines changed

6 files changed

+56
-34
lines changed

internal/e2e/flags.go

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,33 @@ package e2e
44

55
import (
66
"flag"
7+
"fmt"
78
"github.com/octago/sflags/gen/gpflag"
89
"github.com/spf13/pflag"
10+
"reflect"
911
)
1012

11-
// Bridging for test execution => InitFlags parses struct tags into command-line flags and registers them with Go's flag package
12-
func InitFlags(config interface{}, metricDimensions *map[string]string) {
13+
// For CloudWatch metric dimension flag
14+
type MetricOps struct {
15+
MetricDimensions map[string]string `flag:"metricDimensions" desc:"CloudWatch metric dimensions as comma-separated key=value pairs"`
16+
}
17+
18+
func ParseFlags(config interface{}) (*pflag.FlagSet, error) {
1319
flags, err := gpflag.Parse(config)
1420
if err != nil {
15-
panic(err)
21+
return nil, fmt.Errorf("failed to parse flags: %w", err)
1622
}
1723

18-
// Manually add flags for data types that gpflag cannot parse
19-
flags.StringToStringVar(metricDimensions, "metricDimensions", nil, "CloudWatch metric dimensions as comma-separated key=value pairs")
24+
// Handle MetricDimensions map that gpflag doesn't support
25+
if _, hasField := reflect.TypeOf(config).Elem().FieldByName("MetricDimensions"); hasField {
26+
field := reflect.ValueOf(config).Elem().FieldByName("MetricDimensions")
27+
metricDims := field.Addr().Interface().(*map[string]string)
28+
flags.StringToStringVar(metricDims, "metricDimensions", nil, "CloudWatch metric dimensions as comma-separated key=value pairs")
29+
}
2030

2131
flags.VisitAll(func(pf *pflag.Flag) {
2232
flag.CommandLine.Var(pf.Value, pf.Name, pf.Usage)
2333
})
34+
35+
return flags, nil
2436
}

test/cases/nvidia-training/main_test.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,10 @@ import (
2727
)
2828

2929
func TestMain(m *testing.M) {
30-
fwext.InitFlags(&testConfig, &testConfig.MetricDimensions)
30+
_, err := fwext.ParseFlags(&testConfig)
31+
if err != nil {
32+
log.Fatalf("failed to parse flags: %v", err)
33+
}
3134
cfg, err := envconf.NewFromFlags()
3235
if err != nil {
3336
log.Fatalf("failed to initialize test environment: %v", err)
@@ -38,7 +41,7 @@ func TestMain(m *testing.M) {
3841
testenv = env.NewWithConfig(cfg).WithContext(ctx)
3942

4043
// Render CloudWatch Agent manifest with dynamic dimensions
41-
renderedCloudWatchAgentManifest, err := common.RenderCloudWatchAgentManifest(manifests.CloudWatchAgentManifest, testConfig.MetricDimensions)
44+
renderedCloudWatchAgentManifest, err := manifests.RenderCloudWatchAgentManifest(testConfig.MetricDimensions)
4245
if err != nil {
4346
log.Printf("Warning: failed to render CloudWatch Agent manifest: %v", err)
4447
}
@@ -84,10 +87,10 @@ func TestMain(m *testing.M) {
8487
},
8588

8689
// Wait for DaemonSets using helper
87-
common.DeployDaemonSet("nvidia-device-plugin-daemonset", "kube-system"),
88-
common.DeployDaemonSet("aws-efa-k8s-device-plugin-daemonset", "kube-system"),
89-
common.DeployDaemonSet("dcgm-exporter", "kube-system"),
90-
common.DeployDaemonSet("cwagent", "amazon-cloudwatch"),
90+
common.DeployDaemonSet("nvidia-device-plugin-daemonset", "kube-system", false),
91+
common.DeployDaemonSet("aws-efa-k8s-device-plugin-daemonset", "kube-system", false),
92+
common.DeployDaemonSet("dcgm-exporter", "kube-system", true),
93+
common.DeployDaemonSet("cwagent", "amazon-cloudwatch", true),
9194
checkNodeTypes, // Dynamically check node types and capacities after device plugins are ready
9295
)
9396

test/cases/nvidia-training/vars.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@
33
package training
44

55
import (
6+
fwext "github.com/aws/aws-k8s-tester/internal/e2e"
67
"sigs.k8s.io/e2e-framework/pkg/env"
78
)
89

910
type Config struct {
10-
MetricDimensions map[string]string `flag:"metricDimensions" desc:"CloudWatch metric dimensions as comma-separated key=value pairs"`
11-
BertTrainingImage string `flag:"bertTrainingImage" desc:"Docker image used for BERT training workload"`
12-
EfaEnabled bool `flag:"efaEnabled" desc:"Enable Elastic Fabric Adapter (EFA)"`
13-
NodeType string `flag:"nodeType" desc:"Instance type for cluster nodes"`
11+
fwext.MetricOps
12+
BertTrainingImage string `flag:"bertTrainingImage" desc:"Docker image used for BERT training workload"`
13+
EfaEnabled bool `flag:"efaEnabled" desc:"Enable Elastic Fabric Adapter (EFA)"`
14+
NodeType string `flag:"nodeType" desc:"Instance type for cluster nodes"`
1415
}
1516

1617
// Shared global variables

test/common/helper.go renamed to test/common/resources.go

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,7 @@ package common
55
import (
66
"context"
77
"fmt"
8-
"html/template"
98
"log"
10-
"strings"
119
"time"
1210

1311
fwext "github.com/aws/aws-k8s-tester/internal/e2e"
@@ -18,21 +16,9 @@ import (
1816
"sigs.k8s.io/e2e-framework/pkg/envconf"
1917
)
2018

21-
// RenderCloudWatchAgentManifest renders the CloudWatch Agent manifest with dynamic dimensions
22-
func RenderCloudWatchAgentManifest(cloudWatchAgentManifest []byte, metricDimensions map[string]string) ([]byte, error) {
23-
var keys []string
24-
for key := range metricDimensions {
25-
keys = append(keys, `"`+key+`"`)
26-
}
27-
dimensionsStr := strings.Join(keys, ", ")
28-
return fwext.RenderManifests(cloudWatchAgentManifest, map[string]interface{}{
29-
"MetricDimensions": metricDimensions,
30-
"DimensionKeys": template.HTML(dimensionsStr),
31-
})
32-
}
33-
3419
// DeployDaemonSet returns a function to deploy and wait for a DaemonSet to be ready
35-
func DeployDaemonSet(name, namespace string) env.Func {
20+
// If isOptional is true, failures will log warnings instead of returning errors
21+
func DeployDaemonSet(name, namespace string, isOptional bool) env.Func {
3622
return func(ctx context.Context, config *envconf.Config) (context.Context, error) {
3723
log.Printf("Waiting for %s daemonset to be ready.", name)
3824
daemonset := appsv1.DaemonSet{
@@ -44,8 +30,7 @@ func DeployDaemonSet(name, namespace string) env.Func {
4430
wait.WithContext(ctx),
4531
)
4632
if err != nil {
47-
// Do not fail test for optional daemonset failures
48-
if name == "cwagent" || name == "dcgm-exporter" {
33+
if isOptional {
4934
log.Printf("Warning: %s daemonset is not ready: %v", name, err)
5035
return ctx, nil
5136
}

test/manifests/raw.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,5 @@ var (
2222
DCGMExporterManifest []byte
2323

2424
//go:embed assets/cloudwatch-agent.yaml
25-
CloudWatchAgentManifest []byte
25+
cloudWatchAgentManifestTemplate []byte
2626
)

test/manifests/rendered.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package manifests
2+
3+
import (
4+
"html/template"
5+
"strings"
6+
7+
fwext "github.com/aws/aws-k8s-tester/internal/e2e"
8+
)
9+
10+
// RenderCloudWatchAgentManifest renders the CloudWatch Agent manifest with dynamic dimensions
11+
func RenderCloudWatchAgentManifest(metricDimensions map[string]string) ([]byte, error) {
12+
var keys []string
13+
for key := range metricDimensions {
14+
keys = append(keys, `"`+key+`"`)
15+
}
16+
dimensionsStr := strings.Join(keys, ", ")
17+
return fwext.RenderManifests(cloudWatchAgentManifestTemplate, map[string]interface{}{
18+
"MetricDimensions": metricDimensions,
19+
"DimensionKeys": template.HTML(dimensionsStr),
20+
})
21+
}

0 commit comments

Comments
 (0)