Class: Binpkgbot::Container

Inherits:
Object
  • Object
show all
Defined in:
lib/binpkgbot/container.rb

Defined Under Namespace

Classes: ContainerFailure

Constant Summary collapse

COPY_TMPDIR =
"/.binpkgbot.copies"
WORKDIR =
"/.binpkgbot.work"
SHAREDIR =
"/.binpkgbot.share"
SHAREDIR_SRC =
File.expand_path("../../share", __dir__)

Instance Method Summary collapse

Constructor Details

#initialize(directory, ephemeral: true, binds: [], copies: [], env: {}, script:, config: nil) ⇒ Container

Returns a new instance of Container.



15
16
17
18
19
20
21
22
23
# File 'lib/binpkgbot/container.rb', line 15

def initialize(directory, ephemeral: true, binds: [], copies: [], env: {}, script:, config: nil)
  @directory = directory
  @ephemeral = ephemeral
  @env = env
  @binds = normalize_binds(binds)
  @copies = normalize_copies(copies)
  @script = script
  @config = config
end

Instance Method Details

#bindsObject



44
45
46
47
48
49
50
51
52
# File 'lib/binpkgbot/container.rb', line 44

def binds
  @binds + \
    normalize_binds(@config&.binds || []) + \
    @copies.map { |copy| {from: copy[:from], to: "/#{COPY_TMPDIR}-#{copy[:id]}", writable: false} } + \
    [
      {from: workdir, to: WORKDIR, writable: true},
      {from: SHAREDIR_SRC, to: SHAREDIR, writable: false},
    ]
end

#command_lineObject



54
55
56
57
58
59
60
61
62
63
# File 'lib/binpkgbot/container.rb', line 54

def command_line
  [
    @config.use_sudo_for_nspawn? ? 'sudo' : nil,
    'systemd-nspawn',
    "--directory=#{@directory}",
    @ephemeral ? "--ephemeral" : nil,
    binds.map { |_| "--bind#{_[:writable] ? nil : '-ro'}=#{_[:from]}:#{_[:to]}" },
    '/bin/bash'
  ].flatten.compact
end

#run(error: true) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/binpkgbot/container.rb', line 65

def run(error: true)
  puts script.each_line.map.with_index { |_,i| _.strip.empty? ? nil : "#{(i.zero? ? "$ " : "  ")}#{_.chomp}" }.compact.join(?\n)
  r,w = IO.pipe
  w.puts script
  pid = spawn(*command_line, in: r)
  puts "--> #{command_line.shelljoin}"
  r.close
  w.close
  _, status = Process.waitpid2(pid)
  if error && !status.success?
    raise ContainerFailure, "container failed #{status.inspect}, #{command_line.inspect}"
  end
  status
end

#scriptObject



29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/binpkgbot/container.rb', line 29

def script
  parts = ['set -e']
  @copies.each do |copy| 
    parts.push "if [ -e \#{copy[:to].shellescape} ]; then\n  rm -rf \#{copy[:to].shellescape}\nfi\ncp -pr \#{COPY_TMPDIR}-\#{copy[:id]} \#{copy[:to].shellescape}\n    EOF\n  end\n  parts.push @env.map { |k, v| \"export \#{k}=\#{v.shellescape}\" }.join(\"\\n\")\n  parts << @script\n  parts.join(\"\\n\\n\")\nend\n"

#workdirObject



25
26
27
# File 'lib/binpkgbot/container.rb', line 25

def workdir
  @workdir ||= Pathname.new(Dir.mktmpdir)
end