kameleon-builder 2.9.4 → 2.10.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77bd099db84f2bcda3b7a494e19055fc1d16158f8e6cb52d3be3abad4ce61fe8
4
- data.tar.gz: 9cab43b3a49e340aab7e051659c3e51e6dccdf71dffa8df18e5257dae9353ffc
3
+ metadata.gz: 40bafaeccf66d6d3149f1af122656d69ca563488fc51cb358e67a607f813d407
4
+ data.tar.gz: 93d6c6c995fa330626a823c06026e9a3733c0dc72ee1cdc7feefc1d6f0db0362
5
5
  SHA512:
6
- metadata.gz: a343c26b0723fbc92015ea796eaf1846270013cbe07344c7c27ec24e15960fd461b8bcd66adf4743cadaa3173a2bc2adba2fbccf3630126c16ecca8d1fb4d155
7
- data.tar.gz: c7b7c1392ab8d9459a8aba07b9c3580e6ea7a3c46cb2d56b9befb194784c6268c7370f04316a77864c6951c0f8011fd36176f75744d83e55856025fdf92195a4
6
+ metadata.gz: 4ff5b417aced3f8736f9d5d7dbe1f45092310667fbb352903fa9075844222d6e667e86881dca443367d1088d9dee7269d8f185c715ad9615957cda60985b7d07
7
+ data.tar.gz: e69e617c0ee0eddf3d65dc2c2cef1b878222afbd9d0c7f392d57a93f164e84dd5cd217e8c4ac6f8b7673ad7ceb8355c7c0d60c57e555ba2141ed3211a6c2ca25
data/.bumpversion.cfg CHANGED
@@ -1,7 +1,7 @@
1
1
  [bumpversion]
2
2
  commit = True
3
3
  tag = True
4
- current_version = 2.9.4
4
+ current_version = 2.10.1
5
5
  parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(\.(?P<release>[a-z]+))?
6
6
  serialize =
7
7
  {major}.{minor}.{patch}.{release}
data/CHANGES CHANGED
@@ -1,10 +1,33 @@
1
1
  Kameleon CHANGELOG
2
2
  ==================
3
3
 
4
- Version 2.9.3.dev
5
- -----------------
4
+ Version 2.10.1
5
+ -------------
6
+
7
+ Released on March 21th 2020
8
+
9
+ - Fix regression in 2.10.0 with the build directory creation
10
+
11
+ Version 2.10.0
12
+ -------------
13
+
14
+ Released on March 21th 2020
15
+
16
+ - Rework usage (cosmetic fixes)
17
+ - Drop the `kameleon template repository` action (same as `kameleon repository`)
18
+ - Make `kameleon dag` and `kameleon dryrun` standalone actions instead of `kameleon info` options
19
+ - Add the `kamelon dag --recipes-only`
20
+ - Make `kameleon dag` show distincly the extended recipe among the ancestors
21
+ - Add the `kameleon export` action
22
+
23
+ Version 2.9.4
24
+ -------------
25
+
26
+ Released on December 12th 2018
27
+
28
+ - Minor fixes
29
+ - NB: the 2.9.3 version was lost in space...
6
30
 
7
- **unreleased**
8
31
 
9
32
  Version 2.9.2
10
33
  -------------
data/lib/kameleon/cli.rb CHANGED
@@ -11,10 +11,10 @@ module Kameleon
11
11
  class Repository < Thor
12
12
  include Thor::Actions
13
13
 
14
- desc "add [NAME] [URL]", "Adds a new named <name> repository at <url>."
14
+ desc "add <NAME> <GIT_URL>", "Adds a new repository named <NAME> cloned from at <GIT_URL>."
15
15
  method_option :branch, :type => :string ,
16
16
  :default => nil,
17
- :desc => "checkout <branch>",
17
+ :desc => "checkout <BRANCH>",
18
18
  :aliases => "-b"
19
19
  def add(name, url)
