ferry 1.3.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,69 @@
1
+ require 'set'
2
+ require 'ferry/configuration'
3
+ require 'ferry/configuration/filter'
4
+
5
+ module Ferry
6
+ class Configuration
7
+ class Servers
8
+ include Enumerable
9
+
10
+ def add_host(host, properties={})
11
+ new_host = Server[host]
12
+ if server = servers.find { |s| s.matches? new_host }
13
+ server.user = new_host.user if new_host.user
14
+ server.port = new_host.port if new_host.port
15
+ server.with(properties)
16
+ else
17
+ servers << new_host.with(properties)
18
+ end
19
+ end
20
+
21
+ def add_role(role, hosts, options={})
22
+ options_deepcopy = Marshal.dump(options.merge(roles: role))
23
+ Array(hosts).each { |host| add_host(host, Marshal.load(options_deepcopy)) }
24
+ end
25
+
26
+ def roles_for(names)
27
+ options = extract_options(names)
28
+ s = Filter.new(:role, names).filter(servers)
29
+ s.select { |server| server.select?(options) }
30
+ end
31
+
32
+ def role_properties_for(rolenames)
33
+ roles = rolenames.to_set
34
+ rps = Set.new unless block_given?
35
+ roles_for(rolenames).each do |host|
36
+ host.roles.intersection(roles).each do |role|
37
+ [host.properties.fetch(role)].flatten(1).each do |props|
38
+ if block_given?
39
+ yield host, role, props
40
+ else
41
+ rps << (props || {}).merge( role: role, hostname: host.hostname )
42
+ end
43
+ end
44
+ end
45
+ end
46
+ block_given? ? nil: rps
47
+ end
48
+
49
+ def fetch_primary(role)
50
+ hosts = roles_for([role])
51
+ hosts.find(&:primary) || hosts.first
52
+ end
53
+
54
+ def each
55
+ servers.each { |server| yield server }
56
+ end
57
+
58
+ private
59
+
60
+ def servers
61
+ @servers ||= []
62
+ end
63
+
64
+ def extract_options(array)
65
+ array.last.is_a?(::Hash) ? array.pop : {}
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,3 @@
1
+ # default options for user to replace in the deploy_ferry.rb
2
+ # still not sure what we can put here ...
3
+ # see deploy_ferry.rb.erb for ideas
@@ -0,0 +1,3 @@
1
+ require 'ferry/framework'
2
+
3
+ load File.expand_path("../tasks/deploy.rake", __FILE__)
@@ -0,0 +1,2 @@
1
+ dotfile = Pathname.new(File.join(Dir.home, '.ferryfile'))
2
+ load dotfile if dotfile.file?
@@ -0,0 +1,64 @@
1
+ require 'etc'
2
+ require 'ferry/dsl/task_enhancements'
3
+ require 'ferry/dsl/paths'
4
+ require 'ferry/dsl/stages'
5
+ require 'ferry/dsl/env'
6
+ require 'ferry/configuration/filter'
7
+
8
+ module Ferry
9
+ module DSL
10
+ include TaskEnhancements
11
+ include Env
12
+ include Paths
13
+ include Stages
14
+
15
+ def invoke(task, *args)
16
+ Rake::Task[task].invoke(*args)
17
+ end
18
+
19
+ def t(key, options={})
20
+ I18n.t(key, options.merge(scope: :ferry))
21
+ end
22
+
23
+ def scm
24
+ fetch(:scm)
25
+ end
26
+
27
+ def sudo(*args)
28
+ execute :sudo, *args
29
+ end
30
+
31
+ def revision_log_message
32
+ fetch(:revision_log_message,
33
+ t(:revision_log_message,
34
+ branch: fetch(:branch),
35
+ user: local_user,
36
+ sha: fetch(:current_revision),
37
+ release: fetch(:release_timestamp))
38
+ )
39
+ end
40
+
41
+ def rollback_log_message
42
+ t(:rollback_log_message, user: local_user, release: fetch(:rollback_timestamp))
43
+ end
44
+
45
+ def local_user
46
+ fetch(:local_user)
47
+ end
48
+
49
+ def lock(locked_version)
50
+ VersionValidator.new(locked_version).verify
51
+ end
52
+
53
+ def on(hosts, options={}, &block)
54
+ subset_copy = Marshal.dump(Configuration.env.filter(hosts))
55
+ SSHKit::Coordinator.new(Marshal.load(subset_copy)).each(options, &block)
56
+ end
57
+
58
+ def run_locally(&block)
59
+ SSHKit::Backend::Local.new(&block).run
60
+ end
61
+
62
+ end
63
+ end
64
+ self.extend Ferry::DSL
@@ -0,0 +1,81 @@
1
+ module Ferry
2
+ module DSL
3
+ module Env
4
+
5
+ def configure_backend
6
+ env.configure_backend
7
+ end
8
+
9
+ def fetch(key, default=nil, &block)
10
+ env.fetch(key, default, &block)
11
+ end
12
+
13
+ def any?(key)
14
+ value = fetch(key)
15
+ if value && value.respond_to?(:any?)
16
+ value.any?
17
+ else
18
+ !fetch(key).nil?
19
+ end
20
+ end
21
+
22
+ def set(key, value)
23
+ env.set(key, value)
24
+ end
25
+
26
+ def set_if_empty(key, value)
27
+ env.set_if_empty(key, value)
28
+ end
29
+
30
+ def delete(key)
31
+ env.delete(key)
32
+ end
33
+
34
+ def ask(key, value, options={})
35
+ env.ask(key, value, options)
36
+ end
37
+
38
+ def role(name, servers, options={})
39
+ env.role(name, servers, options)
40
+ end
41
+
42
+ def server(name, properties={})
43
+ env.server(name, properties)
44
+ end
45
+
46
+ def roles(*names)
47
+ env.roles_for(names.flatten)
48
+ end
49
+
50
+ def role_properties(*names, &block)
51
+ env.role_properties_for(names, &block)
52
+ end
53
+
54
+ def release_roles(*names)
55
+ if names.last.is_a? Hash
56
+ names.last.merge!({ :exclude => :no_release })
57
+ else
58
+ names << { exclude: :no_release }
59
+ end
60
+ roles(*names)
61
+ end
62
+
63
+ def primary(role)
64
+ env.primary(role)
65
+ end
66
+
67
+ def env
68
+ Configuration.env
69
+ end
70
+
71
+ def release_timestamp
72
+ env.timestamp.strftime("%Y%m%d%H%M%S")
73
+ end
74
+
75
+ def asset_timestamp
76
+ env.timestamp.strftime("%Y%m%d%H%M.%S")
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,103 @@
1
+ require 'pathname'
2
+ module Ferry
3
+ module DSL
4
+ module Paths
5
+
6
+ def deploy_to
7
+ fetch(:deploy_to)
8
+ end
9
+
10
+ def deploy_path
11
+ Pathname.new(deploy_to)
12
+ end
13
+
14
+ def current_path
15
+ deploy_path.join('current')
16
+ end
17
+
18
+ def releases_path
19
+ deploy_path.join('releases')
20
+ end
21
+
22
+ def release_path
23
+ fetch(:release_path, current_path)
24
+ end
25
+
26
+ def set_release_path(timestamp=now)
27
+ set(:release_timestamp, timestamp)
28
+ set(:release_path, releases_path.join(timestamp))
29
+ end
30
+
31
+ def stage_config_path
32
+ Pathname.new fetch(:stage_config_path, 'config/deploy')
33
+ end
34
+
35
+ def deploy_config_path
36
+ Pathname.new fetch(:deploy_config_path, 'config/deploy.rb')
37
+ end
38
+
39
+ def repo_url
40
+ require 'cgi'
41
+ require 'uri'
42
+ if fetch(:git_http_username) and fetch(:git_http_password)
43
+ URI.parse(fetch(:repo_url)).tap do |repo_uri|
44
+ repo_uri.user = fetch(:git_http_username)
45
+ repo_uri.password = CGI.escape(fetch(:git_http_password))
46
+ end.to_s
47
+ elsif fetch(:git_http_username)
48
+ URI.parse(fetch(:repo_url)).tap do |repo_uri|
49
+ repo_uri.user = fetch(:git_http_username)
50
+ end.to_s
51
+ else
52
+ fetch(:repo_url)
53
+ end
54
+ end
55
+
56
+ def repo_path
57
+ Pathname.new(fetch(:repo_path, ->(){deploy_path.join('repo')}))
58
+ end
59
+
60
+ def shared_path
61
+ deploy_path.join('shared')
62
+ end
63
+
64
+ def revision_log
65
+ deploy_path.join('revisions.log')
66
+ end
67
+
68
+ def now
69
+ env.timestamp.strftime("%Y%m%d%H%M%S")
70
+ end
71
+
72
+ def asset_timestamp
73
+ env.timestamp.strftime("%Y%m%d%H%M.%S")
74
+ end
75
+
76
+ def linked_dirs(parent)
77
+ paths = fetch(:linked_dirs)
78
+ join_paths(parent, paths)
79
+ end
80
+
81
+ def linked_files(parent)
82
+ paths = fetch(:linked_files)
83
+ join_paths(parent, paths)
84
+ end
85
+
86
+ def linked_file_dirs(parent)
87
+ map_dirnames(linked_files(parent))
88
+ end
89
+
90
+ def linked_dir_parents(parent)
91
+ map_dirnames(linked_dirs(parent))
92
+ end
93
+
94
+ def join_paths(parent, paths)
95
+ paths.map { |path| parent.join(path) }
96
+ end
97
+
98
+ def map_dirnames(paths)
99
+ paths.map { |path| path.dirname }
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,19 @@
1
+ module Ferry
2
+ module DSL
3
+ module Stages
4
+
5
+ def stages
6
+ Dir[stage_definitions].map { |f| File.basename(f, '.rb') }
7
+ end
8
+
9
+ def stage_definitions
10
+ stage_config_path.join('*.rb')
11
+ end
12
+
13
+ def stage_set?
14
+ !!fetch(:stage, false)
15
+ end
16
+
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,65 @@
1
+ require 'ferry/upload_task'
2
+
3
+ module Ferry
4
+ module TaskEnhancements
5
+ def before(task, prerequisite, *args, &block)
6
+ prerequisite = Rake::Task.define_task(prerequisite, *args, &block) if block_given?
7
+ Rake::Task[task].enhance [prerequisite]
8
+ end
9
+
10
+ def after(task, post_task, *args, &block)
11
+ Rake::Task.define_task(post_task, *args, &block) if block_given?
12
+ Rake::Task[task].enhance do
13
+ Rake::Task[post_task].invoke
14
+ end
15
+ end
16
+
17
+ def remote_file(task)
18
+ target_roles = task.delete(:roles) { :all }
19
+ define_remote_file_task(task, target_roles)
20
+ end
21
+
22
+ def define_remote_file_task(task, target_roles)
23
+ Ferry::UploadTask.define_task(task) do |t|
24
+ prerequisite_file = t.prerequisites.first
25
+ file = shared_path.join(t.name)
26
+
27
+ on roles(target_roles) do
28
+ unless test "[ -f #{file.to_s.shellescape} ]"
29
+ info "Uploading #{prerequisite_file} to #{file}"
30
+ upload! File.open(prerequisite_file), file
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+
37
+ def ensure_stage
38
+ Rake::Task.define_task(:ensure_stage) do
39
+ unless stage_set?
40
+ puts t(:stage_not_set)
41
+ exit 1
42
+ end
43
+ end
44
+ end
45
+
46
+ def tasks_without_stage_dependency
47
+ stages + default_tasks
48
+ end
49
+
50
+ def default_tasks
51
+ %w{install}
52
+ end
53
+
54
+ def exit_deploy_because_of_exception(ex)
55
+ warn t(:deploy_failed, ex: ex.message)
56
+ invoke 'deploy:failed'
57
+ exit(false)
58
+ end
59
+
60
+ def deploying?
61
+ fetch(:deploying, false)
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,2 @@
1
+ load File.expand_path("../tasks/framework.rake", __FILE__)
2
+ require 'ferry/install'
@@ -0,0 +1,18 @@
1
+ require 'i18n'
2
+
3
+ en = {
4
+ starting: 'Starting',
5
+ installing: 'Installing',
6
+ set_sail: 'Set Sail!',
7
+ moving: 'Moving',
8
+ completed: 'Completed'
9
+ },
10
+ error: 'Some error'
11
+ }
12
+ }
13
+
14
+ I18n.backend.store_translations(:en, { ferry: en })
15
+
16
+ if I18n.respond_to?(:enforce_available_locales=)
17
+ I18n.enforce_available_locales = true
18
+ end
@@ -0,0 +1 @@
1
+ load File.expand_path(File.join(File.dirname(__FILE__),'tasks/install.rake'))