kameleon-builder 2.4.0 → 2.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 65da9e8e38e49cbcc45af782e207462e37e18ec1
4
- data.tar.gz: 1ad935fc3207a7a26940bf46b5f43956389829ab
3
+ metadata.gz: d24c2bbdf9e6c88d1e2d4d573210b1c8414c2af8
4
+ data.tar.gz: 00379931012e6056b8cdcf89c196f60e02e3984a
5
5
  SHA512:
6
- metadata.gz: 238d2ddf1bc6b0c901837163cecdebb475a9e1ee680ce22197a43038bf49f6c27d9dcf518a0be2ac976331bf8449934bff637af82b71fae5b864cfafb504bfc4
7
- data.tar.gz: ed9e26c4420b36ae280249a067157546ae1ee9695b1691da99c041acd3728d860a73c5d7bddf226d074680b5230b489ddc4d7ac20bb0da2bfd18cbf81e3fbaeb
6
+ metadata.gz: 20f79f9f06cfc7975a4dce207b07c037ed3ceebc9e6c3571e671ba48335b8608c9abc37d9899f03ea3444227b31384e625cf8d157bde0d7eb490b3b904a80516
7
+ data.tar.gz: dec068dcdcd64c17d00a04d5378226e4036e761fd9c66d172d13859c600e63f1d3594eca6352724bb9d39c0cc15d2f77a9fa81b69ae18b073df22e8e0ede9fcd
data/CHANGELOG.rst CHANGED
@@ -1,6 +1,21 @@
1
1
  Kameleon CHANGELOG
2
2
  ==================
3
3
 
4
+ version 2.5.0
5
+ -------------
6
+
7
+ Released on Jan 27th 2015
8
+
9
+ - Allowed user to get custom shell environement by adding shell script
10
+ - Added option ``--verbose`` to allow user debugging
11
+ - Added option ``--from-cache`` to the ``kameleon info`` subcommand
12
+ - Enabled bash xtrace in verbose mode
13
+ - Checked appropriate proxy cache server start
14
+ - Fixed recipe path in proxy cache metadata
15
+ - Forced proxy cache to use IPv4
16
+ - Improved UI with more color and less output messages
17
+
18
+
4
19
  version 2.4.0
5
20
  -------------
6
21
 
