vagabond 0.2.0 → 0.2.2

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.
Files changed (73) hide show
  1. data/CHANGELOG.md +18 -0
  2. data/README.md +125 -4
  3. data/bin/vagabond +43 -16
  4. data/lib/vagabond/actions/cluster.rb +66 -0
  5. data/lib/vagabond/actions/create.rb +12 -7
  6. data/lib/vagabond/actions/destroy.rb +69 -15
  7. data/lib/vagabond/actions/init.rb +75 -0
  8. data/lib/vagabond/actions/provision.rb +4 -2
  9. data/lib/vagabond/actions/status.rb +33 -22
  10. data/lib/vagabond/actions/up.rb +8 -1
  11. data/lib/vagabond/bootstraps/server-zero.erb +20 -0
  12. data/lib/vagabond/bootstraps/server.erb +3 -2
  13. data/lib/vagabond/constants.rb +0 -15
  14. data/lib/vagabond/cookbooks/lxc/CHANGELOG.md +16 -0
  15. data/lib/vagabond/cookbooks/lxc/Gemfile +3 -2
  16. data/lib/vagabond/cookbooks/lxc/Gemfile.lock +30 -121
  17. data/lib/vagabond/cookbooks/lxc/README.md +43 -14
  18. data/lib/vagabond/cookbooks/lxc/attributes/default.rb +3 -3
  19. data/lib/vagabond/cookbooks/lxc/files/default/lxc-awesome-ephemeral +499 -0
  20. data/lib/vagabond/cookbooks/lxc/libraries/lxc.rb +223 -58
  21. data/lib/vagabond/cookbooks/lxc/libraries/lxc_file_config.rb +3 -0
  22. data/lib/vagabond/cookbooks/lxc/libraries/monkey.rb +51 -0
  23. data/lib/vagabond/cookbooks/lxc/metadata.rb +6 -5
  24. data/lib/vagabond/cookbooks/lxc/providers/config.rb +9 -16
  25. data/lib/vagabond/cookbooks/lxc/providers/container.rb +241 -229
  26. data/lib/vagabond/cookbooks/lxc/providers/default.rb +57 -0
  27. data/lib/vagabond/cookbooks/lxc/providers/ephemeral.rb +40 -0
  28. data/lib/vagabond/cookbooks/lxc/providers/fstab.rb +13 -54
  29. data/lib/vagabond/cookbooks/lxc/providers/interface.rb +13 -67
  30. data/lib/vagabond/cookbooks/lxc/providers/service.rb +14 -14
  31. data/lib/vagabond/cookbooks/lxc/recipes/default.rb +17 -4
  32. data/lib/vagabond/cookbooks/lxc/recipes/install_dependencies.rb +1 -1
  33. data/lib/vagabond/cookbooks/lxc/resources/config.rb +2 -2
  34. data/lib/vagabond/cookbooks/lxc/resources/container.rb +31 -6
  35. data/lib/vagabond/cookbooks/lxc/resources/default.rb +12 -0
  36. data/lib/vagabond/cookbooks/lxc/resources/ephemeral.rb +13 -0
  37. data/lib/vagabond/cookbooks/lxc/resources/fstab.rb +2 -1
  38. data/lib/vagabond/cookbooks/lxc/resources/interface.rb +6 -3
  39. data/lib/vagabond/cookbooks/lxc/resources/service.rb +1 -1
  40. data/lib/vagabond/cookbooks/lxc/templates/default/file_content.erb +2 -0
  41. data/lib/vagabond/cookbooks/lxc/templates/default/interface.erb +9 -3
  42. data/lib/vagabond/cookbooks/vagabond/README.md +10 -0
  43. data/lib/vagabond/cookbooks/vagabond/attributes/default.rb +1 -0
  44. data/lib/vagabond/cookbooks/vagabond/files/default/lxc-centos +13 -6
  45. data/lib/vagabond/cookbooks/vagabond/metadata.rb +1 -0
  46. data/lib/vagabond/cookbooks/vagabond/recipes/default.rb +46 -4
  47. data/lib/vagabond/cookbooks/vagabond/recipes/zero.rb +9 -0
  48. data/lib/vagabond/errors.rb +23 -0
  49. data/lib/vagabond/helpers.rb +41 -14
  50. data/lib/vagabond/internal_configuration.rb +120 -27
  51. data/lib/vagabond/kitchen.rb +143 -63
  52. data/lib/vagabond/knife.rb +8 -5
  53. data/lib/vagabond/layout.rb +16 -0
  54. data/lib/vagabond/monkey/kitchen_config.rb +23 -0
  55. data/lib/vagabond/server.rb +79 -63
  56. data/lib/vagabond/spec.rb +345 -0
  57. data/lib/vagabond/uploader.rb +30 -0
  58. data/lib/vagabond/uploader/berkshelf.rb +53 -0
  59. data/lib/vagabond/uploader/knife.rb +24 -0
  60. data/lib/vagabond/uploader/librarian.rb +31 -0
  61. data/lib/vagabond/vagabond.rb +30 -11
  62. data/lib/vagabond/vagabondfile.rb +40 -5
  63. data/lib/vagabond/version.rb +1 -1
  64. data/vagabond.gemspec +5 -2
  65. metadata +75 -15
  66. data/lib/vagabond/cookbooks/lxc/resources/#container.rb# +0 -28
  67. data/lib/vagabond/cookbooks/lxc/test/kitchen/Kitchenfile +0 -7
  68. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/metadata.rb +0 -2
  69. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/centos_lxc.rb +0 -0
  70. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/chef-bootstrap.rb +0 -0
  71. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/lxc_files.rb +0 -0
  72. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/lxc_templates.rb +0 -0
  73. data/lib/vagabond/cookbooks/lxc/test/kitchen/cookbooks/lxc_test/recipes/ubuntu_lxc.rb +0 -0
