Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Add envs create command #149

Merged
merged 1 commit into from
Oct 22, 2020
Merged
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
69 changes: 69 additions & 0 deletions ci/integration/envs_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package integration

import (
"context"
"regexp"
"testing"

"cdr.dev/coder-cli/ci/tcli"
)

// From Coder organization images
const ubuntuImgID = "5f443b16-30652892427b955601330fa5"

func TestEnvsCLI(t *testing.T) {
t.Parallel()

run(t, "coder-cli-env-tests", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
headlessLogin(ctx, t, c)

// Ensure binary is present.
c.Run(ctx, "which coder").Assert(t,
tcli.Success(),
tcli.StdoutMatches("/usr/sbin/coder"),
tcli.StderrEmpty(),
)

// Minimum args not received.
c.Run(ctx, "coder envs create").Assert(t,
tcli.StderrMatches(regexp.QuoteMeta("accepts 1 arg(s), received 0")),
tcli.Error(),
)

// Successfully output help.
c.Run(ctx, "coder envs create --help").Assert(t,
tcli.Success(),
tcli.StdoutMatches(regexp.QuoteMeta("Create a new environment under the active user.")),
tcli.StderrEmpty(),
)

// TODO(Faris) : uncomment this when we can safely purge the environments
// the integrations tests would create in the sidecar
// Successfully create environment.
// c.Run(ctx, "coder envs create --image "+ubuntuImgID+" test-ubuntu").Assert(t,
// tcli.Success(),
// // why does flog.Success write to stderr?
// tcli.StderrMatches(regexp.QuoteMeta("Successfully created environment \"test-ubuntu\"")),
// )

// Invalid environment name should fail.
c.Run(ctx, "coder envs create --image "+ubuntuImgID+" this-IS-an-invalid-EnvironmentName").Assert(t,
tcli.Error(),
tcli.StderrMatches(regexp.QuoteMeta("environment name must conform to regex ^[a-z0-9]([a-z0-9-]+)?")),
)

// TODO(Faris) : uncomment this when we can safely purge the environments
// the integrations tests would create in the sidecar
// Successfully provision environment with fractional resource amounts
// c.Run(ctx, fmt.Sprintf(`coder envs create -i %s -c 1.2 -m 1.4 non-whole-resource-amounts`, ubuntuImgID)).Assert(t,
// tcli.Success(),
// tcli.StderrMatches(regexp.QuoteMeta("Successfully created environment \"non-whole-resource-amounts\"")),
// )

// Image does not exist should fail.
c.Run(ctx, "coder envs create --image does-not-exist env-will-not-be-created").Assert(t,
tcli.Error(),
tcli.StderrMatches(regexp.QuoteMeta("does not exist")),
)
})
}
6 changes: 0 additions & 6 deletions ci/steps/gendocs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,6 @@ rm -rf ./docs
mkdir ./docs
go run ./cmd/coder gen-docs ./docs

