kameleon-builder 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (157) hide show
  1. data/.editorconfig +0 -0
  2. data/.env +63 -15
  3. data/.gitignore +1 -0
  4. data/README.rst +4 -2
  5. data/Vagrantfile +13 -52
  6. data/bin/kameleon +5 -0
  7. data/completion/_kameleon.zsh +18 -0
  8. data/completion/kameleon.bash +13 -0
  9. data/completion/kameleon.fish +10 -0
  10. data/contrib/polipo_env.sh +2 -0
  11. data/contrib/steps/export/save_as_g5k.yaml +63 -0
  12. data/contrib/steps/setup/add_to_sudoers.yaml +5 -0
  13. data/docs/Makefile +10 -6
  14. data/docs/README.md +17 -0
  15. data/docs/source/_static/kameleon-logo.png +0 -0
  16. data/docs/source/_static/kameleon-logo.xcf +0 -0
  17. data/docs/source/_static/kameleon-long.png +0 -0
  18. data/docs/source/aliases.rst +4 -2
  19. data/docs/source/checkpoint.rst +2 -0
  20. data/docs/source/commands.rst +4 -3
  21. data/docs/source/conf.py +15 -7
  22. data/docs/source/context.rst +7 -4
  23. data/docs/source/faq.rst +39 -1
  24. data/docs/source/getting_started.rst +227 -1
  25. data/docs/source/grid5000_tutorial.rst +110 -0
  26. data/docs/source/index.rst +7 -2
  27. data/docs/source/installation.rst +12 -4
  28. data/docs/source/persistent_cache.rst +34 -0
  29. data/docs/source/recipe.rst +23 -16
  30. data/docs/source/use_cases.rst +93 -0
  31. data/docs/source/workspace.rst +2 -0
  32. data/kameleon-builder.gemspec +7 -1
  33. data/lib/kameleon.rb +3 -6
  34. data/lib/kameleon/cli.rb +104 -50
  35. data/lib/kameleon/compat.rb +39 -0
  36. data/lib/kameleon/context.rb +43 -13
  37. data/lib/kameleon/engine.rb +118 -77
  38. data/lib/kameleon/environment.rb +3 -5
  39. data/lib/kameleon/error.rb +15 -9
  40. data/lib/kameleon/logger.rb +7 -4
  41. data/lib/kameleon/persistent_cache.rb +139 -0
  42. data/lib/kameleon/recipe.rb +200 -81
  43. data/lib/kameleon/shell.rb +51 -16
  44. data/omnibus/.gitignore +11 -0
  45. data/omnibus/.kitchen.yml +25 -0
  46. data/omnibus/Berksfile +9 -0
  47. data/omnibus/Berksfile.lock +25 -0
  48. data/omnibus/Gemfile +12 -0
  49. data/omnibus/README.md +94 -0
  50. data/omnibus/config/projects/kameleon.rb +23 -0
  51. data/omnibus/config/software/kameleon.rb +24 -0
  52. data/omnibus/config/software/polipo.rb +30 -0
  53. data/omnibus/config/software/ruby.rb +158 -0
  54. data/omnibus/files/mac_dmg/Resources/background.png +0 -0
  55. data/omnibus/files/mac_dmg/Resources/icon.png +0 -0
  56. data/omnibus/files/mac_pkg/Resources/background.png +0 -0
  57. data/omnibus/files/mac_pkg/Resources/license.html +1 -0
  58. data/omnibus/files/mac_pkg/Resources/welcome.html +9 -0
  59. data/omnibus/omnibus.rb +27 -0
  60. data/omnibus/package-scripts/kameleon/makeselfinst +27 -0
  61. data/omnibus/package-scripts/kameleon/postrm +9 -0
  62. data/templates/archlinux-desktop.yaml +25 -0
  63. data/templates/archlinux.yaml +106 -0
  64. data/templates/debian-testing.yaml +25 -0
  65. data/templates/debian7-desktop.yaml +25 -0
  66. data/templates/{debian-wheezy-docker.yaml → debian7-docker.yaml} +30 -16
  67. data/templates/debian7-g5k.yaml +97 -0
  68. data/templates/debian7-oar-dev.yaml +51 -0
  69. data/templates/debian7.yaml +128 -0
  70. data/templates/extend.erb +23 -0
  71. data/templates/fedora-rawhide.yaml +30 -0
  72. data/templates/fedora20-desktop.yaml +21 -0
  73. data/templates/fedora20.yaml +105 -0
  74. data/templates/{debian-wheezy-chroot.yaml → old-debian7.yaml} +51 -38
  75. data/templates/{aliases → steps/aliases}/defaults.yaml +37 -12
  76. data/templates/steps/bootstrap/archlinux/arch_bootstrap.yaml +219 -0
  77. data/templates/steps/bootstrap/archlinux/install_bootloader.yaml +46 -0
  78. data/templates/steps/bootstrap/archlinux/populate_disk.yaml +39 -0
  79. data/templates/steps/bootstrap/debian/debootstrap.yaml +18 -10
  80. data/templates/steps/bootstrap/debian/debootstrap_arm.yaml +31 -0
  81. data/templates/steps/bootstrap/fedora/liveos_bootstrap.yaml +123 -0
  82. data/templates/steps/bootstrap/g5k_reserv.yaml +70 -0
  83. data/templates/steps/bootstrap/initialize_disk_chroot.yaml +84 -0
  84. data/templates/steps/bootstrap/initialize_disk_qemu.yaml +72 -0
  85. data/templates/steps/bootstrap/install_bootloader.yaml +42 -0
  86. data/templates/steps/bootstrap/prepare_chroot.yaml +126 -0
  87. data/templates/steps/bootstrap/prepare_docker.yaml +19 -8
  88. data/templates/steps/bootstrap/prepare_qemu.yaml +47 -0
  89. data/templates/steps/bootstrap/start_chroot.yaml +11 -2
  90. data/templates/steps/bootstrap/start_docker.yaml +2 -2
  91. data/templates/steps/bootstrap/start_qemu.yaml +75 -0
  92. data/templates/steps/bootstrap/ubuntu/debootstrap.yaml +27 -0
  93. data/templates/steps/breakpoint.yaml +2 -0
  94. data/templates/{checkpoints → steps/checkpoints}/docker.yaml +0 -0
  95. data/templates/steps/checkpoints/qcow2.yaml +38 -0
  96. data/templates/steps/checkpoints/qemu.yaml +39 -0
  97. data/templates/steps/export/clean_appliance.yaml +7 -1
  98. data/templates/steps/export/compact_qcow_img.yaml +12 -0
  99. data/templates/steps/export/save_appliance.yaml +58 -0
  100. data/templates/steps/export/save_appliance_from_g5k.yaml +47 -0
  101. data/templates/steps/export/save_vagrant_box.yaml +29 -0
  102. data/templates/steps/setup/archlinux/configure_keyboard.yaml +9 -0
  103. data/templates/steps/setup/archlinux/configure_network.yaml +9 -0
  104. data/templates/steps/setup/archlinux/configure_ruby.yaml +7 -0
  105. data/templates/steps/setup/archlinux/configure_system.yaml +20 -0
  106. data/templates/steps/setup/archlinux/install_dev_tools.yaml +18 -0
  107. data/templates/steps/setup/archlinux/install_gnome.yaml +27 -0
  108. data/templates/steps/setup/archlinux/install_software.yaml +9 -0
  109. data/templates/steps/setup/archlinux/install_yaourt.yaml +29 -0
  110. data/templates/steps/setup/autologin.yaml +16 -0
  111. data/templates/steps/setup/create_group.yaml +12 -0
  112. data/templates/steps/setup/create_user.yaml +9 -10
  113. data/templates/steps/setup/debian/configure_apt.yaml +65 -0
  114. data/templates/steps/setup/debian/configure_kernel.yaml +18 -0
  115. data/templates/steps/setup/debian/{keyboard_config.yaml → configure_keyboard.yaml} +1 -1
  116. data/templates/steps/setup/debian/{network_config.yaml → configure_network.yaml} +0 -0
  117. data/templates/steps/setup/debian/{system_config.yaml → configure_system.yaml} +0 -0
  118. data/templates/steps/setup/debian/install_gnome.yaml +13 -0
  119. data/templates/steps/setup/debian/install_kde.yaml +13 -0
  120. data/templates/steps/setup/debian/install_software.yaml +2 -0
  121. data/templates/steps/setup/debian/oar/oar_debian_config_frontend.yaml +8 -0
  122. data/templates/steps/setup/debian/oar/oar_debian_config_node.yaml +5 -0
  123. data/templates/steps/setup/debian/oar/oar_debian_config_server.yaml +5 -0
  124. data/templates/steps/setup/debian/oar/oar_prereq_install.yaml +16 -0
  125. data/templates/steps/setup/debian/setup_vagrant_box.yaml +52 -0
  126. data/templates/steps/setup/debian/upgrade_system.yaml +15 -0
  127. data/templates/steps/setup/fedora/configure_network.yaml +30 -0
  128. data/templates/steps/setup/fedora/configure_system.yaml +59 -0
  129. data/templates/steps/setup/fedora/install_software.yaml +3 -0
  130. data/templates/steps/setup/fedora/update_system.yaml +10 -0
  131. data/templates/steps/setup/oar/oar_config_devel.yaml +21 -0
  132. data/templates/steps/setup/oar/oar_config_frontend.yaml +38 -0
  133. data/templates/steps/setup/oar/oar_config_node.yaml +4 -0
  134. data/templates/steps/setup/oar/oar_config_server.yaml +25 -0
  135. data/templates/steps/setup/oar/oar_config_system.yaml +34 -0
  136. data/templates/steps/setup/oar/oar_devel_prereq_install.yaml +5 -0
  137. data/templates/steps/setup/oar/oar_git_install.yaml +21 -0
  138. data/templates/steps/setup/ubuntu/configure_apt.yaml +67 -0
  139. data/templates/ubuntu-12.04-desktop.yaml +25 -0
  140. data/templates/ubuntu-12.04.yaml +128 -0
  141. data/templates/ubuntu-14.04-desktop.yaml +27 -0
  142. data/templates/ubuntu-14.04.yaml +25 -0
  143. data/templates/vagrant-debian7.yaml +31 -0
  144. data/version.txt +1 -1
  145. metadata +155 -28
  146. checksums.yaml +0 -7
  147. data/templates/checkpoints/qcow2.yaml +0 -44
  148. data/templates/fedora-docker.yaml +0 -96
  149. data/templates/steps/bootstrap/fedora/docker_bootstrap.yaml +0 -25
  150. data/templates/steps/bootstrap/fedora/yum_bootstrap.yaml +0 -22
  151. data/templates/steps/bootstrap/prepare_appliance_with_nbd.yaml +0 -93
  152. data/templates/steps/export/build_appliance_from_docker.yaml +0 -105
  153. data/templates/steps/export/save_appliance_from_nbd.yaml +0 -54
  154. data/templates/steps/setup/debian/kernel_install.yaml +0 -20
  155. data/templates/steps/setup/debian/software_install.yaml +0 -15
  156. data/templates/steps/setup/fedora/kernel_install.yaml +0 -27
  157. data/templates/steps/setup/fedora/software_install.yaml +0 -10