@@ -145,11 +145,11 @@ function __download {
145
145
  if which wget >/dev/null; then
146
146
  wget --retry-connrefused --progress=bar:force "$1" -O "$2" 2>&1
147
147
  else
148
- fail "wget is missing, trying with curl..."
148
+ echo "wget is missing, trying with curl..."
149
149
  if which curl >/dev/null; then
150
150
  curl -# -L --retry 999 --retry-max-time 0 "$1" -o "$2" 2>&1
151
151
  else
152
- fail "curl is missing, trying with python..."
152
+ echo "curl is missing, trying with python..."
153
153
  if which python >/dev/null; then
154
154
  python -c "
155
155
  import sys
@@ -1,18 +1,24 @@
1
1
  #!/usr/bin/env bash
2
2
 
3
- ROOT_DIRECTORY=$(dirname $(readlink -f ${BASH_SOURCE[0]}))
3
+ set -o errexit
4
+ set -o pipefail
5
+
6
+ __ROOT_DIRECTORY__=$(dirname $(readlink -f ${BASH_SOURCE[0]}))
4
7
 
5
8
  function save_env {
6
9
  # Save environment
7
- (comm -3 <(declare | sort) <(declare -f | sort)) > "$ROOT_DIRECTORY/<%= File.basename(@bash_env_file) %>"
10
+ <% if Kameleon.env.debug %>set +x<% end %>
11
+ (comm -3 <(declare | sort) <(declare -f | sort)) > "${__ROOT_DIRECTORY__}/<%= File.basename(@bash_env_file) %>"
8
12
  }
9
13
 
10
14
  trap 'save_env' INT TERM EXIT
11
15
 
12
16
  # Load environment
13
- source "$ROOT_DIRECTORY/<%= File.basename(@bash_env_file) %>" 2> /dev/null || true
17
+ source "${__ROOT_DIRECTORY__}/<%= File.basename(@bash_env_file) %>" 2> /dev/null || true
14
18
 
15
19
  # Log cmd
16
- echo <%= Shellwords.escape(cmd.value) %> >> "$ROOT_DIRECTORY/<%= File.basename(@bash_history_file) %>"
20
+ echo <%= Shellwords.escape(cmd.value) %> >> "${__ROOT_DIRECTORY__}/<%= File.basename(@bash_history_file) %>"
21
+
22
+ <% if Kameleon.env.debug %>set -o xtrace <% end %>
17
23
 
18
24
  <%= cmd.value %>
data/lib/kameleon/cli.rb CHANGED
@@ -62,8 +62,7 @@ module Kameleon
62
62
  "To see all templates, run the command "\
63
63
  "`kameleon template ls`"
64
64
  else
65
- files2copy = tpl.base_recipes_files + tpl.files + tpl.data
66
- files2copy.each do |path|
65
+ tpl.all_files.each do |path|
67
66
  relative_path = path.relative_path_from(Kameleon.env.repositories_path)
68
67
  dst = File.join(Kameleon.env.workspace, relative_path)
69
68
  copy_file(path, dst)
@@ -100,8 +99,10 @@ module Kameleon
100
99
 
101
100
  class_option :color, :type => :boolean, :default => Kameleon.default_values[:color],
102
101
  :desc => "Enables colorization in output"
102
+ class_option :verbose, :type => :boolean, :default => Kameleon.default_values[:verbose],
103
+ :desc => "Enables verbose output for kameleon users"
103
104
  class_option :debug, :type => :boolean, :default => Kameleon.default_values[:debug],
104
- :desc => "Enables debug output"
105
+ :desc => "Enables debug output for kameleon developpers"
105
106
  class_option :script, :type => :boolean, :default => Kameleon.default_values[:script],
106
107
  :desc => "Never prompts for user intervention",
107
108
  :aliases => "-s"
@@ -150,8 +151,7 @@ module Kameleon
150
151
  "To see all templates, run the command "\
151
152
  "`kameleon templates`"
152
153
  else
153
- files2copy = tpl.base_recipes_files + tpl.files + tpl.data
154
- files2copy.each do |path|
154
+ tpl.all_files.each do |path|
155
155
  relative_path = path.relative_path_from(Kameleon.env.repositories_path)
156
156
  dst = File.join(Kameleon.env.workspace, relative_path)
157
157
  copy_file(path, dst)
@@ -170,11 +170,25 @@ module Kameleon
170
170
  end
171
171
  end
172
172
 
173
- desc "info [RECIPE_PATH]", "Display detailed information about a recipe"
173
+ desc "info [[RECIPE_PATH]]", "Display detailed information about a recipe"
174
174
  method_option :global, :type => :hash ,
175
175
  :default => {}, :aliases => "-g",
176
176
  :desc => "Set custom global variables."
177
- def info(recipe_path)
177
+ method_option :from_cache, :type => :string ,
178
+ :default => nil,
179
+ :desc => "Get info from a persistent cache tar file (ignore recipe path)"
180
+
181
+ def info(recipe_path=nil)
182
+ if recipe_path.nil? && !options[:from_cache].nil?
183
+ unless File.file?(options[:from_cache])
184
+ raise CacheError, "The specified cache file "\
185
+ "\"#{options[:from_cache]}\" do not exists"
186
+ end
187
+ Kameleon.ui.info("Using the cached recipe")
188
+ @cache = Kameleon::Persistent_cache.instance
189
+ @cache.cache_path = options[:from_cache]
190
+ recipe_path = @cache.get_recipe
191
+ end
178
192
  recipe = Kameleon::Recipe.new(recipe_path)
179
193
  recipe.resolve!
180
194
  recipe.display_info
@@ -211,6 +225,10 @@ module Kameleon
211
225
  :desc => "Set custom global variables."
212
226
  def build(recipe_path=nil)
213
227
  if recipe_path.nil? && !options[:from_cache].nil?
228
+ unless File.file?(options[:from_cache])
229
+ raise CacheError, "The specified cache file "\
230
+ "\"#{options[:from_cache]}\" do not exists"
231
+ end
214
232
  Kameleon.ui.info("Using the cached recipe")
215
233
  @cache = Kameleon::Persistent_cache.instance
216
234
  @cache.cache_path = options[:from_cache]
@@ -270,7 +288,14 @@ module Kameleon
270
288
  Thor::Base.shell = Thor::Shell::Basic
271
289
  end
272
290
  Kameleon.ui = Kameleon::UI::Shell.new(self.options)
273
- Kameleon.ui.level = "debug" if self.options["debug"]
291
+
292
+ if (self.options["debug"] or ENV['KAMELEON_DEBUG'])
293
+ Kameleon.ui.level = "debug"
294
+ elsif self.options["verbose"]
295
+ Kameleon.ui.level = "verbose"
296
+ end
297
+ Kameleon.ui.verbose("The level of output is set to #{Kameleon.ui.level}")
298
+
274
299
  opts = args[1]
275
300
  cmd_name = args[2][:current_command].name
276
301
  if opts.include? "--help" or opts.include? "-h"
@@ -5,8 +5,15 @@ module Kameleon
5
5
 
6
6
  attr_accessor :shell
7
7
  attr_accessor :name
8
+ attr_accessor :cmd
9
+ attr_accessor :workdir
10
+ attr_accessor :local_workdir
11
+ attr_accessor :proxy_cache
12
+ attr_accessor :env_files
8
13
 
9
- def initialize(name, cmd, workdir, exec_prefix, local_workdir, kwargs = {})
14
+
15
+ def initialize(name, cmd, workdir, exec_prefix, local_workdir, env_files,
16
+ kwargs = {})
10
17
  @name = name.downcase
11
18
  @cmd = cmd
12
19
  @workdir = workdir
@@ -15,11 +22,8 @@ module Kameleon
15
22
  @proxy_cache = kwargs[:proxy_cache]
16
23
  @fail_silently = kwargs.fetch(:fail_silently, true)
17
24
  @lazyload = kwargs.fetch(:lazyload, false)
18
- @shell = Kameleon::Shell.new(@name,
19
- @cmd,
20
- @workdir,
21
- @local_workdir,
22
- @proxy_cache)
25
+ @env_files = env_files
26
+ @shell = Kameleon::Shell.new(self)
23
27
  @already_loaded = false
24
28
  Kameleon.ui.debug("Initialize new ctx (#{name})")
25
29
 
@@ -61,22 +65,22 @@ module Kameleon
61
65
  def log_progress(log_level, msg)
62
66
  Kameleon.ui.confirm(msg, false) if log_level == "info"
63
67
  Kameleon.ui.error(msg, false) if log_level == "error"
68
+ Kameleon.ui.verbose msg if log_level == "verbose"
64
69
  Kameleon.ui.debug msg if log_level == "debug"
65
70
  end
66
71
 
67
72
  def execute(cmd, kwargs = {})
68
73
  load_shell
69
74
  cmd_with_prefix = "#{@exec_prefix} #{cmd}"
70
- cmd_with_prefix.split( /\r?\n/ ).each {|m| Kameleon.ui.debug "+ #{m}" }
71
75
  log_level = kwargs.fetch(:log_level, "info")
72
76
  exit_status = @shell.execute(cmd_with_prefix, kwargs) do |out, err|
73
77
  do_log(out, log_level) unless out.nil?
74
78
  do_log(err, "error") unless err.nil?
75
79
  end
76
- Kameleon.ui.debug("Exit status : #{exit_status}")
80
+ Kameleon.ui.verbose("Exit status : #{exit_status}")
77
81
  fail ExecError unless exit_status.eql? 0
78
82
  rescue ShellError, Errno::EPIPE => e
79
- Kameleon.ui.debug("Shell cmd failed to launch: #{@shell.shell_cmd}")
83
+ Kameleon.ui.verbose("Shell cmd failed to launch: #{@shell.shell_cmd}")
80
84
  raise ExecError, e.message + ". The '#{@name}_context' is inaccessible."
81
85
  end
82
86
 
@@ -86,8 +90,8 @@ module Kameleon
86
90
  tmp = @cache.get_cache_cmd(cmd)
87
91
  else
88
92
  tmp = Tempfile.new("pipe-#{ Kameleon::Utils.generate_slug(cmd)[0..20] }")
89
- Kameleon.ui.debug("Running piped commands")
90
- Kameleon.ui.debug("Saving STDOUT from #{@name}_ctx to local file #{tmp.path}")
93
+ Kameleon.ui.verbose("Running piped commands")
94
+ Kameleon.ui.verbose("Saving STDOUT from #{@name}_ctx to local file #{tmp.path}")
91
95
  execute(cmd, :stdout => tmp)
92
96
  tmp.close
93
97
  end
@@ -96,7 +100,7 @@ module Kameleon
96
100
  @cache.cache_cmd(cmd,tmp.path)
97
101
  end
98
102
 
99
- Kameleon.ui.debug("Forwarding #{tmp.path} to STDIN of #{other_ctx.name}_ctx")
103
+ Kameleon.ui.verbose("Forwarding #{tmp.path} to STDIN of #{other_ctx.name}_ctx")
100
104
  dest_pipe_path = "${KAMELEON_WORKDIR}/pipe-#{ Kameleon::Utils.generate_slug(other_cmd)[0..20] }"
101
105
  other_ctx.send_file(tmp.path, dest_pipe_path)
102
106
  other_cmd_with_pipe = "cat #{dest_pipe_path} | #{other_cmd} && rm #{dest_pipe_path}"
@@ -136,11 +140,7 @@ module Kameleon
136
140
  end
137
141
 
138
142
  def reload
139
- @shell = Kameleon::Shell.new(@name,
140
- @cmd,
141
- @workdir,
142
- @local_workdir,
143
- @proxy_cache)
143
+ @shell = Kameleon::Shell.new(self)
144
144
  @shell.start
145
145
  end
146
146
 
@@ -41,7 +41,7 @@ module Kameleon
41
41
  @cache.mode = @options[:enable_cache] ? :build : :from
42
42
  @cache.cache_path = @options[:from_cache]
43
43
  # I'm passing the Pathname objects
44
- @cache.recipe_files = @recipe.files + @recipe.base_recipes_files + @recipe.data
44
+ @cache.recipe_files = @recipe.all_files
45
45
  @cache.recipe_path = @recipe.path
46
46
 
47
47
  if @recipe.global["in_context"]["proxy_cache"].nil? then
@@ -71,7 +71,8 @@ module Kameleon
71
71
 
72
72
  Kameleon.ui.debug("Building local context [local]")
73
73
  @local_context = Context.new("local", "bash", @cwd, "", @cwd,
74
- :proxy_cache => "localhost",
74
+ @recipe.env_files,
75
+ :proxy_cache => "127.0.0.1",
75
76
  :lazyload => false,
76
77
  :fail_silently => false)
77
78
  Kameleon.ui.debug("Building external context [out]")
@@ -80,6 +81,7 @@ module Kameleon
80
81
  @recipe.global["out_context"]["workdir"],
81
82
  @recipe.global["out_context"]["exec_prefix"],
82
83
  @cwd,
84
+ @recipe.env_files,
83
85
  :proxy_cache => proxy_cache_out,
84
86
  :lazyload => lazyload,
85
87
  :fail_silently => fail_silently)
