fpm-fry 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6d10781e6b5740b80f68e6a7130acd844c2b1d5c
4
- data.tar.gz: 5dc23f36f547bd2359b433424ae8ef091dd2cf53
3
+ metadata.gz: 9d58721a3f79317f65181422ff3a7e5d28ef823e
4
+ data.tar.gz: 85229c608182080d92b67b81c2e6d09f701d19ba
5
5
  SHA512:
6
- metadata.gz: ba95b38a5652f87439105db3c7430505695e5429ef90fdfadcb1b6f517556259c8add886a2c0b0cca72e0d7c7683a4584883d3e1263266ad5f4e162fa911b9f0
7
- data.tar.gz: 9ded152eb45fbab21bdef04a651bee26689f0dd8a45a10d096ece7fe5cbc646f727fbc082e353f49bd62b6a303887d6ab86b6bb0e245625667d0529779f39f3e
6
+ metadata.gz: 5fc67b6dcbe5d6d8944028721665cbee9ae9bdb4f615c68812e012063e66c22ab278b943dc155d1e2ecc58e23021af133e8c0f29185db0ba0b5faa4f2dba5e5e
7
+ data.tar.gz: 03c12a7c8743715a8a33fff09c84e423ef67cbcd6a4a3a8659a6f7a1bd0b2e361797932117478950fb6ca6e5ac9af35049a4087c094a521b16a3e16a8d1fe22a
@@ -6,14 +6,16 @@ class Cabin::NiceOutput
6
6
  :red => "\e[1;31m",
7
7
  :green => "\e[1;32m",
8
8
  :yellow => "\e[0;33m",
9
- :white => "\e[0;37m"
9
+ :white => "\e[0;37m",
10
+ :blue => "\e[1;34m"
10
11
  }
11
12
 
12
13
  DIM_CODEMAP = {
13
14
  red: "\e[0;31m",
14
15
  green: "\e[0;32m",
15
16
  white: "\e[1;30m",
16
- yellow: "\e[33m"
17
+ yellow: "\e[33m",
18
+ blue: "\e[0;34m"
17
19
  }
18
20
 
19
21
  LEVELMAP = {
@@ -21,6 +23,7 @@ class Cabin::NiceOutput
21
23
  :error => :red,
22
24
  :warn => :yellow,
23
25
  :info => :green,
26
+ :hint => :blue,
24
27
  :debug => :white,
25
28
  }
26
29
 
@@ -43,6 +46,9 @@ class Cabin::NiceOutput
43
46
  bold = data.delete(:bold) ? :bold : nil
44
47
 
45
48
  backtrace = data.delete(:backtrace)
49
+ if !backtrace && data[:exception].respond_to?(:backtrace)
50
+ backtrace = data[:exception].backtrace
51
+ end
46
52
 
47
53
  # Make 'error' and other log levels have color
48
54
  if color.nil?
@@ -52,6 +58,9 @@ class Cabin::NiceOutput
52
58
  message = [event[:level] ? '====> ' : ' ',event[:message]]
53
59
  message.unshift(CODEMAP[color.to_sym]) if !color.nil?
54
60
  message << DIM_CODEMAP[color] if !color.nil?
61
+ if documentation = data.delete(:documentation)
62
+ message << "\n\tRead more on this topic here: #{documentation}"
63
+ end
55
64
  if data.any?
56
65
  message << "\n" << pp(data)
57
66
  end
@@ -0,0 +1,23 @@
1
+ require 'cabin/channel'
2
+ module FPM; module Fry
3
+ class Channel < Cabin::Channel
4
+
5
+ module Hint
6
+ def hint( message, data = {} )
7
+ return unless hint?
8
+ log(message, data.merge(level: :hint))
9
+ end
10
+
11
+ def hint?
12
+ !defined?(@hint) || @hint
13
+ end
14
+
15
+ def hint=( bool )
16
+ @hint = !!bool
17
+ end
18
+ end
19
+
20
+ include Hint
21
+
22
+ end
23
+ end ; end
@@ -9,30 +9,6 @@ module FPM; module Fry; end ; end
9
9
 
10
10
  class FPM::Fry::Client
11
11
 
