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
@@ -1,9 +1,10 @@
1
- maintainer "Chris Roberts"
2
- maintainer_email "chrisroberts.code@gmail.com"
3
- license "Apache 2.0"
4
- description "Chef driven Linux Containers"
1
+ name 'lxc'
2
+ maintainer 'Chris Roberts'
3
+ maintainer_email 'chrisroberts.code@gmail.com'
4
+ license 'Apache 2.0'
5
+ description 'Chef driven Linux Containers'
5
6
  long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
6
- version "0.1.1"
7
+ version '1.0.1'
7
8
 
8
9
  supports 'ubuntu'
9
10
 
@@ -1,16 +1,16 @@
1
1
  require 'securerandom'
2
2
 
3
3
  def load_current_resource
4
- new_resource._lxc Lxc.new(
4
+ @lxc = ::Lxc.new(
5
5
  new_resource.name,
6
6
  :base_dir => node[:lxc][:container_directory],
7
7
  :dnsmasq_lease_file => node[:lxc][:dnsmasq_lease_file]
8
8
  )
9
9
  new_resource.utsname new_resource.name unless new_resource.utsname
10
- new_resource.rootfs new_resource._lxc.rootfs unless new_resource.rootfs
10
+ new_resource.rootfs @lxc.rootfs.to_path unless new_resource.rootfs
11
11
  new_resource.default_bridge node[:lxc][:bridge] unless new_resource.default_bridge
12
- new_resource.mount ::File.join(new_resource._lxc.path, 'fstab') unless new_resource.mount
13
- config = LxcFileConfig.new(new_resource._lxc.container_config)
12
+ new_resource.mount @lxc.path.join('fstab').to_path unless new_resource.mount
13
+ config = LxcFileConfig.new(@lxc.container_config)
14
14
  if((new_resource.network.nil? || new_resource.network.empty?))
15
15
  if(config.network.empty?)
16
16
  default_net = {
@@ -19,11 +19,10 @@ def load_current_resource
19
19
  :flags => :up,
20
20
  :hwaddr => "00:16:3e#{SecureRandom.hex(3).gsub(/(..)/, ':\1')}"
21
21
  }
22
- default_net.merge!(:ipv4 => new_resource.static_ip) if new_resource.static_ip
23
22
  else
24
23
  default_net = config.network.first
24
+ default_net.delete(:ipv4) if default_net.has_key?(:ipv4)
25
25
  default_net.merge!(:link => new_resource.default_bridge)
26
- default_net.merge!(:ipv4 => new_resource.static_ip) if new_resource.static_ip
27
26
  end
28
27
  new_resource.network(default_net)
29
28
  else
@@ -62,21 +61,15 @@ def load_current_resource
62
61
  end
63
62
 
64
63
  action :create do
65
- ruby_block "lxc config_updater[#{new_resource.utsname}]" do
66
- block do
67
- new_resource.updated_by_last_action(true)
68
- end
69
- action :nothing
70
- end
71
-
72
- directory new_resource._lxc.container_path do
64
+ _lxc = @lxc
65
+
66
+ directory @lxc.path.to_path do
73
67
  action :create
74
68
  end
75
69
 
76
70
  file "lxc update_config[#{new_resource.utsname}]" do
77
- path new_resource._lxc.container_config
71
+ path _lxc.container_config.to_path
78
72
  content LxcFileConfig.generate_config(new_resource)
79
73
  mode 0644
80
- notifies :create, resources(:ruby_block => "lxc config_updater[#{new_resource.utsname}]"), :immediately
81
74
  end
82
75
  end
@@ -1,38 +1,51 @@
1
1
  def load_current_resource
2
- new_resource._lxc Lxc.new(
2
+ @lxc = ::Lxc.new(
3
3
  new_resource.name,
4
4
  :base_dir => node[:lxc][:container_directory],
5
5
  :dnsmasq_lease_file => node[:lxc][:dnsmasq_lease_file]
6
6
  )
7
+ new_resource.subresources.map! do |s_r|
8
+ s_r.first.run_context = run_context
9
+ s_r.first.instance_eval(&s_r.last)
10
+ s_r.first
11
+ end
12
+
7
13
  # TODO: Use some actual logic here, sheesh
8
14
  if(new_resource.static_ip && new_resource.static_gateway.nil?)
9
- new_resource.static_gateway new_resource.static_ip.sub(/\d+$/, '1')
15
+ raise "Static gateway must be defined when static IP is provided (Container: #{new_resource.name})"
10
16
  end
11
17
  new_resource.default_bridge node[:lxc][:bridge] unless new_resource.default_bridge
12
- new_resource.new_container !new_resource._lxc.exists?
18
+ node.run_state[:lxc] ||= Mash.new
19
+ node.run_state[:lxc][:meta] ||= Mash.new
20
+ node.run_state[:lxc][:meta][new_resource.name] = Mash.new(
21
+ :new_container => !@lxc.exists?,
22
+ :lxc => @lxc
23
+ )
13
24
  end
14
25
 
15
26
  action :create do
27
+ _lxc = @lxc # for use inside resources
28
+ stopped_end_state = _lxc.stopped?
16
29
 
17
30
  #### Add custom key for host based interactions
18
- lxc_dir = directory '/opt/hw-lxc-config' do
19
- action :nothing
31
+ directory '/opt/hw-lxc-config' do
32
+ recursive true
20
33
  end
21
- lxc_dir.run_action(:create)
22
34
 
23
- lxc_key = execute "lxc host_ssh_key" do
35
+ execute 'lxc host_ssh_key' do
24
36
  command "ssh-keygen -P '' -f /opt/hw-lxc-config/id_rsa"
25
- creates "/opt/hw-lxc-config/id_rsa"
26
- action :nothing
37
+ creates '/opt/hw-lxc-config/id_rsa'
27
38
  end
28
- lxc_key.run_action(:run)
29
39
 
30
40
  #### Create container
31
- execute "lxc create[#{new_resource.name}]" do
32
- command "lxc-create -n #{new_resource.name} -t #{new_resource.template} -- #{new_resource.template_opts.to_a.flatten.join(' ')}"
33
- environment new_resource.create_environment
34
- only_if do
35
- !new_resource._lxc.exists? && new_resource.updated_by_last_action(true)
41
+ lxc new_resource.name do
42
+ if(new_resource.clone)
43
+ action :clone
44
+ base_container new_resource.clone
45
+ else
46
+ action :create
47
+ template new_resource.template
48
+ template_opts new_resource.template_opts
36
49
  end
37
50
  end
38
51
 
@@ -41,7 +54,6 @@ action :create do
41
54
  lxc_config new_resource.name do
42
55
  action :create
43
56
  default_bridge new_resource.default_bridge
44
- static_ip new_resource.static_ip
45
57
  end
46
58
  end
47
59
 
@@ -71,272 +83,272 @@ action :create do
71
83
  netmask new_resource.static_netmask
72
84
  gateway new_resource.static_gateway
73
85
  end
86
+ end
74
87
 
75
- ruby_block "force container gateway[#{new_resource.name}]" do
76
- block do
77
- file = Chef::Util::FileEdit.new(
78
- ::File.join(
79
- new_resource._lxc.rootfs, 'etc', 'rc.local'
80
- )
81
- )
82
- file.search_file_delete_line(%r{route add default gw})
83
- file.search_file_replace(
84
- %r{exit 0$},
85
- "route add default gw #{new_resource.static_gateway}\nexit 0"
86
- )
87
- file.write_file
88
+ ruby_block "LXC #{new_resource.name} - Run subresources" do
89
+ block do
90
+ new_resource.subresources.each do |s_r|
91
+ s_r.run_action(:create)
88
92
  end
89
- not_if "grep \"route add default gw #{new_resource.static_gateway}\" #{::File.join(new_resource._lxc.rootfs, 'etc', 'rc.local')}"
93
+ end
94
+ not_if do
95
+ new_resource.subresources.empty?
90
96
  end
91
97
  end
92
98
 
93
- #### Ensure host has ssh access into container
94
- directory ::File.join(new_resource._lxc.rootfs, 'root', '.ssh')
95
-
96
- file ::File.join(new_resource._lxc.rootfs, 'root', '.ssh', 'authorized_keys') do
97
- content "# Chef generated key file\n#{::File.read('/opt/hw-lxc-config/id_rsa.pub')}\n"
99
+ template @lxc.path.join('fstab').to_path do
100
+ source 'fstab.erb'
101
+ cookbook 'lxc'
102
+ variables :container => new_resource.name
103
+ only_if do
104
+ node.run_state[:lxc][:fstabs] &&
105
+ node.run_state[:lxc][:fstabs][new_resource.name]
106
+ end
107
+ mode 0644
98
108
  end
99
109
 
100
- if(new_resource.chef_enabled || !new_resource.container_commands.empty? || !new_resource.initialize_commands.empty?)
101
- if(new_resource.chef_enabled && new_resource.new_container)
102
-
103
- #### Use cached chef package from host if available
104
- if(%w(debian ubuntu).include?(new_resource.template) && system('ls /opt/chef*.deb 2>1 > /dev/null'))
105
- file_name = Dir.new('/opt').detect do |item|
106
- item.start_with?('chef') && item.end_with?('.deb')
107
- end
108
- if(file_name)
109
- execute "lxc copy_chef_full[#{new_resource.name}]" do
110
- command "cp /opt/#{file_name} #{::File.join(new_resource._lxc.rootfs, 'opt')}"
111
- not_if do
112
- ::File.exists?(
113
- ::File.join(new_resource._lxc.rootfs, 'opt', file_name)
114
- )
115
- end
116
- end
117
-
118
- execute "lxc install_chef_full[#{new_resource.name}]" do
119
- action :nothing
120
- command "chroot #{new_resource._lxc.rootfs} dpkg -i #{::File.join('/opt', file_name)}"
121
- subscribes :run, resources(:execute => "lxc copy_chef_full[#{new_resource.name}]"), :immediately
122
- end
123
- @chef_installed = true
124
- end
125
- end
126
-
127
- # TODO: Add resources for RPM install
128
-
129
- #### Setup chef related bits within container
130
- directory ::File.join(new_resource._lxc.rootfs, 'etc', 'chef') do
131
- action :create
132
- mode 0755
133
- end
134
-
135
- template "lxc chef-config[#{new_resource.name}]" do
136
- source 'client.rb.erb'
137
- cookbook 'lxc'
138
- path ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'client.rb')
139
- variables(
140
- :validation_client => new_resource.validation_client,
141
- :node_name => new_resource.node_name || "#{node.name}-#{new_resource.name}",
142
- :server_uri => new_resource.server_uri,
143
- :chef_environment => new_resource.chef_environment || '_default'
144
- )
145
- mode 0644
146
- end
110
+ template @lxc.rootfs.join('etc/network/interfaces').to_path do
111
+ source 'interface.erb'
112
+ cookbook 'lxc'
113
+ variables :container => new_resource.name
114
+ mode 0644
115
+ only_if do
116
+ node.run_state[:lxc][:interfaces] &&
117
+ node.run_state[:lxc][:interfaces][new_resource.name]
118
+ end
119
+ end
147
120
 
148
- file "lxc chef-validator[#{new_resource.name}]" do
149
- path ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'validator.pem')
150
- content new_resource.validator_pem || node[:lxc][:validator_pem]
151
- mode 0600
152
- end
121
+ #### Ensure host has ssh access into container
122
+ directory @lxc.rootfs.join('root/.ssh').to_path
153
123
 