@@ -90,6 +92,7 @@ module Kameleon
90
92
  @recipe.global["in_context"]["workdir"],
91
93
  @recipe.global["in_context"]["exec_prefix"],
92
94
  @cwd,
95
+ @recipe.env_files,
93
96
  :proxy_cache => proxy_cache_in,
94
97
  :lazyload => lazyload,
95
98
  :fail_silently => fail_silently)
@@ -162,36 +165,38 @@ module Kameleon
162
165
  section.sequence do |macrostep|
163
166
  macrostep_time = Time.now.to_i
164
167
  if @cache then
165
- Kameleon.ui.info("Starting proxy cache server for macrostep '#{macrostep.name}'...")
168
+ Kameleon.ui.debug("Starting proxy cache server for macrostep '#{macrostep.name}'...")
166
169
  # the following function start a polipo web proxy and stops a previous run
167
170
  dir_cache = @cache.create_cache_directory(macrostep.name)
168
- @cache.start_web_proxy_in(dir_cache)
171
+ unless @cache.start_web_proxy_in(dir_cache)
172
+ raise CacheError, "The cache process fail to start"
173
+ end
169
174
  end
170
175
  macrostep.sequence do |microstep|
171
176
  step_prefix = "Step #{ microstep.order } : "
172
177
  Kameleon.ui.info("#{step_prefix}#{ microstep.slug }")
