fpm-fry 0.2.2 → 0.4.6

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.
@@ -11,7 +11,7 @@ module FPM; module Fry
11
11
  end
12
12
 
13
13
  # Reads length bytes or all if length is nil.
14
- # @param [Numeric, nil] length
14
+ # @param [Numeric, nil] len
15
15
  # @return [String] resulting bytes
16
16
  def read( len = nil )
17
17
  buf = []
@@ -0,0 +1,52 @@
1
+ require 'fpm/fry/plugin'
2
+ module FPM::Fry::Plugin ;
3
+
4
+ # Allows adding a debian repository.
5
+ #
6
+ # @note experimental
7
+ #
8
+ # @example in a recipe
9
+ # plugin 'apt' do |apt|
10
+ # apt.repository "https://repo.varnish-cache.org/#{distribution}", "trusty", "varnish-4.1"
11
+ # end
12
+ #
13
+ class Apt
14
+
15
+ # Adds a debian repository
16
+ #
17
+ # @param [String] url
18
+ # @param [String] distribution
19
+ # @param [String,Array<String>] components
20
+ # @param [Hash] options
21
+ def repository(url, distribution, components, options = {} )
22
+ name = "#{url}-#{distribution}".gsub(/[^a-zA-Z0-9_\-]/,'-')
23
+ source = ['deb']
24
+ source << '[trusted=yes]'
25
+ source << url
26
+ source << distribution
27
+ source << Array(components).join(' ')
28
+ @builder.before_dependencies do
29
+ @builder.bash "echo '#{source.join(' ')}' >> /etc/apt/sources.list.d/#{name}.list && apt-get update -o Dir::Etc::sourcelist='sources.list.d/#{name}.list' -o Dir::Etc::sourceparts='-' -o APT::Get::List-Cleanup='0'"
30
+ end
31
+ end
32
+
33
+ def self.apply(builder, &block)
34
+ if builder.flavour != "debian"
35
+ builder.logger.info('skipped apt plugin')
36
+ return
37
+ end
38
+ dsl = self.new(builder)
39
+ if block.arity == 1
40
+ block.call(dsl)
41
+ else
42
+ dsl.instance_eval(&block)
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def initialize(builder)
49
+ @builder = builder
50
+ end
51
+
52
+ end ; end
@@ -4,7 +4,7 @@ require 'fileutils'
4
4
  # A plugin to edit the final build results.
5
5
  # @example Add a file
6
6
  # plugin 'edit_staging' do
7
- # add_file '/a_file'
7
+ # add_file '/a_file', 'some content'
8
8
  # end
9
9
  module FPM::Fry::Plugin::EditStaging
10
10
 
@@ -0,0 +1,45 @@
1
+ require 'fpm/fry/plugin'
2
+ # The env plugin sets global environment variables.
3
+ #
4
+ # @example add something to PATH in a recipe
5
+ # plugin 'env', 'PATH' => '$PATH:/usr/local/go/bin'
6
+ #
7
+ module FPM::Fry::Plugin::Env
8
+
9
+ # @api private
10
+ class AddEnv < Struct.new(:env)
11
+
12
+ def call(_, df)
13
+ df[:source] << format
14
+ end
15
+ private
16
+
17
+ def format
18
+ "ENV " + env.map{|k,v| "#{k}=#{escape(v)}" }.join(" ")
19
+ end
20
+
21
+ def escape(v)
22
+ v.gsub(/([ \n\\])/,'\\\\\\1')
23
+ end
24
+ end
25
+
26
+ def self.apply(builder, env)
27
+ unless env.kind_of? Hash
28
+ raise FPM::Fry::WithData(
29
+ ArgumentError.new("ENV must be a Hash, got #{env.inspect}"),
30
+ documentation: 'https://github.com/xing/fpm-fry/wiki/Plugin-env'
31
+ )
32
+ end
33
+ env.each do |k,v|
34
+ k = k.to_s if k.kind_of? Symbol
35
+ unless k.kind_of?(String) && k =~ /\A[A-Z][A-Z0-9_]*\z/
36
+ raise FPM::Fry::WithData(
37
+ ArgumentError.new("environment variable names must be strings consisiting of uppercase letters, numbers and underscores, got #{k.inspect}"),
38
+ documentation: 'https://github.com/xing/fpm-fry/wiki/Plugin-env'
39
+ )
40
+ end
41
+ end
42
+ builder.recipe.dockerfile_hooks << AddEnv.new(env.dup.freeze)
43
+ end
44
+
45
+ end
@@ -1,53 +1,82 @@
1
1
  require 'fpm/fry/plugin'
