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

Commit1a85240

Browse files
authored
feat: split parsing config from creating env (#234)
- Add an endpoint to parse a WAC template.- Add support for specifying a local file.- Decoupled creating an environment from parsing a template (in the API).
1 parent0da2ebf commit1a85240

File tree

4 files changed

+176
-57
lines changed

4 files changed

+176
-57
lines changed

‎coder-sdk/env.go

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package coder
22

33
import (
44
"context"
5+
"io"
56
"net/http"
67
"net/url"
78
"time"
@@ -73,17 +74,16 @@ const (
7374

7475
// CreateEnvironmentRequest is used to configure a new environment.
7576
typeCreateEnvironmentRequeststruct {
76-
Namestring`json:"name"`
77-
ImageIDstring`json:"image_id"`
78-
OrgIDstring`json:"org_id"`
79-
ImageTagstring`json:"image_tag"`
80-
CPUCoresfloat32`json:"cpu_cores"`
81-
MemoryGBfloat32`json:"memory_gb"`
82-
DiskGBint`json:"disk_gb"`
83-
GPUsint`json:"gpus"`
84-
Services []string`json:"services"`
85-
UseContainerVMbool`json:"use_container_vm"`
86-
Template*Template`json:"template"`
77+
Namestring`json:"name"`
78+
ImageIDstring`json:"image_id"`
79+
OrgIDstring`json:"org_id"`
80+
ImageTagstring`json:"image_tag"`
81+
CPUCoresfloat32`json:"cpu_cores"`
82+
MemoryGBfloat32`json:"memory_gb"`
83+
DiskGBint`json:"disk_gb"`
84+
GPUsint`json:"gpus"`
85+
Services []string`json:"services"`
86+
UseContainerVMbool`json:"use_container_vm"`
8787
}
8888

8989
// CreateEnvironment sends a request to create an environment.
@@ -95,14 +95,60 @@ func (c Client) CreateEnvironment(ctx context.Context, req CreateEnvironmentRequ
9595
return&env,nil
9696
}
9797

98-
// Template is used to configure a new environment from a repo.
99-
// It is currently in alpha and subject to API-breaking change.
98+
// ParseTemplateRequest parses a template. If Local is a non-nil reader
99+
// it will obviate any other fields on the request.
100+
typeParseTemplateRequeststruct {
101+
RepoURLstring`json:"repo_url"`
102+
Refstring`json:"ref"`
103+
Local io.Reader`json:"-"`
104+
}
105+
106+
// Template is a Workspaces As Code (WAC) template.
100107
typeTemplatestruct {
101-
RepositoryURLstring`json:"repository_url"`
102-
// Optional. The default branch will be used if not provided.
103-
Branchstring`json:"branch"`
104-
// Optional. The template name will be used if not provided.
105-
FileNamestring`json:"file_name"`
108+
WorkspaceWorkspace`json:"workspace"`
109+
}
110+
111+
// Workspace defines values on the workspace that can be configured.
112+
typeWorkspacestruct {
113+
Namestring`json:"name"`
114+
Imagestring`json:"image"`
115+
ContainerBasedVMbool`json:"container-based-vm"`
116+
ResourcesResources`json:"resources"`
117+
}
118+
119+
// Resources defines compute values that can be configured for a workspace.
120+
typeResourcesstruct {
121+
CPUfloat32`json:"cpu" `
122+
Memoryfloat32`json:"memory"`
123+
Diskint`json:"disk"`
124+
}
125+
126+
// ParseTemplate parses a template config. It support both remote repositories and local files.
127+
// If a local file is specified then all other values in the request are ignored.
128+
func (cClient)ParseTemplate(ctx context.Context,reqParseTemplateRequest) (Template,error) {
129+
constpath="/api/private/environments/template/parse"
130+
var (
131+
tplTemplate
132+
opts []requestOption
133+
headers= http.Header{}
134+
)
135+
136+
ifreq.Local==nil {
137+
iferr:=c.requestBody(ctx,http.MethodPost,path,req,&tpl);err!=nil {
138+
returntpl,err
139+
}
140+
returntpl,nil
141+
}
142+
143+
headers.Set("Content-Type","application/octet-stream")
144+
opts=append(opts,withBody(req.Local),withHeaders(headers))
145+
146+
err:=c.requestBody(ctx,http.MethodPost,path,nil,&tpl,opts...)
147+
iferr!=nil {
148+
returntpl,err
149+
}
150+
151+
returntpl,nil
106152
}
107153

108154
// CreateEnvironmentFromRepo sends a request to create an environment from a repository.

‎coder-sdk/request.go

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,45 @@ import (
77
"fmt"
88
"io"
99
"net/http"
10+
"net/url"
1011

1112
"golang.org/x/xerrors"
1213
)
1314

15+
typerequestOptionsstruct {
16+
BaseURLOverride*url.URL
17+
Query url.Values
18+
Headers http.Header
19+
Reader io.Reader
20+
}
21+
22+
typerequestOptionfunc(*requestOptions)
23+
24+
// withQueryParams sets the provided query parameters on the request.
25+
funcwithQueryParams(q url.Values)func(o*requestOptions) {
26+
returnfunc(o*requestOptions) {
27+
o.Query=q
28+
}
29+
}
30+
31+
funcwithHeaders(h http.Header)func(o*requestOptions) {
32+
returnfunc(o*requestOptions) {
33+
o.Headers=h
34+
}
35+
}
36+
37+
funcwithBaseURL(base*url.URL)func(o*requestOptions) {
38+
returnfunc(o*requestOptions) {
39+
o.BaseURLOverride=base
40+
}
41+
}
42+
43+
funcwithBody(w io.Reader)func(o*requestOptions) {
44+
returnfunc(o*requestOptions) {
45+
o.Reader=w
46+
}
47+
}
48+
1449
// request is a helper to set the cookie, marshal the payload and execute the request.
1550
func (cClient)request(ctx context.Context,method,pathstring,ininterface{},options...requestOption) (*http.Response,error) {
1651
// Create a default http client with the auth in the cookie.
@@ -30,7 +65,6 @@ func (c Client) request(ctx context.Context, method, path string, in interface{}
3065
ifconfig.Query!=nil {
3166
url.RawQuery=config.Query.Encode()
3267
}
33-
3468
url.Path=path
3569

3670
// If we have incoming data, encode it as json.
@@ -43,12 +77,20 @@ func (c Client) request(ctx context.Context, method, path string, in interface{}
4377
payload=bytes.NewReader(body)
4478
}
4579

80+
ifconfig.Reader!=nil {
81+
payload=config.Reader
82+
}
83+
4684
// Create the http request.
4785
req,err:=http.NewRequestWithContext(ctx,method,url.String(),payload)
4886
iferr!=nil {
4987
returnnil,xerrors.Errorf("create request: %w",err)
5088
}
5189

90+
ifconfig.Headers!=nil {
91+
req.Header=config.Headers
92+
}
93+
5294
// Execute the request.
5395
returnclient.Do(req)
5496
}

‎coder-sdk/ws.go

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,31 +3,10 @@ package coder
33
import (
44
"context"
55
"net/http"
6-
"net/url"
76

87
"nhooyr.io/websocket"
98
)
109

11-
typerequestOptionsstruct {
12-
BaseURLOverride*url.URL
13-
Query url.Values
14-
}
15-
16-
typerequestOptionfunc(*requestOptions)
17-
18-
// withQueryParams sets the provided query parameters on the request.
19-
funcwithQueryParams(q url.Values)func(o*requestOptions) {
20-
returnfunc(o*requestOptions) {
21-
o.Query=q
22-
}
23-
}
24-
25-
funcwithBaseURL(base*url.URL)func(o*requestOptions) {
26-
returnfunc(o*requestOptions) {
27-
o.BaseURLOverride=base
28-
}
29-
}
30-
3110
// dialWebsocket establish the websocket connection while setting the authentication header.
3211
func (cClient)dialWebsocket(ctx context.Context,pathstring,options...requestOption) (*websocket.Conn,error) {
3312
// Make a copy of the url so we can update the scheme to ws(s) without mutating the state.

‎internal/cmd/envs.go

Lines changed: 69 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
package cmd
22

33
import (
4+
"bytes"
45
"context"
56
"encoding/json"
67
"fmt"
8+
"io"
9+
"io/ioutil"
10+
"net/url"
711
"os"
812

913
"cdr.dev/coder-cli/coder-sdk"
@@ -254,20 +258,21 @@ coder envs create my-new-powerful-env --cpu 12 --disk 100 --memory 16 --image ub
254258

255259
funccreateEnvFromRepoCmd()*cobra.Command {
256260
var (
257-
branchstring
258-
namestring
259-
followbool
261+
refstring
262+
repostring
263+
followbool
264+
filepathstring
265+
orgstring
260266
)
261267

262268
cmd:=&cobra.Command{
263-
Use:"create-from-repo [environment_name]",
264-
Short:"create a new environment from a git repository.",
265-
Args:xcobra.ExactArgs(1),
266-
Long:"Create a new Coder environment from a Git repository.",
269+
Use:"create-from-config",
270+
Short:"create a new environment from a config file.",
271+
Long:"Create a new Coder environment from a config file.",
267272
Hidden:true,
268273
Example:`# create a new environment from git repository template
269-
coder envs create-from-repo github.com/cdr/m
270-
coder envs create-from-repogithub.com/cdr/m --branch envs-as-code`,
274+
coder envs create-from-repo--repo-urlgithub.com/cdr/m --branch my-branch
275+
coder envs create-from-repo-f coder.yaml`,
271276
RunE:func(cmd*cobra.Command,args []string)error {
272277
ctx:=cmd.Context()
273278

@@ -276,15 +281,60 @@ coder envs create-from-repo github.com/cdr/m --branch envs-as-code`,
276281
returnerr
277282
}
278283

279-
// ExactArgs(1) ensures our name value can't panic on an out of bounds.
280-
createReq:=&coder.Template{
281-
RepositoryURL:args[0],
282-
Branch:branch,
283-
FileName:name,
284+
ifrepo!="" {
285+
_,err=url.Parse(repo)
286+
iferr!=nil {
287+
returnxerrors.Errorf("'repo' must be a valid url: %w",err)
288+
}
289+
}
290+
291+
multiOrgMember,err:=isMultiOrgMember(ctx,client,coder.Me)
292+
iferr!=nil {
293+
returnerr
294+
}
295+
296+
ifmultiOrgMember&&org=="" {
297+
returnxerrors.New("org is required for multi-org members")
298+
}
299+
300+
varrd io.Reader
301+
iffilepath!="" {
302+
b,err:=ioutil.ReadFile(filepath)
303+
iferr!=nil {
304+
returnxerrors.Errorf("read local file: %w",err)
305+
}
306+
rd=bytes.NewReader(b)
307+
}
308+
309+
req:= coder.ParseTemplateRequest{
310+
RepoURL:repo,
311+
Ref:ref,
312+
Local:rd,
313+
}
314+
315+
tpl,err:=client.ParseTemplate(ctx,req)
316+
iferr!=nil {
317+
returnxerrors.Errorf("parse environment template config: %w",err)
318+
}
319+
320+
importedImg,err:=findImg(ctx,client,findImgConf{
321+
email:coder.Me,
322+
imgName:tpl.Workspace.Image,
323+
orgName:org,
324+
})
325+
iferr!=nil {
326+
returnerr
284327
}
285328

286329
env,err:=client.CreateEnvironment(ctx, coder.CreateEnvironmentRequest{
287-
Template:createReq,
330+
Name:tpl.Workspace.Name,
331+
ImageID:importedImg.ID,
332+
OrgID:importedImg.OrganizationID,
333+
ImageTag:importedImg.DefaultTag.Tag,
334+
CPUCores:tpl.Workspace.Resources.CPU,
335+
MemoryGB:tpl.Workspace.Resources.Memory,
336+
DiskGB:tpl.Workspace.Resources.Disk,
337+
UseContainerVM:tpl.Workspace.ContainerBasedVM,
288338
})
289339
iferr!=nil {
290340
returnxerrors.Errorf("create environment: %w",err)
@@ -305,8 +355,10 @@ coder envs create-from-repo github.com/cdr/m --branch envs-as-code`,
305355
returnnil
306356
},
307357
}
308-
cmd.Flags().StringVarP(&branch,"branch","b","master","name of the branch to create the environment from.")
309-
cmd.Flags().StringVarP(&name,"name","n","coder.yaml","name of the config file.")
358+
cmd.Flags().StringVarP(&org,"org","o","","name of the organization the environment should be created under.")
359+
cmd.Flags().StringVarP(&filepath,"filepath","f","","path to local template file.")
360+
cmd.Flags().StringVarP(&ref,"ref","","master","git reference to pull template from. May be a branch, tag, or commit hash.")
361+
cmd.Flags().StringVarP(&repo,"repo-url","r","","URL of the git repository to pull the config from. Config file must live in '.coder/coder.yaml'.")
310362
cmd.Flags().BoolVar(&follow,"follow",false,"follow buildlog after initiating rebuild")
311363
returncmd
312364
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp