kameleon-builder 2.10.1 → 2.10.5

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
  SHA256:
3
- metadata.gz: 40bafaeccf66d6d3149f1af122656d69ca563488fc51cb358e67a607f813d407
4
- data.tar.gz: 93d6c6c995fa330626a823c06026e9a3733c0dc72ee1cdc7feefc1d6f0db0362
3
+ metadata.gz: aeb30622025baa485ebc09845773b1e39db3b701494c01e6a3ac32b94d9f4faa
4
+ data.tar.gz: ea307b68b21479e3f930ffdd53536d9616332037524efca18b25804cb02e616b
5
5
  SHA512:
6
- metadata.gz: 4ff5b417aced3f8736f9d5d7dbe1f45092310667fbb352903fa9075844222d6e667e86881dca443367d1088d9dee7269d8f185c715ad9615957cda60985b7d07
7
- data.tar.gz: e69e617c0ee0eddf3d65dc2c2cef1b878222afbd9d0c7f392d57a93f164e84dd5cd217e8c4ac6f8b7673ad7ceb8355c7c0d60c57e555ba2141ed3211a6c2ca25
6
+ metadata.gz: 4cd740a9d6156e3e6c0ab480e103b8cf4b2d4cb67634c599c2a3fa4f99553d8b067bd00eee821b49a66cec4816450c59cf021298117f413f07b1796e2c0c682e
7
+ data.tar.gz: ea1d8fa490900e1263c9603008df2b174422f6026ae5d8b31b21d71ad56daf4330bc18ade35a9488c12ab3665b468604d1b56baa944553fc95299596107f44a5
data/.bumpversion.cfg CHANGED
@@ -1,13 +1,13 @@
1
1
  [bumpversion]
2
2
  commit = True
3
3
  tag = True
4
- current_version = 2.10.1
4
+ current_version = 2.10.5
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}
8
8
  {major}.{minor}.{patch}
9
9
 
10
- [bumpversion:file:version.txt]
10
+ [bumpversion:file:lib/kameleon/version.rb]
11
11
 
12
12
  [bumpversion:part:release]
13
13
  optional_value = gamma
data/CHANGES CHANGED
@@ -1,6 +1,45 @@
1
1
  Kameleon CHANGELOG
2
2
  ==================
3
3
 
4
+ Version 2.10.5
5
+ --------------
6
+
7
+ Released on July 29th 2021
8
+
9
+ - Remove polipo from the software dependencies as it is not maintained anymore. This breaks the caching feature.
10
+ - Some changes to allow a debian packaging.
11
+ - Update authors.
12
+ - Change the version information file and update scripts accordingly.
13
+
14
+ Version 2.10.4
15
+ --------------
16
+
17
+ Released on May 11th 2020
18
+
19
+ - Fix support for extend ERB
20
+ - Add the `kameleon template erb` command
21
+ - Fix bash completion
22
+ - Cosmetic code fixes
23
+
24
+ Version 2.10.3
25
+ --------------
26
+
27
+ Released on April 10th 2020
28
+
29
+ - Rework kameleon template list: add color add progress bar
30
+ - Make bash completion understand the subcommands
31
+ - Fix the command help -> `kameleon <command> -h`
32
+ - Add support for custom extend erb templates
33
+
34
+ Version 2.10.2
35
+ --------------
36
+
37
+ Released on April 09th 2020
38
+
39
+ - Fix cli help for the repository and template sub-commands
40
+ - Add the git remote url and branch to kameleon repo list
41
+ - Add the 'kameleon repository remove' command
42
+
4
43
  Version 2.10.1
5
44
  -------------
6
45
 
data/bin/kameleon CHANGED
@@ -17,7 +17,7 @@ begin
17
17
  Kameleon.init_userconf
18
18
  Kameleon::Main.start
19
19
  rescue Exception => e
20
- Kameleon.ui.error("Error : #{e}")
20
+ Kameleon.ui.error("Error: #{e}")
21
21
  if Kameleon.env.debug
22
22
  raise e
23
23
  else
@@ -2,12 +2,23 @@
2
2
 
3
3
  _kameleon() {
4
4
  COMPREPLY=()
5
- local word="${COMP_WORDS[COMP_CWORD]}"
6
-
7
- if [ "$COMP_CWORD" -eq 1 ]; then
8
- local commands="$(compgen -W "$(kameleon commands)" -- "$word")"
5
+ local i=1
6
+ while [ $i -le "$COMP_CWORD" -a "${COMP_WORDS[$i]:0:1}" == "-" ]; do
7
+ ((i++))
8
+ done
9
+ if [ "$COMP_CWORD" -eq $i ]; then
10
+ local commands="$(compgen -W "$(kameleon commands)" -- "${COMP_WORDS[$i]}")"
9
11
  COMPREPLY=( $commands $projects )
10
12
  fi
13
+ while [ $i -le "$COMP_CWORD" -a "${COMP_WORDS[$i]:0:1}" == "-" ]; do
14
+ ((i++))
15
+ done
16
+ if [ "$COMP_CWORD" -eq $((i+1)) ] && kameleon commands | grep -q "${COMP_WORDS[$i]}" ; then
17
+ if kameleon help | grep -qe "^ kameleon ${COMP_WORDS[$i]}[a-z]* <SUBCOMMAND>"; then
18
+ local commands="$(compgen -W "$(kameleon ${COMP_WORDS[$i]} commands)" -- "${COMP_WORDS[$((i+1))]}")"
19
+ COMPREPLY=( $commands $projects )
20
+ fi
21
+ fi
11
22
  }
