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 +4 -4
- data/CHANGELOG.rst +15 -0
- data/contrib/kameleon_bashrc.sh +2 -2
- data/contrib/kameleon_exec_cmd.sh +10 -4
- data/lib/kameleon/cli.rb +33 -8
- data/lib/kameleon/context.rb +17 -17
- data/lib/kameleon/engine.rb +15 -10
- data/lib/kameleon/error.rb +1 -0
- data/lib/kameleon/persistent_cache.rb +39 -13
- data/lib/kameleon/recipe.rb +70 -29
- data/lib/kameleon/shell.rb +28 -14
- data/lib/kameleon/ui.rb +9 -1
- data/lib/kameleon/utils.rb +1 -1
- data/tests/recipes/test_recipe.yaml +1 -0
- data/tests/test2/test2.yaml +2 -0
- data/version.txt +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d24c2bbdf9e6c88d1e2d4d573210b1c8414c2af8
|
4
|
+
data.tar.gz: 00379931012e6056b8cdcf89c196f60e02e3984a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
|
data/contrib/kameleon_bashrc.sh
CHANGED
@@ -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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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 "$
|
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) %> >> "$
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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"
|
data/lib/kameleon/context.rb
CHANGED
@@ -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
|
-
|
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
|
-
@
|
19
|
-
|
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.
|
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.
|
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.
|
90
|
-
Kameleon.ui.
|
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.
|
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(
|
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
|
|
data/lib/kameleon/engine.rb
CHANGED
@@ -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.
|
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
|
-
|
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.
|
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.
|
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.
|
184
|
+
Kameleon.ui.msg("--> Using checkpoint")
|
180
185
|
else
|
181
|
-
Kameleon.ui.
|
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.
|
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.
|
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
|
data/lib/kameleon/error.rb
CHANGED
@@ -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('
|
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
|
-
|
108
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
223
|
-
|
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(
|
226
|
-
recipe_file = File.join(
|
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
|
|
data/lib/kameleon/recipe.rb
CHANGED
@@ -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 :
|
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
|
-
@
|
40
|
-
Kameleon.ui.
|
40
|
+
@step_files = []
|
41
|
+
Kameleon.ui.verbose("Initialize new recipe (#{path})")
|
41
42
|
@base_recipes_files = [@path]
|
42
|
-
@
|
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.
|
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.
|
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.
|
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
|
-
@
|
151
|
-
Kameleon.ui.
|
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.
|
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.
|
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.
|
231
|
+
Kameleon.ui.verbose("Loading aliases #{path}")
|
228
232
|
@aliases.merge!(YAML.load_file(path))
|
229
|
-
@
|
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.
|
294
|
+
Kameleon.ui.verbose("Loading checkpoint configuration #{path}")
|
263
295
|
@checkpoint = YAML.load_file(path)
|
264
296
|
@checkpoint["path"] = path.to_s
|
265
|
-
@
|
297
|
+
@step_files.push(path)
|
266
298
|
break
|
267
299
|
end
|
268
300
|
end
|
269
|
-
fail RecipeError, "Checkpoint configuraiton file '#{
|
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.
|
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.
|
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.
|
363
|
-
@
|
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.
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
668
|
+
@step_files.each do |step|
|
636
669
|
prefix ; Kameleon.ui.info("#{step}")
|
637
670
|
end
|
638
671
|
Kameleon.ui.info("Data:")
|
639
|
-
@
|
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
|
data/lib/kameleon/shell.rb
CHANGED
@@ -12,13 +12,14 @@ module Kameleon
|
|
12
12
|
attr :process
|
13
13
|
attr :shell_cmd
|
14
14
|
|
15
|
-
def initialize(
|
16
|
-
@cmd = cmd.chomp
|
17
|
-
@context_name =
|
18
|
-
@local_workdir = local_workdir
|
19
|
-
@shell_workdir =
|
20
|
-
@proxy_cache = proxy_cache
|
21
|
-
@
|
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
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
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
|
data/lib/kameleon/utils.rb
CHANGED
data/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
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
|
+
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:
|
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.
|
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
|