tane 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/Gemfile +14 -0
- data/README.md +22 -0
- data/Rakefile +10 -0
- data/bin/tane +18 -0
- data/lib/tane.rb +64 -0
- data/lib/tane/commands/app.rb +5 -0
- data/lib/tane/commands/base.rb +15 -0
- data/lib/tane/commands/claim.rb +26 -0
- data/lib/tane/commands/create.rb +46 -0
- data/lib/tane/commands/email.rb +50 -0
- data/lib/tane/commands/event.rb +21 -0
- data/lib/tane/commands/exec.rb +37 -0
- data/lib/tane/commands/help.rb +33 -0
- data/lib/tane/commands/init.rb +25 -0
- data/lib/tane/commands/login.rb +91 -0
- data/lib/tane/commands/logout.rb +25 -0
- data/lib/tane/commands/refresh.rb +26 -0
- data/lib/tane/commands/signup.rb +43 -0
- data/lib/tane/commands/support.rb +37 -0
- data/lib/tane/helpers.rb +168 -0
- data/lib/tane/helpers/bushido_helper.rb +50 -0
- data/lib/tane/helpers/init_helper.rb +116 -0
- data/lib/tane/parser.rb +52 -0
- data/lib/tane/version.rb +3 -0
- data/spec/commands/base_spec.rb +26 -0
- data/spec/commands/claim_spec.rb +31 -0
- data/spec/commands/email_spec.rb +71 -0
- data/spec/commands/event_spec.rb +20 -0
- data/spec/commands/exec_spec.rb +18 -0
- data/spec/commands/help_spec.rb +12 -0
- data/spec/commands/init_spec.rb +27 -0
- data/spec/commands/login_spec.rb +81 -0
- data/spec/commands/support_spec.rb +59 -0
- data/spec/executable_spec.rb +11 -0
- data/spec/fixtures/credentials.yml +2 -0
- data/spec/helpers/bushido_helper_spec.rb +87 -0
- data/spec/helpers/init_helper_spec.rb +127 -0
- data/spec/helpers_spec.rb +223 -0
- data/spec/spec_helper.rb +15 -0
- data/tane.gemspec +29 -0
- data/tasks/spec.rake +10 -0
- data/tasks/tane.rake +11 -0
- 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
|
data/lib/tane/helpers.rb
ADDED
@@ -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
|