Class: Navo::Suite
- Inherits:
-
Object
- Object
- Navo::Suite
- Defined in:
- lib/navo/suite.rb
Overview
A test suite.
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Instance Method Summary collapse
- #[](key) ⇒ Object
- #busser_bin ⇒ Object
- #busser_directory ⇒ Object
- #busser_env ⇒ Object
- #chef_config_dir ⇒ Object
- #chef_run_dir ⇒ Object
- #chef_solo_config ⇒ Object
-
#container ⇒ Docker::Container
Returns the Docker::Container used by this test suite, starting it if necessary.
- #converge ⇒ Object
-
#copy(from:, to:) ⇒ Object
Copy file/directory from host to container.
- #create ⇒ Object
- #destroy ⇒ Object
-
#exec(args) ⇒ Object
Execte a command on the container.
-
#exec!(args) ⇒ Object
Execute a command on the container, raising an error if it exists unsuccessfully.
- #fetch(key, *args) ⇒ Object
-
#image ⇒ Docker::Image
Returns the Docker::Image used by this test suite, building it if necessary.
-
#initialize(name:, config:) ⇒ Suite
constructor
A new instance of Suite.
- #login ⇒ Object
- #node_attributes ⇒ Object
- #repo_root ⇒ Object
- #sandbox ⇒ Object
- #state ⇒ Object
- #storage_directory ⇒ Object
- #test ⇒ Object
- #verify ⇒ Object
-
#write(file:, content:) ⇒ Object
Write contents to a file on the container.
Constructor Details
#initialize(name:, config:) ⇒ Suite
Returns a new instance of Suite.
11 12 13 14 |
# File 'lib/navo/suite.rb', line 11 def initialize(name:, config:) @name = name @config = config end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
9 10 11 |
# File 'lib/navo/suite.rb', line 9 def name @name end |
Instance Method Details
#[](key) ⇒ Object
20 21 22 |
# File 'lib/navo/suite.rb', line 20 def [](key) @config[key.to_s] end |
#busser_bin ⇒ Object
213 214 215 |
# File 'lib/navo/suite.rb', line 213 def busser_bin File.join(busser_directory, %w[gems bin busser]) end |
#busser_directory ⇒ Object
209 210 211 |
# File 'lib/navo/suite.rb', line 209 def busser_directory '/tmp/busser' end |
#busser_env ⇒ Object
217 218 219 220 221 222 223 224 |
# File 'lib/navo/suite.rb', line 217 def busser_env %W[ BUSSER_ROOT=#{busser_directory} GEM_HOME=#{File.join(busser_directory, 'gems')} GEM_PATH=#{File.join(busser_directory, 'gems')} GEM_CACHE=#{File.join(busser_directory, %w[gems cache])} ] end |
#chef_config_dir ⇒ Object
28 29 30 |
# File 'lib/navo/suite.rb', line 28 def chef_config_dir '/etc/chef' end |
#chef_run_dir ⇒ Object
32 33 34 |
# File 'lib/navo/suite.rb', line 32 def chef_run_dir '/var/chef' end |
#chef_solo_config ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/navo/suite.rb', line 65 def chef_solo_config return " node_name \#{name.inspect}\n environment \#{@config['chef']['environment'].inspect}\n file_cache_path \#{File.join(chef_run_dir, 'cache').inspect}\n file_backup_path \#{File.join(chef_run_dir, 'backup').inspect}\n cookbook_path \#{File.join(chef_run_dir, 'cookbooks').inspect}\n data_bag_path \#{File.join(chef_run_dir, 'data_bags').inspect}\n environment_path \#{File.join(chef_run_dir, 'environments').inspect}\n role_path \#{File.join(chef_run_dir, 'roles').inspect}\n encrypted_data_bag_secret \#{File.join(chef_config_dir, 'encrypted_data_bag_secret').inspect}\n CONF\nend\n" |
#container ⇒ Docker::Container
Returns the Docker::Container used by this test suite, starting it if necessary.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/navo/suite.rb', line 171 def container @container ||= begin if state['container'] begin container = Docker::Container.get(state['container']) rescue Docker::Error::NotFoundError # Continue creating the container since it doesn't exist end end if !container container = Docker::Container.create( 'Image' => image.id, 'OpenStdin' => true, 'StdinOnce' => true, 'HostConfig' => { 'Privileged' => @config['docker']['privileged'], 'Binds' => @config['docker']['volumes'], }, ) state['container'] = container.id state.save end container.start end end |
#converge ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/navo/suite.rb', line 90 def converge create sandbox.update_chef_config _, _, status = exec(%W[ /opt/chef/embedded/bin/chef-solo --config=#{File.join(chef_config_dir, 'solo.rb')} --json-attributes=#{File.join(chef_config_dir, 'first-boot.json')} --force-formatter ]) state['converged'] = status == 0 state.save state['converged'] end |
#copy(from:, to:) ⇒ Object
Copy file/directory from host to container.
37 38 39 |
# File 'lib/navo/suite.rb', line 37 def copy(from:, to:) system("docker cp #{from} #{container.id}:#{to}") end |
#create ⇒ Object
86 87 88 |
# File 'lib/navo/suite.rb', line 86 def create container end |
#destroy ⇒ Object
121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/navo/suite.rb', line 121 def destroy if @config['docker']['stop-command'] exec(@config['docker']['stop-command']) container.wait(@config['docker'].fetch('stop-timeout', 10)) else container.stop end container.remove(force: true) state['converged'] = false state['container'] = nil state.save end |
#exec(args) ⇒ Object
Execte a command on the container.
47 48 49 50 51 |
# File 'lib/navo/suite.rb', line 47 def exec(args) container.exec(args) do |_stream, chunk| STDOUT.print chunk end end |
#exec!(args) ⇒ Object
Execute a command on the container, raising an error if it exists unsuccessfully.
55 56 57 58 59 |
# File 'lib/navo/suite.rb', line 55 def exec!(args) out, err, status = exec(args) raise Error::ExecutionError, "STDOUT:#{out}\nSTDERR:#{err}" unless status == 0 [out, err, status] end |
#fetch(key, *args) ⇒ Object
24 25 26 |
# File 'lib/navo/suite.rb', line 24 def fetch(key, *args) @config.fetch(key.to_s, *args) end |
#image ⇒ Docker::Image
Returns the Docker::Image used by this test suite, building it if necessary.
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/navo/suite.rb', line 140 def image @image ||= begin state['images'] ||= {} # Build directory is wherever the Dockerfile is located dockerfile = File.(@config['docker']['dockerfile'], repo_root) build_dir = File.dirname(dockerfile) dockerfile_hash = Digest::SHA256.new.hexdigest(File.read(dockerfile)) image_id = state['images'][dockerfile_hash] if image_id && Docker::Image.exist?(image_id) Docker::Image.get(image_id) else Docker::Image.build_from_dir(build_dir) do |chunk| if (log = JSON.parse(chunk)) && log.has_key?('stream') STDOUT.print log['stream'] end end.tap do |image| state['images'][dockerfile_hash] = image.id state.save end end end end |
#login ⇒ Object
61 62 63 |
# File 'lib/navo/suite.rb', line 61 def login Kernel.exec('docker', 'exec', '-it', container.id, *@config['docker']['shell-command']) end |
#node_attributes ⇒ Object
79 80 81 82 83 84 |
# File 'lib/navo/suite.rb', line 79 def node_attributes suite_config = @config['suites'][name] @config['chef']['attributes'] .merge(suite_config.fetch('attributes', {})) .merge(run_list: suite_config['run-list']) end |
#repo_root ⇒ Object
16 17 18 |
# File 'lib/navo/suite.rb', line 16 def repo_root @config.repo_root end |
#sandbox ⇒ Object
201 202 203 |
# File 'lib/navo/suite.rb', line 201 def sandbox @sandbox ||= Sandbox.new(suite: self) end |
#state ⇒ Object
226 227 228 |
# File 'lib/navo/suite.rb', line 226 def state @state ||= SuiteState.new(suite: self).tap(&:load) end |
#storage_directory ⇒ Object
205 206 207 |
# File 'lib/navo/suite.rb', line 205 def storage_directory File.join(repo_root, '.navo', 'suites', name) end |
#test ⇒ Object
116 117 118 119 |
# File 'lib/navo/suite.rb', line 116 def test return false unless converge verify end |
#verify ⇒ Object
107 108 109 110 111 112 113 114 |
# File 'lib/navo/suite.rb', line 107 def verify create sandbox.update_test_config _, _, status = exec(['/usr/bin/env'] + busser_env + %W[#{busser_bin} test]) status == 0 end |
#write(file:, content:) ⇒ Object
Write contents to a file on the container.
42 43 44 |
# File 'lib/navo/suite.rb', line 42 def write(file:, content:) container.exec(%w[bash -c] + ["cat > #{file}"], stdin: StringIO.new(content)) end |