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