fpm-cookery 0.32.0 → 0.33.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +5 -2
  4. data/CHANGELOG.md +19 -0
  5. data/Rakefile +34 -0
  6. data/docs/index.rst +1 -0
  7. data/docs/pages/using-hiera.rst +285 -0
  8. data/fpm-cookery.gemspec +6 -1
  9. data/lib/fpm/cookery/book.rb +29 -2
  10. data/lib/fpm/cookery/book_hook.rb +1 -0
  11. data/lib/fpm/cookery/chain_packager.rb +4 -2
  12. data/lib/fpm/cookery/cli.rb +45 -5
  13. data/lib/fpm/cookery/config.rb +2 -1
  14. data/lib/fpm/cookery/environment.rb +17 -8
  15. data/lib/fpm/cookery/exceptions.rb +3 -1
  16. data/lib/fpm/cookery/facts.rb +50 -35
  17. data/lib/fpm/cookery/hiera.rb +35 -0
  18. data/lib/fpm/cookery/hiera/defaults.rb +50 -0
  19. data/lib/fpm/cookery/hiera/scope.rb +35 -0
  20. data/lib/fpm/cookery/inheritable_attr.rb +222 -0
  21. data/lib/fpm/cookery/log/hiera.rb +21 -0
  22. data/lib/fpm/cookery/omnibus_packager.rb +4 -2
  23. data/lib/fpm/cookery/package/package.rb +1 -0
  24. data/lib/fpm/cookery/package/version.rb +11 -4
  25. data/lib/fpm/cookery/packager.rb +13 -11
  26. data/lib/fpm/cookery/recipe.rb +167 -105
  27. data/lib/fpm/cookery/source.rb +6 -8
  28. data/lib/fpm/cookery/source_handler.rb +18 -3
  29. data/lib/fpm/cookery/source_handler/curl.rb +2 -2
  30. data/lib/fpm/cookery/source_handler/directory.rb +10 -11
  31. data/lib/fpm/cookery/source_handler/noop.rb +1 -2
  32. data/lib/fpm/cookery/source_handler/svn.rb +1 -1
  33. data/lib/fpm/cookery/version.rb +1 -1
  34. data/lib/hiera/fpm_cookery_logger.rb +12 -0
  35. data/recipes/redis/config/common.yaml +11 -0
  36. data/recipes/redis/config/git_2.4.2_tag.yaml +4 -0
  37. data/recipes/redis/config/git_2.4.yaml +4 -0
  38. data/recipes/redis/config/git_sha_072a905.yaml +4 -0
  39. data/recipes/redis/config/svn_r2400.yaml +4 -0
  40. data/recipes/redis/config/svn_trunk.yaml +3 -0
  41. data/recipes/redis/recipe.rb +2 -27
  42. data/spec/book_spec.rb +34 -0
  43. data/spec/config_spec.rb +19 -0
  44. data/spec/environment_spec.rb +37 -0
  45. data/spec/facts_spec.rb +54 -31
  46. data/spec/fixtures/hiera_config/CentOS.yaml +1 -0
  47. data/spec/fixtures/hiera_config/common.yaml +12 -0
  48. data/spec/fixtures/hiera_config/custom.yaml +3 -0
  49. data/spec/fixtures/hiera_config/rpm.yaml +12 -0
  50. data/spec/hiera_spec.rb +158 -0
  51. data/spec/inheritable_attr_spec.rb +202 -0
  52. data/spec/package_dir_spec.rb +37 -0
  53. data/spec/package_maintainer_spec.rb +4 -1
  54. data/spec/package_version_spec.rb +50 -0
  55. data/spec/path_spec.rb +20 -0
  56. data/spec/recipe_spec.rb +161 -56
  57. data/spec/source_integrity_check_spec.rb +7 -6
  58. data/spec/spec_helper.rb +14 -0
  59. data/spec/support/shared_context.rb +71 -0
  60. metadata +108 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a8092cdd01badb7c7c69adc60983e1d8b220f878
