Files
deploy/test/e2e/accounts_test.go
zeekayandHanzo Dev 1ab6e799c1 cd: the module is github.com/hanzoai/cd, where it is actually hosted
go.mod still declared `module github.com/hanzoai/deploy` after the repo was
renamed. A Go module path is not cosmetic — it is the resolvable location. So
`go get github.com/hanzoai/cd` could not work, and anything importing this
module had to spell a name that no longer exists at that address. The build log
of v3.6.0 is where it surfaced: the compiler was still emitting
github.com/hanzoai/deploy/cmd/cd/commands.

3541 import paths across 690 .go, 19 .proto, 4 .yaml, 3 .sh, 2 .mod, Procfile
and Makefile. Plus the 62 ghcr.io/hanzoai/deploy image references, moved to
ghcr.io/hanzoai/cd to match hanzo.yml's build target — a distinct string from
the module path, replaced separately so neither could clobber the other.

go mod tidy clean, CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build ./... clean.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-28 21:16:24 -07:00

210 lines
5.4 KiB
Go

package e2e
import (
"encoding/json"
"path/filepath"
"strings"
"testing"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/hanzoai/cd/cmd/cd/commands/headless"
"github.com/hanzoai/cd/pkg/apiclient/account"
"github.com/hanzoai/cd/pkg/apiclient/session"
. "github.com/hanzoai/cd/test/e2e/fixture"
accountFixture "github.com/hanzoai/cd/test/e2e/fixture/account"
"github.com/hanzoai/cd/util/errors"
utilio "github.com/hanzoai/cd/util/io"
jwtutil "github.com/hanzoai/cd/util/jwt"
)
func TestCreateAndUseAccount(t *testing.T) {
ctx := accountFixture.Given(t)
ctx.
Name("test").
When().
Create().
Then().
And(func(account *account.Account, _ error) {
assert.Equal(t, account.Name, ctx.GetName())
assert.Equal(t, []string{"login"}, account.Capabilities)
}).
When().
Login().
Then().
CurrentUser(func(user *session.GetUserInfoResponse, _ error) {
assert.True(t, user.LoggedIn)
assert.Equal(t, user.Username, ctx.GetName())
})
}
func TestCanIGetLogsAllow(t *testing.T) {
ctx := accountFixture.Given(t)
ctx.
Name("test").
Project(ProjectName).
When().
Create().
Login().
SetPermissions([]ACL{
{
Resource: "logs",
Action: "get",
Scope: ProjectName + "/*",
},
{
Resource: "apps",
Action: "get",
Scope: ProjectName + "/*",
},
}, "log-viewer").
CanIGetLogs().
Then().
AndCLIOutput(func(output string, _ error) {
assert.Contains(t, output, "yes")
})
}
func TestCanIGetLogsDeny(t *testing.T) {
ctx := accountFixture.Given(t)
ctx.
Name("test").
When().
Create().
Login().
CanIGetLogs().
Then().
AndCLIOutput(func(output string, _ error) {
assert.Contains(t, output, "no")
})
}
func TestCreateAndUseAccountCLI(t *testing.T) {
EnsureCleanState(t)
output, err := RunCli("account", "list")
errors.CheckError(err)
assert.Equal(t, `NAME ENABLED CAPABILITIES
admin true login`, output)
errors.CheckError(SetAccounts(map[string][]string{
"test": {"login", "apiKey"},
}))
output, err = RunCli("account", "list")
errors.CheckError(err)
assert.Equal(t, `NAME ENABLED CAPABILITIES
admin true login
test true login, apiKey`, output)
token, err := RunCli("account", "generate-token", "--account", "test")
errors.CheckError(err)
clientOpts := ArgoCDClientset.ClientOptions()
clientOpts.AuthToken = token
testAccountClientset := headless.NewClientOrDie(&clientOpts, &cobra.Command{})
closer, client := testAccountClientset.NewSessionClientOrDie()
defer utilio.Close(closer)
info, err := client.GetUserInfo(t.Context(), &session.GetUserInfoRequest{})
require.NoError(t, err)
assert.Equal(t, "test", info.Username)
}
func TestLoginBadCredentials(t *testing.T) {
EnsureCleanState(t)
closer, sessionClient := ArgoCDClientset.NewSessionClientOrDie()
defer utilio.Close(closer)
requests := []session.SessionCreateRequest{{
Username: "user-does-not-exist", Password: "some-password",
}, {
Username: "admin", Password: "bad-password",
}}
for _, r := range requests {
_, err := sessionClient.Create(t.Context(), &r)
require.Error(t, err)
errStatus, ok := status.FromError(err)
if !assert.True(t, ok) {
return
}
assert.Equal(t, codes.Unauthenticated, errStatus.Code())
assert.Equal(t, "Invalid username or password", errStatus.Message())
}
}
func TestAccountSessionToken(t *testing.T) {
// Create a unique temporary config directory for this test to support parallel execution
tmpDir := t.TempDir()
configPath := filepath.Join(tmpDir, "config")
ctx := accountFixture.Given(t)
ctx.
Name("test").
ConfigPath(configPath).
When().
Create().
CLILogin().
SessionToken().
Then().
AndCLIOutput(func(output string, err error) {
require.NoError(t, err, "session-token command should succeed")
// Verify token is not empty and is a valid JWT format
token := strings.TrimSpace(output)
assert.NotEmpty(t, token)
assert.True(t, jwtutil.IsValid(token), "Token should be a valid JWT format")
// Verify the token can be used for authentication
clientOpts := ArgoCDClientset.ClientOptions()
clientOpts.AuthToken = token
testAccountClientset := headless.NewClientOrDie(&clientOpts, &cobra.Command{})
closer, client := testAccountClientset.NewSessionClientOrDie()
defer utilio.Close(closer)
info, err := client.GetUserInfo(t.Context(), &session.GetUserInfoRequest{})
require.NoError(t, err)
// Verify the token belongs to the test user
assert.Equal(t, ctx.GetName(), info.Username)
assert.True(t, info.LoggedIn)
}).
When().
SessionTokenJSON().
Then().
AndCLIOutput(func(output string, err error) {
require.NoError(t, err, "session-token with JSON output should succeed")
// Parse JSON output
var tokenInfo map[string]any
err = json.Unmarshal([]byte(output), &tokenInfo)
require.NoError(t, err, "JSON output should be valid")
// Verify JSON fields exist
assert.Contains(t, tokenInfo, "token")
assert.Contains(t, tokenInfo, "type")
assert.Contains(t, tokenInfo, "issuer")
assert.Contains(t, tokenInfo, "username")
assert.Contains(t, tokenInfo, "has_refresh_token")
// Verify token type is local
assert.Equal(t, "local", tokenInfo["type"])
// Verify username
username, ok := tokenInfo["username"].(string)
require.True(t, ok, "username should be a string")
assert.Equal(t, ctx.GetName(), username)
})
}