linecook-gem 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: daf691a1760137d1407850c46df82f52f30ab117
4
- data.tar.gz: 830e47b2c9d7267c1f362a62ed214b78512e2185
3
+ metadata.gz: 45514052292ba7f0031994394b15c5dab5447226
4
+ data.tar.gz: 94fdd52fe12e1c6720313ba221c3d9233a346c2c
5
5
  SHA512:
6
- metadata.gz: d5cbe11357a3fa8ea4bae785803da3548e2aebfc30d2a5616ea4403ffb6a3d9b5b349cf38b63129ee4698fa9f6fdaa3bf32a5ee4b431ee63dca6c0906c2b14cd
7
- data.tar.gz: d51d2a394fdd2af2a07e9ba70aef43102f305dfadc9843da66f2bdc2bd5aed650673eb79a833a6b63a55ea8d79cab418e23bbb16a3e6bbd75c34549c9c816dbe
6
+ metadata.gz: 131abec9715038d78fcd107060b77d13e62fef657f60d0471d045cd023aac2fa230e5a84c5bee4c0df68fecb02f080e7521a45e01a4cb9299aeb4a7439bc5d6c
7
+ data.tar.gz: 12ea95edd61ea70c354aca1ed08d272da115a146d354ee4ccbb897dfe2469c8b86b58d2da39c050cf535ad15ec5c3886d7874e48bde4db22d2807dd258c67cd7
data/lib/linecook/bake.rb CHANGED
@@ -1,49 +1,21 @@
1
1
  require 'securerandom'
2
2
 
3
- require 'chef-provisioner'
4
- require 'chefdepartie'
5
-
6
3
  require 'linecook/build'
4
+ require 'linecook/chef'
7
5
 
8
6
  module Linecook
9
7
  module Baker
10
8
  extend self
11
9
 
12
10
  def bake
13
- chef_config = setup
14
- script = ChefProvisioner::Bootstrap.generate(
15
- node_name: chef_config[:node_name],
16
- chef_version: chef_config[:version] || nil,
17
- first_boot: {
18
- run_list: chef_config[:run_list]
19
- }
20
- )
21
-
22
- puts "Establishing connection to build..."
23
- build = Linecook::Build.new('test', 'ubuntu-base.squashfs')
24
- build.start
25
- build.ssh.forward(chef_port)
26
- build.ssh.upload(script, '/tmp/chef_bootstrap')
27
- build.ssh.run('sudo bash /tmp/chef_bootstrap')
28
- build.ssh.stop_forwarding
29
- end
30
-
31
- private
32
-
33
- def setup
34
- ChefProvisioner::Config.setup(client: 'linecook', listen: 'localhost')
35
- config = Linecook::Config.load_config
36
-
37
- chef_config = config[:chef]
38
- chef_config.merge!(node_name: "linecook-#{SecureRandom.uuid}",
39
- chef_server_url: ChefProvisioner::Config.server)
40
- # FIXME: sort out cache copying here for concurrent builds of different refs
41
- Chefdepartie.run(background: true, config: chef_config, cache: '/tmp/linecook-cache')
42
- chef_config
43
- end
44
-
45
- def chef_port
46
- ChefProvisioner::Config.server.split(':')[-1].to_i
11
+ provisioner = 'chef' # FIXME HACK - read from config instead
12
+ build = Linecook::Build.new('test', 'ubuntu-base.squashfs') # FIXME - HACK, read from config
13
+ case provisioner
14
+ when 'chef'
15
+ Linecook::Chef.provision(build)
16
+ else
17
+ fail "Unsupported provisioner #{provisioner}"
18
+ end
47
19
  end
48
20
  end
49
21
  end
@@ -15,7 +15,7 @@ module Linecook
15
15
  end
16
16
 
17
17
  def ssh
18
- @ssh ||= Linecook::SSH.new(@container.ip, username: 'ubuntu', password: 'ubuntu', proxy: Linecook::Builder.ssh)
18
+ @ssh ||= Linecook::SSH.new(@container.ip, username: 'ubuntu', password: 'ubuntu', proxy: Linecook::Builder.ssh, keyfile: Linecook::Builder.pemfile)
19
19
  end
20
20
  end
21
21
  end
@@ -29,6 +29,7 @@ module Linecook
29
29
  extend Forwardable
30
30
  BUILD_HOME = '/u/lxc'
31
31
 
32
+ attr_reader :pemfile
32
33
  def_instance_delegators :backend, :stop, :ip, :info, :running?
33
34
 
34
35
  def backend
@@ -43,7 +44,17 @@ module Linecook
43
44
 
44
45
  def ssh
45
46
  config = Linecook::Config.load_config[:builder]
46
- @ssh ||= SSH.new(ip, username: config[:username], password: config[:password])
47
+ @ssh ||= begin
48
+ userkey = File.expand_path("~/.ssh/id_rsa")
49
+ dedicated_key = File.join(Linecook::Config::LINECOOK_HOME, 'linecook_ssh.pem')
50
+ unless File.exists?(dedicated_key)
51
+ File.write(dedicated_key, SSHKey.generate.private_key)
52
+ FileUtils.chmod(0600, dedicated_key)
53
+ end
54
+ @pemfile = File.exists?(userkey) ? userkey : dedicated_key
55
+ puts @pemfile
56
+ SSH.new(ip, username: config[:username], password: config[:password], keyfile: @pemfile)
57
+ end
47
58
  end