2
+ # A plugin that detects the init system of a docker image.
3
+ #
4
+ # This plugin is a low-level plugin and is used by other plugins such as "service".
5
+ #
6
+ # @example in a recipe when using the image "ubuntu:16.04"
7
+ # plugin 'init'
8
+ # init.systemd? #=> true
9
+ # init.sysv? #=> false
2
10
  module FPM::Fry::Plugin::Init
3
11
 
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 '.'}"
12
+ # Contains information about the init system in use.
13
+ class System
14
+ # @return [Hash<Symbol,Object>] features of the init system
15
+ attr :with
16
+
17
+ def with?(feature)
18
+ !!with[feature]
19
+ end
20
+ def sysv?
21
+ name == :sysv
22
+ end
23
+ def upstart?
24
+ name == :upstart
25
+ end
26
+ def systemd?
27
+ name == :systemd
28
+ end
29
+ private
30
+ attr :name
31
+ def initialize(name, with)
32
+ @name, @with = name, with
33
33
  end
34
34
  end
35
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
36
+ # @return [System] initsystem in use
37
+ def init
38
+ return @init
39
+ end
40
+
41
+ private
42
+ def self.detect(inspector)
43
+ if inspector.exists?('/lib/systemd/systemd')
44
+ return System.new(:systemd, {})
45
+ end
46
+ if inspector.exists?('/etc/init')
47
+ return detect_upstart(inspector)
48
+ end
49
+ if inspector.exists?('/etc/init.d')
50
+ return detect_sysv(inspector)
49
51
  end
52
+ return nil
50
53
  end
51
54
 
55
+ def self.detect_upstart(inspector)
56
+ features = {
57
+ sysvcompat: inspector.exists?('/lib/init/upstart-job') ? '/lib/init/upstart-job' : false
58
+ }
59
+ return System.new(:upstart,features)
60
+ end
61
+
62
+ def self.detect_sysv(inspector)
63
+ features = {
64
+ :chkconfig => inspector.exists?('/sbin/chkconfig'),
65
+ :'update-rc.d' => inspector.exists?('/usr/sbin/update-rc.d'),
66
+ :'invoke-rc.d' => inspector.exists?('/usr/sbin/invoke-rc.d')
67
+ }
68
+ return System.new(:sysv,features)
69
+ end
70
+
71
+ def self.extended(base)
72
+ base.instance_eval do
73
+ @init ||= FPM::Fry::Plugin::Init.detect(inspector)
74
+ end
75
+ end
76
+
77
+ def self.apply(builder)
78
+ builder.extend(self)
79
+ return builder.init
80
+ end
52
81
 
53
82
  end
@@ -24,11 +24,12 @@ module FPM::Fry::Plugin ; module Service
24
24
 
25
25
  class DSL
26
26
 
27
+ # @return [Hash<String,Tuple<Numeric,Numeric>]
27
28
  attr :limits
28
29
 
29
- def initialize(*_)
30
- super
31
- @name = nil
30
+ # @api private
31
+ def initialize(name)
32
+ @name = name
32
33
  @command = []
33
34
  @limits = {}
34
35
  @user = nil
@@ -36,20 +37,35 @@ module FPM::Fry::Plugin ; module Service
36
37
  @chdir = nil
37
38
  end
38
39
 
39
- def name( n = nil )
40
- if n
41
- @name = n
40
+ # @overload name
41
+ # @return [String] this service's name
42
+ # @overload name( name )
43
+ # @param [String] name new name for this service
44
+ # @return [String] this service's name
45
+ def name( name = nil )
46
+ if name
47
+ @name = name
42
48
  end
43
49
  return @name
44
50
  end
45
51
 
46
- def group( n = nil )
47
- if n
48
- @group = n
52
+ # @overload group
53
+ # @return [String] the linux user group this service should run as
54
+ # @overload group( name )
55
+ # @param [String] name new linux user group this service should run as
56
+ # @return [String] the linux user group this service should run as
57
+ def group( group = nil )
58
+ if group
59
+ @group = group
49
60
  end