12
- class LogInstrumentor < Struct.new(:logger)
13
-
14
- def instrument(event, data = {})
15
- if block_given?
16
- logger.debug('Requesting HTTP', filtered(data))
17
- r = yield
18
- return r
19
- else
20
- logger.debug('Getting HTTP response', filtered(data))
21
- end
22
- end
23
-
24
- def filtered(data)
25
- filtered = {}
26
- filtered[:path] = data[:path] if data[:path]
27
- filtered[:verb] = data[:method] if data[:method]
28
- filtered[:status] = data[:status] if data[:status]
29
- filtered[:body] = data[:body][0..500] if data[:body]
30
- filtered[:headers] = data[:headers]
31
- return filtered
32
- end
33
-
34
- end
35
-
36
12
  class FileNotFound < StandardError
37
13
  end
38
14
 
@@ -141,7 +117,6 @@ class FPM::Fry::Client
141
117
  def agent_for( uri, tls )
142
118
  proto, address = uri.split('://',2)
143
119
  options = {
144
- instrumentor: LogInstrumentor.new(logger),
145
120
  read_timeout: 10000
146
121
  }.merge( tls )
147
122
  case(proto)
@@ -18,10 +18,6 @@ module FPM; module Fry
18
18
  parameter 'image', 'Docker image to build from'
19
19
  parameter '[recipe]', 'Recipe file to cook', default: 'recipe.rb'
20
20
 
21
- attr :ui
22
- extend Forwardable
23
- def_delegators :ui, :out, :err, :logger, :tmpdir
24
-
25
21
  def initialize(invocation_path, ctx = {}, parent_attribute_values = {})
26
22
  @tls = nil
27
23
  require 'digest'
@@ -35,10 +31,6 @@ module FPM; module Fry
35
31
  require 'fpm/fry/block_enumerator'
36
32
  require 'fpm/fry/build_output_parser'
37
33
  super
38
- @ui = ctx.fetch(:ui){ UI.new }
39
- if debug?
40
- ui.logger.level = :debug
41
- end
42
34
  end
43
35
 
44
36
  def detector
@@ -53,12 +45,8 @@ module FPM; module Fry
53
45
  end
54
46
 
55
47
  def detector=(d)
56
- begin
57
- unless d.detect!
58
- raise "Unable to detect distribution from given image"
59
- end
60
- rescue Excon::Errors::NotFound
61
- raise "Image not found"
48
+ unless d.detect!
49
+ raise "Unable to detect distribution from given image"
62
50
  end
63
51
  @detector = d
64
52
  end
@@ -70,7 +58,7 @@ module FPM; module Fry
70
58
 
71
59
  def output_class
72
60
  @output_class ||= begin
73
- logger.info("Autodetecting package type",flavour: flavour)
61
+ logger.debug("Autodetecting package type",flavour: flavour)
74
62
  case(flavour)
75
63
  when 'debian'
76
64
  require 'fpm/package/deb'
@@ -92,7 +80,7 @@ module FPM; module Fry
92
80
  distribution_version: detector.version,
93
81
  flavour: flavour
94
82
  }
95
- logger.info("Loading recipe",variables: vars, recipe: recipe)
83
+ logger.debug("Loading recipe",variables: vars, recipe: recipe)
96
84
  b = Recipe::Builder.new(vars, Recipe.new, logger: ui.logger)
97
85
  b.load_file( recipe )
98
86
  b
@@ -150,7 +138,7 @@ module FPM; module Fry
150
138
  'Content-Type'=>'application/tar'
151
139
  },
152
140
  expects: [200],
153
- path: client.url("build?rm=1&t=#{cachetag}"),
141
+ path: client.url("build?rm=1&dockerfile=#{DockerFile::NAME}&t=#{cachetag}"),
154
142
  request_block: BlockEnumerator.new(df.tar_io)
155
143
  )
156
144
  end
@@ -162,12 +150,12 @@ module FPM; module Fry
162
150
  'Content-Type'=>'application/tar'
163
151
  },
164
152
  expects: [200],
165
- path: client.url('build?rm=1'),
153
+ path: client.url("build?rm=1&dockerfile=#{DockerFile::NAME}"),
166
154
  request_block: BlockEnumerator.new(df.tar_io),
167
155
  response_block: parser
168
156
  )
169
157
  if parser.images.none?