20
20
  Kameleon::Repository.add(name, url, options)
@@ -25,7 +25,7 @@ module Kameleon
25
25
  Kameleon::Repository.list
26
26
  end
27
27
 
28
- desc "update [NAME]", "Updates a named <name> repository"
28
+ desc "update <NAME>", "Updates repository named <NAME> repository"
29
29
  def update(name)
30
30
  Kameleon::Repository.update(name)
31
31
  end
@@ -37,7 +37,7 @@ module Kameleon
37
37
  class Template < Thor
38
38
  include Thor::Actions
39
39
 
40
- register CLI::Repository, 'repository', 'repository', 'Manages set of remote git repositories'
40
+ # register CLI::Repository, 'repository', 'repository', 'Manages set of remote git repositories'
41
41
 
42
42
  def self.source_root
43
43
  Kameleon.env.repositories_path
@@ -50,7 +50,7 @@ module Kameleon
50
50
  Utils.list_recipes(Kameleon.env.repositories_path)
51
51
  end
52
52
 
53
- desc "import [TEMPLATE_NAME]", "Imports the given template"
53
+ desc "import <TEMPLATE_NAME>", "Imports the given template"
54
54
  method_option :global, :type => :hash ,
55
55
  :default => {}, :aliases => "-g",
56
56
  :desc => "Set custom global variables."
@@ -81,7 +81,7 @@ module Kameleon
81
81
  end
82
82
  end
83
83
 
84
- desc "info [TEMPLATE_NAME]", "Display detailed information about a template"
84
+ desc "info <TEMPLATE_NAME>", "Display detailed information about a template"
85
85
  method_option :global, :type => :hash ,
86
86
  :default => {}, :aliases => "-g",
87
87
  :desc => "Set custom global variables."
@@ -108,7 +108,7 @@ module Kameleon
108
108
  class Main < Thor
109
109
  include Thor::Actions
110
110
 
111
- register CLI::Repository, 'repository', 'repository', 'Manages set of remote git repositories'
111
+ register CLI::Repository, 'repository', 'repository', 'Manages repositories of recipes'
112
112
  # register CLI::Recipe, 'recipe', 'recipe', 'Manages the local recipes'
113
113
  register CLI::Template, 'template', 'template', 'Lists and imports templates'
114
114
 
@@ -139,7 +139,7 @@ module Kameleon
139
139
  end
140
140
  map %w(ls) => :list
141
141
 
142
- desc "new [RECIPE_PATH] [TEMPLATE_NAME]", "Creates a new recipe"
142
+ desc "new <RECIPE_PATH> <TEMPLATE_NAME>", "Creates a new recipe from template <TEMPLATE_NAME>"
143
143
  method_option :global, :type => :hash ,
144
144
  :default => {}, :aliases => "-g",
145
145
  :desc => "Set custom global variables."
@@ -190,7 +190,7 @@ module Kameleon
190
190
  end
191
191
  end
192
192
 
193
- desc "info [RECIPE_PATH]", "Display detailed information about a recipe"
193
+ desc "info <RECIPE_PATH>", "Display detailed information about a recipe"
194
194
  method_option :global, :type => :hash ,
195
195
  :default => {}, :aliases => "-g",
196
196
  :desc => "Set custom global variables."
@@ -200,9 +200,35 @@ module Kameleon
200
200
  method_option :dryrun, :type => :boolean ,
201
201
  :default => false,
202
202
  :desc => "Show the build sequence but do not actually build"
203
- method_option :dag, :type => :boolean ,
203
+ method_option :relative, :type => :boolean ,
204
204
  :default => false,
