kameleon-builder 2.4.0 → 2.5.0

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
  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