@@ -0,0 +1,12 @@
1
+ actions :create, :delete, :clone
2
+ default_action :create
3
+
4
+ attribute :template, :kind_of => String, :default => 'ubuntu'
5
+ attribute :template_opts, :kind_of => Hash, :default => {}
6
+ attribute :base_container, :kind_of => String
7
+
8
+ # Backing store options. Not yet in use
9
+ attribute :fstype, :kind_of => String, :default => 'ext4'
10
+ attribute :fssize, :kind_of => String, :default => '2G'
11
+ attribute :vgname, :kind_of => String
12
+ attribute :lvname, :kind_of => String
@@ -0,0 +1,13 @@
1
+ actions :run
2
+ default_action :run
3
+
4
+ attribute :command, :kind_of => String, :required => true
5
+ attribute :bind_directory, :kind_of => String
6
+ attribute :base_container, :kind_of => String, :required => true
7
+ attribute :background, :kind_of => [TrueClass,FalseClass], :default => false
8
+ attribute :union_type, :equal_to => %w(aufs overlayfs), :default => 'overlayfs'
9
+ attribute :user, :kind_of => String, :default => 'root'
10
+ attribute :key, :kind_of => String, :default => '/opt/hw-lxc-config/id_rsa'
11
+ attribute :host_rootfs, :kind_of => String
12
+ attribute :virtual_device, :kind_of => Numeric
13
+ attribute :stream_output, :kind_of => [TrueClass,FalseClass,IO]
@@ -8,4 +8,5 @@ attribute :type, :kind_of => String, :required => true
8
8
  attribute :options, :kind_of => [String, Array]
9
9
  attribute :dump, :kind_of => Numeric, :default => 0
10
10
  attribute :pass, :kind_of => Numeric, :default => 0
11
- attribute :_lxc
11
+ attribute :auto_join_rootfs_mount, :kind_of => [TrueClass,FalseClass], :default => true
12
+ attribute :create_mount_point, :kind_of => [TrueClass,FalseClass], :default => true
@@ -5,6 +5,9 @@ attribute :container, :kind_of => String, :required => true
5
5
  attribute :device, :kind_of => String, :required => true
6
6
  attribute :auto, :kind_of => [TrueClass, FalseClass], :default => true
7
7
  attribute :dynamic, :kind_of => [TrueClass, FalseClass], :default => false
8
- attribute :address, :regex => %r{\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}}
9
- attribute :gateway, :regex => %r{\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}}
10
- attribute :netmask, :regex => %r{\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}}, :default => '255.255.255.0'
8
+ attribute :address, :kind_of => String
9
+ attribute :gateway, :kind_of => String
10
+ attribute :up, :kind_of => String
11
+ attribute :down, :kind_of => String
12
+ attribute :netmask, :kind_of => [String,Numeric]
13
+ attribute :ipv6, :kind_of => [TrueClass,FalseClass], :default => false
@@ -2,4 +2,4 @@ actions :start, :stop, :halt, :restart, :freeze, :unfreeze
2
2
  default_action :start