48
59
 
49
60
  def builds
@@ -61,7 +72,8 @@ module Linecook
61
72
  private
62
73
 
63
74
  def setup_ssh
64
- pubkey = SSHKey.new(File.read(File.expand_path("~/.ssh/id_rsa"))).ssh_public_key
75
+ ssh
76
+ pubkey = SSHKey.new(File.read(@pemfile)).ssh_public_key
65
77
  config = Linecook::Config.load_config[:builder]
66
78
  ssh.run("mkdir -p /home/#{config[:username]}/.ssh")
67
79
  ssh.upload(pubkey, "/home/#{config[:username]}/.ssh/authorized_keys")
@@ -0,0 +1,107 @@
1
+ require 'tmpdir'
2
+ require 'fileutils'
3
+
4
+ require 'chef-provisioner'
5
+ require 'chefdepartie'
6
+
7
+ module Linecook
8
+ module Chef
9
+ extend self
10
+
11
+ def provision(build)
12
+ chef_config = setup
13
+ script = ChefProvisioner::Bootstrap.generate(
14
+ node_name: chef_config[:node_name],
15
+ chef_version: chef_config[:version] || nil,
16
+ first_boot: {
17
+ run_list: chef_config[:run_list]
18
+ }
19
+ )
20
+
21
+ puts "Establishing connection to build..."
22
+ build.start
23
+ build.ssh.forward(chef_port)
24
+ build.ssh.upload(script, '/tmp/chef_bootstrap')
25
+ build.ssh.run('sudo bash /tmp/chef_bootstrap')
26
+ build.ssh.stop_forwarding
27
+ end
28
+
29
+ private
30
+
31
+ def setup
32
+ ChefProvisioner::Config.setup(client: 'linecook', listen: 'localhost')
33
+ config = Linecook::Config.load_config
34
+
35
+ chef_config = config[:chef]
36
+ chef_config.merge!(node_name: "linecook-#{SecureRandom.uuid}",
37
+ chef_server_url: ChefProvisioner::Config.server)
38
+ # FIXME: sort out cache copying here for concurrent builds of different refs
39
+ Chefdepartie.run(background: true, config: chef_config, cache: Cache.path)
40
+ chef_config
41
+ end
42
+
43
+ def chef_port
44
+ ChefProvisioner::Config.server.split(':')[-1].to_i
45
+ end
46
+
47
+ # Required in order to have multiple builds run on different refs
48
+ module Cache
49
+ CACHE_PATH = File.join(Linecook::Config::LINECOOK_HOME, 'chefcache').freeze
50
+ PIDFILE = File.join(CACHE_PATH, 'pid')
51
+ STAMPFILE = File.join(CACHE_PATH, 'stamp')
52
+ STALE_THRESHOLD = 86400 # one day in seconds
53
+
54
+ extend self
55
+
56
+ def path
57
+ cache_path = Dir.mktmpdir
58
+ build
59
+ copy(cache_path)
60
+ cache_path
61
+ end
62
+
63
+ private
64
+
65
+ def copy(cache_path)
66
+ FileUtils.copy_entry(CACHE_PATH, cache_path, preserve: true)
67
+ end
68
+
69
+ def build
70
+ if stale
71
+ puts 'Regenerating cookbook cache'
72
+ Chefdepartie.run(background: true, config: Linecook::Config.load_config[:chef], cache: CACHE_PATH)
73
+ Chefdepartie.stop
74
+ write_stamp
75
+ unlock
76
+ end
77
+ end
78
+
79
+ def stale
80
+ return false if locked?
81
+ lock
82
+ old?
83
+ end
84
+
85
+ def locked?
86
+ File.exists?(PIDFILE) && (true if Process.kill(0, File.read(PIDFILE)) rescue false)
87
+ end
88
+
89
+ def lock
90
+ File.write(PIDFILE, Process.pid)
91
+ end
92
+
93
+ def unlock
94
+ FileUtils.rm_f(PIDFILE)
95
+ end
96
+
97
+ def old?
98
+ return true unless File.exists?(STAMPFILE)
99
+ (Time.now.to_i - File.read(STAMPFILE).to_i) > STALE_THRESHOLD
100
+ end
101
+
102
+ def write_stamp
103
+ File.write(STAMPFILE, Time.now.to_i)
104
+ end
105
+ end
106
+ end
107
+ end
data/lib/linecook/lxc.rb CHANGED
@@ -7,6 +7,7 @@ require 'ipaddress'
7
7
  module Linecook
8
8
  module Lxc
9
9
  class Container
10
+ MAX_WAIT = 60
10
11
  attr_reader :config
11
12
  def initialize(name: 'linecook', home: '/u/lxc', image: nil, remote: :local)
12
13
  @remote = remote == :local ? false : remote
