Skip to content

Commit

Permalink
feat: Add cli to list imagerunner containers
Browse files Browse the repository at this point in the history
  • Loading branch information
tianfeng92 committed Jan 27, 2024
1 parent 204bade commit 7a31066
Show file tree
Hide file tree
Showing 3 changed files with 127 additions and 0 deletions.
1 change: 1 addition & 0 deletions internal/cmd/imagerunner/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ func Command(preRun func(cmd *cobra.Command, args []string)) *cobra.Command {
LogsCommand(),
ArtifactsCommand(),
StopCommand(),
ListCommand(),
)
return cmd
}
94 changes: 94 additions & 0 deletions internal/cmd/imagerunner/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package imagerunner

import (
"context"
"errors"
"fmt"
"time"

"github.com/jedib0t/go-pretty/v6/table"
cmds "github.com/saucelabs/saucectl/internal/cmd"
"github.com/saucelabs/saucectl/internal/http"
"github.com/saucelabs/saucectl/internal/segment"
"github.com/saucelabs/saucectl/internal/usage"
"github.com/spf13/cobra"
"golang.org/x/text/cases"
"golang.org/x/text/language"
)

func ListCommand() *cobra.Command {
var out string
cmd := &cobra.Command{
Use: "list",
Short: "Returns the list of containers",
SilenceUsage: true,
PreRunE: func(cmd *cobra.Command, args []string) error {
err := http.CheckProxy()
if err != nil {
return fmt.Errorf("invalid HTTP_PROXY value")
}

tracker := segment.DefaultTracker

go func() {
tracker.Collect(
cases.Title(language.English).String(cmds.FullName(cmd)),
usage.Properties{}.SetFlags(cmd.Flags()),
)
_ = tracker.Close()
}()
return nil
},
RunE: func(cmd *cobra.Command, args []string) error {
return list(out)
},
}
flags := cmd.PersistentFlags()
flags.StringVarP(&out, "out", "o", "text", "Output format to the console. Options: text, json.")

return cmd
}

func list(outputFormat string) error {
containers, err := imagerunnerClient.ListContainers(context.Background())
if err != nil {
return fmt.Errorf("failed to get container list: %v", err)
}

switch outputFormat {
case "json":
if err := renderJSON(containers); err != nil {
return fmt.Errorf("failed to render output: %v", err)
}
case "text":
renderContainersTable(containers)
default:
return errors.New("unknown output format")
}
return nil
}

func renderContainersTable(containers http.ContainersResp) {
if len(containers.Items) == 0 {
println("Cannot find any containers")
return
}
t := table.NewWriter()
t.SetStyle(defaultTableStyle)
t.SuppressEmptyColumns()
t.AppendHeader(table.Row{
"ID", "Image", "Status", "CreationTime", "TerminationTime",
})

for _, c := range containers.Items {
// the order of values must match the order of the header
t.AppendRow(table.Row{
c.ID,
c.Image,
c.Status,
time.Unix(c.CreationTime, 0).Format(time.RFC3339),
time.Unix(c.TerminationTime, 0).Format(time.RFC3339),
})
}
println(t.Render())
}
32 changes: 32 additions & 0 deletions internal/http/imagerunner.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ type AuthToken struct {
Password string `json:"password"`
}

type ContainersResp struct {
Items []imagerunner.Runner `json:"content"`
}

func NewImageRunner(url string, creds iam.Credentials, timeout time.Duration,
asyncEventManager imagerunner.AsyncEventManagerI) ImageRunner {
eventLogger := zerolog.New(zerolog.ConsoleWriter{
Expand Down Expand Up @@ -486,3 +490,31 @@ func (c *ImageRunner) RegistryLogin(ctx context.Context, repo string) (AuthToken
err = json.Unmarshal(data, &authToken)
return authToken, err
}

func (c *ImageRunner) ListContainers(ctx context.Context) (ContainersResp, error) {
url := fmt.Sprintf("%s/v1alpha1/hosted/image/runners", c.URL)

var containers ContainersResp
req, err := NewRetryableRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
return containers, err
}
req.SetBasicAuth(c.Creds.Username, c.Creds.AccessKey)

resp, err := c.Client.Do(req)
if err != nil {
return containers, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
b, _ := io.ReadAll(resp.Body)
return containers, fmt.Errorf("unexpected server response (%d): %s", resp.StatusCode, b)
}

if err = json.NewDecoder(resp.Body).Decode(&containers); err != nil {
return containers, fmt.Errorf("failed to decode server response: %v", err)
}

return containers, nil
}

0 comments on commit 7a31066

Please sign in to comment.