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.
Files changed (75) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +231 -58
  3. data/lib/orats/cli.rb +63 -25
  4. data/lib/orats/commands/common.rb +47 -22
  5. data/lib/orats/commands/{outdated → diff}/compare.rb +5 -4
  6. data/lib/orats/commands/diff/exec.rb +86 -0
  7. data/lib/orats/commands/{outdated → diff}/parse.rb +5 -1
  8. data/lib/orats/commands/inventory.rb +121 -0
  9. data/lib/orats/commands/{play.rb → playbook.rb} +5 -5
  10. data/lib/orats/commands/project/exec.rb +74 -0
  11. data/lib/orats/commands/{new → project}/rails.rb +57 -81
  12. data/lib/orats/commands/{new → project}/server.rb +6 -4
  13. data/lib/orats/templates/auth.rb +26 -481
  14. data/lib/orats/templates/base.rb +74 -716
  15. data/lib/orats/templates/includes/common/LICENSE +22 -0
  16. data/lib/orats/templates/includes/new/rails/.env +43 -0
  17. data/lib/orats/templates/includes/{Gemfile → new/rails/Gemfile} +1 -1
  18. data/lib/orats/templates/includes/new/rails/Procfile +3 -0
  19. data/lib/orats/templates/includes/new/rails/README.md +3 -0
  20. data/lib/orats/templates/includes/{app → new/rails/app}/assets/favicon/favicon_base.png +0 -0
  21. data/lib/orats/templates/includes/new/rails/app/helpers/application_helper.rb +53 -0
  22. data/lib/orats/templates/includes/new/rails/app/models/account.rb +40 -0
  23. data/lib/orats/templates/includes/new/rails/app/views/devise/confirmations/new.html.erb +26 -0
  24. data/lib/orats/templates/includes/new/rails/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  25. data/lib/orats/templates/includes/new/rails/app/views/devise/mailer/reset_password_instructions.html.erb +10 -0
  26. data/lib/orats/templates/includes/new/rails/app/views/devise/mailer/unlock_instructions.html.erb +8 -0
  27. data/lib/orats/templates/includes/new/rails/app/views/devise/passwords/edit.html.erb +28 -0
  28. data/lib/orats/templates/includes/new/rails/app/views/devise/passwords/new.html.erb +26 -0
  29. data/lib/orats/templates/includes/new/rails/app/views/devise/registrations/edit.html.erb +51 -0
  30. data/lib/orats/templates/includes/new/rails/app/views/devise/registrations/new.html.erb +31 -0
  31. data/lib/orats/templates/includes/new/rails/app/views/devise/sessions/new.html.erb +39 -0
  32. data/lib/orats/templates/includes/new/rails/app/views/devise/shared/_links.html.erb +38 -0
  33. data/lib/orats/templates/includes/new/rails/app/views/devise/unlocks/new.html.erb +26 -0
  34. data/lib/orats/templates/includes/new/rails/app/views/layouts/_disqus_comments_snippet.html.erb +19 -0
  35. data/lib/orats/templates/includes/new/rails/app/views/layouts/_disqus_count_snippet.html.erb +12 -0
  36. data/lib/orats/templates/includes/new/rails/app/views/layouts/_flash.html.erb +10 -0
  37. data/lib/orats/templates/includes/new/rails/app/views/layouts/_footer.html.erb +2 -0
  38. data/lib/orats/templates/includes/new/rails/app/views/layouts/_google_analytics_snippet.html.erb +13 -0
  39. data/lib/orats/templates/includes/new/rails/app/views/layouts/_google_analytics_tracker.html.erb +4 -0
  40. data/lib/orats/templates/includes/new/rails/app/views/layouts/_navigation.html.erb +18 -0
  41. data/lib/orats/templates/includes/new/rails/app/views/layouts/_navigation_auth.html.erb +15 -0
  42. data/lib/orats/templates/includes/new/rails/app/views/layouts/_navigation_links.html.erb +3 -0
  43. data/lib/orats/templates/includes/new/rails/app/views/layouts/application.html.erb +48 -0
  44. data/lib/orats/templates/includes/new/rails/app/views/pages/home.html.erb +81 -0
  45. data/lib/orats/templates/includes/new/rails/config/database.yml +19 -0
  46. data/lib/orats/templates/includes/new/rails/config/environments/staging.rb +5 -0
  47. data/lib/orats/templates/includes/new/rails/config/initializers/devise_async.rb +1 -0
  48. data/lib/orats/templates/includes/new/rails/config/initializers/mini_profiler.rb +4 -0
  49. data/lib/orats/templates/includes/new/rails/config/initializers/sidekiq.rb +16 -0
  50. data/lib/orats/templates/includes/new/rails/config/puma.rb +25 -0
  51. data/lib/orats/templates/includes/new/rails/config/secrets.yml +12 -0
  52. data/lib/orats/templates/includes/new/rails/config/sidekiq.yml +5 -0
  53. data/lib/orats/templates/includes/new/rails/config/sitemap.rb +20 -0
  54. data/lib/orats/templates/includes/new/rails/config/whenever.rb +7 -0
  55. data/lib/orats/templates/includes/new/rails/lib/backup/config.rb +116 -0
  56. data/lib/orats/templates/includes/new/rails/lib/backup/models/backup.rb +55 -0
  57. data/lib/orats/templates/includes/new/rails/lib/tasks/orats/backup.rake +18 -0
  58. data/lib/orats/templates/includes/new/rails/lib/tasks/orats/favicon.rake +48 -0
  59. data/lib/orats/templates/includes/new/rails/public/404.html +13 -0
  60. data/lib/orats/templates/includes/new/rails/public/422.html +13 -0
  61. data/lib/orats/templates/includes/new/rails/public/500.html +13 -0
  62. data/lib/orats/templates/includes/new/rails/public/502.html +13 -0
  63. data/lib/orats/templates/includes/new/rails/test/fixtures/accounts.yml +27 -0
  64. data/lib/orats/templates/includes/new/rails/test/models/account_test.rb +46 -0
  65. data/lib/orats/templates/includes/{Galaxyfile → playbook/Galaxyfile} +0 -0
  66. data/lib/orats/templates/includes/playbook/site.yml +53 -0
  67. data/lib/orats/templates/playbook.rb +115 -0
  68. data/lib/orats/version.rb +1 -1
  69. data/test/integration/cli_test.rb +122 -75
  70. data/test/test_helper.rb +16 -8
  71. metadata +63 -14
  72. data/lib/orats/commands/new/ansible.rb +0 -98
  73. data/lib/orats/commands/new/exec.rb +0 -60
  74. data/lib/orats/commands/outdated/exec.rb +0 -46
  75. 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,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Error 404</title>
