capistrano-multimarket 0.0.1
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.
- data/.gitignore +5 -0
- data/Gemfile +1 -0
- data/README.md +102 -0
- data/Rakefile +1 -0
- data/capistrano-multimarket.gemspec +23 -0
- data/examples/check.rb +10 -0
- data/examples/config/deploy/markets/production/blog/site1.rb +1 -0
- data/examples/config/deploy/markets/production/blog/site2.yml +2 -0
- data/examples/config/deploy/markets/production/blog.rb +1 -0
- data/examples/config/deploy/markets/production.rb +0 -0
- data/examples/config/deploy/markets/staging/blog/site1.rb +1 -0
- data/examples/config/deploy/markets/staging/blog/site1.yml +15 -0
- data/lib/capistrano/multi_market/configurations.rb +124 -0
- data/lib/capistrano/multi_market/ensure.rb +15 -0
- data/lib/capistrano/multi_market/version.rb +5 -0
- data/lib/capistrano/multimarket.rb +3 -0
- metadata +93 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
source "http://rubygems.org"
|
data/README.md
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# capistrano-multimarket
|
2
|
+
|
3
|
+
|
4
|
+
#### NOTE
|
5
|
+
Forked from [capistrano-multiconfig](https://github.com/railsware/capistrano-multiconfig). But this extension loads both .yml and .rb files.
|
6
|
+
Use the main project if you want to load only rb files ;-)
|
7
|
+
|
8
|
+
|
9
|
+
## Description
|
10
|
+
|
11
|
+
Capistrano extension that allows to use multiple configurations(Ruby and YAML files).
|
12
|
+
|
13
|
+
MultiMarket extension is similar to [multistage](https://github.com/capistrano/capistrano-ext) extenstion.
|
14
|
+
But it's not only about 'stage' configurations. It's about any configuration that you may need.
|
15
|
+
Extension recursively builds configuration list from configuration root directory.
|
16
|
+
Each configuration loads recursively configuration from it namespace files and own configuration file.
|
17
|
+
|
18
|
+
## Usage
|
19
|
+
|
20
|
+
Install gem
|
21
|
+
|
22
|
+
$ gem install capistrano-multimarket
|
23
|
+
|
24
|
+
|
25
|
+
Add to `Capfile`
|
26
|
+
|
27
|
+
set :config, 'path/to/your/markets'
|
28
|
+
require 'capistrano/multimarket'
|
29
|
+
|
30
|
+
## Example
|
31
|
+
|
32
|
+
Assume we have the following configurations:
|
33
|
+
```bash
|
34
|
+
$ tree config/
|
35
|
+
config/
|
36
|
+
└── deploy
|
37
|
+
└── markets
|
38
|
+
├── production
|
39
|
+
│ ├── blog
|
40
|
+
│ │ ├── site1.rb
|
41
|
+
│ │ └── site2.yml
|
42
|
+
│ └── blog.rb
|
43
|
+
├── production.rb
|
44
|
+
└── staging
|
45
|
+
└── blog
|
46
|
+
├── site1.rb
|
47
|
+
└── site1.yml
|
48
|
+
```
|
49
|
+
|
50
|
+
Check tasks:
|
51
|
+
```bash
|
52
|
+
$ cap -f check.rb -T
|
53
|
+
cap invoke # Invoke a single command on the remote servers.
|
54
|
+
cap production:blog:site1 # Load production:blog:site1 configuration
|
55
|
+
cap production:blog:site2 # Load production:blog:site2 configuration
|
56
|
+
cap shell # Begin an interactive Capistrano session.
|
57
|
+
cap staging:blog:site1 # Load staging:blog:site1 configuration
|
58
|
+
```
|
59
|
+
|
60
|
+
Let's try to run task without specified configuration:
|
61
|
+
```bash
|
62
|
+
$ cap -f check.rb shell
|
63
|
+
triggering start callbacks for `shell'
|
64
|
+
* executing `multimarket:ensure'
|
65
|
+
No configuration specified. Please specify one of:
|
66
|
+
* production:blog:site1
|
67
|
+
* staging:blog:site1
|
68
|
+
* production:blog:site2
|
69
|
+
(e.g. `cap production:blog:site1 shell')
|
70
|
+
```
|
71
|
+
|
72
|
+
So we must provide configuration as first task:
|
73
|
+
```bash
|
74
|
+
$ cap -f check.rb staging:blog:site1 shell
|
75
|
+
* executing `staging:blog:site1'
|
76
|
+
triggering start callbacks for `shell'
|
77
|
+
* executing `multimarket:ensure'
|
78
|
+
* executing `shell'
|
79
|
+
```
|
80
|
+
|
81
|
+
|
82
|
+
### Example of YAML config:
|
83
|
+
$ cat examples/config/deploy/markets/staging/blog/site1.yml
|
84
|
+
|
85
|
+
```yaml
|
86
|
+
variables:
|
87
|
+
application: 'market1'
|
88
|
+
app_servers:
|
89
|
+
- web1.example.com
|
90
|
+
- web2.example.com
|
91
|
+
roles:
|
92
|
+
app:
|
93
|
+
- "app1.example.com"
|
94
|
+
- "app2.example.com"
|
95
|
+
db:
|
96
|
+
- "app1.example.com"
|
97
|
+
- {primary: true}
|
98
|
+
string: |
|
99
|
+
set :branch, :master
|
100
|
+
role(:web) { fetch(:app_servers) }
|
101
|
+
```
|
102
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
require "capistrano/multi_market/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "capistrano-multimarket"
|
8
|
+
s.version = Capistrano::MultiMarket::VERSION
|
9
|
+
s.authors = ["Marcos G. Zimmermann"]
|
10
|
+
s.email = ["mgzmaster@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/marcosgz/capistrano-multimarket"
|
12
|
+
s.summary = %q{Capistrano multimarket}
|
13
|
+
|
14
|
+
s.rubyforge_project = "capistrano-multimarket"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency "capistrano", "~> 2.14.1"
|
22
|
+
s.add_development_dependency "pry", "~> 0.9.11.4"
|
23
|
+
end
|
data/examples/check.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# run with cap -f ckeck.rb
|
2
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
require 'capistrano'
|
4
|
+
set :market_root, 'config/deploy/markets'
|
5
|
+
require 'capistrano/multimarket'
|
6
|
+
|
7
|
+
task :check, :roles => :app do
|
8
|
+
pp self[:app_servers]
|
9
|
+
pp self[:test_config]
|
10
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
set :test_config, 'markets/production/blog/site1.rb'
|
@@ -0,0 +1 @@
|
|
1
|
+
set :test_config, 'markets/production/blog'
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
set :test_config, 'markets/staging/blog/site1.rb'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
variables:
|
2
|
+
application: 'market1'
|
3
|
+
app_servers:
|
4
|
+
- web1.example.com
|
5
|
+
- web2.example.com
|
6
|
+
roles:
|
7
|
+
app:
|
8
|
+
- "app1.example.com"
|
9
|
+
- "app2.example.com"
|
10
|
+
db:
|
11
|
+
- "app1.example.com"
|
12
|
+
- {primary: true}
|
13
|
+
string: |
|
14
|
+
set :branch, :master
|
15
|
+
role(:web) { fetch(:app_servers) }
|
@@ -0,0 +1,124 @@
|
|
1
|
+
Capistrano::Configuration.instance(true).load do
|
2
|
+
# configurations root directory
|
3
|
+
markets_root = File.expand_path(fetch(:markets_root, "config/deploy/markets"))
|
4
|
+
|
5
|
+
# list of configurations files
|
6
|
+
config_files = Dir["#{markets_root}/**/*.{rb,yml}"]
|
7
|
+
|
8
|
+
# remove configuration file if it's part of another configuration
|
9
|
+
config_files.reject! do |config_file|
|
10
|
+
config_dir = config_file.gsub(/\.(rb|yml)$/, '/')
|
11
|
+
config_files.any? { |file| file[0, config_dir.size] == config_dir }
|
12
|
+
end
|
13
|
+
|
14
|
+
# build configuration names list
|
15
|
+
config_names = config_files.map do |config_file|
|
16
|
+
config_file.sub("#{markets_root}/", '').sub(/\.(rb|yml)$/, '').gsub('/', ':')
|
17
|
+
end.uniq
|
18
|
+
|
19
|
+
# ensure that configuration segments don't override any method, task or namespace
|
20
|
+
config_names.each do |config_name|
|
21
|
+
config_name.split(':').each do |segment|
|
22
|
+
if all_methods.any? { |m| m == segment }
|
23
|
+
raise ArgumentError,
|
24
|
+
"Config task #{config_name} name overrides #{segment.inspect} (method|task|namespace)"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# create configuration task for each configuration name
|
30
|
+
config_names.each do |config_name|
|
31
|
+
segments = config_name.split(':')
|
32
|
+
namespace_names = segments[0, segments.size - 1]
|
33
|
+
task_name = segments.last
|
34
|
+
|
35
|
+
# create configuration task block.
|
36
|
+
# NOTE: Capistrano 'namespace' DSL invokes instance_eval that
|
37
|
+
# that pass evaluable object as argument to block.
|
38
|
+
block = lambda do |parent|
|
39
|
+
desc "Load #{config_name} configuration"
|
40
|
+
task(task_name) do
|
41
|
+
# set configuration name as :config_name variable
|
42
|
+
top.set(:config_name, config_name)
|
43
|
+
|
44
|
+
# recursively load configurations
|
45
|
+
segments.size.times do |i|
|
46
|
+
path = ([markets_root] + segments[0..i]).join('/')
|
47
|
+
yml_path = path + '.yml'
|
48
|
+
if File.exists?(yml_path)
|
49
|
+
# variables:
|
50
|
+
# application: "foo"
|
51
|
+
# app_servers:
|
52
|
+
# - test.com
|
53
|
+
# - test1.com
|
54
|
+
configs = YAML.load_file(yml_path)
|
55
|
+
(configs['variables'] || {}).each do |k, v|
|
56
|
+
top.set(k.to_sym, v)
|
57
|
+
end
|
58
|
+
# roles:
|
59
|
+
# web: "app1.example.com"
|
60
|
+
# roles:
|
61
|
+
# web:
|
62
|
+
# - "app1.example.com"
|
63
|
+
# - "app2.example.com"
|
64
|
+
# roles:
|
65
|
+
# db:
|
66
|
+
# - "app1.example.com"
|
67
|
+
# - {primary: true}
|
68
|
+
(configs['roles'] || {}).each do |k, v|
|
69
|
+
top.role(k.to_sym) { v }
|
70
|
+
end
|
71
|
+
# string: |
|
72
|
+
# set :scm, :subversion
|
73
|
+
# set :branch, :master
|
74
|
+
if (v=configs['string'])
|
75
|
+
top.load(:string => v)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
rb_path = path + '.rb'
|
79
|
+
if File.exists?(rb_path)
|
80
|
+
top.load(:file => rb_path)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# wrap task block into namespace blocks
|
87
|
+
#
|
88
|
+
# namespace_names = [nsN, ..., ns2, ns1]
|
89
|
+
#
|
90
|
+
# block = block0 = lambda do |parent|
|
91
|
+
# desc "DESC"
|
92
|
+
# task(:task_name) { TASK }
|
93
|
+
# end
|
94
|
+
# block = block1 = lambda { |parent| parent.namespace(:ns1, &block0) }
|
95
|
+
# block = block2 = lambda { |parent| parent.namespace(:ns2, &block1) }
|
96
|
+
# ...
|
97
|
+
# block = blockN = lambda { |parent| parent.namespace(:nsN, &blockN-1) }
|
98
|
+
#
|
99
|
+
block = namespace_names.reverse.inject(block) do |child, name|
|
100
|
+
lambda do |parent|
|
101
|
+
parent.namespace(name, &child)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# create namespaced configuration task
|
106
|
+
#
|
107
|
+
# block = lambda do
|
108
|
+
# namespace :nsN do
|
109
|
+
# ...
|
110
|
+
# namespace :ns2 do
|
111
|
+
# namespace :ns1 do
|
112
|
+
# desc "DESC"
|
113
|
+
# task(:task_name) { TASK }
|
114
|
+
# end
|
115
|
+
# end
|
116
|
+
# ...
|
117
|
+
# end
|
118
|
+
# end
|
119
|
+
block.call(top)
|
120
|
+
end
|
121
|
+
|
122
|
+
# set configuration names list
|
123
|
+
set(:config_names, config_names)
|
124
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
Capistrano::Configuration.instance(true).load do
|
2
|
+
namespace :multimarket do
|
3
|
+
desc "[internal] Ensure that a configuration has been selected"
|
4
|
+
task :ensure do
|
5
|
+
unless exists?(:config_name)
|
6
|
+
puts "No configuration specified. Please specify one of:"
|
7
|
+
config_names.each { |name| puts " * #{name}" }
|
8
|
+
puts "(e.g. `cap #{config_names.first} #{ARGV.last}')"
|
9
|
+
abort
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
on :start, 'multimarket:ensure', :except => config_names
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: capistrano-multimarket
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Marcos G. Zimmermann
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-01-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: capistrano
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.14.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 2.14.1
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: pry
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 0.9.11.4
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 0.9.11.4
|
46
|
+
description:
|
47
|
+
email:
|
48
|
+
- mgzmaster@gmail.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- .gitignore
|
54
|
+
- Gemfile
|
55
|
+
- README.md
|
56
|
+
- Rakefile
|
57
|
+
- capistrano-multimarket.gemspec
|
58
|
+
- examples/check.rb
|
59
|
+
- examples/config/deploy/markets/production.rb
|
60
|
+
- examples/config/deploy/markets/production/blog.rb
|
61
|
+
- examples/config/deploy/markets/production/blog/site1.rb
|
62
|
+
- examples/config/deploy/markets/production/blog/site2.yml
|
63
|
+
- examples/config/deploy/markets/staging/blog/site1.rb
|
64
|
+
- examples/config/deploy/markets/staging/blog/site1.yml
|
65
|
+
- lib/capistrano/multi_market/configurations.rb
|
66
|
+
- lib/capistrano/multi_market/ensure.rb
|
67
|
+
- lib/capistrano/multi_market/version.rb
|
68
|
+
- lib/capistrano/multimarket.rb
|
69
|
+
homepage: https://github.com/marcosgz/capistrano-multimarket
|
70
|
+
licenses: []
|
71
|
+
post_install_message:
|
72
|
+
rdoc_options: []
|
73
|
+
require_paths:
|
74
|
+
- lib
|
75
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ! '>='
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
requirements: []
|
88
|
+
rubyforge_project: capistrano-multimarket
|
89
|
+
rubygems_version: 1.8.23
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: Capistrano multimarket
|
93
|
+
test_files: []
|