170
- raise "Unable to detect build image"
158
+ raise "Didn't find a build image in the stream. This usually means that the build script failed."
171
159
  end
172
160
  image = parser.images.last
173
161
  logger.debug("Detected build image", image: image)
@@ -191,13 +179,12 @@ module FPM; module Fry
191
179
  begin
192
180
  client.read( container, '/var/lib/apt/lists') do |file|
193
181
  next if file.header.name == 'lists/'
194
- logger.info("/var/lib/apt/lists is not empty, no update is required ( force update with --apt-update=always )")
195
- return false
182
+ logger.hint("/var/lib/apt/lists is not empty, you could try to speed up builds with --update=never", documentation: 'https://github.com/xing/fpm-fry/wiki/The-update-parameter')
183
+ return true
196
184
  end
197
185
  ensure
198
186
  client.delete(path: client.url('containers',container))
199
187
  end
200
- logger.info("/var/lib/apt/lists is empty, update is required ( disable update with --apt-update=never )")
201
188
  return true
202
189
  when 'always'
203
190
  return true
@@ -250,7 +237,7 @@ module FPM; module Fry
250
237
  )
251
238
  json = JSON.parse(res.body)
252
239
  if json["StatusCode"] != 0
253
- raise "Build failed"
240
+ raise "Build failed with exit code #{json["StatusCode"]}"
254
241
  end
255
242
  return yield container
256
243
  ensure
@@ -283,6 +270,12 @@ module FPM; module Fry
283
270
 
284
271
  output.output(tmp_package_file)
285
272
 
273
+ if output.config_files.any?
274
+ logger.debug("Found config files for #{output.name}", files: output.config_files)
275
+ else
276
+ logger.debug("No config files for #{output.name}")
277
+ end
278
+
286
279
  begin
287
280
  FileUtils.rm_rf package_file
288
281
  rescue Errno::ENOENT
@@ -311,6 +304,7 @@ module FPM; module Fry
311
304
 
312
305
  out_map.each do |output, package|
313
306
  package.apply_output(output)
307
+ adjust_config_files(output)
314
308
  end
315
309
 
316
310
  out_map.each do |output, _|
@@ -327,6 +321,39 @@ module FPM; module Fry
327
321
  end
328
322
 
329
323
 
324
+ def adjust_config_files( output )
325
+ # FPM flags all files in /etc as config files but only for debian :/.
326
+ # Actually this behavior makes sense to me for all packages because it's
327
+ # the thing I usually want. By setting this attribute at least the
328
+ # misleading warning goes away.
329
+ output.attributes[:deb_no_default_config_files?] = true
330
+ output.attributes[:deb_auto_config_files?] = false
331
+
332
+ return if output.attributes[:fry_config_explicitly_used]
333
+
334
+ # Now that we have disabled this for debian we have to reenable if it for
335
+ # all.
336
+ etc = File.expand_path('etc', output.staging_path)
337
+ if File.exists?( etc )
338
+ # Config plugin wasn't used. Add everything under /etc
339
+ prefix_length = output.staging_path.size + 1
340
+ added = []
341
+ Find.find(etc) do | path |
342
+ next unless File.file? path
343
+ name = path[prefix_length..-1]
344
+ if !output.config_files.include? name
345
+ added << name
346
+ output.config_files << name
347
+ end
348
+ end
349
+ if added.any?
350
+ logger.hint( "#{output.name} contains some config files in /etc. They were automatically added. You can customize this using the \"config\" plugin.",
351
+ documentation: "https://github.com/xing/fpm-fry/wiki/Plugin-config",
352
+ files: added)
353
+ end
354
+ end
355
+ end
356
+
330
357
  public
331
358
 
332
359
  def execute
@@ -355,7 +382,7 @@ module FPM; module Fry
355
382
 
356
383
  return 0
357
384
  rescue Recipe::NotFound => e
358
- logger.error("Recipe not found", recipe: recipe, exeception: e)
385
+ logger.error("Recipe not found", recipe: recipe, exception: e)
359
386
  return 1
360
387
  rescue => e
361
388
  logger.error(e)
@@ -16,13 +16,29 @@ module FPM; module Fry
16
16
 
17
17
  subcommand 'fpm', 'Works like fpm but with docker support', FPM::Command
