-
Notifications
You must be signed in to change notification settings - Fork 2
feat(create-workspace,list-plans): Add commands to CLI #34
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,149 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "errors" | ||
| "fmt" | ||
| "os" | ||
| "time" | ||
|
|
||
| "github.com/codesphere-cloud/cs-go/api" | ||
| "github.com/codesphere-cloud/cs-go/pkg/cs" | ||
| "github.com/codesphere-cloud/cs-go/pkg/out" | ||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| // CreateWorkspaceCmd represents the workspace command | ||
| type CreateWorkspaceCmd struct { | ||
| cmd *cobra.Command | ||
| Opts CreateWorkspaceOpts | ||
| } | ||
|
|
||
| type CreateWorkspaceOpts struct { | ||
| GlobalOptions | ||
| Repo *string | ||
| Vpn *string | ||
| Env *[]string | ||
| Plan *int | ||
| Private *bool | ||
| Timeout *time.Duration | ||
| Branch *string | ||
| } | ||
|
|
||
| func (c *CreateWorkspaceCmd) RunE(_ *cobra.Command, args []string) error { | ||
| client, err := NewClient(c.Opts.GlobalOptions) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create Codesphere client: %w", err) | ||
| } | ||
|
|
||
| teamId, err := c.Opts.GetTeamId() | ||
| if err != nil { | ||
| return fmt.Errorf("failed to get team ID: %w", err) | ||
| } | ||
|
|
||
| if len(args) != 1 { | ||
| return errors.New("workspace name not set") | ||
| } | ||
| wsName := args[0] | ||
|
|
||
| ws, err := c.CreateWorkspace(client, teamId, wsName) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create workspace: %w", err) | ||
| } | ||
|
|
||
| giturl := "" | ||
| if ws.GitUrl.Get() != nil { | ||
| giturl = *ws.GitUrl.Get() | ||
| } | ||
| branch := "" | ||
| if ws.InitialBranch.Get() != nil { | ||
| branch = *ws.InitialBranch.Get() | ||
| } | ||
| fmt.Println("Workspace created:") | ||
| fmt.Printf("\nID: %d\n", ws.Id) | ||
| fmt.Printf("Name: %s\n", ws.Name) | ||
| fmt.Printf("Team ID: %d\n", ws.TeamId) | ||
| fmt.Printf("Git Repository: %s\n", giturl) | ||
| fmt.Printf("Branch: %s\n", branch) | ||
| fmt.Printf("To open it in the Codesphere IDE run '%s open workspace -w %d'", os.Args[0], ws.Id) | ||
|
|
||
| return nil | ||
| } | ||
|
|
||
| func AddCreateWorkspaceCmd(create *cobra.Command, opts GlobalOptions) { | ||
| workspace := CreateWorkspaceCmd{ | ||
| cmd: &cobra.Command{ | ||
| Use: "workspace", | ||
| Short: "Create a workspace", | ||
| Args: cobra.RangeArgs(1, 1), | ||
| Long: out.Long(`Create a workspace in Codesphere. | ||
|
|
||
| Specify a (private) git repository or start an empty workspace. | ||
| Environment variables can be set to initialize the workspace with a specific environment. | ||
| The command will wait for the workspace to become running or a timeout is reached. | ||
|
|
||
| To decide which plan suits your needs, run 'cs list plans' | ||
| `), | ||
| Example: out.FormatExampleCommands("create workspace my-workspace", []out.Example{ | ||
| {Cmd: "-p 20", Desc: "Create an empty workspace, using plan 20"}, | ||
| {Cmd: "-r https://github.com/codesphere-cloud/landingpage-temp.git", Desc: "Create a workspace from a git repository"}, | ||
| {Cmd: "-r https://github.com/codesphere-cloud/landingpage-temp.git -e DEPLOYMENT=prod -e A=B", Desc: "Create a workspace and set environment variables"}, | ||
| {Cmd: "-r https://github.com/codesphere-cloud/landingpage-temp.git --vpn myVpn", Desc: "Create a workspace and connect to VPN myVpn"}, | ||
| {Cmd: "-r https://github.com/codesphere-cloud/landingpage-temp.git --timeout 30s", Desc: "Create a workspace and wait 30 seconds for it to become running"}, | ||
| {Cmd: "-r https://github.com/codesphere-cloud/landingpage-temp.git -b staging", Desc: "Create a workspace from branch 'staging'"}, | ||
| {Cmd: "-r https://github.com/my-org/my-private-project.git -P", Desc: "Create a workspace from a private git repository"}, | ||
| }), | ||
| }, | ||
| Opts: CreateWorkspaceOpts{GlobalOptions: opts}, | ||
| } | ||
| workspace.Opts.Repo = workspace.cmd.Flags().StringP("repository", "r", "", "Git repository to create the workspace from") | ||
| workspace.Opts.Vpn = workspace.cmd.Flags().String("vpn", "", "Vpn config to use") | ||
| workspace.Opts.Env = workspace.cmd.Flags().StringArrayP("env", "e", []string{}, "Environment variables to set in the workspace in key=value form (e.g. --env DEPLOYMENT=prod)") | ||
| workspace.Opts.Plan = workspace.cmd.Flags().IntP("plan", "p", 8, "Plan ID for the workspace") | ||
| workspace.Opts.Private = workspace.cmd.Flags().BoolP("private", "P", false, "Use private repository") | ||
| workspace.Opts.Timeout = workspace.cmd.Flags().Duration("timeout", 10*time.Minute, "Time to wait for the workspace to start (e.g. 5m for 5 minutes)") | ||
| workspace.Opts.Branch = workspace.cmd.Flags().StringP("branch", "b", "", "branch to check out") | ||
|
|
||
| create.AddCommand(workspace.cmd) | ||
| workspace.cmd.RunE = workspace.RunE | ||
| } | ||
|
|
||
| func (c *CreateWorkspaceCmd) CreateWorkspace(client Client, teamId int, wsName string) (*api.Workspace, error) { | ||
| envVars, err := cs.ArgToEnvVarMap(*c.Opts.Env) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to parse environment variables: %w", err) | ||
| } | ||
|
|
||
| args := api.DeployWorkspaceArgs{ | ||
| TeamId: teamId, | ||
| PlanId: *c.Opts.Plan, | ||
| Name: wsName, | ||
| EnvVars: envVars, | ||
|
|
||
| IsPrivateRepo: *c.Opts.Private, | ||
|
|
||
| Timeout: *c.Opts.Timeout, | ||
| } | ||
|
|
||
| if c.Opts.Repo != nil && *c.Opts.Repo != "" { | ||
| validatedUrl, err := cs.ValidateUrl(*c.Opts.Repo) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("validation of repository URL failed: %w", err) | ||
| } | ||
| args.GitUrl = &validatedUrl | ||
| } | ||
|
|
||
| if c.Opts.Vpn != nil && *c.Opts.Vpn != "" { | ||
| args.VpnConfigName = c.Opts.Vpn | ||
| } | ||
|
|
||
| if c.Opts.Branch != nil && *c.Opts.Branch != "" { | ||
| args.Branch = c.Opts.Branch | ||
| } | ||
|
|
||
| ws, err := client.DeployWorkspace(args) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to create workspace: %w", err) | ||
| } | ||
|
|
||
| return ws, nil | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "github.com/spf13/cobra" | ||
| ) | ||
|
|
||
| // CreateCmd represents the create command | ||
| type CreateCmd struct { | ||
| cmd *cobra.Command | ||
| } | ||
|
|
||
| func AddCreateCmd(rootCmd *cobra.Command, opts GlobalOptions) { | ||
| create := CreateCmd{ | ||
| cmd: &cobra.Command{ | ||
| Use: "create", | ||
| Short: "Create codesphere resource", | ||
| Long: `Create codesphere resources like workspaces.`, | ||
| }, | ||
| } | ||
| rootCmd.AddCommand(create.cmd) | ||
|
|
||
| // Add child commands here | ||
| AddCreateWorkspaceCmd(create.cmd, opts) | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,110 @@ | ||
| package cmd_test | ||
|
|
||
| import ( | ||
| "time" | ||
|
|
||
| . "github.com/onsi/ginkgo/v2" | ||
| . "github.com/onsi/gomega" | ||
|
|
||
| "github.com/codesphere-cloud/cs-go/api" | ||
| "github.com/codesphere-cloud/cs-go/cli/cmd" | ||
| "github.com/codesphere-cloud/cs-go/pkg/cs" | ||
| ) | ||
|
|
||
| var _ = Describe("CreateWorkspace", func() { | ||
| var ( | ||
| mockEnv *cmd.MockEnv | ||
| mockClient *cmd.MockClient | ||
| c *cmd.CreateWorkspaceCmd | ||
| teamId int | ||
| wsName string | ||
| env []string | ||
| repoStr string | ||
| repo *string | ||
| vpn *string | ||
| vpnStr string | ||
| plan int | ||
| private bool | ||
| timeout time.Duration | ||
| branchStr string | ||
| branch *string | ||
| deployArgs api.DeployWorkspaceArgs | ||
| ) | ||
|
|
||
| BeforeEach(func() { | ||
| env = []string{} | ||
| repoStr = "https://fake-git.com/my/repo.git" | ||
| repo = nil | ||
| vpnStr = "MyVpn" | ||
| vpn = nil | ||
| plan = 8 | ||
| private = false | ||
| timeout = 30 * time.Second | ||
| branchStr = "fake-branch" | ||
| branch = nil | ||
| }) | ||
|
|
||
| JustBeforeEach(func() { | ||
| mockClient = cmd.NewMockClient(GinkgoT()) | ||
| mockEnv = cmd.NewMockEnv(GinkgoT()) | ||
| wsName = "foo-workspace" | ||
| teamId = 21 | ||
| c = &cmd.CreateWorkspaceCmd{ | ||
| Opts: cmd.CreateWorkspaceOpts{ | ||
| GlobalOptions: cmd.GlobalOptions{ | ||
| Env: mockEnv, | ||
| TeamId: &teamId, | ||
| }, | ||
| Env: &env, | ||
| Repo: repo, | ||
| Vpn: vpn, | ||
| Plan: &plan, | ||
| Private: &private, | ||
| Timeout: &timeout, | ||
| Branch: branch, | ||
| }, | ||
| } | ||
| envMap, err := cs.ArgToEnvVarMap(env) | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| deployArgs = api.DeployWorkspaceArgs{ | ||
| Name: wsName, | ||
| TeamId: teamId, | ||
| EnvVars: envMap, | ||
| GitUrl: repo, | ||
| VpnConfigName: vpn, | ||
| PlanId: plan, | ||
| IsPrivateRepo: private, | ||
| Timeout: timeout, | ||
| Branch: branch, | ||
| } | ||
| }) | ||
|
|
||
| Context("Minimal values are set", func() { | ||
|
|
||
| It("Creates the workspace", func() { | ||
| mockClient.EXPECT().DeployWorkspace(deployArgs).Return(&api.Workspace{Name: wsName}, nil) | ||
| ws, err := c.CreateWorkspace(mockClient, teamId, wsName) | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(ws.Name).To(Equal(wsName)) | ||
| }) | ||
| }) | ||
|
|
||
| Context("All values are set", func() { | ||
| BeforeEach(func() { | ||
| env = []string{"foo=bla", "blib=blub"} | ||
| repo = &repoStr | ||
| vpn = &vpnStr | ||
| private = true | ||
| timeout = 120 * time.Second | ||
| branch = &branchStr | ||
| wsName = "different-name" | ||
| }) | ||
| It("Creates the workspace and passes expected arguments", func() { | ||
| mockClient.EXPECT().DeployWorkspace(deployArgs).Return(&api.Workspace{Name: wsName}, nil) | ||
| ws, err := c.CreateWorkspace(mockClient, teamId, wsName) | ||
| Expect(err).ToNot(HaveOccurred()) | ||
| Expect(ws.Name).To(Equal(wsName)) | ||
| }) | ||
| }) | ||
|
|
||
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.