fpm-cookery 0.15.0 → 0.16.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +10 -0
- data/CHANGELOG.md +8 -0
- data/bin/fpm-cook +1 -1
- data/fpm-cookery.gemspec +2 -1
- data/lib/fpm/cookery/chain_packager.rb +58 -0
- data/lib/fpm/cookery/cli.rb +93 -104
- data/lib/fpm/cookery/config.rb +86 -0
- data/lib/fpm/cookery/dependency_inspector.rb +7 -3
- data/lib/fpm/cookery/exceptions.rb +11 -0
- data/lib/fpm/cookery/facts.rb +1 -0
- data/lib/fpm/cookery/log.rb +1 -1
- data/lib/fpm/cookery/package/dir.rb +11 -35
- data/lib/fpm/cookery/package/gem.rb +25 -0
- data/lib/fpm/cookery/package/maintainer.rb +39 -0
- data/lib/fpm/cookery/package/package.rb +100 -0
- data/lib/fpm/cookery/package/version.rb +48 -0
- data/lib/fpm/cookery/packager.rb +65 -97
- data/lib/fpm/cookery/path.rb +4 -0
- data/lib/fpm/cookery/recipe.rb +59 -19
- data/lib/fpm/cookery/shellout.rb +35 -0
- data/lib/fpm/cookery/source_handler/curl.rb +12 -2
- data/lib/fpm/cookery/version.rb +1 -1
- data/recipes/arr-pm/recipe.rb +4 -0
- data/recipes/backports/recipe.rb +4 -0
- data/recipes/cabin/recipe.rb +4 -0
- data/recipes/clamp/recipe.rb +4 -0
- data/recipes/facter/recipe.rb +4 -0
- data/recipes/fpm-cookery-gem/addressable.rb +4 -0
- data/recipes/fpm-cookery-gem/arr-pm.rb +4 -0
- data/recipes/fpm-cookery-gem/backports.rb +4 -0
- data/recipes/fpm-cookery-gem/cabin.rb +4 -0
- data/recipes/fpm-cookery-gem/childprocess.rb +7 -0
- data/recipes/fpm-cookery-gem/clamp.rb +4 -0
- data/recipes/fpm-cookery-gem/facter.rb +4 -0
- data/recipes/fpm-cookery-gem/ffi.rb +4 -0
- data/recipes/fpm-cookery-gem/fpm.rb +7 -0
- data/recipes/fpm-cookery-gem/ftw.rb +7 -0
- data/recipes/fpm-cookery-gem/hiera.rb +7 -0
- data/recipes/fpm-cookery-gem/http_parser.rb.rb +4 -0
- data/recipes/fpm-cookery-gem/json.rb +4 -0
- data/recipes/fpm-cookery-gem/json_pure.rb +4 -0
- data/recipes/fpm-cookery-gem/puppet.rb +7 -0
- data/recipes/fpm-cookery-gem/recipe.rb +7 -0
- data/recipes/fpm-cookery-gem/rgen.rb +4 -0
- data/recipes/fpm-cookery/recipe.rb +1 -1
- data/recipes/fpm-cookery/ruby.rb +20 -10
- data/recipes/fpm/recipe.rb +4 -0
- data/recipes/json/recipe.rb +4 -0
- data/recipes/open4/recipe.rb +4 -0
- data/spec/config_spec.rb +167 -0
- data/spec/facts_spec.rb +7 -0
- data/spec/fixtures/test-config-1.yml +2 -0
- data/spec/package_maintainer_spec.rb +79 -0
- data/spec/package_spec.rb +182 -0
- data/spec/package_version_spec.rb +119 -0
- data/spec/recipe_spec.rb +18 -0
- data/spec/spec_helper.rb +1 -0
- metadata +61 -6
data/.travis.yml
ADDED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
# v0.16.0 (2013-09-21)
|
2
|
+
* Chain packager. (smasset)
|
3
|
+
* Add show-depends CLI option. (unakatsuo)
|
4
|
+
* Add fpm-cookery chain packager gem recipes. (smasset)
|
5
|
+
* Compatibility fixes for the latest FPM releases. (skiold)
|
6
|
+
* Fix problems with tar files that contain no directories. (narkisr)
|
7
|
+
* New CLI options parsing backend. (using clamp)
|
8
|
+
|
1
9
|
# v0.15.0 (2013-06-13)
|
2
10
|
* Add --no-deps option to disable dependency checks.
|
3
11
|
|
data/bin/fpm-cook
CHANGED
data/fpm-cookery.gemspec
CHANGED
@@ -18,10 +18,11 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_development_dependency "minitest", "~>
|
21
|
+
s.add_development_dependency "minitest", "~> 5.0"
|
22
22
|
s.add_development_dependency "rake"
|
23
23
|
s.add_runtime_dependency "fpm", "~> 0.4"
|
24
24
|
s.add_runtime_dependency "facter"
|
25
25
|
s.add_runtime_dependency "puppet"
|
26
26
|
s.add_runtime_dependency "addressable"
|
27
|
+
s.add_runtime_dependency "systemu"
|
27
28
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'fpm/cookery/packager'
|
2
|
+
require 'fpm/cookery/omnibus_packager'
|
3
|
+
|
4
|
+
module FPM
|
5
|
+
module Cookery
|
6
|
+
class ChainPackager
|
7
|
+
include FPM::Cookery::Utils
|
8
|
+
|
9
|
+
attr_reader :packager, :recipe, :config
|
10
|
+
|
11
|
+
def initialize(packager, config = {})
|
12
|
+
@packager = packager
|
13
|
+
@recipe = packager.recipe
|
14
|
+
@config = config
|
15
|
+
end
|
16
|
+
|
17
|
+
def run
|
18
|
+
Log.info "Recipe #{recipe.name} is a chain package; looking for child recipes to build"
|
19
|
+
|
20
|
+
recipe.chain_recipes.each do |name|
|
21
|
+
recipe_file = build_recipe_file_path(name)
|
22
|
+
|
23
|
+
unless File.exists?(recipe_file)
|
24
|
+
Log.fatal "Cannot find a recipe for #{name} at #{recipe_file}"
|
25
|
+
exit 1
|
26
|
+
end
|
27
|
+
|
28
|
+
Log.info "Located recipe at #{recipe_file} for child recipe #{name}; starting build"
|
29
|
+
|
30
|
+
FPM::Cookery::Book.instance.load_recipe(recipe_file) do |dep_recipe|
|
31
|
+
depPackager = FPM::Cookery::Packager.new(dep_recipe, config)
|
32
|
+
depPackager.target = FPM::Cookery::Facts.target.to_s
|
33
|
+
|
34
|
+
#Chain, chain, chain ...
|
35
|
+
if dep_recipe.omnibus_package == true
|
36
|
+
FPM::Cookery::OmnibusPackager.new(depPackager, config).run
|
37
|
+
elsif dep_recipe.chain_package == true
|
38
|
+
FPM::Cookery::ChainPackager.new(depPackager, config).run
|
39
|
+
else
|
40
|
+
depPackager.dispense
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
Log.info "Finished building #{name}, moving on to next recipe"
|
45
|
+
end
|
46
|
+
|
47
|
+
packager.dispense
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def build_recipe_file_path(name)
|
53
|
+
# Look for recipes in the same dir as the recipe we loaded
|
54
|
+
File.expand_path(File.dirname(recipe.filename) + "/#{name}.rb")
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/fpm/cookery/cli.rb
CHANGED
@@ -2,51 +2,74 @@ require 'fpm/cookery/book_hook'
|
|
2
2
|
require 'fpm/cookery/recipe'
|
3
3
|
require 'fpm/cookery/facts'
|
4
4
|
require 'fpm/cookery/packager'
|
5
|
+
require 'fpm/cookery/chain_packager'
|
5
6
|
require 'fpm/cookery/omnibus_packager'
|
6
7
|
require 'fpm/cookery/log'
|
7
8
|
require 'fpm/cookery/log/output/console'
|
8
9
|
require 'fpm/cookery/log/output/console_color'
|
9
|
-
require '
|
10
|
+
require 'fpm/cookery/config'
|
11
|
+
require 'clamp'
|
10
12
|
|
11
13
|
module FPM
|
12
14
|
module Cookery
|
13
|
-
class CLI
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
class CLI < Clamp::Command
|
16
|
+
option ['-c', '--color'], :flag, 'toggle color'
|
17
|
+
option ['-D', '--debug'], :flag, 'enable debug output'
|
18
|
+
option ['-t', '--target'], 'TARGET', 'set desired fpm output target (deb, rpm, etc)'
|
19
|
+
option ['-p', '--platform'], 'PLATFORM', 'set the target platform (centos, ubuntu, debian)'
|
20
|
+
option ['-V', '--version'], :flag, 'show fpm-cookery and fpm version'
|
21
|
+
option '--[no-]deps', :flag, 'enable/disable dependency checking',
|
22
|
+
:attribute_name => 'dependency_check'
|
23
|
+
|
24
|
+
class Command < self
|
25
|
+
def recipe_file
|
26
|
+
file = File.expand_path(recipe)
|
18
27
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
"Usage: #{program} [options] [path/to/recipe.rb] action [...]"
|
24
|
-
options.separator "Actions:"
|
25
|
-
options.separator " package - builds the package"
|
26
|
-
options.separator " clean - cleans up"
|
27
|
-
options.separator " install-deps - installs build and runtime dependencies"
|
28
|
-
options.separator "Options:"
|
29
|
-
|
30
|
-
options.on("-c", "--color",
|
31
|
-
"Toggle color. (default #{@colors.inspect})") do |o|
|
32
|
-
@colors = !@colors
|
33
|
-
end
|
28
|
+
# Allow giving the directory containing a recipe.rb
|
29
|
+
if File.directory?(file) && File.exists?(File.join(file, 'recipe.rb'))
|
30
|
+
file = File.join(file, 'recipe.rb')
|
31
|
+
end
|
34
32
|
|
35
|
-
|
36
|
-
@debug = true
|
33
|
+
file
|
37
34
|
end
|
38
35
|
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
def validate
|
37
|
+
unless File.exists?(recipe_file)
|
38
|
+
Log.error 'No recipe.rb found in the current directory, abort.'
|
39
|
+
exit 1
|
40
|
+
end
|
41
|
+
|
42
|
+
# Override the detected platform.
|
43
|
+
if platform
|
44
|
+
FPM::Cookery::Facts.platform = platform
|
45
|
+
end
|
46
|
+
|
47
|
+
if target
|
48
|
+
FPM::Cookery::Facts.target = target
|
49
|
+
end
|
50
|
+
|
51
|
+
if FPM::Cookery::Facts.target.nil?
|
52
|
+
Log.error "No target given and we're unable to detect your platform"
|
53
|
+
exit 1
|
54
|
+
end
|
42
55
|
end
|
43
56
|
|
44
|
-
|
45
|
-
|
46
|
-
|
57
|
+
def execute
|
58
|
+
show_version if version?
|
59
|
+
init_logging
|
60
|
+
validate
|
61
|
+
|
62
|
+
FPM::Cookery::BaseRecipe.send(:include, FPM::Cookery::BookHook)
|
63
|
+
|
64
|
+
FPM::Cookery::Book.instance.load_recipe(recipe_file) do |recipe|
|
65
|
+
packager = FPM::Cookery::Packager.new(recipe, :dependency_check => config.dependency_check)
|
66
|
+
packager.target = FPM::Cookery::Facts.target.to_s
|
67
|
+
|
68
|
+
exec(config, recipe, packager)
|
69
|
+
end
|
47
70
|
end
|
48
71
|
|
49
|
-
|
72
|
+
def show_version
|
50
73
|
require 'fpm/version'
|
51
74
|
require 'fpm/cookery/version'
|
52
75
|
|
@@ -54,99 +77,65 @@ module FPM
|
|
54
77
|
exit 0
|
55
78
|
end
|
56
79
|
|
57
|
-
|
58
|
-
@
|
80
|
+
def config
|
81
|
+
@config ||= FPM::Cookery::Config.from_cli(self)
|
59
82
|
end
|
60
83
|
|
61
|
-
|
62
|
-
|
84
|
+
def init_logging
|
85
|
+
FPM::Cookery::Log.enable_debug(config.debug)
|
63
86
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
FPM::Cookery::Log.output(FPM::Cookery::Log::Output::Console.new)
|
87
|
+
if config.color?
|
88
|
+
FPM::Cookery::Log.output(FPM::Cookery::Log::Output::ConsoleColor.new)
|
89
|
+
else
|
90
|
+
FPM::Cookery::Log.output(FPM::Cookery::Log::Output::Console.new)
|
91
|
+
end
|
70
92
|
end
|
93
|
+
end
|
71
94
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
# See if something that looks like a recipe path is in arguments
|
76
|
-
remainder.each do |arg|
|
77
|
-
# If 'foo.rb' was given, and it exists, use it.
|
78
|
-
if arg =~ /\.rb$/ and File.exists?(arg)
|
79
|
-
remainder.delete(arg)
|
80
|
-
@filename = arg
|
81
|
-
break
|
82
|
-
end
|
95
|
+
class PackageCmd < Command
|
96
|
+
parameter '[RECIPE]', 'the recipe file', :default => 'recipe.rb'
|
83
97
|
|
84
|
-
|
85
|
-
if
|
86
|
-
|
87
|
-
|
88
|
-
|
98
|
+
def exec(config, recipe, packager)
|
99
|
+
if recipe.omnibus_package == true
|
100
|
+
FPM::Cookery::OmnibusPackager.new(packager).run
|
101
|
+
elsif recipe.chain_package == true
|
102
|
+
FPM::Cookery::ChainPackager.new(packager, :dependency_check => config.dependency_check).run
|
103
|
+
else
|
104
|
+
packager.dispense
|
89
105
|
end
|
90
106
|
end
|
91
|
-
|
92
|
-
# Everything that's not the recipe filename is an action.
|
93
|
-
@actions = remainder
|
94
|
-
return self
|
95
107
|
end
|
96
108
|
|
97
|
-
|
98
|
-
|
99
|
-
Log.error 'No recipe.rb found in the current directory, abort.'
|
100
|
-
exit 1
|
101
|
-
end
|
102
|
-
|
103
|
-
# Default action is "package"
|
104
|
-
if @actions.empty?
|
105
|
-
@actions = ["package"]
|
106
|
-
end
|
109
|
+
class CleanCmd < Command
|
110
|
+
parameter '[RECIPE]', 'the recipe file', :default => 'recipe.rb'
|
107
111
|
|
108
|
-
|
109
|
-
|
110
|
-
FPM::Cookery::Facts.platform = @platform
|
112
|
+
def exec(config, recipe, packager)
|
113
|
+
packager.cleanup
|
111
114
|
end
|
115
|
+
end
|
112
116
|
|
113
|
-
|
114
|
-
|
115
|
-
end
|
117
|
+
class InstallDepsCmd < Command
|
118
|
+
parameter '[RECIPE]', 'the recipe file', :default => 'recipe.rb'
|
116
119
|
|
117
|
-
|
118
|
-
|
119
|
-
exit 1
|
120
|
+
def exec(config, recipe, packager)
|
121
|
+
packager.install_deps
|
120
122
|
end
|
121
|
-
|
122
123
|
end
|
123
124
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
FPM::Cookery::Book.instance.load_recipe(@filename) do |recipe|
|
130
|
-
packager = FPM::Cookery::Packager.new(recipe, :dependency_check => !@nodep)
|
131
|
-
packager.target = FPM::Cookery::Facts.target.to_s
|
132
|
-
|
133
|
-
@actions.each do |action|
|
134
|
-
case action
|
135
|
-
when "clean" ; packager.cleanup
|
136
|
-
when "package"
|
137
|
-
if recipe.omnibus_package == true
|
138
|
-
FPM::Cookery::OmnibusPackager.new(packager).run
|
139
|
-
else
|
140
|
-
packager.dispense
|
141
|
-
end
|
142
|
-
when "install-deps" ; packager.install_deps
|
143
|
-
else
|
144
|
-
# TODO(sissel): fail if this happens
|
145
|
-
Log.error "Unknown action: #{action}"
|
146
|
-
end
|
147
|
-
end
|
125
|
+
class ShowDepsCmd < Command
|
126
|
+
parameter '[RECIPE]', 'the recipe file', :default => 'recipe.rb'
|
127
|
+
|
128
|
+
def exec(config, recipe, packager)
|
129
|
+
puts recipe.depends_all.join(' ')
|
148
130
|
end
|
149
131
|
end
|
132
|
+
|
133
|
+
self.default_subcommand = 'package'
|
134
|
+
|
135
|
+
subcommand 'package', 'builds the package', PackageCmd
|
136
|
+
subcommand 'clean', 'cleans up', CleanCmd
|
137
|
+
subcommand 'install-deps', 'installs build and runtime dependencies', InstallDepsCmd
|
138
|
+
subcommand 'show-deps', 'show build and runtime dependencies', ShowDepsCmd
|
150
139
|
end
|
151
140
|
end
|
152
141
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'fpm/cookery/exceptions'
|
3
|
+
|
4
|
+
module FPM
|
5
|
+
module Cookery
|
6
|
+
class Config
|
7
|
+
ATTRIBUTES = [
|
8
|
+
:color, :debug, :target, :platform, :maintainer, :vendor,
|
9
|
+
:skip_package, :keep_destdir, :dependency_check
|
10
|
+
].freeze
|
11
|
+
|
12
|
+
DEFAULTS = {
|
13
|
+
:color => true,
|
14
|
+
:debug => false,
|
15
|
+
:dependency_check => true,
|
16
|
+
:skip_package => false,
|
17
|
+
:keep_destdir => false
|
18
|
+
}.freeze
|
19
|
+
|
20
|
+
def self.load_file(paths)
|
21
|
+
path = Array(paths).find {|p| File.exist?(p) }
|
22
|
+
|
23
|
+
path ? new(YAML.load_file(path)) : new
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_cli(cli)
|
27
|
+
new.tap do |config|
|
28
|
+
ATTRIBUTES.each do |name|
|
29
|
+
if cli.respond_to?("#{name}?")
|
30
|
+
value = cli.__send__("#{name}?")
|
31
|
+
elsif cli.respond_to?(name)
|
32
|
+
value = cli.__send__(name)
|
33
|
+
else
|
34
|
+
value = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
config.__send__("#{name}=", value) unless value.nil?
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
attr_accessor *ATTRIBUTES
|
43
|
+
|
44
|
+
ATTRIBUTES.each do |name|
|
45
|
+
class_eval %Q(
|
46
|
+
def #{name}?
|
47
|
+
!!#{name}
|
48
|
+
end
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def initialize(data = {})
|
53
|
+
validate_input(data)
|
54
|
+
|
55
|
+
DEFAULTS.merge(data).each do |key, value|
|
56
|
+
self.__send__("#{key}=", value)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_hash
|
61
|
+
ATTRIBUTES.inject({}) do |hash, attribute|
|
62
|
+
hash[attribute] = __send__(attribute)
|
63
|
+
hash
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def validate_input(data)
|
70
|
+
errors = []
|
71
|
+
|
72
|
+
data.keys.each do |key|
|
73
|
+
unless ATTRIBUTES.include?(key.to_sym)
|
74
|
+
errors << key
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
unless errors.empty?
|
79
|
+
e = Error::InvalidConfigKey.new("Invalid config keys: #{errors.join(', ')}")
|
80
|
+
e.invalid_keys = errors
|
81
|
+
raise e
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -15,9 +15,7 @@ module FPM
|
|
15
15
|
|
16
16
|
Log.info "Verifying build_depends and depends with Puppet"
|
17
17
|
|
18
|
-
missing = (build_depends + depends)
|
19
|
-
self.package_installed?(package)
|
20
|
-
end
|
18
|
+
missing = missing_packages(build_depends + depends)
|
21
19
|
|
22
20
|
if missing.length == 0
|
23
21
|
Log.info "All build_depends and depends packages installed"
|
@@ -36,6 +34,12 @@ module FPM
|
|
36
34
|
|
37
35
|
end
|
38
36
|
|
37
|
+
def self.missing_packages(*pkgs)
|
38
|
+
pkgs.flatten.reject do |package|
|
39
|
+
self.package_installed?(package)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
39
43
|
def self.package_installed?(package)
|
40
44
|
Log.info("Verifying package: #{package}")
|
41
45
|
return unless self.package_suitable?(package)
|