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

Commit 99468a5

Browse files
author
Russtopia
committed
Add custom prefix devurl
1 parent c8cec8e commit 99468a5

File tree

2 files changed

+96
-38
lines changed

2 files changed

+96
-38
lines changed

cmd/coder/urls.go

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"net/http"
77
"os"
8+
"regexp"
89
"strconv"
910
"strings"
1011
"text/tabwriter"
@@ -21,7 +22,7 @@ type urlsCmd struct{}
2122
type DevURL struct {
2223
ID string `json:"id"`
2324
URL string `json:"url"`
24-
Port string `json:"port"`
25+
Port int `json:"port"`
2526
Access string `json:"access"`
2627
}
2728

@@ -35,47 +36,52 @@ var urlAccessLevel = map[string]string{
3536

3637
func portIsValid(port string) bool {
3738
p, err := strconv.ParseUint(port, 10, 16)
38-
if p < 1 {
39+
if p < 1 || p > 65535 {
3940
// port 0 means 'any free port', which we don't support
4041
err = strconv.ErrRange
4142
}
4243
if err != nil {
43-
fmt.Println("Invalid port")
44+
flog.Error("Invalid port")
4445
}
4546
return err == nil
4647
}
4748

4849
func accessLevelIsValid(level string) bool {
4950
_, ok := urlAccessLevel[level]
5051
if !ok {
51-
fmt.Println("Invalid access level")
52+
flog.Error("Invalid access level")
5253
}
5354
return ok
5455
}
5556

5657
type createSubCmd struct {
57-
access string
58+
access string
59+
urlname string
5860
}
5961

6062
func (sub *createSubCmd) RegisterFlags(fl *pflag.FlagSet) {
6163
fl.StringVarP(&sub.access, "access", "a", "private", "[private | org | authed | public] set devurl access")
64+
fl.StringVarP(&sub.urlname, "name", "n", "", "devurl name")
6265
}
6366

6467
func (sub createSubCmd) Spec() cli.CommandSpec {
6568
return cli.CommandSpec{
6669
Name: "create",
67-
Usage: "<env name> <port> [--access <level>]",
70+
Usage: "<env name> <port> [--access <level>] [--name <name>]",
6871
Desc: "create/update a devurl for external access",
6972
}
7073
}
7174

75+
var devURLNameValidRx = regexp.MustCompile("^[a-zA-Z][a-zA-Z0-9]{0,63}$")
76+
7277
// Run creates or updates a devURL, specified by env ID and port
7378
// (fl.Arg(0) and fl.Arg(1)), with access level (fl.Arg(2)) on
7479
// the cemanager.
7580
func (sub createSubCmd) Run(fl *pflag.FlagSet) {
7681
envName := fl.Arg(0)
7782
port := fl.Arg(1)
78-
access := fl.Arg(2)
83+
name := fl.Arg(2)
84+
access := fl.Arg(3)
7985

8086
if envName == "" {
8187
exitUsage(fl)
@@ -84,26 +90,35 @@ func (sub createSubCmd) Run(fl *pflag.FlagSet) {
8490
if !portIsValid(port) {
8591
exitUsage(fl)
8692
}
93+
portNum, _ := strconv.Atoi(port)
8794

8895
access = strings.ToUpper(sub.access)
8996
if !accessLevelIsValid(access) {
9097
exitUsage(fl)
9198
}
9299

100+
name = sub.urlname
101+
if name != "" && !devURLNameValidRx.MatchString(name) {
102+
flog.Error("update devurl: name must be < 64 chars in length, begin with a letter and only contain letters or digits.")
103+
return
104+
}
93105
entClient := requireAuth()
94106

95107
env := findEnv(entClient, envName)
96108

97-
_, found := devURLID(port, urlList(envName))
109+
found, urlID := devURLID(portNum, urlList(envName))
98110
if found {
99-
fmt.Printf("Updating devurl for port %v\n", port)
111+
flog.Info("Updating devurl for port %v", port)
112+
err := entClient.UpdateDevURL(env.ID, urlID, portNum, name, access)
113+
if err != nil {
114+
flog.Error("update devurl: %s", err.Error())
115+
}
100116
} 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())
117+
flog.Info("Adding devurl for port %v", port)
118+
err := entClient.InsertDevURL(env.ID, portNum, name, access)
119+
if err != nil {
120+
flog.Error("insert devurl: %s", err.Error())
121+
}
107122
}
108123
}
109124

@@ -117,15 +132,16 @@ func (sub delSubCmd) Spec() cli.CommandSpec {
117132
}
118133
}
119134

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) {
135+
// devURLID returns the ID of a devURL, given the env name and port
136+
// from a list of DevURL records.
137+
// (false, "") is returned if no match is found.
138+
func devURLID(port int, urls []DevURL) (bool, string) {
123139
for _, url := range urls {
124140
if url.Port == port {
125-
return url.ID, true
141+
return true, url.ID
126142
}
127143
}
128-
return "", false
144+
return false, ""
129145
}
130146

131147
// Run deletes a devURL, specified by env ID and port, from the cemanager.
@@ -140,14 +156,14 @@ func (sub delSubCmd) Run(fl *pflag.FlagSet) {
140156
if !portIsValid(port) {
141157
exitUsage(fl)
142158
}
159+
portNum, _ := strconv.Atoi(port)
143160

144161
entClient := requireAuth()
145-
146162
env := findEnv(entClient, envName)
147163

148-
urlID, found := devURLID(port, urlList(envName))
164+
found, urlID := devURLID(portNum, urlList(envName))
149165
if found {
150-
fmt.Printf("Deleting devurl for port %v\n", port)
166+
flog.Info("Deleting devurl for port %v", port)
151167
} else {
152168
flog.Fatal("No devurl found for port %v", port)
153169
}
@@ -193,7 +209,7 @@ func urlList(envName string) []DevURL {
193209
}
194210

195211
if len(devURLs) == 0 {
196-
fmt.Printf("no dev urls were found for environment: %s\n", envName)
212+
flog.Error("no dev urls were found for environment: %s", envName)
197213
}
198214

199215
return devURLs
@@ -207,7 +223,7 @@ func (cmd urlsCmd) Run(fl *pflag.FlagSet) {
207223

208224
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.TabIndent)
209225
for _, devURL := range devURLs {
210-
fmt.Fprintf(w, "%s\t%s\t%s\n", devURL.URL, devURL.Port, devURL.Access)
226+
fmt.Fprintf(w, "%s\t%d\t%s\n", devURL.URL, devURL.Port, devURL.Access)
211227
}
212228
w.Flush()
213229
}

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)