154
- file "lxc chef-runlist[#{new_resource.name}]" do
155
- path ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'first_run.json')
156
- content({:run_list => new_resource.run_list}.to_json)
157
- not_if do
158
- ::File.exists?(
159
- ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'client.pem')
160
- )
161
- end
162
- mode 0644
163
- end
124
+ template @lxc.rootfs.join('root/.ssh/authorized_keys').to_path do
125
+ source 'file_content.erb'
126
+ cookbook 'lxc'
127
+ mode 0600
128
+ variables(:path => '/opt/hw-lxc-config/id_rsa.pub')
129
+ end
164
130
 
165
- #### Provide data bag secret file if required
166
- if(new_resource.copy_data_bag_secret_file)
167
- if ::File.readable?(new_resource.data_bag_secret_file)
168
- file "lxc chef-data-bag-secret[#{new_resource.name}]" do
169
- path ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'encrypted_data_bag_secret')
170
- content ::File.open(new_resource.data_bag_secret_file, "rb").read
171
- mode 0600
172
- end
173
- else
174
- Chef::Log.warn "Could not read #{new_resource.data_bag_secret_file}"
175
- end
131
+ #### Use cached chef package from host if available
132
+ if(%w(debian ubuntu).include?(new_resource.template) && system('ls /opt/chef*.deb 2>1 > /dev/null'))
133
+ if(::File.directory?('/opt'))
134
+ file_name = Dir.new('/opt').detect do |item|
135
+ item.start_with?('chef') && item.end_with?('.deb')
176
136
  end