@@ -24,7 +25,7 @@ module Linecook
24
25
  mount_all
25
26
  write_config
26
27
  execute("lxc-start #{container_str} -d")
27
- # wait_running # FIXME - poll until it's running, or we can reach a race condition
28
+ wait_running
28
29
  # Don't start a cgmanager if we're already in a container
29
30
  execute('[ -f /etc/init/cgmanager.conf ] && sudo status cgmanager | grep -q running && sudo stop cgmanager || true') if lxc?
30
31
  setup_bridge unless @remote
@@ -68,12 +69,17 @@ module Linecook
68
69
 
69
70
  private
70
71
 
72
+ def wait_running
73
+ wait_for { running? }
74
+ end
71
75
  def wait_ssh
72
- running = false
73
- max_attempts = 60
76
+ wait_for { capture("lxc-attach -n #{@name} -P #{@home} status ssh || true") =~ /running/ }
77
+ end
78
+
79
+ def wait_for
74
80
  attempts = 0
75
- until running || attempts > max_attempts
76
- break if capture("lxc-attach -n #{@name} -P #{@home} status ssh") =~ /running/
81
+ until attempts > MAX_WAIT
82
+ break if yield
77
83
  attempts += 1
78
84
  sleep(1)
79
85
  end
data/lib/linecook/ssh.rb CHANGED
@@ -50,10 +50,11 @@ module Linecook
50
50
  class SSH
51
51
 
52
52
  attr_reader :username, :hostname
53
- def initialize(hostname, username: 'ubuntu', password: nil, proxy: nil)
53
+ def initialize(hostname, username: 'ubuntu', password: nil, keyfile: nil, proxy: nil)
54
54
  @username = username
55
55
  @password = password
56
56
  @hostname = hostname
57
+ @keyfile = keyfile
57
58
  @proxy = proxy_command(proxy) if proxy
58
59
  end
59
60
 
@@ -110,16 +111,18 @@ module Linecook
110
111
 
111
112
  def linecook_host
112
113
  @host ||= begin
113
-
114
114
  host = SSHKit::Host.new(user: @username, hostname: @hostname)
115
115
  host.password = @password if @password
116
- host.ssh_options = { proxy: @proxy } if @proxy
116
+ opts = {}
117
+ opts.merge!({ proxy: @proxy }) if @proxy
118
+ opts.merge!({ keys: [@keyfile], auth_methods: %w(publickey password) }) if @keyfile
119
+ host.ssh_options = opts
117
120
  host
118
121
  end
119
122
  end
120
123
 
121
124
  def proxy_command(proxy)
122
- ssh_command = "ssh #{proxy.username}@#{proxy.hostname} nc %h %p"
125
+ ssh_command = "ssh #{"-i #{@keyfile}" if @keyfile} #{proxy.username}@#{proxy.hostname} nc %h %p"
123
126
  Net::SSH::Proxy::Command.new(ssh_command)
124
127
  end
125
128
  end
@@ -1,3 +1,3 @@
1
1
  module Linecook
2
- VERSION = '0.0.1'
2
+ VERSION = '0.0.2'
3
3
  end
data/man/LINECOOK.1 CHANGED
@@ -7,7 +7,7 @@ linecook \- system image builder
7
7
  linecook help [\fB\fCCOMMAND\fR]\- for specific command help
8
8
  .SH DESCRIPTION
9
9
  .PP
10
- Linecook
10
+ Linecook builds system images utilizing overlayfs, squashfs, and linux containers via LXC. Currently, linecook only natively supports chef for provisioning, but using packer with a null resource, any of the mechanisms supported by packer are also supported by linecook.
11
11
  .SH CONFIGURATION
12
12
  .PP
13
13
  Describe config file here once it's been determined
@@ -44,6 +44,13 @@ Linux 3.19 or greater with support for cgroups, and netfilter as described by lx
44
44
  OS X 10.10 or later (Hypervisor.framework required for Xhyve)
45
45
  .RE
46
46
  .SH QUIRKS
47
+ .SS Xhyve
48
+ .RS
49
+ .IP \(bu 2
50
+ Xhyve requires root privileges until
51
+ \[la]https://github.com/mist64/xhyve/issues/60\[ra] is resolved. Linecook will setuid on the xhyve binary.
52
+ .RE
53
+ .SS Overlayfs
47
54
  .RS
48
55
  .IP \(bu 2
49
56
  Overlayfs doesn't support unix domain sockets (yet), so anything using a unix domain socket outside of the /run tree should do manually symlink to /run.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: linecook-gem
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Hamel
@@ -205,6 +205,7 @@ files:
205
205
  - lib/linecook/bake.rb
206
206
  - lib/linecook/build.rb
207
207
  - lib/linecook/builder.rb
208
+ - lib/linecook/chef.rb
208
209
  - lib/linecook/cli.rb
209
210
  - lib/linecook/config.rb
210
211
  - lib/linecook/darwin_backend.rb
@@ -239,4 +240,3 @@ signing_key:
239
240
  specification_version: 4
240
241
  summary: Build system images using chef zero, LXC, and packer
241
242
  test_files: []
242
- has_rdoc: