tane 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.gitignore +4 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +14 -0
  4. data/README.md +22 -0
  5. data/Rakefile +10 -0
  6. data/bin/tane +18 -0
  7. data/lib/tane.rb +64 -0
  8. data/lib/tane/commands/app.rb +5 -0
  9. data/lib/tane/commands/base.rb +15 -0
  10. data/lib/tane/commands/claim.rb +26 -0
  11. data/lib/tane/commands/create.rb +46 -0
  12. data/lib/tane/commands/email.rb +50 -0
  13. data/lib/tane/commands/event.rb +21 -0
  14. data/lib/tane/commands/exec.rb +37 -0
  15. data/lib/tane/commands/help.rb +33 -0
  16. data/lib/tane/commands/init.rb +25 -0
  17. data/lib/tane/commands/login.rb +91 -0
  18. data/lib/tane/commands/logout.rb +25 -0
  19. data/lib/tane/commands/refresh.rb +26 -0
  20. data/lib/tane/commands/signup.rb +43 -0
  21. data/lib/tane/commands/support.rb +37 -0
  22. data/lib/tane/helpers.rb +168 -0
  23. data/lib/tane/helpers/bushido_helper.rb +50 -0
  24. data/lib/tane/helpers/init_helper.rb +116 -0
  25. data/lib/tane/parser.rb +52 -0
  26. data/lib/tane/version.rb +3 -0
  27. data/spec/commands/base_spec.rb +26 -0
  28. data/spec/commands/claim_spec.rb +31 -0
  29. data/spec/commands/email_spec.rb +71 -0
  30. data/spec/commands/event_spec.rb +20 -0
  31. data/spec/commands/exec_spec.rb +18 -0
  32. data/spec/commands/help_spec.rb +12 -0
  33. data/spec/commands/init_spec.rb +27 -0
  34. data/spec/commands/login_spec.rb +81 -0
  35. data/spec/commands/support_spec.rb +59 -0
  36. data/spec/executable_spec.rb +11 -0
  37. data/spec/fixtures/credentials.yml +2 -0
  38. data/spec/helpers/bushido_helper_spec.rb +87 -0
  39. data/spec/helpers/init_helper_spec.rb +127 -0
  40. data/spec/helpers_spec.rb +223 -0
  41. data/spec/spec_helper.rb +15 -0
  42. data/tane.gemspec +29 -0
  43. data/tasks/spec.rake +10 -0
  44. data/tasks/tane.rake +11 -0
  45. metadata +188 -0
@@ -0,0 +1,25 @@
1
+ class Tane::Commands::Logout < Tane::Commands::Base
2
+ class << self
3
+ def process(args)
4
+ if logged_in?
5
+ term.say "Logging out #{username} from this computer..."
6
+ destroy_credentials
7
+ term.say "Finished! All gone! Buh bye!"
8
+ else
9
+ term.say "Couldn't find any Bushido account on this computer... kind of lonesome in that way, what with just you and me and all..."
10
+ end
11
+ end
12
+
13
+
14
+ def help_text
15
+ <<-EOL
16
+ Usage:
17
+
18
+ tane logout
19
+
20
+ Deletes the Bushido credentials from the user's `$HOME` directory.
21
+ EOL
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,26 @@
1
+ class Tane::Commands::Refresh < Tane::Commands::Base
2
+
3
+ class << self
4
+ def process(args)
5
+ if in_rails_dir?
6
+ Tane::Helpers::Init.update_app
7
+ else
8
+ term.say("You have to be in the local rails app's root directory when running `tane update`")
9
+
10
+ exit 1
11
+ end
12
+ end
13
+
14
+ def help_text
15
+ <<-EOL
16
+ Usage:
17
+
18
+ tane refresh
19
+
20
+ Updates the Bushido environment for the local application from the
21
+ latest settings from the Bushido server.
22
+ EOL
23
+ end
24
+ end
25
+
26
+ end
@@ -0,0 +1,43 @@
1
+ class Tane::Commands::Signup < Tane::Commands::Base
2
+ include Tane::Helpers
3
+
4
+ class << self
5
+ def process(args)
6
+ warn_if_credentials
7
+
8
+ email, password = prompt_for_credentials
9
+
10
+ auth_token, errors = Tane::Helpers::Bushido.signup(email, password)
11
+
12
+ if auth_token.nil?
13
+ term.say "Couldn't signup - "
14
+ errors.each do |field|
15
+ term.say "\n"
16
+ field.last.each do |error|
17
+ term.say " #{field.first} #{error} \n"
18
+ end
19
+ end
20
+
21
+ exit
22
+ else
23
+ term.say "Ok, you're signed up as #{email}!"
24
+ end
25
+
26
+ term.say "Done!"
27
+ term.say "Saving credentials"
28
+ save_credentials(email, auth_token)
29
+ end
30
+
31
+
32
+ def help_text
33
+ <<-EOL
34
+ Usage:
35
+
36
+ tane signup
37
+
38
+ Prompts you to signup for a Bushido account.
39
+ EOL
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,37 @@
1
+ class Tane::Commands::Support < Tane::Commands::Base
2
+ class << self
3
+ def process(args)
4
+ message = term.ask("Your message to the Bushido clan: ")
5
+ send_message_to_bushido(message)
6
+ end
7
+
8
+ def send_message_to_bushido(message)
9
+ support_data = {}
10
+ support_data[:source] = "tane"
11
+ support_data[:email] = email_from_credentials_or_prompt
12
+ support_data[:message] = message
13
+
14
+ RestClient.post support_url, support_data
15
+
16
+ term.say("Send the bushido team your message:")
17
+ term.say("\t#{message}")
18
+ term.say("Boy are they gonna be excited to hear from you, #{support_data[:email]}")
19
+ end
20
+
21
+ def email_from_credentials_or_prompt
22
+ return username if logged_in?
23
+ return term.ask("And your email address is: ")
24
+ end
25
+
26
+ def help_text
27
+ <<-EOL
28
+ Usage:
29
+
30
+ tane support
31
+
32
+ Prompts you for a message to send to the Bushido team.
33
+ EOL
34
+ end
35
+ end
36
+
37
+ end
@@ -0,0 +1,168 @@
1
+ require 'erb'
2
+ require 'fileutils'
3
+ require 'yaml'
4
+ require 'rest-client'
5
+ require 'json'
6
+
7
+ module Tane
8
+ module Helpers
9
+ def self.included(mod)
10
+ mod.extend(ClassMethods)
11
+ end
12
+
13
+ module ClassMethods
14
+ def term
15
+ @hl ||= HighLine.new
16
+ end
17
+
18
+ def verbose_say(message)
19
+ term.say(message) if opts.verbose
20
+ end
21
+
22
+ def opts
23
+ @opts ||= OpenStruct.new
24
+ end
25
+
26
+ def bushido_url
27
+ ENV['BUSHIDO_URL'] || "http://bushi.do"
28
+ end
29
+
30
+ def bushido_dir
31
+ "#{ENV['HOME']}/.bushido"
32
+ end
33
+
34
+ def email_template_file_path(template_name)
35
+ "#{email_templates_path}/#{template_name}.yml"
36
+ end
37
+
38
+ def email_templates_path
39
+ ".bushido/emails"
40
+ end
41
+
42
+ def tane_file_path
43
+ ".bushido/tane.yml"
44
+ end
45
+
46
+ def credentials_file_path
47
+ "#{bushido_dir}/credentials.yml"
48
+ end
49
+
50
+ def credentials
51
+ YAML.load(ERB.new(File.read( credentials_file_path )).result)
52
+ end
53
+
54
+ def destroy_credentials
55
+ File.delete(credentials_file_path)
56
+ end
57
+
58
+ def logged_in?
59
+ File.exists?(credentials_file_path)
60
+ end
61
+
62
+ def in_rails_dir?
63
+ Dir.exists?('./rails') || Dir.exists?('./script')
64
+ end
65
+
66
+ def bushido_app_exists?
67
+ File.exists?('.bushido/tane.yml') and File.exists?('.bushido/email.yml')
68
+ end
69
+
70
+ def username
71
+ begin
72
+ return credentials[:username]
73
+ rescue
74
+ term.say "Looks like your Bushido credentials file is corrupted - try deleting ~/.bushido/credentials.yml and then logging in again"
75
+ exit 1
76
+ end
77
+ end
78
+
79
+ def password
80
+ begin
81
+ return credentials[:password]
82
+ rescue
83
+ term.say "Looks like your Bushido credentials file is corrupted - try deleting ~/.bushido/credentials.yml and then logging in again"
84
+ exit 1
85
+ end
86
+ end
87
+
88
+ def make_global_bushido_dir
89
+ FileUtils.mkdir_p bushido_dir
90
+ end
91
+
92
+ def make_app_bushido_dir
93
+ if bushido_app_exists?
94
+ term.say("There's already a Bushido app created for this local rails app. If you'd like to create a new one, please remove the .bushido file in this directory")
95
+
96
+ exit 1
97
+ else
98
+ FileUtils.mkdir_p '.bushido/emails'
99
+ end
100
+ end
101
+
102
+ def authenticate_user
103
+ unless logged_in?
104
+ Tane::Commands::Login.process(:exit => false)
105
+ end
106
+ end
107
+
108
+ def save_credentials(username, password)
109
+ new_credentials = credentials rescue {}
110
+ new_credentials[:username] = username
111
+ new_credentials[:password] = password
112
+ Dir.mkdir(bushido_dir) unless File.exists?(bushido_dir)
113
+ File.open(credentials_file_path, 'w+') { |file| file.puts YAML.dump(new_credentials) }
114
+ end
115
+
116
+ def prompt_for_credentials
117
+ email = term.ask("Enter your email: ") { |email| email }
118
+ password = term.ask("Enter your password: ") { |password| password.echo = false }
119
+ return email.to_s, password.to_s
120
+ end
121
+
122
+ def warn_if_credentials
123
+ if logged_in?
124
+ if term.agree("This computer already has the Bushido user '#{username}' logged in, are you sure you would like to proceed? Y/N")
125
+ term.say("Ok, continuing along like nothing happened")
126
+ else
127
+ term.say("Phew, I think we might have dodged a bullet there!")
128
+ exit
129
+ end
130
+ end
131
+ end
132
+
133
+ def bushido_envs
134
+ YAML.load(ERB.new(File.read( '.bushido/tane.yml' )).result)
135
+ end
136
+
137
+ def base_url
138
+ "#{opts.scheme}://#{opts.host}:#{opts.port}"
139
+ end
140
+
141
+ def data_url
142
+ "#{base_url}/bushido/data"
143
+ end
144
+
145
+ def support_url
146
+ "#{bushido_url}/support/v1/message"
147
+ end
148
+
149
+ def envs_url
150
+ "#{base_url}/bushido/envs"
151
+ end
152
+
153
+ def mail_url
154
+ "#{base_url}/bushido/mail"
155
+ end
156
+
157
+ def post(url, data)
158
+ data['key'] = bushido_envs["BUSHIDO_APP_KEY"]
159
+
160
+ verbose_say("RestClient.put #{url}, #{data.inspect}, :content_type => :json, :accept => :json)")
161
+ result = JSON(RestClient.put url, data, :content_type => :json, :accept => :json)
162
+ verbose_say(result.inspect)
163
+
164
+ result
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,50 @@
1
+ class Tane::Helpers::Bushido
2
+ include Tane::Helpers
3
+
4
+ class << self
5
+ def bushido_url
6
+ ENV['BUSHIDO_URL'] || "http://bushi.do"
7
+ end
8
+
9
+ # Returns nil if credentials are invalid
10
+ # Returns the authentication_token if credentials are valid
11
+ def verify_credentials(email, password)
12
+ begin
13
+ result = JSON(RestClient.get("#{bushido_url}/users/verify.json", { :params => {:email => email, :password => password }}))
14
+ if result['errors'].nil?
15
+ return result['authentication_token'], nil
16
+ else
17
+ return nil, result['errors']
18
+ end
19
+ rescue => e
20
+ return nil, ["Couldn't login with those credentials!"]
21
+ end
22
+ end
23
+
24
+ def signup(email, password)
25
+ term.say "Contacting bushido..."
26
+ term.say "(using #{bushido_url}/users/create.json)"
27
+
28
+ begin
29
+ result = JSON(RestClient.get("#{bushido_url}/users/create.json", { :params => {:email => email, :password => password }}))
30
+
31
+ if result['errors'].nil?
32
+ return result['authentication_token'], nil
33
+ else
34
+ return nil, result['errors']
35
+ end
36
+ rescue => e
37
+ if e.respond_to?(:http_body)
38
+ return nil, [["", [JSON(e.http_body)['error']]]]
39
+ end
40
+
41
+ return nil
42
+ end
43
+ end
44
+
45
+ def authenticate_user(email, password)
46
+ warn_if_credentials
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,116 @@
1
+ class Tane::Helpers::Init
2
+ include Tane::Helpers
3
+
4
+ class << self
5
+ def initialize_app
6
+ term.say "Initializing a local Bushido app for this rails app..."
7
+ if bushido_app_exists?
8
+ update_app
9
+ else
10
+ app = create_app
11
+ make_app_bushido_dir
12
+ save_envs(get_app_envs(app['name']))
13
+ save_emails
14
+ end
15
+
16
+ term.say "Finished successfully! Check out .bushido/tane.yml for the env vars if you care, or .bushido/emails/#{example_email_template.keys.first}.yml to create email templates to test with"
17
+ end
18
+
19
+ def update_app
20
+ save_envs(get_app_envs(bushido_envs['BUSHIDO_NAME']))
21
+ end
22
+
23
+ # TODO: Replace envs_template with values retrieved from Bushido side
24
+ def save_envs(env_vars)
25
+ if File.exists?('.bushido/tane.yml')
26
+ if not term.agree('.bushido/tane.yml already exists! Are you sure you want to overwrite it?')
27
+ return
28
+ end
29
+ end
30
+
31
+ File.open('.bushido/tane.yml', 'w+') { |file| file.puts YAML.dump(envs_template(env_vars)) }
32
+ end
33
+
34
+ def save_emails
35
+ if File.exists?("#{email_templates_path}/#{example_email_template.keys.first}")
36
+ if not term.agree("#{example_email_template.keys.first} already exists! Are you sure you want to overwrite it?")
37
+ return
38
+ end
39
+ end
40
+
41
+ File.open("#{email_templates_path}/#{example_email_template.keys.first}", "w") do |file|
42
+ file.puts email_template_explanation
43
+ file.puts YAML.dump(example_email_template)
44
+ end
45
+ end
46
+
47
+ def envs_template(app_envs)
48
+ envs = {}
49
+ env_var_keys = [
50
+ 'APP_TLD', 'BUNDLE_WITHOUT', 'BUSHIDO_APP', 'BUSHIDO_APP_KEY',
51
+ 'BUSHIDO_DOMAIN', 'BUSHIDO_EVENTS', 'BUSHIDO_HOST', 'BUSHIDO_NAME',
52
+ 'BUSHIDO_PROJECT_NAME', 'BUSHIDO_SALT', 'BUSHIDO_SUBDOMAIN',
53
+ 'B_SQL_DB', 'B_SQL_PASS', 'B_SQL_USER', 'DATABASE_URL',
54
+ 'HOSTING_PLATFORM', 'LANG', 'PUBLIC_URL', 'RACK_ENV',
55
+ 'RAILS_ENV', 'S3_ACCESS_KEY_ID', 'S3_ARN', 'S3_BUCKET',
56
+ 'SHARED_DATABASE_URL', 'S3_PREFIX', 'S3_SECRET_ACCESS_KEY',
57
+ 'SMTP_AUTHENTICATION', 'SMTP_DOMAIN', 'SMTP_PASSWORD',
58
+ 'SMTP_PORT', 'SMTP_SERVER', 'SMTP_TLS', 'SMTP_USER'
59
+ ]
60
+
61
+ env_var_keys.each { |env_var_key| envs[env_var_key] = app_envs[env_var_key] }
62
+ envs
63
+ end
64
+
65
+ def example_email_template
66
+ email = {}
67
+ email['example_email_1'] = {}
68
+
69
+ email['example_email_1']['recipient'] = "postmaster@your-app-name.gobushido.com"
70
+ email['example_email_1']['sender'] = "sender@example.org"
71
+ email['example_email_1']['from'] = "Example Sender <example.sender@example.org>"
72
+ email['example_email_1']['subject'] = "Example subject"
73
+ email['example_email_1']['body-plain'] = "Example plain body with no HTML, but with all the quoted conversations"
74
+ email['example_email_1']['stripped-text'] = "Example stripped text, with no HTML, quotes, or signature"
75
+ email['example_email_1']['stripped-signature'] = "Example stripped signature with no HTML"
76
+ email['example_email_1']['body-html'] = "Example body containing <a href='http://example.org'>HTML</a>, and all of the quotes"
77
+ email['example_email_1']['stripped-html'] = "Example body containing <a href='http://example.org'>HTML</a>, but no quotes or signature "
78
+ email['example_email_1']['attachment-count'] = "How many attachments the email has"
79
+ email['example_email_1']['attachment-1'] = "binary blob of file to be sent as attachment-1"
80
+ email['example_email_1']['timestamp'] = "1323286600"
81
+
82
+ email
83
+ end
84
+
85
+ def email_template_explanation
86
+ explanation=<<-EOL
87
+ # Email format description
88
+ #
89
+ # 'name': - name of the email template (used with `tane email 'name'`)
90
+ # recipient - Recipient of the message as reported by MAIL TO during SMTP chat.
91
+ # sender - Sender of the message as reported by MAIL FROM during SMTP chat. Note- this value may differ from From MIME header.
92
+ # from - Sender of the message as reported by From message header, for example Example Sender <example.sender@example.org>".
93
+ # subject - Subject string.
94
+ # body-plain - Text Version of the email. This field is always present. If the incoming message only has HTML body, this will be the text representation of it.
95
+ # stripped-text - Text Version of the message without quoted parts and signature block (if found).
96
+ # stripped-signature - The Signature block stripped from the plain text message (if found).
97
+ # body-html - HTML version of the message, if message was multipart. Note that all parts of the message will be posted, not just text/html. For instance if a message arrives with "foo" part it will be posted as "body-foo".
98
+ # stripped-html - HTML version of the message, without quoted parts.
99
+ # attachment-count - How many attachments the message has.
100
+ # attachment-x - Attached file ('x' stands for number of the attachment). Attachments are handled as file uploads, encoded as multipart/form-data.
101
+ # timestamp - Number of second passed since January 1, 1970
102
+
103
+
104
+ EOL
105
+ end
106
+
107
+ def create_app
108
+ JSON(RestClient.post("#{bushido_url}/apps.json", {:app => {:url => "https://github.com/Bushido/tane.git", :platform => "developer"}, :authentication_token => password}))
109
+ end
110
+
111
+ def get_app_envs(app_name)
112
+ result = JSON(RestClient.get("#{bushido_url}/apps/#{app_name}.json", {:params => {:authentication_token => password}}))
113
+ result["app"]["full_app_env_vars"]
114
+ end
115
+ end
116
+ end