12
23
 
13
24
  complete -o default -F _kameleon kameleon
@@ -0,0 +1,24 @@
1
+ #==============================================================================
2
+ # vim: softtabstop=2 shiftwidth=2 expandtab fenc=utf-8 cc=81 tw=80
3
+ #==============================================================================
4
+ #
5
+ # DESCRIPTION: <MY RECIPE DESCRIPTION>
6
+ #
7
+ #==============================================================================
8
+ # This recipe extends another. To look at the step involed, run:
9
+ # kameleon dryrun <%= recipe_name %>
10
+ # To see the variables that you can override, use the following command:
11
+ # kameleon info <%= recipe_name %>
12
+ ---
13
+ extend: <%= tpl.relative_path_from_recipe(recipe_path) %>
14
+
15
+ global:
16
+
17
+ bootstrap:
18
+ - "@base"
19
+
20
+ setup:
21
+ - "@base"
22
+
23
+ export:
24
+ - "@base"
@@ -1,5 +1,6 @@
1
1
  ---
2
2
  repositories_path: <%= Kameleon.default_values[:repositories_path] %>
3
+ extend_yaml_erb: <%= Kameleon.default_values[:extend_yaml_erb] %>
3
4
  script: <%= Kameleon.default_values[:script] %>
4
5
  color: <%= Kameleon.default_values[:color] %>
5
6
  debug: <%= Kameleon.default_values[:debug] %>
@@ -12,13 +12,13 @@ Gem::Specification.new do |s|
12
12
  'Cristan Ruiz',
13
13
  'Pierre Neyron',
14
14
  'Bruno Bzeznik']
15
- s.email = ['salem.harrache@inria.fr',
16
- 'michael.mercier@inria.fr',
17
- 'cristian.ruiz@imag.fr',
15
+ s.email = ['salem@harrache.info',
16
+ 'michael.mercier@libr.fr',
17
+ 'camilo1729@gmail.com',
18
18
  'pierre.neyron@imag.fr',
19
19
  'bruno.bzeznik@imag.fr']
20
20
  s.description = %q{The mindful appliance builder}
21
- s.summary = %q{Kameleon is a tool to build virtual machines from scratch}
21
+ s.summary = %q{Kameleon is a tool to build system appliances from scratch}
22
22
  s.homepage = 'http://kameleon.imag.fr/'
23
23
  s.license = 'GPL-2.0'
24
24
 
@@ -33,6 +33,7 @@ Gem::Specification.new do |s|
33
33
  s.add_dependency 'table_print', '~> 1.5'
34
34
  s.add_dependency 'psych', '~> 2.0'
35
35
  s.add_dependency 'ruby-graphviz', '~> 1.2'
36
+ s.add_dependency 'progressbar', '~> 1'
36
37
 
37
38
  s.requirements = ['polipo 1.0.3, or greater', 'graphviz 2.38.0 or greater']
38
39
  end
data/lib/kameleon.rb CHANGED
@@ -30,7 +30,12 @@ module Kameleon
30
30
  end
31
31
 
32
32
  def erb_dirpath
33
- File.join(Kameleon.source_root, 'erb')
33
+ d = File.join(Kameleon.source_root, 'erb')
34
+ if File::directory?(d)
35
+ return d
36
+ elsif File::directory?(d = '/usr/share/kameleon/erb')
37
+ return d
38
+ end
34
39
  end
35
40
 
36
41
  def userdir
@@ -46,7 +51,7 @@ module Kameleon
46
51
  def init_userconf()
47
52
  if not File.exists?(Kameleon.userconf_path) or File.zero?(Kameleon.userconf_path)
48
53
  File.open(Kameleon.userconf_path, 'w+') do |file|
49
- userconf_erb = File.join(Kameleon.erb_dirpath, "userconf.erb")
54
+ userconf_erb = File.join(Kameleon.erb_dirpath, "userconf.yaml.erb")
50
55
  erb = ERB.new(File.open(userconf_erb, 'rb') { |f| f.read })
51
56
  result = erb.result(binding)
52
57
  file.write(result)
@@ -73,7 +78,8 @@ module Kameleon
73
78
  :debug => userconf.fetch("debug", false),
74
79
  :script => userconf.fetch("script", false),
75
80
  :repositories_path => userconf.fetch("repositories_path",
76
- File.join(userdir.to_s, 'repos')),
81
+ File.join(userdir.to_s, 'repos')),
82
+ :extend_yaml_erb => userconf.fetch("extend_yaml_erb", ".extend.yaml.erb")
77
83
  }
78
84
  end
79
85
 
data/lib/kameleon/cli.rb CHANGED
@@ -11,8 +11,8 @@ module Kameleon
11
11
  class Repository < Thor
12
12
  include Thor::Actions
13
13
 