177
137
  end
178
-
179
- ruby_block "lxc start[#{new_resource.name}]" do
180
- block do
181
- new_resource._lxc.start
182
- end
183
- only_if do
184
- ::File.exists?(
185
- ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'first_run.json')
186
- ) || (new_resource.new_container && new_resource.initialize_commands)
138
+
139
+ execute "lxc copy_chef_full[#{new_resource.name}]" do
140
+ command "cp /opt/#{file_name} #{_lxc.rootfs.join('opt')}"
141
+ not_if do
142
+ file_name.nil? || !new_resource.chef_enabled || _lxc.rootfs.join('opt', file_name).exist?
187
143
  end
188
144
  end
145
+
146
+ execute "lxc install_chef_full[#{new_resource.name}]" do
147
+ action :nothing
148
+ command "chroot #{_lxc.rootfs} dpkg -i #{::File.join('/opt', file_name)}"
149
+ subscribes :run, "execute[lxc copy_chef_full[#{new_resource.name}]]", :immediately
150
+ end
151
+ elsif(new_resource.chef_enabled)
152
+ pkg_coms = ['update -y -q', 'upgrade -y -q','install curl -y -q']
153
+ if(!new_resource.template.to_s.scan(%r{debian|ubuntu}).empty?)
154
+ pkg_man = 'apt-get'
155
+ elsif(!new_resource.template.to_s.scan(%r{fedora|centos}).empty?)
156
+ pkg_man = 'yum'
157
+ end
158
+ if(pkg_man)
159
+ new_resource.initialize_commands(
160
+ pkg_coms.map do |c|
161
+ "#{pkg_man} #{c}"
162
+ end + new_resource.initialize_commands
163
+ )
164
+ end
165
+ end
189
166
 
