testlab 0.4.16 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/bin/tl +6 -1
- data/lib/testlab/container/actions.rb +16 -20
- data/lib/testlab/container/user.rb +32 -0
- data/lib/testlab/container.rb +3 -4
- data/lib/testlab/node/ssh.rb +4 -3
- data/lib/testlab/node/templates/node-setup.erb +11 -1
- data/lib/testlab/user/actions.rb +69 -0
- data/lib/testlab/user.rb +35 -0
- data/lib/testlab/version.rb +1 -1
- data/lib/testlab.rb +1 -0
- metadata +7 -4
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
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
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
|
-
|
85
|
-
|
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
|
data/lib/testlab/container.rb
CHANGED
@@ -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
|
data/lib/testlab/node/ssh.rb
CHANGED
@@ -30,9 +30,10 @@ class TestLab
|
|
30
30
|
c.proxy_keys = @provider.identity
|
31
31
|
|
32
32
|
c.host_name = container.ip
|
33
|
-
|
34
|
-
c.
|
35
|
-
c.
|
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
|
data/lib/testlab/user.rb
ADDED
@@ -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
|
data/lib/testlab/version.rb
CHANGED
data/lib/testlab.rb
CHANGED
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
|
+
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-
|
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: -
|
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: -
|
297
|
+
hash: -532232323948453701
|
295
298
|
requirements: []
|
296
299
|
rubyforge_project:
|
297
300
|
rubygems_version: 1.8.25
|