14
- desc "add <NAME> <GIT_URL>", "Adds a new repository named <NAME> cloned from at <GIT_URL>."
15
- method_option :branch, :type => :string ,
14
+ desc "add <NAME> <GIT_URL>", "Adds a new repository named <NAME> cloned from <GIT_URL>."
15
+ method_option :branch, :type => :string,
16
16
  :default => nil,
17
17
  :desc => "checkout <BRANCH>",
18
18
  :aliases => "-b"
@@ -21,37 +21,53 @@ module Kameleon
21
21
  end
22
22
 
23
23
  desc "list", "Lists available repositories."
24
+ method_option :git, :type => :boolean,
25
+ :default => true,
26
+ :desc => "show the git repository and branch each repository comes from"
24
27
  def list
25
- Kameleon::Repository.list
28
+ Kameleon::Repository.list(options)
26
29
  end
27
30
 
28
- desc "update <NAME>", "Updates repository named <NAME> repository"
31
+ desc "update <NAME>", "Updates repository named <NAME> from git"
29
32
  def update(name)
30
33
  Kameleon::Repository.update(name)
31
34
  end
32
- map %w(-h --help) => :help
35
+
36
+ desc "remove <NAME>", "Remove repository named <NAME>"
37
+ def remove(name)
38
+ Kameleon::Repository.remove(name)
39
+ end
40
+
41
+ desc "commands", "Lists all available commands", :hide => true
42
+ def commands
43
+ puts Repository.all_commands.keys - ["commands"]
44
+ end
45
+
33
46
  map %w(ls) => :list
47
+ map %w(rm) => :remove
48
+ map %w(completions) => :commands
34
49
  end
35
50
 
36
51
 
37
52
  class Template < Thor
38
53
  include Thor::Actions
39
54
 
40
- # register CLI::Repository, 'repository', 'repository', 'Manages set of remote git repositories'
41
-
42
55
  def self.source_root
43
56
  Kameleon.env.repositories_path
44
57
  end
45
58
 
46
59
  desc "list", "Lists all available templates"
60
+ method_option :progress, :type => :boolean, :default => true,
61
+ :desc => "Show progress bar while resolving templates",
62
+ :aliases => "-p"
47
63
  def list
48
- Kameleon.ui.info "The following templates are available in " \
49
- "#{ Kameleon.env.repositories_path }:"
50
- Utils.list_recipes(Kameleon.env.repositories_path)
64
+ Kameleon.ui.shell.say "Recipe templates available in: ", :red, false
65
+ Kameleon.ui.shell.say Kameleon.env.repositories_path.to_s, :yellow
66
+ Utils.list_recipes(Kameleon.env.repositories_path, options[:progress], true)
51
67
  end
52
68
 
53
69
  desc "import <TEMPLATE_NAME>", "Imports the given template"
54
- method_option :global, :type => :hash ,
70
+ method_option :global, :type => :hash,
55
71
  :default => {}, :aliases => "-g",
56
72
  :desc => "Set custom global variables."
57
73
  def import(template_name)
@@ -82,7 +98,7 @@ module Kameleon
82
98
  end
83
99
 
84
100
  desc "info <TEMPLATE_NAME>", "Display detailed information about a template"
85
- method_option :global, :type => :hash ,
101
+ method_option :global, :type => :hash,
86
102
  :default => {}, :aliases => "-g",
87
103
  :desc => "Set custom global variables."
88
104
  def info(template_name)
@@ -99,8 +115,27 @@ module Kameleon
99
115
  tpl.resolve! :strict => false
100
116
  tpl.display_info(false)
101
117
  end
102
- map %w(-h --help) => :help
118
+
119
+ desc "erb <PATH>", "Create a extend recipe ERB file"
120
+ def erb(path)
121
+ if File.directory?(path)
122
+ erb_file = Pathname.new(path).join(Kameleon.default_values[:extend_yaml_erb])
123
+ elsif File.file?(path) and path.end_with?(".yaml")
124
+ erb_file = Pathname.new(path.gsub(%r{^(.+?/)?([^/]+?)(\.yaml)?$},'\1.\2') + Kameleon.default_values[:extend_yaml_erb])
125
+ else
126
+ fail KameleonError, "Invalid path '#{path}', please give a path to a yaml file or a directory"
127
+ end
128
+ Kameleon.ui.verbose("Create extend recipe ERB '#{erb_file}'")
129
+ copy_file(Pathname.new(Kameleon.erb_dirpath).join("extend.yaml.erb"), erb_file)
130
+ end
131
+
132
+ desc "commands", "Lists all available commands", :hide => true
133
+ def commands
134
+ puts Template.all_commands.keys - ["commands"]
135
+ end
136
+
103
137
  map %w(ls) => :list
138
+ map %w(completions) => :commands
104
139
  end
105
140
  end
106
141
 
@@ -108,9 +143,10 @@ module Kameleon
108
143
  class Main < Thor
109
144
  include Thor::Actions
110
145
 
