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

Commit d14be73

Browse files
author
Faris Huskovic
authored
Merge pull request #189 from cdr/faris/2456/implement-coder-images-ls
Implement coder images ls
2 parents 8ebcfd1 + 30126a3 commit d14be73

File tree

8 files changed

+207
-13
lines changed

8 files changed

+207
-13
lines changed

ci/integration/images_test.go

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package integration
2+
3+
import (
4+
"context"
5+
"regexp"
6+
"testing"
7+
8+
"cdr.dev/coder-cli/coder-sdk"
9+
"cdr.dev/coder-cli/pkg/tcli"
10+
)
11+
12+
func TestImagesCLI(t *testing.T) {
13+
t.Parallel()
14+
15+
run(t, "coder-cli-images-tests", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
16+
headlessLogin(ctx, t, c)
17+
18+
// Successfully output help.
19+
c.Run(ctx, "coder images --help").Assert(t,
20+
tcli.Success(),
21+
tcli.StdoutMatches(regexp.QuoteMeta("Manage existing images and/or import new ones.")),
22+
tcli.StderrEmpty(),
23+
)
24+
25+
// OK - human output
26+
c.Run(ctx, "coder images ls").Assert(t,
27+
tcli.Success(),
28+
)
29+
30+
imgs := []coder.Image{}
31+
// OK - json output
32+
c.Run(ctx, "coder images ls --output json").Assert(t,
33+
tcli.Success(),
34+
tcli.StdoutJSONUnmarshal(&imgs),
35+
)
36+
37+
// Org not found
38+
c.Run(ctx, "coder images ls --org doesntexist").Assert(t,
39+
tcli.Error(),
40+
tcli.StderrMatches(regexp.QuoteMeta("org name \"doesntexist\" not found\n\n")),
41+
)
42+
})
43+
}