173
178
  if @enable_checkpoint
174
179
  if microstep.on_checkpoint == "skip"
175
- Kameleon.ui.info("--> Skipped")
180
+ Kameleon.ui.msg("--> Skipped")
176
181
  next
177
182
  end
178
183
  if microstep.in_cache && microstep.on_checkpoint == "use_cache"
179
- Kameleon.ui.info("--> Using checkpoint")
184
+ Kameleon.ui.msg("--> Using checkpoint")
180
185
  else
181
- Kameleon.ui.info("--> Running the step...")
186
+ Kameleon.ui.msg("--> Running the step...")
182
187
  microstep.commands.each do |cmd|
183
188
  safe_exec_cmd(cmd)
184
189
  end
185
190
  unless microstep.on_checkpoint == "redo"
186
191
  if checkpoint_enabled?
187
- Kameleon.ui.info("--> Creating checkpoint : #{ microstep.identifier }")
192
+ Kameleon.ui.msg("--> Creating checkpoint : #{ microstep.identifier }")
188
193
  create_checkpoint(microstep.identifier)
189
194
  end
190
195
  end
191
196
  end
192
197
  else
193
198
  begin
194
- Kameleon.ui.info("--> Running the step...")
199
+ Kameleon.ui.msg("--> Running the step...")
195
200
  microstep.commands.each do |cmd|
196
201
  safe_exec_cmd(cmd)
197
202
  end
@@ -200,8 +205,8 @@ module Kameleon
200
205
  breakpoint(nil)
201
206
  end
202
207
  end
203
- Kameleon.ui.info("Step #{macrostep.name} took: #{Time.now.to_i-macrostep_time} secs")
204
208
  end
209
+ Kameleon.ui.info("Step #{macrostep.name} took: #{Time.now.to_i-macrostep_time} secs")
205
210
  end
206
211
  @cleaned_sections.push(section.name)
207
212
  end
@@ -23,4 +23,5 @@ module Kameleon
23
23
  class BuildError < Error; status_code(7) ; end
24
24
  class AbortError < Error; status_code(8) ; end
25
25
  class TemplateNotFound < Error; status_code(9) ; end
26
+ class CacheError < Error; status_code(10) ; end
26
27
  end
@@ -1,6 +1,7 @@
1
1
  require 'childprocess'
2
2
  require 'singleton'
3
3
  require 'socket'
4
+ require 'net/http'
4
5
 
5
6
  module Kameleon
6
7
  #This ruby class will control the execution of Polipo web proxy
@@ -17,7 +18,7 @@ module Kameleon
17
18
  attr_writer :cache_path
18
19
  attr_accessor :mode
19
20
  attr_accessor :name
20
- attr_accessor :recipe_files # have to check those.
21
+ attr_accessor :recipe_files # FIXME have to check those.
21
22
  attr_accessor :recipe_path
22
23
 
23
24
  def initialize()
@@ -63,7 +64,7 @@ module Kameleon
63
64
  ports.each do |p|
64
65
  begin
65
66
  port = p
66
- tmp = TCPServer.new('localhost', port)
67
+ tmp = TCPServer.new('127.0.0.1', port)
67
68
  rescue
68
69
  port =0
69
70
  end
@@ -99,13 +100,27 @@ module Kameleon
99
100
  directory_name
100
101
  end
101
102
 
103
+ def proxy_is_running?()
104
+ begin
105
+ res = Net::HTTP.get_response(URI("http://127.0.0.1:#{@polipo_port}/polipo/status"))
106
+ if not res.body.include? "is on line"
107
+ Kameleon.ui.debug("The proxy is running but not responding. Server response: #{res.inspect}")
108
+ else
109
+ Kameleon.ui.debug("The proxy is responding")
110
+ return true
111
+ end
112
+ return false
113
+ rescue Exception => e
114
+ Kameleon.ui.debug("The proxy is not responding. Server response: #{e.message}")
115
+ return false
116
+ end
117
+ end
118
+
102
119
  def start_web_proxy_in(directory)
103
- sleep 2 # this is for assuring that the cache is correctly created
104
- ## setting current step dir
105
- @current_step_dir = directory
106
120
  ## This function assumes that the cache directory has already been created by the engine