205
- :desc => "Show a DAG of the build sequence"
205
+ :desc => "Make pathnames relative to the current working directory"
206
+ def info(*recipe_paths)
207
+ if recipe_paths.empty?
208
+ if options[:from_cache].nil?
209
+ raise ArgumentError
210
+ else
211
+ unless File.file?(options[:from_cache])
212
+ raise CacheError, "The specified cache file "\
213
+ "\"#{options[:from_cache]}\" do not exists"
214
+ end
215
+ Kameleon.ui.info("Using the cached recipe")
216
+ @cache = Kameleon::Persistent_cache.instance
217
+ @cache.cache_path = options[:from_cache]
218
+ end
219
+ else
220
+ recipe_paths.each do |path|
221
+ recipe = Kameleon::Recipe.new(path)
222
+ recipe.resolve!
223
+ recipe.display_info(options[:relative])
224
+ end
225
+ end
226
+ end
227
+
228
+ desc "dag <RECIPE_PATH> [<RECIPE_PATH> [<...>]]", "Draw a DAG of the steps to build one or more recipes"
229
+ method_option :global, :type => :hash ,
230
+ :default => {}, :aliases => "-g",
231
+ :desc => "Set custom global variables."
206
232
  method_option :file, :type => :string ,
207
233
  :default => "/tmp/kameleon.dag",
208
234
  :desc => "DAG output filename"
@@ -211,52 +237,95 @@ module Kameleon
211
237
  method_option :relative, :type => :boolean ,
212
238
  :default => false,
213
239
  :desc => "Make pathnames relative to the current working directory"
214
-
215
- def info(*recipe_paths)
216
- if recipe_paths.length == 0 && !options[:from_cache].nil?
217
- unless File.file?(options[:from_cache])
218
- raise CacheError, "The specified cache file "\
219
- "\"#{options[:from_cache]}\" do not exists"
220
- end
221
- Kameleon.ui.info("Using the cached recipe")
222
- @cache = Kameleon::Persistent_cache.instance
223
- @cache.cache_path = options[:from_cache]
224
- end
225
- dag = nil
240
+ method_option :recipes_only, :type => :boolean ,
241
+ :default => false,
242
+ :desc => "Show recipes only (mostly useful to display multiple recipes inheritance)"
243
+ def dag(*recipe_paths)
244
+ raise ArgumentError if recipe_paths.empty?
226
245
  color = 0
246
+ recipes_dag = nil
227
247
  recipe_paths.each do |path|
228
248
  recipe = Kameleon::Recipe.new(path)
229
- if options[:dryrun]
230
- Kameleon::Engine.new(recipe, options).dryrun
231
- elsif options[:dag]
232
- dag = Kameleon::Engine.new(recipe, options).dag(dag, color)
233
- color += 1
249
+ recipes_dag = Kameleon::Engine.new(recipe, options.dup.merge({no_create_build_dir: true}).freeze).dag(recipes_dag, color, options[:recipes_only])
250
+ color += 1
251
+ end
252
+ format = "canon"
253
+ if options[:format]
254
+ if GraphViz::Constants::FORMATS.include?(options[:format])
255
+ format = options[:format]
234
256
  else
235
- recipe.resolve!
236
- recipe.display_info(options[:relative])
257
+ Kameleon.ui.warn("Unknown GraphViz format #{options[:format]}, fall back to #{format}")
237
258
  end
238
- end
239
- if options[:dag]
240
- format = "canon"
241
- if options[:format]
242
- if GraphViz::Constants::FORMATS.include?(options[:format])
243
- format = options[:format]
244
- else
245
- Kameleon.ui.warn("Unknown GraphViz format #{options[:format]}, fall back to #{format}")
259
+ else
260
+ options[:file].match(/^.+\.([^\.]+)$/) do |f|
261
+ if GraphViz::Constants::FORMATS.include?(f[1])
262
+ format = f[1]
246
263
  end