50
61
  return @group
51
62
  end
52
63
 
64
+ # @overload user
65
+ # @return [String] the linux user this service should run as
66
+ # @overload user( name )
67
+ # @param [String] name new linx user this service should run as
68
+ # @return [String] the linux user this service should run as
53
69
  def user( n = nil )
54
70
  if n
55
71
  @user = n
@@ -57,13 +73,39 @@ module FPM::Fry::Plugin ; module Service
57
73
  return @user
58
74
  end
59
75
 
76
+ # Sets a limit for this service. Valid limits are:
77
+ #
78
+ # - core
79
+ # - cpu
80
+ # - data
81
+ # - fsize
82
+ # - memlock
83
+ # - msgqueue
84
+ # - nice
85
+ # - nofile
86
+ # - nproc
87
+ # - rss
88
+ # - rtprio
89
+ # - sigpending
90
+ # - stack
91
+ #
92
+ # @see http://linux.die.net/man/5/limits.conf Limits.conf manpage for limits and their meanings.
93
+ # @param [String] name see above list for valid limits
94
+ # @param [Numeric,"unlimited"] soft soft limit
95
+ # @param [Numeric,"unlimited"] hard hard limit
60
96
  def limit( name, soft, hard = soft )
61
97
  unless LIMITS.include? name
62
98
  raise ArgumentError, "Unknown limit #{name.inspect}. Known limits are: #{LIMITS.inspect}"
63
99
  end
64
100
  @limits[name] = [soft,hard]
101
+ return nil
65
102
  end
66
103
 
104
+ # @overload chdir
105
+ # @return [String,nil] working directory of the service
106
+ # @overload chdir( dir )
107
+ # @param [String] dir new working directory of the service
108
+ # @return [String] working directory of the service
67
109
  def chdir( dir = nil )
68
110
  if dir
69
111
  @chdir = dir
@@ -80,76 +122,93 @@ module FPM::Fry::Plugin ; module Service
80
122
 
81
123
  # @api private
82
124
  def add!(builder)
83
- name = self.name || builder.name || raise
84
- init = Init.detect_init(builder.variables)
125
+ init = builder.plugin('init')
126
+ if init.systemd?
127
+ add_systemd!(builder)
128
+ elsif init.upstart?
129
+ add_upstart!(builder)
130
+ elsif init.sysv?
131
+ add_sysv!(builder)
132
+ end
133
+ end
134
+ private
135
+ def add_upstart!(builder)
136
+ init = builder.plugin('init')
85
137
  edit = builder.plugin('edit_staging')
86
138
  env = Environment.new(name, command, "", @limits, @user, @group, @chdir)
87
- case(init)
88
- when 'upstart' then
89
- edit.add_file "/etc/init/#{name}.conf",StringIO.new( env.render('upstart.erb') )
90
- edit.ln_s '/lib/init/upstart-job', "/etc/init.d/#{name}"
91
- builder.plugin('script_helper') do |sh|
92
- sh.after_install_or_upgrade(<<BASH)
139
+ edit.add_file "/etc/init/#{name}.conf",StringIO.new( env.render('upstart.erb') )
140
+ if init.with? :sysvcompat
141
+ edit.ln_s init.with[:sysvcompat], "/etc/init.d/#{name}"
142
+ end
143
+ builder.plugin('script_helper') do |sh|
144
+ sh.after_install_or_upgrade(<<BASH)
93
145
  if status #{Shellwords.shellescape name} 2>/dev/null | grep -q ' start/'; then
94
- # It has to be stop+start because upstart doesn't pickup changes with restart.
95
- if which invoke-rc.d >/dev/null 2>&1; then
96
- invoke-rc.d #{Shellwords.shellescape name} stop
97
- else
98
- stop #{Shellwords.shellescape name}
99
- fi
146
+ # It has to be stop+start because upstart doesn't pickup changes with restart.
147
+ if which invoke-rc.d >/dev/null 2>&1; then
148
+ invoke-rc.d #{Shellwords.shellescape name} stop
149
+ else
150
+ stop #{Shellwords.shellescape name}
151
+ fi
100
152
  fi
101
153
  if which invoke-rc.d >/dev/null 2>&1; then
