tane 0.0.1
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/.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
|