orats 0.6.5 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
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