@@ -44,6 +44,7 @@ import (
44
44
// $HOME/harp/$APP/script
45
45
46
46
func init () {
47
+ log .SetOutput (os .Stdout )
47
48
if option .debug {
48
49
log .SetFlags (log .Lshortfile )
49
50
} else {
@@ -115,6 +116,14 @@ func (t *Tasks) Set(s string) error {
115
116
return nil
116
117
}
117
118
119
+ type FlagStrings []string
120
+
121
+ func (t FlagStrings ) String () string { return "" }
122
+ func (t * FlagStrings ) Set (s string ) error {
123
+ * t = append (* t , s )
124
+ return nil
125
+ }
126
+
118
127
var (
119
128
option = struct {
120
129
configPath string
@@ -137,17 +146,21 @@ var (
137
146
syncFileLimit int
138
147
139
148
// TODO: can specify a single server, instead of the whole server set
140
- server string
141
- serverSet string
142
- serverSets []string
149
+ servers FlagStrings
150
+ serverSets FlagStrings
143
151
help bool
144
152
version bool
145
153
146
154
buildArgs string
147
155
148
156
all bool
149
157
158
+ deploy string
159
+
150
160
tasks Tasks
161
+ hand bool
162
+
163
+ cli bool
151
164
}{}
152
165
153
166
migrations []Migration
@@ -195,10 +208,10 @@ func main() {
195
208
196
209
// flag.StringVar(&option.script, "scripts", "", "scripts to build and run on server")
197
210
198
- flag .StringVar (& option .serverSet , "s" , " " , "specify server sets to deploy, multiple sets are split by comma" )
199
- flag .StringVar (& option .serverSet , "server-set" , " " , "specify server sets to deploy, multiple sets are split by comma" )
211
+ flag .Var (& option .serverSets , "s" , "specify server sets to deploy, multiple sets are split by comma" )
212
+ flag .Var (& option .serverSets , "server-set" , "specify server sets to deploy, multiple sets are split by comma" )
200
213
201
- flag .StringVar (& option .server , "server" , " " , "specify servers to deploy, multiple servers are split by comma" )
214
+ flag .Var (& option .servers , "server" , "specify servers to deploy, multiple servers are split by comma" )
202
215
203
216
flag .BoolVar (& option .all , "all" , false , "execute action on all server" )
204
217
@@ -207,7 +220,10 @@ func main() {
207
220
// flag.StringVar(&option.migration, "m", "", "specify migrations to run on server, multiple migrations are split by comma")
208
221
// flag.StringVar(&option.server, "server", "", "specify servers to deploy, multiple servers are split by comma")
209
222
223
+ flag .StringVar (& option .deploy , "deploy" , "" , "deploy app to servers/sets" )
224
+
210
225
flag .Var (& option .tasks , "run" , "run go scripts/packages on remote server." )
226
+ flag .BoolVar (& option .hand , "hand" , false , "pirnt out shell scripts could be executed by hand on remote servers" )
211
227
212
228
flag .Parse ()
213
229
@@ -216,16 +232,19 @@ func main() {
216
232
return
217
233
}
218
234
235
+ var action string
219
236
args := flag .Args ()
220
- if len (migrations ) > 0 {
221
- args = append (args , "run" )
222
- }
223
- if len (args ) == 0 || option .help {
237
+ switch {
238
+ case len (migrations ) > 0 :
239
+ action = "run"
240
+ case len (args ) > 0 :
241
+ action = args [0 ]
242
+ case len (args ) == 0 || option .help :
224
243
printUsage ()
225
244
return
226
245
}
227
246
228
- switch args [ 0 ] {
247
+ switch action {
229
248
case "init" :
230
249
initHarp ()
231
250
return
@@ -238,19 +257,22 @@ func main() {
238
257
cfg = parseCfg (option .configPath )
239
258
240
259
var servers []* Server
241
- if args [ 0 ] != "cross-compile" && args [ 0 ] != "xc" {
260
+ if action != "cross-compile" && action != "xc" {
242
261
servers = retrieveServers ()
243
262
}
244
263
245
- switch args [ 0 ] {
264
+ switch action {
246
265
case "kill" :
247
266
kill (servers )
248
267
case "deploy" :
249
268
deploy (servers )
250
269
case "migrate" , "run" :
251
270
// TODO: could specify to run on all servers
252
- // migrations := retrieveMigrations(args[1:])
253
- // var server = cfg.Servers[serverSets[0]][0]
271
+ if len (migrations ) == 0 {
272
+ log .Println ("run command is deprecated. please use flag: -run." )
273
+ log .Println ("e.g. harp -s prod -run file.go -run file2.go" )
274
+ os .Exit (1 )
275
+ }
254
276
migrate (servers , migrations )
255
277
case "info" :
256
278
info (servers )
@@ -336,103 +358,6 @@ func deploy(servers []*Server) {
336
358
wg .Wait ()
337
359
}
338
360
339
- func syncFiles () {
340
- log .Println ("syncing files" )
341
- if err := os .MkdirAll (filepath .Join (tmpDir , "files" ), 0755 ); err != nil {
342
- exitf ("os.MkdirAll(.harp/files) error: %s" , err )
343
- }
344
-
345
- var wg sync.WaitGroup
346
- wg .Add (len (cfg .App .Files ))
347
- for _ , file := range cfg .App .Files {
348
- go func (f File ) {
349
- defer func () { wg .Done () }()
350
- var src , gopath string
351
- for _ , gopath = range GoPaths {
352
- src = filepath .Join (gopath , "src" , f .Path )
353
- if _ , err := os .Stat (src ); err != nil {
354
- src = ""
355
- continue
356
- }
357
-
358
- break
359
- }
360
- if src == "" {
361
- exitf ("failed to find %s from %s" , f .Path , GoPaths )
362
- }
363
-
364
- dst := filepath .Join (tmpDir , "files" , strings .Replace (f .Path , "/" , "_" , - 1 ))
365
- if fi , err := os .Stat (src ); err != nil {
366
- exitf ("os.Stat(%s) error: %s" , src , err )
367
- } else if fi .IsDir () {
368
- if option .debug {
369
- log .Println (dst , fi .Mode ())
370
- }
371
- if err := os .Mkdir (dst , fi .Mode ()); err != nil {
372
- exitf ("os.Mkdir(%s) error: %s" , dst , err )
373
- }
374
- } else {
375
- // a single file speicified in Files.
376
- copyFile (dst , src )
377
- }
378
-
379
- // handle directory here
380
- base := filepath .Join (gopath , "src" , f .Path )
381
- err := filepath .Walk (src , func (path string , info os.FileInfo , err error ) error {
382
- if err != nil {
383
- exitf ("walk %s: %s" , path , err )
384
- } else if path == base {
385
- return nil
386
- }
387
-
388
- rel , err := filepath .Rel (base , path )
389
- if err != nil {
390
- exitf ("fielpath.Rel(%s, %s) error: %s" , base , path , err )
391
- }
392
-
393
- for _ , e := range append (cfg .App .DefaultExcludeds , f .Excludeds ... ) {
394
- matched , err := filepath .Match (e , rel )
395
- if err != nil {
396
- exitf ("filepath.Match(%s, %s) error: %s" , e , rel , err )
397
- }
398
- if ! matched && ! option .softExclude {
399
- matched = strings .Contains (rel , e )
400
- }
401
- if matched {
402
- if info .IsDir () {
403
- return filepath .SkipDir
404
- } else {
405
- return nil
406
- }
407
- }
408
- }
409
-
410
- if info .IsDir () {
411
- if option .debug {
412
- log .Println (filepath .Join (dst , rel ), info .Mode ())
413
- }
414
- if err := os .Mkdir (filepath .Join (dst , rel ), info .Mode ()); err != nil {
415
- exitf ("os.Mkdir(%s) error: %s" , filepath .Join (dst , rel ), err )
416
- }
417
- return nil
418
- }
419
-
420
- wg .Add (1 )
421
- go func () {
422
- defer func () { wg .Done () }()
423
- copyFile (filepath .Join (dst , rel ), path )
424
- }()
425
- return nil
426
- })
427
- if err != nil && err != filepath .SkipDir {
428
- exitf ("walking %s: %s" , src , err )
429
- }
430
- }(file )
431
- }
432
-
433
- wg .Wait ()
434
- }
435
-
436
361
func info (servers []* Server ) {
437
362
var wg sync.WaitGroup
438
363
for _ , serv := range servers {
@@ -456,15 +381,11 @@ func parseCfg(configPath string) (cfg Config) {
456
381
r , err := os .OpenFile (configPath , os .O_RDONLY , 0644 )
457
382
if err != nil {
458
383
if os .IsNotExist (err ) {
459
- fmt .Printf ("Config %s doesn't exist or is unspecified.\n To specify with flag -c (e.g. -c harp.json)\n " , configPath )
460
- os .Exit (1 )
461
- return
384
+ exitf ("Config %s doesn't exist or is unspecified.\n To specify with flag -c (e.g. -c harp.json)" , configPath )
462
385
}
463
386
exitf ("failed to read config: %s" , err )
464
387
}
465
- r = JsonConfigReader .New (r )
466
- err = json .NewDecoder (r ).Decode (& cfg )
467
- if err != nil {
388
+ if err := json .NewDecoder (JsonConfigReader .New (r )).Decode (& cfg ); err != nil {
468
389
exitf ("failed to parse config: %s" , err )
469
390
}
470
391
@@ -650,31 +571,17 @@ examples:
650
571
}
651
572
652
573
func retrieveServers () []* Server {
653
- var serverSets []string
654
- for _ , set := range strings .Split (option .serverSet , "," ) {
655
- set = strings .TrimSpace (set )
656
- if set == "" {
657
- continue
658
- }
659
- serverSets = append (serverSets , set )
660
- }
661
-
662
- var servers []string
663
- for _ , server := range strings .Split (option .server , "," ) {
664
- server = strings .TrimSpace (server )
665
- if server == "" {
666
- continue
667
- }
668
- servers = append (servers , server )
669
- }
574
+ serverSets := option .serverSets
575
+ servers := option .servers
670
576
671
577
if option .all {
578
+ serverSets = []string {}
672
579
for set , _ := range cfg .Servers {
673
580
serverSets = append (serverSets , set )
674
581
}
675
582
}
676
583
677
- if option . server == "" && option . serverSet == "" {
584
+ if len ( servers ) == 0 && len ( serverSets ) == 0 {
678
585
println ("please specify servers or server sets to deploy (-s or -server)." )
679
586
println ("specify -all flag to execute the action on all servers." )
680
587
os .Exit (1 )
@@ -705,7 +612,13 @@ serversLoop:
705
612
}
706
613
}
707
614
}
708
- println ("unknown server:" , server )
615
+
616
+ // one-shot servers
617
+ if s := newOneShotServer (server ); s != nil {
618
+ targetServers = append (targetServers , newOneShotServer (server ))
619
+ } else {
620
+ exitf ("wrong url format (eg: name@host:port): %s" , server )
621
+ }
709
622
os .Exit (1 )
710
623
}
711
624
@@ -735,7 +648,7 @@ func initHarp() {
735
648
"name": "%s",
736
649
"importpath": "%s",
737
650
"envs": {},
738
- "DefaultExcludeds": [".git/", "tmp/", ".DS_Store", "node_modules/", "*.swp"],
651
+ "DefaultExcludeds": [".git/", "tmp/", ".DS_Store", "node_modules/", "*.swp", "*.go" ],
739
652
"files": [
740
653
"%s"
741
654
]
0 commit comments