fpm-fry 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/fpm-fry +10 -0
- data/lib/cabin/nice_output.rb +70 -0
- data/lib/fpm/fry/block_enumerator.rb +25 -0
- data/lib/fpm/fry/build_output_parser.rb +22 -0
- data/lib/fpm/fry/client.rb +162 -0
- data/lib/fpm/fry/command/cook.rb +370 -0
- data/lib/fpm/fry/command.rb +90 -0
- data/lib/fpm/fry/detector.rb +109 -0
- data/lib/fpm/fry/docker_file.rb +149 -0
- data/lib/fpm/fry/joined_io.rb +63 -0
- data/lib/fpm/fry/os_db.rb +35 -0
- data/lib/fpm/fry/plugin/alternatives.rb +90 -0
- data/lib/fpm/fry/plugin/edit_staging.rb +66 -0
- data/lib/fpm/fry/plugin/exclude.rb +18 -0
- data/lib/fpm/fry/plugin/init.rb +53 -0
- data/lib/fpm/fry/plugin/platforms.rb +10 -0
- data/lib/fpm/fry/plugin/script_helper.rb +176 -0
- data/lib/fpm/fry/plugin/service.rb +100 -0
- data/lib/fpm/fry/plugin.rb +3 -0
- data/lib/fpm/fry/recipe/builder.rb +267 -0
- data/lib/fpm/fry/recipe.rb +141 -0
- data/lib/fpm/fry/source/dir.rb +56 -0
- data/lib/fpm/fry/source/git.rb +90 -0
- data/lib/fpm/fry/source/package.rb +202 -0
- data/lib/fpm/fry/source/patched.rb +118 -0
- data/lib/fpm/fry/source.rb +47 -0
- data/lib/fpm/fry/stream_parser.rb +98 -0
- data/lib/fpm/fry/tar.rb +71 -0
- data/lib/fpm/fry/templates/debian/after_install.erb +9 -0
- data/lib/fpm/fry/templates/debian/before_install.erb +13 -0
- data/lib/fpm/fry/templates/debian/before_remove.erb +13 -0
- data/lib/fpm/fry/templates/redhat/after_install.erb +2 -0
- data/lib/fpm/fry/templates/redhat/before_install.erb +6 -0
- data/lib/fpm/fry/templates/redhat/before_remove.erb +6 -0
- data/lib/fpm/fry/templates/sysv.erb +125 -0
- data/lib/fpm/fry/templates/upstart.erb +15 -0
- data/lib/fpm/fry/ui.rb +12 -0
- data/lib/fpm/package/docker.rb +186 -0
- metadata +111 -0
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'tmpdir'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'clamp'
|
4
|
+
require 'json'
|
5
|
+
require 'forwardable'
|
6
|
+
require 'fpm/fry/ui'
|
7
|
+
require 'fpm/command'
|
8
|
+
|
9
|
+
module FPM; module Fry
|
10
|
+
|
11
|
+
class Command < Clamp::Command
|
12
|
+
|
13
|
+
option '--debug', :flag, 'Turns on debugging'
|
14
|
+
option '--[no-]tls', :flag, 'Turns on tls ( default is false for schema unix, tcp and http and true for https )'
|
15
|
+
option '--[no-]tlsverify', :flag, 'Turns off tls peer verification', default:true, environment_variable: 'DOCKER_TLS_VERIFY'
|
16
|
+
|
17
|
+
subcommand 'fpm', 'Works like fpm but with docker support', FPM::Command
|
18
|
+
|
19
|
+
def client
|
20
|
+
@client ||= begin
|
21
|
+
client = FPM::Fry::Client.new(
|
22
|
+
logger: logger,
|
23
|
+
tls: tls?, tlsverify: tlsverify?
|
24
|
+
)
|
25
|
+
logger.info("Docker connected",client.server_version)
|
26
|
+
client
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_writer :client
|
31
|
+
|
32
|
+
subcommand 'detect', 'Detects distribution from an image, a container or a given name' do
|
33
|
+
|
34
|
+
option '--image', 'image', 'Docker image to detect'
|
35
|
+
option '--container', 'container', 'Docker container to detect'
|
36
|
+
option '--distribution', 'distribution', 'Distribution name to detect'
|
37
|
+
|
38
|
+
attr :ui
|
39
|
+
extend Forwardable
|
40
|
+
def_delegators :ui, :logger
|
41
|
+
|
42
|
+
def initialize(*_)
|
43
|
+
super
|
44
|
+
@ui = UI.new()
|
45
|
+
if debug?
|
46
|
+
ui.logger.level = :debug
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def execute
|
51
|
+
require 'fpm/fry/os_db'
|
52
|
+
require 'fpm/fry/detector'
|
53
|
+
|
54
|
+
if image
|
55
|
+
d = Detector::Image.new(client, image)
|
56
|
+
elsif distribution
|
57
|
+
d = Detector::String.new(distribution)
|
58
|
+
elsif container
|
59
|
+
d = Detector::Container.new(client, container)
|
60
|
+
else
|
61
|
+
logger.error("Please supply either --image, --distribution or --container")
|
62
|
+
return 1
|
63
|
+
end
|
64
|
+
|
65
|
+
begin
|
66
|
+
if d.detect!
|
67
|
+
data = {distribution: d.distribution, version: d.version}
|
68
|
+
if i = OsDb[d.distribution]
|
69
|
+
data[:flavour] = i[:flavour]
|
70
|
+
else
|
71
|
+
data[:flavour] = "unknown"
|
72
|
+
end
|
73
|
+
logger.info("Detected distribution",data)
|
74
|
+
return 0
|
75
|
+
else
|
76
|
+
logger.error("Detection failed")
|
77
|
+
return 2
|
78
|
+
end
|
79
|
+
rescue => e
|
80
|
+
logger.error(e)
|
81
|
+
return 3
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end ; end
|
89
|
+
|
90
|
+
require 'fpm/fry/command/cook'
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'fpm/fry/client'
|
2
|
+
module FPM; module Fry
|
3
|
+
|
4
|
+
module Detector
|
5
|
+
|
6
|
+
class String < Struct.new(:value)
|
7
|
+
attr :distribution
|
8
|
+
attr :version
|
9
|
+
|
10
|
+
def detect!
|
11
|
+
@distribution, @version = value.split('-',2)
|
12
|
+
return true
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
class Container < Struct.new(:client,:container)
|
18
|
+
attr :distribution
|
19
|
+
attr :version
|
20
|
+
|
21
|
+
def detect!
|
22
|
+
begin
|
23
|
+
client.read(container,'/etc/lsb-release') do |file|
|
24
|
+
file.read.each_line do |line|
|
25
|
+
case(line)
|
26
|
+
when /\ADISTRIB_ID=/ then
|
27
|
+
@distribution = $'.strip.downcase
|
28
|
+
when /\ADISTRIB_RELEASE=/ then
|
29
|
+
@version = $'.strip
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
return !!(@distribution and @version)
|
34
|
+
rescue Client::FileNotFound
|
35
|
+
end
|
36
|
+
begin
|
37
|
+
client.read(container,'/etc/debian_version') do |file|
|
38
|
+
content = file.read
|
39
|
+
if /\A\d+(?:\.\d+)+\Z/ =~ content
|
40
|
+
@distribution = 'debian'
|
41
|
+
@version = content.strip
|
42
|
+
end
|
43
|
+
end
|
44
|
+
return !!(@distribution and @version)
|
45
|
+
rescue Client::FileNotFound
|
46
|
+
end
|
47
|
+
begin
|
48
|
+
client.read(container,'/etc/redhat-release') do |file|
|
49
|
+
if file.header.typeflag == "2" # centos links this file
|
50
|
+
client.read(container,File.absolute_path(file.header.linkname,'/etc')) do |file|
|
51
|
+
detect_redhat_release(file)
|
52
|
+
end
|
53
|
+
else
|
54
|
+
detect_redhat_release(file)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
return !!(@distribution and @version)
|
58
|
+
rescue Client::FileNotFound
|
59
|
+
end
|
60
|
+
return false
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
def detect_redhat_release(file)
|
65
|
+
file.read.each_line do |line|
|
66
|
+
case(line)
|
67
|
+
when /\A(\w+) release ([\d\.]+)/ then
|
68
|
+
@distribution = $1.strip.downcase
|
69
|
+
@version = $2.strip
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Image < Struct.new(:client,:image,:factory)
|
76
|
+
attr :distribution
|
77
|
+
attr :version
|
78
|
+
|
79
|
+
def initialize(client, image, factory = Container)
|
80
|
+
super
|
81
|
+
end
|
82
|
+
|
83
|
+
def detect!
|
84
|
+
body = JSON.generate({"Image" => image, "Cmd" => "exit 0"})
|
85
|
+
res = client.post( path: client.url('containers','create'),
|
86
|
+
headers: {'Content-Type' => 'application/json'},
|
87
|
+
body: body,
|
88
|
+
expects: [201]
|
89
|
+
)
|
90
|
+
body = JSON.parse(res.body)
|
91
|
+
container = body.fetch('Id')
|
92
|
+
begin
|
93
|
+
d = factory.new(client,container)
|
94
|
+
if d.detect!
|
95
|
+
@distribution = d.distribution
|
96
|
+
@version = d.version
|
97
|
+
return true
|
98
|
+
else
|
99
|
+
return false
|
100
|
+
end
|
101
|
+
ensure
|
102
|
+
client.delete(path: client.url('containers',container))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
end
|
109
|
+
end ; end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
require 'fiber'
|
2
|
+
require 'shellwords'
|
3
|
+
require 'rubygems/package'
|
4
|
+
require 'fpm/fry/os_db'
|
5
|
+
require 'fpm/fry/source'
|
6
|
+
require 'fpm/fry/joined_io'
|
7
|
+
module FPM; module Fry
|
8
|
+
class DockerFile < Struct.new(:variables,:cache,:recipe)
|
9
|
+
|
10
|
+
class Source < Struct.new(:variables, :cache)
|
11
|
+
|
12
|
+
def initialize(variables, cache = Source::Null::Cache)
|
13
|
+
variables = variables.dup
|
14
|
+
if variables[:distribution] && !variables[:flavour] && OsDb[variables[:distribution]]
|
15
|
+
variables[:flavour] = OsDb[variables[:distribution]][:flavour]
|
16
|
+
end
|
17
|
+
variables.freeze
|
18
|
+
super(variables, cache)
|
19
|
+
end
|
20
|
+
|
21
|
+
def dockerfile
|
22
|
+
df = []
|
23
|
+
df << "FROM #{variables[:image]}"
|
24
|
+
|
25
|
+
df << "RUN mkdir /tmp/build"
|
26
|
+
|
27
|
+
cache.file_map.each do |from, to|
|
28
|
+
df << "ADD #{map_from(from)} #{map_to(to)}"
|
29
|
+
end
|
30
|
+
|
31
|
+
df << ""
|
32
|
+
return df.join("\n")
|
33
|
+
end
|
34
|
+
|
35
|
+
def tar_io
|
36
|
+
JoinedIO.new(
|
37
|
+
self_tar_io,
|
38
|
+
cache.tar_io
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self_tar_io
|
43
|
+
sio = StringIO.new
|
44
|
+
tar = Gem::Package::TarWriter.new(sio)
|
45
|
+
tar.add_file('Dockerfile','0777') do |io|
|
46
|
+
io.write(dockerfile)
|
47
|
+
end
|
48
|
+
#tar.close
|
49
|
+
sio.rewind
|
50
|
+
return sio
|
51
|
+
end
|
52
|
+
|
53
|
+
def map_to(dir)
|
54
|
+
if ['','.'].include? dir
|
55
|
+
return '/tmp/build'
|
56
|
+
else
|
57
|
+
return File.join('/tmp/build',dir)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def map_from(dir)
|
62
|
+
if dir == ''
|
63
|
+
return '.'
|
64
|
+
else
|
65
|
+
return dir
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
class Build < Struct.new(:base, :variables, :recipe)
|
72
|
+
|
73
|
+
attr :options
|
74
|
+
private :options
|
75
|
+
|
76
|
+
def initialize(base, variables, recipe, options = {})
|
77
|
+
variables = variables.dup
|
78
|
+
if variables[:distribution] && !variables[:flavour] && OsDb[variables[:distribution]]
|
79
|
+
variables[:flavour] = OsDb[variables[:distribution]][:flavour]
|
80
|
+
end
|
81
|
+
variables.freeze
|
82
|
+
@options = options.dup.freeze
|
83
|
+
super(base, variables, recipe)
|
84
|
+
end
|
85
|
+
|
86
|
+
def dockerfile
|
87
|
+
df = []
|
88
|
+
df << "FROM #{base}"
|
89
|
+
df << "WORKDIR /tmp/build"
|
90
|
+
|
91
|
+
deps = (recipe.build_depends.merge recipe.depends)\
|
92
|
+
.select{|_,v| v.fetch(:install,true) }\
|
93
|
+
.map do |k,v|
|
94
|
+
i = v.fetch(:install,true)
|
95
|
+
if i == true then
|
96
|
+
k
|
97
|
+
else
|
98
|
+
i
|
99
|
+
end
|
100
|
+
end.sort
|
101
|
+
if deps.any?
|
102
|
+
case(variables[:flavour])
|
103
|
+
when 'debian'
|
104
|
+
update = ''
|
105
|
+
if options[:update]
|
106
|
+
update = 'apt-get update && '
|
107
|
+
end
|
108
|
+
df << "RUN #{update}apt-get install --yes #{Shellwords.join(deps)}"
|
109
|
+
when 'redhat'
|
110
|
+
df << "RUN yum -y install #{Shellwords.join(deps)}"
|
111
|
+
else
|
112
|
+
raise "Unknown flavour: #{variables[:flavour]}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
df << "ADD .build.sh /tmp/build/"
|
117
|
+
df << "ENTRYPOINT /tmp/build/.build.sh"
|
118
|
+
df << ''
|
119
|
+
return df.join("\n")
|
120
|
+
end
|
121
|
+
|
122
|
+
def build_sh
|
123
|
+
df = ['#!/bin/bash']
|
124
|
+
df << 'set -e'
|
125
|
+
recipe.steps.each do |k,v|
|
126
|
+
df << "echo -e '\\e[1;32m====> #{Shellwords.escape k}\\e[0m'"
|
127
|
+
df << v.to_s
|
128
|
+
end
|
129
|
+
df << ''
|
130
|
+
return df.join("\n")
|
131
|
+
end
|
132
|
+
|
133
|
+
def tar_io
|
134
|
+
sio = StringIO.new
|
135
|
+
tar = Gem::Package::TarWriter.new(sio)
|
136
|
+
tar.add_file('.build.sh','0777') do |io|
|
137
|
+
io.write(build_sh)
|
138
|
+
end
|
139
|
+
tar.add_file('Dockerfile','0777') do |io|
|
140
|
+
io.write(dockerfile)
|
141
|
+
end
|
142
|
+
#tar.close
|
143
|
+
sio.rewind
|
144
|
+
return sio
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end ; end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module FPM; module Fry
|
2
|
+
class JoinedIO
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def initialize(*ios)
|
6
|
+
@ios = ios
|
7
|
+
@pos = 0
|
8
|
+
@readbytes = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def read( len = nil )
|
12
|
+
buf = []
|
13
|
+
if len.nil?
|
14
|
+
while chunk = readpartial(512)
|
15
|
+
buf << chunk
|
16
|
+
@readbytes += chunk.bytesize
|
17
|
+
end
|
18
|
+
return buf.join
|
19
|
+
else
|
20
|
+
con = 0
|
21
|
+
while con < len
|
22
|
+
chunk = readpartial(len - con)
|
23
|
+
if chunk.nil?
|
24
|
+
if con == 0
|
25
|
+
return nil
|
26
|
+
else
|
27
|
+
return buf.join
|
28
|
+
end
|
29
|
+
end
|
30
|
+
@readbytes += chunk.bytesize
|
31
|
+
con += chunk.bytesize
|
32
|
+
buf << chunk
|
33
|
+
end
|
34
|
+
return buf.join
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def readpartial( len )
|
39
|
+
while (io = @ios[@pos])
|
40
|
+
r = io.read( len )
|
41
|
+
if r.nil?
|
42
|
+
@pos = @pos + 1
|
43
|
+
next
|
44
|
+
else
|
45
|
+
return r
|
46
|
+
end
|
47
|
+
end
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
|
51
|
+
def pos
|
52
|
+
@readbytes
|
53
|
+
end
|
54
|
+
|
55
|
+
def eof?
|
56
|
+
@pos == @ios.size
|
57
|
+
end
|
58
|
+
|
59
|
+
def close
|
60
|
+
@ios.each(&:close)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end ; end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module FPM; module Fry
|
2
|
+
|
3
|
+
# Structure is
|
4
|
+
#
|
5
|
+
# <distribution> => {
|
6
|
+
# codenames: {
|
7
|
+
# <codename> => <version>
|
8
|
+
# },
|
9
|
+
# flavour: <flavour>
|
10
|
+
# }
|
11
|
+
OsDb = {
|
12
|
+
'centos' => {
|
13
|
+
codenames: {},
|
14
|
+
flavour: 'redhat'
|
15
|
+
},
|
16
|
+
|
17
|
+
'debian' => {
|
18
|
+
codenames: {
|
19
|
+
'lenny' => '5',
|
20
|
+
'squeeze' => '6',
|
21
|
+
'wheezy' => '7'
|
22
|
+
},
|
23
|
+
flavour: 'debian'
|
24
|
+
},
|
25
|
+
|
26
|
+
'ubuntu' => {
|
27
|
+
codenames: {
|
28
|
+
'precise' => '12.04',
|
29
|
+
'trusty' => '14.04'
|
30
|
+
},
|
31
|
+
flavour: 'debian'
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
end ; end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'fpm/fry/plugin'
|
2
|
+
module FPM::Fry::Plugin::Alternatives
|
3
|
+
|
4
|
+
BASH_HEADER = ['#!/bin/bash']
|
5
|
+
DEFAULT_PRIORITY = 10000
|
6
|
+
EXPECTED_KEYS = [:path, :link, :priority]
|
7
|
+
|
8
|
+
class DSL < Struct.new(:builder, :alternatives)
|
9
|
+
|
10
|
+
def initialize( b, a = {})
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def []=(name, options={}, value)
|
15
|
+
name = name.to_s
|
16
|
+
if value.kind_of? String
|
17
|
+
options = normalize(name, options.merge(path: value) )
|
18
|
+
else
|
19
|
+
options = normalize(name, options.merge(value) )
|
20
|
+
end
|
21
|
+
alternatives[name] = options
|
22
|
+
end
|
23
|
+
|
24
|
+
def add(name, value, options={})
|
25
|
+
self[name, options] = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def finish!
|
29
|
+
install = alternatives.map{|_,v| install_command(v) }
|
30
|
+
uninstall = alternatives.map{|_,v| uninstall_command(v) }
|
31
|
+
builder.plugin('script_helper') do
|
32
|
+
after_install_or_upgrade(*install)
|
33
|
+
before_remove_entirely(*uninstall)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
def normalize_without_slaves(name, options)
|
39
|
+
if options.kind_of? String
|
40
|
+
options = {path: options}
|
41
|
+
elsif options.kind_of? Hash
|
42
|
+
additional_keys = options.keys - EXPECTED_KEYS
|
43
|
+
raise ArgumentError, "Unexpected options: #{additional_keys.inspect}" if additional_keys.any?
|
44
|
+
options = options.dup
|
45
|
+
else
|
46
|
+
raise ArgumentError, "Options must be either a Hash or a String, got #{options.inspect}"
|
47
|
+
end
|
48
|
+
options[:name] = name
|
49
|
+
options[:link] ||= File.join('/usr/bin',name)
|
50
|
+
return options
|
51
|
+
end
|
52
|
+
|
53
|
+
def normalize( name, options )
|
54
|
+
slaves = {}
|
55
|
+
if options.kind_of?(Hash) && options.key?(:slaves)
|
56
|
+
options = options.dup
|
57
|
+
slaves = options.delete(:slaves)
|
58
|
+
end
|
59
|
+
options = normalize_without_slaves(name, options)
|
60
|
+
options[:slaves] = slaves.map{|k,v| normalize_without_slaves(k, v) }
|
61
|
+
options[:priority] ||= DEFAULT_PRIORITY
|
62
|
+
return options
|
63
|
+
end
|
64
|
+
|
65
|
+
def install_command(options)
|
66
|
+
slaves = options.fetch(:slaves,[]).flat_map{|options| ['--slave', options[:link],options[:name],options[:path]] }
|
67
|
+
Shellwords.join(['update-alternatives','--install',options[:link],options[:name],options[:path],options[:priority].to_s, *slaves])
|
68
|
+
end
|
69
|
+
|
70
|
+
def uninstall_command(options)
|
71
|
+
Shellwords.join(['update-alternatives','--remove',options[:name],options[:path]])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.apply(builder, options = {}, &block)
|
76
|
+
dsl = DSL.new(builder)
|
77
|
+
options.each do |k,v|
|
78
|
+
dsl.add(k,v)
|
79
|
+
end
|
80
|
+
if block
|
81
|
+
if block.arity == 1
|
82
|
+
yield dsl
|
83
|
+
else
|
84
|
+
dsl.instance_eval(&block)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
dsl.finish!
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'fpm/fry/plugin'
|
2
|
+
require 'fileutils'
|
3
|
+
module FPM::Fry::Plugin::EditStaging
|
4
|
+
|
5
|
+
class AddFile < Struct.new(:path, :io, :options)
|
6
|
+
def call(_ , package)
|
7
|
+
file = package.staging_path(path)
|
8
|
+
FileUtils.mkdir_p(File.dirname(file))
|
9
|
+
File.open(file,'w') do | f |
|
10
|
+
IO.copy_stream(io, f)
|
11
|
+
if options[:chmod]
|
12
|
+
f.chmod(options[:chmod])
|
13
|
+
end
|
14
|
+
end
|
15
|
+
io.close if io.respond_to? :close
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class LnS < Struct.new(:src, :dest)
|
20
|
+
def call(_ , package)
|
21
|
+
file = package.staging_path(dest)
|
22
|
+
FileUtils.mkdir_p(File.dirname(file))
|
23
|
+
File.symlink(src, file)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class DSL < Struct.new(:builder)
|
28
|
+
def add_file(path, io, options = {})
|
29
|
+
options = options.dup
|
30
|
+
options[:chmod] = convert_chmod(options[:chmod]) if options[:chmod]
|
31
|
+
options.freeze
|
32
|
+
io.rewind if io.respond_to? :rewind
|
33
|
+
builder.output_hooks << AddFile.new(path, io, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def ln_s(src, dest)
|
37
|
+
builder.output_hooks << LnS.new(src,dest)
|
38
|
+
end
|
39
|
+
private
|
40
|
+
|
41
|
+
def convert_chmod(chmod)
|
42
|
+
if chmod.kind_of? Numeric
|
43
|
+
num = chmod
|
44
|
+
elsif chmod.kind_of? String
|
45
|
+
num = chmod.to_i(8)
|
46
|
+
else
|
47
|
+
raise ArgumentError, "Invalid chmod format: #{chmod}"
|
48
|
+
end
|
49
|
+
return num
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.apply(builder, &block)
|
55
|
+
d = DSL.new(builder)
|
56
|
+
if !block
|
57
|
+
return d
|
58
|
+
elsif block.arity == 1
|
59
|
+
block.call(d)
|
60
|
+
else
|
61
|
+
d.instance_eval(&block)
|
62
|
+
end
|
63
|
+
return d
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'fpm/fry/plugin'
|
2
|
+
module FPM::Fry::Plugin::Exclude
|
3
|
+
|
4
|
+
class Exclude < Struct.new(:matches)
|
5
|
+
|
6
|
+
def call(_, package)
|
7
|
+
(package.attributes[:excludes] ||= []).push(*matches)
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def exclude(*matches)
|
13
|
+
return if matches.none?
|
14
|
+
input_hooks << Exclude.new(matches)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'fpm/fry/plugin'
|
2
|
+
module FPM::Fry::Plugin::Init
|
3
|
+
|
4
|
+
def self.detect_init(variables)
|
5
|
+
if variables[:init]
|
6
|
+
return variables[:init]
|
7
|
+
end
|
8
|
+
d = variables[:distribution]
|
9
|
+
v = variables[:distribution_version].split('.').map(&:to_i)
|
10
|
+
case(d)
|
11
|
+
when 'debian'
|
12
|
+
if v[0] < 8
|
13
|
+
return 'sysv'
|
14
|
+
else
|
15
|
+
return 'systemd'
|
16
|
+
end
|
17
|
+
when 'ubuntu'
|
18
|
+
if v[0] <= 14 && v[1] < 10
|
19
|
+
return 'upstart'
|
20
|
+
else
|
21
|
+
return 'systemd'
|
22
|
+
end
|
23
|
+
when 'centos','redhat'
|
24
|
+
if v[0] <= 5
|
25
|
+
return 'sysv'
|
26
|
+
elsif v[0] == 6
|
27
|
+
return 'upstart'
|
28
|
+
else
|
29
|
+
return 'systemd'
|
30
|
+
end
|
31
|
+
else
|
32
|
+
raise "Unknown init system for #{d} #{v.join '.'}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def init(*inits)
|
37
|
+
inits = inits.flatten.map(&:to_s)
|
38
|
+
actual = FPM::Fry::Plugin::Init.detect_init(variables)
|
39
|
+
if inits.none?
|
40
|
+
return actual
|
41
|
+
elsif inits.include? actual
|
42
|
+
if block_given?
|
43
|
+
yield
|
44
|
+
else
|
45
|
+
return true
|
46
|
+
end
|
47
|
+
else
|
48
|
+
return false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
end
|