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

Commit ea7e23a

Browse files
author
Russtopia
committed
Add custom prefix devurl
1 parent 65fce15 commit ea7e23a

File tree

6 files changed

+118
-52
lines changed

6 files changed

+118
-52
lines changed

cmd/coder/envs.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ type envsCmd struct {
1414
func (cmd envsCmd) Spec() cli.CommandSpec {
1515
return cli.CommandSpec{
1616
Name: "envs",
17-
Desc: "get a list of active environment",
17+
Desc: "get a list of active environments",
1818
}
1919
}
2020

cmd/coder/sync.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func (cmd *syncCmd) RegisterFlags(fl *pflag.FlagSet) {
3434
}
3535

3636
// version returns local rsync protocol version as a string.
37-
func (_ *syncCmd) version() string {
37+
func (*syncCmd) version() string {
3838
cmd := exec.Command("rsync", "--version")
3939
out, err := cmd.CombinedOutput()
4040
if err != nil {
@@ -99,7 +99,7 @@ func (cmd *syncCmd) Run(fl *pflag.FlagSet) {
9999
if rsyncErr != nil {
100100
flog.Info("Unable to determine remote rsync version. Proceeding cautiously.")
101101
} else if localVersion != remoteVersion {
102-
flog.Fatal(fmt.Sprintf("rsync protocol mismatch. %s.", localVersion, rsyncErr))
102+
flog.Fatal(fmt.Sprintf("rsync protocol mismatch. %s (%v).", localVersion, rsyncErr))
103103
}
104104

105105
for err == nil || err == sync.ErrRestartSync {

cmd/coder/urls.go

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ package main
33
import (
44
"encoding/json"
55
"fmt"
6+
"math"
67
"net/http"
78
"os"
9+
"regexp"
810
"strconv"
911
"strings"
1012
"text/tabwriter"
@@ -21,7 +23,7 @@ type urlsCmd struct{}
2123
type DevURL struct {
2224
ID string `json:"id"`
2325
URL string `json:"url"`
24-
Port string `json:"port"`
26+
Port int `json:"port"`
2527
Access string `json:"access"`
2628
}
2729

@@ -33,55 +35,66 @@ var urlAccessLevel = map[string]string{
3335
"PUBLIC": "Anyone on the internet can access this link",
3436
}
3537

36-
func portIsValid(port string) bool {
38+
func validatePort(port string) (int, error) {
3739
p, err := strconv.ParseUint(port, 10, 16)
38-
if p < 1 {
40+
if p < 1 || p > math.MaxUint16 {
3941
// port 0 means 'any free port', which we don't support
4042
err = strconv.ErrRange
4143
}
4244
if err != nil {
43-
fmt.Println("Invalid port")
45+
flog.Error("Invalid port")
46+
return 0, err
4447
}
45-
return err == nil
48+
return int(p), nil
4649
}
4750

4851
func accessLevelIsValid(level string) bool {
4952
_, ok := urlAccessLevel[level]
5053
if !ok {
51-
fmt.Println("Invalid access level")
54+
flog.Error("Invalid access level")
5255
}
5356
return ok
5457
}
5558

5659
type createSubCmd struct {
57-
access string
60+
access string
61+
urlname string
5862
}
5963

6064
func (sub *createSubCmd) RegisterFlags(fl *pflag.FlagSet) {
6165
fl.StringVarP(&sub.access, "access", "a", "private", "[private | org | authed | public] set devurl access")
66+
fl.StringVarP(&sub.urlname, "name", "n", "", "devurl name")
6267
}
6368

6469
func (sub createSubCmd) Spec() cli.CommandSpec {
6570
return cli.CommandSpec{
66-
Name: "create",
67-
Usage: "<env name> <port> [--access <level>]",
68-
Desc: "create/update a devurl for external access",
71+
Name: "create",
72+
Usage: "<env name> <port> [--access <level>] [--name <name>]",
73+
Aliases: []string{"edit"},
74+
Desc: "create or update a devurl for external access",
6975
}
7076
}
7177

78+
// devURLNameValidRx is the regex used to validate devurl names specified
79+
// via the --name subcommand. Named devurls must begin with a letter, and
80+
// consist solely of letters and digits, with a max length of 64 chars.
81+
var devURLNameValidRx = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9]{0,63}$")
82+
7283
// Run creates or updates a devURL, specified by env ID and port
7384
// (fl.Arg(0) and fl.Arg(1)), with access level (fl.Arg(2)) on
7485
// the cemanager.
7586
func (sub createSubCmd) Run(fl *pflag.FlagSet) {
7687
envName := fl.Arg(0)
7788
port := fl.Arg(1)
78-
access := fl.Arg(2)
89+
name := fl.Arg(2)
90+
access := fl.Arg(3)
7991

8092
if envName == "" {
8193
exitUsage(fl)
8294
}
8395

84-
if !portIsValid(port) {
96+
portNum, err := validatePort(port)
97+
if err != nil {
8598
exitUsage(fl)
8699
}
87100

@@ -90,20 +103,28 @@ func (sub createSubCmd) Run(fl *pflag.FlagSet) {
90103
exitUsage(fl)
91104
}
92105

106+
name = sub.urlname
107+
if name != "" && !devURLNameValidRx.MatchString(name) {
108+
flog.Error("update devurl: name must be < 64 chars in length, begin with a letter and only contain letters or digits.")
109+
return
110+
}
93111
entClient := requireAuth()
94112

95113
env := findEnv(entClient, envName)
96114

97-
_, found := devURLID(port, urlList(envName))
115+
found, urlID := devURLID(portNum, urlList(envName))
98116
if found {
99-
fmt.Printf("Updating devurl for port %v\n", port)
117+
flog.Info("Updating devurl for port %v", port)
118+
err := entClient.UpdateDevURL(env.ID, urlID, portNum, name, access)
119+
if err != nil {
120+
flog.Error("update devurl: %s", err.Error())
121+
}
100122
} else {
101-
fmt.Printf("Adding devurl for port %v\n", port)
102-
}
103-
104-
err := entClient.UpsertDevURL(env.ID, port, access)
105-
if err != nil {
106-
flog.Error("upsert devurl: %s", err.Error())
123+
flog.Info("Adding devurl for port %v", port)
124+
err := entClient.InsertDevURL(env.ID, portNum, name, access)
125+
if err != nil {
126+
flog.Error("insert devurl: %s", err.Error())
127+
}
107128
}
108129
}
109130

@@ -117,15 +138,16 @@ func (sub delSubCmd) Spec() cli.CommandSpec {
117138
}
118139
}
119140

120-
// devURLID returns the ID of a devURL, given the env name and port.
121-
// ("", false) is returned if no match is found.
122-
func devURLID(port string, urls []DevURL) (string, bool) {
141+
// devURLID returns the ID of a devURL, given the env name and port
142+
// from a list of DevURL records.
143+
// (false, "") is returned if no match is found.
144+
func devURLID(port int, urls []DevURL) (bool, string) {
123145
for _, url := range urls {
124146
if url.Port == port {
125-
return url.ID, true
147+
return true, url.ID
126148
}
127149
}
128-
return "", false
150+
return false, ""
129151
}
130152

131153
// Run deletes a devURL, specified by env ID and port, from the cemanager.
@@ -137,22 +159,22 @@ func (sub delSubCmd) Run(fl *pflag.FlagSet) {
137159
exitUsage(fl)
138160
}
139161

140-
if !portIsValid(port) {
162+
portNum, err := validatePort(port)
163+
if err != nil {
141164
exitUsage(fl)
142165
}
143166

144167
entClient := requireAuth()
145-
146168
env := findEnv(entClient, envName)
147169

148-
urlID, found := devURLID(port, urlList(envName))
170+
found, urlID := devURLID(portNum, urlList(envName))
149171
if found {
150-
fmt.Printf("Deleting devurl for port %v\n", port)
172+
flog.Info("Deleting devurl for port %v", port)
151173
} else {
152174
flog.Fatal("No devurl found for port %v", port)
153175
}
154176

155-
err := entClient.DelDevURL(env.ID, urlID)
177+
err = entClient.DelDevURL(env.ID, urlID)
156178
if err != nil {
157179
flog.Error("delete devurl: %s", err.Error())
158180
}
@@ -192,10 +214,6 @@ func urlList(envName string) []DevURL {
192214
flog.Fatal("%v", err)
193215
}
194216

195-
if len(devURLs) == 0 {
196-
fmt.Printf("no dev urls were found for environment: %s\n", envName)
197-
}
198-
199217
return devURLs
200218
}
201219

@@ -207,7 +225,7 @@ func (cmd urlsCmd) Run(fl *pflag.FlagSet) {
207225

208226
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.TabIndent)
209227
for _, devURL := range devURLs {
210-
fmt.Fprintf(w, "%s\t%s\t%s\n", devURL.URL, devURL.Port, devURL.Access)
228+
fmt.Fprintf(w, "%s\t%d\t%s\n", devURL.URL, devURL.Port, devURL.Access)
211229
}
212230
w.Flush()
213231
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ require (
1212
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4
1313
github.com/rjeczalik/notify v0.9.2
1414
github.com/spf13/pflag v1.0.5
15-
go.coder.com/cli v0.4.0
15+
go.coder.com/cli v0.5.0
1616
go.coder.com/flog v0.0.0-20190906214207-47dd47ea0512
1717
golang.org/x/crypto v0.0.0-20200422194213-44a606286825
1818
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a

go.sum

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
163163
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
164164
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
165165
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
166+
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
167+
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
166168
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
167169
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
168170
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
@@ -171,6 +173,8 @@ github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyC
171173
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
172174
go.coder.com/cli v0.4.0 h1:PruDGwm/CPFndyK/eMowZG3vzg5CgohRWeXWCTr3zi8=
173175
go.coder.com/cli v0.4.0/go.mod h1:hRTOURCR3LJF1FRW9arecgrzX+AHG7mfYMwThPIgq+w=
176+
go.coder.com/cli v0.5.0 h1:7W9ECtZdVKaAc0Oe2uk5J/c0LCtsWufQz4NeX6YwP0g=
177+
go.coder.com/cli v0.5.0/go.mod h1:h6091Eox0VdgJw2CDBvTyx7SnhduTm8qYM2bR2pewls=
174178
go.coder.com/flog v0.0.0-20190906214207-47dd47ea0512 h1:DjCS6dRQh+1PlfiBmnabxfdrzenb0tAwJqFxDEH/s9g=
175179
go.coder.com/flog v0.0.0-20190906214207-47dd47ea0512/go.mod h1:83JsYgXYv0EOaXjIMnaZ1Fl6ddNB3fJnDZ/8845mUJ8=
176180
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
@@ -300,6 +304,8 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
300304
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
301305
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
302306
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
307+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
308+
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
303309
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
304310
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
305311
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

internal/entclient/devurl.go

Lines changed: 55 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,23 @@ package entclient
33
import (
44
"fmt"
55
"net/http"
6+
7+
"golang.org/x/xerrors"
68
)
79

10+
type delDevURLRequest struct {
11+
EnvID string `json:"environment_id"`
12+
DevURLID string `json:"url_id"`
13+
}
14+
15+
// DelDevURL deletes a devurl from the specified environment.
816
func (c Client) DelDevURL(envID, urlID string) error {
917
reqString := "/api/environments/%s/devurls/%s"
10-
reqUrl := fmt.Sprintf(reqString, envID, urlID)
18+
reqURL := fmt.Sprintf(reqString, envID, urlID)
1119

12-
res, err := c.request("DELETE", reqUrl, map[string]string{
13-
"environment_id": envID,
14-
"url_id": urlID,
20+
res, err := c.request("DELETE", reqURL, delDevURLRequest{
21+
EnvID: envID,
22+
DevURLID: urlID,
1523
})
1624
if err != nil {
1725
return err
@@ -24,22 +32,56 @@ func (c Client) DelDevURL(envID, urlID string) error {
2432
return nil
2533
}
2634

27-
func (c Client) UpsertDevURL(envID, port, access string) error {
35+
type createDevURLRequest struct {
36+
EnvID string `json:"environment_id"`
37+
Port int `json:"port"`
38+
Access string `json:"access"`
39+
Name string `json:"name"`
40+
}
41+
42+
// InsertDevURL inserts a new devurl into the specified environment.
43+
func (c Client) InsertDevURL(envID string, port int, name, access string) error {
2844
reqString := "/api/environments/%s/devurls"
29-
reqUrl := fmt.Sprintf(reqString, envID)
45+
reqURL := fmt.Sprintf(reqString, envID)
3046

31-
res, err := c.request("POST", reqUrl, map[string]string{
32-
"environment_id": envID,
33-
"port": port,
34-
"access": access,
47+
res, err := c.request("POST", reqURL, createDevURLRequest{
48+
EnvID: envID,
49+
Port: port,
50+
Access: access,
51+
Name: name,
3552
})
53+
if res != nil && res.StatusCode == http.StatusConflict {
54+
return xerrors.Errorf("Failed to create devurl. Check that the port and name are unique.")
55+
}
3656
if err != nil {
3757
return err
3858
}
59+
return nil
60+
}
3961

40-
if res.StatusCode != http.StatusOK {
41-
return bodyError(res)
42-
}
62+
type updateDevURLRequest struct {
63+
EnvID string `json:"environment_id"`
64+
Port int `json:"port"`
65+
Access string `json:"access"`
66+
Name string `json:"name"`
67+
}
4368

69+
// UpdateDevURL updates an existing devurl in the specified environment.
70+
func (c Client) UpdateDevURL(envID, urlID string, port int, name, access string) error {
71+
reqString := "/api/environments/%s/devurls/%s"
72+
reqURL := fmt.Sprintf(reqString, envID, urlID)
73+
74+
res, err := c.request("PUT", reqURL, updateDevURLRequest{
75+
EnvID: envID,
76+
Port: port,
77+
Access: access,
78+
Name: name,
79+
})
80+
if res != nil && res.StatusCode == http.StatusConflict {
81+
return xerrors.Errorf("Failed to update devurl. Check that the port and name are unique.")
82+
}
83+
if err != nil {
84+
return err
85+
}
4486
return nil
4587
}

0 commit comments

Comments
 (0)