testlab 0.4.16 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/tl CHANGED
@@ -341,10 +341,14 @@ command :container do |c|
341
341
  c.desc 'Open an SSH console to a container'
342
342
  c.command :ssh do |ssh|
343
343
 
344
- ssh.desc 'Username'
344
+ ssh.desc 'Specify an SSH Username to use'
345
345
  ssh.arg_name 'username'
346
346
  ssh.flag [:u, :user]
347
347
 
348
+ ssh.desc 'Specify an SSH Identity Key to use'
349
+ ssh.arg_name 'key'
350
+ ssh.flag [:k, :key]
351
+
348
352
  ssh.action do |global_options, options, args|
349
353
  help_now!('id is required') if options[:id].nil?
350
354
 
@@ -353,6 +357,7 @@ command :container do |c|
353
357
 
354
358
  ssh_options = Hash.new
355
359
  ssh_options[:user] = options[:user]
360
+ ssh_options[:keys] = options[:key]
356
361
 
357
362
  container.ssh(ssh_options).console
358
363
  end
@@ -20,24 +20,18 @@ class TestLab
20
20
 
21
21
  self.lxc.create(*create_args)
22
22
 
23
- # TODO: This needs to really go somewhere else:
24
- home_dir = ((self.node.user == "root") ? %(/root) : %(/home/#{self.node.user}))
25
- container_home_dir = File.join(self.lxc.fs_root, "/home/ubuntu")
26
-
27
- home_authkeys = File.join(home_dir, ".ssh", "authorized_keys")
28
- container_authkeys = File.join(container_home_dir, ".ssh", "authorized_keys")
29
- container_authkeys2 = File.join(container_home_dir, ".ssh", "authorized_keys2")
30
-
31
- authkeys = {
32
- home_authkeys => container_authkeys,
33
- home_authkeys => container_authkeys2
34
- }
35
-
36
- self.node.ssh.exec(%(mkdir -pv #{File.join(container_home_dir, %(.ssh))}))
37
- authkeys.each do |source, destination|
38
- self.node.ssh.exec(%(sudo cp -v #{source} #{destination}))
39
- self.node.ssh.exec(%(sudo chown -v 1000:1000 #{destination}))
40
- self.node.ssh.exec(%(sudo chmod -v 644 #{destination}))
23
+ # Ensure the container APT calls use apt-cacher-ng on the node
24
+ gateway_ip = self.primary_interface.network.ip
25
+ apt_conf_d_proxy_file = File.join(self.lxc.fs_root, "etc", "apt", "apt.conf.d", "02proxy")
26
+ self.node.ssh.exec(%(sudo mkdir -pv #{File.dirname(apt_conf_d_proxy_file)}))
27
+ self.node.ssh.exec(%(echo 'Acquire::http { Proxy "http://#{gateway_ip}:3142"; };' | sudo tee #{apt_conf_d_proxy_file}))
28
+
29
+ # Fix the APT sources since LXC mudges them when using apt-cacher-ng
30
+ apt_conf_sources_file = File.join(self.lxc.fs_root, "etc", "apt", "sources.list")
31
+ self.node.ssh.exec(%(sudo sed -i 's/127.0.0.1:3142\\///g' #{apt_conf_sources_file}))
32
+
33
+ self.users.each do |u|
34
+ u.create
41
35
  end
42
36
 
43
37
  end
@@ -81,8 +75,10 @@ class TestLab
81
75
 
82
76
  (self.lxc.state != :running) and raise ContainerError, "The container failed to online!"
83
77
 
84
- # TODO: This needs to really go somewhere else:
85
- self.lxc.attach(%(-- /bin/bash -c 'grep "sudo\tALL=\(ALL:ALL\) ALL" /etc/sudoers && sed -i "s/sudo\tALL=\(ALL:ALL\) ALL/sudo\tALL=\(ALL:ALL\) NOPASSWD: ALL/" /etc/sudoers'))
78
+ self.users.each do |u|
79
+ u.up
80
+ end
81
+
86
82
  end
87
83
 
88
84
  true
@@ -0,0 +1,32 @@
1
+ class TestLab
2
+ class Container
3
+
4
+ module User
5
+
6
+ # Container primary user
7
+ #
8
+ # Returns the primary user for the container. If the container has
9
+ # multiple users, this is based on which ever user is marked
10
+ # with the primary flag. If the container only has one user, then
11
+ # it is returned.
12
+ #
13
+ # @return [TestLab::User] The primary user for the container.
14
+ def primary_user
15
+ if self.users.count == 0
16
+ case self.distro.downcase
17
+ when 'ubuntu' then
18
+ TestLab::User.new "ubuntu" do
19
+ password 'ubuntu'
20
+ end
21
+ end
22
+ elsif self.users.any?{ |u| u.primary == true }
23
+ self.users.find{ |u| u.primary == true }
24
+ else
25
+ self.users.first
26
+ end
27
+ end
28
+
29
+ end
30
+
31
+ end
32
+ end
@@ -70,6 +70,7 @@ class TestLab
70
70
  autoload :MethodMissing, 'testlab/container/method_missing'
71
71
  autoload :SSH, 'testlab/container/ssh'
72
72
  autoload :Status, 'testlab/container/status'
73
+ autoload :User, 'testlab/container/user'
73
74
 
74
75
  include TestLab::Container::Actions
75
76
  include TestLab::Container::Generators
@@ -79,6 +80,7 @@ class TestLab
79
80
  include TestLab::Container::MethodMissing
80
81
  include TestLab::Container::SSH
81
82
  include TestLab::Container::Status
83
+ include TestLab::Container::User
82
84
 
83
85
  extend TestLab::Container::ClassMethods
84
86
 
@@ -87,16 +89,13 @@ class TestLab
87
89
  # Associations and Attributes
88
90
  belongs_to :node, :class_name => 'TestLab::Node'
89
91
  has_many :interfaces, :class_name => 'TestLab::Interface'
92
+ has_many :users, :class_name => 'TestLab::User'
90
93
 
91
94
  attribute :provisioner
92
95
  attribute :config, :default => Hash.new
93
96
 
94
97
  attribute :domain
95
98
 
96
- attribute :user, :default => 'ubuntu'
97
- attribute :passwd, :default => 'ubuntu'
98
- attribute :keys
99
-
100
99
  attribute :distro, :default => 'ubuntu'
101
100
  attribute :release, :default => 'precise'
102
101
  attribute :arch
@@ -30,9 +30,10 @@ class TestLab
30
30
  c.proxy_keys = @provider.identity
31
31
 
32
32
  c.host_name = container.ip
33
- c.user = (options[:user] || container.user)
34
- c.password = (options[:passwd] || container.passwd)
35
- c.keys = (options[:keys] || container.keys || @provider.identity)
33
+
34
+ c.user = (options[:user] || container.primary_user.id)
35
+ c.password = (options[:passwd] || container.primary_user.password)
36
+ c.keys = (options[:keys] || container.primary_user.keys || @provider.identity)
36
37
  end
37
38
  end
38
39
  @container_ssh[name]
@@ -2,11 +2,21 @@ set -x
2
2
 
3
3
  # Update APT and ensure our required packages are installed
4
4
  apt-get -y update
5
- apt-get -y install lxc bridge-utils debootstrap yum iptables ntpdate ntp
5
+ apt-get -y install lxc bridge-utils debootstrap yum iptables ntpdate ntp apt-cacher-ng
6
+
7
+ # Ensure APT Cache-NG is running
8
+ service apt-cacher-ng restart || service apt-cacher-ng start
9
+ cat <<EOF | tee /etc/apt/apt.conf.d/02proxy
10
+ Acquire::http { Proxy "http://127.0.0.1:3142"; };
11
+ EOF
6
12
 
7
13
  # Ensure the default lxc networking services are off
8
14
  service lxc-net stop
9
15
 
16
+ # Ensure that we use APT Cacher-NG for building containers
17
+ grep "^MIRROR" /etc/default/lxc || echo "MIRROR=\"http://127.0.0.1:3142/archive.ubuntu.com/ubuntu\"" | tee -a /etc/default/lxc
18
+ service lxc restart || service lxc start
19
+
10
20
  # Ensure NTP services are enabled and running
11
21
  service ntp restart || service ntp start
12
22
 
@@ -0,0 +1,69 @@
1
+ class TestLab
2
+ class User
3
+
4
+ module Actions
5
+
6
+ # Create the user
7
+ #
8
+ # @return [Boolean] True if successful.
9
+ def create
10
+ @ui.logger.debug { "User Create: #{self.id} " }
11
+
12
+ node_home_dir = ((self.container.node.user == "root") ? %(/root) : %(/home/#{self.container.node.user}))
13
+ node_authkeys = File.join(node_home_dir, ".ssh", "authorized_keys")
14
+
15
+ user_home_dir = File.join(self.container.lxc.fs_root, ((self.id == "root") ? %(/root) : %(/home/#{self.id})))
16
+ user_authkeys = File.join(user_home_dir, ".ssh", "authorized_keys")
17
+ user_authkeys2 = File.join(user_home_dir, ".ssh", "authorized_keys2")
18
+
19
+ # ensure the container user exists
20
+ container_passwd_file = File.join(self.container.lxc.fs_root, "etc", "passwd")
21
+ if self.container.node.ssh.exec(%(sudo grep "#{self.id}" #{container_passwd_file}), :ignore_exit_status => true).exit_code != 0
22
+
23
+ if !self.gid.nil?
24
+ groupadd_command = %(groupadd --gid #{self.gid} #{self.id})
25
+ self.container.node.ssh.exec(%(sudo chroot #{self.container.lxc.fs_root} /bin/bash -c '#{groupadd_command}'))
26
+ end
27
+
28
+ useradd_command = %W(useradd --create-home --shell /bin/bash --groups sudo --password #{self.password})
29
+ useradd_command << "--uid #{self.uid}" if !self.uid.nil?
30
+ useradd_command << "--gid #{self.gid}" if !self.gid.nil?
31
+ useradd_command << self.id
32
+ useradd_command = useradd_command.flatten.compact.join(' ')
33
+
34
+ self.container.node.ssh.exec(%(sudo chroot #{self.container.lxc.fs_root} /bin/bash -c '#{useradd_command}'))
35
+ end
36
+
37
+ # ensure the user user gets our node user key
38
+ authkeys = {
39
+ node_authkeys => user_authkeys,
40
+ node_authkeys => user_authkeys2
41
+ }
42
+
43
+ authkeys.each do |source, destination|
44
+ self.container.node.ssh.exec(%(sudo mkdir -pv #{File.dirname(destination)}))
45
+ self.container.node.ssh.exec(%(sudo cp -v #{source} #{destination}))
46
+ self.container.node.ssh.exec(%(sudo chmod -v 644 #{destination}))
47
+ end
48
+
49
+ true
50
+ end
51
+
52
+ # Up the user
53
+ #
54
+ # @return [Boolean] True if successful.
55
+ def up
56
+ @ui.logger.debug { "User Up: #{self.id}" }
57
+
58
+ # ensure the container user home directory is owned by them
59
+ home_dir = self.container.lxc.attach(%(-- /bin/bash -c 'grep #{self.id} /etc/passwd | cut -d ":" -f6')).strip
60
+ self.container.lxc.attach(%(-- /bin/bash -c 'sudo chown -Rv $(id -u #{self.id}):$(id -g #{self.id}) #{home_dir}'))
61
+
62
+ # ensure the sudo user group can do passwordless sudo
63
+ self.container.lxc.attach(%(-- /bin/bash -c 'grep "sudo\tALL=\(ALL:ALL\) ALL" /etc/sudoers && sed -i "s/sudo\tALL=\(ALL:ALL\) ALL/sudo\tALL=\(ALL:ALL\) NOPASSWD: ALL/" /etc/sudoers'))
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,35 @@
1
+ class TestLab
2
+
3
+ # User Error Class
4
+ class UserError < TestLabError; end
5
+
6
+ # User Class
7
+ #
8
+ # @author Zachary Patten <zachary AT jovelabs DOT com>
9
+ class User < ZTK::DSL::Base
10
+
11
+ # Sub-Modules
12
+ autoload :Actions, 'testlab/user/actions'
13
+
14
+ include TestLab::User::Actions
15
+
16
+ # Associations and Attributes
17
+ belongs_to :container, :class_name => 'TestLab::Container'
18
+
19
+ attribute :user
20
+ attribute :password
21
+ attribute :keys
22
+ attribute :uid
23
+ attribute :gid
24
+
25
+ attribute :primary, :default => false
26
+
27
+ def initialize(*args)
28
+ super(*args)
29
+
30
+ @ui = TestLab.ui
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -1,6 +1,6 @@
1
1
  class TestLab
2
2
  unless const_defined?(:VERSION)
3
3
  # TestLab Gem Version
4
- VERSION = "0.4.16"
4
+ VERSION = "0.5.0"
5
5
  end
6
6
  end
data/lib/testlab.rb CHANGED
@@ -93,6 +93,7 @@ class TestLab
93
93
  autoload :Node, 'testlab/node'
94
94
  autoload :Provider, 'testlab/provider'
95
95
  autoload :Provisioner, 'testlab/provisioner'
96
+ autoload :User, 'testlab/user'
96
97
  autoload :Utility, 'testlab/utility'
97
98
 
98
99
  include TestLab::Utility::Misc
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: testlab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.16
4
+ version: 0.5.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-05 00:00:00.000000000 Z
12
+ date: 2013-06-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: gli
@@ -217,6 +217,7 @@ files:
217
217
  - lib/testlab/container/method_missing.rb
218
218
  - lib/testlab/container/ssh.rb
219
219
  - lib/testlab/container/status.rb
220
+ - lib/testlab/container/user.rb
220
221
  - lib/testlab/interface.rb
221
222
  - lib/testlab/labfile.rb
222
223
  - lib/testlab/monkeys.rb
@@ -252,6 +253,8 @@ files:
252
253
  - lib/testlab/provisioners/shell.rb
253
254
  - lib/testlab/provisioners/templates/chef/omnibus.erb
254
255
  - lib/testlab/provisioners/templates/chef/omnitruck.erb
256
+ - lib/testlab/user.rb
257
+ - lib/testlab/user/actions.rb
255
258
  - lib/testlab/utility.rb
256
259
  - lib/testlab/utility/cidr.rb
257
260
  - lib/testlab/utility/misc.rb
@@ -282,7 +285,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
282
285
  version: '0'
283
286
  segments:
284
287
  - 0
285
- hash: -1044264548674071638
288
+ hash: -532232323948453701
286
289
  required_rubygems_version: !ruby/object:Gem::Requirement
287
290
  none: false
288
291
  requirements:
@@ -291,7 +294,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
291
294
  version: '0'
292
295
  segments:
293
296
  - 0
294
- hash: -1044264548674071638
297
+ hash: -532232323948453701
295
298
  requirements: []
296
299
  rubyforge_project:
297
300
  rubygems_version: 1.8.25