turbot 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +15 -0
  2. data/README.md +36 -0
  3. data/bin/turbot +17 -0
  4. data/data/cacert.pem +3988 -0
  5. data/lib/turbot/auth.rb +315 -0
  6. data/lib/turbot/cli.rb +38 -0
  7. data/lib/turbot/client/cisaurus.rb +25 -0
  8. data/lib/turbot/client/pgbackups.rb +113 -0
  9. data/lib/turbot/client/rendezvous.rb +111 -0
  10. data/lib/turbot/client/ssl_endpoint.rb +25 -0
  11. data/lib/turbot/client/turbot_postgresql.rb +148 -0
  12. data/lib/turbot/client.rb +757 -0
  13. data/lib/turbot/command/auth.rb +85 -0
  14. data/lib/turbot/command/base.rb +192 -0
  15. data/lib/turbot/command/bots.rb +326 -0
  16. data/lib/turbot/command/config.rb +123 -0
  17. data/lib/turbot/command/help.rb +179 -0
  18. data/lib/turbot/command/keys.rb +115 -0
  19. data/lib/turbot/command/logs.rb +34 -0
  20. data/lib/turbot/command/ssl.rb +43 -0
  21. data/lib/turbot/command/status.rb +51 -0
  22. data/lib/turbot/command/update.rb +47 -0
  23. data/lib/turbot/command/version.rb +23 -0
  24. data/lib/turbot/command.rb +304 -0
  25. data/lib/turbot/deprecated/help.rb +38 -0
  26. data/lib/turbot/deprecated.rb +5 -0
  27. data/lib/turbot/distribution.rb +9 -0
  28. data/lib/turbot/errors.rb +28 -0
  29. data/lib/turbot/excon.rb +11 -0
  30. data/lib/turbot/helpers/log_displayer.rb +70 -0
  31. data/lib/turbot/helpers/pg_dump_restore.rb +115 -0
  32. data/lib/turbot/helpers/turbot_postgresql.rb +213 -0
  33. data/lib/turbot/helpers.rb +521 -0
  34. data/lib/turbot/plugin.rb +165 -0
  35. data/lib/turbot/updater.rb +171 -0
  36. data/lib/turbot/version.rb +3 -0
  37. data/lib/turbot.rb +19 -0
  38. data/lib/vendor/turbot/okjson.rb +598 -0
  39. data/spec/helper/legacy_help.rb +16 -0
  40. data/spec/helper/pg_dump_restore_spec.rb +67 -0
  41. data/spec/schemas/dummy_schema.json +12 -0
  42. data/spec/spec.opts +1 -0
  43. data/spec/spec_helper.rb +220 -0
  44. data/spec/support/display_message_matcher.rb +49 -0
  45. data/spec/support/dummy_api.rb +120 -0
  46. data/spec/support/openssl_mock_helper.rb +8 -0
  47. data/spec/support/organizations_mock_helper.rb +11 -0
  48. data/spec/turbot/auth_spec.rb +214 -0
  49. data/spec/turbot/client/pgbackups_spec.rb +43 -0
  50. data/spec/turbot/client/rendezvous_spec.rb +62 -0
  51. data/spec/turbot/client/ssl_endpoint_spec.rb +48 -0
  52. data/spec/turbot/client/turbot_postgresql_spec.rb +71 -0
  53. data/spec/turbot/client_spec.rb +548 -0
  54. data/spec/turbot/command/auth_spec.rb +38 -0
  55. data/spec/turbot/command/base_spec.rb +66 -0
  56. data/spec/turbot/command/bots_spec.rb +54 -0
  57. data/spec/turbot/command/config_spec.rb +143 -0
  58. data/spec/turbot/command/help_spec.rb +90 -0
  59. data/spec/turbot/command/keys_spec.rb +117 -0
  60. data/spec/turbot/command/logs_spec.rb +60 -0
  61. data/spec/turbot/command/status_spec.rb +48 -0
  62. data/spec/turbot/command/version_spec.rb +16 -0
  63. data/spec/turbot/command_spec.rb +131 -0
  64. data/spec/turbot/helpers/turbot_postgresql_spec.rb +181 -0
  65. data/spec/turbot/helpers_spec.rb +48 -0
  66. data/spec/turbot/plugin_spec.rb +172 -0
  67. data/spec/turbot/updater_spec.rb +44 -0
  68. data/templates/manifest.json +7 -0
  69. data/templates/scraper.py +5 -0
  70. data/templates/scraper.rb +6 -0
  71. metadata +199 -0
