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

Commit 30126a3

Browse files
author
Faris Huskovic
committed
implement coder images ls
1 parent ce06c53 commit 30126a3

File tree

8 files changed

+207
-13
lines changed

8 files changed

+207
-13
lines changed

ci/integration/images_test.go

Lines changed: 43 additions & 0 deletions
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

Lines changed: 13 additions & 13 deletions
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 26 additions & 0 deletions
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

Lines changed: 31 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 88 additions & 0 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy