Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings
This repository was archived by the owner on Aug 30, 2024. It is now read-only.
/coder-v1-cliPublic archive

Add new image tags commands#181

Merged
cmoog merged 6 commits intomasterfromtags-cmd
Nov 8, 2020
Merged
Show file tree
Hide file tree
Changes fromall 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
36 changes: 36 additions & 0 deletionsci/integration/tags_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
package integration

import (
"context"
"testing"

"cdr.dev/coder-cli/coder-sdk"
"cdr.dev/coder-cli/pkg/tcli"
"cdr.dev/slog/sloggers/slogtest/assert"
)

func TestTags(t *testing.T) {
t.Parallel()
t.Skip("wait for dedicated test cluster so we can create an org")
run(t, "tags-cli-tests", func(t *testing.T, ctx context.Context, c *tcli.ContainerRunner) {
headlessLogin(ctx, t, c)
client := cleanupClient(ctx, t)

ensureImageImported(ctx, t, client, "ubuntu")

c.Run(ctx, "coder tags ls").Assert(t,
tcli.Error(),
)
c.Run(ctx, "coder tags ls --image ubuntu --org default").Assert(t,
tcli.Success(),
)
var tags []coder.ImageTag
c.Run(ctx, "coder tags ls --image ubuntu --org default --output json").Assert(t,
tcli.Success(),
tcli.StdoutJSONUnmarshal(&tags),
)
assert.True(t, "> 0 tags", len(tags) > 0)

// TODO(@cmoog) add create and rm integration tests
})
}
68 changes: 68 additions & 0 deletionscoder-sdk/tags.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
package coder

import (
"context"
"net/http"
"time"
)

// ImageTag is a Docker image tag.
type ImageTag struct {
ImageID string `json:"image_id" table:"-"`
Tag string `json:"tag" table:"Tag"`
LatestHash string `json:"latest_hash" table:"-"`
HashLastUpdatedAt time.Time `json:"hash_last_updated_at" table:"-"`
OSRelease *OSRelease `json:"os_release" table:"OS"`
Environments []*Environment `json:"environments" table:"-"`
UpdatedAt time.Time `json:"updated_at" table:"UpdatedAt"`
CreatedAt time.Time `json:"created_at" table:"-"`
}

// OSRelease is the marshalled /etc/os-release file.
type OSRelease struct {
ID string `json:"id"`
PrettyName string `json:"pretty_name"`
HomeURL string `json:"home_url"`
}

func (o OSRelease) String() string {
return o.PrettyName
}

// CreateImageTagReq defines the request parameters for creating a new image tag.
type CreateImageTagReq struct {
Tag string `json:"tag"`
Default bool `json:"default"`
}

// CreateImageTag creates a new image tag resource.
func (c Client) CreateImageTag(ctx context.Context, imageID string, req CreateImageTagReq) (*ImageTag, error) {
var tag ImageTag
if err := c.requestBody(ctx, http.MethodPost, "/api/images/"+imageID+"/tags", req, tag); err != nil {
return nil, err
}
return &tag, nil
}

// DeleteImageTag deletes an image tag resource.
func (c Client) DeleteImageTag(ctx context.Context, imageID, tag string) error {
return c.requestBody(ctx, http.MethodDelete, "/api/images/"+imageID+"/tags/"+tag, nil, nil)
}

// ImageTags fetch all image tags.
func (c Client) ImageTags(ctx context.Context, imageID string) ([]ImageTag, error) {
var tags []ImageTag
if err := c.requestBody(ctx, http.MethodGet, "/api/images/"+imageID+"/tags", nil, &tags); err != nil {
return nil, err
}
return tags, nil
}