102
- invoke-rc.d #{Shellwords.shellescape name} start
154
+ invoke-rc.d #{Shellwords.shellescape name} start
103
155
  else
104
- start #{Shellwords.shellescape name}
156
+ start #{Shellwords.shellescape name}
105
157
  fi
106
158
  BASH
107
- sh.before_remove_entirely(<<BASH)
159
+ sh.before_remove_entirely(<<BASH)
108
160
  if status #{Shellwords.shellescape name} 2>/dev/null | grep -q ' start/'; then
109
- stop #{Shellwords.shellescape name}
161
+ stop #{Shellwords.shellescape name}
110
162
  fi
111
163
  BASH
112
- end
113
- builder.plugin('config', FPM::Fry::Plugin::Config::IMPLICIT => true) do |co|
114
- co.include "etc/init/#{name}.conf"
115
- end
116
- when 'sysv' then
117
- edit.add_file "/etc/init.d/#{name}",StringIO.new( env.render('sysv.erb') ), chmod: '750'
118
- builder.plugin('script_helper') do |sh|
119
- sh.after_install_or_upgrade(<<BASH)
164
+ end
165
+ builder.plugin('config', FPM::Fry::Plugin::Config::IMPLICIT => true) do |co|
166
+ co.include "etc/init/#{name}.conf"
167
+ end
168
+ end
169
+
170
+ def add_sysv!(builder)
171
+ edit = builder.plugin('edit_staging')
172
+ env = Environment.new(name, command, "", @limits, @user, @group, @chdir)
173
+ edit.add_file "/etc/init.d/#{name}",StringIO.new( env.render('sysv.erb') ), chmod: '750'
174
+ builder.plugin('script_helper') do |sh|
175
+ sh.after_install_or_upgrade(<<BASH)
120
176
  update-rc.d #{Shellwords.shellescape name} defaults
121
177
  /etc/init.d/#{Shellwords.shellescape name} restart
122
178
  BASH
123
- sh.before_remove_entirely(<<BASH)
179
+ sh.before_remove_entirely(<<BASH)
124
180
  /etc/init.d/#{Shellwords.shellescape name} stop
125
181
  update-rc.d -f #{Shellwords.shellescape name} remove
126
182
  BASH
127
- end
128
- builder.plugin('config', FPM::Fry::Plugin::Config::IMPLICIT => true) do |co|
129
- co.include "etc/init.d/#{name}"
130
- end
131
- when 'systemd' then
132
- edit.add_file "/lib/systemd/system/#{name}.service", StringIO.new( env.render('systemd.erb') ), chmod: '644'
133
- builder.plugin('script_helper') do |sh|
134
- sh.after_install_or_upgrade(<<BASH)
183
+ end
184
+ builder.plugin('config', FPM::Fry::Plugin::Config::IMPLICIT => true) do |co|
185
+ co.include "etc/init.d/#{name}"
186
+ end
187
+ end
188
+
189
+ def add_systemd!(builder)
190
+ edit = builder.plugin('edit_staging')
191
+ env = Environment.new(name, command, "", @limits, @user, @group, @chdir)
192
+ edit.add_file "/lib/systemd/system/#{name}.service", StringIO.new( env.render('systemd.erb') ), chmod: '644'
193
+ builder.plugin('script_helper') do |sh|
194
+ sh.after_install_or_upgrade(<<BASH)
135
195
  systemctl preset #{Shellwords.shellescape name}.service
136
196
  if systemctl is-enabled --quiet #{Shellwords.shellescape name}.service ; then
137
- systemctl --system daemon-reload
138
- systemctl try-reload-or-restart #{Shellwords.shellescape name}.service
197
+ systemctl --system daemon-reload
198
+ systemctl restart #{Shellwords.shellescape name}.service
139
199
  fi
140
200
  BASH
141
- sh.before_remove_entirely(<<BASH)
201
+ sh.before_remove_entirely(<<BASH)
142
202
  systemctl disable --now #{Shellwords.shellescape name}.service
143
203
  BASH
144
204
 
145
- end
146
205
  end
147
206
  end
148
207
 
149
208
  end
150
209
 
151
210
  def self.apply(builder, &block)
152
- d = DSL.new
211
+ d = DSL.new(builder.name)
153
212
  if !block
154
213
  raise ArgumentError, "service plugin requires a block"
155
214
  elsif block.arity == 1