111
- register CLI::Repository, 'repository', 'repository', 'Manages repositories of recipes'
112
- # register CLI::Recipe, 'recipe', 'recipe', 'Manages the local recipes'
113
- register CLI::Template, 'template', 'template', 'Lists and imports templates'
146
+ desc 'repository <SUBCOMMAND>', 'Manages repositories of recipes'
147
+ subcommand 'repository', CLI::Repository
148
+ desc 'template <SUBCOMMAND>', 'Lists and imports templates'
149
+ subcommand 'template', CLI::Template
114
150
 
115
151
  class_option :color, :type => :boolean, :default => Kameleon.default_values[:color],
116
152
  :desc => "Enables colorization in output"
@@ -121,26 +157,27 @@ module Kameleon
121
157
  class_option :script, :type => :boolean, :default => Kameleon.default_values[:script],
122
158
  :desc => "Never prompts for user intervention",
123
159
  :aliases => "-s"
124
- map %w(-h --help) => :help
125
160
 
126
161
  desc "version", "Prints the Kameleon's version information"
127
162
  def version
128
163
  puts "Kameleon version #{Kameleon::VERSION}"
129
164
  end
130
- map %w(-v --version) => :version
131
165
 
132
166
  def self.source_root
133
167
  Kameleon.env.repositories_path
134
168
  end
135
169
 
136
170
  desc "list", "Lists all defined recipes in the current directory"
171
+ method_option :progress, :type => :boolean, :default => false,
172
+ :desc => "Show progress bar while resolving templates",
173
+ :aliases => "-p"
137
174
  def list
138
- Utils.list_recipes(Kameleon.env.workspace)
175
+ Kameleon.ui.shell.say "Workspace recipes:", :red
176
+ Utils.list_recipes(Kameleon.env.workspace, options[:progress])
139
177
  end
140
- map %w(ls) => :list
141
178
 
142
179
  desc "new <RECIPE_PATH> <TEMPLATE_NAME>", "Creates a new recipe from template <TEMPLATE_NAME>"
143
- method_option :global, :type => :hash ,
180
+ method_option :global, :type => :hash,
144
181
  :default => {}, :aliases => "-g",
145
182
  :desc => "Set custom global variables."
146
183
  def new(recipe_name, template_name)
@@ -180,9 +217,19 @@ module Kameleon
180
217
  recipe_temp = File.join(tmp_dir, File.basename(recipe_path))
181
218
  ## copying recipe
182
219
  File.open(recipe_temp, 'w+') do |file|
183
- extend_erb_tpl = File.join(Kameleon.erb_dirpath, "extend.erb")
184
- erb = ERB.new(File.open(extend_erb_tpl, 'rb') { |f| f.read })
185
- result = erb.result(binding)
220
+ message="Try and use extend recipe ERB: "
221
+ extend_yaml_erb_list = Pathname.new(template_name).dirname.ascend.to_a.map do |p|
222
+ Kameleon.env.repositories_path.join(p, Kameleon.default_values[:extend_yaml_erb])
223
+ end
224
+ extend_yaml_erb_list.unshift(Kameleon.env.repositories_path.join(template_name.gsub(%r{^(.+?/)?([^/]+?)(\.yaml)?$},'\1.\2') + Kameleon.default_values[:extend_yaml_erb]))
225
+ extend_yaml_erb_list.push(Pathname.new(Kameleon.erb_dirpath).join("extend.yaml.erb"))
226
+ extend_yaml_erb = extend_yaml_erb_list.find do |f|
227
+ Kameleon.ui.verbose(message + f.to_s)
228
+ message = "-> Not found, fallback: "
229
+ File.readable?(f)
230
+ end
231
+ Kameleon.ui.debug("Open ERB file: '#{extend_yaml_erb}'")
232
+ result = ERB.new(File.open(extend_yaml_erb, 'rb') { |f| f.read }).result(binding)
186
233
  file.write(result)
187
234
  end
188
235
  copy_file(recipe_temp, recipe_path)
@@ -191,16 +238,13 @@ module Kameleon
191
238
  end
192
239
 
193
240
  desc "info <RECIPE_PATH>", "Display detailed information about a recipe"
194
- method_option :global, :type => :hash ,
241
+ method_option :global, :type => :hash,
195
242
  :default => {}, :aliases => "-g",
196
243
  :desc => "Set custom global variables."
197
- method_option :from_cache, :type => :string ,
244
+ method_option :from_cache, :type => :string,
198
245
  :default => nil,
199
246
  :desc => "Get info from a persistent cache tar file (ignore recipe path)"
200
- method_option :dryrun, :type => :boolean ,
201
- :default => false,
202
- :desc => "Show the build sequence but do not actually build"
203
- method_option :relative, :type => :boolean ,
247
+ method_option :relative, :type => :boolean,
204
248
  :default => false,
205
249
  :desc => "Make pathnames relative to the current working directory"
206
250
  def info(*recipe_paths)
@@ -226,18 +270,18 @@ module Kameleon
226
270
  end
227
271
 
228
272
  desc "dag <RECIPE_PATH> [<RECIPE_PATH> [<...>]]", "Draw a DAG of the steps to build one or more recipes"
229
- method_option :global, :type => :hash ,
273
+ method_option :global, :type => :hash,
230
274
  :default => {}, :aliases => "-g",
231
275
  :desc => "Set custom global variables."
232
- method_option :file, :type => :string ,
276
+ method_option :file, :type => :string,
233
277
  :default => "/tmp/kameleon.dag",