// ImageTagByID fetch an image tag by ID.
func (c Client) ImageTagByID(ctx context.Context, imageID, tagID string) (*ImageTag, error) {
var tag ImageTag
if err := c.requestBody(ctx, http.MethodGet, "/api/images/"+imageID+"/tags/"+tagID, nil, &tag); err != nil {
return nil, err
}
return &tag, nil
}
1 change: 1 addition & 0 deletionsinternal/cmd/cmd.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -26,6 +26,7 @@ func Make() *cobra.Command {
logoutCmd(),
shCmd(),
usersCmd(),
tagsCmd(),
configSSHCmd(),
secretsCmd(),
envsCmd(),
Expand Down
172 changes: 172 additions & 0 deletionsinternal/cmd/tags.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
package cmd

import (
"encoding/json"
"os"

"cdr.dev/coder-cli/coder-sdk"
"cdr.dev/coder-cli/pkg/clog"
"cdr.dev/coder-cli/pkg/tablewriter"
"github.com/spf13/cobra"
"golang.org/x/xerrors"
)

func tagsCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "tags",
Hidden: true,
Short: "operate on Coder image tags",
}

cmd.AddCommand(
tagsLsCmd(),
tagsCreateCmd(),
tagsRmCmd(),
)
return cmd
}

func tagsCreateCmd() *cobra.Command {
var (
orgName string
imageName string
defaultTag bool
)
cmd := &cobra.Command{
Use: "create [tag]",
Short: "add an image tag",
Long: "allow users to create environments with this image tag",
Example: `coder tags create latest --image ubuntu --org default`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
client, err := newClient(ctx)
if err != nil {
return err
}
img, err := findImg(ctx, client, findImgConf{
orgName: orgName,
imgName: imageName,
email: coder.Me,
})
if err != nil {
return xerrors.Errorf("find image: %w", err)
}

_, err = client.CreateImageTag(ctx, img.ID, coder.CreateImageTagReq{
Tag: args[0],
Default: defaultTag,
})
if err != nil {
return xerrors.Errorf("create image tag: %w", err)
}
clog.LogSuccess("created new tag")

return nil
},
}

cmd.Flags().StringVarP(&imageName, "image", "i", "", "image name")
cmd.Flags().StringVarP(&orgName, "org", "o", "", "organization name")
cmd.Flags().BoolVar(&defaultTag, "default", false, "make this tag the default for its image")
_ = cmd.MarkFlagRequired("org")
_ = cmd.MarkFlagRequired("image")
return cmd
}

func tagsLsCmd() *cobra.Command {
var (
orgName string
imageName string
outputFmt string
)
cmd := &cobra.Command{
Use: "ls",
Example: `coder tags ls --image ubuntu --org default --output json`,
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
client, err := newClient(ctx)
if err != nil {
return err
}

img, err := findImg(ctx, client, findImgConf{
email: coder.Me,
orgName: orgName,
imgName: imageName,
})
if err != nil {
return err
}

tags, err := client.ImageTags(ctx, img.ID)
if err != nil {
return err
}

switch outputFmt {
case humanOutput:
err = tablewriter.WriteTable(len(tags), func(i int) interface{} { return tags[i] })
if err != nil {
return err
}
case jsonOutput:
err := json.NewEncoder(os.Stdout).Encode(tags)
if err != nil {
return err
}
default:
return clog.Error("unknown --output value")
}

return nil
},
}
cmd.Flags().StringVar(&orgName, "org", "", "organization by name")
cmd.Flags().StringVarP(&imageName, "image", "i", "", "image by name")
cmd.Flags().StringVar(&outputFmt, "output", humanOutput, "output format (human|json)")
_ = cmd.MarkFlagRequired("image")
_ = cmd.MarkFlagRequired("org")
return cmd
}

func tagsRmCmd() *cobra.Command {
var (
imageName string
orgName string
)
cmd := &cobra.Command{
Use: "rm [tag]",
Short: "remove an image tag",
Example: `coder tags rm latest --image ubuntu --org default`,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
ctx := cmd.Context()
client, err := newClient(ctx)
if err != nil {
return err
}

img, err := findImg(ctx, client, findImgConf{
email: coder.Me,
imgName: imageName,
orgName: orgName,
})
if err != nil {
return err
}

if err = client.DeleteImageTag(ctx, img.ID, args[0]); err != nil {
return err
}
clog.LogSuccess("removed tag")

return nil
},
}
cmd.Flags().StringVarP(&orgName, "org", "o", "", "organization by name")
cmd.Flags().StringVarP(&imageName, "image", "i", "", "image by name")
_ = cmd.MarkFlagRequired("image")
_ = cmd.MarkFlagRequired("org")
return cmd
}

[8]ページ先頭

©2009-2025 Movatter.jp