5
5
"fmt"
6
6
"net/http"
7
7
"os"
8
+ "regexp"
8
9
"strconv"
9
10
"strings"
10
11
"text/tabwriter"
@@ -21,7 +22,7 @@ type urlsCmd struct{}
21
22
type DevURL struct {
22
23
ID string `json:"id"`
23
24
URL string `json:"url"`
24
- Port string `json:"port"`
25
+ Port int `json:"port"`
25
26
Access string `json:"access"`
26
27
}
27
28
@@ -33,55 +34,68 @@ var urlAccessLevel = map[string]string{
33
34
"PUBLIC" : "Anyone on the internet can access this link" ,
34
35
}
35
36
36
- func portIsValid (port string ) bool {
37
+ func validatePort (port string ) ( int , error ) {
37
38
p , err := strconv .ParseUint (port , 10 , 16 )
39
+ if err != nil {
40
+ flog .Error ("Invalid port" )
41
+ return 0 , err
42
+ }
38
43
if p < 1 {
39
44
// port 0 means 'any free port', which we don't support
40
45
err = strconv .ErrRange
46
+ flog .Error ("Port must be > 0" )
47
+ return 0 , err
41
48
}
42
- if err != nil {
43
- fmt .Println ("Invalid port" )
44
- }
45
- return err == nil
49
+ return int (p ), nil
46
50
}
47
51
48
52
func accessLevelIsValid (level string ) bool {
49
53
_ , ok := urlAccessLevel [level ]
50
54
if ! ok {
51
- fmt . Println ("Invalid access level" )
55
+ flog . Error ("Invalid access level" )
52
56
}
53
57
return ok
54
58
}
55
59
56
60
type createSubCmd struct {
57
- access string
61
+ access string
62
+ urlname string
58
63
}
59
64
60
65
func (sub * createSubCmd ) RegisterFlags (fl * pflag.FlagSet ) {
61
66
fl .StringVarP (& sub .access , "access" , "a" , "private" , "[private | org | authed | public] set devurl access" )
67
+ fl .StringVarP (& sub .urlname , "name" , "n" , "" , "devurl name" )
62
68
}
63
69
64
70
func (sub createSubCmd ) Spec () cli.CommandSpec {
65
71
return cli.CommandSpec {
66
- Name : "create" ,
67
- Usage : "<env name> <port> [--access <level>]" ,
68
- Desc : "create/update a devurl for external access" ,
72
+ Name : "create" ,
73
+ Usage : "<env name> <port> [--access <level>] [--name <name>]" ,
74
+ Aliases : []string {"edit" },
75
+ Desc : "create or update a devurl for external access" ,
69
76
}
70
77
}
71
78
79
+ // devURLNameValidRx is the regex used to validate devurl names specified
80
+ // via the --name subcommand. Named devurls must begin with a letter, and
81
+ // consist solely of letters and digits, with a max length of 64 chars.
82
+ var devURLNameValidRx = regexp .MustCompile ("^[a-zA-Z][a-zA-Z0-9]{0,63}$" )
83
+
72
84
// Run creates or updates a devURL, specified by env ID and port
73
85
// (fl.Arg(0) and fl.Arg(1)), with access level (fl.Arg(2)) on
74
86
// the cemanager.
75
87
func (sub createSubCmd ) Run (fl * pflag.FlagSet ) {
76
88
envName := fl .Arg (0 )
77
89
port := fl .Arg (1 )
78
- access := fl .Arg (2 )
90
+ name := fl .Arg (2 )
91
+ access := fl .Arg (3 )
79
92
80
93
if envName == "" {
81
94
exitUsage (fl )
82
95
}
83
96
84
- if ! portIsValid (port ) {
97
+ portNum , err := validatePort (port )
98
+ if err != nil {
85
99
exitUsage (fl )
86
100
}
87
101
@@ -90,20 +104,28 @@ func (sub createSubCmd) Run(fl *pflag.FlagSet) {
90
104
exitUsage (fl )
91
105
}
92
106
107
+ name = sub .urlname
108
+ if name != "" && ! devURLNameValidRx .MatchString (name ) {
109
+ flog .Error ("update devurl: name must be < 64 chars in length, begin with a letter and only contain letters or digits." )
110
+ return
111
+ }
93
112
entClient := requireAuth ()
94
113
95
114
env := findEnv (entClient , envName )
96
115
97
- _ , found := devURLID (port , urlList (envName ))
116
+ urlID , found := devURLID (portNum , urlList (envName ))
98
117
if found {
99
- fmt .Printf ("Updating devurl for port %v\n " , port )
118
+ flog .Info ("Updating devurl for port %v" , port )
119
+ err := entClient .UpdateDevURL (env .ID , urlID , portNum , name , access )
120
+ if err != nil {
121
+ flog .Error ("update devurl: %s" , err .Error ())
122
+ }
100
123
} 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 ())
124
+ flog .Info ("Adding devurl for port %v" , port )
125
+ err := entClient .InsertDevURL (env .ID , portNum , name , access )
126
+ if err != nil {
127
+ flog .Error ("insert devurl: %s" , err .Error ())
128
+ }
107
129
}
108
130
}
109
131
@@ -117,9 +139,10 @@ func (sub delSubCmd) Spec() cli.CommandSpec {
117
139
}
118
140
}
119
141
120
- // devURLID returns the ID of a devURL, given the env name and port.
142
+ // devURLID returns the ID of a devURL, given the env name and port
143
+ // from a list of DevURL records.
121
144
// ("", false) is returned if no match is found.
122
- func devURLID (port string , urls []DevURL ) (string , bool ) {
145
+ func devURLID (port int , urls []DevURL ) (string , bool ) {
123
146
for _ , url := range urls {
124
147
if url .Port == port {
125
148
return url .ID , true
@@ -137,22 +160,22 @@ func (sub delSubCmd) Run(fl *pflag.FlagSet) {
137
160
exitUsage (fl )
138
161
}
139
162
140
- if ! portIsValid (port ) {
163
+ portNum , err := validatePort (port )
164
+ if err != nil {
141
165
exitUsage (fl )
142
166
}
143
167
144
168
entClient := requireAuth ()
145
-
146
169
env := findEnv (entClient , envName )
147
170
148
- urlID , found := devURLID (port , urlList (envName ))
171
+ urlID , found := devURLID (portNum , urlList (envName ))
149
172
if found {
150
- fmt . Printf ("Deleting devurl for port %v\n " , port )
173
+ flog . Info ("Deleting devurl for port %v" , port )
151
174
} else {
152
175
flog .Fatal ("No devurl found for port %v" , port )
153
176
}
154
177
155
- err : = entClient .DelDevURL (env .ID , urlID )
178
+ err = entClient .DelDevURL (env .ID , urlID )
156
179
if err != nil {
157
180
flog .Error ("delete devurl: %s" , err .Error ())
158
181
}
@@ -192,10 +215,6 @@ func urlList(envName string) []DevURL {
192
215
flog .Fatal ("%v" , err )
193
216
}
194
217
195
- if len (devURLs ) == 0 {
196
- fmt .Printf ("no dev urls were found for environment: %s\n " , envName )
197
- }
198
-
199
218
return devURLs
200
219
}
201
220
@@ -207,7 +226,7 @@ func (cmd urlsCmd) Run(fl *pflag.FlagSet) {
207
226
208
227
w := tabwriter .NewWriter (os .Stdout , 0 , 0 , 1 , ' ' , tabwriter .TabIndent )
209
228
for _ , devURL := range devURLs {
210
- fmt .Fprintf (w , "%s\t %s \t %s\n " , devURL .URL , devURL .Port , devURL .Access )
229
+ fmt .Fprintf (w , "%s\t %d \t %s\n " , devURL .URL , devURL .Port , devURL .Access )
211
230
}
212
231
w .Flush ()
213
232
}
0 commit comments