subspace 2.1.2 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd87407fb11ec6c94c168ebd5b9352df4f5d548d58680d8d55f48d10b358ebf2
4
- data.tar.gz: b2ee02cff26d17e5a7ec2f09e3dbbee0c9faf9884bf28d2800419729363cb319
3
+ metadata.gz: 1a7d67442d9d8f4d6e936c27e62bfa3975b2a78a68f2cbee3684163a93cafab9
4
+ data.tar.gz: 5779b928d53d165975310a59b362b4b092388f495bb15d1da7c28602fddfe2e4
5
5
  SHA512:
6
- metadata.gz: fbb758b5dbefb0df98314cb8001baa09eab07f7586e5377441c9f453a70cce025abf0ee3aa0a09d36fb99ec437abe3565372f3a578dc6e361278e12a315397af
7
- data.tar.gz: 57bdb1094df5925b3594e198e91fe47b0f1971c7cacb0e05f2b474a2b72d81a0d5e5be216e9a998fcdf03ba62cc605d61005ce468780d227d4a805aef8decd83
6
+ metadata.gz: b71b2a2f3b4b42a61a65436ed888a735ec6d5d6d9ee17366843453ae016a594ede442d7750c1f191264166a9f58db71cb9a3435058f4fcb60fa66e3188a27996
7
+ data.tar.gz: 43cd84e03cd768befea33217d5d7440d1ac83c2cdd5e87e0b2ba2d1920dd9c1e24271274fd2c4c0be522f177e9f71cd976bd4c92160e379d670876bde77239e8
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.4.4
1
+ 2.6.3
data/.travis.yml CHANGED
@@ -1,4 +1,4 @@
1
- sudo: false
1
+ become: false
2
2
  language: ruby
3
3
  rvm:
4
4
  - 2.3.1