18
18
 
19
+ attr :ui
20
+ extend Forwardable
21
+ def_delegators :ui, :out, :err, :logger, :tmpdir
22
+
23
+ def initialize(invocation_path, ctx = {}, parent_attribute_values = {})
24
+ super
25
+ @ui = ctx.fetch(:ui){ UI.new }
26
+ end
27
+
28
+ def parse(attrs)
29
+ super
30
+ if debug?
31
+ ui.logger.level = :debug
32
+ end
33
+ end
34
+
19
35
  def client
20
36
  @client ||= begin
21
37
  client = FPM::Fry::Client.new(
22
38
  logger: logger,
23
39
  tls: tls?, tlsverify: tlsverify?
24
40
  )
25
- logger.info("Docker connected",client.server_version)
41
+ logger.debug("Docker connected",client.server_version)
26
42
  client
27
43
  end
28
44
  end
@@ -39,14 +55,6 @@ module FPM; module Fry
39
55
  extend Forwardable
40
56
  def_delegators :ui, :logger
41
57
 
42
- def initialize(*_)
43
- super
44
- @ui = UI.new()
45
- if debug?
46
- ui.logger.level = :debug
47
- end
48
- end
49
-
50
58
  def execute
51
59
  require 'fpm/fry/os_db'
52
60
  require 'fpm/fry/detector'
@@ -73,6 +73,10 @@ module FPM; module Fry
73
73
  end
74
74
 
75
75
  class Image < Struct.new(:client,:image,:factory)
76
+
77
+ class ImageNotFound < StandardError
78
+ end
79
+
76
80
  attr :distribution
77
81
  attr :version
78
82
 
@@ -82,11 +86,15 @@ module FPM; module Fry
82
86
 
83
87
  def detect!
84
88
  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
- )
89
+ begin
90
+ res = client.post( path: client.url('containers','create'),
91
+ headers: {'Content-Type' => 'application/json'},
92
+ body: body,
93
+ expects: [201]
94
+ )
95
+ rescue Excon::Errors::NotFound
96
+ raise ImageNotFound, "Image #{image.inspect} not found. Did you do a `docker pull #{image}` before?"
97
+ end
90
98
  body = JSON.parse(res.body)
91
99
  container = body.fetch('Id')
92
100
  begin
@@ -7,6 +7,8 @@ require 'fpm/fry/joined_io'
7
7
  module FPM; module Fry
8
8
  class DockerFile < Struct.new(:variables,:cache,:recipe)
9
9
 
10
+ NAME = 'Dockerfile.fpm-fry'
11
+
10
12
  class Source < Struct.new(:variables, :cache)
11
13
 
12
14
  def initialize(variables, cache = Source::Null::Cache)
@@ -42,7 +44,7 @@ module FPM; module Fry
42
44
  def self_tar_io
43
45
  sio = StringIO.new
44
46
  tar = Gem::Package::TarWriter.new(sio)
45
- tar.add_file('Dockerfile','0777') do |io|
47
+ tar.add_file(NAME,'0777') do |io|
46
48
  io.write(dockerfile)
47
49
  end
48
50
  #tar.close
@@ -122,8 +124,10 @@ module FPM; module Fry
122
124
  def build_sh
123
125
  df = ['#!/bin/bash']
124
126
  df << 'set -e'
125
- recipe.steps.each do |k,v|
126
- df << "echo -e '\\e[1;32m====> #{Shellwords.escape k}\\e[0m'"
127
+ recipe.steps.each do |v|
128
+ if v.respond_to? :name
129
+ df << "echo -e '\\e[1;32m====> #{Shellwords.escape v.name}\\e[0m'"
130
+ end
127
131
  df << v.to_s
128
132
  end
129
133
  df << ''
@@ -136,7 +140,7 @@ module FPM; module Fry
136
140
  tar.add_file('.build.sh','0777') do |io|
137
141
  io.write(build_sh)
138
142
  end
139
- tar.add_file('Dockerfile','0777') do |io|
143
+ tar.add_file(NAME,'0777') do |io|
140
144
  io.write(dockerfile)
141
145
  end
142
146
  #tar.close
