orats 0.6.5 → 0.7.0
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.
- checksums.yaml +4 -4
- data/README.md +231 -58
- data/lib/orats/cli.rb +63 -25
- data/lib/orats/commands/common.rb +47 -22
- data/lib/orats/commands/{outdated → diff}/compare.rb +5 -4
- data/lib/orats/commands/diff/exec.rb +86 -0
- data/lib/orats/commands/{outdated → diff}/parse.rb +5 -1
- data/lib/orats/commands/inventory.rb +121 -0
- data/lib/orats/commands/{play.rb → playbook.rb} +5 -5
- data/lib/orats/commands/project/exec.rb +74 -0
- data/lib/orats/commands/{new → project}/rails.rb +57 -81
- data/lib/orats/commands/{new → project}/server.rb +6 -4
- data/lib/orats/templates/auth.rb +26 -481
- data/lib/orats/templates/base.rb +74 -716
- data/lib/orats/templates/includes/common/LICENSE +22 -0
- data/lib/orats/templates/includes/new/rails/.env +43 -0
- data/lib/orats/templates/includes/{Gemfile → new/rails/Gemfile} +1 -1
- data/lib/orats/templates/includes/new/rails/Procfile +3 -0
- data/lib/orats/templates/includes/new/rails/README.md +3 -0
- data/lib/orats/templates/includes/{app → new/rails/app}/assets/favicon/favicon_base.png +0 -0
- data/lib/orats/templates/includes/new/rails/app/helpers/application_helper.rb +53 -0
- data/lib/orats/templates/includes/new/rails/app/models/account.rb +40 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/confirmations/new.html.erb +26 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/mailer/reset_password_instructions.html.erb +10 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/mailer/unlock_instructions.html.erb +8 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/passwords/edit.html.erb +28 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/passwords/new.html.erb +26 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/registrations/edit.html.erb +51 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/registrations/new.html.erb +31 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/sessions/new.html.erb +39 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/shared/_links.html.erb +38 -0
- data/lib/orats/templates/includes/new/rails/app/views/devise/unlocks/new.html.erb +26 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_disqus_comments_snippet.html.erb +19 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_disqus_count_snippet.html.erb +12 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_flash.html.erb +10 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_footer.html.erb +2 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_google_analytics_snippet.html.erb +13 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_google_analytics_tracker.html.erb +4 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_navigation.html.erb +18 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_navigation_auth.html.erb +15 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/_navigation_links.html.erb +3 -0
- data/lib/orats/templates/includes/new/rails/app/views/layouts/application.html.erb +48 -0
- data/lib/orats/templates/includes/new/rails/app/views/pages/home.html.erb +81 -0
- data/lib/orats/templates/includes/new/rails/config/database.yml +19 -0
- data/lib/orats/templates/includes/new/rails/config/environments/staging.rb +5 -0
- data/lib/orats/templates/includes/new/rails/config/initializers/devise_async.rb +1 -0
- data/lib/orats/templates/includes/new/rails/config/initializers/mini_profiler.rb +4 -0
- data/lib/orats/templates/includes/new/rails/config/initializers/sidekiq.rb +16 -0
- data/lib/orats/templates/includes/new/rails/config/puma.rb +25 -0
- data/lib/orats/templates/includes/new/rails/config/secrets.yml +12 -0
- data/lib/orats/templates/includes/new/rails/config/sidekiq.yml +5 -0
- data/lib/orats/templates/includes/new/rails/config/sitemap.rb +20 -0
- data/lib/orats/templates/includes/new/rails/config/whenever.rb +7 -0
- data/lib/orats/templates/includes/new/rails/lib/backup/config.rb +116 -0
- data/lib/orats/templates/includes/new/rails/lib/backup/models/backup.rb +55 -0
- data/lib/orats/templates/includes/new/rails/lib/tasks/orats/backup.rake +18 -0
- data/lib/orats/templates/includes/new/rails/lib/tasks/orats/favicon.rake +48 -0
- data/lib/orats/templates/includes/new/rails/public/404.html +13 -0
- data/lib/orats/templates/includes/new/rails/public/422.html +13 -0
- data/lib/orats/templates/includes/new/rails/public/500.html +13 -0
- data/lib/orats/templates/includes/new/rails/public/502.html +13 -0
- data/lib/orats/templates/includes/new/rails/test/fixtures/accounts.yml +27 -0
- data/lib/orats/templates/includes/new/rails/test/models/account_test.rb +46 -0
- data/lib/orats/templates/includes/{Galaxyfile → playbook/Galaxyfile} +0 -0
- data/lib/orats/templates/includes/playbook/site.yml +53 -0
- data/lib/orats/templates/playbook.rb +115 -0
- data/lib/orats/version.rb +1 -1
- data/test/integration/cli_test.rb +122 -75
- data/test/test_helper.rb +16 -8
- metadata +63 -14
- data/lib/orats/commands/new/ansible.rb +0 -98
- data/lib/orats/commands/new/exec.rb +0 -60
- data/lib/orats/commands/outdated/exec.rb +0 -46
- data/lib/orats/templates/play.rb +0 -185
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
Model.new(:backup, 'Backup for the current RAILS_ENV') do
|
|
2
|
+
split_into_chunks_of 10
|
|
3
|
+
compress_with Gzip
|
|
4
|
+
|
|
5
|
+
database PostgreSQL do |db|
|
|
6
|
+
db.sudo_user = ENV['DATABASE_USERNAME']
|
|
7
|
+
# To dump all databases, set `db.name = :all` (or leave blank)
|
|
8
|
+
db.name = ENV['DATABASE_NAME']
|
|
9
|
+
db.username = ENV['DATABASE_USERNAME']
|
|
10
|
+
db.password = ENV['DATABASE_PASSWORD']
|
|
11
|
+
db.host = ENV['DATABASE_HOST']
|
|
12
|
+
db.port = 5432
|
|
13
|
+
db.socket = '/var/run/postgresql'
|
|
14
|
+
#db.skip_tables = ['skip', 'these', 'tables']
|
|
15
|
+
#db.only_tables = ['only', 'these', 'tables']
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# uncomment the block below to archive a specific path
|
|
19
|
+
# this may be useful if you have user supplied content
|
|
20
|
+
|
|
21
|
+
# archive :app_archive do |archive|
|
|
22
|
+
# archive.add File.join(ENV['PROJECT_PATH'], 'public', 'system')
|
|
23
|
+
# end
|
|
24
|
+
|
|
25
|
+
# uncomment the block below and fill in the required information
|
|
26
|
+
# to use S3 to store your backups
|
|
27
|
+
|
|
28
|
+
# don't want to use S3? check out the other available options:
|
|
29
|
+
# http://meskyanichi.github.io/backup/v4/storages/
|
|
30
|
+
|
|
31
|
+
# store_with S3 do |s3|
|
|
32
|
+
# s3.access_key_id = ENV['S3_ACCESS_KEY_ID']
|
|
33
|
+
# s3.secret_access_key = ENV['S3_SECRET_ACCESS_KEY']
|
|
34
|
+
# s3.region = ENV['S3_REGION']
|
|
35
|
+
# s3.bucket = 'backup'
|
|
36
|
+
# s3.path = "/database/#{ENV['RAILS_ENV']}"
|
|
37
|
+
# end
|
|
38
|
+
|
|
39
|
+
ENV['SMTP_ENCRYPTION'].empty? ? mail_encryption = 'none' : mail_encryption = ENV['SMTP_ENCRYPTION']
|
|
40
|
+
|
|
41
|
+
notify_by Mail do |mail|
|
|
42
|
+
mail.on_success = false
|
|
43
|
+
#mail.on_warning = true
|
|
44
|
+
mail.on_failure = true
|
|
45
|
+
mail.from = ENV['ACTION_MAILER_DEFAULT_FROM']
|
|
46
|
+
mail.to = ENV['ACTION_MAILER_DEFAULT_TO']
|
|
47
|
+
mail.address = ENV['SMTP_ADDRESS']
|
|
48
|
+
mail.port = ENV['SMTP_PORT'].to_i
|
|
49
|
+
mail.domain = ENV['SMTP_DOMAIN']
|
|
50
|
+
mail.user_name = ENV['SMTP_USERNAME']
|
|
51
|
+
mail.password = ENV['SMTP_PASSWORD']
|
|
52
|
+
mail.authentication = ENV['SMTP_AUTH']
|
|
53
|
+
mail.encryption = mail_encryption.to_sym
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
namespace :orats do
|
|
2
|
+
desc 'Create a backup of your application for a specific environment'
|
|
3
|
+
task :backup do
|
|
4
|
+
if File.exist?('.env') && File.file?('.env')
|
|
5
|
+
require 'dotenv'
|
|
6
|
+
Dotenv.load
|
|
7
|
+
source_external_env = ''
|
|
8
|
+
else
|
|
9
|
+
source_external_env = '. /etc/default/app_name &&'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# hack'ish way to run the backup command with elevated privileges, it won't prompt for a password on the production
|
|
13
|
+
# server because passwordless sudo has been enabled if you use the ansible setup provided by orats
|
|
14
|
+
system 'sudo whoami'
|
|
15
|
+
|
|
16
|
+
system "#{source_external_env} backup perform -t backup -c '#{File.join('lib', 'backup', 'config.rb')}' --log-path='#{File.join('log')}'"
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
namespace :orats do
|
|
2
|
+
desc 'Create favicons from a single base png'
|
|
3
|
+
task :favicons do
|
|
4
|
+
require 'favicon_maker'
|
|
5
|
+
|
|
6
|
+
FaviconMaker.generate do
|
|
7
|
+
setup do
|
|
8
|
+
template_dir Rails.root.join('app', 'assets', 'favicon')
|
|
9
|
+
output_dir Rails.root.join('public')
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
favicon_base_path = "#{template_dir}/favicon_base.png"
|
|
13
|
+
|
|
14
|
+
unless File.exist?(favicon_base_path)
|
|
15
|
+
puts
|
|
16
|
+
puts 'A base favicon could not be found, make sure one exists at:'
|
|
17
|
+
puts favicon_base_path
|
|
18
|
+
puts
|
|
19
|
+
exit 1
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
from File.basename(favicon_base_path) do
|
|
23
|
+
icon 'speeddial-160x160.png'
|
|
24
|
+
icon 'apple-touch-icon-228x228-precomposed.png'
|
|
25
|
+
icon 'apple-touch-icon-152x152-precomposed.png'
|
|
26
|
+
icon 'apple-touch-icon-144x144-precomposed.png'
|
|
27
|
+
icon 'apple-touch-icon-120x120-precomposed.png'
|
|
28
|
+
icon 'apple-touch-icon-114x114-precomposed.png'
|
|
29
|
+
icon 'apple-touch-icon-76x76-precomposed.png'
|
|
30
|
+
icon 'apple-touch-icon-72x72-precomposed.png'
|
|
31
|
+
icon 'apple-touch-icon-60x60-precomposed.png'
|
|
32
|
+
icon 'apple-touch-icon-57x57-precomposed.png'
|
|
33
|
+
icon 'favicon-196x196.png'
|
|
34
|
+
icon 'favicon-160x160.png'
|
|
35
|
+
icon 'favicon-96x96.png'
|
|
36
|
+
icon 'favicon-64x64.png'
|
|
37
|
+
icon 'favicon-32x32.png'
|
|
38
|
+
icon 'favicon-24x24.png'
|
|
39
|
+
icon 'favicon-16x16.png'
|
|
40
|
+
icon 'favicon.ico', size: '64x64,32x32,24x24,16x16'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
each_icon do |filepath|
|
|
44
|
+
puts "Creating favicon @ #{filepath}"
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
---
|
|
2
|
+
foo:
|
|
3
|
+
id: 1
|
|
4
|
+
email: foo@bar.com
|
|
5
|
+
encrypted_password: passwordisnotreallyencrypted
|
|
6
|
+
role: admin
|
|
7
|
+
created_at: 2012-01-01 01:45:17
|
|
8
|
+
current_sign_in_at: 2013-03-15 11:22:33
|
|
9
|
+
|
|
10
|
+
no_role:
|
|
11
|
+
id: 2
|
|
12
|
+
email: joey@almostcool.com
|
|
13
|
+
encrypted_password: hackthegibson
|
|
14
|
+
created_at: 1995-09-15 08:10:12
|
|
15
|
+
|
|
16
|
+
bad_role:
|
|
17
|
+
id: 3
|
|
18
|
+
email: hello@world.com
|
|
19
|
+
encrypted_password: reallysecure
|
|
20
|
+
role: ahhhh
|
|
21
|
+
created_at: 2011-09-20 10:10:10
|
|
22
|
+
|
|
23
|
+
beep:
|
|
24
|
+
id: 4
|
|
25
|
+
email: beep@beep.com
|
|
26
|
+
encrypted_password: beepbeepbeep
|
|
27
|
+
created_at: 2010-03-6 05:15:45
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
require 'test_helper'
|
|
2
|
+
|
|
3
|
+
class AccountTest < ActiveSupport::TestCase
|
|
4
|
+
def setup
|
|
5
|
+
@account = accounts(:foo)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def teardown
|
|
9
|
+
@account = nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
test 'expect new account' do
|
|
13
|
+
assert @account.valid?
|
|
14
|
+
assert_not_nil @account.email
|
|
15
|
+
assert_not_nil @account.encrypted_password
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
test 'expect guest to be default role' do
|
|
19
|
+
no_role = accounts(:no_role)
|
|
20
|
+
assert_equal 'guest', no_role.role
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
test 'expect invalid role to not save' do
|
|
24
|
+
bad_role = accounts(:bad_role)
|
|
25
|
+
assert_not bad_role.valid?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
test 'expect e-mail to be unique' do
|
|
29
|
+
duplicate = Account.create(email: 'foo@bar.com')
|
|
30
|
+
|
|
31
|
+
assert_not duplicate.valid?
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
test 'expect random password if password is empty' do
|
|
35
|
+
@account.password = ''
|
|
36
|
+
@account.encrypted_password = ''
|
|
37
|
+
@account.save
|
|
38
|
+
|
|
39
|
+
random_password = Account.generate_password
|
|
40
|
+
assert_equal 10, random_password.length
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
test 'expect random password of 20 characters' do
|
|
44
|
+
assert_equal 20, Account.generate_password(20).length
|
|
45
|
+
end
|
|
46
|
+
end
|
|
File without changes
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
- name: ensure all servers are commonly configured
|
|
3
|
+
hosts: all
|
|
4
|
+
sudo: true
|
|
5
|
+
|
|
6
|
+
roles:
|
|
7
|
+
- { role: nickjj.user, tags: [common, user] }
|
|
8
|
+
|
|
9
|
+
- name: ensure database servers are configured
|
|
10
|
+
hosts: database
|
|
11
|
+
sudo: true
|
|
12
|
+
|
|
13
|
+
roles:
|
|
14
|
+
- role: nickjj.security
|
|
15
|
+
tags: [database, security]
|
|
16
|
+
security_ufw_ports:
|
|
17
|
+
- rule: deny
|
|
18
|
+
port: 80
|
|
19
|
+
proto: tcp
|
|
20
|
+
- { role: nickjj.postgres, tags: [database, postgres] }
|
|
21
|
+
|
|
22
|
+
- name: ensure cache servers are configured
|
|
23
|
+
hosts: cache
|
|
24
|
+
sudo: true
|
|
25
|
+
|
|
26
|
+
roles:
|
|
27
|
+
- role: nickjj.security
|
|
28
|
+
tags: [cache, security]
|
|
29
|
+
security_ufw_ports:
|
|
30
|
+
- rule: deny
|
|
31
|
+
port: 80
|
|
32
|
+
proto: tcp
|
|
33
|
+
- { role: DavidWittman.redis, tags: [cache, redis] }
|
|
34
|
+
|
|
35
|
+
- name: ensure app servers are configured
|
|
36
|
+
hosts: app
|
|
37
|
+
sudo: true
|
|
38
|
+
|
|
39
|
+
roles:
|
|
40
|
+
- role: nickjj.security
|
|
41
|
+
tags: [app, security]
|
|
42
|
+
security_ufw_ports:
|
|
43
|
+
- rule: allow
|
|
44
|
+
port: 80
|
|
45
|
+
proto: tcp
|
|
46
|
+
- { role: nickjj.ruby, tags: [app, ruby] }
|
|
47
|
+
- { role: nickjj.nodejs, tags: [app, nodejs] }
|
|
48
|
+
- { role: nickjj.nginx, tags: [app, nginx] }
|
|
49
|
+
- { role: nickjj.rails, tags: [app, rails] }
|
|
50
|
+
- { role: nickjj.whenever, tags: [app, rails] }
|
|
51
|
+
- { role: nickjj.pumacorn, tags: [app, rails] }
|
|
52
|
+
- { role: nickjj.sidekiq, tags: [app, rails] }
|
|
53
|
+
- { role: nickjj.monit, tags: [app, monit] }
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
|
|
3
|
+
# =============================================================================
|
|
4
|
+
# template for generating an orats ansible playbook for ansible 1.6.x
|
|
5
|
+
# =============================================================================
|
|
6
|
+
# view the task list at the bottom of the file
|
|
7
|
+
# -----------------------------------------------------------------------------
|
|
8
|
+
|
|
9
|
+
# -----------------------------------------------------------------------------
|
|
10
|
+
# private functions
|
|
11
|
+
# -----------------------------------------------------------------------------
|
|
12
|
+
def generate_token
|
|
13
|
+
SecureRandom.hex(64)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def method_to_sentence(method)
|
|
17
|
+
method.tr!('_', ' ')
|
|
18
|
+
method[0] = method[0].upcase
|
|
19
|
+
method
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def log_task(message)
|
|
23
|
+
puts
|
|
24
|
+
say_status 'task', "#{method_to_sentence(message.to_s)}:", :yellow
|
|
25
|
+
puts '-'*80, ''; sleep 0.25
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def git_commit(message)
|
|
29
|
+
git add: '-A'
|
|
30
|
+
git commit: "-m '#{message}'"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def git_config(field)
|
|
34
|
+
command = "git config --global user.#{field}"
|
|
35
|
+
git_field_value = run(command, capture: true).gsub("\n", '')
|
|
36
|
+
default_value = "YOUR_#{field.upcase}"
|
|
37
|
+
|
|
38
|
+
git_field_value.to_s.empty? ? default_value : git_field_value
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def copy_from_local_gem(source, dest = '')
|
|
42
|
+
dest = source if dest.empty?
|
|
43
|
+
|
|
44
|
+
base_path = "#{File.expand_path File.dirname(__FILE__)}/includes/playbook"
|
|
45
|
+
|
|
46
|
+
run "mkdir -p #{File.dirname(dest)}" unless Dir.exist?(File.dirname(dest))
|
|
47
|
+
run "cp -f #{base_path}/#{source} #{dest}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# ---
|
|
51
|
+
|
|
52
|
+
def delete_generated_rails_code
|
|
53
|
+
log_task __method__
|
|
54
|
+
|
|
55
|
+
run 'rm -rf * .git .gitignore'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def add_playbook_directory
|
|
59
|
+
log_task __method__
|
|
60
|
+
|
|
61
|
+
run "mkdir -p #{app_name}"
|
|
62
|
+
run "mv #{app_name}/* ."
|
|
63
|
+
run "rm -rf #{app_name}"
|
|
64
|
+
git :init
|
|
65
|
+
git_commit 'Initial commit'
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def add_license
|
|
69
|
+
log_task __method__
|
|
70
|
+
|
|
71
|
+
author_name = git_config 'name'
|
|
72
|
+
author_email = git_config 'email'
|
|
73
|
+
|
|
74
|
+
copy_from_local_gem '../common/LICENSE', 'LICENSE'
|
|
75
|
+
gsub_file 'LICENSE', 'Time.now.year', Time.now.year.to_s
|
|
76
|
+
gsub_file 'LICENSE', 'author_name', author_name
|
|
77
|
+
gsub_file 'LICENSE', 'author_email', author_email
|
|
78
|
+
git_commit 'Add MIT license'
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def add_main_playbook
|
|
82
|
+
log_task __method__
|
|
83
|
+
|
|
84
|
+
copy_from_local_gem 'site.yml', 'site.yml'
|
|
85
|
+
git_commit 'Add the main playbook'
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def remove_unused_files_from_git
|
|
89
|
+
log_task __method__
|
|
90
|
+
|
|
91
|
+
git add: '-u'
|
|
92
|
+
git_commit 'Remove unused files'
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def log_complete
|
|
96
|
+
puts
|
|
97
|
+
say_status 'success', "\e[1m\Everything has been setup successfully\e[0m", :cyan
|
|
98
|
+
puts
|
|
99
|
+
say_status 'question', 'Are most of your apps similar?', :yellow
|
|
100
|
+
say_status 'answer', 'You only need to generate one playbook and you just did', :white
|
|
101
|
+
say_status 'answer', 'Use the inventory in each project to customize certain things', :white
|
|
102
|
+
puts
|
|
103
|
+
say_status 'question', 'Are you new to ansible?', :yellow
|
|
104
|
+
say_status 'answer', 'http://docs.ansible.com/intro_getting_started.html', :white
|
|
105
|
+
puts
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# ---
|
|
109
|
+
|
|
110
|
+
delete_generated_rails_code
|
|
111
|
+
add_playbook_directory
|
|
112
|
+
add_license
|
|
113
|
+
add_main_playbook
|
|
114
|
+
remove_unused_files_from_git
|
|
115
|
+
log_complete
|
data/lib/orats/version.rb
CHANGED
|
@@ -1,135 +1,182 @@
|
|
|
1
|
+
require 'yaml'
|
|
1
2
|
require_relative '../test_helper'
|
|
2
3
|
|
|
3
4
|
class TestCLI < Minitest::Test
|
|
4
5
|
include Orats::Test
|
|
5
6
|
|
|
6
|
-
|
|
7
|
-
app_name = generate_app_name
|
|
7
|
+
attr_accessor :target_path, :extra_flags
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
assert_match /Start your server/, out
|
|
9
|
+
def startup
|
|
10
|
+
@target_path = ''
|
|
11
|
+
@extra_flags = ''
|
|
12
|
+
end
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
def teardown
|
|
15
|
+
assert_nuked unless @target_path.nil?
|
|
16
|
+
end
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
def test_project
|
|
19
|
+
assert_project ansible: :assert
|
|
19
20
|
end
|
|
20
21
|
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
def test_project_with_auth
|
|
23
|
+
assert_project '--template auth', ansible: :assert
|
|
24
|
+
end
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
def test_project_without_ansible
|
|
27
|
+
assert_project '--skip-ansible', ansible: :refute
|
|
28
|
+
end
|
|
28
29
|
|
|
29
|
-
|
|
30
|
+
def test_project_with_invalid_template
|
|
31
|
+
@target_path = generate_app_name
|
|
32
|
+
@extra_flags = "#{ORATS_NEW_FLAGS} --template foo"
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
assert_path_exists "#{TEST_PATH}/#{app_name}/services/#{app_name}"
|
|
34
|
+
assert_orats 'project', 'not a valid template'
|
|
35
|
+
end
|
|
34
36
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
37
|
+
def test_inventory
|
|
38
|
+
assert_inventory
|
|
39
|
+
end
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
def test_playbook
|
|
42
|
+
assert_playbook
|
|
40
43
|
end
|
|
41
44
|
|
|
42
|
-
def
|
|
43
|
-
|
|
45
|
+
def test_diff
|
|
46
|
+
assert_playbook
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
@target_path = ''
|
|
49
|
+
assert_orats 'diff', 'Compare this version of'
|
|
50
|
+
end
|
|
48
51
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
assert_path_exists "#{TEST_PATH}/#{app_name}"
|
|
52
|
+
def test_templates
|
|
53
|
+
assert_orats 'templates', '--template auth'
|
|
54
|
+
end
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
def test_version
|
|
57
|
+
assert_orats 'version', 'Orats'
|
|
55
58
|
end
|
|
56
59
|
|
|
57
|
-
|
|
58
|
-
app_name = generate_app_name
|
|
60
|
+
private
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
end
|
|
62
|
+
def assert_orats(command, match_regex, ansible: nil)
|
|
63
|
+
out, err = capture_orats(command)
|
|
63
64
|
|
|
64
|
-
assert_match
|
|
65
|
-
|
|
65
|
+
assert_match /#{match_regex}/, out
|
|
66
|
+
|
|
67
|
+
assert_or_refute_ansible ansible if ansible
|
|
66
68
|
end
|
|
67
69
|
|
|
68
|
-
def
|
|
69
|
-
|
|
70
|
+
def assert_project(flags = '', ansible: nil)
|
|
71
|
+
@target_path = generate_app_name
|
|
72
|
+
absolute_target_path = "#{TEST_PATH}/#{@target_path}"
|
|
73
|
+
@extra_flags = "#{ORATS_NEW_FLAGS} #{flags}"
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
orats "play #{app_name}"
|
|
73
|
-
end
|
|
74
|
-
assert_match /success/, out
|
|
75
|
+
assert_orats 'project', 'Start your server', ansible: ansible
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
if ansible == :assert
|
|
78
|
+
assert_ansible_yaml "#{absolute_target_path}/inventory/group_vars/all.yml"
|
|
78
79
|
end
|
|
79
|
-
assert_match /Comparing this version of/, out
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
absolute_target_path << "/services/#{@target_path}"
|
|
82
|
+
assert_project_tests_pass absolute_target_path
|
|
82
83
|
end
|
|
83
84
|
|
|
84
|
-
def
|
|
85
|
+
def assert_project_tests_pass(target_path)
|
|
85
86
|
out, err = capture_subprocess_io do
|
|
86
|
-
|
|
87
|
+
system "cd #{target_path} && bundle exec rake test"
|
|
87
88
|
end
|
|
88
89
|
|
|
89
|
-
|
|
90
|
+
log_rails_test_results out
|
|
91
|
+
assert out.include?('0 failures') && out.include?('0 errors'), err
|
|
90
92
|
end
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
def assert_inventory
|
|
95
|
+
@target_path = generate_app_name
|
|
96
|
+
@extra_flags = '--skip-galaxy'
|
|
97
|
+
|
|
98
|
+
assert_orats 'inventory', 'success'
|
|
99
|
+
assert_ansible_yaml "#{TEST_PATH}/#{@target_path}/inventory/group_vars/all.yml"
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def assert_playbook
|
|
103
|
+
@target_path = generate_app_name
|
|
93
104
|
|
|
94
|
-
|
|
105
|
+
assert_orats 'playbook', 'success'
|
|
106
|
+
assert_ansible_yaml "#{TEST_PATH}/#{@target_path}/site.yml"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def assert_nuked(options = {})
|
|
95
110
|
out, err = capture_subprocess_io do
|
|
96
|
-
orats "nuke #{
|
|
111
|
+
orats "nuke #{@target_path}", flags: options[:flags], answer: 'y'
|
|
97
112
|
end
|
|
98
113
|
|
|
99
|
-
assert_match /#{
|
|
100
|
-
system
|
|
114
|
+
assert_match /#{@target_path}/, out
|
|
115
|
+
system "rm -rf #{TEST_PATH}"
|
|
101
116
|
end
|
|
102
117
|
|
|
103
|
-
def
|
|
104
|
-
|
|
118
|
+
def assert_in_file(file_path, match_regex)
|
|
119
|
+
file_contents = `cat #{file_path}`
|
|
120
|
+
assert_match /#{match_regex}/, file_contents
|
|
105
121
|
end
|
|
106
122
|
|
|
107
|
-
def
|
|
123
|
+
def assert_path(file_or_dir)
|
|
108
124
|
assert File.exists?(file_or_dir), "Expected path '#{file_or_dir}' to exist"
|
|
109
125
|
end
|
|
110
126
|
|
|
111
|
-
def
|
|
127
|
+
def refute_path(file_or_dir)
|
|
112
128
|
refute File.exists?(file_or_dir), "Expected path '#{file_or_dir}' to exist"
|
|
113
129
|
end
|
|
114
130
|
|
|
115
|
-
def
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
131
|
+
def assert_or_refute_ansible(assert_or_refute)
|
|
132
|
+
absolute_target_path = "#{TEST_PATH}/#{@target_path}"
|
|
133
|
+
|
|
134
|
+
assert_path "#{absolute_target_path}/services"
|
|
135
|
+
send("#{assert_or_refute.to_s}_path",
|
|
136
|
+
"#{absolute_target_path}/inventory")
|
|
137
|
+
send("#{assert_or_refute.to_s}_path",
|
|
138
|
+
"#{absolute_target_path}/secrets")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def assert_ansible_yaml(file_path)
|
|
142
|
+
begin
|
|
143
|
+
file = IO.read(file_path)
|
|
144
|
+
invalid_ansible_yaml = file.match(/^([^#].\w): {/)
|
|
145
|
+
|
|
146
|
+
if invalid_ansible_yaml
|
|
147
|
+
assert false, "Invalid yaml syntax found near:\n #{invalid_ansible_yaml}\n\nYou need to include quotes around values that start with jinja template tags:\n Example, foo: '{{ bar }}'"
|
|
148
|
+
return
|
|
149
|
+
end
|
|
119
150
|
|
|
120
|
-
|
|
151
|
+
assert YAML.load(file)
|
|
152
|
+
rescue Psych::SyntaxError => ex
|
|
153
|
+
assert false, ex.message
|
|
154
|
+
end
|
|
121
155
|
end
|
|
122
156
|
|
|
123
|
-
def
|
|
124
|
-
|
|
157
|
+
def capture_orats(command)
|
|
158
|
+
out, err = capture_subprocess_io do
|
|
159
|
+
orats "#{command} #{@target_path}", flags: @extra_flags
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
[out, err]
|
|
125
163
|
end
|
|
126
164
|
|
|
127
|
-
def
|
|
128
|
-
|
|
165
|
+
def log_rails_test_results(out)
|
|
166
|
+
out_lines = out.split("\n")
|
|
129
167
|
|
|
130
|
-
|
|
131
|
-
|
|
168
|
+
out_lines.delete_if do |line|
|
|
169
|
+
line.include?('Sidekiq') || line.start_with?('.') ||
|
|
170
|
+
line.include?('Running') || line.include?('Run options') ||
|
|
171
|
+
line.empty?
|
|
172
|
+
end
|
|
132
173
|
|
|
133
|
-
|
|
174
|
+
puts
|
|
175
|
+
puts '-'*80
|
|
176
|
+
puts 'Results of running `bundle exec rake test` on the generated test app:'
|
|
177
|
+
puts '-'*80
|
|
178
|
+
puts out_lines.join("\n\n").rstrip
|
|
179
|
+
puts '-'*80
|
|
180
|
+
puts
|
|
134
181
|
end
|
|
135
182
|
end
|