Skip to content

Commit

Permalink
feat: require workspace when creating projects (#382)
Browse files Browse the repository at this point in the history
  • Loading branch information
zepatrik committed Sep 23, 2024
1 parent b215681 commit de3f2c9
Show file tree
Hide file tree
Showing 18 changed files with 150 additions and 69 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ jobs:
ORY_RATE_LIMIT_HEADER: ${{ secrets.ORY_RATE_LIMIT_HEADER }}
ORY_CONSOLE_URL: https://console.staging.ory.dev
ORY_ORYAPIS_URL: https://staging.oryapis.dev
- uses: actions/upload-artifact@v4
with:
name: playwright-traces
path: playwright-traces

docs:
name: Generate docs
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ unpacked_bin/
cypress/screenshots
cypress/videos
cli
playwright-traces
.DS_Store
2 changes: 1 addition & 1 deletion cmd/cloudx/accountexperience/accountexperience_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ var (
)

func TestMain(m *testing.M) {
ctx, _, _, project, cmd = testhelpers.CreateDefaultAssetsBrowser()
ctx, _, _, _, project, cmd = testhelpers.CreateDefaultAssetsBrowser()
testhelpers.UseStaging()
m.Run()
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/cloudx/client/command_helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ func TestCommandHelper(t *testing.T) {

t.Run("func=CreateProject", func(t *testing.T) {
t.Parallel()
ctx := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfigFile)
ctx, _ := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfigFile)

h, err := client.NewCommandHelper(ctx)
require.NoError(t, err)
Expand Down
3 changes: 2 additions & 1 deletion cmd/cloudx/identity/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import (
func TestListIdentities(t *testing.T) {
t.Parallel()

project := testhelpers.CreateProject(ctx, t, nil)
workspace := testhelpers.CreateWorkspace(ctx, t)
project := testhelpers.CreateProject(ctx, t, workspace)
userID := testhelpers.ImportIdentity(ctx, t, project.Id, nil)

t.Run("is not able to list identities if not authenticated and quiet flag", func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion cmd/cloudx/identity/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ var (
)

func TestMain(m *testing.M) {
ctx, _, _, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
ctx, _, _, _, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
m.Run()
}
5 changes: 3 additions & 2 deletions cmd/cloudx/oauth2/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var (
)

func TestMain(m *testing.M) {
ctx, _, _, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
ctx, _, _, _, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
m.Run()
}

Expand Down Expand Up @@ -140,7 +140,8 @@ func TestImportClient(t *testing.T) {
func TestListClients(t *testing.T) {
t.Parallel()

project := testhelpers.CreateProject(ctx, t, nil)
workspace := testhelpers.CreateWorkspace(ctx, t)
project := testhelpers.CreateProject(ctx, t, workspace)
clientID := testhelpers.CreateClient(ctx, t, project.Id).Get("client_id").String()

t.Run("is not able to list oauth2 clients if not authenticated and quiet flag", func(t *testing.T) {
Expand Down
2 changes: 1 addition & 1 deletion cmd/cloudx/organizations/organizations_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ var (
)

func TestMain(m *testing.M) {
_, _, _, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
_, _, _, _, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
m.Run()
}

Expand Down
11 changes: 8 additions & 3 deletions cmd/cloudx/project/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,13 @@ func NewCreateProjectCmd() *cobra.Command {
return err
}

if (len(name) == 0 || len(environment) == 0) && flagx.MustGetBool(cmd, cmdx.FlagQuiet) {
return errors.New("you must specify the --name and --environment flags when using --quiet")
wsID := h.WorkspaceID()
if wsID == nil {
return errors.New("a workspace is required to create a project")
}

if len(name) == 0 && flagx.MustGetBool(cmd, cmdx.FlagQuiet) {
return errors.New("you must specify the --name flag when using --quiet")
}

for name == "" {
Expand All @@ -51,7 +56,7 @@ func NewCreateProjectCmd() *cobra.Command {
}
}

p, err := h.CreateProject(ctx, name, string(environment), h.WorkspaceID(), useProject)
p, err := h.CreateProject(ctx, name, string(environment), wsID, useProject)
if err != nil {
return cmdx.PrintOpenAPIError(cmd, err)
}
Expand Down
50 changes: 40 additions & 10 deletions cmd/cloudx/project/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ package project_test

import (
"context"
"encoding/json"
"os"
"strings"
"testing"

"github.com/gofrs/uuid"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/tidwall/gjson"
Expand All @@ -33,14 +37,38 @@ func TestCreateProject(t *testing.T) {
return
}

t.Run("requires workspace and environment", func(t *testing.T) {
t.Parallel()

ctx, newConfig := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
conf := testhelpers.ReadConfig(t, newConfig)
conf.SelectedWorkspace = uuid.Nil
rawConfig, err := json.Marshal(conf)
require.NoError(t, err)
require.NoError(t, os.WriteFile(newConfig, rawConfig, 0600))

for _, extraArgs := range [][]string{
{},
{"--environment", "dev"},
} {
t.Run("args="+strings.Join(extraArgs, " "), func(t *testing.T) {
_, stderr, err := testhelpers.Cmd(ctx).Exec(nil, append([]string{"create", "project", "--name", testhelpers.TestName(), "--format", "json"}, extraArgs...)...)
require.Error(t, err)
assert.Contains(t, stderr, "a workspace is required to create a project")
})
}
})

t.Run("is able to create a project", func(t *testing.T) {
t.Parallel()

ctx := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
ctx, _ := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
testhelpers.SetDefaultProject(ctx, t, defaultProject.Id)

wsID := testhelpers.CreateWorkspace(ctx, t)

name := testhelpers.TestName()
stdout, _, err := testhelpers.Cmd(ctx).Exec(nil, "create", "project", "--name", name, "--format", "json")
stdout, _, err := testhelpers.Cmd(ctx).Exec(nil, "create", "project", "--name", name, "--format", "json", "--workspace", wsID)
require.NoError(t, err)
assertResult(t, defaultConfig, stdout, name)

Expand All @@ -50,10 +78,11 @@ func TestCreateProject(t *testing.T) {
t.Run("is able to create a project and use the project as default", func(t *testing.T) {
t.Parallel()

ctx := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
ctx, _ := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)

workspace := testhelpers.CreateWorkspace(ctx, t)
name := testhelpers.TestName()
stdout, _, err := testhelpers.Cmd(ctx).Exec(nil, "create", "project", "--name", name, "--use-project", "--format", "json")
stdout, _, err := testhelpers.Cmd(ctx).Exec(nil, "create", "project", "--name", name, "--use-project", "--workspace", workspace, "--environment", "dev", "--format", "json")
require.NoError(t, err)
id, _, _ := assertResult(t, defaultConfig, stdout, name)

Expand All @@ -65,28 +94,29 @@ func TestCreateProject(t *testing.T) {

name := testhelpers.TestName()
stdin := strings.NewReader(name + "\n")
stdout, _, err := defaultCmd.Exec(stdin, "create", "project", "--format", "json")
workspace := testhelpers.CreateWorkspace(ctx, t)
stdout, _, err := defaultCmd.Exec(stdin, "create", "project", "--workspace", workspace, "--environment", "dev", "--format", "json")
require.NoError(t, err)
assertResult(t, defaultConfig, stdout, name)
})

t.Run("is not able to create a project if no name flag and quiet flag", func(t *testing.T) {
t.Parallel()

workspace := testhelpers.CreateWorkspace(ctx, t)
name := testhelpers.TestName()
stdin := strings.NewReader(name)
_, stderr, err := defaultCmd.Exec(stdin, "create", "project", "--quiet")
_, stderr, err := defaultCmd.Exec(stdin, "create", "project", "--quiet", "--workspace", workspace, "--environment", "dev")
require.Error(t, err)
assert.Contains(t, stderr, "you must specify the --name and --environment flags when using --quiet")
assert.Contains(t, stderr, "you must specify the --name flag when using --quiet")
})

t.Run("is not able to create a project if not authenticated and quiet flag", func(t *testing.T) {
t.Parallel()

ctx := testhelpers.WithCleanConfigFile(context.Background(), t)

name := testhelpers.TestName()
_, _, err := testhelpers.Cmd(ctx).Exec(nil, "create", "project", "--name", name, "--quiet")
_, _, err := testhelpers.Cmd(ctx).Exec(nil, "create", "project", "--name", testhelpers.TestName(), "--workspace", uuid.Must(uuid.NewV4()).String(), "--environment", "dev", "--quiet")
require.ErrorIs(t, err, client.ErrNoConfigQuiet)
})

Expand All @@ -95,7 +125,7 @@ func TestCreateProject(t *testing.T) {

ctx := testhelpers.WithEmitAuthFlowTriggeredErr(context.Background(), t)

_, _, err := testhelpers.Cmd(ctx).Exec(nil, "create", "project", "--name", testhelpers.TestName(), "--format", "json")
_, _, err := testhelpers.Cmd(ctx).Exec(nil, "create", "project", "--name", testhelpers.TestName(), "--workspace", uuid.Must(uuid.NewV4()).String(), "--environment", "dev", "--format", "json")
assert.ErrorIs(t, err, testhelpers.ErrAuthFlowTriggered)
})
}
6 changes: 3 additions & 3 deletions cmd/cloudx/project/helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ type execFunc = func(stdin io.Reader, args ...string) (string, string, error)

func runWithProjectAsDefault(ctx context.Context, t *testing.T, projectID string, test func(t *testing.T, exec execFunc)) {
t.Run("project passed as default", func(t *testing.T) {
ctx := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
ctx, _ := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
testhelpers.SetDefaultProject(ctx, t, projectID)

test(t, testhelpers.Cmd(ctx).Exec)
Expand All @@ -30,7 +30,7 @@ func runWithProjectAsDefault(ctx context.Context, t *testing.T, projectID string

func runWithProjectAsArgument(ctx context.Context, t *testing.T, projectID string, test func(t *testing.T, exec execFunc)) {
t.Run("project passed as argument", func(t *testing.T) {
ctx := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
ctx, _ := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
selectedProject := testhelpers.GetDefaultProjectID(ctx, t)
require.NotEqual(t, selectedProject, projectID, "to ensure correct isolation, please use another project than the 'default' selected")

Expand All @@ -46,7 +46,7 @@ func runWithProjectAsArgument(ctx context.Context, t *testing.T, projectID strin

func runWithProjectAsFlag(ctx context.Context, t *testing.T, projectID string, test func(t *testing.T, exec execFunc)) {
t.Run("project passed as flag", func(t *testing.T) {
ctx := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
ctx, _ := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
selectedProject := testhelpers.GetDefaultProjectID(ctx, t)
require.NotEqual(t, selectedProject, projectID, "to ensure correct isolation, please use another project than the 'default' selected")

Expand Down
36 changes: 10 additions & 26 deletions cmd/cloudx/project/list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,45 +21,29 @@ import (
func TestListProject(t *testing.T) {
t.Parallel()

// this test needs a separate account to properly list projects
ctx := client.ContextWithOptions(ctx,
client.WithConfigLocation(testhelpers.NewConfigFile(t)))

email, password, _, _ := testhelpers.RegisterAccount(context.Background(), t)
_, page, cleanup := testhelpers.SetupPlaywright(t)
t.Cleanup(cleanup)
h, err := client.NewCommandHelper(
ctx,
client.WithQuiet(false),
client.WithOpenBrowserHook(testhelpers.PlaywrightAcceptConsentBrowserHook(t, page, email, password)),
)
require.NoError(t, err)
require.NoError(t, h.Authenticate(ctx))
cleanup()

cmd := testhelpers.Cmd(ctx)

projects := make([]*cloud.Project, 3)
workspace := testhelpers.CreateWorkspace(ctx, t)
projects := make([]*cloud.Project, 2)
projectIDs := make([]string, len(projects))
for k := range projects {
projects[k] = testhelpers.CreateProject(ctx, t, nil)
projects[k] = testhelpers.CreateProject(ctx, t, workspace)
projectIDs[k] = projects[k].Id
}

assertHasProjects := func(t *testing.T, stdout string) {
out := gjson.Parse(stdout)
assert.EqualValues(t, out.Get("#").Int(), len(projects))
out.ForEach(func(_, project gjson.Result) bool {
assert.Contains(t, projectIDs, project.Get("id").String())
return true
})
require.EqualValues(t, out.Get("#").Int(), len(projects))
actualIDs := make([]string, 0, len(projects))
for _, id := range out.Get("#.id").Array() {
actualIDs = append(actualIDs, id.Str)
}
assert.ElementsMatch(t, projectIDs, actualIDs)
}

for _, proc := range []string{"list", "ls"} {
t.Run(fmt.Sprintf("is able to %s projects", proc), func(t *testing.T) {
t.Parallel()

stdout, _, err := cmd.Exec(nil, proc, "projects", "--format", "json")
stdout, _, err := defaultCmd.Exec(nil, proc, "projects", "--format", "json", "--workspace", workspace)
require.NoError(t, err)
assertHasProjects(t, stdout)
})
Expand Down
12 changes: 7 additions & 5 deletions cmd/cloudx/project/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ package project_test

import (
"context"
"fmt"
"testing"

cloud "github.com/ory/client-go"
Expand All @@ -14,13 +15,14 @@ import (
)

var (
ctx context.Context
defaultProject, extraProject *cloud.Project
defaultConfig string
defaultCmd *cmdx.CommandExecuter
ctx context.Context
defaultProject, extraProject *cloud.Project
defaultConfig, defaultWorkspaceID string
defaultCmd *cmdx.CommandExecuter
)

func TestMain(m *testing.M) {
ctx, defaultConfig, extraProject, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
ctx, defaultConfig, defaultWorkspaceID, extraProject, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
fmt.Println("done setting up, running tests")
m.Run()
}
3 changes: 2 additions & 1 deletion cmd/cloudx/project/update_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ var (
func TestUpdateProject(t *testing.T) {
t.Parallel()

project := testhelpers.CreateProject(ctx, t, nil)
workspace := testhelpers.CreateWorkspace(ctx, t)
project := testhelpers.CreateProject(ctx, t, workspace)

for _, tc := range []struct {
subcommand,
Expand Down
2 changes: 1 addition & 1 deletion cmd/cloudx/project/use_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestUseProject(t *testing.T) {
t.Run("is able to use project", func(t *testing.T) {
t.Parallel()

ctx := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
ctx, _ := testhelpers.WithDuplicatedConfigFile(ctx, t, defaultConfig)
testhelpers.SetDefaultProject(ctx, t, defaultProject.Id)

stdout, _, err := testhelpers.Cmd(ctx).Exec(nil, "use", "project", extraProject.Id, "--quiet")
Expand Down
2 changes: 1 addition & 1 deletion cmd/cloudx/relationtuples/relationtuples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ var (
)

func TestMain(m *testing.M) {
_, _, _, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
_, _, _, _, defaultProject, defaultCmd = testhelpers.CreateDefaultAssetsBrowser()
m.Run()
}

Expand Down
Loading

0 comments on commit de3f2c9

Please sign in to comment.