3
3
 
4
4
  attribute :service_name, :kind_of => String
5
- attribute :_lxc
5
+
@@ -0,0 +1,2 @@
1
+ # Chef generated key file
2
+ <%= ::File.read(@path) %>
@@ -4,18 +4,24 @@
4
4
  auto lo
5
5
  iface lo inet loopback
6
6
 
7
- <% node[:lxc][:interfaces][@container].each do |net_set| -%>
7
+ <% node.run_state[:lxc][:interfaces][@container].each do |net_set| -%>
8
8
  <% if net_set[:auto] -%>
9
9
  auto <%= net_set[:device] %>
10
10
  <% end -%>
11
11
  <% if net_set[:dynamic] -%>
12
- iface <%= net_set[:device] %> inet dhcp
12
+ iface <%= net_set[:device] %> inet<%= '6' if net_set[:ipv6] %> dhcp
13
13
  <% else -%>
14
- iface <%= net_set[:device] %> inet static
14
+ iface <%= net_set[:device] %> inet<%= '6' if net_set[:ipv6] %> static
15
15
  address <%= net_set[:address] %>
16
16
  <% if net_set[:gateway] -%>
17
17
  gateway <%= net_set[:gateway] %>
18
18
  <% end -%>
19
19
  netmask <%= net_set[:netmask] %>
20
+ <% if net_set[:up] -%>
21
+ up <%= net_set[:up] %>
22
+ <% end -%>
23
+ <% if net_set[:down] -%>
24
+ down <%= net_set[:down] %>
25
+ <% end -%>
20
26
  <% end -%>
21
27
  <% end %>