@@ -0,0 +1,90 @@
1
+ require 'fpm/fry/plugin'
2
+ module FPM::Fry::Plugin::Config
3
+
4
+ # @api private
5
+ IMPLICIT = Module.new
6
+
7
+ # @api private
8
+ MARK_EXPLICIT = Module.new do
9
+ def self.call(_, package)
10
+ package.attributes[:fry_config_explicitly_used] = true
11
+ end
12
+ end
13
+
14
+ # @api private
15
+ class Callback < Struct.new(:files)
16
+
17
+ def call(_, package)
18
+ prefix_length = package.staging_path.size + 1
19
+ candidates = []
20
+ # Sorting is important so that more specific rules override more generic
21
+ # rules.
22
+ keys = files.keys.sort_by(&:size)
23
+ keys.each do | key |
24
+ if files[key]
25
+ # Inclusion rule. Crawl file system for candidates
26
+ Find.find( File.expand_path(key, package.staging_path) ) do | path |
27
+ next unless File.file? path
28
+ name = path[prefix_length..-1]
29
+ candidates << name
30
+ end
31
+ else
32
+ # Exclusion rule. Remove matching candidates
33
+ keydir = key + "/"
34
+ candidates.reject!{ |can|
35
+ can.start_with?(keydir) || can == key
36
+ }
37
+ end
38
+ end
39
+ package.config_files |= candidates
40
+ end
41
+
42
+ end
43
+
44
+ class DSL < Struct.new(:builder, :options, :callback)
45
+
46
+ def initialize( builder, options )
47
+ callback = builder.output_hooks.find{|h| h.kind_of? Callback }
48
+ if !callback
49
+ callback = Callback.new({'etc' => true})
50
+ builder.output_hooks << callback
51
+ end
52
+ # This looks kind of dirty. The callback tells the cook comamnd that the
53
+ # user has explictly used the config plugin. This way the cook command
54
+ # can hint the user to use this plugin if config files were automatically
55
+ # added.
56
+ if !options[IMPLICIT]
57
+ builder.output_hooks << MARK_EXPLICIT
58
+ end
59
+ super( builder, options, callback )
60
+ end
61
+
62
+ def include( path )
63
+ if path[0] == "/"
64
+ path = path[1..-1]
65
+ end
66
+ callback.files[path] = true
67
+ end
68
+
69
+ def exclude( path )
70
+ if path[0] == "/"
71
+ path = path[1..-1]
72
+ end
73
+ callback.files[path] = false
74
+ end
75
+
76
+ end
77
+
78
+ def self.apply( builder, options = {}, &block )
79
+ dsl = DSL.new(builder, options)
80
+ if block
81
+ if block.arity == 1
82
+ yield dsl
83
+ else
84
+ dsl.instance_eval(&block)
85
+ end
86
+ end
87
+ dsl
88
+ end
89
+
90
+ end
@@ -0,0 +1,19 @@
1
+ module FPM::Fry::Plugin::SameVersion
2
+
3
+ # Generates a special constraint that ignores iterations.
4
+ # This is especially pointful in multi-package recipes.
5
+ # @example
6
+ # name 'mainpackage'
7
+ # version '0.2.3'
8
+ # package 'subpackage'
9
+ # plugin 'same_version'
10
+ # depends 'mainpackage', same_version
11
+ # end
12
+ #
13
+ def same_version
14
+ *head, last = version.split('.')
15
+ last = last.to_i + 1
16
+ return ">= #{version}, << #{head.join '.'}.#{last}"
17
+ end
18
+
19
+ end
@@ -1,29 +1,39 @@
1
1
  require 'fpm/fry/plugin'
2
2
  require 'fpm/fry/plugin/init'
3
3
  require 'fpm/fry/plugin/edit_staging'
4
+ require 'fpm/fry/plugin/config'
4
5
  require 'erb'
5
6
  require 'shellwords'
6
7
  module FPM::Fry::Plugin ; module Service
7
8
 
8
- class Environment < Struct.new(:name,:command, :description)
9
+ class Environment < Struct.new(:name,:command, :description, :limits, :user, :group, :chdir)
9
10
 
10
11
  def render(file)
11
12
  _erbout = ""
12
13
  erb = ERB.new(
13
- IO.read(File.join(File.dirname(__FILE__),'..','templates',file))
14
+ IO.read(File.join(File.dirname(__FILE__),'..','templates',file)),
15
+ 0, "-"
14
16
  )
