Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions pkg/behaviourtest/drivers/install/common/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import (
type CLIRunnerFunc = func(binary, token string, args ...string) (string, error)

// RunGitHubSetup runs fullsend github setup for the given target with the
// provided mint URL. If gcpProjectID is non-empty, inference provisioning
// is performed first and the resulting WIF provider is threaded to setup.
// provided mint URL. If gcpProjectID is non-empty, the existing WIF
// provider is looked up first via "inference status". Provisioning is
// only performed when no healthy provider exists, avoiding redundant
// create/undelete/update/enable IAM writes on every run.
func RunGitHubSetup(
binary, token, target, mintURL, gcpProjectID string,
runCLI CLIRunnerFunc,
Expand All @@ -25,9 +27,18 @@ func RunGitHubSetup(
"--runtime", "dummy",
}
if project := strings.TrimSpace(gcpProjectID); project != "" {
wifProvider, err := ProvisionInference(binary, token, target, project, runCLI, logf)
// Read-before-write: reuse the existing WIF provider when it
// is already healthy to avoid redundant IAM write operations.
wifProvider, err := GetExistingInferenceWIFProvider(binary, token, target, project, runCLI, logf)
if err != nil {
return err
// Provider missing or unhealthy — fall through to provision.
logf("[install] existing WIF provider not found for %s, provisioning: %v", target, err)
wifProvider, err = ProvisionInference(binary, token, target, project, runCLI, logf)
if err != nil {
return err
}
} else {
logf("[install] reusing existing WIF provider for %s: %s", target, wifProvider)
}
args = append(args, "--inference-project", project, "--inference-wif-provider", wifProvider)
}
Expand All @@ -39,6 +50,25 @@ func RunGitHubSetup(
return nil
}

// GetExistingInferenceWIFProvider checks whether a healthy WIF provider
// already exists for the given target by running "inference status". It
// returns the provider resource name when one is found, or an error when
// the provider is missing, unhealthy, or the status command fails.
func GetExistingInferenceWIFProvider(
binary, token, target, project string,
runCLI CLIRunnerFunc,
logf func(string, ...any),
) (string, error) {
statusArgs := []string{"inference", "status", target, "--project", project, "--format", "json"}
logf("[install] checking existing inference WIF provider: fullsend %s", strings.Join(statusArgs, " "))
out, err := runCLI(binary, token, statusArgs...)
if err != nil {
return "", fmt.Errorf("inference status %s: %w", target, err)
}

return ParseInferenceStatusWIFProvider(out)
}

// ProvisionInference runs inference provision and returns the WIF provider
// resource name. Mirrors the per-repo driver's provisionPerRepoInference.
func ProvisionInference(
Expand Down
130 changes: 130 additions & 0 deletions pkg/behaviourtest/drivers/install/common/setup_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
package common

import (
"fmt"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func noopLogf(string, ...any) {}

func TestRunGitHubSetup_NoGCPProject(t *testing.T) {
var calls [][]string
runCLI := func(binary, token string, args ...string) (string, error) {
calls = append(calls, args)
return "", nil
}

err := RunGitHubSetup("/usr/bin/fullsend", "tok", "org/repo", "https://mint.test", "", runCLI, noopLogf)
require.NoError(t, err)

require.Len(t, calls, 1, "expected a single github setup call")
assert.Equal(t, "github", calls[0][0])
assert.Equal(t, "setup", calls[0][1])
assert.NotContains(t, calls[0], "--inference-project")
}

func TestRunGitHubSetup_SkipsProvisionWhenProviderExists(t *testing.T) {
var calls [][]string
runCLI := func(binary, token string, args ...string) (string, error) {
calls = append(calls, args)
if len(args) >= 2 && args[0] == "inference" && args[1] == "status" {
return `{"status":"healthy","FULLSEND_GCP_WIF_PROVIDER":"projects/p/locations/l/providers/wif"}`, nil
}
return "", nil
}

err := RunGitHubSetup("/usr/bin/fullsend", "tok", "org/repo", "https://mint.test", "proj", runCLI, noopLogf)
require.NoError(t, err)

require.Len(t, calls, 2, "expected status + setup, no provision")
assert.Equal(t, "status", calls[0][1])
assert.Equal(t, "setup", calls[1][1])
assert.Contains(t, calls[1], "--inference-wif-provider")
assert.Contains(t, calls[1], "projects/p/locations/l/providers/wif")
}

func TestRunGitHubSetup_FallsBackToProvisionWhenProviderMissing(t *testing.T) {
var calls [][]string
statusCalls := 0
runCLI := func(binary, token string, args ...string) (string, error) {
calls = append(calls, args)
if len(args) >= 2 && args[0] == "inference" && args[1] == "status" {
statusCalls++
if statusCalls == 1 {
return "", fmt.Errorf("not found")
}
return `{"status":"healthy","FULLSEND_GCP_WIF_PROVIDER":"projects/p/locations/l/providers/wif"}`, nil
}
return "", nil
}

err := RunGitHubSetup("/usr/bin/fullsend", "tok", "org/repo", "https://mint.test", "proj", runCLI, noopLogf)
require.NoError(t, err)

require.Len(t, calls, 4, "expected status-fail, provision, status-ok, setup")
assert.Equal(t, "status", calls[0][1])
assert.Equal(t, "provision", calls[1][1])
assert.Equal(t, "status", calls[2][1])
assert.Equal(t, "setup", calls[3][1])
}

func TestRunGitHubSetup_ProvisionFails(t *testing.T) {
runCLI := func(binary, token string, args ...string) (string, error) {
if len(args) >= 2 && args[0] == "inference" && args[1] == "status" {
return "", fmt.Errorf("not found")
}
if len(args) >= 2 && args[0] == "inference" && args[1] == "provision" {
return "", fmt.Errorf("provision boom")
}
return "", nil
}

err := RunGitHubSetup("/usr/bin/fullsend", "tok", "org/repo", "https://mint.test", "proj", runCLI, noopLogf)
require.Error(t, err)
assert.Contains(t, err.Error(), "provision boom")
}

func TestRunGitHubSetup_SetupCLIError(t *testing.T) {
runCLI := func(binary, token string, args ...string) (string, error) {
if len(args) >= 2 && args[0] == "github" && args[1] == "setup" {
return "", fmt.Errorf("setup boom")
}
return "", nil
}

err := RunGitHubSetup("/usr/bin/fullsend", "tok", "org/repo", "https://mint.test", "", runCLI, noopLogf)
require.Error(t, err)
assert.Contains(t, err.Error(), "setup boom")
}

func TestGetExistingInferenceWIFProvider_OK(t *testing.T) {
runCLI := func(binary, token string, args ...string) (string, error) {
return `{"status":"healthy","FULLSEND_GCP_WIF_PROVIDER":"projects/p/locations/l/providers/wif"}`, nil
}

got, err := GetExistingInferenceWIFProvider("/usr/bin/fullsend", "tok", "org/repo", "proj", runCLI, noopLogf)
require.NoError(t, err)
assert.Equal(t, "projects/p/locations/l/providers/wif", got)
}

func TestGetExistingInferenceWIFProvider_CLIError(t *testing.T) {
runCLI := func(binary, token string, args ...string) (string, error) {
return "", fmt.Errorf("boom")
}

_, err := GetExistingInferenceWIFProvider("/usr/bin/fullsend", "tok", "org/repo", "proj", runCLI, noopLogf)
require.Error(t, err)
assert.Contains(t, err.Error(), "inference status")
}

func TestGetExistingInferenceWIFProvider_Unhealthy(t *testing.T) {
runCLI := func(binary, token string, args ...string) (string, error) {
return `{"status":"unhealthy","FULLSEND_GCP_WIF_PROVIDER":"projects/p/locations/l/providers/wif"}`, nil
}

_, err := GetExistingInferenceWIFProvider("/usr/bin/fullsend", "tok", "org/repo", "proj", runCLI, noopLogf)
require.Error(t, err)
}
78 changes: 66 additions & 12 deletions pkg/behaviourtest/drivers/install/ensure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -368,10 +368,11 @@ func TestRepoEnsurer_DoEnsure_RepoMissing_ThenInstalled(t *testing.T) {
assert.Len(t, cliCalls, 1, "cached call should not invoke CLI again")
}

func TestRepoEnsurer_DoEnsure_WithGCPProject(t *testing.T) {
func TestRepoEnsurer_DoEnsure_WithGCPProject_SkipsProvision(t *testing.T) {
speedUpValidateRetries(t)
// When GCPProjectID is set, provisionInference should be called
// before github setup.
// When GCPProjectID is set and the WIF provider already exists,
// the read-before-write guard should skip inference provision and
// reuse the existing provider from inference status.
sc := &stubClient{installed: false}
var cliCalls [][]string
e := &repoEnsurer{
Expand Down Expand Up @@ -401,17 +402,70 @@ func TestRepoEnsurer_DoEnsure_WithGCPProject(t *testing.T) {
require.NoError(t, err)
require.NotNil(t, st)

// Expect: inference provision, inference status, github setup (3 calls).
require.Len(t, cliCalls, 3, "expected 3 CLI calls (provision, status, setup)")
// Read-before-write: inference status (existing check) + github setup.
// No inference provision call — the provider already exists.
require.Len(t, cliCalls, 2, "expected 2 CLI calls (status, setup)")
assert.Equal(t, "inference", cliCalls[0][0])
assert.Equal(t, "provision", cliCalls[0][1])
assert.Equal(t, "inference", cliCalls[1][0])
assert.Equal(t, "status", cliCalls[1][1])
assert.Equal(t, "github", cliCalls[2][0])
assert.Equal(t, "setup", cliCalls[2][1])
assert.Equal(t, "status", cliCalls[0][1])
assert.Equal(t, "github", cliCalls[1][0])
assert.Equal(t, "setup", cliCalls[1][1])
// Verify inference flags were threaded to github setup.
assert.Contains(t, cliCalls[2], "--inference-project")
assert.Contains(t, cliCalls[2], "--inference-wif-provider")
assert.Contains(t, cliCalls[1], "--inference-project")
assert.Contains(t, cliCalls[1], "--inference-wif-provider")
}

func TestRepoEnsurer_DoEnsure_WithGCPProject_FallsBackToProvision(t *testing.T) {
speedUpValidateRetries(t)
// When the initial inference status check fails (provider missing),
// the fallback provisions the WIF provider via the full create path.
sc := &stubClient{installed: false}
var cliCalls [][]string
statusCallCount := 0
e := &repoEnsurer{
e2eCfg: e2etest.EnvConfig{
MintURL: "https://mint.test",
GCPProjectID: "test-project",
},
client: sc,
binary: "/usr/bin/fullsend",
token: "tok",
runCLI: func(binary, token string, args ...string) (string, error) {
cliCalls = append(cliCalls, args)
if len(args) >= 2 && args[0] == "github" && args[1] == "setup" {
sc.installed = true
}
if len(args) >= 2 && args[0] == "inference" && args[1] == "status" {
statusCallCount++
if statusCallCount == 1 {
// First status call (read-before-write check): provider not found.
return "", fmt.Errorf("provider not found")
}
// Second status call (inside ProvisionInference): provider now exists.
return `{"status":"healthy","FULLSEND_GCP_WIF_PROVIDER":"projects/p/locations/l/providers/wif"}`, nil
}
return "", nil
},
settle: noopSettle,
logf: t.Logf,
ensured: make(map[string]State),
}

st, err := e.EnsureRepo(context.Background(), "org", "test-repo-gcp-fallback")
require.NoError(t, err)
require.NotNil(t, st)

// Fallback path: status (fail) + provision + status (ok) + setup = 4 calls.
require.Len(t, cliCalls, 4, "expected 4 CLI calls (status-fail, provision, status-ok, setup)")
assert.Equal(t, "inference", cliCalls[0][0])
assert.Equal(t, "status", cliCalls[0][1])
assert.Equal(t, "inference", cliCalls[1][0])
assert.Equal(t, "provision", cliCalls[1][1])
assert.Equal(t, "inference", cliCalls[2][0])
assert.Equal(t, "status", cliCalls[2][1])
assert.Equal(t, "github", cliCalls[3][0])
assert.Equal(t, "setup", cliCalls[3][1])
assert.Contains(t, cliCalls[3], "--inference-project")
assert.Contains(t, cliCalls[3], "--inference-wif-provider")
}

func TestRepoEnsurer_DoEnsure_MintURLPopulated(t *testing.T) {
Expand Down
Loading