ferry 1.3.3 → 2.0.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.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/bin/ferry +4 -4
- data/{doc → img}/ferry_readme_icon.png +0 -0
- data/{doc → img}/ferry_readme_icon_2.png +0 -0
- data/lib/Ferryfile +3 -0
- data/lib/ferry/all.rb +14 -0
- data/lib/ferry/configuration.rb +142 -0
- data/lib/ferry/configuration/filter.rb +56 -0
- data/lib/ferry/configuration/question.rb +53 -0
- data/lib/ferry/configuration/server.rb +131 -0
- data/lib/ferry/configuration/servers.rb +69 -0
- data/lib/ferry/defaults.rb +3 -0
- data/lib/ferry/deploy.rb +3 -0
- data/lib/ferry/dotfile.rb +2 -0
- data/lib/ferry/dsl.rb +64 -0
- data/lib/ferry/dsl/env.rb +81 -0
- data/lib/ferry/dsl/paths.rb +103 -0
- data/lib/ferry/dsl/stages.rb +19 -0
- data/lib/ferry/dsl/task_enhancements.rb +65 -0
- data/lib/ferry/framework.rb +2 -0
- data/lib/ferry/i18n.rb +18 -0
- data/lib/ferry/install.rb +1 -0
- data/lib/ferry/setup.rb +22 -0
- data/lib/ferry/tasks/deploy.rake +226 -0
- data/lib/ferry/tasks/framework.rake +52 -0
- data/lib/ferry/tasks/install.rake +41 -0
- data/lib/ferry/templates/Ferryfile +8 -0
- data/lib/ferry/templates/deploy_ferry.rb.erb +21 -0
- data/lib/ferry/templates/stage.rb.erb +1 -0
- data/lib/ferry/upload_task.rb +9 -0
- data/lib/ferry/utilities.rb +0 -12
- data/lib/ferry/version.rb +1 -1
- metadata +31 -7
- data/doc/ferry_rake_contents.rb +0 -9
- data/lib/ferry/dsl/captain.rb +0 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f492db93e09993eb5609bb9550f8bf3fc3076cd5
|
4
|
+
data.tar.gz: afca6fdd10a193d69ccf45f141c814b914f74972
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b17c36ac8df1dff74d595e7f0d1112364562f462b069207fa341986184b9df60a07d2682d672a1445067f4fba97561786d3fc322102806e662ccbf65318ac76
|
7
|
+
data.tar.gz: 366782e71c8fa8a83fd784cc13e965a01a3ef6fcd2b58578ff832f1c59dbaedc8b4e80bc09a5897ae1caf7a5712bf1a3ac5b6e5b004a10d6928ab3a5e0ec637d
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-