# remove cobra footer from each file
for filename in ./docs/*.md; do
trimmed=$(head -n -1 "$filename")
echo "$trimmed" >$filename
done

if [[ ${CI-} && $(git ls-files --other --modified --exclude-standard) ]]; then
echo "Documentation needs generation:"
git -c color.ui=always status | grep --color=no '\e\[31m'
Expand Down
2 changes: 1 addition & 1 deletion coder-sdk/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ type CreateEnvironmentRequest struct {
ImageID string `json:"image_id"`
ImageTag string `json:"image_tag"`
CPUCores float32 `json:"cpu_cores"`
MemoryGB int `json:"memory_gb"`
MemoryGB float32 `json:"memory_gb"`
DiskGB int `json:"disk_gb"`
GPUs int `json:"gpus"`
Services []string `json:"services"`
Expand Down
1 change: 1 addition & 0 deletions docs/coder.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ coder provides a CLI for working with an existing Coder Enterprise installation
* [coder sync](coder_sync.md) - Establish a one way directory sync to a Coder environment
* [coder urls](coder_urls.md) - Interact with environment DevURLs
* [coder users](coder_users.md) - Interact with Coder user accounts

1 change: 1 addition & 0 deletions docs/coder_completion.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ MacOS:
### SEE ALSO

* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation

1 change: 1 addition & 0 deletions docs/coder_config-ssh.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ coder config-ssh [flags]
### SEE ALSO

* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation

1 change: 1 addition & 0 deletions docs/coder_envs.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ Perform operations on the Coder environments owned by the active user.
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
* [coder envs ls](coder_envs_ls.md) - list all environments owned by the active user
* [coder envs stop](coder_envs_stop.md) - stop Coder environments by name

1 change: 1 addition & 0 deletions docs/coder_envs_ls.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ coder envs ls [flags]
### SEE ALSO

* [coder envs](coder_envs.md) - Interact with Coder environments

1 change: 1 addition & 0 deletions docs/coder_envs_stop.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,4 @@ coder envs --user charlie@coder.com ls -o json \
### SEE ALSO

* [coder envs](coder_envs.md) - Interact with Coder environments

1 change: 1 addition & 0 deletions docs/coder_login.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ coder login [Coder Enterprise URL eg. https://my.coder.domain/] [flags]
### SEE ALSO

* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation

1 change: 1 addition & 0 deletions docs/coder_logout.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ coder logout [flags]
### SEE ALSO

* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation

1 change: 1 addition & 0 deletions docs/coder_secrets.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ Interact with secrets objects owned by the active user.
* [coder secrets ls](coder_secrets_ls.md) - List all secrets owned by the active user
* [coder secrets rm](coder_secrets_rm.md) - Remove one or more secrets by name
* [coder secrets view](coder_secrets_view.md) - View a secret by name

1 change: 1 addition & 0 deletions docs/coder_secrets_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ coder secrets create aws-credentials --from-file ./credentials.json
### SEE ALSO

* [coder secrets](coder_secrets.md) - Interact with Coder Secrets

1 change: 1 addition & 0 deletions docs/coder_secrets_ls.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ coder secrets ls [flags]
### SEE ALSO

* [coder secrets](coder_secrets.md) - Interact with Coder Secrets

1 change: 1 addition & 0 deletions docs/coder_secrets_rm.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ coder secrets rm mysql-password mysql-user
### SEE ALSO

* [coder secrets](coder_secrets.md) - Interact with Coder Secrets

1 change: 1 addition & 0 deletions docs/coder_secrets_view.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ coder secrets view mysql-password
### SEE ALSO

* [coder secrets](coder_secrets.md) - Interact with Coder Secrets

1 change: 1 addition & 0 deletions docs/coder_sh.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ coder sh backend-env
### SEE ALSO

* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation

1 change: 1 addition & 0 deletions docs/coder_sync.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ coder sync [local directory] [<env name>:<remote directory>] [flags]
### SEE ALSO

* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation

1 change: 1 addition & 0 deletions docs/coder_urls.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ Interact with environment DevURLs
* [coder urls create](coder_urls_create.md) - Create a new devurl for an environment
* [coder urls ls](coder_urls_ls.md) - List all DevURLs for an environment
* [coder urls rm](coder_urls_rm.md) - Remove a dev url

1 change: 1 addition & 0 deletions docs/coder_urls_create.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ coder urls create [env_name] [port] [--access <level>] [--name <name>] [flags]
### SEE ALSO

* [coder urls](coder_urls.md) - Interact with environment DevURLs

1 change: 1 addition & 0 deletions docs/coder_urls_ls.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ coder urls ls [environment_name] [flags]
### SEE ALSO

* [coder urls](coder_urls.md) - Interact with environment DevURLs

1 change: 1 addition & 0 deletions docs/coder_urls_rm.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ coder urls rm [environment_name] [port] [flags]
### SEE ALSO

* [coder urls](coder_urls.md) - Interact with environment DevURLs

1 change: 1 addition & 0 deletions docs/coder_users.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,4 @@ Interact with Coder user accounts

* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
* [coder users ls](coder_users_ls.md) - list all user accounts

1 change: 1 addition & 0 deletions docs/coder_users_ls.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ coder users ls -o json | jq .[] | jq -r .email
### SEE ALSO

* [coder users](coder_users.md) - Interact with Coder user accounts

9 changes: 5 additions & 4 deletions internal/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ var verbose bool = false
// Make constructs the "coder" root command
func Make() *cobra.Command {
app := &cobra.Command{
Use: "coder",
Short: "coder provides a CLI for working with an existing Coder Enterprise installation",
SilenceErrors: true,
SilenceUsage: true,
Use: "coder",
Short: "coder provides a CLI for working with an existing Coder Enterprise installation",
SilenceErrors: true,
SilenceUsage: true,
DisableAutoGenTag: true,
}

app.AddCommand(
Expand Down
84 changes: 83 additions & 1 deletion internal/cmd/envs.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ import (
"golang.org/x/xerrors"
)

const (
defaultOrg = "default"
defaultImgTag = "latest"
defaultCPUCores float32 = 1
defaultMemGB float32 = 1
defaultDiskGB = 10
defaultGPUs = 0
)

func envsCommand() *cobra.Command {
var outputFmt string
var user string
Expand Down Expand Up @@ -64,9 +73,9 @@ func envsCommand() *cobra.Command {
lsCmd.Flags().StringVarP(&outputFmt, "output", "o", "human", "human | json")
cmd.AddCommand(lsCmd)
cmd.AddCommand(stopEnvCommand(&user))

cmd.AddCommand(watchBuildLogCommand())
cmd.AddCommand(rebuildEnvCommand())
cmd.AddCommand(createEnvCommand())
return cmd
}

Expand Down Expand Up @@ -125,3 +134,76 @@ coder envs --user charlie@coder.com ls -o json \
},
}
}

func createEnvCommand() *cobra.Command {
var (
org string
img string
tag string
follow bool
)

cmd := &cobra.Command{
Use: "create [environment_name]",
Short: "create a new environment.",
Args: cobra.ExactArgs(1),
// Don't unhide this command until we can pass image names instead of image id's.
Hidden: true,
Long: "Create a new environment under the active user.",
Example: `# create a new environment using default resource amounts
coder envs create --image 5f443b16-30652892427b955601330fa5 my-env-name

# create a new environment using custom resource amounts
coder envs create --cpu 4 --disk 100 --memory 8 --image 5f443b16-30652892427b955601330fa5 my-env-name`,
RunE: func(cmd *cobra.Command, args []string) error {
if img == "" {
return xerrors.New("image id unset")
}
// ExactArgs(1) ensures our name value can't panic on an out of bounds.
createReq := &coder.CreateEnvironmentRequest{
Name: args[0],
ImageID: img,
ImageTag: tag,
}
// We're explicitly ignoring errors for these because all of these flags
// have a non-zero-value default value set already.
createReq.CPUCores, _ = cmd.Flags().GetFloat32("cpu")
createReq.MemoryGB, _ = cmd.Flags().GetFloat32("memory")
createReq.DiskGB, _ = cmd.Flags().GetInt("disk")
createReq.GPUs, _ = cmd.Flags().GetInt("gpus")

client, err := newClient()
if err != nil {
return err
}

env, err := client.CreateEnvironment(cmd.Context(), org, *createReq)
if err != nil {
return xerrors.Errorf("create environment: %w", err)
}

clog.LogSuccess(
"creating environment...",
clog.BlankLine,
clog.Tip(`run "coder envs watch-build %q" to trail the build logs`, args[0]),
)

if follow {
if err := trailBuildLogs(cmd.Context(), client, env.ID); err != nil {
return err
}
}
return nil
},
}
cmd.Flags().StringVarP(&org, "org", "o", defaultOrg, "ID of the organization the environment should be created under.")
cmd.Flags().StringVarP(&tag, "tag", "t", defaultImgTag, "tag of the image the environment will be based off of.")
cmd.Flags().Float32P("cpu", "c", defaultCPUCores, "number of cpu cores the environment should be provisioned with.")
cmd.Flags().Float32P("memory", "m", defaultMemGB, "GB of RAM an environment should be provisioned with.")
cmd.Flags().IntP("disk", "d", defaultDiskGB, "GB of disk storage an environment should be provisioned with.")
cmd.Flags().IntP("gpus", "g", defaultGPUs, "number GPUs an environment should be provisioned with.")
cmd.Flags().StringVarP(&img, "image", "i", "", "ID of the image to base the environment off of.")
cmd.Flags().BoolVar(&follow, "follow", false, "follow buildlog after initiating rebuild")
cmd.MarkFlagRequired("image")
return cmd
}