15
- eval(erb.src)
17
+ eval(erb.src,nil,File.join(File.dirname(__FILE__),'..','templates',file))
16
18
  return _erbout
17
19
  end
18
20
 
19
21
  end
20
22
 
23
+ LIMITS = %w(core cpu data fsize memlock msgqueue nice nofile nproc rss rtprio sigpending stack)
24
+
21
25
  class DSL
22
26
 
27
+ attr :limits
28
+
23
29
  def initialize(*_)
24
30
  super
25
31
  @name = nil
26
32
  @command = []
33
+ @limits = {}
34
+ @user = nil
35
+ @group = nil
36
+ @chdir = nil
27
37
  end
28
38
 
29
39
  def name( n = nil )
@@ -33,6 +43,34 @@ module FPM::Fry::Plugin ; module Service
33
43
  return @name
34
44
  end
35
45
 
46
+ def group( n = nil )
47
+ if n
48
+ @group = n
49
+ end
50
+ return @group
51
+ end
52
+
53
+ def user( n = nil )
54
+ if n
55
+ @user = n
56
+ end
57
+ return @user
58
+ end
59
+
60
+ def limit( name, soft, hard = soft )
61
+ unless LIMITS.include? name
62
+ raise ArgumentError, "Unknown limit #{name.inspect}. Known limits are: #{LIMITS.inspect}"
63
+ end
64
+ @limits[name] = [soft,hard]
65
+ end
66
+
67
+ def chdir( dir = nil )
68
+ if dir
69
+ @chdir = dir
70
+ end
71
+ @chdir
72
+ end
73
+
36
74
  def command( *args )
37
75
  if args.any?
38
76
  @command = args
@@ -45,7 +83,7 @@ module FPM::Fry::Plugin ; module Service
45
83
  name = self.name || builder.name || raise
46
84
  init = Init.detect_init(builder.variables)
47
85
  edit = builder.plugin('edit_staging')
48
- env = Environment.new(name, command, "")
86
+ env = Environment.new(name, command, "", @limits, @user, @group, @chdir)
49
87
  case(init)
50
88
  when 'upstart' then
51
89
  edit.add_file "/etc/init/#{name}.conf",StringIO.new( env.render('upstart.erb') )
@@ -64,6 +102,10 @@ if status #{Shellwords.shellescape name} 2>/dev/null | grep -q ' start/'; then
64
102
  fi
65
103
  BASH
66
104
  end
105
+ builder.plugin('config', FPM::Fry::Plugin::Config::IMPLICIT => true) do |co|
106
+ co.include "etc/init/#{name}.conf"
107
+ co.include "etc/init.d/#{name}"
108
+ end
67
109
  when 'sysv' then
68
110
  edit.add_file "/etc/init.d/#{name}",StringIO.new( env.render('sysv.erb') ), chmod: '750'
69
111
  builder.plugin('script_helper') do |sh|
@@ -76,6 +118,9 @@ BASH
76
118
  update-rc.d -f #{Shellwords.shellescape name} remove
77
119
  BASH
78
120
  end
121
+ builder.plugin('config', FPM::Fry::Plugin::Config::IMPLICIT => true) do |co|
122
+ co.include "etc/init.d/#{name}"
123
+ end
79
124
  when 'systemd' then
80
125
 
81
126
  end
@@ -0,0 +1,21 @@
1
+ require 'fpm/fry/plugin'
2
+ module FPM::Fry::Plugin ; module User
3
+
4
+ def self.apply(builder, name, options = {}, &block)
5
+ cmd = ["adduser", "--system"]
6
+ case options[:group]
7
+ when String
8
+ cmd << '--ingroup' << options[:group]
9
+ when true
10
+ cmd << '--group'
11
+ when nil
12
+ else
13
+ raise ArgumentError, ":group must be a String or true, got #{options[:group].inspect}"
14
+ end
15
+ cmd << name
16
+ builder.plugin('script_helper') do |sh|
17
+ sh.after_install_or_upgrade(Shellwords.shelljoin(cmd))
18
+ end
19
+ end
20
+
21
+ end ; end
@@ -86,6 +86,9 @@ module FPM::Fry
86
86
  if mod.respond_to? :apply