190
- if(new_resource.chef_enabled && new_resource.new_container)
191
- # Make sure we have chef in the container
192
- unless(@chef_installed)
193
- # Use remote file to remove curl dep
194
- remote_file "lxc chef_install_script[#{new_resource.name}]" do
195
- source "http://opscode.com/chef/install.sh"
196
- path ::File.join(new_resource._lxc.rootfs, 'opt', 'chef-install.sh')
197
- action :create_if_missing
198
- end
199
-
200
- ruby_block "lxc install_chef[#{new_resource.name}]" do
201
- block do
202
- new_resource._lxc.container_command(
203
- "bash /opt/chef-install.sh"
204
- )
205
- end
206
- not_if do
207
- ::File.exists?(
208
- ::File.join(new_resource._lxc.rootfs, 'usr', 'bin', 'chef-client')
209
- )
167
+ ruby_block "lxc lock_default_users" do
168
+ block do
169
+ contents = ::File.readlines(_lxc.rootfs.join('etc/shadow').to_path)
170
+ ::File.open(_lxc.rootfs.join('etc/shadow').to_path, 'w') do |file|
171
+ contents.each do |line|
172
+ parts = line.split(':')
173
+ if(node[:lxc][:user_locks].include?(parts.first) && !parts[1].start_with?('!'))
174
+ parts[1] = "!#{parts[1]}"
210
175
  end