247
- else
248
- options[:file].match(/^.+\.([^\.]+)$/) do |f|
249
- if GraphViz::Constants::FORMATS.include?(f[1])
250
- format = f[1]
251
- end
264
+ end
265
+ end
266
+ recipes_dag.output( :"#{format}" => options[:file] )
267
+ Kameleon.ui.info("Generated GraphViz #{format} file: #{options[:file]}")
268
+ end
269
+
270
+ desc "dryrun <RECIPE_PATH>", "Show the steps the build would process"
271
+ method_option :global, :type => :hash ,
272
+ :default => {}, :aliases => "-g",
273
+ :desc => "Set custom global variables."
274
+ method_option :relative, :type => :boolean ,
275
+ :default => false,
276
+ :desc => "Make pathnames relative to the current working directory"
277
+ def dryrun(*recipe_paths)
278
+ raise ArgumentError if recipe_paths.empty?
279
+ recipe_paths.each do |path|
280
+ recipe = Kameleon::Recipe.new(path)
281
+ Kameleon::Engine.new(recipe, options.dup.merge({no_create_build_dir: true}).freeze).dryrun
282
+ end
283
+ end
284
+
285
+ desc "export <RECIPE_PATH> <EXPORT_PATH>", "Export the given recipe with its steps and data to a given directory"
286
+ method_option :global, :type => :hash ,
287
+ :default => {}, :aliases => "-g",
288
+ :desc => "Set custom global variables."
289
+ method_option :add, :type => :boolean ,
290
+ :default => false, :aliases => "-A",
291
+ :desc => "export recipe and steps to an existing directory (this may overwrite some existing files)"
292
+ def export(recipe_path,dest_path)
293
+ unless recipe_path.end_with? '.yaml'
294
+ recipe_path = recipe_path + '.yaml'
295
+ end
296
+ # Manage global as it is not passed to env by default
297
+ if options[:global]
298
+ Kameleon.env.global.merge!(options[:global])
299
+ end
300
+ recipe = Recipe.new(recipe_path)
301
+ recipe.resolve! :strict => false
302
+ recipe.all_files.uniq.each do |path|
303
+ relative_path = path.relative_path_from(Kameleon.env.workspace)
304
+ if relative_path.fnmatch("../*")
305
+ raise if Kameleon.ui.level("verbose")
306
+ raise ExportError, "Recipe '#{recipe_path}' depends on a file" \
307
+ " outside of the current directory: '#{relative_path.to_s}'"
252
308
  end
309
+ end
310
+ Kameleon.ui.info("Export recipe #{recipe_path} to directory: #{dest_path}")
311
+ if File.exists?(dest_path)
312
+ unless options[:add]
313
+ raise if Kameleon.ui.level("verbose")
314
+ raise ExportError, "Target export directory '#{dest_path}' already "\
315
+ "exists, use the --add option if you really want to export the "\
316
+ "recipe files to it (this may overwrite some existing files)"
253
317
  end
254
- dag.output( :"#{format}" => options[:file] )
255
- Kameleon.ui.info("Generated GraphViz #{format} file: #{options[:file]}")
318
+ else
319
+ FileUtils.mkdir_p(dest_path)
320
+ end
321
+ recipe.all_files.uniq.each do |path|
322
+ relative_path = path.relative_path_from(Kameleon.env.workspace)
323
+ dst = File.join(dest_path, relative_path)
324
+ copy_file(path, dst)
256
325
  end
257
326
  end
258
327
 
259
- desc "build [RECIPE_PATH]", "Builds the appliance from the given recipe"
328
+ desc "build <RECIPE_PATH>", "Builds the appliance from the given recipe"
260
329
  method_option :build_path, :type => :string ,
261
330
  :default => nil, :aliases => "-b",
262
331
  :desc => "Sets the build directory path"
@@ -75,7 +75,7 @@ module Kameleon
75
75
  if @options[:enable_cache] || @options[:from_cache] then
76
76
  @cache.recipe_files = @recipe.all_files
77
77
  end
78
- unless @options[:dryrun] or @options[:dag]
78
+ unless @options[:no_create_build_dir]
79
79
  begin