@@ -0,0 +1,10 @@
1
+ # Vagabond
2
+
3
+ This cookbooks is used internally by the vagabond project.
4
+ It's general intention is to be used in that fashion, but
5
+ if you want to do something else with it, go nuts.
6
+
7
+ ## Info
8
+
9
+ * Repository: https://github.com/chrisroberts/chef-vagabond
10
+ * IRC: spox @ Freenode
@@ -15,3 +15,4 @@ default[:vagabond][:bases][:debian_6][:create_environment] = {'SUITE' => 'squeez
15
15
  default[:vagabond][:bases][:debian_7][:template] = 'debian'
16
16
  default[:vagabond][:bases][:debian_7][:create_environment] = {'SUITE' => 'wheezy'}
17
17
  default[:vagabond][:customs] = {}
18
+ default[:vagabond][:server_base] = true
@@ -156,16 +156,23 @@ YUM="yum --installroot $INSTALL_ROOT -y --nogpgcheck"
156
156
  PKG_LIST="yum initscripts passwd rsyslog vim-minimal dhclient chkconfig"
157
157
  PKG_LIST="$PKG_LIST rootfiles policycoreutils centos-release openssh-server avahi"
158
158
  MIRRORLIST_URL="http://mirrorlist.centos.org/?release=$release.$releaseminor&arch=$arch&repo=os"
159
-
159
+
160
+ FOUND_MIRRORS=$(curl -s -S -f "$MIRRORLIST_URL")
161
+ AVAIL_MIRRORS="${FOUND_MIRRORS} http://vault.centos.org/$release.$releaseminor/os/$arch"
162
+
160
163
  DOWNLOAD_OK=no
161
- for trynumber in 1 2 3; do
162
- [ $trynumber != 1 ] && echo "Trying again..."
163
- MIRROR_URL=$(curl -s -S -f "$MIRRORLIST_URL" | head -n2 | tail -n1)
164
+ for MIRROR_URL in $AVAIL_MIRRORS; do
164
165
  if [ $? -ne 0 ] || [ -z "$MIRROR_URL" ]; then
165
166
  echo "Failed to get a mirror"
166
167
  continue
167
168
  fi
168
- RELEASE_URL="$MIRROR_URL/Packages/centos-release-$release-$releaseminor.el6.centos.9.$arch.rpm"
169
+ if [ $release = "6" ]; then
170
+ PACKAGE_NAME=`wget -q -O - ${MIRROR_URL}/Packages/ | grep centos-release-${release}.${releaseminor} | sed -r 's/.+rpm">//g' | sed -r 's/<.+//g'`
171
+ RELEASE_URL="$MIRROR_URL/Packages/${PACKAGE_NAME}"
172
+ else
173
+ PACKAGE_NAME=`wget -q -O - ${MIRROR_URL}/CentOS/ | grep centos-release-${release}.${releaseminor} | sed -r 's/.+rpm">//g' | sed -r 's/<.+//g'`
174
+ RELEASE_URL="$MIRROR_URL/CentOS/${PACKAGE_NAME}"
175
+ fi
169
176
  echo "Fetching from $RELEASE_URL"
170
177
  curl -f "$RELEASE_URL" > $INSTALL_ROOT/centos-release-$release-$releaseminor.centos.$arch.rpm
171
178
  if [ $? -ne 0 ]; then
@@ -412,7 +419,7 @@ fi
412
419
 
413
420
  rootfs_path=$path/rootfs
414
421
  config_path=$default_path/$name
415
- cache=$cache_base/$release
422
+ cache=$cache_base/$release.$releaseminor
416
423
 
417
424
  revert()
418
425
  {
@@ -1,5 +1,6 @@
1
1
  name 'vagabond'
2
2
  version '1.0.0'
3
+ license 'Apache 2.0'
3
4
  maintainer 'Chris Roberts'
4
5
  maintainer_email 'chrisroberts.code@gmail.com'
5
6
 
@@ -1,3 +1,37 @@
1
+
2
+ # TODO: Move this to lxc cookbook proper at some point
3
+ # TODO: Test this on fresh node to ensure start up scripts actuall do
4
+ # what they are expected to
5
+ =begin
6
+ dpkg_autostart 'lxc' do
7
+ allow false
8
+ end
9
+
10
+ dpkg_autostart 'lxc-net' do
11
+ allow false
12
+ end
13
+ =end
14
+ # Start at 0 and increment up if found
15
+ unless(node[:network][:interfaces][:lxcbr0])
16
+ max = node.network.interfaces.map do |name, val|
17
+ Array(val[:routes]).map do |route|
18
+ if(route[:family] == 'inet' && route[:destination].start_with?('10.0'))
19
+ route[:destination].split('/').first.split('.')[3].to_i
20
+ end
21
+ end
22
+ end.compact.max
23
+
24
+ node.default[:vagabond][:lxc_network][:oct] = max ? max + 1 : 0
25
+
26
+ # Test for existing bridge. Use different subnet if found
27
+ l_net = "10.0.#{node[:vagabond][:lxc_network][:oct]}"
28
+
29
+ node.set[:lxc][:addr] = "#{l_net}.1"
30
+ node.set[:lxc][:network] = "#{l_net}.0/24"
31
+ node.set[:lxc][:dhcp_range] = "#{l_net}.2,#{l_net}.199"
32
+ node.set[:lxc][:dhcp_max] = '199'
33
+ end
34
+
1
35
  include_recipe 'lxc'
2
36
 
3
37
  ruby_block 'LXC template: lxc-centos' do
@@ -57,11 +91,21 @@ node[:vagabond][:bases].each do |name, options|
57
91
  end
58
92
  end
59
93
 
94
+ lxc_container 'chef-server' do
95
+ clone 'ubuntu_1204'
96
+ initialize_commands [
97
+
98
+ ]
99
+ only_if do
100
+ node[:vagabond][:server_base]
101
+ end
102
+ end
103
+
60
104
  node[:vagabond][:customs].each do |name, options|
61
105
 
62
106
  lxc_container name do
63
- action :clone
64
- base_container options[:base]
107
+ action :create
108
+ clone options[:base]
65
109
  end
66
110
 
67
111
  if(options[:memory])
@@ -76,5 +120,3 @@ node[:vagabond][:customs].each do |name, options|
76
120
  end
77
121
  end
78
122
  end
79
-
80
-
@@ -0,0 +1,9 @@
1
+ execute 'apt-get update'
2
+ package 'build-essential'
3
+ gem_package 'chef-zero'
4
+
5
+ execute 'start chef-zero' do
6
+ command "start-stop-daemon --background --start --quiet --exec #{File.join(node[:languages][:ruby][:bin_dir],'chef-zero')} -- -H #{node[:ipaddress]} -p 80 start"
7
+ not_if 'netstat -lpt | grep "tcp[[:space:]]" | grep ruby'
8
+ end
9
+
@@ -0,0 +1,23 @@
1
+ module Vagabond
2
+ class VagabondError < StandardError
3
+ class << self
4
+ attr_accessor :exit_code
5
+ end
6
+ def exit_code
7
+ self.class.exit_code
8
+ end
9
+ end
10
+
11
+ class VagabondError
12
+ %w(
13
+ reserved_name invalid_name invalid_base_template
14
+ invalid_action invalid_template kitchen_missing_yml
15
+ kitchen_no_cookbook_args kitchen_too_many_args
16
+ kitchen_invalid_platform missing_node_name cluster_invalid
17
+ kitchen_test_failed host_provision_failed spec_failed
18
+ ).each_with_index do |klass_name, i|
19
+ klass = klass_name.split('_').map(&:capitalize).join
20
+ self.class_eval("class #{klass} < VagabondError; self.exit_code = #{i + 1}; end")
21
+ end
22
+ end
23
+ end
@@ -1,41 +1,68 @@
1
1
  require 'vagabond/constants'
2
+ require 'tmpdir'
3
+ require 'uuidtools'
2
4
 
3
5
  module Vagabond
4
6
  module Helpers
7
+
8
+ RAND_CHARS = ('a'..'z').map(&:to_s) + ('A'..'Z').map(&:to_s) + (0..9).map(&:to_s)
9
+ GEN_NAME_LENGTH = 10
10
+
5
11
  private
12
+
13
+ def base_setup
14
+ @options = options.dup
15
+ @vagabondfile = Vagabondfile.new(options[:vagabond_file], :allow_missing)
16
+ Lxc.use_sudo = sudo
17
+ options[:sudo] = sudo
18
+ setup_ui
19
+ @internal_config = InternalConfiguration.new(@vagabondfile, ui, options)
20
+ end
21
+
6
22
  def sudo
7
- case @vagabondfile[:sudo]
8
- when TrueClass
9
- 'sudo '
23
+ case vagabondfile[:sudo]
24
+ when FalseClass
25
+ ''
10
26
  when String
11
- "#{@vagabondfile[:sudo]} "
27
+ "#{vagabondfile[:sudo]} "
28
+ else
29
+ 'sudo '
12
30
  end
13
31
  end
14
32
 
15
33
  def debug(s)
16
- ui.info "#{ui.color('DEBUG:', :red, :bold)} #{s}" if options[:debug]
34
+ ui.info "#{ui.color('DEBUG:', :red, :bold)} #{s}" if options[:debug] && ui
35
+ end
36
+
37
+ def random_name(n=nil)
38
+ n = name unless n
39
+ [n, SecureRandom.hex].compact.join('-')
17
40
  end
18
41
 
19
42
  def generated_name(n=nil)
43
+ seed = vagabondfile.directory.chars.map(&:ord).inject(&:+)
44
+ srand(seed)
20
45
  n = name unless n
21
46
  if(@_gn.nil? || @_gn[n].nil?)
22
47
  @_gn ||= Mash.new
23
- s = Digest::MD5.new
24
- s << @vagabondfile.path
25
- @_gn[n] = "#{n}-#{s.hexdigest}"
48
+ @_gn[n] = "#{n}-"
49
+ GEN_NAME_LENGTH.times do
50
+ @_gn[n] << RAND_CHARS[rand(RAND_CHARS.size)]
51
+ end
26
52
  end
27
53
  @_gn[n]
28
54
  end
29
55
 
30
- def setup_ui(ui=nil)
31
- unless(ui)
56
+ def setup_ui(*args)
57
+ unless(args.first.is_a?(Chef::Knife::UI))
32
58
  Chef::Config[:color] = options[:color].nil? ? true : options[:color]
33
59
  @ui = Chef::Knife::UI.new(STDOUT, STDERR, STDIN, {})
34
60
  else
35
- @ui = ui
61
+ @ui = args.first
36
62
  end
37
63
  options[:debug] = STDOUT if options[:debug]
38
- self.class.ui = @ui
64
+ self.class.ui = @ui unless args.include?(:no_class_set)
65
+ @ui
39
66
  end
40
67
 
41
68
  def execute
@@ -43,7 +70,7 @@ module Vagabond
43
70
  send(@action)
44
71
  else
45
72
  ui.error "Invalid action received: #{@action}"
46
- exit EXIT_CODES[:invalid_action]
73
+ raise VagabondError::InvalidAction.new(@action)
47
74
  end
48
75
  end
49
76
 
@@ -75,9 +102,9 @@ module Vagabond
75
102
  class << self
76
103
  attr_accessor :ui
77
104
  end
105
+ attr_accessor :vagabondfile, :internal_config, :name, :ui
78
106
  end
79
107
  end
80
108
  end
81
-
82
109
  end
83
110
  end
@@ -2,6 +2,7 @@ require 'digest/sha2'
2
2
  require 'json'
3
3
  require 'vagabond/helpers'
4
4
  require 'vagabond/constants'
5
+ require 'chef/mixin/deep_merge'
5
6
 
6
7
  module Vagabond
7
8
  class InternalConfiguration
@@ -23,17 +24,36 @@ module Vagabond
23
24
  @config = Mash.new(
24
25
  :mappings => Mash.new,
25
26
  :template_mappings => Mash.new,
26
- :test_mappings => Mash.new
27
+ :test_mappings => Mash.new,
28
+ :spec_mappings => Mash.new,
29
+ :spec_clusters => Mash.new
27
30
  ).merge(config)
28
31
  @force_bases = args[:force_bases] || []
29
32
  ensure_state
33
+ make_knife_config_if_required
30
34
  end
31
35
 
32
36
  def ensure_state
33
- store_checksums
34
- write_dna_json
35
- write_solo_rb
36
- run_solo if solo_needed?
37
+ check_bases_and_customs!
38
+ if(solo_needed?)
39
+ store_checksums
40
+ write_dna_json
41
+ write_solo_rb
42
+ run_solo if solo_needed?
43
+ end
44
+ end
45
+
46
+ def check_bases_and_customs!
47
+ if(File.exists?(dna_path))
48
+ dna = Mash.new(JSON.load(File.read(dna_path)))
49
+ %w(bases customs).each do |key|
50
+ if(dna[:vagabond][key])
51
+ dna[:vagabond][key].each do |n, opts|
52
+ options[:force_solo] = true unless Lxc.new(n).exists?
53
+ end
54
+ end
55
+ end
56
+ end
37
57
  end
38
58
 
39
59
  def [](k)
@@ -48,24 +68,33 @@ module Vagabond
48
68
  FileUtils.mkdir_p(store_path)
49
69
  end
50
70
 
51
- def load_existing
71
+ def load_existing(file=nil)
52
72
  if(File.exists?(path = File.join(store_path, 'vagabond.json')))
53
- @config = Mash.new(
54
- JSON.load(
55
- File.read(path)
73
+ if(file)
74
+ file.rewind
75
+ content = file.read
76
+ else
77
+ content = File.read(path)
78
+ end
79
+ if(content.strip.empty?)
80
+ config = Mash.new
81
+ else
82
+ config = Mash.new(
83
+ JSON.load(content)
56
84
  )
57
- )
85
+ end
86
+ @config = Chef::Mixin::DeepMerge.merge(config, @config)
58
87
  else
59
88
  @config = Mash.new
60
89
  end
61
90
  end
62
91
 
63
92
  def store_path
64
- FileUtils.mkdir_p(
65
- File.join(
66
- File.dirname(@vagabondfile.path), '.vagabond'
67
- )
68
- )
93
+ path = File.join(File.dirname(@vagabondfile.store_path), '.vagabond')
94
+ unless(File.directory?(path))
95
+ FileUtils.mkdir_p(path)
96
+ end
97
+ path
69
98
  end
70
99
 
71
100
  def dna_path
@@ -90,9 +119,9 @@ module Vagabond
90
119
  conf[:customs][generated_name(t_name)] = opts
91
120
  config[:template_mappings][t_name] = generated_name(t_name)
92
121
  else
93
- ui.fatal "Invalid base template encountered: #{t}"
122
+ ui.fatal "Invalid base template encountered: #{t_name}"
94
123
  ui.info ui.color(" -> Valid base templates: #{BASE_TEMPLATES.sort.join(', ')}", :red)
95
- exit EXIT_CODES[:invalid_base_template]
124
+ raise VagabondError::InvalidBaseTemplate.new(t_name)
96
125
  end
97
126
  end
98
127
  File.open(dna_path, 'w') do |file|
@@ -156,21 +185,85 @@ module Vagabond
156
185
  end
157
186
 
158
187
  def run_solo
159
- ui.info ui.color('Ensuring expected system state (creating required base containers)', :yellow)
160
- ui.info ui.color(' - This can take a while...', :yellow)
161
- com = "#{options[:sudo]}chef-solo -j #{File.join(store_path, 'dna.json')} -c #{File.join(store_path, 'solo.rb')}"
162
- debug(com)
163
- cmd = Mixlib::ShellOut.new(com, :timeout => 12000, :live_stream => options[:debug])
164
- cmd.run_command
165
- cmd.error!
166
- ui.info ui.color(' -> COMPLETE!', :yellow)
188
+ begin
189
+ ui.info ui.color('Ensuring expected system state (creating required base containers)', :yellow)
190
+ ui.info ui.color(' - This can take a while on first run or new templates...', :yellow)
191
+ com = "#{options[:sudo]}chef-solo -j #{File.join(store_path, 'dna.json')} -c #{File.join(store_path, 'solo.rb')}"
192
+ debug(com)
193
+ cmd = Mixlib::ShellOut.new(com, :timeout => 12000, :live_stream => options[:debug])
194
+ cmd.run_command
195
+ cmd.error!
196
+ ui.info ui.color(' -> COMPLETE!', :yellow)
197
+ rescue => e
198
+ ui.info e.to_s
199
+ FileUtils.rm(solo_path)
200
+ ui.info ui.color(' -> FAILED!', :red, :bold)
201
+ raise VagabondError::HostProvisionFailed.new(e)
202
+ end
203
+ end
204
+
205
+ def config_path
206
+ File.join(store_path, 'vagabond.json')
167
207
  end
168
208
 
169
209
  def save
170
- File.open(File.join(store_path, 'vagabond.json'), 'w') do |file|
171
- file.write(JSON.dump(@config))
210
+ mode = File.exists?(config_path) ? 'r+' : 'w+'
211
+ File.open(config_path, mode) do |file|
212
+ file.flock(File::LOCK_EX)
213
+ file.rewind
214
+ if(sha = file_changed?(file.path))
215
+ @checksums[file.path] = sha
216
+ load_existing(file)
217
+ end
218
+ file.rewind
219
+ file.write(JSON.pretty_generate(@config))
220
+ file.truncate(file.pos)
172
221
  end
173
222
  end
174
223
 
224
+ def knife_config_available?
225
+ if(File.exists?(File.join(store_path, 'knife.rb')))
226
+ false
227
+ else
228
+ cwd = @vagabondfile.directory.split('/')
229
+ found = false
230
+ until(found || cwd.empty?)
231
+ found = File.exists?(File.join(*(cwd + ['.chef/knife.rb'])))
232
+ cwd.pop
233
+ end
234
+ found
235
+ end
236
+ end
237
+
238
+ def file_changed?(path)
239
+ checksum = get_checksum(path)
240
+ checksum unless @checksums[path] == checksum
241
+ end
242
+
243
+ def make_knife_config_if_required(force=false)
244
+ if((@vagabondfile[:local_chef_server] && @vagabondfile[:local_chef_server][:enabled]) || force)
245
+ unless(knife_config_available?)
246
+ store_dir = File.dirname(store_path)
247
+ k_dir = File.join(store_dir, '.chef')
248
+ FileUtils.mkdir_p(k_dir)
249
+ unless(File.exists?(knife = File.join(k_dir, 'knife.rb')))
250
+ File.open(knife, 'w') do |file|
251
+ file.write <<-EOF
252
+ node_name 'dummy'
253
+ client_key File.join(File.dirname(__FILE__), 'client.pem')
254
+ validation_client_name 'dummy-validator'
255
+ validation_key File.join(File.dirname(__FILE__), 'validation.pem')
256
+ cookbook_path ['#{%w(cookbooks site-cookbooks).map{|dir|File.join(@vagabondfile.directory, dir)}.join(',')}']
257
+ EOF
258
+ end
259
+ end
260
+ %w(client.pem validation.pem).each do |name|
261
+ unless(File.exists?(pem = File.join(k_dir, name)))
262
+ %x{openssl genrsa -out #{pem} 2048}
263
+ end
264
+ end
265
+ end
266
+ end
267
+ end
175
268
  end
176
269
  end