|
2
2
|
|
3
3
|
[](https://travis-ci.org/cmu-is-projects/ferry)
|
4
4
|
[](http://badge.fury.io/rb/ferry)
|
data/bin/ferry
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/ruby
|
2
2
|
require 'ferry'
|
3
|
+
# require 'all'
|
3
4
|
|
4
5
|
OptionParser.new do |opts|
|
5
6
|
options = {}
|
@@ -36,10 +37,9 @@ OptionParser.new do |opts|
|
|
36
37
|
importer.import_json(opt, ARGV[0], ARGV[1])
|
37
38
|
end
|
38
39
|
|
39
|
-
opts.on('
|
40
|
-
|
41
|
-
|
42
|
-
end
|
40
|
+
# opts.on('--init', 'Installs and configures ferry') do |opt|
|
41
|
+
# Ferry::DSL
|
42
|
+
# end
|
43
43
|
|
44
44
|
opts.on("--to_csv ENVIRONMENT TABLE", 'Exports table to csv file in db/csv/[your db environment]/[your table]') do |opt|
|
45
45
|
check_appro_args(1)
|
File without changes
|
File without changes
|
data/lib/Ferryfile
ADDED
data/lib/ferry/all.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require_relative 'configuration/filter'
|
2
|
+
require_relative 'configuration/question'
|
3
|
+
require_relative 'configuration/server'
|
4
|
+
require_relative 'configuration/servers'
|
5
|
+
|
6
|
+
module Ferry
|
7
|
+
class Configuration
|
8
|
+
|
9
|
+
def initialize(config = nil)
|
10
|
+
@config ||= config
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.env
|
14
|
+
@env ||= new
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.reset!
|
18
|
+
@env = new
|
19
|
+
end
|
20
|
+
|
21
|
+
def ask(key, default=nil, options={})
|
22
|
+
question = Question.new(key, default, options)
|
23
|
+
set(key, question)
|
24
|
+
end
|
25
|
+
|
26
|
+
def set(key, value)
|
27
|
+
config[key] = value
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_if_empty(key, value)
|
31
|
+
config[key] = value unless config.has_key? key
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete(key)
|
35
|
+
config.delete(key)
|
36
|
+
end
|
37
|
+
|
38
|
+
def fetch(key, default=nil, &block)
|
39
|
+
value = fetch_for(key, default, &block)
|
40
|
+
while callable_without_parameters?(value)
|
41
|
+
value = set(key, value.call)
|
42
|
+
end
|
43
|
+
return value
|
44
|
+
end
|
45
|
+
|
46
|
+
def keys
|
47
|
+
config.keys
|
48
|
+
end
|
49
|
+
|
50
|
+
def role(name, hosts, options={})
|
51
|
+
if name == :all
|
52
|
+
raise ArgumentError.new("#{name} reserved name for role. Please choose another name")
|
53
|
+
end
|
54
|
+
|
55
|
+
servers.add_role(name, hosts, options)
|
56
|
+
end
|
57
|
+
|
58
|
+
def server(name, properties={})
|
59
|
+
servers.add_host(name, properties)
|
60
|
+
end
|
61
|
+
|
62
|
+
def roles_for(names)
|
63
|
+
servers.roles_for(names)
|
64
|
+
end
|
65
|
+
|
66
|
+
def role_properties_for(names, &block)
|
67
|
+
servers.role_properties_for(names, &block)
|
68
|
+
end
|
69
|
+
|
70
|
+
def primary(role)
|
71
|
+
servers.fetch_primary(role)
|
72
|
+
end
|
73
|
+
|
74
|
+
def backend
|
75
|
+
@backend ||= SSHKit
|
76
|
+
end
|
77
|
+
|
78
|
+
attr_writer :backend
|
79
|
+
|
80
|
+
def configure_backend
|
81
|
+
backend.configure do |sshkit|
|
82
|
+
sshkit.format = fetch(:format)
|
83
|
+
sshkit.output_verbosity = fetch(:log_level)
|
84
|
+
sshkit.default_env = fetch(:default_env)
|
85
|
+
sshkit.backend = fetch(:sshkit_backend, SSHKit::Backend::Netssh)
|
86
|
+
sshkit.backend.configure do |backend|
|
87
|
+
backend.pty = fetch(:pty)
|
88
|
+
backend.connection_timeout = fetch(:connection_timeout)
|
89
|
+
backend.ssh_options = (backend.ssh_options || {}).merge(fetch(:ssh_options,{}))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def timestamp
|
95
|
+
@timestamp ||= Time.now.utc
|
96
|
+
end
|
97
|
+
|
98
|
+
def setup_filters
|
99
|
+
@filters = cmdline_filters.clone
|
100
|
+
@filters << Filter.new(:role, ENV['ROLES']) if ENV['ROLES']
|
101
|
+
@filters << Filter.new(:host, ENV['HOSTS']) if ENV['HOSTS']
|
102
|
+
fh = fetch_for(:filter,{}) || {}
|
103
|
+
@filters << Filter.new(:host, fh[:host]) if fh[:host]
|
104
|
+
@filters << Filter.new(:role, fh[:role]) if fh[:role]
|
105
|
+
end
|
106
|
+
|
107
|
+
def add_cmdline_filter(type, values)
|
108
|
+
cmdline_filters << Filter.new(type, values)
|
109
|
+
end
|
110
|
+
|
111
|
+
def filter list
|
112
|
+
setup_filters if @filters.nil?
|
113
|
+
@filters.reduce(list) { |l,f| f.filter l }
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def cmdline_filters
|
119
|
+
@cmdline_filters ||= []
|
120
|
+
end
|
121
|
+
|
122
|
+
def servers
|
123
|
+
@servers ||= Servers.new
|
124
|
+
end
|
125
|
+
|
126
|
+
def config
|
127
|
+
@config ||= Hash.new
|
128
|
+
end
|
129
|
+
|
130
|
+
def fetch_for(key, default, &block)
|
131
|
+
if block_given?
|
132
|
+
config.fetch(key, &block)
|
133
|
+
else
|
134
|
+
config.fetch(key, default)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def callable_without_parameters?(x)
|
139
|
+
x.respond_to?(:call) && ( !x.respond_to?(:arity) || x.arity == 0)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'ferry/configuration'
|
2
|
+
|
3
|
+
module Ferry
|
4
|
+
class Configuration
|
5
|
+
class Filter
|
6
|
+
def initialize type, values = nil
|
7
|
+
raise "Invalid filter type #{type}" unless [:host,:role].include? type
|
8
|
+
av = Array(values).dup
|
9
|
+
@mode = case
|
10
|
+
when av.size == 0 then :none
|
11
|
+
when av.include?(:all) then :all
|
12
|
+
else type
|
13
|
+
end
|
14
|
+
@rex = case @mode
|
15
|
+
when :host
|
16
|
+
av.map!{|v| (v.is_a?(String) && v =~ /^(?<name>[-A-Za-z0-9.]+)(,\g<name>)*$/) ? v.split(',') : v }
|
17
|
+
av.flatten!
|
18
|
+
av.map! do |v|
|
19
|
+
case v
|
20
|
+
when Regexp then v
|
21
|
+
else
|
22
|
+
vs = v.to_s
|
23
|
+
vs =~ /^[-A-Za-z0-9.]+$/ ? vs : Regexp.new(vs)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
Regexp.union av
|
27
|
+
when :role
|
28
|
+
av.map!{|v| v.is_a?(String) ? v.split(',') : v }
|
29
|
+
av.flatten!
|
30
|
+
av.map! do |v|
|
31
|
+
case v
|
32
|
+
when Regexp then v
|
33
|
+
else
|
34
|
+
vs = v.to_s
|
35
|
+
vs =~ %r{^/(.+)/$} ? Regexp.new($1) : %r{^#{vs}$}
|
36
|
+
end
|
37
|
+
end
|
38
|
+
Regexp.union av
|
39
|
+
else
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
def filter servers
|
44
|
+
as = Array(servers)
|
45
|
+
case @mode
|
46
|
+
when :none then return []
|
47
|
+
when :all then return servers
|
48
|
+
when :host
|
49
|
+
as.select {|s| @rex.match s.to_s}
|
50
|
+
when :role
|
51
|
+
as.select { |s| s.is_a?(String) ? false : s.roles.any? {|r| @rex.match r} }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Ferry
|
2
|
+
module Configuration
|
3
|
+
module Question
|
4
|
+
def initialize(key, default, options = {})
|
5
|
+
@key, @default, @options = key, default, options
|
6
|
+
end
|
7
|
+
|
8
|
+
def call
|
9
|
+
ask_question
|
10
|
+
value_or_default
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
attr_reader :key, :default, :options
|
15
|
+
|
16
|
+
def ask_question
|
17
|
+
$stdout.print question
|
18
|
+
end
|
19
|
+
|
20
|
+
def value_or_default
|
21
|
+
if response.empty?
|
22
|
+
default
|
23
|
+
else
|
24
|
+
response
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def response
|
29
|
+
return @response if defined? @response
|
30
|
+
|
31
|
+
@response = (gets || "").chomp
|
32
|
+
end
|
33
|
+
|
34
|
+
def gets
|
35
|
+
if echo?
|
36
|
+
$stdin.gets
|
37
|
+
else
|
38
|
+
$stdin.noecho(&:gets).tap{ $stdout.print "\n" }
|
39
|
+
end
|
40
|
+
rescue Errno::EIO
|
41
|
+
# when stdio gets closed
|
42
|
+
end
|
43
|
+
|
44
|
+
def question
|
45
|
+
I18n.t(:question, key: key, default_value: default, scope: :capistrano)
|
46
|
+
end
|
47
|
+
|
48
|
+
def echo?
|
49
|
+
(options || {}).fetch(:echo, true)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
require 'set'
|
2
|
+
module Ferry
|
3
|
+
class Configuration
|
4
|
+
class Server < SSHKit::Host
|
5
|
+
extend Forwardable
|
6
|
+
def_delegators :properties, :roles, :fetch, :set
|
7
|
+
|
8
|
+
def self.[](host)
|
9
|
+
host.is_a?(Server) ? host : new(host)
|
10
|
+
end
|
11
|
+
|
12
|
+
def add_roles(roles)
|
13
|
+
Array(roles).each { |role| add_role(role) }
|
14
|
+
self
|
15
|
+
end
|
16
|
+
alias roles= add_roles
|
17
|
+
|
18
|
+
def add_role(role)
|
19
|
+
roles.add role.to_sym
|
20
|
+
self
|
21
|
+
end
|
22
|
+
|
23
|
+
def has_role?(role)
|
24
|
+
roles.include? role.to_sym
|
25
|
+
end
|
26
|
+
|
27
|
+
def select?(options)
|
28
|
+
options.each do |k,v|
|
29
|
+
callable = v.respond_to?(:call) ? v: ->(server){server.fetch(v)}
|
30
|
+
result = case k
|
31
|
+
when :filter, :select
|
32
|
+
callable.call(self)
|
33
|
+
when :exclude
|
34
|
+
!callable.call(self)
|
35
|
+
else
|
36
|
+
self.fetch(k) == v
|
37
|
+
end
|
38
|
+
return false unless result
|
39
|
+
end
|
40
|
+
return true
|
41
|
+
end
|
42
|
+
|
43
|
+
def primary
|
44
|
+
self if fetch(:primary)
|
45
|
+
end
|
46
|
+
|
47
|
+
def with(properties)
|
48
|
+
properties.each { |key, value| add_property(key, value) }
|
49
|
+
self
|
50
|
+
end
|
51
|
+
|
52
|
+
def properties
|
53
|
+
@properties ||= Properties.new
|
54
|
+
end
|
55
|
+
|
56
|
+
def netssh_options
|
57
|
+
@netssh_options ||= super.merge( fetch(:ssh_options) || {} )
|
58
|
+
end
|
59
|
+
|
60
|
+
def roles_array
|
61
|
+
roles.to_a
|
62
|
+
end
|
63
|
+
|
64
|
+
def matches?(other)
|
65
|
+
hostname == other.hostname
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def add_property(key, value)
|
71
|
+
if respond_to?("#{key}=")
|
72
|
+
send("#{key}=", value)
|
73
|
+
else
|
74
|
+
set(key, value)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class Properties
|
79
|
+
|
80
|
+
def initialize
|
81
|
+
@properties = {}
|
82
|
+
end
|
83
|
+
|
84
|
+
def set(key, value)
|
85
|
+
pval = @properties[key]
|
86
|
+
if pval.is_a? Hash and value.is_a? Hash
|
87
|
+
pval.merge!(value)
|
88
|
+
elsif pval.is_a? Set and value.is_a? Set
|
89
|
+
pval.merge(value)
|
90
|
+
elsif pval.is_a? Array and value.is_a? Array
|
91
|
+
pval.concat value
|
92
|
+
else
|
93
|
+
@properties[key] = value
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def fetch(key)
|
98
|
+
@properties[key]
|
99
|
+
end
|
100
|
+
|
101
|
+
def respond_to?(method, include_all=false)
|
102
|
+
@properties.has_key?(method)
|
103
|
+
end
|
104
|
+
|
105
|
+
def roles
|
106
|
+
@roles ||= Set.new
|
107
|
+
end
|
108
|
+
|
109
|
+
def keys
|
110
|
+
@properties.keys
|
111
|
+
end
|
112
|
+
|
113
|
+
def method_missing(key, value=nil)
|
114
|
+
if value
|
115
|
+
set(lvalue(key), value)
|
116
|
+
else
|
117
|
+
fetch(key)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
private
|
122
|
+
|
123
|
+
def lvalue(key)
|
124
|
+
key.to_s.chomp('=').to_sym
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|