diff --git a/pkg/helper/adapter.go b/pkg/helper/adapter.go index 8edb5de..04ffa9d 100644 --- a/pkg/helper/adapter.go +++ b/pkg/helper/adapter.go @@ -89,7 +89,6 @@ type AdapterDeploymentOptions struct { const maxReleaseNameLength = 48 func GenerateAdapterReleaseName(resourceType, adapterName string) string { - releaseName := fmt.Sprintf("adapter-%s-%s", resourceType, adapterName) if len(releaseName) > maxReleaseNameLength { @@ -224,28 +223,8 @@ func (h *Helper) DeployAdapter(ctx context.Context, opts AdapterDeploymentOption "-f", valuesFilePath, } - // Add fullnameOverride to ensure consistent release naming - helmArgs = append(helmArgs, - "--set", fmt.Sprintf("fullnameOverride=%s", releaseName), - ) - - // Add run-id label for resource tracking and cleanup - if h.Cfg.RunID != "" { - // Label the Helm release itself (for Helm SDK-based cleanup) - helmArgs = append(helmArgs, - "--labels", fmt.Sprintf("e2e.hyperfleet.io/run-id=%s", h.Cfg.RunID), - ) - } - - // Override image pull policy if set (e.g. IfNotPresent for local kind clusters) - if policy := os.Getenv("IMAGE_PULL_POLICY"); policy != "" { - helmArgs = append(helmArgs, "--set", fmt.Sprintf("image.pullPolicy=%s", policy)) - } - - // Add additional --set values if provided - for key, value := range opts.SetValues { - helmArgs = append(helmArgs, "--set", fmt.Sprintf("%s=%s", key, value)) - } + // Append conditional --set flags + helmArgs = append(helmArgs, h.adapterHelmSetArgs(releaseName, opts)...) logger.Info("executing Helm command", "args", helmArgs) @@ -279,6 +258,37 @@ func (h *Helper) DeployAdapter(ctx context.Context, opts AdapterDeploymentOption return nil } +// adapterHelmSetArgs builds the conditional --set flags for adapter Helm deployments. +// Extracted for testability - DeployAdapter calls this to append flags after the base args. +func (h *Helper) adapterHelmSetArgs(releaseName string, opts AdapterDeploymentOptions) []string { + var args []string + + // Ensure consistent release naming + args = append(args, "--set", fmt.Sprintf("fullnameOverride=%s", releaseName)) + + // Add run-id label for resource tracking and cleanup + if h.Cfg.RunID != "" { + args = append(args, "--labels", fmt.Sprintf("e2e.hyperfleet.io/run-id=%s", h.Cfg.RunID)) + } + + // Override image pull policy if set (e.g. IfNotPresent for local kind clusters) + if policy := os.Getenv("IMAGE_PULL_POLICY"); policy != "" { + args = append(args, "--set", fmt.Sprintf("image.pullPolicy=%s", policy)) + } + + // Enable adapter API auth when JWT is enabled on the API server + if h.Cfg.Identity.TokenRequest.IsEnabled() { + args = append(args, "--set", "adapterConfig.hyperfleetApi.auth.enabled=true") + } + + // Add additional --set values if provided + for key, value := range opts.SetValues { + args = append(args, "--set", fmt.Sprintf("%s=%s", key, value)) + } + + return args +} + // resolveInternalAPIURL looks up the hyperfleet-api Kubernetes service in the configured // namespace and returns an in-cluster FQDN URL that adapters deployed in any namespace can use. // This is needed because the external LoadBalancer IP is not routable from within GKE pods. diff --git a/pkg/helper/adapter_test.go b/pkg/helper/adapter_test.go index 4fa0bf6..e2794ca 100644 --- a/pkg/helper/adapter_test.go +++ b/pkg/helper/adapter_test.go @@ -380,3 +380,69 @@ func TestDeletePubSubSubscription(t *testing.T) { }) } } + +func TestAdapterHelmSetArgs(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + tokenRequestSA string // ServiceAccountName - non-empty enables JWT + runID string + setValues map[string]string + wantContains []string // substrings that must appear in joined args + wantAbsent []string // substrings that must NOT appear + }{ + { + name: "includes auth flag when JWT is enabled", + tokenRequestSA: "hyperfleet-e2e-sa", + wantContains: []string{"adapterConfig.hyperfleetApi.auth.enabled=true"}, + }, + { + name: "omits auth flag when JWT is disabled", + wantAbsent: []string{"adapterConfig.hyperfleetApi.auth.enabled"}, + }, + { + name: "includes fullnameOverride", + wantContains: []string{"fullnameOverride=test-release"}, + }, + { + name: "includes run-id label when set", + runID: "abc-123", + wantContains: []string{"e2e.hyperfleet.io/run-id=abc-123"}, + }, + { + name: "omits run-id label when empty", + wantAbsent: []string{"e2e.hyperfleet.io/run-id"}, + }, + { + name: "includes custom set values", + setValues: map[string]string{"image.tag": "latest"}, + wantContains: []string{"image.tag=latest"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + cfg := &config.Config{RunID: tt.runID} + cfg.Identity.TokenRequest.ServiceAccountName = tt.tokenRequestSA + + h := &Helper{Cfg: cfg} + opts := AdapterDeploymentOptions{SetValues: tt.setValues} + args := h.adapterHelmSetArgs("test-release", opts) + joined := strings.Join(args, " ") + + for _, want := range tt.wantContains { + if !strings.Contains(joined, want) { + t.Errorf("expected args to contain %q, got: %v", want, args) + } + } + for _, absent := range tt.wantAbsent { + if strings.Contains(joined, absent) { + t.Errorf("expected args NOT to contain %q, got: %v", absent, args) + } + } + }) + } +}