@@ -10,6 +10,9 @@ Welcome to Kameleon's documentation!
10
10
  .. note::
11
11
  This documentation is currently being written...
12
12
 
13
+ .. image:: _static/kameleon-long.png
14
+ :align: right
15
+
13
16
  -----
14
17
  About
15
18
  -----
@@ -17,7 +20,7 @@ About
17
20
  Kameleon should be seen as a simple but powerful tool to generate customized
18
21
  appliances. With Kameleon, you make your recipe that describes how to create
19
22
  step by step your own distribution. At start Kameleon is used to create custom
20
- kvm, LXC, VirtualBox, iso images, ..., but as it is designed to be very generic
23
+ kvm, docker, VirtualBox, ..., but as it is designed to be very generic
21
24
  you can probably do a lot more than that.
22
25
 
23
26
 
@@ -31,13 +34,16 @@ User Documentation
31
34
 
32
35
  installation.rst
33
36
  getting_started.rst
37
+ use_cases.rst
34
38
  recipe.rst
35
39
  context.rst
36
40
  commands.rst
37
41
  workspace.rst
38
42
  checkpoint.rst
43
+ persistent_cache.rst
39
44
  aliases.rst
40
45
  faq.rst
46
+ grid5000_tutorial.rst
41
47
 
42
48
  Indices and tables