5
+ <meta charset="utf-8"/>
6
+ <style>
7
+ </style>
8
+ </head>
9
+
10
+ <body>
11
+ <h1>Error 404</h1>
12
+ </body>
13
+ </html>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Error 422</title>
5
+ <meta charset="utf-8"/>
6
+ <style>
7
+ </style>
8
+ </head>
9
+
10
+ <body>
11
+ <h1>Error 422</h1>
12
+ </body>
13
+ </html>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Error 500</title>
5
+ <meta charset="utf-8"/>
6
+ <style>
7
+ </style>
8
+ </head>
9
+
10
+ <body>
11
+ <h1>Error 500</h1>
12
+ </body>
13
+ </html>
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+
5
+ <title>Error 502</title>
6
+ <meta charset="utf-8"/>
7
+ <style>
8
+ </style>
9
+ </head>
10
+ <body>
11
+ <h1>Error 502</h1>
12
+ </body>
13
+ </html>
@@ -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
@@ -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,3 +1,3 @@
1
1
  module Orats
2
- VERSION = '0.6.5'
2
+ VERSION = '0.7.0'
3
3
  end
@@ -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
- def test_new_app
7
- app_name = generate_app_name
7
+ attr_accessor :target_path, :extra_flags
8
8
 
9
- out, err = capture_subprocess_io do
10
- orats "new #{app_name}", flags: ORATS_FLAGS
11
- end
12
-
13
- assert_match /Start your server/, out
9
+ def startup
10
+ @target_path = ''
11
+ @extra_flags = ''
12
+ end
14
13
 
15
- assert_path_exists "#{TEST_PATH}/#{app_name}/inventory"
16
- assert_path_exists "#{TEST_PATH}/#{app_name}/secrets"
14
+ def teardown
15
+ assert_nuked unless @target_path.nil?
16
+ end
17
17
 
18
- assert_nuked app_name
18
+ def test_project
19
+ assert_project ansible: :assert
19
20
  end
20
21
 
21
- def test_new_app_with_auth
22
- app_name = generate_app_name
23
- gemfile_path = "#{TEST_PATH}/#{app_name}/services/#{app_name}/Gemfile"
22
+ def test_project_with_auth
23
+ assert_project '--template auth', ansible: :assert
24
+ end
24
25
 
25
- out, err = capture_subprocess_io do
26
- orats "new #{app_name}", flags: "--auth #{ORATS_FLAGS}"
27
- end
26
+ def test_project_without_ansible
27
+ assert_project '--skip-ansible', ansible: :refute
28
+ end
28
29
 
29
- assert_match /Start your server/, out
30
+ def test_project_with_invalid_template
31
+ @target_path = generate_app_name
32
+ @extra_flags = "#{ORATS_NEW_FLAGS} --template foo"
30
33
 