80
80
  Kameleon.ui.info("Creating kameleon build directory : #{@cwd}")
81
81
  FileUtils.mkdir_p @cwd
@@ -466,7 +466,7 @@ module Kameleon
466
466
  Kameleon.ui.shell.say ""
467
467
  end
468
468
 
469
- def dag(graph, color)
469
+ def dag(graph, color, recipes_only)
470
470
  if graph.nil?
471
471
  graph = GraphViz::new( "G" )
472
472
  end
@@ -482,47 +482,61 @@ module Kameleon
482
482
  n_recipe['colorscheme'] = colorscheme
483
483
  n_recipe['color'] = color
484
484
  (@recipe.base_recipes_files - [@recipe.path]).uniq.each do |base_recipe_path|
485
- n_base_recipe = g_recipes.add_nodes(base_recipe_path.relative_path_from(Pathname(Dir.pwd)).to_s)
486
- n_base_recipe['shape'] = 'Mdiamond'
487
- edge = graph.add_edges(n_base_recipe, n_recipe)
485
+ Kameleon.ui.debug("Dag add node #{base_recipe_path}")
486
+ n_base_recipe = g_recipes.add_nodes(base_recipe_path.relative_path_from(Pathname(Dir.pwd)).to_s)
487
+ n_base_recipe['shape'] = 'Mdiamond'
488
+ edge = graph.add_edges(n_base_recipe, n_recipe)
489
+ if base_recipe_path == @recipe.extended_recipe_file
490
+ Kameleon.ui.debug("This is the extended recipe")
491
+ edge['colorscheme'] = colorscheme
492
+ edge['color'] = color
493
+ else
488
494
  edge['style'] = 'dashed'
495
+ end
489
496
  end
490
497
  n_prev = n_recipe