data/CHANGELOG.md CHANGED
@@ -10,10 +10,14 @@ This project attempts to follow [semantic versioning](https://semver.org/)
10
10
  * Not working on OSX - macs don't read from /etc/profile.d/
11
11
  * Stops showing color if you `sudo su`
12
12
 
13
+ ## 2.2.0
14
+ * Add maintenance_mode command
15
+ * Add ppa:ondrej/nginx repo in common role for TLS 1.3 and nginx support
16
+
13
17
  ## 2.1.2
14
18
  * bug fixes
15
19
  * PostgreSQL database server works for version > 10
16
- * New LetsEncrypt/NGINX servers get the correct file from the certbot repo
20
+ * New LetsEncrypt/NGINX servers get the correct file from the certbot repo
17
21
 
18
22
  ## 2.1.1
19
23
  * bug fixes
data/README.md CHANGED
@@ -69,6 +69,18 @@ At the time of this writing, we pass through the `ansible-playbook` "limit" opti
69
69
 
70
70
  e.g. To run only on the host "prod-web1": `subspace maintain production --limit=prod-web1`
71
71
 
72
+ ### `subspace maintenance_mode <environment> --on`
73
+
74
+ This sets up nginx to return all requests as 503 and serve only the
75
+ static page at `/u/apps/{{project_name}}/current/public/maintenance.html`
76
+ which must be checked into your project and deployed to the server.
77
+
78
+ `--on` and `--off`, defaults to off.
79
+
80
+ Only works for hosts using the `nginx` role, but you can pass in your entire environment. Running it on worker servers won't hurt anything.
81
+
82
+ MUST be turned off manually by running `subspace maintenance_mode <environment> --off`, even a deploy will not disable maintenance mode.
83
+
72
84
  #### Tagged roles
73
85
 
74
86
  Role | Tags | Comment
@@ -0,0 +1,5 @@
1
+ ---
2
+ - hosts: "{{ maintenance_hosts }}"
3
+ become: true
4
+ roles:
5
+ - nginx-maintenance
@@ -71,6 +71,10 @@
71
71
  tags:
72
72
  - maintenance
73
73
 
74
+ - name: Add ppa:ondrej/nginx apt repository for TLS 1.3
75
+ apt_repository:
76
+ repo: ppa:ondrej/nginx
77
+
74
78
  - name: apt-get update
75
79
  apt: update_cache=yes cache_valid_time=86400
76
80
  become: true
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  - name: apache restart
3
3
  service: name=apache2 state=restarted
4
- sudo: yes
4
+ become: yes
5
5
 
6
6
  - name: nginx restart
7
7
  service: name=nginx state=restarted
8
- sudo: yes
8
+ become: yes
@@ -2,5 +2,5 @@
2
2
  dependencies:
3
3
  - {
4
4
  role: ANXS.mysql,
5
- sudo: true
5
+ become: true
6
6
  }
@@ -3,10 +3,10 @@
3
3
  template:
4
4
  src: mysql_database.yml
5
5
  dest: /u/apps/{{project_name}}/shared/config/database.yml
6
- sudo: true
6
+ become: true
7
7
  sudo_user: "{{deploy_user}}"
8
8
 
9
9
  - name: Install mysql2 gem dependencies
10
10
  apt:
11
11
  name: libmysqlclient-dev
12
- sudo: true
12
+ become: true
@@ -3,6 +3,6 @@
3
3
  # dependencies:
4
4
  # - {
5
5
  # role: ANXS.mysql,
6
- # sudo: true
6
+ # become: true
7
7
  # }
8
8
 
@@ -2,4 +2,4 @@
2
2
  - name: Install mysql2 gem dependencies
3
3
  apt:
4
4
  name: libmysqlclient-dev
5
- sudo: true
5
+ become: true
@@ -3,21 +3,21 @@
3
3
  apt_repository:
4
4
  repo: deb http://apt.newrelic.com/debian/ newrelic non-free
5
5
  state: present
6
- sudo: true
6
+ become: true
7
7
 
8
8
  - name: Add New Relic apt key
9
9
  apt_key:
10
10
  url: https://download.newrelic.com/548C16BF.gpg
11
11
  state: present
12
- sudo: true
12
+ become: true
13
13
 
14
14
  - name: Install New Relic server agent
15
15
  apt:
16
16
  pkg: newrelic-sysmond
17
17
  state: present
18
18
  update_cache: true
19
- sudo: true
19
+ become: true
20
20
 
21
21
  - shell: "nrsysmond-config --set license_key={{newrelic_licence}}"
22
- sudo: true
22
+ become: true
23
23
  notify: start newrelic agent
@@ -0,0 +1,33 @@
1
+ ---
2
+ - name: Check that /opt/subspace/ exists
3
+ stat:
4
+ path: /opt/subspace/
5
+ register: subspace_dir
6
+ tags:
7
+ - maintenance_on
8
+ - maintenance_off
9
+
10
+ - name: Check that /u/apps/{{project_name}}/current/public/maintenance.html exists
11
+ stat:
12
+ path: /u/apps/{{project_name}}/current/public/maintenance.html
13
+ register: app_maintenance_html
14
+ tags:
15
+ - maintenance_on
16
+
17
+ - name: Move maintenance.html to /opt/subspace
18
+ command: cp /u/apps/{{project_name}}/current/public/maintenance.html /opt/subspace/maintenance.html
19
+ args:
20
+ creates: /opt/subspace/maintenance.html
21
+ when:
22
+ - app_maintenance_html.stat.exists == True
23
+ - subspace_dir.stat.exists == True
24
+ tags:
25
+ - maintenance_on
26
+
27
+ - name: Remove /opt/subspace/maintenance.html
28
+ file:
29
+ path: /opt/subspace/maintenance.html
30
+ state: absent
31
+ when: subspace_dir.stat.exists == True
32
+ tags:
33
+ - maintenance_off
@@ -2,6 +2,9 @@
2
2
  try_files $uri/index.html $uri @app;
3
3
 
4
4
  location @app {
5
+ if (-f /opt/subspace/maintenance.html) {
6
+ return 503;
7
+ }
5
8
  proxy_pass http://app;
6
9
  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
7
10
  proxy_set_header X-Forwarded-Proto $app_proto;
@@ -20,7 +23,11 @@
20
23
  }
21
24
  {% endif %}
22
25
 
23
- error_page 500 502 503 504 /500.html;
26
+ error_page 500 502 504 /500.html;
27
+ error_page 503 /maintenance.html;
28
+ location /maintenance.html {
29
+ root /opt/subspace;
30
+ }
24
31
  client_max_body_size {{client_max_body_size}};
25
32
  keepalive_timeout 10;
26
33
 
@@ -5,23 +5,23 @@
5
5
  - command: tar xzf /tmp/remote_syslog.tar.gz chdir=/tmp/ creates=/usr/bin/remote_syslog
6
6
 
7
7
  - command: mv /tmp/remote_syslog/remote_syslog /usr/bin/remote_syslog creates=/usr/bin/remote_syslog
8
- sudo: true
8
+ become: true
9
9
 
10
10
  - file: path=/usr/bin/remote_syslog owner=root group=root mode=0755
11
- sudo: true
11
+ become: true
12
12
 
13
13
  - command: wget -O /etc/init.d/remote_syslog https://raw.githubusercontent.com/papertrail/remote_syslog2/v0.13/examples/remote_syslog.init.d creates=/etc/init.d/remote_syslog
14
- sudo: true
14
+ become: true
15
15
 
16
16
  - file: path=/etc/init.d/remote_syslog owner=root group=root mode=0755
17
- sudo: true
17
+ become: true
18
18
 
19
19
  - file: path=/tmp/remote_syslog/ state=absent
20
20
 
21
21
  - file: path=/tmp/remote_syslog.tar.gz state=absent
22
22
 
23
23
  - service: name=remote_syslog state=restarted enabled=yes
24
- sudo: true
24
+ become: true
25
25
 
26
26
  - template: src=log_files.yml dest=/etc/log_files.yml owner=root group=root mode=0644
27
- sudo: true
27
+ become: true
@@ -3,7 +3,7 @@
3
3
  # [repository]: http://www.postgresql.org/download/
4
4
  - name: Adding APT repository key
5
5
  when: ansible_os_family == 'Debian'
6
- sudo: yes
6
+ become: yes
7
7
  apt_key:
8
8
  id: ACCC4CF8
9
9
  url: https://www.postgresql.org/media/keys/ACCC4CF8.asc
@@ -14,7 +14,7 @@
14
14
 
15
15
  - name: Add PostgreSQL official APT repository
16
16
  when: ansible_os_family == 'Debian'
17
- sudo: yes
17
+ become: yes
18
18
  apt_repository:
19
19
  repo: "deb http://apt.postgresql.org/pub/repos/apt/ {{ansible_distribution_release}}-pgdg main"
20
20
  tags:
@@ -24,7 +24,7 @@
24
24
 
25
25
  - name: Install PostgreSQL
26
26
  when: ansible_os_family == 'Debian'
27
- sudo: yes
27
+ become: yes
28
28
  apt:
29
29
  name: "postgresql-client-{{postgresql_version}}"
30
30
  state: present
@@ -37,7 +37,7 @@
37
37
 
38
38
  - name: Install dependencies for the Ansible module
39
39
  when: ansible_os_family == 'Debian'
40
- sudo: yes
40
+ become: yes
41
41
  apt:
42
42
  name: "{{item}}"
43
43
  state: latest
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  - name: postgresql restart
3
3
  service: name=postgresql state=restarted
4
- sudo: yes
4
+ become: yes
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  - name: restart postgresql
3
- sudo: yes
3
+ become: yes
4
4
  service: name=postgresql state=restarted
5
5
 
6
6
  - name: reload postgresql
7
- sudo: yes
8
- service: name=postgresql state=reloaded
7
+ become: yes
8
+ service: name=postgresql state=reloaded
@@ -1,7 +1,7 @@
1
1
  ---
2
2
 
3
3
  - name: Create the necessary directories
4
- sudo: yes
4
+ become: yes
5
5
  file:
6
6
  dest: "{{item}}"
7
7
  state: directory
@@ -18,7 +18,7 @@
18
18
  - conf
19
19
 
20
20
  - name: Configure PostgreSQL
21
- sudo: yes
21
+ become: yes
22
22
  template:
23
23
  src: "{{item}}"
24
24
  dest: "{{postgresql_conf_directory}}/{{item}}"
@@ -33,7 +33,7 @@
33
33
  - conf
34
34
 
35
35
  - name: Configure PostgreSQL (authentication)
36
- sudo: yes
36
+ become: yes
37
37
  template:
38
38
  src: pg_hba.conf
39
39
  dest: "{{postgresql_hba_file}}"
@@ -44,7 +44,7 @@
44
44
  - conf
45
45
 
46
46
  - name: Configure PostgreSQL (ident)
47
- sudo: yes
47
+ become: yes
48
48
  template:
49
49
  src: pg_ident.conf
50
50
  dest: "{{postgresql_ident_file}}"
@@ -6,7 +6,7 @@
6
6
 
7
7
  - name: Install development headers
8
8
  when: postgresql_dev_headers == True
9
- sudo: yes
9
+ become: yes
10
10
  apt:
11
11
  name: libpq-dev
12
12
  tags:
@@ -21,7 +21,7 @@
21
21
 
22
22
  - name: Install PostgreSQL contribs
23
23
  when: postgresql_contrib
24
- sudo: yes
24
+ become: yes
25
25
  apt:
26
26
  name: "postgresql-contrib-{{postgresql_version}}"
27
27
  notify: restart postgresql
@@ -36,7 +36,7 @@
36
36
 
37
37
  - name: Add postgis extensions
38
38
  when: postgresql_postgis
39
- sudo: yes
39
+ become: yes
40
40
  apt:
41
41
  name: "{{item}}"
42
42
  with_items:
@@ -5,7 +5,7 @@
5
5
 
6
6
  - name: Adding APT repository key
7
7
  when: ansible_os_family == 'Debian'
8
- sudo: yes
8
+ become: yes
9
9
  apt_key:
10
10
  id: ACCC4CF8
11
11
  url: https://www.postgresql.org/media/keys/ACCC4CF8.asc
@@ -16,7 +16,7 @@
16
16
 
17
17
  - name: Add PostgreSQL official APT repository
18
18
  when: ansible_os_family == 'Debian'
19
- sudo: yes
19
+ become: yes
20
20
  apt_repository:
21
21
  repo: "deb http://apt.postgresql.org/pub/repos/apt/ {{ansible_distribution_release}}-pgdg main"
22
22
  tags:
@@ -26,7 +26,7 @@
26
26
 
27
27
  - name: Install PostgreSQL
28
28
  when: ansible_os_family == 'Debian'
29
- sudo: yes
29
+ become: yes
30
30
  apt:
31
31
  name: "postgresql-{{postgresql_version}}"
32
32
  state: present
@@ -39,7 +39,7 @@
39
39
 
40
40
  - name: Install dependencies for the Ansible module
41
41
  when: ansible_os_family == 'Debian'
42
- sudo: yes
42
+ become: yes
43
43
  apt:
44
44
  name: "{{item}}"
45
45
  state: latest
data/lib/subspace/cli.rb CHANGED
@@ -13,6 +13,7 @@ require 'subspace/commands/provision'
13
13
  require 'subspace/commands/ssh'
14
14
  require 'subspace/commands/vars'
15
15
  require 'subspace/commands/maintain'
16
+ require 'subspace/commands/maintenance_mode.rb'
16
17
 
17
18
  class Subspace::Cli
18
19
  include Commander::Methods
@@ -105,6 +106,19 @@ class Subspace::Cli
105
106
  c.when_called Subspace::Commands::Maintain
106
107
  end
107
108
 
109
+ command :maintenance_mode do |c, args|
110
+ c.syntax = 'subspace maintenance_mode [options]'
111
+ c.summary = 'Turns on or off maintenance mode'
112
+ c.description = ''
113
+ c.option "-i", "--private-key PRIVATE-KEY", "Alias for private-key"
114
+ c.option "--on", "Turns on maintenance mode"
115
+ c.option "--off", "Turns off maintenance mode"
116
+ Subspace::Commands::MaintenanceMode::PASS_THROUGH_PARAMS.each do |param_name|
117
+ c.option "--#{param_name} #{param_name.upcase}", "Passed directly through to ansible-playbook command"
118
+ end
119
+ c.when_called Subspace::Commands::MaintenanceMode
120
+ end
121
+
108
122
  run!
109
123
  end
110
124
  end
@@ -53,6 +53,23 @@ module Subspace
53
53
  return answer.downcase.start_with? "y"
54
54
  end
55
55
 
56
+ def pass_through_params
57
+ ansible_options = []
58
+ self.class::PASS_THROUGH_PARAMS.each do |param_name|
59
+ x = param_name.split('-')[1..-1].map(&:upcase).join('_')
60
+ hash_key = (param_name.gsub('-', '_') + (x == '' ? '' : "_#{x}")).to_sym
61
+ value = @options.__hash__[hash_key]
62
+ if value
63
+ if param_name.length > 1
64
+ ansible_options += ["--#{param_name}", value]
65
+ else
66
+ ansible_options += ["-#{param_name}", value]
67
+ end
68
+ end
69
+ end
70
+
71
+ ansible_options
72
+ end
56
73
  end
57
74
  end
58
75
  end
@@ -41,7 +41,7 @@ class Subspace::Commands::Bootstrap < Subspace::Commands::Base
41
41
  "--become",
42
42
  "-vvvv"
43
43
  ]