211
- end
212
- end
213
-
214
- #### Let chef configure the container
215
- ruby_block "lxc run_chef[#{new_resource.name}]" do
216
- block do
217
- new_resource._lxc.container_command(
218
- "chef-client -K /etc/chef/validator.pem -c /etc/chef/client.rb -j /etc/chef/first_run.json",
219
- new_resource.chef_retries
220
- )
221
- end
222
- not_if do
223
- ::File.exists?(
224
- ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'client.pem')
225
- )
176
+ file.write parts.join(':')
226
177
  end
227
178
  end
228
179
  end
229
-
230
- #### Have initialize commands for the container? Run them now
231
- if(new_resource.new_container && !new_resource.initialize_commands.empty?)
232
- ruby_block "lxc initialize_commands[#{new_resource.name}]" do
233
- block do
234
- new_resource.initialize_commands.each do |cmd|
235
- new_resource._lxc.container_command(cmd, 2)
236
- end
237
- end
180
+ only_if do
181
+ ::File.readlines(_lxc.rootfs.join('etc/shadow').to_path).detect do |line|
182
+ parts = line.split(':')
183
+ node[:lxc][:user_locks].include?(parts.first) && !parts[1].start_with?('!')
238
184
  end
239
185
  end
186
+ end
240
187
 
241
- #### Have commands for the container? Run them now
242
- unless(new_resource.container_commands.empty?)
243
- ruby_block "lxc container_commands[#{new_resource.name}]" do
244
- block do
245
- new_resource.container_commands.each do |cmd|
246
- new_resource._lxc.container_command(cmd, 2)
188
+ ruby_block "lxc default_password_scrub" do
189
+ block do
190
+ contents = ::File.readlines(_lxc.rootfs.join('etc/shadow').to_path)
191
+ ::File.open(_lxc.rootfs.join('etc/shadow'), 'w') do |file|
192
+ contents.each do |line|
193
+ if(line.start_with?('root:'))
194
+ line.sub!(%r{root:.+?:}, 'root:*')
247
195
  end
196
+ file.write line
248
197
  end
249
198
  end
250
199
  end
200
+ not_if "grep 'root:*' #{_lxc.rootfs.join('etc/shadow').to_path}"
201
+ end
251
202
 
252
- #### NOTE: Creation always leaves the container in a stopped state
253
- ruby_block "lxc shutdown[#{new_resource.name}]" do
254
- block do
255
- new_resource._lxc.shutdown
256
- end
257
- only_if do
258
- new_resource.new_container
259
- end
203
+ ruby_block "lxc start[#{new_resource.name}]" do
204
+ block do
205
+ _lxc.start
260
206
  end
261
-
262
- #### Clean up after chef if it's enabled
263
- if(new_resource.chef_enabled)
264
- file ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'first_run.json') do
265
- action :delete
266
- end
267
-
268
- file ::File.join(new_resource._lxc.rootfs, 'etc', 'chef', 'validator.pem') do
269
- action :delete
207
+ only_if do
208
+ _lxc.rootfs.join('etc/chef/first_run.json').exist? ||
209
+ !new_resource.container_commands.empty? ||
210
+ (node.run_state[:lxc][:meta][new_resource.name][:new_container] && new_resource.initialize_commands)
211
+ end
212
+ end
213
+
214
+ #### Have initialize commands for the container? Run them now
215
+ ruby_block "lxc initialize_commands[#{new_resource.name}]" do
216
+ block do
217
+ new_resource.initialize_commands.each do |cmd|
218
+ Chef::Log.info "Running command on #{new_resource.name}: #{cmd}"
219
+ _lxc.container_command(cmd, 2)
270
220
  end
