luban 0.2.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 +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +37 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/exe/luban +3 -0
- data/lib/luban/deployment/cli/application/authenticator.rb +106 -0
- data/lib/luban/deployment/cli/application/base.rb +179 -0
- data/lib/luban/deployment/cli/application/builder.rb +67 -0
- data/lib/luban/deployment/cli/application/publisher.rb +215 -0
- data/lib/luban/deployment/cli/application/repository.rb +175 -0
- data/lib/luban/deployment/cli/application/scm/git.rb +49 -0
- data/lib/luban/deployment/cli/application/scm/rsync.rb +47 -0
- data/lib/luban/deployment/cli/application.rb +5 -0
- data/lib/luban/deployment/cli/command.rb +360 -0
- data/lib/luban/deployment/cli/package/binary.rb +241 -0
- data/lib/luban/deployment/cli/package/dependency.rb +49 -0
- data/lib/luban/deployment/cli/package/dependency_set.rb +71 -0
- data/lib/luban/deployment/cli/package/installer/core.rb +98 -0
- data/lib/luban/deployment/cli/package/installer/install.rb +330 -0
- data/lib/luban/deployment/cli/package/installer/paths.rb +81 -0
- data/lib/luban/deployment/cli/package/installer.rb +3 -0
- data/lib/luban/deployment/cli/package/service.rb +17 -0
- data/lib/luban/deployment/cli/package/worker.rb +43 -0
- data/lib/luban/deployment/cli/package.rb +6 -0
- data/lib/luban/deployment/cli/project.rb +94 -0
- data/lib/luban/deployment/cli.rb +4 -0
- data/lib/luban/deployment/configuration/core.rb +67 -0
- data/lib/luban/deployment/configuration/filter.rb +54 -0
- data/lib/luban/deployment/configuration/question.rb +38 -0
- data/lib/luban/deployment/configuration/server.rb +70 -0
- data/lib/luban/deployment/configuration/server_set.rb +86 -0
- data/lib/luban/deployment/configuration.rb +5 -0
- data/lib/luban/deployment/error.rb +5 -0
- data/lib/luban/deployment/helpers/configuration.rb +159 -0
- data/lib/luban/deployment/helpers/utils.rb +180 -0
- data/lib/luban/deployment/helpers.rb +2 -0
- data/lib/luban/deployment/packages/bundler.rb +81 -0
- data/lib/luban/deployment/packages/git.rb +37 -0
- data/lib/luban/deployment/packages/openssl.rb +59 -0
- data/lib/luban/deployment/packages/ruby.rb +125 -0
- data/lib/luban/deployment/packages/rubygems.rb +89 -0
- data/lib/luban/deployment/packages/yaml.rb +33 -0
- data/lib/luban/deployment/parameters.rb +160 -0
- data/lib/luban/deployment/runner.rb +99 -0
- data/lib/luban/deployment/templates/envrc.erb +30 -0
- data/lib/luban/deployment/templates/unset_envrc.erb +28 -0
- data/lib/luban/deployment/version.rb +5 -0
- data/lib/luban/deployment/worker/base.rb +71 -0
- data/lib/luban/deployment/worker/controller.rb +11 -0
- data/lib/luban/deployment/worker/local.rb +19 -0
- data/lib/luban/deployment/worker/remote.rb +55 -0
- data/lib/luban/deployment/worker/task.rb +25 -0
- data/lib/luban/deployment/worker.rb +4 -0
- data/lib/luban/deployment.rb +8 -0
- data/lib/luban.rb +4 -0
- data/luban.gemspec +29 -0
- metadata +174 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
module Luban
|
2
|
+
module Deployment
|
3
|
+
class Configuration
|
4
|
+
class Question
|
5
|
+
attr_reader :prompt, :default
|
6
|
+
|
7
|
+
def initialize(default:, prompt: nil, echo: true)
|
8
|
+
@default = default
|
9
|
+
@echo = echo
|
10
|
+
@prompt = "#{prompt.to_s}: " unless prompt.nil?
|
11
|
+
end
|
12
|
+
|
13
|
+
def echo?; @echo; end
|
14
|
+
|
15
|
+
def call
|
16
|
+
ask_question
|
17
|
+
get_response
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def ask_question
|
23
|
+
$stdout.print prompt
|
24
|
+
end
|
25
|
+
|
26
|
+
def get_response
|
27
|
+
response = if echo?
|
28
|
+
$stdin.gets.chomp
|
29
|
+
else
|
30
|
+
require 'io/console'
|
31
|
+
$stdin.noecho(&:gets).chomp.tap{ $stdout.print "\n" }
|
32
|
+
end
|
33
|
+
response.empty? ? default : response
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
module Luban
|
4
|
+
module Deployment
|
5
|
+
class Configuration
|
6
|
+
class Server < SSHKit::Host
|
7
|
+
attr_reader :roles
|
8
|
+
|
9
|
+
def self.create(host, **properties)
|
10
|
+
server = host.is_a?(Server) ? host : Server.new(host)
|
11
|
+
server.add_properties(properties) unless properties.empty?
|
12
|
+
server.ssh_options ||= {}
|
13
|
+
server
|
14
|
+
end
|
15
|
+
|
16
|
+
def roles
|
17
|
+
self[:roles]
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_roles(roles)
|
21
|
+
roles.each { |role| add_role(role) }
|
22
|
+
end
|
23
|
+
alias_method :roles=, :add_roles
|
24
|
+
|
25
|
+
def add_role(role)
|
26
|
+
roles.add(role.to_sym)
|
27
|
+
end
|
28
|
+
|
29
|
+
def has_role?(role)
|
30
|
+
roles.include? role.to_sym
|
31
|
+
end
|
32
|
+
|
33
|
+
def properties
|
34
|
+
@properties ||= { :roles => Set.new }
|
35
|
+
end
|
36
|
+
|
37
|
+
def [](key)
|
38
|
+
properties[key]
|
39
|
+
end
|
40
|
+
alias_method :fetch, :[]
|
41
|
+
|
42
|
+
def []=(key, value)
|
43
|
+
if respond_to?("#{key}=")
|
44
|
+
send("#{key}=", value)
|
45
|
+
else
|
46
|
+
pval = properties[key]
|
47
|
+
if pval.is_a? Hash and value.is_a? Hash
|
48
|
+
pval.merge!(value)
|
49
|
+
elsif pval.is_a? Set and value.is_a? Set
|
50
|
+
pval.merge(value)
|
51
|
+
elsif pval.is_a? Array and value.is_a? Array
|
52
|
+
pval.concat value
|
53
|
+
else
|
54
|
+
properties[key] = value
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
alias_method :set, :[]=
|
59
|
+
|
60
|
+
def add_properties(_properties)
|
61
|
+
_properties.each { |k, v| self[k] = v }
|
62
|
+
end
|
63
|
+
|
64
|
+
def primary?
|
65
|
+
self[:primary]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module Luban
|
2
|
+
module Deployment
|
3
|
+
class Configuration
|
4
|
+
class ServerSet
|
5
|
+
include Enumerable
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
@servers = { :all => [] }
|
9
|
+
end
|
10
|
+
|
11
|
+
def all
|
12
|
+
@servers[:all]
|
13
|
+
end
|
14
|
+
|
15
|
+
def available_roles
|
16
|
+
@servers.keys - [:all]
|
17
|
+
end
|
18
|
+
|
19
|
+
def has_server?(server)
|
20
|
+
all.find do |s|
|
21
|
+
s.user == server.user and
|
22
|
+
s.hostname == server.hostname and
|
23
|
+
s.port == server.port
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def add_host(host, **properties)
|
28
|
+
new_server = Server.create(host, properties)
|
29
|
+
if server = has_server?(new_server)
|
30
|
+
server.user = new_server.user unless new_server.user.nil?
|
31
|
+
server.port = new_server.port unless new_server.port.nil?
|
32
|
+
server.add_properties(properties)
|
33
|
+
server
|
34
|
+
else
|
35
|
+
all << new_server
|
36
|
+
new_server.roles.each do |role|
|
37
|
+
@servers[role] ||= []
|
38
|
+
@servers[role] << new_server
|
39
|
+
end
|
40
|
+
new_server
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_hosts_for_role(role, hosts, **properties)
|
45
|
+
properties_deepcopy = Marshal.dump(properties.merge(:roles => Array(role)))
|
46
|
+
Array(hosts).each { |host| add_host(host, Marshal.load(properties_deepcopy)) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def find_by_roles(roles, **opts)
|
50
|
+
roles.inject([]) do |result, role|
|
51
|
+
result.concat(find_by_role(role, opts))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_by_role(role, **opts)
|
56
|
+
if @servers.has_key?(role)
|
57
|
+
opts.inject(@servers[role]) do |_servers, (action, key)|
|
58
|
+
send(action, _servers, key)
|
59
|
+
end
|
60
|
+
else
|
61
|
+
[]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_primary(role)
|
66
|
+
_servers = find_by_role(role)
|
67
|
+
_servers.find(&:primary?) || _servers.first
|
68
|
+
end
|
69
|
+
|
70
|
+
def each
|
71
|
+
all.each { |server| yield server }
|
72
|
+
end
|
73
|
+
|
74
|
+
protected
|
75
|
+
|
76
|
+
def exclude(_servers, key)
|
77
|
+
_servers.select { |server| !server[key] }
|
78
|
+
end
|
79
|
+
|
80
|
+
def filter(_servers, key)
|
81
|
+
_servers.select { |server| server[key] }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
module Luban
|
2
|
+
module Deployment
|
3
|
+
module Helpers
|
4
|
+
module Configuration
|
5
|
+
attr_accessor :config
|
6
|
+
|
7
|
+
def config
|
8
|
+
@config ||= Luban::Deployment::Configuration.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def fetch(key, *args, &blk)
|
12
|
+
config.fetch(key, *args, &blk)
|
13
|
+
end
|
14
|
+
|
15
|
+
def set(key, *args, &blk)
|
16
|
+
config.set(key, *args, &blk)
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_default(key, *args, &blk)
|
20
|
+
config.set_default(key, *args, &blk)
|
21
|
+
end
|
22
|
+
|
23
|
+
def ask(key=nil, default: nil, prompt: nil, echo: true)
|
24
|
+
config.ask(key, default: default, echo: echo, prompt: prompt)
|
25
|
+
end
|
26
|
+
|
27
|
+
def role(name, hosts, **properties)
|
28
|
+
config.role(name, hosts, properties)
|
29
|
+
end
|
30
|
+
|
31
|
+
def server(name, **properties)
|
32
|
+
config.server(name, properties)
|
33
|
+
end
|
34
|
+
|
35
|
+
def roles(*names)
|
36
|
+
config.roles(*names)
|
37
|
+
end
|
38
|
+
|
39
|
+
def release_roles(*names)
|
40
|
+
config.release_roles(*names)
|
41
|
+
end
|
42
|
+
|
43
|
+
def primary(role)
|
44
|
+
config.primary(role)
|
45
|
+
end
|
46
|
+
|
47
|
+
def load_configuration_file(config_file, optional: false)
|
48
|
+
if File.file?(config_file)
|
49
|
+
if error = syntax_error?(config_file)
|
50
|
+
abort "Aborted! Syntax errors in configuration file.\n#{error}"
|
51
|
+
else
|
52
|
+
instance_eval(File.read(config_file))
|
53
|
+
end
|
54
|
+
else
|
55
|
+
unless optional
|
56
|
+
abort "Aborted! Configuration file is NOT found: #{config_file}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def syntax_error?(file)
|
62
|
+
_stderr = $stderr
|
63
|
+
$stderr = StringIO.new('', 'w')
|
64
|
+
# ONLY work for MRI Ruby
|
65
|
+
RubyVM::InstructionSequence.compile_file(file)
|
66
|
+
$stderr.string.chomp.empty? ? false : $stderr.string
|
67
|
+
ensure
|
68
|
+
$stderr = _stderr
|
69
|
+
end
|
70
|
+
|
71
|
+
def find_template_file(file_name)
|
72
|
+
path = find_template_file_by_config_finder(file_name) ||
|
73
|
+
find_default_template_file(file_name)
|
74
|
+
raise RuntimeError, "Template file is NOT found: #{file_name}." if path.nil?
|
75
|
+
path
|
76
|
+
end
|
77
|
+
|
78
|
+
protected
|
79
|
+
|
80
|
+
def find_template_file_by_config_finder(file_name)
|
81
|
+
path = config_finder[:application].find_template_file(file_name) ||
|
82
|
+
config_finder[:project].find_template_file(file_name)
|
83
|
+
end
|
84
|
+
|
85
|
+
def find_default_template_file(file_name)
|
86
|
+
path = File.expand_path(File.join(File.dirname(__FILE__), '..',
|
87
|
+
'templates', file_name))
|
88
|
+
return path if File.file?(path)
|
89
|
+
end
|
90
|
+
|
91
|
+
class Finder
|
92
|
+
class Project < Finder
|
93
|
+
def base_path; base_path ||= target.work_dir; end
|
94
|
+
end
|
95
|
+
|
96
|
+
class Application < Finder
|
97
|
+
def base_path; base_path ||= target.apps_path.join(target.application); end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.project(target); Project.new(target); end
|
101
|
+
def self.application(target); Application.new(target); end
|
102
|
+
|
103
|
+
attr_reader :target
|
104
|
+
attr_reader :base_path
|
105
|
+
attr_reader :config_root
|
106
|
+
attr_reader :config_file
|
107
|
+
attr_reader :config_path
|
108
|
+
attr_reader :templates_path
|
109
|
+
attr_reader :stage_config_file
|
110
|
+
attr_reader :stage_config_path
|
111
|
+
attr_reader :stage_templates_path
|
112
|
+
|
113
|
+
def initialize(target)
|
114
|
+
@target = target
|
115
|
+
set_config_paths
|
116
|
+
end
|
117
|
+
|
118
|
+
def deployfile; @deployfile ||= 'deploy.rb'; end
|
119
|
+
def stagefile; @stagefile ||= "#{target.stage}.rb"; end
|
120
|
+
|
121
|
+
def load_configuration
|
122
|
+
load_general_configuration
|
123
|
+
load_stage_configuration
|
124
|
+
end
|
125
|
+
|
126
|
+
def load_general_configuration
|
127
|
+
target.load_configuration_file(config_file)
|
128
|
+
end
|
129
|
+
|
130
|
+
def load_stage_configuration
|
131
|
+
target.load_configuration_file(stage_config_file)
|
132
|
+
if File.directory?(stage_config_path)
|
133
|
+
Dir[stage_config_path.join("{packages}/**/*.rb")].each do |file|
|
134
|
+
target.load_configuration_file(file)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def find_template_file(file_name)
|
140
|
+
return file_path if File.file?(file_path = stage_templates_path.join(file_name))
|
141
|
+
return file_path if File.file?(file_path = templates_path.join(file_name))
|
142
|
+
end
|
143
|
+
|
144
|
+
protected
|
145
|
+
|
146
|
+
def set_config_paths
|
147
|
+
@config_root = base_path.join('config')
|
148
|
+
@config_file = @config_root.join(deployfile)
|
149
|
+
@config_path = @config_root.join(deployfile.sub('.rb', ''))
|
150
|
+
@templates_path = @config_root.join('templates')
|
151
|
+
@stage_config_file = @config_path.join(stagefile)
|
152
|
+
@stage_config_path = @config_path.join(target.stage)
|
153
|
+
@stage_templates_path = @stage_config_path.join('templates')
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require "digest/md5"
|
2
|
+
|
3
|
+
module Luban
|
4
|
+
module Deployment
|
5
|
+
module Helpers
|
6
|
+
module Utils
|
7
|
+
LogLevels = %i(fatal error warn info debug trace)
|
8
|
+
|
9
|
+
attr_reader :backend
|
10
|
+
|
11
|
+
def check_pass?(type, *args)
|
12
|
+
send("#{type}?", *args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def directory?(path)
|
16
|
+
test "[ -d #{path} ]"
|
17
|
+
end
|
18
|
+
|
19
|
+
def file?(path)
|
20
|
+
test "[ -f #{path} ]"
|
21
|
+
end
|
22
|
+
|
23
|
+
def symlink?(path)
|
24
|
+
test "[ -L #{path} ]"
|
25
|
+
end
|
26
|
+
|
27
|
+
def match?(cmd, expect)
|
28
|
+
expect = Regexp.new(Regexp.escape(expect.to_s)) unless expect.is_a?(Regexp)
|
29
|
+
output = capture(cmd)
|
30
|
+
output =~ expect
|
31
|
+
end
|
32
|
+
|
33
|
+
def assure(type, *args)
|
34
|
+
unless check_pass?(type, *args)
|
35
|
+
if block_given?
|
36
|
+
yield
|
37
|
+
else
|
38
|
+
abort "Aborted! #{type} dependency with #{args.inspect} are not met and no block is given to resolve it."
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def assure_dirs(*dirs)
|
44
|
+
dirs.each { |dir| assure(:directory, dir) { mkdir(dir) } }
|
45
|
+
end
|
46
|
+
|
47
|
+
def assure_symlink(source_path, target_path)
|
48
|
+
unless symlink?(target_path) and readlink(target_path) == source_path.to_s
|
49
|
+
ln(source_path, target_path)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def mkdir(*opts, path)
|
54
|
+
execute(:mkdir, '-p', *opts, path)
|
55
|
+
end
|
56
|
+
|
57
|
+
def rm(*opts, path)
|
58
|
+
execute(:rm, '-fr', *opts, path)
|
59
|
+
end
|
60
|
+
alias_method :rmdir, :rm
|
61
|
+
|
62
|
+
def chmod(*opts, path)
|
63
|
+
execute(:chmod, '-R', *opts, path)
|
64
|
+
end
|
65
|
+
|
66
|
+
def ln(*opts, source_path, target_path)
|
67
|
+
execute(:ln, '-nfs', *opts, source_path, target_path)
|
68
|
+
end
|
69
|
+
|
70
|
+
def mv(*opts, source_path, target_path)
|
71
|
+
execute(:mv, *opts, source_path, target_path)
|
72
|
+
end
|
73
|
+
|
74
|
+
def cp(*opts, source_path, target_path)
|
75
|
+
execute(*opts, source_path, target_path)
|
76
|
+
end
|
77
|
+
|
78
|
+
def readlink(source_file)
|
79
|
+
capture("$(type -p readlink greadlink|head -1) #{source_file}")
|
80
|
+
end
|
81
|
+
|
82
|
+
def md5_for_file(file)
|
83
|
+
capture(:cat, "#{file} 2>/dev/null | openssl md5")
|
84
|
+
end
|
85
|
+
|
86
|
+
def sudo(*args)
|
87
|
+
execute(:sudo, *args)
|
88
|
+
end
|
89
|
+
|
90
|
+
def os_name
|
91
|
+
@os_name ||= capture("uname -s")
|
92
|
+
end
|
93
|
+
|
94
|
+
def os_release
|
95
|
+
@os_release ||= capture("uname -r")
|
96
|
+
end
|
97
|
+
|
98
|
+
def hardware_name
|
99
|
+
@hardware_name ||= capture("uname -m")
|
100
|
+
end
|
101
|
+
|
102
|
+
def user_home
|
103
|
+
@user_home ||= capture("eval echo ~")
|
104
|
+
end
|
105
|
+
|
106
|
+
def url_exists?(download_url)
|
107
|
+
# Sent HEAD request to avoid downloading the file contents
|
108
|
+
test("curl -s -L -I -o /dev/null -f #{download_url}")
|
109
|
+
|
110
|
+
# Other effective ways to check url existence with curl
|
111
|
+
|
112
|
+
# In case HEAD request is refused,
|
113
|
+
# only the first byte of the file is requested
|
114
|
+
# test("curl -s -L -o /dev/null -f -r 0-0 #{download_url}")
|
115
|
+
|
116
|
+
# Alternatively, http code (200) can be validated
|
117
|
+
# capture("curl -s -L -I -o /dev/null -w '%{http_code}' #{download_url}") == '200'
|
118
|
+
end
|
119
|
+
|
120
|
+
def upload_by_template(file_to_upload:, template_file:, auto_revision: false, **opts)
|
121
|
+
template = File.read(template_file)
|
122
|
+
|
123
|
+
if auto_revision and file?(file_to_upload)
|
124
|
+
revision = Digest::MD5.hexdigest(template)
|
125
|
+
return if revision_match?(file_to_upload, revision)
|
126
|
+
end
|
127
|
+
|
128
|
+
require 'erb'
|
129
|
+
context = opts[:binding] || binding
|
130
|
+
upload!(StringIO.new(ERB.new(template, nil, '<>').result(context)), file_to_upload)
|
131
|
+
yield file_to_upload if block_given?
|
132
|
+
end
|
133
|
+
|
134
|
+
def revision_match?(file_to_upload, revision)
|
135
|
+
match?("grep \"Revision: \" #{file_to_upload}", revision)
|
136
|
+
end
|
137
|
+
|
138
|
+
[:test, :make, :within, :with, :as, :execute,
|
139
|
+
:upload!, :download!].each do |cmd|
|
140
|
+
define_method(cmd) do |*args, &blk|
|
141
|
+
backend.send(__method__, *args, &blk)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def capture(*args, &blk)
|
146
|
+
backend.capture(*args, &blk).chomp
|
147
|
+
end
|
148
|
+
|
149
|
+
def md5_matched?(file_path, md5)
|
150
|
+
file?(file_path) and md5 == md5_for_file(file_path)
|
151
|
+
end
|
152
|
+
|
153
|
+
#def execute(*args, &blk)
|
154
|
+
# if args.last.is_a?(::Hash)
|
155
|
+
# args.last.merge(verbosity: SSHKit::Logger::DEBUG)
|
156
|
+
# else
|
157
|
+
# args.push(verbosity: SSHKit::Logger::DEBUG)
|
158
|
+
# end
|
159
|
+
# backend.execute(*args, &blk)
|
160
|
+
#end
|
161
|
+
|
162
|
+
LogLevels.each do |cmd|
|
163
|
+
define_method(cmd) { |msg| backend.send(__method__, "[#{hostname}] #{msg}") }
|
164
|
+
end
|
165
|
+
|
166
|
+
def host
|
167
|
+
@host ||= backend.host
|
168
|
+
end
|
169
|
+
|
170
|
+
def hostname
|
171
|
+
@hostname ||= host.hostname
|
172
|
+
end
|
173
|
+
|
174
|
+
def method_missing(sym, *args, &blk)
|
175
|
+
backend.respond_to?(sym) ? backend.send(sym, *args, &blk) : super
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Luban
|
2
|
+
module Deployment
|
3
|
+
module Packages
|
4
|
+
class Bundler < Luban::Deployment::Package::Binary
|
5
|
+
protected
|
6
|
+
|
7
|
+
def setup_install_tasks
|
8
|
+
super
|
9
|
+
commands[:install].switch :install_doc, "Install Bundler document"
|
10
|
+
end
|
11
|
+
|
12
|
+
class Installer < Luban::Deployment::Package::Installer
|
13
|
+
def install_doc?
|
14
|
+
task.opts.install_doc
|
15
|
+
end
|
16
|
+
|
17
|
+
def package_version
|
18
|
+
parent.task.opts.bundler || super
|
19
|
+
end
|
20
|
+
|
21
|
+
def package_path
|
22
|
+
parent.package_path
|
23
|
+
end
|
24
|
+
|
25
|
+
def install_path
|
26
|
+
parent.install_path
|
27
|
+
end
|
28
|
+
|
29
|
+
def bundler_executable
|
30
|
+
@bundler_executable ||= bin_path.join('bundle')
|
31
|
+
end
|
32
|
+
|
33
|
+
def gem_executable
|
34
|
+
parent.gem_executable
|
35
|
+
end
|
36
|
+
|
37
|
+
def src_file_extname
|
38
|
+
@src_file_extname ||= 'gem'
|
39
|
+
end
|
40
|
+
|
41
|
+
def source_repo
|
42
|
+
#@source_repo ||= "http://production.cf.rubygems.org"
|
43
|
+
@source_repo ||= "https://rubygems.org"
|
44
|
+
end
|
45
|
+
|
46
|
+
def source_url_root
|
47
|
+
@source_url_root ||= "downloads"
|
48
|
+
end
|
49
|
+
|
50
|
+
def installed?
|
51
|
+
return false unless file?(bundler_executable)
|
52
|
+
match?("#{bundler_executable} -v", package_version)
|
53
|
+
end
|
54
|
+
|
55
|
+
protected
|
56
|
+
|
57
|
+
def validate
|
58
|
+
if parent.nil?
|
59
|
+
abort "Aborted! Parent package for Bundler MUST be provided."
|
60
|
+
end
|
61
|
+
unless parent.is_a?(Ruby::Installer)
|
62
|
+
abort "Aborted! Parent package for Bundler MUST be an instance of #{Ruby::Installer.name}"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def uncompress_package; end
|
67
|
+
def configure_package; end
|
68
|
+
def make_package; end
|
69
|
+
def update_binstubs!; end
|
70
|
+
|
71
|
+
def install_package!
|
72
|
+
install_opts = ['--local']
|
73
|
+
install_opts << "--no-document" unless install_doc?
|
74
|
+
test("#{gem_executable} uninstall bundler -a -x -I >> #{install_log_file_path} 2>&1") and
|
75
|
+
test("#{gem_executable} install #{install_opts.join(' ')} #{src_file_path} >> #{install_log_file_path} 2>&1")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Luban
|
2
|
+
module Deployment
|
3
|
+
module Packages
|
4
|
+
class Git < Luban::Deployment::Package::Binary
|
5
|
+
apply_to :all do
|
6
|
+
before_install do
|
7
|
+
depend_on 'openssl', version: '1.0.2e'
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class Installer < Luban::Deployment::Package::Installer
|
12
|
+
def git_executable
|
13
|
+
@git_executable ||= bin_path.join('git')
|
14
|
+
end
|
15
|
+
|
16
|
+
def source_repo
|
17
|
+
@source_repo ||= "https://www.kernel.org"
|
18
|
+
end
|
19
|
+
|
20
|
+
def source_url_root
|
21
|
+
@source_url_root ||= "pub/software/scm/git"
|
22
|
+
end
|
23
|
+
|
24
|
+
def installed?
|
25
|
+
return false unless file?(git_executable)
|
26
|
+
pattern = "version #{package_major_version}"
|
27
|
+
match?("#{git_executable} --version", pattern)
|
28
|
+
end
|
29
|
+
|
30
|
+
def with_openssl_dir(dir)
|
31
|
+
@configure_opts << "--with-openssl=#{dir}"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|