diff --git a/README.md b/README.md index 05f1371..a94f980 100644 --- a/README.md +++ b/README.md @@ -103,7 +103,7 @@ $ cat ~/.fog ##### Setting up a new machine ```ruby -$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::abs --targets localhost action=provision platform=ubuntu-1604-x86_64 inventory=/Users/tp/workspace/git/provision/inventory.yaml +$ bundle exec bolt task run provision::abs --targets localhost action=provision platform=ubuntu-1604-x86_64 Started on localhost... Finished on localhost: @@ -118,7 +118,7 @@ Ran on 1 node in 1.44 seconds ##### Tearing down a finished machine ```ruby -$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::abs --targets localhost action=tear_down inventory=/Users/tp/workspace/git/provision/inventory.yaml node_name=yh6f4djvz7o3te6.delivery.puppetlabs.net +$ bundle exec bolt task run provision::abs --targets localhost action=tear_down node_name=yh6f4djvz7o3te6.delivery.puppetlabs.net Started on localhost... Finished on localhost: @@ -139,7 +139,7 @@ Containers by default will be managed in the current [docker context](https://do #### Provision ```ruby -$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 inventory=/Users/tp/workspace/git/provision/inventory.yaml +$ bundle exec bolt task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 Started on localhost... Finished on localhost: @@ -166,13 +166,13 @@ These defaults can be overriden by passing the flags with different values i.e. ``` ```ruby -bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 inventory=/Users/tp/workspace/git/provision/inventory.yaml vars='{ "docker_run_opts": ["-p 8086:8086", "-p 3000:3000"]}' +bundle exec bolt task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 vars='{ "docker_run_opts": ["-p 8086:8086", "-p 3000:3000"]}' ``` #### Tear down ```ruby -$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::docker --targets localhost action=tear_down inventory=/Users/tp/workspace/git/provision/inventory.yaml node_name=localhost:2222 +$ bundle exec bolt task run provision::docker --targets localhost action=tear_down node_name=localhost:2222 Started on localhost... Finished on localhost: @@ -197,7 +197,7 @@ Tested with vagrant images: provision ```ruby -$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::vagrant --targets localhost action=provision platform=ubuntu/xenial64 inventory=/Users/tp/workspace/git/provision/inventory.yaml +$ bundle exec bolt task run provision::vagrant --targets localhost action=provision platform=ubuntu/xenial64 Started on localhost... Finished on localhost: @@ -217,7 +217,7 @@ This leads to errors when anything tries to execute `puppet` commands on the tes To add the Puppet agent binary path to the *secure_path* please run the `provision::fix_secure_path` Bolt task: ```ruby -$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::fix_secure_path path=/opt/puppetlabs/bin -i inventory.yaml -t ssh_nodes +$ bundle exec bolt task run provision::fix_secure_path path=/opt/puppetlabs/bin -i inventory.yaml -t ssh_nodes Started on 127.0.0.1:2222... Finished on 127.0.0.1:2222: @@ -229,7 +229,7 @@ Ran on 1 target in 0.84 sec tear_down ```ruby -$ bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::vagrant --targets localhost action=tear_down inventory=/Users/tp/workspace/git/provision/inventory.yaml node_name=127.0.0.1:2222 +$ bundle exec bolt task run provision::vagrant --targets localhost action=tear_down node_name=127.0.0.1:2222 Started on localhost... Finished on localhost: @@ -284,7 +284,7 @@ In the provision step you can invoke bundle exec rake 'litmus:provision_list[tes Manual invocation of the provision service task from a workflow can be done using: ```ruby -bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::provision_service --targets localhost action=provision platform=centos-7-v20200813 inventory=/Users/tp/workspace/git/provision/inventory.yaml +bolt task run provision::provision_service --targets localhost action=provision platform=centos-7-v20200813 ``` Or using Litmus: @@ -320,7 +320,7 @@ provision ```powershell PS> $env:LITMUS_HYPERV_VSWITCH = 'internal_nat' -PS> bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::vagrant --targets localhost action=provision platform=centos/7 inventory=/Users/tp/workspace/git/provision/inventory.yaml hyperv_smb_username=tp hyperv_smb_password=notMyrealPassword +PS> bundle exec bolt task run provision::vagrant --targets localhost action=provision platform=centos/7 hyperv_smb_username=tp hyperv_smb_password=notMyrealPassword Started on localhost... Finished on localhost: @@ -353,7 +353,7 @@ Testing/development/debugging it is better to use ruby directly, you will need t Testing using bolt, the second step ```ruby -bundle exec bolt --modulepath /Users/tp/workspace/git/ task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 inventory=/Users/tp/workspace/git/provision/inventory.yaml +bundle exec bolt task run provision::docker --targets localhost action=provision platform=ubuntu:14.04 ``` ## License diff --git a/lib/docker_helper.rb b/lib/docker_helper.rb index d0c020a..b0c5d40 100644 --- a/lib/docker_helper.rb +++ b/lib/docker_helper.rb @@ -1,10 +1,9 @@ # frozen_string_literal: true require 'json' -require 'puppet_litmus' -def docker_exec(container, command) - run_local_command("docker exec #{container} #{command}") +def docker_exec(container_id, command) + run_local_command("docker exec #{container_id} #{command}") end def docker_image_os_release_facts(image) @@ -34,18 +33,9 @@ def docker_image_os_release_facts(image) os_release_facts end -def docker_tear_down(node_name, inventory_location) - extend PuppetLitmus::InventoryManipulation - inventory_full_path = File.join(inventory_location, '/spec/fixtures/litmus_inventory.yaml') - raise "Unable to find '#{inventory_full_path}'" unless File.file?(inventory_full_path) - - inventory_hash = inventory_hash_from_inventory_file(inventory_full_path) - node_facts = facts_from_node(inventory_hash, node_name) - remove_docker = "docker rm -f #{node_facts['container_id']}" - run_local_command(remove_docker) - remove_node(inventory_hash, node_name) - puts "Removed #{node_name}" - File.open(inventory_full_path, 'w') { |f| f.write inventory_hash.to_yaml } +def docker_tear_down(container_id) + run_local_command("docker rm -f #{container_id}") + puts "Removed #{container_id}" { status: 'ok' } end diff --git a/lib/inventory_helper.rb b/lib/inventory_helper.rb new file mode 100644 index 0000000..87a74bf --- /dev/null +++ b/lib/inventory_helper.rb @@ -0,0 +1,108 @@ +# frozen_string_literal: true + +require 'yaml' +require 'delegate' + +# simple bolt inventory manipulator +class InventoryHelper < SimpleDelegator + def initialize(location) + @location = location + super(refresh) + end + + # Load inventory from location in YAML format + # or generate a default structure + # + # @return [Hash] + def refresh + x = YAML.load_file(@location) if File.file?(@location) + { 'version' => 2, 'groups' => [] }.merge(x || {}) + end + + # Save inventory to location in yaml format + def save + File.open(@location, 'wb+') { |f| f.write(to_yaml) } + end + + # Adds a node to a group specified, if group_name exists in inventory hash. + # + # @param node [Hash] node to add to the group + # @param group [String] group of nodes to limit the search for the node_name in + # @return [Hash] inventory_hash with node added to group if group_name exists in inventory hash. + def add(node, group) + # check if group exists + if self['groups'].any? { |g| g['name'] == group } + self['groups'].each do |g| + g['targets'].push(node) if g['name'] == group + end + else + # add new group + self['groups'].push({ 'name' => group, 'targets' => [node] }) + end + + self + end + + # Lookup a node + # + # @param uri [String] uri of node to find + # @param name [String] name of node to find + # @param group [String] limit search to group + # @return [Hash] inventory target + def lookup(uri = nil, name: nil, group: nil) + value = uri || name + key = uri.nil? ? 'name' : 'uri' + + self['groups'].each do |g| + next unless (group && group == g['name']) || group.nil? + g['targets'].each do |t| + return t if t[key].eql? value + end + end + + # fallback lookup uri by name + return lookup(value, group: group) if uri.nil? + + raise "Failed to lookup target for #{key} #{value} in inventory #{inspect}" + end + + # Remove node + # + # @param node [Hash] + # @return [Hash] inventory_hash with node of node_name removed. + def remove(node) + self['groups'].map! do |g| + g['targets'].reject! { |target| target == node } + g + end + + self + end + + class << self + attr_accessor :instances + + def open(location = nil) + # Inventory location is an optional task parameter. + location = location.nil? ? Dir.pwd : location + location = if File.directory?(location) + # DEPRECATED: puppet_litmus <= 1.3.0 support + if Gem.loaded_specs['puppet_litmus'] && Gem.loaded_specs['puppet_litmus'].version <= Gem::Version.new('1.3.0') + File.join(location, 'spec', 'fixtures', 'litmus_inventory.yaml') + else + File.join(location, 'inventory.yaml') + end + else + location + end + + @instances ||= {} + @instances[location] = new(location) unless @instances.key? location + @instances[location] + end + end + + protected + + attr_accessor :location +end diff --git a/lib/task_helper.rb b/lib/task_helper.rb index af1aafe..0173e9d 100644 --- a/lib/task_helper.rb +++ b/lib/task_helper.rb @@ -1,29 +1,5 @@ # frozen_string_literal: true -def sanitise_inventory_location(location) - # Inventory location is an optional task parameter. - location = location.nil? ? Dir.pwd : location - # If not specified use the current directory + inventory.yaml - if File.exist?(location) && File.directory?(location) - # DEPRECATED: puppet_litmus <= 1.3.0 support - if Gem.loaded_specs['puppet_litmus'].version <= Gem::Version.new('1.3.0') - File.join(location, 'spec', 'fixtures', 'litmus_inventory.yaml') - else - File.join(location, 'inventory.yaml') - end - else - location - end -end - -def get_inventory_hash(inventory_full_path) - if File.file?(inventory_full_path) - inventory_hash_from_inventory_file(inventory_full_path) - else - { 'version' => 2, 'groups' => [{ 'name' => 'docker_nodes', 'targets' => [] }, { 'name' => 'ssh_nodes', 'targets' => [] }, { 'name' => 'winrm_nodes', 'targets' => [] }] } - end -end - def run_local_command(command, dir = Dir.pwd) require 'open3' stdout, stderr, status = Open3.capture3(command, chdir: dir) diff --git a/spec/tasks/provision_service_spec.rb b/spec/tasks/provision_service_spec.rb index 9e98d08..33d9c46 100644 --- a/spec/tasks/provision_service_spec.rb +++ b/spec/tasks/provision_service_spec.rb @@ -65,7 +65,7 @@ end describe '#provision' do - let(:inventory_location) { "#{Dir.pwd}/litmus_inventory.yaml" } + let(:inventory) { InventoryHelper.open("#{Dir.pwd}/litmus_inventory.yaml") } let(:vars) { nil } let(:platform) { 'centos-8' } let(:retry_attempts) { 8 } @@ -94,7 +94,7 @@ }, ) .to_return(status: 200, body: '', headers: {}) - expect { provision_service.provision(platform, inventory_location, vars, retry_attempts) }.to raise_error(RuntimeError) + expect { provision_service.provision(platform, inventory, vars, retry_attempts) }.to raise_error(RuntimeError) end end @@ -112,7 +112,7 @@ }, ) .to_return(status: 200, body: '', headers: {}) - expect { provision_service.provision(platform, inventory_location, vars, retry_attempts) }.to raise_error(RuntimeError) + expect { provision_service.provision(platform, inventory, vars, retry_attempts) }.to raise_error(RuntimeError) stub_request(:post, 'https://facade-release-6f3kfepqcq-ew.a.run.app/v1/provision') .with( body: '{"url":"https://api.github.com/repos/puppetlabs/puppetlabs-iis/actions/runs/1234567890","VMs":[{"cloud":null,"region":null,"zone":null,"images":["centos-8"]}]}', @@ -126,11 +126,11 @@ ) .to_return(status: 200, body: response_body.to_json, headers: {}) allow(File).to receive(:open) - expect(provision_service.provision(platform, inventory_location, vars, retry_attempts)[:status]).to eq('ok') + expect(provision_service.provision(platform, inventory, vars, retry_attempts)[:status]).to eq('ok') end end - context 'when response is avlid' do + context 'when response is valid' do it 'return valid response' do stub_request(:post, 'https://facade-release-6f3kfepqcq-ew.a.run.app/v1/provision') .with( @@ -146,7 +146,7 @@ .to_return(status: 200, body: response_body.to_json, headers: {}) allow(File).to receive(:open) - expect(provision_service.provision(platform, inventory_location, vars, retry_attempts)[:status]).to eq('ok') + expect(provision_service.provision(platform, inventory, vars, retry_attempts)[:status]).to eq('ok') end end end diff --git a/spec/unit/docker_helper_spec.rb b/spec/unit/docker_helper_spec.rb index 51a006e..4736766 100644 --- a/spec/unit/docker_helper_spec.rb +++ b/spec/unit/docker_helper_spec.rb @@ -81,19 +81,10 @@ end describe '.docker_tear_down' do - it 'expect to raise error if inventory file is not found' do - allow(File).to receive(:file?).and_return(false) - expect { docker_tear_down(container_id, inventory_location) }.to raise_error(RuntimeError, "Unable to find '#{inventory_location}/spec/fixtures/litmus_inventory.yaml'") - end - it 'expect to return status ok' do - allow(File).to receive(:file?).with(full_inventory_location).and_return(true) - allow(File).to receive(:exist?).with(full_inventory_location).and_return(true) - allow(File).to receive(:open).with(full_inventory_location, anything).and_yield(StringIO.new(inventory_yaml.dup)) allow(self).to receive(:run_local_command).with("docker rm -f #{container_id}") - allow(self).to receive(:remove_node).and_return(nil) expect { - expect(docker_tear_down(container_id, inventory_location)).to eql({ status: 'ok' }) + expect(docker_tear_down(container_id)).to eql({ status: 'ok' }) }.to output("Removed #{container_id}\n").to_stdout end end diff --git a/tasks/abs.json b/tasks/abs.json index ff4b1df..0b209f4 100644 --- a/tasks/abs.json +++ b/tasks/abs.json @@ -26,6 +26,7 @@ } }, "files": [ - "provision/lib/task_helper.rb" + "provision/lib/task_helper.rb", + "provision/lib/inventory_helper.rb" ] } diff --git a/tasks/abs.rb b/tasks/abs.rb index 122e895..61fd165 100755 --- a/tasks/abs.rb +++ b/tasks/abs.rb @@ -4,15 +4,13 @@ require 'json' require 'net/http' require 'yaml' -require 'puppet_litmus' require 'etc' require 'date' require_relative '../lib/task_helper' +require_relative '../lib/inventory_helper' # Provision and teardown vms through ABS. class ABSProvision - include PuppetLitmus::InventoryManipulation - # Enforces a k8s.infracore.puppet.net domain, but allows selection of prod, # stage, etc hostname from the environment variable +ABS_SUBDOMAIN+ so that # CI can test vms from staging. @@ -23,7 +21,7 @@ def abs_host "#{subdomain}.k8s.infracore.puppet.net" end - def provision(platform, inventory_location, vars) + def provision(platform, inventory, vars) uri = URI.parse("https://#{abs_host}/api/v2/request") jenkins_build_url = if ENV['CI'] == 'true' && ENV['TRAVIS'] == 'true' ENV.fetch('TRAVIS_JOB_WEB_URL', nil) @@ -85,7 +83,6 @@ def provision(platform, inventory_location, vars) raise "Timeout: unable to get a 200 response in #{poll_duration} seconds" if reply.code != '200' - inventory_hash = get_inventory_hash(inventory_location) data = JSON.parse(reply.body) data.each do |host| if platform_uses_ssh(host['type']) @@ -109,31 +106,27 @@ def provision(platform, inventory_location, vars) var_hash = YAML.safe_load(vars) node['vars'] = var_hash end - add_node_to_group(inventory_hash, node, group_name) + inventory.add(node, group_name) end - File.open(inventory_location, 'w') { |f| f.write inventory_hash.to_yaml } + inventory.save { status: 'ok', nodes: data.length } end - def tear_down(node_name, inventory_location) - if File.file?(inventory_location) - inventory_hash = inventory_hash_from_inventory_file(inventory_location) - facts = facts_from_node(inventory_hash, node_name) - platform = facts['platform'] - job_id = facts['job_id'] - end + def tear_down(node_name, inventory) + node = inventory.lookup(name: node_name, group: 'ssh_nodes') targets_to_remove = [] - inventory_hash['groups'].each do |group| - group['targets'].each do |node| - targets_to_remove.push(node['uri']) if node['facts']['job_id'] == job_id + inventory['groups'].each do |group| + group['targets'].each do |job_node| + targets_to_remove.push(job_node) if job_node['facts']['job_id'] == node['facts']['job_id'] end end + uri = URI.parse("https://#{abs_host}/api/v2/return") headers = { 'X-AUTH-TOKEN' => token_from_fogfile('abs'), 'Content-Type' => 'application/json' } - payload = { 'job_id' => job_id, - 'hosts' => [{ 'hostname' => node_name, 'type' => platform, 'engine' => 'vmpooler' }] } + payload = { 'job_id' => node['job_id'], + 'hosts' => [{ 'hostname' => node['uri'], 'type' => node['facts']['platform'], 'engine' => 'vmpooler' }] } http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true request = Net::HTTP::Post.new(uri.request_uri, headers) @@ -143,16 +136,17 @@ def tear_down(node_name, inventory_location) raise "Error: #{reply}: #{reply.message}" unless reply.code == '200' targets_to_remove.each do |target| - remove_node(inventory_hash, target) + inventory.remove(target) end - File.open(inventory_location, 'w') { |f| f.write inventory_hash.to_yaml } - { status: 'ok', removed: targets_to_remove } + inventory.save + + { status: 'ok', removed: targets_to_remove.map { |t| t['name'] || t['uri'] } } end def task(action:, platform: nil, node_name: nil, inventory: nil, vars: nil, **_kwargs) - inventory_location = sanitise_inventory_location(inventory) - result = provision(platform, inventory_location, vars) if action == 'provision' - result = tear_down(node_name, inventory_location) if action == 'tear_down' + inventory = InventoryHelper.open(inventory) + result = provision(platform, inventory, vars) if action == 'provision' + result = tear_down(node_name, inventory) if action == 'tear_down' result end diff --git a/tasks/docker.json b/tasks/docker.json index d14fe2c..8f2df56 100644 --- a/tasks/docker.json +++ b/tasks/docker.json @@ -27,6 +27,7 @@ }, "files": [ "provision/lib/task_helper.rb", - "provision/lib/docker_helper.rb" + "provision/lib/docker_helper.rb", + "provision/lib/inventory_helper.rb" ] } diff --git a/tasks/docker.rb b/tasks/docker.rb index a7d4ca5..f77dd2d 100755 --- a/tasks/docker.rb +++ b/tasks/docker.rb @@ -4,9 +4,9 @@ require 'json' require 'uri' require 'yaml' -require 'puppet_litmus' require_relative '../lib/task_helper' require_relative '../lib/docker_helper' +require_relative '../lib/inventory_helper' def install_ssh_components(distro, version, container) case distro @@ -119,9 +119,7 @@ def random_ssh_forwarding_port(start_port = 52_222, end_port = 52_999) random_ssh_forwarding_port(new_start_port, new_end_port) end -def provision(docker_platform, inventory_location, vars) - include PuppetLitmus::InventoryManipulation - inventory_hash = get_inventory_hash(inventory_location) +def provision(docker_platform, inventory, vars) os_release_facts = docker_image_os_release_facts(docker_platform) distro = os_release_facts['ID'] version = os_release_facts['VERSION_ID'] @@ -184,8 +182,7 @@ def provision(docker_platform, inventory_location, vars) inventory_node['name'] = container_id inventory_node['facts']['container_id'] = container_id - add_node_to_group(inventory_hash, inventory_node, 'ssh_nodes') - File.open(inventory_location, 'w') { |f| f.write inventory_hash.to_yaml } + inventory.add(inventory_node, 'ssh_nodes').save { status: 'ok', node_name: inventory_node['name'], node: inventory_node } end @@ -194,7 +191,7 @@ def provision(docker_platform, inventory_location, vars) platform = params['platform'] action = params['action'] node_name = params['node_name'] -inventory_location = sanitise_inventory_location(params['inventory']) +inventory = InventoryHelper.open(params['inventory']) vars = params['vars'] raise 'specify a node_name when tearing down' if action == 'tear_down' && node_name.nil? raise 'specify a platform when provisioning' if action == 'provision' && platform.nil? @@ -211,8 +208,12 @@ def provision(docker_platform, inventory_location, vars) end begin - result = provision(platform, inventory_location, vars) if action == 'provision' - result = docker_tear_down(node_name, inventory_location) if action == 'tear_down' + result = provision(platform, inventory, vars) if action == 'provision' + if action == 'tear_down' + node = inventory.lookup(name: node_name, group: 'ssh_nodes') + result = docker_tear_down(node['facts']['container_id']) + inventory.remove(node).save + end puts result.to_json exit 0 rescue StandardError => e diff --git a/tasks/docker_exp.json b/tasks/docker_exp.json index d14fe2c..8f2df56 100644 --- a/tasks/docker_exp.json +++ b/tasks/docker_exp.json @@ -27,6 +27,7 @@ }, "files": [ "provision/lib/task_helper.rb", - "provision/lib/docker_helper.rb" + "provision/lib/docker_helper.rb", + "provision/lib/inventory_helper.rb" ] } diff --git a/tasks/docker_exp.rb b/tasks/docker_exp.rb index f7888fc..b651da9 100755 --- a/tasks/docker_exp.rb +++ b/tasks/docker_exp.rb @@ -3,16 +3,14 @@ require 'json' require 'yaml' -require 'puppet_litmus' require_relative '../lib/task_helper' require_relative '../lib/docker_helper' +require_relative '../lib/inventory_helper' # TODO: detect what shell to use @shell_command = 'bash -lc' -def provision(docker_platform, inventory_location, vars) - include PuppetLitmus::InventoryManipulation - inventory_hash = get_inventory_hash(inventory_location) +def provision(docker_platform, inventory, vars) os_release_facts = docker_image_os_release_facts(docker_platform) inventory_node = { @@ -53,15 +51,14 @@ def provision(docker_platform, inventory_location, vars) inventory_node['uri'] = container_id inventory_node['facts']['container_id'] = container_id - add_node_to_group(inventory_hash, inventory_node, 'docker_nodes') - File.open(inventory_location, 'w') { |f| f.write inventory_hash.to_yaml } + inventory.add(inventory_node, 'docker_nodes').save { status: 'ok', node_name: inventory_node['name'], node: inventory_node } end params = JSON.parse($stdin.read) action = params['action'] -inventory_location = sanitise_inventory_location(params['inventory']) +inventory = InventoryHelper.open(params['inventory']) node_name = params['node_name'] platform = params['platform'] vars = params['vars'] @@ -80,11 +77,15 @@ def provision(docker_platform, inventory_location, vars) end begin - result = provision(platform, inventory_location, vars) if action == 'provision' - result = docker_tear_down(node_name, inventory_location) if action == 'tear_down' + result = provision(platform, inventory, vars) if action == 'provision' + if action == 'tear_down' + node = inventory.lookup(name: node_name, group: 'docker_nodes') + result = docker_tear_down(node['facts']['container_id']) + inventory.remove(node).save + end puts result.to_json exit 0 rescue StandardError => e - puts({ _error: { kind: 'provision/docker_exp_failure', msg: e.message } }.to_json) + puts({ _error: { kind: 'provision/docker_exp_failure', msg: e.message, backtrace: e.backtrace } }.to_json) exit 1 end diff --git a/tasks/provision_service.json b/tasks/provision_service.json index 584b182..d0c5c84 100644 --- a/tasks/provision_service.json +++ b/tasks/provision_service.json @@ -31,6 +31,7 @@ } }, "files": [ - "provision/lib/task_helper.rb" + "provision/lib/task_helper.rb", + "provision/lib/inventory_helper.rb" ] } diff --git a/tasks/provision_service.rb b/tasks/provision_service.rb index b5690da..d7eea61 100755 --- a/tasks/provision_service.rb +++ b/tasks/provision_service.rb @@ -4,16 +4,14 @@ require 'json' require 'net/http' require 'yaml' -require 'puppet_litmus' require 'etc' require_relative '../lib/task_helper' +require_relative '../lib/inventory_helper' # Provision and teardown vms through provision service. class ProvisionService RETRY_COUNT = 3 - include PuppetLitmus::InventoryManipulation - def default_uri 'https://facade-release-6f3kfepqcq-ew.a.run.app/v1/provision' end @@ -85,7 +83,7 @@ def invoke_cloud_request(params, uri, job_url, verb, retry_attempts) end end - def provision(platform, inventory_location, vars, retry_attempts) + def provision(platform, inventory, vars, retry_attempts) # Call the provision service with the information necessary and write the inventory file locally if ENV['GITHUB_RUN_ID'] @@ -119,27 +117,15 @@ def provision(platform, inventory_location, vars, retry_attempts) unless vars.nil? var_hash = YAML.safe_load(vars) - response_hash['groups'].each do |bg| - bg['targets'].each do |trgts| - trgts['vars'] = var_hash - end - end end - if File.file?(inventory_location) - inventory_hash = inventory_hash_from_inventory_file(inventory_location) - inventory_hash['groups'].each do |g| - response_hash['groups'].each do |bg| - g['targets'] = g['targets'] + bg['targets'] if g['name'] == bg['name'] - end - end - File.open(inventory_location, 'w') { |f| f.write inventory_hash.to_yaml } - else - FileUtils.mkdir_p(File.join(Dir.pwd, '/spec/fixtures')) - File.open(inventory_location, 'wb') do |f| - f.write(YAML.dump(response_hash)) + response_hash['groups'].each do |bg| + bg['targets'].each do |trgts| + trgts['vars'] = var_hash if var_hash + inventory.add(trgts, bg['name']) end end + inventory.save { status: 'ok', @@ -148,26 +134,22 @@ def provision(platform, inventory_location, vars, retry_attempts) } end - def tear_down(platform, inventory_location, _vars, retry_attempts) + def tear_down(node_name, inventory, _vars, retry_attempts) # remove all provisioned resources uri = URI.parse(ENV['SERVICE_URL'] || default_uri) - # rubocop:disable Style/GuardClause - if File.file?(inventory_location) - inventory_hash = inventory_hash_from_inventory_file(inventory_location) - facts = facts_from_node(inventory_hash, platform) - job_id = facts['uuid'] - response = invoke_cloud_request(job_id, uri, '', 'delete', retry_attempts) - response.to_json - end - # rubocop:enable Style/GuardClause + node = inventory.lookup(name: node_name) + facts = node['facts'] + job_id = facts['uuid'] + response = invoke_cloud_request(job_id, uri, '', 'delete', retry_attempts) + response.to_json end def self.run params = JSON.parse($stdin.read) params.transform_keys!(&:to_sym) action, node_name, platform, vars, retry_attempts, inventory_location = params.values_at(:action, :node_name, :platform, :vars, :retry_attempts, :inventory) - inventory_location = sanitise_inventory_location(inventory_location) + inventory = InventoryHelper.open(inventory_location) runner = new begin @@ -175,11 +157,11 @@ def self.run when 'provision' raise 'specify a platform when provisioning' if platform.to_s.empty? - result = runner.provision(platform, inventory_location, vars, retry_attempts) + result = runner.provision(platform, inventory, vars, retry_attempts) when 'tear_down' raise 'specify a node_name when tearing down' if node_name.nil? - result = runner.tear_down(node_name, inventory_location, vars, retry_attempts) + result = runner.tear_down(node_name, inventory, vars, retry_attempts) else result = { _error: { kind: 'provision_service/argument_error', msg: "Unknown action '#{action}'" } } end