234
278
  :desc => "DAG output filename"
235
- method_option :format, :type => :string ,
279
+ method_option :format, :type => :string,
236
280
  :desc => "DAG GraphViz format"
237
- method_option :relative, :type => :boolean ,
281
+ method_option :relative, :type => :boolean,
238
282
  :default => false,
239
283
  :desc => "Make pathnames relative to the current working directory"
240
- method_option :recipes_only, :type => :boolean ,
284
+ method_option :recipes_only, :type => :boolean,
241
285
  :default => false,
242
286
  :desc => "Show recipes only (mostly useful to display multiple recipes inheritance)"
243
287
  def dag(*recipe_paths)
@@ -268,10 +312,10 @@ module Kameleon
268
312
  end
269
313
 
270
314
  desc "dryrun <RECIPE_PATH>", "Show the steps the build would process"
271
- method_option :global, :type => :hash ,
315
+ method_option :global, :type => :hash,
272
316
  :default => {}, :aliases => "-g",
273
317
  :desc => "Set custom global variables."
274
- method_option :relative, :type => :boolean ,
318
+ method_option :relative, :type => :boolean,
275
319
  :default => false,
276
320
  :desc => "Make pathnames relative to the current working directory"
277
321
  def dryrun(*recipe_paths)
@@ -283,10 +327,10 @@ module Kameleon
283
327
  end
284
328
 
285
329
  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 ,
330
+ method_option :global, :type => :hash,
287
331
  :default => {}, :aliases => "-g",
288
332
  :desc => "Set custom global variables."
289
- method_option :add, :type => :boolean ,
333
+ method_option :add, :type => :boolean,
290
334
  :default => false, :aliases => "-A",
291
335
  :desc => "export recipe and steps to an existing directory (this may overwrite some existing files)"
292
336
  def export(recipe_path,dest_path)
@@ -326,36 +370,36 @@ module Kameleon
326
370
  end
327
371
 
328
372
  desc "build <RECIPE_PATH>", "Builds the appliance from the given recipe"
329
- method_option :build_path, :type => :string ,
373
+ method_option :build_path, :type => :string,
330
374
  :default => nil, :aliases => "-b",
331
375
  :desc => "Sets the build directory path"
332
- method_option :clean, :type => :boolean ,
376
+ method_option :clean, :type => :boolean,
333
377
  :default => false,
334
378
  :desc => "Runs the command `kameleon clean` first"
335
- method_option :from_checkpoint, :type => :string ,
379
+ method_option :from_checkpoint, :type => :string,
336
380
  :default => nil,
337
381
  :desc => "Uses specific checkpoint to build the image. " \
338
382
  "Default value is the last checkpoint."
339
- method_option :enable_checkpoint, :type => :boolean ,
383
+ method_option :enable_checkpoint, :type => :boolean,
340
384
  :default => false,
341
385
  :desc => "Enables checkpoint [experimental]"
342
- method_option :list_checkpoints, :type => :boolean , :aliases => "--checkpoints",
386
+ method_option :list_checkpoints, :type => :boolean, :aliases => "--checkpoints",
343
387
  :default => false,
344
388
  :desc => "Lists all availables checkpoints"
345
389
  method_option :enable_cache, :type => :boolean,
346
390
  :default => false,
347
391
  :desc => "Generates a persistent cache for the appliance."
348
- method_option :cache_path, :type => :string ,
392
+ method_option :cache_path, :type => :string,
349
393
  :default => nil,
350
394
  :desc => "Sets the cache directory path"
351
- method_option :from_cache, :type => :string ,
395
+ method_option :from_cache, :type => :string,
352
396
  :default => nil,
353
397
  :desc => "Uses a persistent cache tar file to build the image."
354
- method_option :cache_archive_compression, :type => :string ,
398
+ method_option :cache_archive_compression, :type => :string,
355
399
  :enum => ["none", "gzip", "bz2", "xz"],
356
400
  :default => "gzip",
357
401
  :desc => "Set the persistent cache tar file compression."
358
- method_option :polipo_path, :type => :string ,
402
+ method_option :polipo_path, :type => :string,
359
403
  :default => nil,
360
404
  :desc => "Full path of the polipo binary to use for the persistent cache."
361
405
  method_option :proxy, :type => :string, :default => "",
@@ -365,7 +409,7 @@ module Kameleon
365
409
  :desc => "Specifies the username and password if the parent "\
366
410
  "proxy requires authorisation it should have the "\
367
411
  "form 'username:password'"
368
- method_option :proxy_offline, :type => :boolean ,
412
+ method_option :proxy_offline, :type => :boolean,
369
413
  :default => false, :aliases => "--offline",
370
414
  :desc => "Prevents Polipo from contacting remote servers"
371
415
  method_option :global, :type => :hash,
@@ -407,8 +451,16 @@ module Kameleon
407
451
  end
408
452
 
409
453
  desc "commands", "Lists all available commands", :hide => true
