duostack 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/duostack +122 -4
- metadata +5 -5
data/bin/duostack
CHANGED
@@ -28,7 +28,7 @@ $client = File.basename(__FILE__)
|
|
28
28
|
module Duostack
|
29
29
|
class Client
|
30
30
|
|
31
|
-
VERSION = '0.
|
31
|
+
VERSION = '0.3.0'
|
32
32
|
DEPENDENCIES_LAST_MODIFIED = 1298683372
|
33
33
|
USER_AGENT = "duostack-#{VERSION}"
|
34
34
|
|
@@ -49,7 +49,8 @@ module Duostack
|
|
49
49
|
:user => [ # commands requiring credentials (first-time setup)
|
50
50
|
'create',
|
51
51
|
'list',
|
52
|
-
'sync'
|
52
|
+
'sync',
|
53
|
+
'billing_reset'
|
53
54
|
],
|
54
55
|
:app => [ # commands requiring an app to be specified (either by git inference or flag)
|
55
56
|
'logs',
|
@@ -61,7 +62,8 @@ module Duostack
|
|
61
62
|
'config',
|
62
63
|
'env',
|
63
64
|
'access',
|
64
|
-
'domains'
|
65
|
+
'domains',
|
66
|
+
'instances'
|
65
67
|
],
|
66
68
|
:compound => [ # mult-part commands that expect subsequent arguments, must validate extra args on their own
|
67
69
|
'help',
|
@@ -70,7 +72,8 @@ module Duostack
|
|
70
72
|
'config',
|
71
73
|
'env',
|
72
74
|
'access',
|
73
|
-
'domains'
|
75
|
+
'domains',
|
76
|
+
'instances'
|
74
77
|
]
|
75
78
|
}
|
76
79
|
|
@@ -419,6 +422,9 @@ module Duostack
|
|
419
422
|
|
420
423
|
def api_get(endpoint, params=nil, timeout=20)
|
421
424
|
|
425
|
+
# store previous request
|
426
|
+
@previous_request = [endpoint, params, timeout]
|
427
|
+
|
422
428
|
url = "#{api_host}/api/#{endpoint}?#{@credentials}"
|
423
429
|
|
424
430
|
url += "&app_name=#{@app_name}" if @app_name
|
@@ -427,6 +433,23 @@ module Duostack
|
|
427
433
|
curl_get(url, timeout)
|
428
434
|
end
|
429
435
|
|
436
|
+
# just retries last api_get, optionally passing additional params
|
437
|
+
def api_retry(params=nil)
|
438
|
+
exit false if @previous_request.empty?
|
439
|
+
|
440
|
+
# add in additional params
|
441
|
+
if params
|
442
|
+
if @previous_request[1]
|
443
|
+
@previous_request[1] = "#{@previous_request[1]}&#{params}"
|
444
|
+
else
|
445
|
+
@previous_request[1] = params
|
446
|
+
end
|
447
|
+
end
|
448
|
+
|
449
|
+
# retry
|
450
|
+
api_get(*@previous_request)
|
451
|
+
end
|
452
|
+
|
430
453
|
def curl_get(url, timeout=nil)
|
431
454
|
command = "curl -s -A '#{USER_AGENT}' -w '\n%{http_code}'" # use w flag to append http status code, set user-agent header
|
432
455
|
command += " --cacert #{ca_cert_location}" if ca_cert_location # use our own certificate if present
|
@@ -448,6 +471,11 @@ module Duostack
|
|
448
471
|
exit_with result
|
449
472
|
end
|
450
473
|
|
474
|
+
if status == 402
|
475
|
+
print result # prints error message and prompt
|
476
|
+
return verify_account # handles input and retrying
|
477
|
+
end
|
478
|
+
|
451
479
|
case (status / 100) # just get the class of status, e.g. any 4xx code will become 4
|
452
480
|
when 2 # success, return result sans status code
|
453
481
|
return result
|
@@ -458,6 +486,15 @@ module Duostack
|
|
458
486
|
end
|
459
487
|
end
|
460
488
|
|
489
|
+
def verify_account
|
490
|
+
response = $stdin.gets.chomp.downcase
|
491
|
+
|
492
|
+
# unless response is yes or blank (default yes), exit
|
493
|
+
exit unless response == 'yes'
|
494
|
+
|
495
|
+
api_retry("billing_confirmed=1")
|
496
|
+
end
|
497
|
+
|
461
498
|
def sentencize(array, conjunction='or')
|
462
499
|
# http://stackoverflow.com/questions/2038787/join-array-contents-into-an-english-list
|
463
500
|
case array.length
|
@@ -504,6 +541,11 @@ module Duostack
|
|
504
541
|
# empty method, just makes sure credentials are set
|
505
542
|
end
|
506
543
|
|
544
|
+
# internal method for testing, just resets the billing confirmation prompt
|
545
|
+
def billing_reset
|
546
|
+
puts api_get('test_reset_billing_verification')
|
547
|
+
end
|
548
|
+
|
507
549
|
def list
|
508
550
|
puts api_get('list_apps')
|
509
551
|
end
|
@@ -654,6 +696,56 @@ module Duostack
|
|
654
696
|
})
|
655
697
|
end
|
656
698
|
|
699
|
+
def instances
|
700
|
+
|
701
|
+
arg = @args.shift || 'show' # show is the default
|
702
|
+
|
703
|
+
# instance only takes one arg so any remaning ones are invalid
|
704
|
+
unless @args.empty?
|
705
|
+
exit_with("unrecognized argument: '#{@args.first}', run '#{@client} help #{@command}' for usage")
|
706
|
+
end
|
707
|
+
|
708
|
+
action = if arg == 'show'
|
709
|
+
:show
|
710
|
+
else
|
711
|
+
case arg[0..0]
|
712
|
+
when '+' then :add
|
713
|
+
when '-' then :remove
|
714
|
+
else :set
|
715
|
+
end
|
716
|
+
end
|
717
|
+
|
718
|
+
# process numerical argument unless listing
|
719
|
+
if action != :show
|
720
|
+
# drop the plus/minus sign to get qty (if add/remove)
|
721
|
+
qty = if action == :set
|
722
|
+
arg
|
723
|
+
else
|
724
|
+
arg[1..-1]
|
725
|
+
end
|
726
|
+
end
|
727
|
+
|
728
|
+
# ensure qty is a plain integer at this point
|
729
|
+
begin
|
730
|
+
qty = Integer(qty)
|
731
|
+
rescue ArgumentError # this is what Integer() throws if its arg isn't convertible to an int
|
732
|
+
exit_with "'#{@command}' requires a numerical argument, try '#{@command} [+/-]<quantity>'"
|
733
|
+
end
|
734
|
+
|
735
|
+
|
736
|
+
# finally, process action
|
737
|
+
case action
|
738
|
+
when :show
|
739
|
+
puts api_get("count_instances")
|
740
|
+
when :add
|
741
|
+
puts api_get("set_instances", "qty=#{qty}&type=inc")
|
742
|
+
when :remove
|
743
|
+
puts api_get("set_instances", "qty=#{qty}&type=dec")
|
744
|
+
when :set
|
745
|
+
puts api_get("set_instances", "qty=#{qty}")
|
746
|
+
end
|
747
|
+
end
|
748
|
+
|
657
749
|
|
658
750
|
module Help
|
659
751
|
|
@@ -705,6 +797,7 @@ module Duostack
|
|
705
797
|
env [<operation>] Manage environment variables
|
706
798
|
access [<operation>] Manage app collaborator access
|
707
799
|
domains [<operation>] Manage custom domains
|
800
|
+
instances [<operation>] Manage app instance count
|
708
801
|
|
709
802
|
App Commands - Ruby:
|
710
803
|
console Connect to IRB/Rails console
|
@@ -926,6 +1019,31 @@ module Duostack
|
|
926
1019
|
EOF
|
927
1020
|
end
|
928
1021
|
|
1022
|
+
def instances
|
1023
|
+
<<-EOF
|
1024
|
+
|
1025
|
+
Usage:
|
1026
|
+
#{$client} instances shows current instance count
|
1027
|
+
#{$client} instances <qty> sets instance count to <qty>
|
1028
|
+
#{$client} instances +<qty> increments instance count by <qty>
|
1029
|
+
#{$client} instances -<qty> decrements instance count by <qty>
|
1030
|
+
|
1031
|
+
Examples:
|
1032
|
+
#{$client} instances shows current instance count
|
1033
|
+
#{$client} instances 5 sets instance count to 5
|
1034
|
+
#{$client} instances +2 increments instance count by 2
|
1035
|
+
#{$client} instances -2 decrements instance count by 2
|
1036
|
+
|
1037
|
+
Adjusts instance count, either setting absolutely, or incrementing/decrementing
|
1038
|
+
by a given quantity.
|
1039
|
+
|
1040
|
+
Any increment, decrement, or set command that would result in an invalid
|
1041
|
+
instance count will be rejected with an error message. Instance counts must be
|
1042
|
+
greater than 0 and not greater than 15.
|
1043
|
+
|
1044
|
+
EOF
|
1045
|
+
end
|
1046
|
+
|
929
1047
|
def console
|
930
1048
|
<<-EOF
|
931
1049
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: duostack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Todd Eichel
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-03-03 00:00:00 -05:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|