43
49
  ==================
@@ -45,4 +51,3 @@ Indices and tables
45
51
  * :ref:`genindex`
46
52
  * :ref:`modindex`
47
53
  * :ref:`search`
48
-
@@ -1,7 +1,8 @@
1
1
  ------------
2
2
  Installation
3
3
  ------------
4
-
4
+ .. note::
5
+ On debian based distribution be sure to install the ``ruby-dev`` package first
5
6
 
6
7
  To install the latest release from `RubyGems`_:
7
8
 
@@ -11,11 +12,18 @@ To install the latest release from `RubyGems`_:
11
12
 
12
13
  gem install kameleon-builder --pre
13
14
 
14
- Or from source:
15
-
16
- ::
15
+ Or from source::
17
16
 
18
17
  git clone https://github.com/oar-team/kameleon.git
19
18
  cd kameleon
20
19
  gem build kameleon-builder.gemspec
21
20
  gem install kameleon-builder-<version>.gem
21
+
22
+
23
+ Any troubles?
24
+ ~~~~~~~~~~~~~
25
+ If you got an error message like this one::
26
+
27
+ ``/usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- mkmf (LoadError)``
28
+
29
+ It's because you need the ``ruby-dev`` package to fit the dependancies.
@@ -0,0 +1,34 @@
1
+ .. _`persistent_cache`:
2
+
3
+ ----------------
4
+ Persistent Cache
5
+ ----------------
6
+
7
+ .. versionadded:: 2.0.1
8
+
9
+ In order to exactly reconstruct a software appliance with the same exact
10
+ version of packages. Kameleon offer the option of creating a persistent cache
11
+ that will catch all the software packages during the building of the software
12
+ appliance. Enabling other to reconstruct the same exact software appliance
13
+ with the right package versions. Kameleon uses Polipo [1]_ which is a tiny and
14
+ lightweight web proxy to cache most of the packages that comes form the
15
+ network. First of all, you have to install Polipo on your system. If you are
16
+ under a debian distribution you can install it using the package manager::
17
+
18
+ sudo apt-get install polipo
19
+
20
+ You can as well build it from sources and then specify the path of the
21
+ generated binary using the option ``--proxy_path``. To use, you just have to
22
+ add the option ``--cache`` as an argument of the build command.
23
+ For example::
24
+
25
+ kameleon build debian_test -b /tmp/kameleon/ --cache
26
+
27
+ This will create a tar file in the build directory ``/tmp/kameleon`` called
28
+ ``debian_test-cache.tar``. In order to use this generated cache file in
29
+ another build, we have just to use the options ``--from_cache`` as follows::
30
+
31
+ kameleon build debian_test -b /tmp/kameleon/ --from_cache /tmp/debian_test-cache.tar
32
+
33
+
34
+ .. [1] http://www.pps.univ-paris-diderot.fr/~jch/software/polipo/
@@ -3,20 +3,24 @@ Recipe
3
3
  ------