4
- data.tar.gz: b31722bf137e40a7201b1b8b00aaa6adc89ca165
3
+ metadata.gz: 1bf794a51fecd510948128ab67bb5c795ed3e4c6
4
+ data.tar.gz: 7020e143e7ba574171c2ace14831df9336e40182
5
5
  SHA512:
6
- metadata.gz: cf005ab828be976ab4372ea4366155ac3e0c9b21d545d462a7000430ceebd4117c0cff927c7feb17a39873e6057b79d8a5f83e8bb30789f3ff216efc2a2674af
7
- data.tar.gz: a3b7a495348df7a575f802f7f4881a4996791a7ae5a4fade00f62111c5da79196fa99c08ee4cfa2a95e339e0caa07511bafcdbad5b074647e6682ee3e335a894
6
+ metadata.gz: a711e293257e46fbb1b46601c96e4ee90152cb835604ab30e75fc10f204f54f2b5d19591ef9a6777ea2b085dc50097554611517a1601aa1a886e4008dbb193ff
7
+ data.tar.gz: 0625f2d75df8e1aaafdeedcf2796ffc4b65d57a8648cbdd655aa60ae09f353fa6eb60ee5bf8f5d6ae03207c3bdb61a12f601e611cdc62474efa32107c31d6746
data/.gitignore CHANGED
@@ -12,6 +12,8 @@ tmp-dest/
12
12
  .vagrant
13
13
  Vagrantfile
14
14
  /vendor
15
+ /coverage
16
+ /doc
15
17
 
16
18
  # vim backups
17
19
  *~
@@ -1,10 +1,13 @@
1
1
  sudo: false
2
+ cache: bundler
2
3
  script: bundle exec rake spec
3
4
  rvm:
4
5
  - 1.9.3
5
6
  - 2.0.0
6
- - 2.1.1
7
- - 2.2.1
7
+ - 2.1.10
8
+ - 2.2.5
9
+ - 2.3.1
10
+ - 2.4.1
8
11
  - ruby-head
9
12
 
10
13
  matrix:
