55 "fmt"
66 "net/http"
77 "os"
8+ "regexp"
89 "strconv"
910 "strings"
1011 "text/tabwriter"
@@ -21,7 +22,7 @@ type urlsCmd struct{}
2122type 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
@@ -33,55 +34,68 @@ var urlAccessLevel = map[string]string{
3334 "PUBLIC" : "Anyone on the internet can access this link" ,
3435}
3536
36- func portIsValid (port string ) bool {
37+ func validatePort (port string ) ( int , error ) {
3738 p , err := strconv .ParseUint (port , 10 , 16 )
39+ if err != nil {
40+ flog .Error ("Invalid port" )
41+ return 0 , err
42+ }
3843 if p < 1 {
3944 // port 0 means 'any free port', which we don't support
4045 err = strconv .ErrRange
46+ flog .Error ("Port must be > 0" )
47+ return 0 , err
4148 }
42- if err != nil {
43- fmt .Println ("Invalid port" )
44- }
45- return err == nil
49+ return int (p ), nil
4650}
4751
4852func accessLevelIsValid (level string ) bool {
4953 _ , ok := urlAccessLevel [level ]
5054 if ! ok {
51- fmt . Println ("Invalid access level" )
55+ flog . Error ("Invalid access level" )
5256 }
5357 return ok
5458}
5559
5660type createSubCmd struct {
57- access string
61+ access string
62+ urlname string
5863}
5964
6065func (sub * createSubCmd ) RegisterFlags (fl * pflag.FlagSet ) {
6166 fl .StringVarP (& sub .access , "access" , "a" , "private" , "[private | org | authed | public] set devurl access" )
67+ fl .StringVarP (& sub .urlname , "name" , "n" , "" , "devurl name" )
6268}
6369
6470func (sub createSubCmd ) Spec () cli.CommandSpec {
6571 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" ,
6976 }
7077}
7178
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+
7284// Run creates or updates a devURL, specified by env ID and port
7385// (fl.Arg(0) and fl.Arg(1)), with access level (fl.Arg(2)) on
7486// the cemanager.
7587func (sub createSubCmd ) Run (fl * pflag.FlagSet ) {
7688 envName := fl .Arg (0 )
7789 port := fl .Arg (1 )
78- access := fl .Arg (2 )
90+ name := fl .Arg (2 )
91+ access := fl .Arg (3 )
7992
8093 if envName == "" {
8194 exitUsage (fl )
8295 }
8396
84- if ! portIsValid (port ) {
97+ portNum , err := validatePort (port )
98+ if err != nil {
8599 exitUsage (fl )
86100 }
87101
@@ -90,20 +104,28 @@ func (sub createSubCmd) Run(fl *pflag.FlagSet) {
90104 exitUsage (fl )
91105 }
92106
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+ }
93112 entClient := requireAuth ()
94113
95114 env := findEnv (entClient , envName )
96115
97- _ , found := devURLID (port , urlList (envName ))
116+ urlID , found := devURLID (portNum , urlList (envName ))
98117 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+ }
100123 } 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+ }
107129 }
108130}
109131
@@ -117,9 +139,10 @@ func (sub delSubCmd) Spec() cli.CommandSpec {
117139 }
118140}
119141
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.
121144// ("", 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 ) {
123146 for _ , url := range urls {
124147 if url .Port == port {
125148 return url .ID , true
@@ -137,22 +160,22 @@ func (sub delSubCmd) Run(fl *pflag.FlagSet) {
137160 exitUsage (fl )
138161 }
139162
140- if ! portIsValid (port ) {
163+ portNum , err := validatePort (port )
164+ if err != nil {
141165 exitUsage (fl )
142166 }
143167
144168 entClient := requireAuth ()
145-
146169 env := findEnv (entClient , envName )
147170
148- urlID , found := devURLID (port , urlList (envName ))
171+ urlID , found := devURLID (portNum , urlList (envName ))
149172 if found {
150- fmt . Printf ("Deleting devurl for port %v\n " , port )
173+ flog . Info ("Deleting devurl for port %v" , port )
151174 } else {
152175 flog .Fatal ("No devurl found for port %v" , port )
153176 }
154177
155- err : = entClient .DelDevURL (env .ID , urlID )
178+ err = entClient .DelDevURL (env .ID , urlID )
156179 if err != nil {
157180 flog .Error ("delete devurl: %s" , err .Error ())
158181 }
@@ -192,10 +215,6 @@ func urlList(envName string) []DevURL {
192215 flog .Fatal ("%v" , err )
193216 }
194217
195- if len (devURLs ) == 0 {
196- fmt .Printf ("no dev urls were found for environment: %s\n " , envName )
197- }
198-
199218 return devURLs
200219}
201220
@@ -207,7 +226,7 @@ func (cmd urlsCmd) Run(fl *pflag.FlagSet) {
207226
208227 w := tabwriter .NewWriter (os .Stdout , 0 , 0 , 1 , ' ' , tabwriter .TabIndent )
209228 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 )
211230 }
212231 w .Flush ()
213232}
0 commit comments