87
87
  mod.apply(self, *args, &block)
88
88
  else
89
+ if args.any? or block_given?
90
+ raise ArgumentError, "Simple plugins can't accept additional arguments and blocks."
91
+ end
89
92
  extend(mod)
90
93
  end
91
94
  end
@@ -131,14 +134,16 @@ module FPM::Fry
131
134
 
132
135
  def parse_package( name, options = {} )
133
136
  if options.kind_of? String
134
- options = {version: options}
137
+ options = {constraints: options}
135
138
  end
136
- case(v = options[:version])
139
+ case(v = options[:constraints])
137
140
  when String
138
- if v =~ /\A(<=|<<|>=|>>|<>|=|>|<)(\s*)/
139
- options[:version] = ' ' + $1 + ' ' + $'
140
- else
141
- options[:version] = ' = ' + v
141
+ options[:constraints] = v.split(',').map do |c|
142
+ if c =~ /\A\s*(<=|<<|>=|>>|<>|=|>|<)(\s*)/
143
+ $1 + ' ' + $'
144
+ else
145
+ '= ' + c
146
+ end
142
147
  end
143
148
  end
144
149
  return name, options
@@ -202,8 +207,16 @@ module FPM::Fry
202
207
  options = {}
203
208
  end
204
209
  command = args.shift
205
- name = options.fetch(:name){ [command,*args].select{|c| c[0] != '-' }.join('-') }
206
- recipe.steps[name] = Shellwords.join([command, *args])
210
+ name = options.fetch(:name){ [command,*args].select{|c| c[0] != '-' }.join(' ') }
211
+ bash( name, Shellwords.join([command, *args]) )
212
+ end
213
+
214
+ def bash( name = nil, code )
215
+ if name
216
+ recipe.steps << Recipe::Step.new(name, code)
217
+ else
218
+ recipe.steps << code.to_s
219
+ end
207
220
  end
208
221
 
209
222
  def build_depends( name , options = {} )
@@ -12,6 +12,12 @@ module FPM; module Fry
12
12
 
13
13
  class Recipe
14
14
 
15
+ class Step < Struct.new(:name, :value)
16
+ def to_s
17
+ value.to_s
18
+ end
19
+ end
20
+
15
21
  class PackageRecipe
16
22
  attr_accessor :name,
17
23
  :iteration,
@@ -62,7 +68,14 @@ module FPM; module Fry
62
68
  end
63
69
  [:dependencies, :conflicts, :replaces, :provides].each do |sym|
64
70
  send(sym).each do |name, options|
65
- package.send(sym) << "#{name}#{options[:version]}"
71
+ constr = Array(options[:constraints])
72
+ if constr.any?
73
+ constr.each do | c |
74
+ package.send(sym) << "#{name} #{c}"
75
+ end
76
+ else
77
+ package.send(sym) << name
78
+ end
66
79
  end
67
80
  end
68
81
  output_hooks.each{|h| h.call(self, package) }
@@ -112,7 +125,7 @@ module FPM; module Fry
112
125
 
113
126
  def initialize
114
127
  @source = Source::Null
115
- @steps = {}
128
+ @steps = []
116
129
  @packages = [PackageRecipe.new]
117
130
  @packages[0].files << '**'
118
131
  @build_depends = {}
@@ -1,4 +1,21 @@
1
1
  #!/bin/sh
2
+ <%
3
+ startopts = ['']
4
+ if user
5
+ if group
6
+ startopts << '-c' << Shellwords.escape(user + ':' + group)
7
+ else
8
+ startopts << '-c' << Shellwords.escape(user)
9
+ end
10
+ else
11
+ if group
12
+ startopts << '-g' << Shellwords.escape(group)
13
+ end
14
+ end
15
+ if chdir
16
+ startopts << '-d' << Shellwords.escape(chdir)
17
+ end
18
+ -%>
2
19
  ### BEGIN INIT INFO
3
20
  # Provides: <%= name %>
4
21
  # Required-Start: $remote_fs $syslog
@@ -42,7 +59,7 @@ do_start()
42
59
  # 2 if daemon could not be started
43
60
  start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $DAEMON --test > /dev/null \
44
61
  || return 1