410
- def commands
411
- puts Main.all_commands.keys - ["commands", "completions"]
454
+ def commands(context="main")
455
+ Kameleon.ui.debug("Commands for '#{context}':")
456
+ case context
457
+ when "main"
458
+ puts Main.all_commands.keys - ["commands"]
459
+ when "repository"
460
+ invoke CLI::Repository, "commands", [], []
461
+ when "template"
462
+ invoke CLI::Template, "commands", [], []
463
+ end
412
464
  end
413
465
 
414
466
  desc "source_root", "Prints the kameleon directory path", :hide => true
@@ -416,6 +468,10 @@ module Kameleon
416
468
  puts Kameleon.source_root
417
469
  end
418
470
 
471
+ map %w(-v --version) => :version
472
+ map %w(ls) => :list
473
+ map %w(completions) => :commands
474
+
419
475
  def initialize(*args)
420
476
  super
421
477
  self.options ||= {}
@@ -431,16 +487,19 @@ module Kameleon
431
487
  Kameleon.ui.level = "verbose"
432
488
  end
433
489
  Kameleon.ui.verbose("The level of output is set to #{Kameleon.ui.level}")
434
-
435
- opts = args[1]
436
- cmd_name = args[2][:current_command].name
437
- if opts.include? "--help" or opts.include? "-h"
438
- Main.command_help(Kameleon.ui.shell, cmd_name)
439
- raise Kameleon::Exit
440
- end
441
490
  end
442
491
 