44
- cmd = add_pass_through_params cmd
44
+ cmd = cmd | pass_through_params
45
45
  bootstrap_command cmd
46
46
  end
47
47
 
@@ -51,16 +51,4 @@ class Subspace::Commands::Bootstrap < Subspace::Commands::Base
51
51
  end
52
52
  ansible_command *cmd
53
53
  end
54
-
55
- def add_pass_through_params(cmd)
56
- PASS_THROUGH_PARAMS.each do |param_name|
57
- x = param_name.split('-')[1..-1].map(&:upcase).join('_')
58
- hash_key = (param_name.gsub('-', '_') + (x == '' ? '' : "_#{x}")).to_sym
59
- value = @options.__hash__[hash_key]
60
- if value
61
- cmd += ["--#{param_name}", value]
62
- end
63
- end
64
- cmd
65
- end
66
54
  end
@@ -9,14 +9,7 @@ class Subspace::Commands::Maintain < Subspace::Commands::Base
9
9
 
10
10
  def run
11
11
  ansible_options = ["--diff", "--tags=maintenance"]
12
- PASS_THROUGH_PARAMS.each do |param_name|
13
- x = param_name.split('-')[1..-1].map(&:upcase).join('_')
14
- hash_key = (param_name.gsub('-', '_') + (x == '' ? '' : "_#{x}")).to_sym
15
- value = @options.__hash__[hash_key]
16
- if value
17
- ansible_options += ["--#{param_name}", value]
18
- end
19
- end
12
+ ansible_options = ansible_options | pass_through_params
20
13
  ansible_command "ansible-playbook", "#{@environment}.yml", *ansible_options