491
- ["bootstrap", "setup", "export"].each do |section_name|
492
- section = @recipe.sections.fetch(section_name)
493
- g_section = graph.add_graph( "cluster S:#{ section_name }" )
494
- g_section['label'] = section_name.capitalize
495
- section.sequence do |macrostep|
496
- if macrostep.path.nil?
497
- macrostep_name = macrostep.name
498
- else
499
- macrostep_name = macrostep.path.relative_path_from(Pathname(Dir.pwd)).to_s
500
- macrostep_name.chomp!(".yaml")
501
- macrostep_name.sub!(/^steps\//, "")
502
- end
503
- g_macrostep = g_section.add_graph( "cluster M:#{ macrostep_name }")
504
- g_macrostep['label'] = macrostep_name
505
- g_macrostep['style'] = 'filled'
506
- g_macrostep['color'] = 'gray'
507
- macrostep.sequence do |microstep|
508
- n_microstep = g_macrostep.add_nodes("m:#{macrostep_name}/#{microstep.name}")
509
- n_microstep['label'] = microstep.name
510
- n_microstep['style'] = 'filled'
511
- n_microstep['color'] = 'white'
512
- edge = graph.add_edges(n_prev, n_microstep)
513
- edge['colorscheme'] = colorscheme
514
- edge['color'] = color
515
- n_prev = n_microstep
498
+ if recipes_only
499
+ Kameleon.ui.debug("As requested, only show recipes")
500
+ else
501
+ ["bootstrap", "setup", "export"].each do |section_name|
502
+ Kameleon.ui.debug("Dag add section #{section_name}")
503
+ section = @recipe.sections.fetch(section_name)
504
+ g_section = graph.add_graph( "cluster S:#{ section_name }" )
505
+ g_section['label'] = section_name.capitalize
506
+ section.sequence do |macrostep|
507
+ Kameleon.ui.debug("Dag add macrostep #{macrostep.name}")
508
+ if macrostep.path.nil?
509
+ macrostep_name = macrostep.name
510
+ else
511
+ macrostep_name = macrostep.path.relative_path_from(Pathname(Dir.pwd)).to_s
512
+ macrostep_name.chomp!(".yaml")
513
+ macrostep_name.sub!(/^steps\//, "")
514
+ end
515
+ g_macrostep = g_section.add_graph( "cluster M:#{ macrostep_name }")
516
+ g_macrostep['label'] = macrostep_name
517
+ g_macrostep['style'] = 'filled'
518
+ g_macrostep['color'] = 'gray'
519
+ macrostep.sequence do |microstep|
520
+ Kameleon.ui.debug("Dag add microstep #{microstep.name}")
521
+ n_microstep = g_macrostep.add_nodes("m:#{macrostep_name}/#{microstep.name}")
522
+ n_microstep['label'] = microstep.name
523
+ n_microstep['style'] = 'filled'
524
+ n_microstep['color'] = 'white'
525
+ edge = graph.add_edges(n_prev, n_microstep)
526
+ edge['colorscheme'] = colorscheme
527
+ edge['color'] = color
528
+ n_prev = n_microstep
529
+ end
516
530
  end
517
531
  end
532
+ n_end = graph.add_nodes('end')
533
+ n_end['label'] = 'END'
534
+ n_end['shape'] = 'Msquare'
535
+ edge = graph.add_edges(n_prev, n_end)
536
+ edge['colorscheme'] = colorscheme
537
+ edge['color'] = color
518
538
  end
519
- n_end = graph.add_nodes('end')
520
- n_end['label'] = 'END'
521
- n_end['shape'] = 'Msquare'
522
- edge = graph.add_edges(n_prev, n_end)
523
- edge['colorscheme'] = colorscheme
524
- edge['color'] = color
525
- Kameleon.ui.info "-> Drawn DAG for #{recipe_path}"
539
+ Kameleon.ui.info "-> Draw DAG for #{recipe_path}"
526
540
  return graph
527
541
  end
528
542
 
@@ -26,4 +26,5 @@ module Kameleon
26
26
  class AbortError < Error; status_code(8) ; end
27
27
  class TemplateNotFound < Error; status_code(9) ; end
28
28
  class CacheError < Error; status_code(10) ; end
29
+ class ExportError < Error; status_code(11) ; end
29
30
  end
@@ -14,6 +14,7 @@ module Kameleon
14
14
  attr_accessor :checkpoint_path
15
15
  attr_accessor :metainfo
16
16
  attr_accessor :files
17
+ attr_accessor :extended_recipe_file
17
18
  attr_accessor :base_recipes_files
18
19
  attr_accessor :data_files
19
20
  attr_accessor :env_files
@@ -97,6 +98,12 @@ module Kameleon
97
98
 
98
99
  update_steps_dirs()
99
100
 
101
+ extended_recipe_name = yaml_recipe.fetch("extend", "")
102
+ unless extended_recipe_name.nil?
103
+ extended_recipe_name << ".yaml" unless extended_recipe_name.end_with? ".yaml"
104
+ @extended_recipe_file = Pathname.new(File.expand_path(File.join(File.dirname(path), extended_recipe_name)))
105
+ end
106
+
100
107
  # Load extended recipe variables
101
108
  yaml_recipe = load_base_recipe(yaml_recipe, @path)
102
109
  yaml_recipe.delete("extend")
data/version.txt CHANGED
@@ -1 +1 @@
1
- 2.9.4
1
+ 2.10.1
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kameleon-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.9.4
4
+ version: 2.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Salem Harrache
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2018-12-12 00:00:00.000000000 Z
15
+ date: 2020-03-21 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: childprocess
@@ -223,7 +223,7 @@ requirements:
223
223
  - polipo 1.0.3, or greater
224
224
  - graphviz 2.38.0 or greater
225
225
  rubyforge_project:
226
- rubygems_version: 2.7.7
226
+ rubygems_version: 2.7.6.2
227
227
  signing_key:
228
228
  specification_version: 4
229
229
  summary: Kameleon is a tool to build virtual machines from scratch