107
- ## Stopping first the previous proxy
108
- ## have to check if polipo is running
121
+
122
+ # setting current step dir
123
+ @current_step_dir = directory
109
124
  Kameleon.ui.debug("Starting web proxy Polipo in directory #{directory} using port: #{@polipo_port}")
110
125
  @polipo_process.stop(0) unless @polipo_process.nil?
111
126
  command = ["#{@polipo_path}/polipo", "-c", "/dev/null"]
@@ -115,7 +130,12 @@ module Kameleon
115
130
  Kameleon.ui.debug("Starting process '#{command}'")
116
131
  @polipo_process = ChildProcess.build(*command)
117
132
  @polipo_process.start
118
- return true
133
+ timeout = 0
134
+ while ( not(proxy_is_running?) and timeout < 5 )
135
+ sleep 1
136
+ timeout = timeout + 1
137
+ end
138
+ return (@polipo_process.alive? and proxy_is_running?)
119
139
  end
120
140
 
121
141
 
@@ -182,7 +202,12 @@ module Kameleon
182
202
  Kameleon.ui.info("Caching recipe")
183
203
 
184
204
  File.open("#{cache_metadata_dir}/header",'w+') do |f|
185
- f.puts({:recipe_path => @recipe_path.basename.to_s}.to_yaml)
205
+ if recipe_dir.nil?
206
+ recipe_path = @recipe_path.basename
207
+ else
208
+ recipe_path = @recipe_path.relative_path_from(recipe_dir)
209
+ end
210
+ f.puts({:recipe_path => recipe_path.to_s}.to_yaml)
186
211
  f.puts({:date => Time.now.to_i}.to_yaml)
187
212
  end
188
213
 
@@ -219,11 +244,12 @@ module Kameleon
219
244
  end
220
245
 
221
246
  def get_recipe()
222
- cached_recipe=Dir.mktmpdir("cache")
223
- execute("tar","-xf #{@cache_path} -C #{cached_recipe} ./recipe ./metadata")
247
+ extract_path = File.join(Kameleon.env.build_path, File.basename(@cache_path, ".*"))
248
+ FileUtils.mkdir_p extract_path
249
+ execute("tar","-xf #{@cache_path} -C #{extract_path} ./recipe ./metadata")
224
250
  Kameleon.ui.info("Getting cached recipe")
225
- recipe_header = YAML::load(File.read(File.join(cached_recipe,"metadata","header")))
226
- recipe_file = File.join(cached_recipe,"recipe",recipe_header[:recipe_path])
251
+ recipe_header = YAML::load(File.read(File.join(extract_path,"metadata","header")))
252
+ recipe_file = File.join(extract_path,"recipe",recipe_header[:recipe_path])
227
253
  return recipe_file
228
254
  end
229
255
 
@@ -15,7 +15,8 @@ module Kameleon
15
15
  attr_accessor :metainfo
16
16
  attr_accessor :files
17
17
  attr_accessor :base_recipes_files
18
- attr_accessor :data
18
+ attr_accessor :data_files
19
+ attr_accessor :env_files
19
20
 
20
21
  def initialize(path, kwargs = {})
21
22
  @path = Pathname.new(File.expand_path(path))
@@ -36,10 +37,11 @@ module Kameleon
36
37
  }
37
38
  @aliases = {}
38
39
  @checkpoint = nil
39
- @files = []
40
- Kameleon.ui.debug("Initialize new recipe (#{path})")
40
+ @step_files = []
41
+ Kameleon.ui.verbose("Initialize new recipe (#{path})")
41
42
  @base_recipes_files = [@path]
42
- @data = []
43
+ @data_files = []
44
+ @env_files = []
43
45
  @steps_dirs = []
44
46
  load! :strict => false
45
47
  end
@@ -67,7 +69,7 @@ module Kameleon
67
69
 
68
70
  def load!(kwargs = {})
69
71
  # Find recipe path
70
- Kameleon.ui.debug("Loading #{@path}")
72
+ Kameleon.ui.verbose("Loading #{@path}")
71
73
  fail RecipeError, "Could not find this following recipe : #{@path}" \
72
74
  unless File.file? @path
73
75
  yaml_recipe = YAML.load_file @path
@@ -92,6 +94,8 @@ module Kameleon
92
94
  resolved_global = @global.merge YAML.load(resolved_global)
93
95
  # Loads aliases
94
96
  load_aliases(yaml_recipe)
97
+ # Load env files
98
+ load_env_files(yaml_recipe)
95
99
  # Loads checkpoint configuration
96
100
  load_checkpoint_config(yaml_recipe)
97
101
 
@@ -134,7 +138,7 @@ module Kameleon
134
138
  end
135
139
  end
136
140
  if embedded_step
137
- Kameleon.ui.debug("Loading embedded macrostep #{name}")
141
+ Kameleon.ui.verbose("Loading embedded macrostep #{name}")
138
142
  macrostep = load_macrostep(nil, name, args, kwargs)
139
143
  section.macrosteps.push(macrostep)
140
144
  next
@@ -144,16 +148,16 @@ module Kameleon
144
148
  dir_to_search.each do |dir|
145
149
  macrostep_path = Pathname.new(File.join(dir, name + '.yaml'))
146
150
  if File.file?(macrostep_path)