4
4
 
5
5
  Kameleon compute YAML files, named *recipes*, that describes how you will
6
- build your appliance. These files are stored in the root of your `Workspace`_.
7
- A recipe is a hierarchical structure of `Sections`_, `Steps`_, `Microsteps`_ and
8
- `Commands`_. Here is an overview of this structure:
6
+ build your appliance. These files are stored in the root of your :ref:`workspace`.
7
+ A recipe is a hierarchical structure of `Section`_, `Step`_, `Microstep`_ and
8
+ :ref:`commands`. Here is an overview of this structure:
9
9
 
10
10
  .. code-block:: yaml
11
11
 
12
12
  recipe
13
- └── section
14
- └── step
15
- └── microstep
16
- └──command
13
+ |
14
+ `-- section
15
+ |
16
+ `-- step
17
+ |
18
+ `-- microstep
19
+ |
20
+ `-- command
17
21
 
18
22
  The recipe also contains set of `Global variables`_ declaration and some
19
- imports like `Aliases`_ and `Checkpoint`_.
23
+ imports like :ref:`aliases` and :ref:`checkpoint`.
20
24
 
21
25
  This is an example of a recipe:
22
26
 
@@ -89,7 +93,7 @@ This is an example of a recipe:
89
93
  - system_config:
90
94
  - locales: fr_FR en_US
91
95
  - lang: fr_FR.UTF-8
92
- - timezone: Europe/Paris
96
+ - timezone: UTC
93
97
  - keyboard_config:
94
98
  - layout: "fr,us"
95
99
  - network_config:
@@ -112,11 +116,11 @@ This is an example of a recipe:
112
116
  Section
113
117
  -------
114
118
 
115
- Each section is a list of `Steps`_. Currently, there is 3 sections:
119
+ Each section is a list of steps. Currently, there is 3 sections:
116
120
 
117
121
  bootstrap
118
122
  This section contains the bootstrap of the new system and create the *in*
119
- context (see `Contexts`_).
123
+ context (see :ref:`context`).
120
124
 
121
125
  setup
122
126
  This one is dedicated to the install and configuration steps.
@@ -125,10 +129,13 @@ export
125
129
  Export the generated appliance in the format of your choice.
126
130
 
127
131
 
128
- Step
129
- ----
132
+ .. _`step`:
133
+ .. _`microstep`:
130
134
 
131
- Each *step* contains a list of microsteps that contains a list of Commands_
135
+ Step and microstep
136
+ -------------------
137
+
138
+ Each *step* contains a list of *microsteps* that contains a list of :ref:`commands`
132
139
  written in one YAML file. To be found by Kameleon this file must be named by
133
140
  with the step name plus the YAML extension ``.yaml``. For example the
134
141
  ``software_install.yaml`` step file looks like this:
@@ -171,7 +178,7 @@ Steps path
171
178
  ~~~~~~~~~~
172
179
 
173
180
  The steps are YAML formated files stored in the ``recipe/steps`` directory of
174
- the Workspace_. To enable a better recipe reuse and ease of write the steps
181
+ the :ref:`workspace`. To enable a better recipe reuse and ease of write the steps
175
182
  are stored by default in specific folders depending on the sections.
176
183
 
177
184
  Kameleon is looking for the steps files using the ``include_steps`` list value,
@@ -227,7 +234,7 @@ Global variables
227
234
  ~~~~~~~~~~~~~~~~~