31
- assert_path_exists "#{TEST_PATH}/#{app_name}/inventory"
32
- assert_path_exists "#{TEST_PATH}/#{app_name}/secrets"
33
- assert_path_exists "#{TEST_PATH}/#{app_name}/services/#{app_name}"
34
+ assert_orats 'project', 'not a valid template'
35
+ end
34
36
 
35
- assert_in_file gemfile_path, /devise/
36
- assert_in_file gemfile_path, /devise-async/
37
- assert_in_file gemfile_path, /pundit/
37
+ def test_inventory
38
+ assert_inventory
39
+ end
38
40
 
39
- assert_nuked app_name
41
+ def test_playbook
42
+ assert_playbook
40
43
  end
41
44
 
42
- def test_new_app_without_extras
43
- app_name = generate_app_name
45
+ def test_diff
46
+ assert_playbook
44
47
 
45
- out, err = capture_subprocess_io do
46
- orats "new #{app_name}", flags: "--skip-extras #{ORATS_FLAGS}"
47
- end
48
+ @target_path = ''
49
+ assert_orats 'diff', 'Compare this version of'
50
+ end
48
51
 
49
- refute_path_exists "#{TEST_PATH}/#{app_name}/inventory"
50
- refute_path_exists "#{TEST_PATH}/#{app_name}/secrets"
51
- refute_path_exists "#{TEST_PATH}/#{app_name}/services/#{app_name}"
52
- assert_path_exists "#{TEST_PATH}/#{app_name}"
52
+ def test_templates
53
+ assert_orats 'templates', '--template auth'
54
+ end
53
55
 
54
- assert_nuked app_name
56
+ def test_version
57
+ assert_orats 'version', 'Orats'
55
58
  end
56
59
 
57
- def test_play
58
- app_name = generate_app_name
60
+ private
59
61
 
60
- out, err = capture_subprocess_io do
61
- orats "play #{app_name}"
62
- end
62
+ def assert_orats(command, match_regex, ansible: nil)
63
+ out, err = capture_orats(command)
63
64
 
64
- assert_match /success/, out
65
- assert_nuked app_name
65
+ assert_match /#{match_regex}/, out
66
+
67
+ assert_or_refute_ansible ansible if ansible
66
68
  end
67
69
 
68
- def test_outdated
69
- app_name = generate_app_name
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
- out, err = capture_subprocess_io do
72
- orats "play #{app_name}"
73
- end
74
- assert_match /success/, out
75
+ assert_orats 'project', 'Start your server', ansible: ansible
75
76
 
76
- out, err = capture_subprocess_io do
77
- orats 'outdated'
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
- assert_nuked app_name
81
+ absolute_target_path << "/services/#{@target_path}"
82
+ assert_project_tests_pass absolute_target_path
82
83
  end
83
84
 
84
- def test_version
85
+ def assert_project_tests_pass(target_path)
85
86
  out, err = capture_subprocess_io do
86
- orats 'version'
87
+ system "cd #{target_path} && bundle exec rake test"
87
88
  end
88
89
 
89
- assert_match /Orats/, out
90
+ log_rails_test_results out
91
+ assert out.include?('0 failures') && out.include?('0 errors'), err
90
92
  end
91
93
 
92
- private
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
- def assert_nuked(app_name, options = {})
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 #{app_name}", flags: options[:flags], answer: 'y'
111
+ orats "nuke #{@target_path}", flags: options[:flags], answer: 'y'
97
112
  end
98
113
 
99
- assert_match /#{app_name}/, out
100
- system 'rm -rf /tmp/orats'
114
+ assert_match /#{@target_path}/, out
115
+ system "rm -rf #{TEST_PATH}"
101
116
  end
102
117
 
103
- def assert_server_started
104
- assert port_taken?
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 assert_path_exists(file_or_dir)
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 refute_path_exists(file_or_dir)
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 assert_in_file(file_path, regex)
116
- out, err = capture_subprocess_io do
117
- system "cat #{file_path}"
118
- end
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
- assert_match regex, out
151
+ assert YAML.load(file)
152
+ rescue Psych::SyntaxError => ex
153
+ assert false, ex.message
154
+ end
121
155
  end
122
156
 
123
- def ensure_port_is_free
124
- skip 'Port 3000 is already in use, aborting test' if port_taken?
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 kill_server(stdout_text)
128
- pid_lines = stdout_text.scan(/started with pid \d+/)
165
+ def log_rails_test_results(out)
166
+ out_lines = out.split("\n")
129
167
 
130
- puma = pid_lines[0].split(' ').last
131
- sidekiq = pid_lines[1].split(' ').last
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
- system "kill -9 #{puma} && kill -9 #{sidekiq}"
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