@@ -0,0 +1,179 @@
1
+ require "turbot/command/base"
2
+ require "turbot/deprecated/help"
3
+
4
+ # list commands and display help
5
+ #
6
+ class Turbot::Command::Help < Turbot::Command::Base
7
+
8
+ PRIMARY_NAMESPACES = %w( auth bots ps run addons config releases domains logs sharing )
9
+
10
+ include Turbot::Deprecated::Help
11
+
12
+ # help [COMMAND]
13
+ #
14
+ # list available commands or display help for a specific command
15
+ #
16
+ #Examples:
17
+ #
18
+ # $ turbot help
19
+ # Usage: turbot COMMAND [--bot APP] [command-specific-options]
20
+ #
21
+ # Primary help topics, type "turbot help TOPIC" for more details:
22
+ #
23
+ # addons # manage addon resources
24
+ # bots # manage bots (create, destroy)
25
+ # ...
26
+ #
27
+ # Additional topics:
28
+ #
29
+ # account # manage turbot account options
30
+ # accounts # manage multiple turbot accounts
31
+ # ...
32
+ #
33
+ # $ turbot help bots:create
34
+ # Usage: turbot bots:create [NAME]
35
+ #
36
+ # create a new bot
37
+ #
38
+ # --addons ADDONS # a comma-delimited list of addons to install
39
+ # -b, --buildpack BUILDPACK # a buildpack url to use for this bot
40
+ # -r, --remote REMOTE # the git remote to create, default "turbot"
41
+ # -s, --stack STACK # the stack on which to create the bot
42
+ #
43
+ def index
44
+ if command = args.shift
45
+ help_for_command(command)
46
+ else
47
+ help_for_root
48
+ end
49
+ end
50
+
51
+ alias_command "-h", "help"
52
+ alias_command "--help", "help"
53
+
54
+ private
55
+
56
+ def commands_for_namespace(name)
57
+ Turbot::Command.commands.values.select do |command|
58
+ command[:namespace] == name && command[:command] != name
59
+ end
60
+ end
61
+
62
+ def namespaces
63
+ namespaces = Turbot::Command.namespaces
64
+ namespaces.delete("bot")
65
+ namespaces
66
+ end
67
+
68
+ def commands
69
+ Turbot::Command.commands
70
+ end
71
+
72
+ def legacy_help_for_namespace(namespace)
73
+ instance = Turbot::Command::Help.groups.map do |group|
74
+ [ group.title, group.select { |c| c.first =~ /^#{namespace}/ }.length ]
75
+ end.sort_by { |l| l.last }.last
76
+ return nil unless instance
77
+ return nil if instance.last.zero?
78
+ instance.first
79
+ end
80
+
81
+ def legacy_help_for_command(command)
82
+ Turbot::Command::Help.groups.each do |group|
83
+ group.each do |cmd, description|
84
+ return description if cmd.split(" ").first == command
85
+ end
86
+ end
87
+ nil
88
+ end
89
+
90
+ def skip_namespace?(ns)
91
+ return true if ns[:description] =~ /DEPRECATED:/
92
+ return true if ns[:description] =~ /HIDDEN:/
93
+ false
94
+ end
95
+
96
+ def skip_command?(command)
97
+ return true if command[:help] =~ /DEPRECATED:/
98
+ return true if command[:help] =~ /^ HIDDEN:/
99
+ false
100
+ end
101
+
102
+ def primary_namespaces
103
+ PRIMARY_NAMESPACES.map { |name| namespaces[name] }.compact
104
+ end
105
+
106
+ def additional_namespaces
107
+ (namespaces.values - primary_namespaces)
108
+ end
109
+
110
+ def summary_for_namespaces(namespaces)
111
+ size = longest(namespaces.map { |n| n[:name] })
112
+ namespaces.sort_by {|namespace| namespace[:name]}.each do |namespace|
113
+ next if skip_namespace?(namespace)
114
+ name = namespace[:name]
115
+ namespace[:description] ||= legacy_help_for_namespace(name)
116
+ puts " %-#{size}s # %s" % [ name, namespace[:description] ]
117
+ end
118
+ end
119
+
120
+ def help_for_root
121
+ puts "Usage: turbot COMMAND [--bot APP] [command-specific-options]"
122
+ puts
123
+ puts "Primary help topics, type \"turbot help TOPIC\" for more details:"
124
+ puts
125
+ summary_for_namespaces(primary_namespaces)
126
+ puts
127
+ puts "Additional topics:"
128
+ puts
129
+ summary_for_namespaces(additional_namespaces)
130
+ puts
131
+ end
132
+
133
+ def help_for_namespace(name)
134
+ namespace_commands = commands_for_namespace(name)
135
+
136
+ unless namespace_commands.empty?
137
+ size = longest(namespace_commands.map { |c| c[:banner] })
138
+ namespace_commands.sort_by { |c| c[:banner].to_s }.each do |command|
139
+ next if skip_command?(command)
140
+ command[:summary] ||= legacy_help_for_command(command[:command])
141
+ puts " %-#{size}s # %s" % [ command[:banner], command[:summary] ]
142
+ end
143
+ end
144
+ end
145
+
146
+ def help_for_command(name)
147
+ if command_alias = Turbot::Command.command_aliases[name]
148
+ display("Alias: #{name} redirects to #{command_alias}")
149
+ name = command_alias
150
+ end
151
+ if command = commands[name]
152
+ puts "Usage: turbot #{command[:banner]}"
153
+
154
+ if command[:help].strip.length > 0
155
+ help = command[:help].split("\n").reject do |line|
156
+ line =~ /HIDDEN/
157
+ end
158
+ puts help[1..-1].join("\n")
159
+ else
160
+ puts
161
+ puts " " + legacy_help_for_command(name).to_s
162
+ end
163
+ puts
164
+ end
165
+
166
+ namespace_commands = commands_for_namespace(name).reject do |command|
167
+ command[:help] =~ /DEPRECATED/
168
+ end
169
+
170
+ if !namespace_commands.empty?
171
+ puts "Additional commands, type \"turbot help COMMAND\" for more details:"
172
+ puts
173
+ help_for_namespace(name)
174
+ puts
175
+ elsif command.nil?
176
+ error "#{name} is not a turbot command. See `turbot help`."
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,115 @@
1
+ require "turbot/command/base"
2
+
3
+ module Turbot::Command
4
+
5
+ # manage authentication keys
6
+ #
7
+ class Keys < Base
8
+
9
+ # keys
10
+ #
11
+ # display keys for the current user
12
+ #
13
+ # -l, --long # display extended information for each key
14
+ #
15
+ #Examples:
16
+ #
17
+ # $ turbot keys
18
+ # === email@example.com Keys
19
+ # ssh-rsa ABCDEFGHIJK...OPQRSTUV== email@example.com
20
+ #
21
+ # $ turbot keys --long
22
+ # === email@example.com Keys
23
+ # ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAp9AJD5QABmOcrkHm6SINuQkDefaR0MUrfgZ1Pxir3a4fM1fwa00dsUwbUaRuR7FEFD8n1E9WwDf8SwQTHtyZsJg09G9myNqUzkYXCmydN7oGr5IdVhRyv5ixcdiE0hj7dRnOJg2poSQ3Qi+Ka8SVJzF7nIw1YhuicHPSbNIFKi5s0D5a+nZb/E6MNGvhxoFCQX2IcNxaJMqhzy1ESwlixz45aT72mXYq0LIxTTpoTqma1HuKdRY8HxoREiivjmMQulYP+CxXFcMyV9kxTKIUZ/FXqlC6G5vSm3J4YScSatPOj9ID5HowpdlIx8F6y4p1/28r2tTl4CY40FFyoke4MQ== email@example.com
24
+ #
25
+ def index
26
+ validate_arguments!
27
+ keys = api.get_keys
28
+ if keys.length > 0
29
+ styled_header("#{Turbot::Auth.user} Keys")
30
+ keys = if options[:long]
31
+ keys.map {|key| key["contents"].strip}
32
+ else
33
+ keys.map {|key| format_key_for_display(key["contents"])}
34
+ end
35
+ styled_array(keys)
36
+ else
37
+ display("You have no keys.")
38
+ end
39
+ end
40
+
41
+ # keys:add [KEY]
42
+ #
43
+ # add a key for the current user
44
+ #
45
+ # if no KEY is specified, will try to find ~/.ssh/id_[rd]sa.pub
46
+ #
47
+ #Examples:
48
+ #
49
+ # $ turbot keys:add
50
+ # Could not find an existing public key.
51
+ # Would you like to generate one? [Yn] y
52
+ # Generating new SSH public key.
53
+ # Uploading SSH public key /.ssh/id_rsa.pub... done
54
+ #
55
+ # $ turbot keys:add /my/key.pub
56
+ # Uploading SSH public key /my/key.pub... done
57
+ #
58
+ def add
59
+ keyfile = shift_argument
60
+ validate_arguments!
61
+
62
+ if keyfile
63
+ Turbot::Auth.associate_key(keyfile)
64
+ else
65
+ # make sure we have credentials
66
+ Turbot::Auth.get_credentials
67
+ Turbot::Auth.associate_or_generate_ssh_key
68
+ end
69
+ end
70
+
71
+ # keys:remove KEY
72
+ #
73
+ # remove a key from the current user
74
+ #
75
+ #Examples:
76
+ #
77
+ # $ turbot keys:remove email@example.com
78
+ # Removing email@example.com SSH key... done
79
+ #
80
+ def remove
81
+ key = shift_argument
82
+ if key.nil? || key.empty?
83
+ error("Usage: turbot keys:remove KEY\nMust specify KEY to remove.")
84
+ end
85
+ validate_arguments!
86
+
87
+ action("Removing #{key} SSH key") do
88
+ api.delete_key(key)
89
+ end
90
+ end
91
+
92
+ # keys:clear
93
+ #
94
+ # remove all authentication keys from the current user
95
+ #
96
+ #Examples:
97
+ #
98
+ # $ turbot keys:clear
99
+ # Removing all SSH keys... done
100
+ #
101
+ def clear
102
+ validate_arguments!
103
+
104
+ action("Removing all SSH keys") do
105
+ api.delete_keys
106
+ end
107
+ end
108
+
109
+ protected
110
+ def format_key_for_display(key)
111
+ type, hex, local = key.strip.split(/\s/)
112
+ [type, hex[0,10] + '...' + hex[-10,10], local].join(' ')
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,34 @@
1
+ require "turbot/command/base"
2
+ require "turbot/helpers/log_displayer"
3
+
4
+ # display logs for an bot
5
+ #
6
+ class Turbot::Command::Logs < Turbot::Command::Base
7
+
8
+ # logs
9
+ #
10
+ # display recent log output
11
+ #
12
+ # -n, --num NUM # the number of lines to display
13
+ # -p, --ps PS # only display logs from the given process
14
+ # -s, --source SOURCE # only display logs from the given source
15
+ # -t, --tail # continually stream logs
16
+ #
17
+ #Example:
18
+ #
19
+ # $ turbot logs
20
+ # 2012-01-01T12:00:00+00:00 turbot[api]: Config add EXAMPLE by email@example.com
21
+ # 2012-01-01T12:00:01+00:00 turbot[api]: Release v1 created by email@example.com
22
+ #
23
+ def index
24
+ validate_arguments!
25
+
26
+ opts = []
27
+ opts << "tail=1" if options[:tail]
28
+ opts << "num=#{options[:num]}" if options[:num]
29
+ opts << "ps=#{URI.encode(options[:ps])}" if options[:ps]
30
+ opts << "source=#{URI.encode(options[:source])}" if options[:source]
31
+ log_displayer = ::Turbot::Helpers::LogDisplayer.new(api, bot, opts)
32
+ log_displayer.display_logs
33
+ end
34
+ end
@@ -0,0 +1,43 @@
1
+ require "turbot/command/base"
2
+
3
+ module Turbot::Command
4
+
5
+ # DEPRECATED: see `turbot certs` instead
6
+ #
7
+ # manage ssl certificates for an bot
8
+ #
9
+ class Ssl < Base
10
+
11
+ # ssl
12
+ #
13
+ # list legacy certificates for an bot
14
+ #
15
+ def index
16
+ api.get_domains(bot).body.each do |domain|
17
+ if cert = domain['cert']
18
+ display "#{domain['domain']} has a SSL certificate registered to #{cert['subject']} which expires on #{format_date(cert['expires_at'])}"
19
+ else
20
+ display "#{domain['domain']} has no certificate"
21
+ end
22
+ end
23
+ end
24
+
25
+ # ssl:add PEM KEY
26
+ #
27
+ # DEPRECATED: see `turbot certs:add` instead
28
+ #
29
+ def add
30
+ $stderr.puts " ! `turbot ssl:add` has been deprecated. Please use the SSL Endpoint add-on and the `turbot certs` commands instead."
31
+ $stderr.puts " ! SSL Endpoint documentation is available at: https://devcenter.turbot.com/articles/ssl-endpoint"
32
+ end
33
+
34
+ # ssl:clear
35
+ #
36
+ # remove legacy ssl certificates from an bot
37
+ #
38
+ def clear
39
+ turbot.clear_ssl(bot)
40
+ display "Cleared certificates for #{bot}"
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,51 @@
1
+ require "turbot/command/base"
2
+
3
+ # check status of turbot platform
4
+ #
5
+ class Turbot::Command::Status < Turbot::Command::Base
6
+
7
+ # status
8
+ #
9
+ # display current status of turbot platform
10
+ #
11
+ #Example:
12
+ #
13
+ # $ turbot status
14
+ # === Turbot Status
15
+ # Development: No known issues at this time.
16
+ # Production: No known issues at this time.
17
+ #
18
+ def index
19
+ validate_arguments!
20
+
21
+ turbot_status_host = ENV['TURBOT_STATUS_HOST'] || "status.turbot.com"
22
+ require('excon')
23
+ status = json_decode(Excon.get("https://#{turbot_status_host}/api/v3/current-status.json", :nonblock => false).body)
24
+
25
+ styled_header("Turbot Status")
26
+
27
+ status['status'].each do |key, value|
28
+ if value == 'green'
29
+ status['status'][key] = 'No known issues at this time.'
30
+ end
31
+ end
32
+ styled_hash(status['status'])
33
+
34
+ unless status['issues'].empty?
35
+ display
36
+ status['issues'].each do |issue|
37
+ duration = time_ago(issue['created_at']).gsub(' ago', '+')
38
+ styled_header("#{issue['title']} #{duration}")
39
+ changes = issue['updates'].map do |issue|
40
+ [
41
+ time_ago(issue['created_at']),
42
+ issue['update_type'],
43
+ issue['contents']
44
+ ]
45
+ end
46
+ styled_array(changes, :sort => false)
47
+ end
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,47 @@
1
+ require "turbot/command/base"
2
+ require "turbot/updater"
3
+
4
+ # update the turbot client
5
+ #
6
+ class Turbot::Command::Update < Turbot::Command::Base
7
+
8
+ # update
9
+ #
10
+ # update the turbot client
11
+ #
12
+ # Example:
13
+ #
14
+ # $ turbot update
15
+ # Updating from v1.2.3... done, updated to v2.3.4
16
+ #
17
+ def index
18
+ validate_arguments!
19
+ update_from_url("https://toolbelt.turbot.com/download/zip")
20
+ end
21
+
22
+ # update:beta
23
+ #
24
+ # update to the latest beta client
25
+ #
26
+ # $ turbot update
27
+ # Updating from v1.2.3... done, updated to v2.3.4.pre
28
+ #
29
+ def beta
30
+ validate_arguments!
31
+ update_from_url("https://toolbelt.turbot.com/download/beta-zip")
32
+ end
33
+
34
+ private
35
+
36
+ def update_from_url(url)
37
+ Turbot::Updater.check_disabled!
38
+ action("Updating from #{Turbot::VERSION}") do
39
+ if new_version = Turbot::Updater.update(url)
40
+ status("updated to #{new_version}")
41
+ else
42
+ status("nothing to update")
43
+ end
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,23 @@
1
+ require "turbot/command/base"
2
+ require "turbot/version"
3
+
4
+ # display version
5
+ #
6
+ class Turbot::Command::Version < Turbot::Command::Base
7
+
8
+ # version
9
+ #
10
+ # show turbot client version
11
+ #
12
+ #Example:
13
+ #
14
+ # $ turbot version
15
+ # turbot-toolbelt/1.2.3 (x86_64-darwin11.2.0) ruby/1.9.3
16
+ #
17
+ def index
18
+ validate_arguments!
19
+
20
+ display(Turbot.user_agent)
21
+ end
22
+
23
+ end