228
235
 
229
236
  Global variables are defined in the ``global`` dictionary of the recipe.
230
- Kameleon use some global variable to enable the appliance build. See Context_
237
+ Kameleon use some global variable to enable the appliance build. See :ref:`context`
231
238
  and `Steps path`_ for more details
232
239
 
233
240
 
@@ -0,0 +1,93 @@
1
+ .. _`use cases`:
2
+
3
+ ---------
4
+ Use Cases
5
+ ---------
6
+
7
+ Here it is described different use cases for Kameleon. It should give you a better
8
+ idea, through examples, of how Kameleon is useful for.
9
+
10
+ Distribute an environnement to your co-workers/students/friends/...
11
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
12
+ Whit Kameleon you can easily export your environnement in any format. The
13
+ export section of the recipe is made for this. For example, if you would like
14
+ to export your image in vdi format to use VirtualBox you just have to uncomment
15
+ the right line. Like in the debian7 template::
16
+
17
+ #== Export the generated appliance in the format of your choice
18
+ export:
19
+ - save_appliance_from_nbd:
20
+ - mountdir: $$rootfs
21
+ - filename: "$${kameleon_recipe_name}"
22
+ - save_as_qcow2
23
+ # - save_as_qed
24
+ # - save_as_tgz
25
+ # - save_as_raw
26
+ # - save_as_vmdk
27
+ - save_as_vdi
28
+
29
+ Make a Linux virtual machine with graphical support
30
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
31
+ You can directly use the templates that provide a desktop. However, here is an
32
+ example of adding desktop capability to the ``debian8`` template. First create
33
+ a new recipe from this template::
34
+
35
+ kameleon new debian8-dektop -t debian8
36
+
37
+ Then edit the recipe file ``debian8-dektop.yaml`` and add ``gnome-core`` and ``xorg``
38
+ packages to the install list::
39
+
40
+ setup:
41
+ # Install
42
+ - software_install:
43
+ - packages: >
44
+ debian-keyring ntp zip unzip rsync sudo less vim bash-completion
45
+ gnome-core xorg
46
+
47
+ These packages take some extra space, so add some space on the disk. 4G should
48
+ be enough::
49
+
50
+ bootstrap:
51
+ ...
52
+ - create_disk_nbd:
53
+ - image_size: 4G
54
+
55
+ Build your recipe::
56
+
57
+ sudo kameleon build debian8-desktop
58
+
59
+ When the build has finished, you can try you image with Qemu::
60
+
61
+ sudo qemu-system-x86_64 -m 1024 --enable-kvm -vga std \
62
+ builds/debian8-desktop/debian8-desktop.qcow2
63
+
64
+ Alternatively, you could use ``virt-manager`` that provide a good GUI to manage
65
+ your virtual machines.
66
+
67
+ .. note::
68
+ If you want a better integration between the host and the guest like
69
+ copy/paste use ``spice`` (http://www.linux-kvm.org/page/SPICE)
70
+
71
+
72
+ Create a fully reproducible experimental environement
73
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
74
+ You should use the :ref:`persistent_cache` feature.
75
+
76
+ .. todo::
77
+ Give a complete use case.
78
+
79
+ Create a persistent live USB key
80
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
81
+ A dirty but reliable method to do this is to cat the entire raw disk on the USB
82
+ key. First be sure that the disk size is equal or smaller then your
83
+ Then, export you image in raw format (this is the disk content bit by bit) and
84
+ dump it to your USB key. Once your image is built, if your USB key is the
85
+ ``/dev/sdb`` device, be sure that it is not mounted and just do this::
86
+
87
+ cat my_image.raw > /dev/my_key
88
+
89
+ .. warning::
90
+ This is a dangerous operation, you usb key will erase without
91
+ warning! Be sure that you pick the right device (use lsblk): it should be
92
+ ``/dev/sdX`` where X is a letter. Do NOT use the ``dev/sdXY``. unmount it
93
+ and use the root device instead.
@@ -1,3 +1,5 @@
1
+ .. _`workspace`:
2
+
1
3
  ---------
2
4
  Workspace
3
5
  ---------
@@ -1,4 +1,6 @@
1
1
  # coding: utf-8
2
+ RUBYONEX = RUBY_VERSION < "2.0"
3
+
2
4
  lib = File.expand_path('../lib', __FILE__)
3
5
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
6
  require 'kameleon/version'
@@ -24,10 +26,14 @@ Gem::Specification.new do |s|
24
26
  s.test_files = s.files.grep(%r{^(tests|s|features)/})
25
27
  s.require_paths = ["lib"]
26
28
 
27
- s.add_dependency 'childprocess', '~> 0.3'
29
+ s.required_ruby_version = RUBYONEX ? '>= 1.9.3' : '>= 2.0.0'
30
+
31
+ s.add_dependency 'childprocess', '~> 0.5'
28
32
  s.add_dependency 'thor', '~> 0.15'
29
33
  s.add_dependency 'table_print', '~> 1.5'
30
34
  s.add_dependency 'log4r-color', '~> 1.2'
35
+ s.add_dependency 'syck', '~> 1.0.0' unless RUBYONEX
36
+ s.add_dependency 'diffy', '~> 3.0.4'
31
37
 
32
38
  s.add_development_dependency 'pry', '~> 0.9'
33
39
  s.add_development_dependency 'pry-debugger', '~> 0.2'
data/lib/kameleon.rb CHANGED
@@ -1,5 +1,3 @@
1
- require 'securerandom'
2
- require 'yaml'
3
1
  require 'fileutils'
4
2
  require 'optparse'
5
3
  require 'erb'
@@ -12,11 +10,9 @@ require 'log4r-color'
12
10
  require 'log4r-color/configurator'
13
11
  require 'pathname'
14
12
  require 'table_print'
13
+ require 'diffy'
15
14
 
16
15
  module Kameleon
17
- # to force yaml to dump ASCII-8Bit strings as strings
18
- YAML::ENGINE.yamler='syck'
19
-
20
16
  # add a PROGRESS and NOTICE level
21
17
  Log4r::Configurator.custom_levels(:DEBUG, :INFO, :NOTICE,
22
18
  :PROGRESS, :WARN, :ERROR,
@@ -56,7 +52,7 @@ module Kameleon
56
52
  end
57
53
 
58
54
  def logger
59
- @logger ||= Log4r::Logger.new("kameleon::[global]")
55
+ @logger ||= Log4r::Logger.new("kameleon::[kameleon]")
60
56
  end
61
57
 
62
58
  def env
@@ -67,6 +63,7 @@ module Kameleon
67
63
  end
68
64
 
69
65
  # Load the things which must be loaded before anything else
66
+ require 'kameleon/compat'
70
67
  require 'kameleon/utils'
71
68
  require 'kameleon/error'
72
69
  require 'kameleon/cli'
data/lib/kameleon/cli.rb CHANGED
@@ -5,40 +5,62 @@ require 'kameleon/utils'
5
5
  module Kameleon
6
6
  class CLI < Thor
7
7
 
8
- class_option :no_color, :type => :boolean, :default => false,
9
- :desc => "Disable colorization in output"
8
+
9
+ class_option :color, :type => :boolean, :default => true,
10
+ :desc => "Enable colorization in output"
10
11
  class_option :debug, :type => :boolean, :default => false,
11
12
  :desc => "Enable debug output"
12
- class_option :workspace, :aliases => '-w', :type => :string,
13
- :desc => 'Change the kameleon current work directory. ' \
14
- '(The folder containing your recipes folder).' \
15
- ' Default : ./'
13
+ map %w(-h --help) => :help
14
+
16
15
  no_commands do
17
16
  def logger
18
- @logger ||= Log4r::Logger.new("kameleon::[cli]")
17
+ @logger ||= Log4r::Logger.new("kameleon::[kameleon]")
18
+ end
19
+ end
20
+
21
+ method_option :force,:type => :boolean,
22
+ :default => false, :aliases => "-f",
23
+ :desc => "Overwrite all existing files"
24
+ desc "import [TEMPLATE_NAME]", "Imports the given template"
25
+ def import(template_name)
26
+ templates_path = Kameleon.env.templates_path
27
+ template_path = File.join(templates_path, template_name) + '.yaml'
28
+ begin
29
+ template_recipe = RecipeTemplate.new(template_path)
30
+ rescue
31
+ raise TemplateNotFound, "Template '#{template_name}' not found. " \
32
+ "To see all templates, run the command "\
33
+ "`kameleon templates`"
34
+ else
35
+ logger.notice("Importing template '#{template_name}'...")
36
+ template_recipe.copy_template(options[:force])
37
+ logger.notice("done")
19
38
  end
20
39
  end
21
40
 
22
- method_option :template, :aliases => "-t",
23
- :desc => "Starting from a template", :required => true,
24
- :enum => Kameleon.templates_names
25
41
  method_option :force,:type => :boolean,
26
42
  :default => false, :aliases => "-f",
27
- :desc => "overwrite the recipe"
28
- desc "new [RECIPE_NAME]", "Creates a new recipe"
29
- def new(recipe_name)
30
- logger.notice("Cloning template '#{options[:template]}'")
43
+ :desc => "Overwrite all existing files"
44
+ desc "new [RECIPE_NAME] [TEMPLATE_NAME]", "Creates a new recipe"
45
+ def new(recipe_name, template_name)
46
+ if recipe_name == template_name
47
+ fail RecipeError, "Recipe name should be different from template name"
48
+ end
31
49
  templates_path = Kameleon.env.templates_path
32
- recipes_path = Kameleon.env.recipes_path
33
-
34
- template_path = File.join(templates_path, options[:template]) + '.yaml'
35
- template_recipe = RecipeTemplate.new(template_path)
36
- template_recipe.copy_template(recipes_path,
37
- recipe_name,
38
- options[:force])
39
- recipe_path = File.join(recipes_path, recipe_name + ".yaml")
40
- logger.notice("New recipe \"#{recipe_name}\" "\
41
- "as been created in #{recipe_path}")
50
+ template_path = File.join(templates_path, template_name) + '.yaml'
51
+ begin
52
+ template_recipe = RecipeTemplate.new(template_path)
53
+ rescue
54
+ raise TemplateNotFound, "Template '#{template_name}' not found. " \
55
+ "To see all templates, run the command "\
56
+ "`kameleon templates`"
57
+ else
58
+ logger.notice("Cloning template '#{template_name}'...")
59
+ template_recipe.copy_template(options[:force])
60
+ logger.notice("Creating extended recipe from template '#{template_name}'...")
61
+ template_recipe.copy_extended_recipe(recipe_name, options[:force])
62
+ logger.notice("done")
63
+ end
42
64
  end
43
65
 
44
66
  desc "templates", "Lists all defined templates"
@@ -58,6 +80,7 @@ module Kameleon
58
80
  raise e if Kameleon.env.debug
59
81
  end
60
82
  end
83
+ templates_hash = templates_hash.sort_by{ |k| k["name"] }
61
84
  tp templates_hash, {"name" => {:width => 30}}, { "description" => {:width => 60}}
62
85
  end
63
86
 
@@ -68,61 +91,80 @@ module Kameleon
68
91
  end
69
92
  map %w(-v --version) => :version
70
93
 
71
-
72
- desc "build [RECIPE_NAME]", "Builds the appliance from the recipe"
94
+ desc "build [RECIPE_PATH]", "Builds the appliance from the given recipe"
73
95
  method_option :build_path, :type => :string ,
74
96
  :default => nil, :aliases => "-b",
75
97
  :desc => "Set the build directory path"
98
+ method_option :clean, :type => :boolean ,
99
+ :default => false,
100
+ :desc => "Run the command `kameleon clean` first"
76
101
  method_option :from_checkpoint, :type => :string ,
77
102
  :default => nil,
78
103
  :desc => "Using specific checkpoint to build the image. " \
79
104
  "Default value is the last checkpoint."
80
- method_option :no_checkpoint, :type => :boolean ,
81
- :default => false,
105
+ method_option :checkpoint, :type => :boolean ,
106
+ :default => true,
82
107
  :desc => "Do not use checkpoints"
83
- def build(recipe_name)
84
- logger.notice("Starting build recipe '#{recipe_name}'")
85
- start_time = Time.now.to_i
86
- recipe_path = File.join(Kameleon.env.recipes_path, recipe_name) + '.yaml'
108
+ method_option :cache, :type => :boolean,
109
+ :default => false,
110
+ :desc => "Generate a persistent cache for the appliance."
111
+ method_option :from_cache, :type => :string ,
112
+ :default => nil,
113
+ :desc => "Using a persistent cache tar file to build the image."
114
+ method_option :proxy_path, :type => :string ,
115
+ :default => nil,
116
+ :desc => "Full path of the proxy binary to use for the persistent cache."
117
+
118
+ def build(recipe_path)
119
+ clean(recipe_path) if options[:clean]
87
120
  engine = Kameleon::Engine.new(Recipe.new(recipe_path), options)
121
+ logger.notice("Starting build recipe '#{recipe_path}'")
122
+ start_time = Time.now.to_i
88
123
  engine.build
89
124
  total_time = Time.now.to_i - start_time
90
125
  logger.notice("")
91
- logger.notice("Build recipe '#{recipe_name}' is completed !")
126
+ logger.notice("Build recipe '#{recipe_path}' is completed !")
92
127
  logger.notice("Build total duration : #{total_time} secs")
93
128
  logger.notice("Build directory : #{engine.cwd}")
94
129
  logger.notice("Build recipe file : #{engine.build_recipe_path}")
95
130
  logger.notice("Log file : #{Kameleon.env.log_file}")
96
131
  end
97
132
 
98
- desc "checkpoints [RECIPE_NAME]", "Lists all availables checkpoints"
133
+ desc "checkpoints [RECIPE_PATH]", "Lists all availables checkpoints"
99
134
  method_option :build_path, :type => :string ,
100
135
  :default => nil, :aliases => "-b",
101
136
  :desc => "Set the build directory path"
102
- def checkpoints(recipe_name)
137
+ def checkpoints(recipe_path)
103
138
  Log4r::Outputter['console'].level = Log4r::ERROR unless Kameleon.env.debug
104
- recipe_path = File.join(Kameleon.env.recipes_path, recipe_name) + '.yaml'
105
139
  engine = Kameleon::Engine.new(Recipe.new(recipe_path), options)
106
140
  engine.pretty_checkpoints_list
107
141
  end
108
142
 
109
- desc "clear [RECIPE_NAME]", "Cleaning out context and removing all checkpoints"
143
+ desc "clean [RECIPE_PATH]", "Cleaning 'out' and 'local' contexts and removing all checkpoints"
110
144
  method_option :build_path, :type => :string ,
111
145
  :default => nil, :aliases => "-b",
112
146
  :desc => "Set the build directory path"
113
- def clear(recipe_name)
147
+ def clean(recipe_path)
114
148
  Log4r::Outputter['console'].level = Log4r::INFO
115
- recipe_path = File.join(Kameleon.env.recipes_path, recipe_name) + '.yaml'
116
149
  engine = Kameleon::Engine.new(Recipe.new(recipe_path), options)
117
150
  engine.clear
118
151
  end
152
+ map %w(clear) => :clean
153
+
154
+ desc "commands", "Lists all available commands", :hide => true
155
+ def commands
156
+ puts CLI.all_commands.keys - ["commands", "completions"]
157
+ end
158
+
159
+ desc "source_root", "Prints the kameleon directory path", :hide => true
160
+ def source_root
161
+ puts Kameleon.source_root
162
+ end
119
163
 
120
164
  # Hack Thor to init Kameleon env soon
121
165
  def self.init(base_config)
122
- options = base_config[:shell].base.options
123
- workspace ||= options[:workspace] || ENV['KAMELEON_WORKSPACE'] || Dir.pwd
124
- env_options = options.merge({:workspace => workspace})
125
- FileUtils.mkdir_p workspace
166
+ env_options = Hash.new
167
+ env_options.merge! base_config[:shell].base.options.clone
126
168
  # configure logger
127
169
  env_options["debug"] = true if ENV["KAMELEON_LOG"] == "debug"
128
170
  ENV["KAMELEON_LOG"] = "debug" if env_options["debug"]
@@ -138,34 +180,46 @@ module Kameleon
138
180
  begin
139
181
  level = Log4r.const_get(level_name.upcase)
140
182
  rescue NameError
141
- fail KameleonError, "Invalid KAMELEON_LOG level is set: #{level_name}.\n" \
142
- "Please use one of the standard log levels: debug," \
143
- " info, warn, or error"
183
+ level = Log4r.const_get("INFO")
184
+ $stderr << "Invalid KAMELEON_LOG level is set: #{level_name}.\n" \
185
+ "Please use one of the standard log levels: debug," \
186
+ " info, warn, or error\n"
187
+ raise KameleonError
144
188
  end
145
189
  format = ConsoleFormatter.new
146
190
  # format = Log4r::PatternFormatter.new(:pattern => '%11c: %M')
147
- if !$stdout.tty? or env_options["no_color"]
191
+ if !$stdout.tty? or !env_options["color"]
148
192
  console_output = Log4r::StdoutOutputter.new('console',
149
193
  :formatter => format)
194
+ Diffy::Diff.default_format = :text
150
195
  else
151
196
  console_output = Log4r::ColorOutputter.new 'console', {
152
197
  :colors => { :debug => :light_black,
153
198
  :info => :green,
199
+ :progress_info => :green,
154
200
  :notice => :light_blue,
155
- :progress => :light_blue,
201
+ :progress_notice => :light_blue,
156
202
  :warn => :yellow,
157
203
  :error => :red,
204
+ :progress_error => :red,
158
205
  :fatal => :red,
159
206
  },
160
207
  :formatter => format,
161
208
  }
209
+ Diffy::Diff.default_format = :color
162
210
  end
163
211
  logger = Log4r::Logger.new('kameleon')
164
- logger.outputters << console_output
165
212
  logger.level = level
166
- logger = nil
213
+ logger.outputters << console_output
214
+ format_file = FileFormatter.new
167
215
  Kameleon.logger.debug("`kameleon` invoked: #{ARGV.inspect}")
168
216
  Kameleon.env = Kameleon::Environment.new(env_options)
217
+ filelog = Log4r::FileOutputter.new('logfile',
218
+ :trunc=>false,
219
+ :filename => Kameleon.env.log_file.to_s,
220
+ :formatter => format_file)
221
+ logger.outputters << filelog
222
+ logger = nil
169
223
  end
170
224
 
171
225
  def self.start(given_args=ARGV, config={})