@@ -1,3 +1,22 @@
1
+ # v0.33.0
2
+ * Hiera lookups of recipe data from templated YAML files. (BaxterStockman / #150)
3
+ * Travis-CI build matrix improvements. (thedrow / #155)
4
+ * Expose `lsbcodename` fact. (thedrow / #158)
5
+ * Improved build cookie generator. (BaxterStockman / #157)
6
+ * Improved facter usage. (BaxterStockman / #167)
7
+ * Alpine (apk) package support. (lloydpick / #162)
8
+ * Fix typos and missing tests. (lloydpick / #163)
9
+ * Add `inspect` command. (BaxterStockman / #165)
10
+ * json dependency fix to work with older Rubies. (BaxterStockman / #166)
11
+ * Bug fix when using local directory sources. (#164)
12
+ * Make vendor delimiter configurable. (#169)
13
+ * Ensure consistend extracted source value from all source handlers. (#170)
14
+ * Add default package version and guard against nil/empty versions. (BaxterStockman / #176)
15
+ * Documenting the use of Hiera in recipes. (BaxterStockman / #184)
16
+ * Ruby pre-2.0 compatibility fix. (BaxterStockman / #183)
17
+ * Add "safe\_yaml" dependency. (davewongillies / #186, #154)
18
+ * Add `rpm_dist` method. (sfzylad / #190)
19
+
1
20
  # v0.32.0
2
21
  * Add `sourcedir` accessor that holds the path to the extracted source. (#132)
3
22
  * Add support for DirRecipe and Directory Handler. (cas-ei / #147)
data/Rakefile CHANGED
@@ -5,3 +5,37 @@ desc 'Run all specs'
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
 
7
7
  task :default => :spec
8
+
9
+ namespace :docs do |ns|
10
+ require 'systemu'
11
+
12
+ docs_dir = File.join(File.dirname(File.expand_path(__FILE__)), 'docs')
13
+
14
+ Dir.chdir docs_dir do
15
+ sphinxbuild = ENV['SPHINXBUILD'] || 'sphinx-build'
16
+
17
+ status, stdout, stderr = systemu "make SPHINXBUILD=#{sphinxbuild} help"
18
+ if status != 0 and Rake.verbose
19
+ $stderr.puts '# Unable to load tasks in the `docs` namespace:'
20
+ stderr.each_line { |l| $stderr.puts "# #{l}" }
21
+ end
22
+
23
+ desc 'clean up doc builds'
24
+ task 'clean' do
25
+ Dir.chdir docs_dir do
26
+ system "make SPHINXBUILD=#{sphinxbuild} clean"
27
+ end
28
+ end
29
+
30
+ stdout.each_line.grep(/^\s+(\w+?)\s+(.*)$/) do
31
+ t, d = $1, $2
32
+
33
+ desc d
34
+ task t do
35
+ Dir.chdir docs_dir do
36
+ system "make SPHINXBUILD=#{sphinxbuild} #{t}"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -26,6 +26,7 @@ Documentation Contents
26
26
  :maxdepth: 2
27
27
 
28
28
  pages/getting-started
29
+ pages/using-hiera
29
30
 
30
31
 
31
32
  Indices and tables
@@ -0,0 +1,285 @@
1
+ Using Hiera
2
+ ===========
3
+
4
+ `Hiera <http://docs.puppetlabs.com/hiera>`_ is a hierarchical key-value lookup
5
+ tool from Puppet Labs that, integrated with fpm-cookery, allows you to improve
6
+ your package builds by:
7
+
8
+ * Separating data from build logic,
9
+ * Selectively overriding particular recipe attributes for different platforms,
10
+ software versions, etc., and
11
+ * Staying DRY by reusing data via the ``hiera`` and ``scope``
12
+ :ref:`interpolation methods <hiera-interpolation-in-data-files>`.
13
+
14
+ Configuring Hiera
15
+ -----------------
16
+
17
+ Controlling the Lookup Hierarchy
18
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19
+
20
+ By default, FPM-Cookery looks for Hiera data files under the ``config``
21
+ subdirectory of the directory containing the target recipe. You can override
22
+ this through the ``--data-dir`` option to ``fpm-cook``. You can also set the
23
+ data file directory via the ``datadir=`` class method while defining the recipe
24
+ class:
25
+
26
+ .. code-block:: ruby
27
+
28
+ class FreshRecipe < FPM::Cookery::Recipe
29
+ datadir = "/somewhere/other/than/#{File.dirname(__FILE__)}/config"
30
+ end
31
+
32
+ .. note::
33
+
34
+ Part of the recipe initialization process involves :ref:`automatically
35
+ applying data<hiera-automatic-application-of-hiera-data>` contained in the
36
+ files in the current ``datadir``. If you change ``datadir`` after the
37
+ ``initialize`` method completes, you must call the ``apply`` method
38
+ manually to reconfigure the recipe according to the files in the the new
39
+ ``datadir``.
40
+
41
+ When retrieving recipe data, fpm-cookery observes the following hierarchy of
42
+ files under ``datadir``, ordered from highest to lowest precedence:
43
+
44
+ +--------------------------------+--------------------------------------------+
45
+ | Path | Description |
46
+ +================================+============================================+
47
+ | ``"#{recipe.platform}.yaml"``, | The platform for which the recipe is being |
48
+ | ``"#{recipe.platform}.json"`` | built. Corresponds to Facter's |
49
+ | | ``operatingsystem`` fact, except that all |
50
+ | | characters are lowercase. For instance, if |
51
+ | | ``operatingsystem`` is ``ArchLinux``, |
52
+ | | ``recipe.platform`` will be ``archlinux``. |
53
+ +--------------------------------+--------------------------------------------+
54
+ | ``"#{recipe.target}.yaml"``, | The target package type. Options span all |
55
+ | ``"#{recipe.target}.json"`` | package types that FPM can build, |
56
+ | | including include ``rpm``, ``apk``, |
57
+ | | ``deb``, ``osxpkg``, and others. |
58
+ +--------------------------------+--------------------------------------------+
59
+ | ``"common.yaml"``, | Intended for configuration data that is |
60
+ | ``"common.json"`` | common to all builds. |
61
+ +--------------------------------+--------------------------------------------+
62
+
63
+ You can further influence the lookup hierarchy by setting the environment
64
+ variable ``FPM_HIERARCHY``. The value should be string containing a
65
+ colon-separated list of filename stems. For example::
66
+
67
+ $ FPM_HIERARCHY=centos:rhel:el fpm-cook package
68
+
69
+ prepends ``centos``, ``rhel``, and ``el`` to the search hierarchy, causing
70
+ fpm-cookery to attempt load data from ``centos.yaml``, ``rhel.yaml``,
71
+ ``el.yaml``, and their ``.json`` counterparts. The final hierarchy is:
72
+
73
+ * ``"centos.yaml"``
74
+ * ``"rhel.yaml"``
75
+ * ``"el.yaml"``
76
+ * ``"#{recipe.platform}.yaml"``
77
+ * ``"#{recipe.target}.yaml"``
78
+ * ``"common.yaml"``
79
+
80
+ Other Settings
81
+ ^^^^^^^^^^^^^^
82
+
83
+ You can exercise more fine-grained control by providing the path to a Hiera
84
+ configuration file via the ``--hiera-config`` option. See `the Hiera docs
85
+ <http://docs.puppetlabs.com/hiera/3.0/configuring.html>`_ for available
86
+ configuration file options.
87
+
88
+ Hiera in Recipes
89
+ ----------------
90
+
91
+ Lookups
92
+ ^^^^^^^
93
+
94
+ fpm-cookery provides the ``lookup`` class method on all classes that inherit
95
+ from ``FPM::Cookery::Recipe``, as well as an instance method of the same name.
96
+ ``lookup`` takes one mandatory argument: a key to be looked up in the Hiera
97
+ data files. If Hiera locates the key, ``lookup`` returns the corresponding
98
+ value; otherwise ``lookup`` returns ``nil``.
99
+
100
+ Writing Data Files
101
+ ^^^^^^^^^^^^^^^^^^
102
+
103
+ See `the Hiera data sources documentation <http://docs.puppetlabs.com/hiera/3.0/data_sources.html>`_
104
+ for an overview of Hiera data sources.
105
+
106
+ .. note::
107
+
108
+ Please ensure that your data files use the extensions ``.yaml`` or
109
+ ``.json``, as appropriate -- Hiera ignores files with any other
110
+ extension.
111
+
112
+ You'll probably find data files most useful for defining recipe attributes.
113
+ However, key-value mappings in Hiera data sources need not correspond to recipe
114
+ attributes -- you can store any data you like as long as it is valid YAML or
115
+ JSON:
116
+
117
+ .. code-block:: yaml
118
+
119
+ name: custom-package
120
+ version: '2.1.6'
121
+ some_arbitrary_data:
122
+ - thing one
123
+ - thing two
124
+ - thing: three
125
+ is_a: hash
126
+
127
+ *(later on...)*
128
+
129
+ .. code-block:: ruby
130
+
131
+ CustomPackageRecipe.lookup('some_arbitrary_data')
132
+ #=> ['thing one', 'thing two', {'thing' => 'three', 'is_a' => 'hash'}]
133
+
134
+ .. _hiera-interpolation-in-data-files:
135
+
136
+ Interpolation in Data Files
137
+ '''''''''''''''''''''''''''
138
+
139
+ Within a data file, the ``%{scope("...")}`` method interpolates values from the
140
+ following sources:
141
+
142
+ * The current recipe class
143
+ * ``FPM::Cookery::Facts``
144
+ * `Facter <https://puppetlabs.com/facter>`_ facts
145
+
146
+ The ``%{hiera("...")}`` method interpolates values looked up in the data files
147
+ themselves.
148
+
149
+ Say you are on an ``x86_64`` system, and consider the following YAML data:
150
+
151
+ .. code-block:: yaml
152
+
153
+ name: something-clever
154
+ version: '0.9.0'
155
+ source: 'https://www.sporkforge.net/archive/%{scope("arch")}/%{hiera("name")}-%{hiera("version")}.tar.gz'
156
+
157
+ ``source`` evaluates like so:
158
+
159
+ .. code-block:: ruby
160
+
161
+ SomethingCleverRecipe.lookup('source')
162
+ #=> 'https://www.sporkforge.net/archive/x86_64/something-clever-0.9.0.tar.gz'
163
+
164
+ .. _hiera-automatic-application-of-hiera-data:
165
+
166
+ Symbolized Hash Keys
167
+ ''''''''''''''''''''
168
+
169
+ Ruby's YAML library automatically converts hash keys prefixed with colons into
170
+ symbols. This is good to know when using Hiera to store data relevant to
171
+ methods that expect symbols in their arguments -- for instance, ``source``.
172
+
173
+ **BAD**:
174
+
175
+ .. code-block:: yaml
176
+
177
+ source:
178
+ - 'git://gogs.myhostname.info/labyrinthm/bowie.git'
179
+ - with: git
180
+ tag: 'v1.1.3'
181
+
182
+ **GOOD**:
183
+
184
+ .. code-block:: yaml
185
+
186
+ source:
187
+ - 'git://gogs.myhostname.info/labyrinthm/bowie.git'
188
+ - :with: git
189
+ :tag: 'v1.1.3'
190
+
191
+ Method Signatures and Unpacking Data Structures
192
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
193
+
194
+ fpm-cookery tries to Do What You Mean when dealing when loading data from
195
+ Hiera, but there are some subtleties relating to method signatures that you
196
+ should be aware of.
197
+
198
+ Methods that expect a single argument are the simplest case -- just provide a
199
+ single key-value pair:
200
+
201
+ .. code-block:: yaml
202
+
203
+ name: 'myrecipe'
204
+
205
+ Methods that expect multiple arguments should be given as a list:
206
+
207
+ .. code-block:: yaml
208
+
209
+ depends:
210
+ - openssl-devel
211
+ - docker-compose
212
+
213
+ fpm-cookery will automatically unpack the argument list with Ruby's splat
214
+ (``*``) operator when invoking the method.
215
+
216
+ Methods that expect a hash should be given as a series of key-value pairs:
217
+
218
+ .. code-block:: yaml
219
+
220
+ environment:
221
+ LC_ALL: C
222
+ SHELLOPTS: xtrace
223
+ PAGER: cat
224
+
225
+ fpm-cookery will *merge* these pairs into whatever data is already assigned as
226
+ the value of the attribute, rather than replacing it.
227
+
228
+ Some methods expect a heterogeneous list of arguments, ``source`` being the
229
+ most important of these. If you want to pass options to ``source`` or other
230
+ such methods, use the following technique:
231
+
232
+ .. code-block:: yaml
233
+
234
+ source:
235
+ - 'https://my.subversion-server.net/trunk'
236
+ - :revision: 92834
237
+ :externals: false
238
+
239
+ This translates to a Ruby ``Array``:
240
+
241
+ .. code-block:: ruby
242
+
243
+ ['https://my.subversion-server.net/trunk', {:revision => 92834, :externals => false}]
244
+
245
+ For simple sources that consist only of a URL, you can do:
246
+
247
+ .. code-block:: yaml
248
+
249
+ source: 'git://our.internal-git.com/foo/bar.git'
250
+
251
+ Automatic Application of Hiera Data
252
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
253
+
254
+ As part of the recipe initialization process, fpm-cookery calls ``lookup`` to
255
+ retrieve any Hiera-defined values corresponding to recipe attribute names such
256
+ as ``name``, ``version``, and ``source``. If Hiera can locate the key,
257
+ fpm-cookery automatically sets the relevant attribute to the retrieved value.
258
+
259
+ Attributes defined in Hiera data files take precedence over
260
+ attributes defined in ``recipe.rb``:
261
+
262
+ .. code-block:: yaml
263
+
264
+ --- # common.yaml
265
+ source: https://www.repourl.org/source/neato-0.2.4-7.tar.bz2
266
+
267
+ .. code-block:: ruby
268
+
269
+ # recipe.rb
270
+ class NeatoRecipe < FPM::Cookery::Recipe
271
+ source 'https://www.repourl.org/source/nightly/neato-nightly.tar.gz'
272
+ end
273
+
274
+ This results in:
275
+
276
+ .. code-block:: ruby
277
+
278
+ NeatoRecipe.source #=> https://www.repourl.org/source/neato-0.2.4-7.tar.bz2
279
+
280
+ Examples
281
+ --------
282
+
283
+ See the `Redis recipe
284
+ <https://github.com/bernd/fpm-cookery/tree/master/recipes/redis>`_ for an
285
+ example of fpm-cookery and Hiera in action.
@@ -18,11 +18,16 @@ 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 "rspec", "~> 3.0"
21
+ s.add_development_dependency "rspec", "~> 3.3"
22
22
  s.add_development_dependency "rake"
23
+ s.add_development_dependency "pry"
24
+ s.add_development_dependency "simplecov", "~> 0.11"
23
25
  s.add_runtime_dependency "fpm", "~> 1.1"
24
26
  s.add_runtime_dependency "facter"
25
27
  s.add_runtime_dependency "puppet", "~> 3.4"
26
28
  s.add_runtime_dependency "addressable", "~> 2.3.8"
27
29
  s.add_runtime_dependency "systemu"
30
+ s.add_runtime_dependency "json", ">= 1.7.7", "< 2.0"
31
+ s.add_runtime_dependency "json_pure", ">= 1.7.7", "< 2.0"
32
+ s.add_runtime_dependency "safe_yaml", "~> 1.0.4"
28
33
  end
@@ -1,10 +1,13 @@
1
1
  require 'singleton'
2
+ require 'fpm/cookery/path'
2
3
 
3
4
  module FPM
4
5
  module Cookery
5
6
  class Book
6
7
  include Singleton
7
8
 
9
+ attr_accessor :filename, :config
10
+
8
11
  def initialize
9
12
  @recipe = nil
10
13
  end
@@ -12,13 +15,37 @@ module FPM
12
15
  # Load the given file and instantiate an object. Wrap the class in an
13
16
  # anonymous module to avoid namespace cluttering. (see Kernel.load)
14
17
  def load_recipe(filename, config, &callback)
15
- Kernel.load(filename, true)
16
- callback.call(@recipe.new(filename, config))
18
+ @filename = FPM::Cookery::Path.new(filename).realpath
19
+ @config = config
20
+
21
+ Kernel.load(@filename.to_path, true)
22
+ callback.call(@recipe.new)
17
23
  end
18
24
 
19
25
  def add_recipe_class(klass)
20
26
  @recipe = klass
21
27
  end
28
+
29
+ # Hijack the recipe singleton to make the +filename+ and +config+ objects
30
+ # available when a descendent of BaseRecipe is declared. This makes it
31
+ # possible to do Hiera lookups at class definition time.
32
+ def inject_class_methods!(klass)
33
+ # It's necessary to close over local variables because the receiver
34
+ # changes within the scope of +define_method+, so +self.filename+ would
35
+ # wrongly refer to +singleton_klass.filename+.
36
+ filename = self.filename
37
+ config = self.config
38
+
39
+ singleton_klass = (class << klass ; self ; end)
40
+
41
+ singleton_klass.send(:define_method, :filename) do
42
+ filename
43
+ end
44
+
45
+ singleton_klass.send(:define_method, :config) do
46
+ config
47
+ end
48
+ end
22
49
  end
23
50
  end
24
51
  end