coder-sdk/image.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ import (
88

99
// Image describes a Coder Image.
1010
type Image struct {
11-
ID string `json:"id"`
12-
OrganizationID string `json:"organization_id"`
13-
Repository string `json:"repository"`
14-
Description string `json:"description"`
15-
URL string `json:"url"` // User-supplied URL for image.
16-
Registry *Registry `json:"registry"`
17-
DefaultTag *ImageTag `json:"default_tag"`
18-
DefaultCPUCores float32 `json:"default_cpu_cores"`
19-
DefaultMemoryGB float32 `json:"default_memory_gb"`
20-
DefaultDiskGB int `json:"default_disk_gb"`
21-
Deprecated bool `json:"deprecated"`
22-
CreatedAt time.Time `json:"created_at"`
23-
UpdatedAt time.Time `json:"updated_at"`
11+
ID string `json:"id" table:"-"`
12+
OrganizationID string `json:"organization_id" table:"-"`
13+
Repository string `json:"repository" table:"Repository"`
14+
Description string `json:"description" table:"-"`
15+
URL string `json:"url" table:"-"` // User-supplied URL for image.
16+
Registry *Registry `json:"registry" table:"-"`
17+
DefaultTag *ImageTag `json:"default_tag" table:"DefaultTag"`
18+
DefaultCPUCores float32 `json:"default_cpu_cores" table:"DefaultCPUCores"`
19+
DefaultMemoryGB float32 `json:"default_memory_gb" table:"DefaultMemoryGB"`
20+
DefaultDiskGB int `json:"default_disk_gb" table:"DefaultDiskGB"`
21+
Deprecated bool `json:"deprecated" table:"-"`
22+
CreatedAt time.Time `json:"created_at" table:"-"`
23+
UpdatedAt time.Time `json:"updated_at" table:"-"`
2424
}
2525

2626
// NewRegistryRequest describes a docker registry used in importing an image.

coder-sdk/tags.go

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ type ImageTag struct {
1818
CreatedAt time.Time `json:"created_at" table:"-"`
1919
}
2020

21+
func (i ImageTag) String() string {
22+
return i.Tag
23+
}
24+
2125
// OSRelease is the marshalled /etc/os-release file.
2226
type OSRelease struct {
2327
ID string `json:"id"`

docs/coder.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ coder provides a CLI for working with an existing Coder Enterprise installation
1414
* [coder completion](coder_completion.md) - Generate completion script
1515
* [coder config-ssh](coder_config-ssh.md) - Configure SSH to access Coder environments
1616
* [coder envs](coder_envs.md) - Interact with Coder environments
17+
* [coder images](coder_images.md) - Manage Coder images
1718
* [coder login](coder_login.md) - Authenticate this client for future operations
1819
* [coder logout](coder_logout.md) - Remove local authentication credentials if any exist
1920
* [coder sh](coder_sh.md) - Open a shell and execute commands in a Coder environment

docs/coder_images.md

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
## coder images
2+
3+
Manage Coder images
4+
5+
### Synopsis
6+
7+
Manage existing images and/or import new ones.
8+
9+
### Options
10+
11+
```
12+
-h, --help help for images
13+
--user string Specifies the user by email (default "me")
14+
```
15+
16+
### Options inherited from parent commands
17+
18+
```
19+
-v, --verbose show verbose output
20+
```
21+
22+
### SEE ALSO
23+
24+
* [coder](coder.md) - coder provides a CLI for working with an existing Coder Enterprise installation
25+
* [coder images ls](coder_images_ls.md) - list all images available to the active user
26+

docs/coder_images_ls.md

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
## coder images ls
2+
3+
list all images available to the active user
4+
5+
### Synopsis
6+
7+
List all Coder images available to the active user.
8+
9+
```
10+
coder images ls [flags]
11+
```
12+
13+
### Options
14+
15+
```
16+
-h, --help help for ls
17+
--org string organization name
18+
--output string human | json (default "human")
19+
```
20+
21+
### Options inherited from parent commands
22+
23+
```
24+
--user string Specifies the user by email (default "me")
25+
-v, --verbose show verbose output
26+
```
27+
28+
### SEE ALSO
29+
30+
* [coder images](coder_images.md) - Manage Coder images
31+

internal/cmd/cmd.go

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func Make() *cobra.Command {
3535
tokensCmd(),
3636
resourceCmd(),
3737
completionCmd(),
38+
imgsCmd(),
3839
genDocsCmd(app),
3940
)
4041
app.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "show verbose output")

internal/cmd/images.go

+88
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
package cmd
2+
3+
import (
4+
"encoding/json"
5+
"os"
6+
7+
"cdr.dev/coder-cli/coder-sdk"
8+
"cdr.dev/coder-cli/pkg/clog"
9+
"cdr.dev/coder-cli/pkg/tablewriter"
10+
"github.com/spf13/cobra"
11+
"golang.org/x/xerrors"
12+
)
13+
14+
func imgsCmd() *cobra.Command {
15+
var user string
16+
17+
cmd := &cobra.Command{
18+
Use: "images",
19+
Short: "Manage Coder images",
20+
Long: "Manage existing images and/or import new ones.",
21+
}
22+
23+
cmd.PersistentFlags().StringVar(&user, "user", coder.Me, "Specifies the user by email")
24+
cmd.AddCommand(lsImgsCommand(&user))
25+
return cmd
26+
}
27+
28+
func lsImgsCommand(user *string) *cobra.Command {
29+
var (
30+
orgName string
31+
outputFmt string
32+
)
33+
34+
cmd := &cobra.Command{
35+
Use: "ls",
36+
Short: "list all images available to the active user",
37+
Long: "List all Coder images available to the active user.",
38+
RunE: func(cmd *cobra.Command, args []string) error {
39+
ctx := cmd.Context()
40+
41+
client, err := newClient(ctx)
42+
if err != nil {
43+
return err
44+
}
45+
46+
imgs, err := getImgs(ctx, client,
47+
getImgsConf{
48+
email: *user,
49+
orgName: orgName,
50+
},
51+
)
52+
53+
if err != nil {
54+
return err
55+
}
56+
57+
if len(imgs) < 1 {
58+
clog.LogInfo("no images found")
59+
imgs = []coder.Image{} // ensures that json output still marshals
60+
}
61+
62+
switch outputFmt {
63+
case jsonOutput:
64+
enc := json.NewEncoder(os.Stdout)
65+
// pretty print the json
66+
enc.SetIndent("", "\t")
67+
68+
if err := enc.Encode(imgs); err != nil {
69+
return xerrors.Errorf("write images as JSON: %w", err)
70+
}
71+
return nil
72+
case humanOutput:
73+
err = tablewriter.WriteTable(len(imgs), func(i int) interface{} {
74+
return imgs[i]
75+
})
76+
if err != nil {
77+
return xerrors.Errorf("write table: %w", err)
78+
}
79+
return nil
80+
default:
81+
return xerrors.Errorf("%q is not a supported value for --output", outputFmt)
82+
}
83+
},
84+
}
85+
cmd.Flags().StringVar(&orgName, "org", "", "organization name")
86+
cmd.Flags().StringVar(&outputFmt, "output", humanOutput, "human | json")
87+
return cmd
88+
}

0 commit comments

Comments
 (0)