21
14
  end
22
15
  end
@@ -0,0 +1,16 @@
1
+ class Subspace::Commands::MaintenanceMode < Subspace::Commands::Base
2
+ PASS_THROUGH_PARAMS = ["private-key", "limit"]
3
+
4
+ def initialize(args, options)
5
+ @hosts = args.first
6
+ @options = options
7
+ run
8
+ end
9
+
10
+ def run
11
+ on_off = @options.__hash__[:on] ? "on" : "off"
12
+ ansible_options = ["--diff", "-e maintenance_hosts=#{@hosts}", "--tags=maintenance_#{on_off}"]
13
+ ansible_options = ansible_options | pass_through_params
14
+ ansible_command "ansible-playbook", File.join(File.dirname(__FILE__), "../../../ansible/playbooks/maintenance_mode.yml"), *ansible_options
15
+ end
16
+ end
@@ -9,14 +9,7 @@ class Subspace::Commands::Provision < Subspace::Commands::Base
9
9
 
10
10
  def run
11
11
  ansible_options = ["--diff"]
12
- PASS_THROUGH_PARAMS.each do |param_name|
13
- x = param_name.split('-')[1..-1].map(&:upcase).join('_')
14
- hash_key = (param_name.gsub('-', '_') + (x == '' ? '' : "_#{x}")).to_sym
15
- value = @options.__hash__[hash_key]
16
- if value
17
- ansible_options += ["--#{param_name}", value]
18
- end
19
- end
12
+ ansible_options = ansible_options | pass_through_params
20
13
  ansible_command "ansible-playbook", "#{@environment}.yml", *ansible_options