443
- def self.start(*)
492
+ def self.start(*args)
493
+ # `kameleon build -h` does not work without the following, except for subcommands...
494
+ # Ref: https://stackoverflow.com/a/49044225/6431461
495
+ if (Thor::HELP_MAPPINGS & ARGV).any? and subcommands.grep(/^#{ARGV[0]}/).empty?
496
+ Kameleon.ui.debug("Apply workaround to handle the help command in #{ARGV}")
497
+ Thor::HELP_MAPPINGS.each do |cmd|
498
+ if match = ARGV.delete(cmd)
499
+ ARGV.unshift match
500
+ end
501
+ end
502
+ end
444
503
  super
445
504
  rescue Exception => e
446
505
  Kameleon.ui = Kameleon::UI::Shell.new
@@ -27,4 +27,5 @@ module Kameleon
27
27
  class TemplateNotFound < Error; status_code(9) ; end
28
28
  class CacheError < Error; status_code(10) ; end
29
29
  class ExportError < Error; status_code(11) ; end
30
+ class RepositoryError < Error; status_code(12) ; end
30
31
  end
@@ -93,7 +93,7 @@ module Kameleon
93
93
  unless File.file? @path
94
94
  yaml_recipe = YAML.load_file @path
95
95
  unless yaml_recipe.kind_of? Hash
96
- fail RecipeError, "Invalid yaml error : #{@path}"
96
+ fail RecipeError, "Invalid yaml: #{@path}"
97
97
  end
98
98
 
99
99
  update_steps_dirs()
@@ -242,7 +242,7 @@ module Kameleon
242
242
  unless File.file? path
243
243
  base_yaml_recipe = YAML.load_file base_recipe_path
244
244
  unless yaml_recipe.kind_of? Hash
245
- fail RecipeError, "Invalid yaml error : #{base_yaml_recipe}"
245
+ fail RecipeError, "Invalid yaml: #{base_yaml_recipe}"
246
246
  end
247
247
  base_yaml_recipe.keys.each do |key|
248
248
  if ["export", "bootstrap", "setup"].include? key
@@ -28,6 +28,7 @@ module Kameleon
28
28
  def self.update(name)
29
29
  check_git_binary
30
30
  git_repo = File.join(Kameleon.env.repositories_path, name)
31
+ raise RepositoryError, "Repository not found '#{name}'" if not File.directory?(git_repo)
31
32
  cmd = ["git", "--git-dir", File.join(git_repo, ".git"), "--work-tree",
32
33
  git_repo, "pull", "--verbose"]
33
34
  process = ChildProcess.build(*cmd)
@@ -37,10 +38,49 @@ module Kameleon
37
38
  process.stop
38
39
  end
39
40
 
40
- def self.list
41
+ def self.list(kwargs = {})
41
42
  Dir["#{Kameleon.env.repositories_path}/*"].each do |repo_path|
42
- Kameleon.ui.info File.basename("#{repo_path}")
43
+ if kwargs[:git]
44
+ show_git_repository(repo_path)
45
+ else
46
+ Kameleon.ui.info File.basename(repo_path)
47
+ end
43
48
  end
44
49
  end
50
+
51
+ def self.remove(name)
52
+ repo_path = File.join(Kameleon.env.repositories_path, name)
53
+ raise RepositoryError, "Repository not found '#{name}'" if not File.directory?(repo_path)
54
+ Kameleon.ui.shell.say "Removing: ", :red, false
55
+ show_git_repository(repo_path)
56
+ FileUtils.rm_rf(repo_path)
57
+ end
58
+
59
+ def self.show_git_repository(repo_path)
60
+ cmd = ["git", "remote", "-v"]
61
+ r, w = IO.pipe
62
+ process = ChildProcess.build(*cmd)
63
+ process.io.stdout = w
64
+ process.cwd = repo_path
65
+ process.start
66
+ w.close
67
+ url = r.readline.split[1]
68
+ process.wait
69
+ process.stop
70
+ cmd = ["git", "rev-parse", "--abbrev-ref", "HEAD"]
71
+ r, w = IO.pipe
72
+ process = ChildProcess.build(*cmd)
73
+ process.io.stdout = w
74
+ process.cwd = repo_path
75
+ process.start
76
+ w.close
77
+ branch = r.readline.chomp
78
+ process.wait
79
+ process.stop
80
+ Kameleon.ui.shell.say "#{File.basename("#{repo_path}")}", nil, false
81
+ Kameleon.ui.shell.say " <-", :magenta, false
82
+ Kameleon.ui.shell.say " #{url}", :cyan, false
83
+ Kameleon.ui.shell.say " (#{branch})", :yellow
84
+ end
45
85
  end
46
86
  end
@@ -25,12 +25,17 @@ module Kameleon
25
25
  @bash_history_file = File.join(@bash_scripts_dir, "bash_history")
26
26
  @bash_env_file = File.join(@bash_scripts_dir, "bash_env")
27
27
  @bash_status_file = File.join(@bash_scripts_dir, "bash_status")
28
- @default_bashrc_file = File.join(Kameleon.source_root, "contrib", "kameleon_bashrc.sh")
29
- @cmd_tpl = ERB.new(File.read(File.join(Kameleon.source_root,
30
- "contrib",
28
+ if File::directory?(f = File.join(Kameleon.source_root, "contrib"))
29
+ @contrib_dir = f
30
+ elsif File::directory?(f = '/usr/share/kameleon/contrib')
31
+ @contrib_dir = f
32
+ else
33
+ raise "Could not find contrib dir"
34
+ end
35
+ @default_bashrc_file = File.join(@contrib_dir, 'kameleon_bashrc.sh')
36
+ @cmd_tpl = ERB.new(File.read(File.join(@contrib_dir,
31
37
  "kameleon_exec_cmd.sh")))
32
- @cmd_wrapper_tpl = ERB.new(File.read(File.join(Kameleon.source_root,
33
- "contrib",
38
+ @cmd_wrapper_tpl = ERB.new(File.read(File.join(@contrib_dir,
34
39
  "kameleon_exec_cmd_wrapper.sh")))
35
40
 
36
41
  if @shell_workdir
@@ -1,3 +1,5 @@
1
+ require 'progressbar'
2
+
1
3
  module Kameleon
2
4
  module Utils
3
5
 
@@ -123,33 +125,63 @@ module Kameleon
123
125
  end
124
126
  end
125
127
 
126
- def self.list_recipes(repository_path, kwargs = {})
127
- Kameleon.env.root_dir = repository_path
128
+ def self.list_recipes(recipes_path, do_progressbar = false, is_repository = false, kwargs = {})
129
+ Kameleon.env.root_dir = recipes_path
128
130
  catch_exception = kwargs.fetch(:catch_exception, true)
129
131
  recipes_hash = []
130
- recipes_files = get_recipes(repository_path)
132
+ recipes_files = get_recipes(recipes_path)
133
+ if recipes_files.empty?
134
+ Kameleon.ui.shell.say " <None>", :cyan
135
+ return
136
+ end
137
+ if do_progressbar
138
+ progressbar = ProgressBar.create(:format => '%t (%p%%) %bᗧ%i',
139
+ :title => 'Resolving ' + if is_repository; 'templates' else 'recipes' end,
140
+ :progress_mark => '.',
141
+ :remainder_mark => '・',
142
+ :total => recipes_files.size + 10,
143
+ :starting_at => 10)
144
+ end
131
145
  recipes_files.each do |f|
132
146
  path = f.to_s
133
147
  begin
134
148
  recipe = RecipeTemplate.new(path)
135
- name = path.gsub(repository_path.to_s + '/', '').chomp('.yaml')
149
+ name = path.gsub(recipes_path.to_s + '/', '').chomp('.yaml')
136
150
  recipes_hash.push({
137
151
  "name" => name,
138
152
  "description" => recipe.metainfo['description'],
139
153
  })
154
+ progressbar.increment if do_progressbar
140
155
  rescue => e
141
156
  raise e if Kameleon.env.debug or not catch_exception
142
157
  end
143
158
  end
144
159
  unless recipes_hash.empty?
145
- recipes_hash = recipes_hash.sort_by{ |k| k["name"] }
146
160
  name_width = recipes_hash.map { |k| k['name'].size }.max
147
161
  desc_width = Kameleon.ui.shell.terminal_width - name_width - 3
148
162
  desc_width = (80 - name_width - 3) if desc_width < 0
149
163
  end
150
- tp(recipes_hash,
151
- {"name" => {:width => name_width}},
152
- { "description" => {:width => desc_width}})
164
+ repo_str_old = nil
165
+ recipes_hash.sort_by{ |k| k["name"] }.each do |r|
166
+ if is_repository
167
+ repo_str,recipe_dir_str,recipe_str = r["name"].match(%r{^([^/]+/)(.+/)?([^/]+)$}).to_a[1..3].map{|m| m.to_s}
168
+ else
169
+ repo_str,recipe_dir_str,recipe_str = r["name"].match(%r{^()(.+/)?([^/]+)$}).to_a[1..3].map{|m| m.to_s}
170
+ end
171
+ if not repo_str_old.nil? and repo_str_old != repo_str
172
+ Kameleon.ui.shell.say "#{'-' * name_width} | #{'-' * desc_width}"
173
+ end
174
+ repo_str_old = repo_str
175
+ Kameleon.ui.debug("#{r["name"]} -> repo=#{repo_str}, recipe_dir=#{recipe_dir_str}, recipee=#{recipe_str}")
176
+ Kameleon.ui.shell.say "#{repo_str}", :yellow, false
177
+ Kameleon.ui.shell.say "#{recipe_dir_str}", :cyan, false
178
+ Kameleon.ui.shell.say sprintf("%-#{name_width - repo_str.length - recipe_dir_str.length}s", recipe_str), :magenta, false
179
+ Kameleon.ui.shell.say " | ", nil, false
180
+ if r["description"].to_s.length > desc_width - 4
181
+ r["description"] = r["description"][0..(desc_width - 4)] + "..."
182
+ end
183
+ Kameleon.ui.shell.say sprintf("%-#{desc_width}s", r["description"]), :blue
184
+ end
153
185
  end
154
186
 
155
187
  def self.get_recipes(path)
@@ -1,4 +1,3 @@
1
1
  module Kameleon
2
- VERSION = File.read(
3
- File.expand_path("../../../version.txt", __FILE__)).chomp
2
+ VERSION = '2.10.5'
4
3
  end
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.10.1
4
+ version: 2.10.5
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: 2020-03-21 00:00:00.000000000 Z
15
+ date: 2021-07-29 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: childprocess
@@ -96,11 +96,25 @@ dependencies:
96
96
  - - "~>"
97
97
  - !ruby/object:Gem::Version
98
98
  version: '1.2'
99
+ - !ruby/object:Gem::Dependency
100
+ name: progressbar
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - "~>"
104
+ - !ruby/object:Gem::Version
105
+ version: '1'
106
+ type: :runtime
107
+ prerelease: false
108
+ version_requirements: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - "~>"
111
+ - !ruby/object:Gem::Version
112
+ version: '1'
99
113
  description: The mindful appliance builder
100
114
  email:
101
- - salem.harrache@inria.fr
102
- - michael.mercier@inria.fr
103
- - cristian.ruiz@imag.fr
115
+ - salem@harrache.info
116
+ - michael.mercier@libr.fr
117
+ - camilo1729@gmail.com
104
118
  - pierre.neyron@imag.fr
105
119
  - bruno.bzeznik@imag.fr
106
120
  executables:
@@ -157,8 +171,8 @@ files:
157
171
  - contrib/steps/setup/root_ssh_config.yaml
158
172
  - contrib/steps/setup/set_user_password.yaml
159
173
  - contrib/steps/setup/system_optimization.yaml
160
- - erb/extend.erb
161
- - erb/userconf.erb
174
+ - erb/extend.yaml.erb
175
+ - erb/userconf.yaml.erb
162
176
  - kameleon-builder.gemspec
163
177
  - lib/kameleon.rb
164
178
  - lib/kameleon/cli.rb
@@ -200,7 +214,6 @@ files:
200
214
  - tests/test_context.rb
201
215
  - tests/test_recipe.rb
202
216
  - tests/test_version.rb
203
- - version.txt
204
217
  homepage: http://kameleon.imag.fr/
205
218
  licenses:
206
219
  - GPL-2.0
@@ -226,7 +239,7 @@ rubyforge_project:
226
239
  rubygems_version: 2.7.6.2
227
240
  signing_key:
228
241
  specification_version: 4
229
- summary: Kameleon is a tool to build virtual machines from scratch
242
+ summary: Kameleon is a tool to build system appliances from scratch
230
243
  test_files:
231
244
  - tests/helper.rb
232
245
  - tests/issue76/fail.stdout
data/erb/extend.erb DELETED
@@ -1,33 +0,0 @@
1
- #==============================================================================
2
- # vim: softtabstop=2 shiftwidth=2 expandtab fenc=utf-8 cc=81 tw=80
3
- #==============================================================================
4
- #
5
- # DESCRIPTION: <MY RECIPE DESCRIPTION>
6
- #
7
- #==============================================================================
8
- ---
9
- extend: <%= tpl.relative_path_from_recipe(recipe_path) %>
10
-
11
- global:
12
- # This is the backend you have imported to switch to an other backend BCKD do:
13
- #
14
- # kameleon template import <%= tpl.relative_path_from_recipe(recipe_path) %> --global backend:BCKB
15
- #
16
- # Then, uncomment and update the following variable.
17
- <% if Kameleon.env.global["backend"] %>
18
- backend: <%= Kameleon.env.global["backend"] %>
19
- <% else %>
20
- # backend: qemu
21
- <% end %>
22
- # To see the variables that you can override, use the following command:
23
- #
24
- # kameleon info <%= recipe_name %>
25
-
26
- bootstrap:
27
- - "@base"
28
-
29
- setup:
30
- - "@base"
31
-
32
- export:
33
- - "@base"
data/version.txt DELETED
@@ -1 +0,0 @@
1
- 2.10.1