duostack 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/bin/.duostack-console-expect +2 -1
- data/bin/.duostack-expect +4 -0
- data/bin/bash/.duostack-console-expect +16 -5
- data/bin/bash/.duostack-expect +9 -0
- data/bin/duostack +160 -15
- metadata +7 -4
data/Rakefile
CHANGED
@@ -13,5 +13,5 @@ Jeweler::Tasks.new do |gem|
|
|
13
13
|
gem.authors = "Todd Eichel"
|
14
14
|
gem.require_paths = ['.'] # default is ["lib"] but we don't have that
|
15
15
|
|
16
|
-
gem.executables = ["duostack", ".duostack-console-expect"]
|
16
|
+
gem.executables = ["duostack", ".duostack-expect", ".duostack-console-expect"]
|
17
17
|
end
|
@@ -1,7 +1,18 @@
|
|
1
1
|
#!/usr/bin/env expect
|
2
|
-
set appname [lindex $argv 0]
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
set timeout 3600
|
4
|
+
|
5
|
+
set client [lindex $argv 0]
|
6
|
+
set type [lindex $argv 1]
|
7
|
+
set prompt [lindex $argv 2]
|
8
|
+
set command [lindex $argv 3]
|
9
|
+
set appname [lindex $argv 4]
|
10
|
+
|
11
|
+
spawn $client console $type --app $appname
|
12
|
+
expect $prompt
|
13
|
+
send "\r"
|
14
|
+
send -- "[read [open $command r]]"
|
15
|
+
send "\r"
|
16
|
+
expect $prompt
|
17
|
+
send "exit\r"
|
18
|
+
expect eof
|
data/bin/duostack
CHANGED
@@ -28,13 +28,14 @@ $client = File.basename(__FILE__)
|
|
28
28
|
module Duostack
|
29
29
|
class Client
|
30
30
|
|
31
|
-
VERSION = '0.
|
31
|
+
VERSION = '0.4.0'
|
32
32
|
DEPENDENCIES_LAST_MODIFIED = 1298683372
|
33
33
|
USER_AGENT = "duostack-#{VERSION}"
|
34
34
|
|
35
35
|
DEFAULTS = {
|
36
36
|
:credentials_location => '~/.duostack',
|
37
|
-
:remote_name => 'duostack'
|
37
|
+
:remote_name => 'duostack',
|
38
|
+
:console_type => 'app'
|
38
39
|
}
|
39
40
|
|
40
41
|
FLAGS = [ # app and remote get special handling
|
@@ -53,6 +54,7 @@ module Duostack
|
|
53
54
|
'billing_reset'
|
54
55
|
],
|
55
56
|
:app => [ # commands requiring an app to be specified (either by git inference or flag)
|
57
|
+
'info',
|
56
58
|
'logs',
|
57
59
|
'restart',
|
58
60
|
'ps',
|
@@ -68,6 +70,7 @@ module Duostack
|
|
68
70
|
:compound => [ # mult-part commands that expect subsequent arguments, must validate extra args on their own
|
69
71
|
'help',
|
70
72
|
'create',
|
73
|
+
'console',
|
71
74
|
'rake',
|
72
75
|
'config',
|
73
76
|
'env',
|
@@ -77,6 +80,28 @@ module Duostack
|
|
77
80
|
]
|
78
81
|
}
|
79
82
|
|
83
|
+
CONSOLES = {
|
84
|
+
:app => {
|
85
|
+
:target => 'cli-console@duostack.net',
|
86
|
+
:display_type => 'Ruby',
|
87
|
+
:display_name_suffix => '',
|
88
|
+
:prompt => '>> '
|
89
|
+
},
|
90
|
+
:mysql => {
|
91
|
+
:target => 'cli-dbconsole@duostack.net',
|
92
|
+
:display_type => 'database',
|
93
|
+
:display_name_suffix => ' (mysql)',
|
94
|
+
:prompt => 'mysql> '
|
95
|
+
},
|
96
|
+
:mongodb => {
|
97
|
+
:target => 'cli-dbconsole@duostack.net',
|
98
|
+
:display_type => 'database',
|
99
|
+
:display_name_suffix => ' (mongodb)',
|
100
|
+
:prompt => '> '
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
|
80
105
|
def initialize(args=[], client='duostack')
|
81
106
|
@args = args
|
82
107
|
@client = client
|
@@ -225,8 +250,15 @@ module Duostack
|
|
225
250
|
puts "First-time Duostack client setup"
|
226
251
|
print "Email: "
|
227
252
|
username = $stdin.gets.chomp
|
228
|
-
|
229
|
-
|
253
|
+
print "Password: "
|
254
|
+
begin
|
255
|
+
# http://stackoverflow.com/questions/133719/how-to-read-a-password-in-ruby
|
256
|
+
system "stty -echo"
|
257
|
+
password = $stdin.gets.chomp
|
258
|
+
puts '' # clears the line after
|
259
|
+
ensure
|
260
|
+
system "stty echo" # this is important
|
261
|
+
end
|
230
262
|
|
231
263
|
username = CGI::escape(username)
|
232
264
|
password = CGI::escape(password)
|
@@ -574,6 +606,11 @@ module Duostack
|
|
574
606
|
end
|
575
607
|
|
576
608
|
|
609
|
+
def info
|
610
|
+
puts api_get('get_info')
|
611
|
+
end
|
612
|
+
|
613
|
+
|
577
614
|
def logs
|
578
615
|
puts api_get('get_logs')
|
579
616
|
end
|
@@ -609,12 +646,65 @@ module Duostack
|
|
609
646
|
def console
|
610
647
|
# TODO: just use ruby expect lib
|
611
648
|
|
612
|
-
#
|
649
|
+
# get console and ensure it's valid
|
650
|
+
arg = (@args.shift || DEFAULTS[:console_type]).downcase
|
651
|
+
console = CONSOLES.fetch(arg.to_sym) do |invalid_type|
|
652
|
+
exit_with "invalid console type given ('#{invalid_type}'), try #{sentencize(CONSOLES.keys.collect { |k| k.to_s})}"
|
653
|
+
end
|
654
|
+
|
655
|
+
# take piped input first as command, fall back to using remaining command line args
|
656
|
+
if $stdin.tty?
|
657
|
+
console_command = @args.join(' ') unless @args.empty?
|
658
|
+
@args.clear
|
659
|
+
else
|
660
|
+
console_command = ''
|
661
|
+
$stdin.each_line { |line| console_command << line }
|
662
|
+
end
|
663
|
+
|
664
|
+
# we're finished processing args any remaning ones are invalid
|
665
|
+
unless @args.empty?
|
666
|
+
exit_with("unrecognized argument: '#{@args.first}', run '#{@client} help #{@command}' for usage")
|
667
|
+
end
|
668
|
+
|
669
|
+
# check for expect dependency
|
613
670
|
if `which expect`.empty?
|
614
671
|
exit_with "missing dependency, please install Expect (http://expect.sourceforge.net/)"
|
615
672
|
end
|
616
673
|
|
617
|
-
|
674
|
+
if console_command
|
675
|
+
|
676
|
+
# generate console command filename
|
677
|
+
timestamp = begin
|
678
|
+
t = Time.now
|
679
|
+
"#{t.to_i}.#{t.usec}"
|
680
|
+
end
|
681
|
+
console_command_file = File.join('/tmp', "ds-#{timestamp}.txt")
|
682
|
+
|
683
|
+
# write console command to file
|
684
|
+
file = File.new(console_command_file, 'w+')
|
685
|
+
file.chmod(0600)
|
686
|
+
file.write(console_command)
|
687
|
+
file.close
|
688
|
+
|
689
|
+
result = `#{$dir}/.duostack-console-expect '#{File.join($dir, $client)}' '#{arg}' '#{console[:prompt]}' '#{console_command_file}' '#{@app_name}'`
|
690
|
+
|
691
|
+
# clean up command file
|
692
|
+
File.delete(console_command_file)
|
693
|
+
|
694
|
+
# munge results
|
695
|
+
result = result.split("\r\n")
|
696
|
+
start = (result.index("#{console[:prompt]}") || 0) + 2
|
697
|
+
stop = (result.index("#{console[:prompt]}exit") || 0) - 1
|
698
|
+
result = result.slice(start..stop)
|
699
|
+
|
700
|
+
# clean up ruby return value marker
|
701
|
+
result[-1] = result[-1][3..-1] if arg == 'app'
|
702
|
+
|
703
|
+
puts result.join("\r\n")
|
704
|
+
|
705
|
+
else
|
706
|
+
exec("#{$dir}/.duostack-expect '#{console[:target]}' 'Connecting to #{console[:display_type]} console for ' '#{@app_name}#{console[:display_name_suffix]}'")
|
707
|
+
end
|
618
708
|
end
|
619
709
|
|
620
710
|
|
@@ -789,10 +879,12 @@ module Duostack
|
|
789
879
|
version Show version of this Duostack client
|
790
880
|
|
791
881
|
App Commands:
|
882
|
+
info Show app summary information
|
792
883
|
logs Retrieve server logs
|
793
884
|
restart Restart instances
|
794
885
|
ps List instances with current status
|
795
886
|
destroy Destroy Duostack App and associated data
|
887
|
+
console [<type> [command]] Connect to app or database console, run command
|
796
888
|
config [<name> [<setting>]] Show or set configuration options
|
797
889
|
env [<operation>] Manage environment variables
|
798
890
|
access [<operation>] Manage app collaborator access
|
@@ -800,7 +892,6 @@ module Duostack
|
|
800
892
|
instances [<operation>] Manage app instance count
|
801
893
|
|
802
894
|
App Commands - Ruby:
|
803
|
-
console Connect to IRB/Rails console
|
804
895
|
rake [<command>] Run a Rake command
|
805
896
|
|
806
897
|
EOF
|
@@ -856,12 +947,22 @@ module Duostack
|
|
856
947
|
EOF
|
857
948
|
end
|
858
949
|
|
950
|
+
def info
|
951
|
+
<<-EOF
|
952
|
+
|
953
|
+
Usage: #{$client} info
|
954
|
+
|
955
|
+
Retrieves a summary of app data, e.g. Git remote URL, instance count, etc.
|
956
|
+
|
957
|
+
EOF
|
958
|
+
end
|
959
|
+
|
859
960
|
def logs
|
860
961
|
<<-EOF
|
861
962
|
|
862
963
|
Usage: #{$client} logs
|
863
964
|
|
864
|
-
|
965
|
+
Retrieves aggregate logs from all of the app's instances.
|
865
966
|
|
866
967
|
EOF
|
867
968
|
end
|
@@ -888,7 +989,7 @@ module Duostack
|
|
888
989
|
|
889
990
|
Usage: #{$client} ps
|
890
991
|
|
891
|
-
|
992
|
+
Retrieves a listing of all of the app's instances with status information
|
892
993
|
(uptime) for each.
|
893
994
|
|
894
995
|
EOF
|
@@ -1039,7 +1140,7 @@ module Duostack
|
|
1039
1140
|
|
1040
1141
|
Any increment, decrement, or set command that would result in an invalid
|
1041
1142
|
instance count will be rejected with an error message. Instance counts must be
|
1042
|
-
greater than 0
|
1143
|
+
greater than 0.
|
1043
1144
|
|
1044
1145
|
EOF
|
1045
1146
|
end
|
@@ -1047,12 +1148,56 @@ module Duostack
|
|
1047
1148
|
def console
|
1048
1149
|
<<-EOF
|
1049
1150
|
|
1050
|
-
Usage:
|
1151
|
+
Usage:
|
1152
|
+
#{$client} console [<type> [<command>]]
|
1153
|
+
launches console session of <type> (defaults to
|
1154
|
+
'app' console), optionally runs specified
|
1155
|
+
<command> in console and prints the result
|
1156
|
+
|
1157
|
+
#{$client} console <type> <command> > <output-file>
|
1158
|
+
pipes the output from running <command> to the
|
1159
|
+
specified <output-file>
|
1160
|
+
|
1161
|
+
#{$client} console <type> < <input-file>
|
1162
|
+
pipes the contents of <input-file> into the
|
1163
|
+
specified console <type>, prints the result
|
1164
|
+
|
1165
|
+
Examples:
|
1166
|
+
#{$client} console same as running "#{$client} console app"
|
1167
|
+
#{$client} console app launches interactive app console (Ruby apps only)
|
1168
|
+
#{$client} console mysql launches interactive MySQL database console
|
1169
|
+
#{$client} console mongodb launches interactive MongoDB database console
|
1170
|
+
|
1171
|
+
#{$client} console app "puts('hello world')"
|
1172
|
+
#{$client} console mysql "SHOW TABLES;"
|
1173
|
+
runs the specified command and prints the result
|
1174
|
+
|
1175
|
+
#{$client} console mysql "SHOW TABLES;" > tables.txt
|
1176
|
+
runs "SHOW TABLES;" in the app's MySQL console,
|
1177
|
+
piping output into the file "tables.txt"
|
1178
|
+
|
1179
|
+
#{$client} console mysql < import.sql
|
1180
|
+
(EXPERIMENTAL) pipes the contents of "import.sql"
|
1181
|
+
into the app's MySQL console, printing the result
|
1182
|
+
|
1183
|
+
The "console" command can operate in three ways:
|
1184
|
+
|
1185
|
+
1. Launching an interactive console session with your app or one of its
|
1186
|
+
databases. If no argument is given, it connects to the app console itself
|
1187
|
+
(applicable only to Ruby apps). If a database name is given, connects to a
|
1188
|
+
database console session for that database. Valid database names are: mysql,
|
1189
|
+
mongodb.
|
1190
|
+
|
1191
|
+
You can use then use these interactive console sessions to make any action you
|
1192
|
+
would normally make in your app or database console.
|
1051
1193
|
|
1052
|
-
|
1053
|
-
|
1194
|
+
2. Running an ad-hoc command specified on the command line in the remaining
|
1195
|
+
arguments, and printing the result. You could also then pipe the output into an
|
1196
|
+
arbitrary file.
|
1054
1197
|
|
1055
|
-
|
1198
|
+
3. (EXPERIMENTAL) Sending the contents of a piped-in file to the specified (app
|
1199
|
+
or database) console. The resulting output will be collected and printed to your
|
1200
|
+
terminal.
|
1056
1201
|
|
1057
1202
|
EOF
|
1058
1203
|
end
|
@@ -1069,7 +1214,7 @@ module Duostack
|
|
1069
1214
|
Passing of environment variables if your rake task requires them is supported
|
1070
1215
|
(e.g. rake db:seed MODEL=Posts).
|
1071
1216
|
|
1072
|
-
Applicable only to Ruby
|
1217
|
+
Applicable only to Ruby apps.
|
1073
1218
|
|
1074
1219
|
EOF
|
1075
1220
|
end
|
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: 15
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
8
|
+
- 4
|
9
9
|
- 0
|
10
|
-
version: 0.
|
10
|
+
version: 0.4.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-03-
|
18
|
+
date: 2011-03-20 00:00:00 -04:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -23,6 +23,7 @@ description: "Duostack command line client: create and manage Duostack apps"
|
|
23
23
|
email: todd@toddeichel.com
|
24
24
|
executables:
|
25
25
|
- duostack
|
26
|
+
- .duostack-expect
|
26
27
|
- .duostack-console-expect
|
27
28
|
extensions: []
|
28
29
|
|
@@ -31,7 +32,9 @@ extra_rdoc_files: []
|
|
31
32
|
files:
|
32
33
|
- Rakefile
|
33
34
|
- bin/.duostack-console-expect
|
35
|
+
- bin/.duostack-expect
|
34
36
|
- bin/bash/.duostack-console-expect
|
37
|
+
- bin/bash/.duostack-expect
|
35
38
|
- bin/duostack
|
36
39
|
- vendor/duostack-startcom.pem
|
37
40
|
has_rdoc: true
|