taperole 1.6.0 → 1.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -0
- data/CONTRIBUTING.md +8 -0
- data/README.md +33 -4
- data/Rakefile +6 -0
- data/Vagrantfile +6 -7
- data/bin/tape +2 -89
- data/lib/taperole/commands/ansible.rb +56 -0
- data/lib/taperole/commands/installer.rb +19 -0
- data/lib/taperole/commands/tape.rb +32 -0
- data/lib/taperole/core/ansible_runner.rb +86 -0
- data/lib/taperole/core/installer.rb +87 -0
- data/lib/taperole/core/notifier.rb +47 -0
- data/lib/taperole/helpers/files.rb +76 -0
- data/lib/taperole/helpers/logging.rb +37 -0
- data/lib/taperole/notifiers/slack.rb +83 -0
- data/lib/taperole/version.rb +3 -0
- data/lib/taperole.rb +24 -0
- data/requirements.yml +1 -1
- data/roles/backend_checkout/tasks/main.yml +1 -0
- data/roles/delayed_job/tasks/main.yml +0 -15
- data/roles/deployer_user/tasks/keys.yml +6 -6
- data/roles/deployer_user/tasks/main.yml +0 -3
- data/roles/monit_install/tasks/main.yml +6 -0
- data/roles/monit_install/templates/monitrc.j2 +290 -0
- data/roles/nginx/tasks/main.yml +3 -4
- data/roles/nginx/templates/nginx_unicorn.j2 +1 -0
- data/roles/node/tasks/main.yml +2 -1
- data/roles/ruby/tasks/main.yml +3 -11
- data/roles/unicorn_install/tasks/main.yml +0 -3
- data/roles/unicorn_install/templates/unicorn.rb.j2 +1 -1
- data/roles/unicorn_install/templates/unicorn_init.j2 +1 -1
- data/roles/unicorn_install/templates/unicorn_monit.j2 +1 -1
- data/spec/commands/installer_spec.rb +117 -0
- data/spec/spec_helper.rb +24 -0
- data/taperole.gemspec +8 -1
- data/templates/base/deploy.example.yml +1 -0
- data/templates/base/hosts.example +1 -1
- data/templates/base/omnibox.example.yml +15 -0
- data/templates/base/rake.example.yml +18 -0
- data/templates/base/tape_vars.example.yml +9 -8
- data/templates/static_html/omnibox.example.yml +13 -0
- data/test/base_docker_box/Dockerfile +1 -1
- data/test/rails/Dockerfile +3 -3
- data/test/rails/start_rails.sh +1 -0
- data/test/rails/tape_vars.yml +2 -2
- data/vendor/ANXS.postgresql/.travis.yml +27 -12
- data/vendor/ANXS.postgresql/README.md +1 -1
- data/vendor/ANXS.postgresql/Vagrantfile +7 -2
- data/vendor/ANXS.postgresql/meta/.galaxy_install_info +1 -1
- data/vendor/ANXS.postgresql/meta/main.yml +1 -1
- data/vendor/ANXS.postgresql/tasks/configure.yml +10 -10
- data/vendor/ANXS.postgresql/tasks/databases.yml +27 -27
- data/vendor/ANXS.postgresql/tasks/install_yum.yml +2 -2
- data/vendor/ANXS.postgresql/tasks/users.yml +4 -4
- data/vendor/ANXS.postgresql/tasks/users_privileges.yml +3 -3
- data/vendor/ANXS.postgresql/tests/Dockerfile-centos6 +20 -0
- data/vendor/ANXS.postgresql/tests/Dockerfile-ubuntu14.04 +17 -0
- data/vendor/ANXS.postgresql/tests/playbook.yml +1 -1
- data/vendor/ANXS.postgresql/tests/vars.yml +2 -0
- data/vendor/Stouts.backup/.bumpversion.cfg +1 -1
- data/vendor/Stouts.backup/.travis.yml +0 -1
- data/vendor/Stouts.backup/CONTRIBUTORS +2 -0
- data/vendor/Stouts.backup/README.md +1 -0
- data/vendor/Stouts.backup/defaults/main.yml +3 -3
- data/vendor/Stouts.backup/meta/.galaxy_install_info +1 -1
- data/vendor/Stouts.backup/runtests.sh +65 -0
- data/vendor/Stouts.backup/tasks/backup.yml +3 -0
- data/vendor/Stouts.backup/tasks/configure.yml +13 -12
- data/vendor/Stouts.backup/tasks/install.deb.yml +6 -8
- data/vendor/Stouts.backup/tasks/install.red.yml +28 -0
- data/vendor/Stouts.backup/tasks/remove.yml +3 -3
- data/vendor/Stouts.backup/templates/cron.j2 +1 -1
- data/vendor/Stouts.backup/templates/duply.sh.j2 +219 -218
- data/vendor/Stouts.backup/templates/pre.j2 +6 -0
- data/vendor/Stouts.backup/templates/restore.j2 +6 -0
- data/vendor/Stouts.backup/vars/Debian.yml +3 -0
- data/vendor/Stouts.backup/vars/Ubuntu.yml +1 -0
- metadata +67 -10
- data/lib/tape/ansible_runner.rb +0 -130
- data/lib/tape/info.rb +0 -9
- data/lib/tape/installer.rb +0 -160
- data/lib/tape/notifiers/slack.rb +0 -79
- data/lib/tape/overwriter.rb +0 -14
- data/lib/tape/qemu_provisioner.rb +0 -167
- data/lib/tape.rb +0 -127
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 21ca9a88b00c6e0ed2f77b29937b871038b3f911
|
4
|
+
data.tar.gz: 4768be3843152356b7add30fbe8e5e3dedfcaad2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3c6f367b84e1b0b339fd4f768cf079e36279e3e35b310924de4d04836a4637a4706b4cb635bc1d09c895518a40f78ca04755250610b04618a2636531c117fd9
|
7
|
+
data.tar.gz: 5e1b9437c2ebfc85bdb591af65f4040ead65ec91977c7d3678c416ee86a1af4449fec373754284e33a580c0568a2e86a6b99c8a1f2790372e4cebacfd7c96a77
|
data/.travis.yml
CHANGED
data/CONTRIBUTING.md
CHANGED
@@ -5,6 +5,14 @@
|
|
5
5
|
###Workflow
|
6
6
|
We use [Waffle.io](https://waffle.io/smashingboxes/tape) to manage our workflow for this project. Please respect the workflow and move PRs that are ready to be mereged into the 'Ready' column.
|
7
7
|
|
8
|
+
####Testing
|
9
|
+
|
10
|
+
There are two main ways we test taperole. The first is basic unit tests, via rspec. Those can be run via:
|
11
|
+
|
12
|
+
`rake test`
|
13
|
+
|
14
|
+
The second way is a kind of integration test. We use tape to stand up a basic vanilla rails app (leveraging docker) and then check that a curl returns the correct thing. There isn't an easy way to run this locally, but it is set up on travis to run automatically.
|
15
|
+
|
8
16
|
###PR Structure
|
9
17
|
|
10
18
|
Please give details regarding your PR in the following format. It really helps with review and quickens the speed at which your changes are merged in
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Infrastructure Management
|
4
4
|
|
5
5
|
## Deploying & provisioning with tape
|
6
|
-
**Use Unbuntu trusty64 (
|
6
|
+
**Use Unbuntu trusty64 (16 x64)**
|
7
7
|
|
8
8
|
**Enable ssh access via root user**
|
9
9
|
|
@@ -45,9 +45,30 @@ All default configurations found in `vars/defaults.yml` can be overridden in you
|
|
45
45
|
**Default Ruby Version** 2.3.0
|
46
46
|
|
47
47
|
### Backups
|
48
|
-
Backups are handled via [duply](http://duply.net/) and occur every night at 4am under the root user. You can configure your backup schedule and target where you want your backups stored at within your `taperole/tape_vars.yml` file.
|
48
|
+
Backups are handled via [duply](http://duply.net/) and are configured via the [Stouts.backup](https://github.com/Stouts/Stouts.backup) ansible galaxy role. Bacups occur every night at 4am under the root user. You can configure your backup schedule and target where you want your backups stored at within your `taperole/tape_vars.yml` file.
|
49
49
|
|
50
|
-
|
50
|
+
The default location for backups is the `/var/lib/postgresql/backups` directory.
|
51
|
+
|
52
|
+
All servers in your [production] group will have backups enabled by default.
|
53
|
+
|
54
|
+
Detailed configurations can be made in your tape_vars.yml file.
|
55
|
+
|
56
|
+
```
|
57
|
+
# Store Backups on S3
|
58
|
+
backup_dir: s3+http://[aws_access_key:aws_secret_access_key]@bucket_name[/folder]
|
59
|
+
|
60
|
+
# Store Backups on Seperate server via rsync
|
61
|
+
backup_dir: s3+http://[aws_access_key:aws_secret_access_key]@bucket_name[/folder]
|
62
|
+
|
63
|
+
# Adjust Cron Job Schedule (default is every night at 4am)
|
64
|
+
backup_schedule: "* */4 * * *"
|
65
|
+
|
66
|
+
# Change Which Servers are backed up
|
67
|
+
backup_hosts:
|
68
|
+
- production
|
69
|
+
- staging
|
70
|
+
- qa
|
71
|
+
```
|
51
72
|
|
52
73
|
### Custom roles
|
53
74
|
You can add app specific ansible roles to `<app_root>/roles`.
|
@@ -93,7 +114,7 @@ localhost:2222 ansible_ssh_private_key_file=~/.vagrant.d/insecure_private_key
|
|
93
114
|
The port number might be different if other vagrant machines are running, run `vagrant ssh-config` to find the correct configuration.
|
94
115
|
You can specify a port using the `ansible_ssh_port` in your hosts inventory file.
|
95
116
|
|
96
|
-
3. Update `tape_vars.yml` with information to a
|
117
|
+
3. Update `tape_vars.yml` with information to a rails app you want to deploy
|
97
118
|
4. `tape ansible everything -l vagrant`
|
98
119
|
|
99
120
|
### With Docker
|
@@ -235,6 +256,14 @@ This will git pull the latest changes from the tracking branch you specified and
|
|
235
256
|
|
236
257
|
This command runs all Ansible roles specified in the deploy.yml playbook.
|
237
258
|
|
259
|
+
### Rake tasks
|
260
|
+
|
261
|
+
To run ad-hoc rake tasks, you can use the following:
|
262
|
+
|
263
|
+
```
|
264
|
+
tape ansible rake --task users:rank
|
265
|
+
```
|
266
|
+
|
238
267
|
## Slack integration
|
239
268
|
|
240
269
|
Tape includes built-in support for posting messages to slack at the beginning and end of deployments.
|
data/Rakefile
ADDED
data/Vagrantfile
CHANGED
@@ -2,25 +2,24 @@
|
|
2
2
|
# vi: set ft=ruby :
|
3
3
|
|
4
4
|
Vagrant.configure 2 do |config|
|
5
|
-
config.vm.box =
|
5
|
+
config.vm.box = "ubuntu/xenial64"
|
6
6
|
|
7
|
-
name = %x[basename `git rev-parse --show-toplevel`].chomp
|
7
|
+
name = %x[basename `git rev-parse --show-toplevel`].chomp.gsub(/[^0-9a-z ]/i, '')
|
8
8
|
config.vm.define "#{name}_vagrant_box"
|
9
|
+
config.vm.hostname = "#{name}"
|
9
10
|
|
10
|
-
|
11
|
-
|
11
|
+
private_ip = "192.168.13.37"
|
12
|
+
config.vm.network(:private_network, :ip => private_ip)
|
12
13
|
|
13
|
-
# TODO free me from the bonds of this ip
|
14
14
|
config.vm.network 'forwarded_port', guest: 443, host: 8080
|
15
15
|
config.vm.network 'private_network', type: 'dhcp'
|
16
16
|
|
17
|
-
config.ssh.insert_key = false
|
18
17
|
config.ssh.shell = 'bash -c "BASH_ENV=/etc/profile exec bash"'
|
19
18
|
|
20
19
|
config.vm.provision :shell, inline: <<-SCRIPT
|
21
20
|
sudo su
|
22
21
|
mkdir -p ~/.ssh/
|
23
|
-
cp /home/
|
22
|
+
cp /home/ubuntu/.ssh/authorized_keys ~/.ssh/
|
24
23
|
chmod 600 ~/.ssh/authorized_keys
|
25
24
|
SCRIPT
|
26
25
|
end
|
data/bin/tape
CHANGED
@@ -1,92 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
3
|
+
require 'taperole'
|
4
4
|
|
5
|
-
|
6
|
-
require 'ostruct'
|
7
|
-
require 'tape'
|
8
|
-
|
9
|
-
options = OpenStruct.new
|
10
|
-
opt_parser = OptionParser.new do |opts|
|
11
|
-
opts.banner = "Usage: tape <module> <action> [options]"
|
12
|
-
|
13
|
-
opts.on("-v", "--[no-]verbose", "Be loud") {|v| options.verbose = v}
|
14
|
-
opts.on("--ask-vault-pass", "Ask for Ansible vault password") { options.vault = true }
|
15
|
-
|
16
|
-
opts.on("-i", "--inventory [INVENTORY_FILE]",
|
17
|
-
String, "Do actions with the given inventory file") do |i|
|
18
|
-
options.inventory_file = i
|
19
|
-
end
|
20
|
-
|
21
|
-
opts.on('-n', "--name [NAME]",
|
22
|
-
String, "The name of the machine to operate on") do |n|
|
23
|
-
options.name = n
|
24
|
-
end
|
25
|
-
|
26
|
-
opts.on('-p', "--port [PORT]",
|
27
|
-
Integer, "The port that the machine is listening on for SSH connections") do |p|
|
28
|
-
options.port = p
|
29
|
-
end
|
30
|
-
|
31
|
-
opts.on('-bBOOK', "--book=PLAYBOOK",
|
32
|
-
String, "A custom playbook to run") do |p|
|
33
|
-
options.book = p
|
34
|
-
end
|
35
|
-
|
36
|
-
opts.on("-h", "--help", "Show this help") do
|
37
|
-
STDERR.puts opts
|
38
|
-
exit 0
|
39
|
-
end
|
40
|
-
|
41
|
-
opts.on("-l", "--limit [PATTERN]",
|
42
|
-
String, "Limits ansible runs to hosts matching PATTERN") do |p|
|
43
|
-
options.host_pattern = p
|
44
|
-
end
|
45
|
-
|
46
|
-
opts.on("-t", "--tags [TAGS]",
|
47
|
-
String, "only run plays and tasks tagged with these values") do |t|
|
48
|
-
options.tags = t
|
49
|
-
end
|
50
|
-
|
51
|
-
opts.on("-r", "--role=ROLE_NAME",
|
52
|
-
String, "name of the role to operate on") do |r|
|
53
|
-
options.role = r
|
54
|
-
end
|
55
|
-
|
56
|
-
opts.separator ''
|
57
|
-
opts.separator "MODULES"
|
58
|
-
TapeBoxer.registered_modules.values.each do |exec_module|
|
59
|
-
opts.separator " #{exec_module.name.to_s.upcase}"
|
60
|
-
exec_module.klass.actions.values.each do |action|
|
61
|
-
opts.separator " #{action.name}: #{action.description}"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
|
67
|
-
opt_parser.parse!(ARGV)
|
68
|
-
|
69
|
-
fail_without = ->(&block){
|
70
|
-
val = block.call
|
71
|
-
|
72
|
-
if val
|
73
|
-
return val
|
74
|
-
else
|
75
|
-
STDERR.puts(opt_parser.help)
|
76
|
-
exit 1
|
77
|
-
end
|
78
|
-
}
|
79
|
-
|
80
|
-
module_name = fail_without.call{ ARGV.shift }.to_sym
|
81
|
-
action_name = fail_without.call{ ARGV.shift }.to_sym
|
82
|
-
|
83
|
-
exec_module = fail_without.call{TapeBoxer.registered_modules[module_name]}
|
84
|
-
|
85
|
-
begin
|
86
|
-
exec_module.klass.new(options).execute_action(action_name)
|
87
|
-
rescue TapeBoxer::InvalidAction,
|
88
|
-
TapeBoxer::ActionError, TapeBoxer::UnspecifiedOption => e
|
89
|
-
|
90
|
-
STDERR.puts(e.message)
|
91
|
-
exit 2
|
92
|
-
end
|
5
|
+
Taperole::Commands::Tape.start(ARGV)
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Taperole
|
2
|
+
module Commands
|
3
|
+
class Ansible < Thor
|
4
|
+
include Taperole::AnsibleRunner
|
5
|
+
include Taperole::Helpers::Logging
|
6
|
+
|
7
|
+
class_option :limit,
|
8
|
+
type: :string,
|
9
|
+
aliases: :l,
|
10
|
+
desc: 'Limits ansible runs to hosts matching the given pattern'
|
11
|
+
class_option :task,
|
12
|
+
type: :string,
|
13
|
+
aliases: :T,
|
14
|
+
desc: 'Name of the rake task to execute'
|
15
|
+
class_option :inventory,
|
16
|
+
aliases: :i,
|
17
|
+
type: :string,
|
18
|
+
desc: 'Do actions with the given inventory file'
|
19
|
+
class_option :name,
|
20
|
+
aliases: :n,
|
21
|
+
type: :string,
|
22
|
+
desc: 'The name of the machine to operate on'
|
23
|
+
class_option :port,
|
24
|
+
aliases: :p,
|
25
|
+
type: :numeric,
|
26
|
+
desc: 'The port that the machine is listening on for SSH connections'
|
27
|
+
class_option :tags,
|
28
|
+
aliases: :t,
|
29
|
+
type: :string,
|
30
|
+
desc: 'Only run plays and tasks tagged with these values'
|
31
|
+
class_option :role,
|
32
|
+
aliases: :r,
|
33
|
+
type: :string,
|
34
|
+
desc: 'Name of the role to operate on'
|
35
|
+
|
36
|
+
class_option :'ask-vault-pass', type: :boolean, desc: 'Ask for Ansible vault password'
|
37
|
+
|
38
|
+
class_option :book,
|
39
|
+
aliases: :b,
|
40
|
+
type: :string,
|
41
|
+
desc: 'A custom playbook to run'
|
42
|
+
|
43
|
+
desc 'everything', 'Initial setup of a server'
|
44
|
+
def everything
|
45
|
+
Taperole::Notifier.register_notifiers(options)
|
46
|
+
valid_preconfigs ? ansible(options: options) : puts("Not a Rails or JS app")
|
47
|
+
end
|
48
|
+
|
49
|
+
desc 'deploy', 'Deploy the latest version of the app'
|
50
|
+
def deploy
|
51
|
+
Taperole::Notifier.register_notifiers(options)
|
52
|
+
ansible_deploy(args: '-t be_deploy,fe_deploy', options: options)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Taperole
|
2
|
+
module Commands
|
3
|
+
class Installer < Thor
|
4
|
+
include Taperole::Installer
|
5
|
+
include Taperole::Helpers::Logging
|
6
|
+
|
7
|
+
option :vagrant, type: :boolean
|
8
|
+
desc 'install', 'Creates all necessary hosts and config files'
|
9
|
+
def install
|
10
|
+
install_tape
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'uninstall', 'Cleans up files generated by the installer'
|
14
|
+
def uninstall
|
15
|
+
uninstall_tape
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Taperole
|
4
|
+
module Commands
|
5
|
+
class Tape < Thor
|
6
|
+
include Taperole::Helpers::Files
|
7
|
+
include Taperole::Helpers::Logging
|
8
|
+
|
9
|
+
class_option :verbose, type: :boolean
|
10
|
+
class_option :debug, type: :boolean
|
11
|
+
class_option :quiet, type: :boolean
|
12
|
+
|
13
|
+
map %w[--version -v] => :__print_version
|
14
|
+
|
15
|
+
desc "--version, -v", "print the version"
|
16
|
+
def __print_version
|
17
|
+
puts Taperole::VERSION
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'ansible [COMMAND]', 'run tapes ansible commands'
|
21
|
+
subcommand 'ansible', Ansible
|
22
|
+
|
23
|
+
desc 'installer [COMMAND]', 'install and uninstall tape'
|
24
|
+
subcommand 'installer', Installer
|
25
|
+
|
26
|
+
desc 'overwrite [ROLE]', 'Overwrite a taperole ansible role'
|
27
|
+
def overwrite_role(role)
|
28
|
+
FileUtils.cp_r("#{tape_dir}/roles/#{role}", "taperole/roles/")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Taperole
|
2
|
+
module AnsibleRunner
|
3
|
+
include Taperole::Helpers::Files
|
4
|
+
|
5
|
+
protected
|
6
|
+
|
7
|
+
def valid_preconfigs
|
8
|
+
if rails_app?
|
9
|
+
valid_gems
|
10
|
+
elsif fe_app?
|
11
|
+
true
|
12
|
+
else
|
13
|
+
false
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid_gems
|
18
|
+
has_gem_in_gemfile?('unicorn')
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_gem_in_gemfile?(name)
|
22
|
+
if open('Gemfile').grep(/#{name}/).empty?
|
23
|
+
logger.error "💥 ERROR: Add #{name} to your Gemfile!💥 ".red
|
24
|
+
false
|
25
|
+
else
|
26
|
+
true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def ansible(args: '', options: {})
|
31
|
+
exec_ansible("#{tapefiles_dir}/omnibox.yml", args, options)
|
32
|
+
end
|
33
|
+
|
34
|
+
def ansible_deploy(args: '', options: {})
|
35
|
+
exec_ansible("#{tapefiles_dir}/deploy.yml", args, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
def ansible_custom_playbook(args: '', options: {})
|
39
|
+
exec_ansible("#{tapefiles_dir}/#{options[:book]}", args, options)
|
40
|
+
end
|
41
|
+
|
42
|
+
def ansible_rake_task(options: {})
|
43
|
+
exec_ansible("#{tapefiles_dir}/rake.yml", "--extra-vars \"task=#{options[:task]}\"", options)
|
44
|
+
end
|
45
|
+
|
46
|
+
def exec_ansible(playbook, args, options)
|
47
|
+
enforce_roles_path!
|
48
|
+
cmd = "ANSIBLE_CONFIG=#{local_dir}/.tape/ansible.cfg ansible-playbook -i"
|
49
|
+
cmd += " #{inventory_file(options)} #{playbook} #{args} #{hosts_flag(options)}"
|
50
|
+
cmd += " -e tape_dir=#{tape_dir}"
|
51
|
+
cmd += ' --ask-vault-pass' if options[:vault]
|
52
|
+
cmd += ' -vvvv' if options[:verbose]
|
53
|
+
cmd += " -t #{options[:tags]}" if options[:tags]
|
54
|
+
logger.info "Executing: #{cmd}" if options[:verbose]
|
55
|
+
Taperole::Notifier.notify_observers(:start)
|
56
|
+
if Kernel.system(cmd)
|
57
|
+
Taperole::Notifier.notify_observers(:success)
|
58
|
+
else
|
59
|
+
Taperole::Notifier.notify_observers(:fail)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def enforce_roles_path!
|
64
|
+
Dir.mkdir('.tape') unless Dir.exist?('.tape')
|
65
|
+
|
66
|
+
File.open("#{local_dir}/.tape/ansible.cfg", 'w') do |f|
|
67
|
+
f.puts '[defaults]'
|
68
|
+
f.puts "roles_path=.tape/roles:#{tape_dir}/roles:#{tape_dir}/vendor"
|
69
|
+
f.puts "inventory=#{tapefiles_dir}/hosts"
|
70
|
+
f.puts "retries-dir=/dev/null"
|
71
|
+
f.puts "retry_files_enabled = False"
|
72
|
+
f.puts '[ssh_connection]'
|
73
|
+
f.puts 'ssh_args=-o ForwardAgent=yes'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def hosts_flag(options)
|
78
|
+
limit = options[:limit]
|
79
|
+
"-l #{limit}" if limit
|
80
|
+
end
|
81
|
+
|
82
|
+
def inventory_file(options)
|
83
|
+
options[:inventory_file] || "#{tapefiles_dir}/hosts"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
|
3
|
+
module Taperole
|
4
|
+
module Installer
|
5
|
+
include Taperole::Helpers::Files
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
protected
|
9
|
+
|
10
|
+
def install_tape
|
11
|
+
add_tape_to_gitignore
|
12
|
+
mkdir tapefiles_dir
|
13
|
+
create_tape_files
|
14
|
+
create_roles_dir
|
15
|
+
create_inventory_file
|
16
|
+
create_ssh_keys_dir
|
17
|
+
handle_vagrantfile
|
18
|
+
end
|
19
|
+
|
20
|
+
def uninstall_tape
|
21
|
+
rm "#{tapefiles_dir}/omnibox.yml"
|
22
|
+
rm "#{tapefiles_dir}/deploy.yml"
|
23
|
+
rm "#{tapefiles_dir}/tape_vars.yml"
|
24
|
+
rm "#{tapefiles_dir}/rake.yml"
|
25
|
+
rm "#{tapefiles_dir}/roles"
|
26
|
+
rm "#{tapefiles_dir}/hosts"
|
27
|
+
rm "#{local_dir}/dev_keys"
|
28
|
+
rm "#{local_dir}/Vagrantfile"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def add_tape_to_gitignore
|
34
|
+
File.open('.gitignore', 'r+') { |f| f.puts '.tape' unless f.read =~ /^\.tape$/ }
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_tape_files
|
38
|
+
if fe_app? && !rails_app?
|
39
|
+
logger.info '🔎 JS/HTML app detected'.red
|
40
|
+
copy_static_app_examples
|
41
|
+
elsif rails_app?
|
42
|
+
logger.info '🔎 Rails app detected'.red
|
43
|
+
copy_basic_examples
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def copy_static_app_examples
|
48
|
+
%w(omnibox deploy tape_vars).each do |base_filename|
|
49
|
+
copy_example(
|
50
|
+
"templates/static_html/#{base_filename}.example.yml",
|
51
|
+
"#{tapefiles_dir}/#{base_filename}.yml"
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def copy_basic_examples
|
57
|
+
%w(omnibox deploy tape_vars rake).each do |base_filename|
|
58
|
+
copy_example(
|
59
|
+
"templates/base/#{base_filename}.example.yml",
|
60
|
+
"#{tapefiles_dir}/#{base_filename}.yml"
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def create_roles_dir
|
66
|
+
mkdir "#{tapefiles_dir}/roles"
|
67
|
+
`touch #{tapefiles_dir}/roles/.keep`
|
68
|
+
end
|
69
|
+
|
70
|
+
def create_inventory_file
|
71
|
+
copy_example 'templates/base/hosts.example', "#{tapefiles_dir}/hosts"
|
72
|
+
end
|
73
|
+
|
74
|
+
def create_ssh_keys_dir
|
75
|
+
mkdir "#{local_dir}/dev_keys"
|
76
|
+
end
|
77
|
+
|
78
|
+
def handle_vagrantfile
|
79
|
+
if options[:vagrant].nil?
|
80
|
+
options[:vagrant] = ask('Are you going to use vagrant? (y/n): ')
|
81
|
+
end
|
82
|
+
if options[:vagrant]
|
83
|
+
copy_example 'Vagrantfile', 'Vagrantfile'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Taperole
|
5
|
+
class Notifier
|
6
|
+
include ::Singleton
|
7
|
+
|
8
|
+
attr_accessor :observers
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@observers = []
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
include Taperole::Helpers::Files
|
16
|
+
|
17
|
+
def register_notifiers(options)
|
18
|
+
if config["slack_webhook_url"]
|
19
|
+
slack_notifier = Taperole::Notifiers::Slack.new(
|
20
|
+
config["slack_webhook_url"],
|
21
|
+
deploy_info(options)
|
22
|
+
)
|
23
|
+
instance.observers.push(slack_notifier)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def config
|
28
|
+
@config ||= YAML.load_file("#{tapefiles_dir}/tape_vars.yml")
|
29
|
+
end
|
30
|
+
|
31
|
+
def deploy_info(options)
|
32
|
+
{
|
33
|
+
app_name: config["app_name"],
|
34
|
+
user: `whoami`.chomp,
|
35
|
+
hosts: options[:limit] || 'default',
|
36
|
+
repo: config["be_app_repo"] || ''
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def notify_observers(state)
|
41
|
+
instance.observers.each do |observer|
|
42
|
+
observer.update(state)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Taperole
|
2
|
+
module Helpers
|
3
|
+
module Files
|
4
|
+
def fe_app?
|
5
|
+
!Dir["#{local_dir}/package.json"].empty?
|
6
|
+
end
|
7
|
+
|
8
|
+
def rails_app?
|
9
|
+
!Dir["#{local_dir}/config.ru"].empty?
|
10
|
+
end
|
11
|
+
|
12
|
+
def tape_dir
|
13
|
+
File.realpath(File.join(__dir__, '../../../'))
|
14
|
+
end
|
15
|
+
|
16
|
+
def local_dir
|
17
|
+
Dir.pwd
|
18
|
+
end
|
19
|
+
|
20
|
+
def tapefiles_dir
|
21
|
+
local_dir + '/taperole'
|
22
|
+
end
|
23
|
+
|
24
|
+
def tapecfg_dir
|
25
|
+
local_dir + '/.tape'
|
26
|
+
end
|
27
|
+
|
28
|
+
def rm(file)
|
29
|
+
logger.info 'Deleting '.red + file
|
30
|
+
FileUtils.rm_r file
|
31
|
+
end
|
32
|
+
|
33
|
+
def mkdir(name)
|
34
|
+
file_text = "#{::Pathname.new(name).basename}: "
|
35
|
+
begin
|
36
|
+
FileUtils.mkdir name
|
37
|
+
success(file_text)
|
38
|
+
rescue Errno::EEXIST
|
39
|
+
exists(file_text)
|
40
|
+
rescue StandardError => e
|
41
|
+
error(file_text)
|
42
|
+
raise e
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def copy_example(file, cp_file)
|
47
|
+
file_text = "#{::Pathname.new(cp_file).basename}: "
|
48
|
+
begin
|
49
|
+
if File.exist?(cp_file.to_s)
|
50
|
+
exists(file_text)
|
51
|
+
else
|
52
|
+
FileUtils.cp("#{tape_dir}/#{file}", cp_file.to_s)
|
53
|
+
success(file_text)
|
54
|
+
end
|
55
|
+
rescue StandardError => e
|
56
|
+
error(file_text)
|
57
|
+
raise e
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def success(file_text)
|
64
|
+
logger.info file_text + '✔'.green
|
65
|
+
end
|
66
|
+
|
67
|
+
def error(file_text)
|
68
|
+
logger.info file_text + '✘'.red
|
69
|
+
end
|
70
|
+
|
71
|
+
def exists(file_text)
|
72
|
+
logger.info file_text + '✘ (Exists)'.yellow
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Taperole
|
4
|
+
module Helpers
|
5
|
+
module Logging
|
6
|
+
def initialize(*_args)
|
7
|
+
super
|
8
|
+
logger.level = logger_level
|
9
|
+
logger.formatter = proc do |_severity, _datetime, _progname, msg|
|
10
|
+
"#{msg}\n"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def logger
|
15
|
+
Logging.logger
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.logger
|
19
|
+
@logger ||= Logger.new(STDOUT)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def logger_level
|
25
|
+
if options[:debug]
|
26
|
+
Logger::DEBUG
|
27
|
+
elsif options[:verbose]
|
28
|
+
Logger::INFO
|
29
|
+
elsif options[:quiet]
|
30
|
+
Logger::ERROR
|
31
|
+
else
|
32
|
+
Logger::INFO
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|