271
221
  end
222
+ only_if do
223
+ node.run_state[:lxc][:meta][new_resource.name][:new_container] &&
224
+ !new_resource.initialize_commands.empty?
225
+ end
272
226
  end
273
227
 
274
- end
228
+ # Make sure we have chef in the container
229
+ remote_file "lxc chef_install_script[#{new_resource.name}]" do
230
+ source "http://opscode.com/chef/install.sh"
231
+ path _lxc.rootfs.join('opt/chef-install.sh').to_path
232
+ action :create_if_missing
233
+ only_if do
234
+ new_resource.chef_enabled && !_lxc.rootfs.join('usr/bin/chef-client').exist?
235
+ end
236
+ end
275
237
 
276
- action :delete do
277
- ruby_block "lxc stop[#{new_resource.name}]" do
238
+ ruby_block "lxc install_chef[#{new_resource.name}]" do
278
239
  block do
279
- new_resource._lxc.stop
240
+ _lxc.container_command('bash /opt/chef-install.sh')
280
241
  end
242
+ action :create
281
243
  only_if do
282
- new_resource._lxc.running?
244
+ new_resource.chef_enabled &&
245
+ !_lxc.rootfs.join('usr/bin/chef-client').exist? &&
246
+ _lxc.rootfs.join('opt/chef-install.sh').exist?
283
247
  end
284
248
  end
285
-
286
- execute "lxc delete[#{new_resource.name}]" do
287
- command "lxc-destroy -n #{new_resource.name}"
288
- only_if do
289
- new_resource._lxc.exists? && new_resource.updated_by_last_action(true)
290
- end
249
+
250
+ #### Setup chef related bits within container
251
+ directory @lxc.rootfs.join('etc/chef').to_path do
252
+ action :create
253
+ mode 0755
254
+ only_if{ new_resource.chef_enabled }
255
+ end
256
+
257
+ template "lxc chef-config[#{new_resource.name}]" do
258
+ source 'client.rb.erb'
259
+ cookbook 'lxc'
260
+ path _lxc.rootfs.join('etc/chef/client.rb').to_path
261
+ variables(
262
+ :validation_client => new_resource.validation_client || Chef::Config[:validation_client_name],
263
+ :node_name => new_resource.node_name || "#{node.name}-#{new_resource.name}",
264
+ :server_uri => new_resource.server_uri || Chef::Config[:chef_server_url],
265
+ :chef_environment => new_resource.chef_environment || '_default'
266
+ )
267
+ mode 0644
268
+ only_if{ new_resource.chef_enabled }
291
269
  end
292
- end
293
270
 
294
- action :clone do
295
- execute "lxc clone[#{new_resource.base_container} -> #{new_resource.name}]" do
296
- command "lxc-clone -o #{new_resource.base_container} -n #{new_resource.name}"
271
+ file "lxc chef-validator[#{new_resource.name}]" do
272
+ path _lxc.rootfs.join('etc/chef/validator.pem').to_path
273
+ content new_resource.validator_pem || node[:lxc][:validator_pem]
274
+ mode 0600
275
+ only_if{ new_resource.chef_enabled && !_lxc.rootfs.join('etc/chef/client.pem').exist? }
276
+ end
277
+
278
+ file "lxc chef-runlist[#{new_resource.name}]" do
279
+ path _lxc.rootfs.join('etc/chef/first_run.json').to_path
280
+ content({:run_list => new_resource.run_list}.to_json)
297
281
  only_if do
298
- !new_resource._lxc.exists? && new_resource.updated_by_last_action(true)
282
+ new_resource.chef_enabled && !_lxc.rootfs.join('etc/chef/client.pem').exist?
299
283
  end
284
+ mode 0644
300
285
  end
301
286
 