147
- Kameleon.ui.debug("Loading macrostep #{macrostep_path}")
151
+ Kameleon.ui.verbose("Loading macrostep #{macrostep_path}")
148
152
  macrostep = load_macrostep(macrostep_path, name, args, kwargs)
149
153
  section.macrosteps.push(macrostep)
150
- @files.push(macrostep_path)
151
- Kameleon.ui.debug("Macrostep '#{name}' found in this path: " \
154
+ @step_files.push(macrostep_path)
155
+ Kameleon.ui.verbose("Macrostep '#{name}' found in this path: " \
152
156
  "#{macrostep_path}")
153
157
  loaded = true
154
158
  break
155
159
  else
156
- Kameleon.ui.debug("Macrostep '#{name}' not found in this path: " \
160
+ Kameleon.ui.verbose("Macrostep '#{name}' not found in this path: " \
157
161
  "#{macrostep_path}")
158
162
  end
159
163
  end
@@ -161,7 +165,7 @@ module Kameleon
161
165
  end
162
166
  end
163
167
  end
164
- Kameleon.ui.debug("Loading recipe metadata")
168
+ Kameleon.ui.verbose("Loading recipe metadata")
165
169
  @metainfo = {
166
170
  "description" => Utils.extract_meta_var("description", @recipe_content)
167
171
  }
@@ -191,7 +195,7 @@ module Kameleon
191
195
  end
192
196
  end
193
197
  yaml_recipe.keys.each do |key|
194
- if ["aliases", "checkpoint"].include? key
198
+ if ["aliases", "checkpoint", "env"].include? key
195
199
  base_yaml_recipe[key] = yaml_recipe[key]
196
200
  elsif ["export", "bootstrap", "setup"].include? key
197
201
  base_section = base_yaml_recipe.fetch(key, [])
@@ -224,13 +228,13 @@ module Kameleon
224
228
  dir_search.each do |dir_path|
225
229
  path = Pathname.new(File.join(dir_path, aliases_file))
226
230
  if File.file?(path)
227
- Kameleon.ui.debug("Loading aliases #{path}")
231
+ Kameleon.ui.verbose("Loading aliases #{path}")
228
232
  @aliases.merge!(YAML.load_file(path))
229
- @files.push(path)
233
+ @step_files.push(path)
230
234
  return path
231
235
  end
232
236
  end
233
- fail RecipeError, "Aliases file for recipe '#{path}' does not exists"
237
+ fail RecipeError, "Aliases file for recipe '#{@path}' does not exists"
234
238
  end
235
239
  if yaml_recipe.keys.include? "aliases"
236
240
  aliases = yaml_recipe.fetch("aliases")
@@ -246,6 +250,34 @@ module Kameleon
246
250
  end
247
251
  end
248
252
 
253
+ def load_env_files(yaml_recipe)
254
+ def add_env_file(env_file)
255
+ dir_search = @steps_dirs.map do |steps_dir|
256
+ File.join(steps_dir, "env")
257
+ end.flatten
258
+ dir_search.each do |dir_path|
259
+ path = Pathname.new(File.join(dir_path, env_file))
260
+ if File.file?(path)
261
+ Kameleon.ui.verbose("Adding env file #{path}")
262
+ @env_files.push(path)
263
+ return path
264
+ end
265
+ end
266
+ fail RecipeError, "The env file script '#{env_file}' does not exists "\
267
+ "in any of these directories: #{dir_search}"
268
+ end
269
+ if yaml_recipe.keys.include? "env"
270
+ env_content = yaml_recipe.fetch("env")
271
+ if env_content.kind_of? String
272
+ add_env_file(env_content)
273
+ elsif env_content.kind_of? Array
274
+ env_content.each do |env_file|
275
+ add_env_file(env_file)
276
+ end
277
+ end
278
+ end
279
+ end
280
+
249
281
  def load_checkpoint_config(yaml_recipe)
250
282
  if yaml_recipe.keys.include? "checkpoint"
251
283
  checkpoint = yaml_recipe.fetch("checkpoint")
@@ -259,14 +291,14 @@ module Kameleon
259
291
  dir_search.each do |dir_path|
260
292
  path = Pathname.new(File.join(dir_path, checkpoint))
261
293
  if File.file?(path)
262
- Kameleon.ui.debug("Loading checkpoint configuration #{path}")
294
+ Kameleon.ui.verbose("Loading checkpoint configuration #{path}")
263
295
  @checkpoint = YAML.load_file(path)
264
296
  @checkpoint["path"] = path.to_s
265
- @files.push(path)
297
+ @step_files.push(path)
266
298
  break
267
299
  end
268
300
  end
269
- fail RecipeError, "Checkpoint configuraiton file '#{path}' " \
301
+ fail RecipeError, "Checkpoint configuraiton file '#{checkpoint}' " \
270
302
  "does not exists" if @checkpoint.nil?
271
303
  end
272
304
  (@checkpoint.keys - ["path"]).each do |key|
@@ -342,7 +374,7 @@ module Kameleon
342
374
  end
343
375
 
344
376
  def find_microstep(microstep_name, loaded_microsteps)
345
- Kameleon.ui.debug("Looking for microstep #{microstep_name}")
377
+ Kameleon.ui.verbose("Looking for microstep #{microstep_name}")
346
378
  loaded_microsteps.each do |microstep|
347
379
  if microstep_name.eql? microstep.name
348
380
  return microstep
@@ -352,18 +384,18 @@ module Kameleon
352
384
  end
353
385
 
354
386
  def resolve_data_path(partial_path, step_path)
355
- Kameleon.ui.debug("Looking for data '#{partial_path}'")
387
+ Kameleon.ui.verbose("Looking for data '#{partial_path}'")
356
388
  dir_search = @steps_dirs.map do |steps_dir|
357
389
  File.join(steps_dir, "data")
358
390
  end.flatten
359
391
  dir_search.each do |dir_path|
360
392
  real_path = Pathname.new(File.join(dir_path, partial_path)).cleanpath
361
393
  if real_path.exist?
362
- Kameleon.ui.debug("Register data #{real_path}")
363
- @data.push(real_path) unless @data.include? real_path
394
+ Kameleon.ui.verbose("Register data #{real_path}")
395
+ @data_files.push(real_path) unless @data_files.include? real_path
364
396
  return real_path
365
397
  end
366
- Kameleon.ui.debug("#{real_path} : nonexistent")
398
+ Kameleon.ui.verbose("#{real_path} : nonexistent")
367
399
  end
368
400
  fail RecipeError, "Cannot found data '#{partial_path}' unsed in '#{step_path}'"
369
401
  end
@@ -591,7 +623,7 @@ module Kameleon
591
623
 
592
624
  def flatten_data
593
625
  files = []
594
- @data.each do |d|
626
+ @data_files.each do |d|
595
627
  if d.directory?
596
628
  Find.find("#{d}") do |f|
597
629
  files.push(Pathname.new(f)) unless File.directory? f
@@ -600,7 +632,7 @@ module Kameleon
600
632
  files.push(d)
601
633
  end
602
634
  end
603
- @data = files.uniq
635
+ @data_files = files.uniq
604
636
  end
605
637
 
606
638
 
@@ -608,11 +640,12 @@ module Kameleon
608
640
  recipe_hash = {
609
641
  "name" => @name,
610
642
  "path" => @path.to_s,
611
- "files" => @files.map {|p| p.to_s },
612
643
  "base_recipes_files" => @base_recipes_files.map {|p| p.to_s },
644
+ "step_files" => @step_files.map {|p| p.to_s },
645
+ "env_files" => @env_files.map {|p| p.to_s },
646
+ "data_files" => @data_files.map {|p| p.to_s },
613
647
  "global" => @global,
614
648
  "aliases" => @aliases,
615
- "data" => @data,
616
649
  }
617
650
  recipe_hash["checkpoint"] = @checkpoint unless @checkpoint.nil?
618
651
  recipe_hash["steps"] = to_array
@@ -632,11 +665,15 @@ module Kameleon
632
665
  prefix ; Kameleon.ui.info("#{base_recipe_file}")
633
666
  end
634
667
  Kameleon.ui.info("Steps:")
635
- @files.each do |step|
668
+ @step_files.each do |step|
636
669
  prefix ; Kameleon.ui.info("#{step}")
637
670
  end
638
671
  Kameleon.ui.info("Data:")
639
- @data.each do |d|
672
+ @data_files.each do |d|
673
+ prefix ; Kameleon.ui.info("#{d}")
674
+ end
675
+ Kameleon.ui.info("Environment scripts:")
676
+ @env_files.each do |d|
640
677
  prefix ; Kameleon.ui.info("#{d}")
641
678
  end
642
679
  Kameleon.ui.info("Variables:")
@@ -653,6 +690,10 @@ module Kameleon
653
690
  return array
654
691
  end
655
692
 
693
+ def all_files
694
+ return @base_recipes_files + @step_files + @data_files + @env_files
695
+ end
696
+
656
697
  end
657
698
 
658
699
  class RecipeTemplate < Recipe
@@ -12,13 +12,14 @@ module Kameleon
12
12
  attr :process
13
13
  attr :shell_cmd
14
14
 
15
- def initialize(context_name, cmd, shell_workdir, local_workdir, proxy_cache)
16
- @cmd = cmd.chomp
17
- @context_name = context_name
18
- @local_workdir = local_workdir
19
- @shell_workdir = shell_workdir
20
- @proxy_cache = proxy_cache
21
- @bash_scripts_dir = File.join(".scripts", @context_name)
15
+ def initialize(context)
16
+ @cmd = context.cmd.chomp
17
+ @context_name = context.name
18
+ @local_workdir = context.local_workdir
19
+ @shell_workdir = context.workdir
20
+ @proxy_cache = context.proxy_cache
21
+ @env_files = context.env_files
22
+ @bash_scripts_dir = File.join("kameleon_scripts", @context_name)
22
23
  @bashrc_file = File.join(@bash_scripts_dir, "bash_rc")
23
24
  @bash_history_file = File.join(@bash_scripts_dir, "bash_history")
24
25
  @bash_env_file = File.join(@bash_scripts_dir, "bash_env")
@@ -113,12 +114,12 @@ module Kameleon
113
114
  end
114
115
  # Inject sigint handler
115
116
  bashrc_content << <<-SCRIPT
116
- function save_state_handler {
117
- echo "Saved ENV in #{@bash_env_file} file"
118
- (comm -3 <(declare | sort) <(declare -f | sort)) > #{@bash_env_file}
119
- }
120
- trap save_state_handler EXIT
121
- SCRIPT
117
+ function save_state_handler {
118
+ echo "Saved ENV in #{@bash_env_file} file"
119
+ (comm -3 <(declare | sort) <(declare -f | sort)) > #{@bash_env_file}
120
+ }
121
+ trap save_state_handler EXIT
122
+ SCRIPT
122
123
  bashrc = Shellwords.escape(bashrc_content)
123
124
  if @shell_workdir
124
125
  unless @shell_workdir.eql? "/"
@@ -133,8 +134,21 @@ module Kameleon
133
134
  unless change_dir_cmd.nil?
134
135
  shell_cmd << "echo #{change_dir_cmd} >> #{@bashrc_file}\n"
135
136
  end
136
- shell_cmd << "source #{@bashrc_file}\n"
137
137
  shell_cmd << "export KAMELEON_WORKDIR=$PWD\n"
138
+ @env_files.each do |env_file|
139
+ env_content = <<-SCRIPT
140
+ #====================================================
141
+ # Begin content of user script '#{env_file.basename}'
142
+ #====================================================
143
+ #{File.read(env_file)}
144
+ #====================================================
145
+ # End content of user script '#{env_file.basename}'
146
+ #====================================================
147
+ SCRIPT
148
+ env_escaped_content = Shellwords.escape(env_content)
149
+ shell_cmd << "echo #{env_escaped_content} >> #{@bashrc_file}\n"
150
+ end
151
+ shell_cmd << "source #{@bashrc_file}\n"
138
152
  shell_cmd << "(comm -3 <(declare | sort) <(declare -f | sort)) > #{@bash_env_file}\n"
139
153
  shell_cmd
140
154
  end
data/lib/kameleon/ui.rb CHANGED
@@ -43,7 +43,7 @@ module Kameleon
43
43
  end
44
44
 
45
45
  class Shell
46
- LEVELS = %w(silent error warn confirm info debug)
46
+ LEVELS = %w(silent error warn confirm info verbose debug)
47
47
 
48
48
  attr_accessor :shell
49
49
 
@@ -56,6 +56,10 @@ module Kameleon
56
56
  tell_me(msg, nil, newline) if level("info")
57
57
  end
58
58
 
59
+ def msg(msg, newline = nil)
60
+ tell_me(msg, :blue, newline) if level("info")
61
+ end
62
+
59
63
  def confirm(msg, newline = nil)
60
64
  tell_me(msg, :green, newline) if level("confirm")
61
65
  end
@@ -68,6 +72,10 @@ module Kameleon
68
72
  tell_me(msg, :red, newline) if level("error")
69
73
  end
70
74
 
75
+ def verbose(msg, newline = nil)
76
+ tell_me("[info] #{msg}", nil, newline) if level("verbose")
77
+ end
78
+
71
79
  def debug(msg, newline = nil)
72
80
  tell_me("[debug] #{msg}", nil, newline) if level("debug")
73
81
  end
@@ -48,7 +48,7 @@ module Kameleon
48
48
  value.gsub!(/\s*[^A-Za-z0-9\.]\s*/, '_')
49
49
  value.gsub!(/_+/, "_")
50
50
  value.gsub!(/\A[_\.]+|[_\.]+\z/, "")
51
- value.chomp("_")
51
+ value.chomp("_").downcase
52
52
  end
53
53
 
54
54
  def self.extract_meta_var(name, content)
@@ -7,6 +7,7 @@
7
7
  #===============================================================================
8
8
  ---
9
9
  # Loads some helpful aliases
10
+ extend: ../test2/test2.yaml
10
11
  aliases: defaults.yaml
11
12
  checkpoint: test.yaml
12
13
  #== Global variables use by Kameleon engine and the steps
@@ -0,0 +1,2 @@
1
+ global:
2
+ toto: tata
data/version.txt CHANGED
@@ -1 +1 @@
1
- 2.4.0
1
+ 2.5.0
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.4.0
4
+ version: 2.5.0
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: 2014-12-23 00:00:00.000000000 Z
15
+ date: 2015-01-27 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: childprocess
@@ -154,6 +154,7 @@ files:
154
154
  - tests/recipes/steps/export/save_appliance.yaml
155
155
  - tests/recipes/steps/setup/linux/software_install.yaml
156
156
  - tests/recipes/test_recipe.yaml
157
+ - tests/test2/test2.yaml
157
158
  - tests/test_context.rb
158
159
  - tests/test_recipe.rb
159
160
  - tests/test_version.rb
@@ -179,7 +180,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
180
  requirements:
180
181
  - polipo 1.0.3, or greater
181
182
  rubyforge_project:
182
- rubygems_version: 2.2.2
183
+ rubygems_version: 2.4.5
183
184
  signing_key:
184
185
  specification_version: 4
185
186
  summary: Kameleon is a tool to build virtual machines from scratch
@@ -192,6 +193,7 @@ test_files:
192
193
  - tests/recipes/steps/export/save_appliance.yaml
193
194
  - tests/recipes/steps/setup/linux/software_install.yaml
194
195
  - tests/recipes/test_recipe.yaml
196
+ - tests/test2/test2.yaml
195
197
  - tests/test_context.rb
196
198
  - tests/test_recipe.rb
197
199
  - tests/test_version.rb