turbot 0.0.2

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.
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