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

Commit 7d89f9e

Browse files
author
Faris Huskovic
committed
Change coder create | edit envs image flag to take image name and use defaults from image
1 parent 6f8b9b8 commit 7d89f9e

File tree

5 files changed

+258
-70
lines changed

5 files changed

+258
-70
lines changed

ci/integration/envs_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func TestEnvsCLI(t *testing.T) {
4949
// Invalid environment name should fail.
5050
c.Run(ctx, "coder envs create --image "+ubuntuImgID+" this-IS-an-invalid-EnvironmentName").Assert(t,
5151
tcli.Error(),
52-
tcli.StderrMatches(regexp.QuoteMeta("environment name must conform to regex ^[a-z0-9]([a-z0-9-]+)?")),
52+
tcli.StderrMatches(regexp.QuoteMeta("fatal: image not found - did you forget to import this image?\n\n")),
5353
)
5454

5555
// TODO(Faris) : uncomment this when we can safely purge the environments
@@ -63,7 +63,7 @@ func TestEnvsCLI(t *testing.T) {
6363
// Image does not exist should fail.
6464
c.Run(ctx, "coder envs create --image does-not-exist env-will-not-be-created").Assert(t,
6565
tcli.Error(),
66-
tcli.StderrMatches(regexp.QuoteMeta("does not exist")),
66+
tcli.StderrMatches(regexp.QuoteMeta("fatal: image not found - did you forget to import this image?\n\n")),
6767
)
6868
})
6969
}

coder-sdk/image.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ type Image struct {
1313
Description string `json:"description"`
1414
URL string `json:"url"` // User-supplied URL for image.
1515
DefaultCPUCores float32 `json:"default_cpu_cores"`
16-
DefaultMemoryGB int `json:"default_memory_gb"`
16+
DefaultMemoryGB float32 `json:"default_memory_gb"`
1717
DefaultDiskGB int `json:"default_disk_gb"`
1818
Deprecated bool `json:"deprecated"`
1919
}
@@ -47,3 +47,13 @@ func (c Client) ImportImage(ctx context.Context, orgID string, req ImportImageRe
4747
}
4848
return &img, nil
4949
}
50+
51+
// GetOrganizationImages returns all of the images imported for org.
52+
func (c Client) GetOrganizationImages(ctx context.Context, org string) ([]*Image, error) {
53+
var imgs []*Image
54+
55+
if err := c.requestBody(ctx, http.MethodGet, "/api/orgs/"+org+"/images", nil, &imgs); err != nil {
56+
return nil, err
57+
}
58+
return imgs, nil
59+
}

internal/cmd/ceapi.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cmd
33
import (
44
"context"
55
"fmt"
6+
"strings"
67

78
"cdr.dev/coder-cli/coder-sdk"
89
"cdr.dev/coder-cli/internal/clog"
@@ -81,3 +82,94 @@ func findEnv(ctx context.Context, client *coder.Client, envName, userEmail strin
8182
clog.Tipf("run \"coder envs ls\" to view your environments"),
8283
)
8384
}
85+
86+
func findImg(ctx context.Context, client *coder.Client, email, imgName string) (*coder.Image, error) {
87+
userImgs, err := lookupUserImgs(ctx, client, email, imgName)
88+
if err != nil {
89+
return nil, err
90+
}
91+
92+
numImgs := len(userImgs)
93+
94+
if numImgs == 0 {
95+
return nil, xerrors.New("image not found - did you forget to import this image?")
96+
}
97+
98+
if numImgs > 1 {
99+
var lines []string
100+
101+
for _, img := range userImgs {
102+
lines = append(lines, img.Repository)
103+
}
104+
105+
clog.LogInfo(
106+
fmt.Sprintf("Found %d possible matches for %q.", numImgs, imgName),
107+
clog.Tipf("Did you mean?\n\t%s", strings.Join(lines, "\n\t")),
108+
)
109+
110+
return nil, xerrors.New("please refine your search")
111+
}
112+
return userImgs[0], nil
113+
}
114+
115+
func getImgs(ctx context.Context, client *coder.Client, userEmail string) ([]*coder.Image, error) {
116+
u, err := client.UserByEmail(ctx, userEmail)
117+
if err != nil {
118+
return nil, err
119+
}
120+
121+
orgs, err := client.Organizations(ctx)
122+
if err != nil {
123+
return nil, err
124+
}
125+
126+
orgs = lookupUserOrgs(u, orgs)
127+
var importedImgs []*coder.Image
128+
129+
// Get all of the imported images for all of the orgs the user belongs to.
130+
for _, org := range orgs {
131+
imgs, err := client.GetOrganizationImages(ctx, org.ID)
132+
if err != nil {
133+
return nil, err
134+
}
135+
importedImgs = append(importedImgs, imgs...)
136+
}
137+
return importedImgs, nil
138+
}
139+
140+
// returns all images that contain imgName as a substring and have been imported by the user.
141+
func lookupUserImgs(ctx context.Context, client *coder.Client, email, imgName string) ([]*coder.Image, error) {
142+
switch {
143+
case client == nil:
144+
return nil, xerrors.New("nil client")
145+
case email == "":
146+
return nil, xerrors.New("user email unset")
147+
case imgName == "":
148+
return nil, xerrors.New("image name unset")
149+
}
150+
151+
// Get all imported images for each org the user belongs to.
152+
imgs, err := getImgs(ctx, client, email)
153+
if err != nil {
154+
return nil, err
155+
}
156+
157+
var userImgs []*coder.Image
158+
159+
// The user may provide an image thats not an exact match
160+
// to one of their imported images but they may be close.
161+
// We can assist the user by collecting images that contain
162+
// the user provided image flag value as a substring.
163+
for _, img := range imgs {
164+
if strings.Contains(img.Repository, imgName) {
165+
userImgs = append(userImgs, img)
166+
}
167+
// If it's an exact match we can overwrite the slice and exit the loop
168+
// since we won't need the fuzzy matched images anymore.
169+
if img.Repository == imgName {
170+
userImgs = []*coder.Image{img}
171+
break
172+
}
173+
}
174+
return userImgs, nil
175+
}

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