45
- start-stop-daemon --start --quiet --pidfile $PIDFILE --background --exec $DAEMON -- \
62
+ start-stop-daemon --start --quiet --pidfile $PIDFILE --background<%= startopts.join(" ") %> --exec $DAEMON -- \
46
63
  $DAEMON_ARGS \
47
64
  || return 2
48
65
  # Add code here, if necessary, that waits for the process to be ready
@@ -7,6 +7,15 @@ env NAME=<%= name.inspect %>
7
7
  env DAEMON=<%= command[0].inspect %>
8
8
  env DAEMON_ARGS=<%= Shellwords.shelljoin(command[1..-1]).inspect %>
9
9
 
10
+ <% if user %>setuid <%= user.inspect %>
11
+ <% end -%>
12
+ <% if group %>setgid <%= group.inspect %>
13
+ <% end -%>
14
+ <% if chdir %>chdir <%= chdir.inspect %>
15
+ <% end -%>
16
+ <% limits.each do | name, (soft, hard) | -%>
17
+ limit <%= name %> <%= soft %> <%= hard %>
18
+ <% end -%>
10
19
  respawn
11
20
 
12
21
  script
data/lib/fpm/fry/ui.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  require 'cabin/nice_output'
2
+ require 'fpm/fry/channel'
2
3
  module FPM; module Fry
3
4
  class UI < Struct.new(:out, :err, :logger, :tmpdir)
4
5
 
5
6
  def initialize( out = STDOUT, err = STDERR, logger = nil , tmpdir = '/tmp/fpm-fry' )
6
- logger ||= Cabin::Channel.new.tap{|chan| chan.subscribe(Cabin::NiceOutput.new(out)) }
7
+ logger ||= Channel.new.tap{|chan| chan.subscribe(Cabin::NiceOutput.new(out)) }
7
8
  FileUtils.mkdir_p( tmpdir )
8
9
  super( out, err, logger, tmpdir )
9
10
  end
@@ -25,7 +25,7 @@ class FPM::Package::Docker < FPM::Package
25
25
  def split( name, map )
26
26
  changes = changes(name)
27
27
  changes.remove_modified_leaves! do | ml |
28
- @logger.warn("Found a modified file. You can only create new files in a package",file: ml)
28
+ @logger.warn("Found a modified file. You can only create new files in a package",name: ml)
29
29
  end
30
30
  fmap = {}
31
31
  changes.leaves.each do | change |
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fpm-fry
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hannes Georg
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-13 00:00:00.000000000 Z
11
+ date: 2015-12-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: excon
@@ -49,6 +49,7 @@ files:
49
49
  - lib/cabin/nice_output.rb
50
50
  - lib/fpm/fry/block_enumerator.rb
51
51
  - lib/fpm/fry/build_output_parser.rb
52
+ - lib/fpm/fry/channel.rb
52
53
  - lib/fpm/fry/client.rb
53
54
  - lib/fpm/fry/command.rb
54
55
  - lib/fpm/fry/command/cook.rb
@@ -58,12 +59,15 @@ files:
58
59
  - lib/fpm/fry/os_db.rb
59
60
  - lib/fpm/fry/plugin.rb
60
61
  - lib/fpm/fry/plugin/alternatives.rb
62
+ - lib/fpm/fry/plugin/config.rb
61
63
  - lib/fpm/fry/plugin/edit_staging.rb
62
64
  - lib/fpm/fry/plugin/exclude.rb
63
65
  - lib/fpm/fry/plugin/init.rb
64
66
  - lib/fpm/fry/plugin/platforms.rb
67
+ - lib/fpm/fry/plugin/same_version.rb
65
68
  - lib/fpm/fry/plugin/script_helper.rb
66
69
  - lib/fpm/fry/plugin/service.rb
70
+ - lib/fpm/fry/plugin/user.rb
67
71
  - lib/fpm/fry/recipe.rb
68
72
  - lib/fpm/fry/recipe/builder.rb
69
73
  - lib/fpm/fry/source.rb
@@ -103,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
107
  version: '0'
104
108
  requirements: []
105
109
  rubyforge_project:
106
- rubygems_version: 2.2.1
110
+ rubygems_version: 2.4.8
107
111
  signing_key:
108
112
  specification_version: 4
109
113
  summary: FPM Fry