21
14
  end
22
15
  end
@@ -20,16 +20,7 @@ class Subspace::Commands::Ssh < Subspace::Commands::Base
20
20
  user = @user || host_vars["ansible_ssh_user"] || host_vars["ansible_user"]
21
21
  host = host_vars["ansible_ssh_host"] || host_vars["ansible_host"]
22
22
  port = host_vars["ansible_ssh_port"] || host_vars["ansible_port"] || 22
23
- ssh_options = []
24
- PASS_THROUGH_PARAMS.each do |param_name|
25
- x = param_name.split('-')[1..-1].map(&:upcase).join('_')
26
- hash_key = (param_name.gsub('-', '_') + (x == '' ? '' : "_#{x}")).to_sym
27
- value = @options.__hash__[hash_key]
28
- if value
29
- ssh_options += ["-#{param_name}", value]
30
- end
31
- end
32
- cmd = "ssh #{user}@#{host} -p #{port} #{ssh_options.join(" ")}"
23
+ cmd = "ssh #{user}@#{host} -p #{port} #{pass_through_params.join(" ")}"
33
24
  say cmd
34
25
  exec cmd
35
26
  end
@@ -1,3 +1,3 @@
1
1
  module Subspace
2
- VERSION = "2.1.2"
2
+ VERSION = "2.2.0"
3
3
  end