302
- lxc_service "lxc config_restart[#{new_resource.name}]" do
303
- service_name new_resource.name
304
- action :nothing
287
+ file "lxc chef-data-bag-secret[#{new_resource.name}]" do
288
+ path _lxc.rootfs.join('etc/chef/encrypted_data_bag_secret').to_path
289
+ content(
290
+ ::File.exists?(new_resource.data_bag_secret_file) ? ::File.open(new_resource.data_bag_secret_file, "rb").read : ''
291
+ )
292
+ mode 0600
305
293
  only_if do
306
- new_resource._lxc.running?
294
+ new_resource.chef_enabled &&
295
+ new_resource.copy_data_bag_secret_file &&
296
+ ::File.exists?(new_resource.copy_data_bag_secret_file)
307
297
  end
308
298
  end
309
299
 
310
- lxc_config new_resource.name do
311
- action :create
312
- notifies :restart, resources(:lxc_service => "lxc config_restart[#{new_resource.name}]"), :immediately
300
+ #### Let chef configure the container
301
+ # NOTE: We run chef-client if the validator.pem exists and the
302
+ # client.pem file does not exist.
303
+ ruby_block "lxc run_chef[#{new_resource.name}]" do
304
+ block do
305
+ cmd = 'chef-client -K /etc/chef/validator.pem -c /etc/chef/client.rb -j /etc/chef/first_run.json'
306
+ Chef::Log.info "Running command on #{new_resource.name}: #{cmd}"
307
+ _lxc.container_command(cmd, new_resource.chef_retries)
308
+ end
309
+ only_if do
310
+ new_resource.chef_enabled &&
311
+ _lxc.rootfs.join('etc/chef/validator.pem').exist? &&
312
+ !_lxc.rootfs.join('etc/chef/client.pem').exist?
313
+ end
313
314
  end
314
-
315
- if(new_resource.chef_enabled)
316
- ruby_block "lxc start[#{new_resource.name}]" do
317
- block do
318
- new_resource._lxc.start
315
+
316
+ #### Have commands for the container? Run them now
317
+ ruby_block "lxc container_commands[#{new_resource.name}]" do
318
+ block do
319
+ new_resource.container_commands.each do |cmd|
320
+ _lxc.container_command(cmd, 2)
319
321
  end
320
- action :nothing
321
- subscribes :create, resources(:execute => "lxc clone[#{new_resource.base_container} -> #{new_resource.name}]"), :immediately
322
322
  end
323
+ not_if do
324
+ new_resource.container_commands.empty?
325
+ end
326
+ end
323
327
 
324
- ruby_block "lxc run_chef[#{new_resource.name}]" do
325
- block do
326
- new_resource._lxc.container_command(
327
- "chef-client -K /etc/chef/validator.pem -c /etc/chef/client.rb -j /etc/chef/first_run.json", 3
328
- )
329
- end
330
- action :nothing
331
- subscribes :create, resources(:execute => "lxc clone[#{new_resource.base_container} -> #{new_resource.name}]"), :immediately
328
+ # NOTE: If the container was not running before we started, make
329
+ # sure we leave it in a stopped state
330
+ ruby_block "lxc shutdown[#{new_resource.name}]" do
331
+ block do
332
+ _lxc.shutdown
332
333
  end
333
-
334
- ruby_block "lxc shutdown[#{new_resource.name}]" do
335
- block do
336
- new_resource._lxc.shutdown
337
- end
338
- action :nothing
339
- subscribes :create, resources(:execute => "lxc clone[#{new_resource.base_container} -> #{new_resource.name}]"), :immediately
334
+ only_if do
335
+ stopped_end_state && _lxc.running?
340
336
  end
341
337
  end
338
+
339
+ #### Clean up after chef if it's enabled
340
+ file @lxc.rootfs.join('etc/chef/first_run.json').to_path do
341
+ action :delete
342
+ end
343
+
344
+ file @lxc.rootfs.join('etc/chef/validator.pem').to_path do
345
+ action :delete
346
+ end
347
+
348
+ end
349
+
350
+ action :delete do
351
+ lxc new_resource.name do
352
+ action :delete
353
+ end
342
354
  end