@@ -27,7 +27,7 @@ Subspace.configure do |config|
27
27
  config.host :dev, {
28
28
  ssh_host: "1.2.3.4", # Ansible connects to this to provision
29
29
  ssh_user: "deploy", # ssh user
30
- sudo: true, # probably should be true if user isn't root
30
+ become: true, # probably should be true if user isn't root
31
31
  hostname: "dev.example.com" # This will get set in /etc/hostname
32
32
  }
33
33
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: subspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Samson
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-10-01 00:00:00.000000000 Z
11
+ date: 2019-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -101,6 +101,7 @@ files:
101
101
  - Rakefile
102
102
  - TODO
103
103
  - ansible/playbooks/local_template.yml
104
+ - ansible/playbooks/maintenance_mode.yml
104
105
  - ansible/roles/alienvault/tasks/main.yml
105
106
  - ansible/roles/apache-rails/tasks/main.yml
106
107
  - ansible/roles/apache-rails/templates/_canonical_domain.conf
@@ -172,6 +173,7 @@ files:
172
173
  - ansible/roles/mysql2_gem/tasks/main.yml
173
174
  - ansible/roles/newrelic/handlers/main.yml
174
175
  - ansible/roles/newrelic/tasks/main.yml
176
+ - ansible/roles/nginx-maintenance/tasks/main.yml
175
177
  - ansible/roles/nginx-rails/defaults/main.yml
176
178
  - ansible/roles/nginx-rails/tasks/main.yml
177
179
  - ansible/roles/nginx-rails/templates/_asset_cors.conf
@@ -263,6 +265,7 @@ files:
263
265
  - lib/subspace/commands/configure.rb
264
266
  - lib/subspace/commands/init.rb
265
267
  - lib/subspace/commands/maintain.rb
268
+ - lib/subspace/commands/maintenance_mode.rb
266
269
  - lib/subspace/commands/override.rb
267
270
  - lib/subspace/commands/provision.rb
268
271
  - lib/subspace/commands/ssh.rb
@@ -300,8 +303,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
300
303
  - !ruby/object:Gem::Version
301
304
  version: '0'
302
305
  requirements: []
303
- rubyforge_project:
304
- rubygems_version: 2.7.8
306
+ rubygems_version: 3.0.3
305
307
  signing_key:
306
308
  specification_version: 4
307
309
  summary: Ansible-based server provisioning for rails projects