-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8 from jameswnl/init-tower
Re-record vcr cassette and spec update, plus a script to generate Tower objects
- Loading branch information
Showing
5 changed files
with
16,257 additions
and
1,979 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
namespace :spec do | ||
desc "Populate expected Tower objects for casssettes and spec tests" | ||
task :populate_tower do | ||
tower_host = ENV['TOWER_URL'] || "https://dev-ansible-tower3.example.com/api/v1/" | ||
id = ENV['TOWER_USER'] || 'testuser' | ||
password = ENV['TOWER_PASSWORD'] || 'secret' | ||
PopulateTower.new(tower_host, id, password).create_dataset.counts | ||
end | ||
|
||
desc "Get counts of various Tower objects" | ||
task :tower_counts do | ||
tower_host = ENV['TOWER_URL'] || "https://dev-ansible-tower3.example.com/api/v1/" | ||
id = ENV['TOWER_USER'] || 'testuser' | ||
password = ENV['TOWER_PASSWORD'] || 'secret' | ||
PopulateTower.new(tower_host, id, password).counts | ||
end | ||
end | ||
|
||
class PopulateTower | ||
# This is to create a set of objects in Tower and the objects will be captured in a vcr cassette for | ||
# refresh spec tests. If we need to update the cassette, we can update/rerun this script to modify the objects | ||
# and so spec expectations can be updated (hopefully) easily | ||
# | ||
# It will print out object counts that are needed for the spec | ||
# Sample output on console | ||
# | ||
# === Re-creating Tower objects === | ||
# deleting old spec_test_org: /api/v1/organizations/39/ | ||
# Created name=spec_test_org manager_ref/ems_ref= 40 url=/api/v1/organizations/40/ | ||
# Created name=hello_scm_cred manager_ref/ems_ref= 136 url=/api/v1/credentials/136/ | ||
# Created name=hello_machine_cred manager_ref/ems_ref= 137 url=/api/v1/credentials/137/ | ||
# Created name=hello_aws_cred manager_ref/ems_ref= 138 url=/api/v1/credentials/138/ | ||
# Created name=hello_network_cred manager_ref/ems_ref= 139 url=/api/v1/credentials/139/ | ||
# Created name=hello_inventory manager_ref/ems_ref= 110 url=/api/v1/inventories/110/ | ||
# Created name=hello_vm manager_ref/ems_ref= 249 url=/api/v1/hosts/249/ | ||
# Created name=hello_repo manager_ref/ems_ref= 591 url=/api/v1/projects/591/ | ||
# deleting old hello_template: /api/v1/job_templates/589/ | ||
# Created name=hello_template manager_ref/ems_ref= 592 url=/api/v1/job_templates/592/ | ||
# deleting old hello_template_with_survey: /api/v1/job_templates/590/ | ||
# Created name=hello_template_with_survey manager_ref/ems_ref= 593 url=/api/v1/job_templates/593/ | ||
# created /api/v1/job_templates/593/ survey_spec | ||
# === Object counts === | ||
# configuration_script (job_templates) : 120 | ||
# configuration_script_source (projects) : 32 | ||
# configured_system (hosts) : 133 | ||
# inventory_group (inventories) : 29 | ||
# credential (credentials) : 47 | ||
# | ||
|
||
require "faraday" | ||
require 'faraday_middleware' | ||
|
||
def initialize(tower_host, id, password) | ||
@conn = Faraday.new(tower_host, :ssl => {:verify => false}) do |c| | ||
c.use(FaradayMiddleware::EncodeJson) | ||
c.use(FaradayMiddleware::FollowRedirects, :limit => 3, :standards_compliant => true) | ||
c.use Faraday::Response::RaiseError | ||
c.adapter(Faraday.default_adapter) | ||
c.basic_auth(id, password) | ||
end | ||
end | ||
|
||
def create_obj(uri, data) | ||
del_obj(uri, data['name']) | ||
obj = JSON.parse(@conn.post(uri, data).body) | ||
puts "%s %s %s" % ["Created name=#{obj['name']}".ljust(40), "manager_ref/ems_ref= #{obj['id']}".ljust(30), "url=#{obj['url']}".ljust(10)] | ||
obj | ||
end | ||
|
||
def del_obj(uri, match_name) | ||
data = JSON.parse(@conn.get(uri).body) | ||
data['results'].each do |item| | ||
next if item['name'] != match_name | ||
puts " deleting old #{item['name']}: #{item['url']}" | ||
resp = @conn.delete(item['url']) | ||
sleep(20) # without sleep, sometimes subsequent create will return 400. Seems the deletion has some delay in Tower | ||
resp | ||
end | ||
del_obj(data['next'], match_name) if data['next'] | ||
end | ||
|
||
def create_dataset | ||
puts "=== Re-creating Tower objects ===" | ||
# create test organization | ||
uri = '/api/v1/organizations/' | ||
data = {"name" => 'spec_test_org', "description" => "for miq spec tests"} | ||
organization = create_obj(uri, data) | ||
|
||
# create scm cred | ||
uri = '/api/v1/credentials/' | ||
data = {"name" => "hello_scm_cred", "kind" => "scm", "username" => "admin", "password" => "abc", "organization" => organization['id']} | ||
scm_credential = create_obj(uri, data) | ||
|
||
# create machine cred | ||
data = {"name" => "hello_machine_cred", "kind" => "ssh", "username" => "admin", "password" => "abc", "organization" => organization['id']} | ||
machine_credential = create_obj(uri, data) | ||
|
||
# create cloud aws cred | ||
data = {"name" => "hello_aws_cred", "kind" => "aws", "username" => "ABC", "password" => "abc", "organization" => organization['id']} | ||
aws_credential = create_obj(uri, data) | ||
|
||
# create network cred | ||
data = {"name" => "hello_network_cred", "kind" => "net", "username" => "admin", "password" => "abc", "organization" => organization['id']} | ||
network_credential = create_obj(uri, data) | ||
|
||
# create inventory | ||
uri = '/api/v1/inventories/' | ||
data = {"name" => "hello_inventory", "description" => "inventory for miq spec tests", "organization" => organization['id']} | ||
inventory = create_obj(uri, data) | ||
|
||
# create a host | ||
uri = '/api/v1/hosts/' | ||
data = {"name" => "hello_vm", "instance_id" => "4233080d-7467-de61-76c9-c8307b6e4830", "inventory" => inventory['id']} | ||
create_obj(uri, data) | ||
|
||
# create a project | ||
uri = '/api/v1/projects/' | ||
data = {"name" => 'hello_repo', "scm_url" => "https://github.com/jameswnl/ansible-examples", "scm_type" => "git", "credential" => scm_credential['id'], "organization" => organization['id']} | ||
project = create_obj(uri, data) | ||
|
||
# create a job_template | ||
uri = '/api/v1/job_templates/' | ||
data = {"name" => 'hello_template', "description" => "test job", "job_type" => "run", "project" => project['id'], "playbook" => "hello_world.yml", "credential" => machine_credential['id'], "cloud_credential" => aws_credential['id'], "network_credential" => network_credential['id'], "inventory" => inventory['id'], "organization" => organization['id']} | ||
create_obj(uri, data) | ||
|
||
# create a job_template with survey spec | ||
uri = '/api/v1/job_templates/' | ||
data = {"name" => "hello_template_with_survey", "description" => "test job with survey spec", "job_type" => "run", "project" => project['id'], "playbook" => "hello_world.yml", "credential" => machine_credential['id'], "inventory" => inventory['id'], "survey_enabled" => true, "organization" => organization['id']} | ||
template = create_obj(uri, data) | ||
# create survey spec | ||
uri = "/api/v1/job_templates/#{template['id']}/survey_spec/" | ||
data = {"name" => "Simple Survey", "description" => "Description of the simple survey", "spec" => [{"type" => "text", "question_name" => "example question", "question_description" => "What is your favorite color?", "variable" => "favorite_color", "required" => false, "default" => "blue"}]} | ||
@conn.post(uri, data).body | ||
puts "created #{template['url']} survey_spec" | ||
self | ||
end | ||
|
||
def counts | ||
puts "=== Object counts ===" | ||
targets = { | ||
'configuration_script' => 'job_templates', | ||
'configuration_script_source' => 'projects', | ||
'configured_system' => 'hosts', | ||
'inventory_group' => 'inventories', | ||
'credential' => 'credentials' | ||
} | ||
targets.each do |miq_name, tower_name| | ||
count = JSON.parse(@conn.get("/api/v1/#{tower_name}/").body)['count'] | ||
puts("%s %s: %s" % [miq_name.ljust(30), "(#{tower_name})".ljust(20), count]) | ||
end | ||
self | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,20 @@ | ||
|
||
shared_examples_for "ansible refresher" do |ansible_provider, manager_class, ems_type, cassette_path| | ||
# Maintaining cassettes for new specs | ||
# | ||
# Option #1 | ||
# ======== | ||
# Update: re-create expected set of Tower objects and re-record cassettes | ||
# 1. Modify the rake task lib/tasks_private/spec_helper.rake to modify the objects for new spec | ||
# 2. rake manageiq:providers:ansible_tower:populate_tower | ||
# (refer to the task doc for detail) | ||
# 2. remove the old cassette | ||
# 3. run the spec to create the cassette | ||
# 4. update the expectations | ||
# 5. change credentials in cassettes before commit | ||
# | ||
# Option #2 | ||
# ======== | ||
# To re-record cassettes or to add cassettes you can add another inner `VCR.use_cassette` block to the | ||
# 'will perform a full refresh' example. When running specs, new requests are recorded to the innermost cassette and | ||
# can be played back from any level of nesting (it tries the innermost cassette first, then searches up the parent | ||
|
@@ -16,7 +31,9 @@ | |
# * rm cassette ; run specs | ||
# * change back the order of cassettes | ||
# | ||
# To change credentials in cassettes: | ||
# | ||
# To change credentials in cassettes | ||
# ================================== | ||
# replace with defaults - before committing | ||
# ruby -pi -e 'gsub /yourdomain.com/, "example.com"; gsub /admin:smartvm/, "testuser:secret"' spec/vcr_cassettes/manageiq/providers/ansible_tower/automation_manager/*.yml | ||
# replace with your working credentials | ||
|
@@ -66,12 +83,8 @@ | |
2.times do | ||
# to re-record cassettes see comment at the beginning of this file | ||
VCR.use_cassette(cassette_path) do | ||
VCR.use_cassette("#{cassette_path}_configuration_script_sources") do | ||
VCR.use_cassette("#{cassette_path}_credentials") do | ||
EmsRefresh.refresh(automation_manager) | ||
expect(automation_manager.reload.last_refresh_error).to be_nil | ||
end | ||
end | ||
EmsRefresh.refresh(automation_manager) | ||
expect(automation_manager.reload.last_refresh_error).to be_nil | ||
end | ||
assert_counts | ||
assert_configured_system | ||
|
@@ -85,14 +98,14 @@ | |
end | ||
|
||
def assert_counts | ||
expect(Provider.count).to eq(1) | ||
expect(Provider.count).to eq(1) | ||
expect(automation_manager).to have_attributes(:api_version => "3.0.1") | ||
expect(automation_manager.configured_systems.count).to eq(84) | ||
expect(automation_manager.configuration_scripts.count).to eq(11) | ||
expect(automation_manager.inventory_groups.count).to eq(6) | ||
expect(automation_manager.configuration_script_sources.count).to eq(6) | ||
expect(automation_manager.configuration_script_payloads.count).to eq(438) | ||
expect(automation_manager.credentials.count).to eq(8) | ||
expect(automation_manager.configured_systems.count).to eq(130) | ||
expect(automation_manager.configuration_scripts.count).to eq(120) | ||
expect(automation_manager.inventory_groups.count).to eq(29) | ||
expect(automation_manager.configuration_script_sources.count).to eq(32) | ||
expect(automation_manager.configuration_script_payloads.count).to eq(2720) | ||
expect(automation_manager.credentials.count).to eq(47) | ||
end | ||
|
||
def assert_credentials | ||
|
@@ -101,67 +114,68 @@ def assert_credentials | |
:type => manager_class::MachineCredential | ||
) | ||
expect(machine_credential).to have_attributes( | ||
:name => "Demo Credential", | ||
:name => "hello_machine_cred", | ||
:userid => "admin", | ||
) | ||
expect(machine_credential.options.keys).to match_array(machine_credential.class::EXTRA_ATTRIBUTES.keys) | ||
expect(machine_credential.options[:become_method]).to eq('su') | ||
expect(machine_credential.options[:become_username]).to eq('root') | ||
expect(machine_credential.options[:become_method]).to eq('') | ||
expect(machine_credential.options[:become_username]).to eq('') | ||
|
||
network_credential = expected_configuration_script.authentications.find_by( | ||
:type => manager_class::NetworkCredential | ||
) | ||
expect(network_credential).to have_attributes( | ||
:name => "Demo Creds 2", | ||
:userid => "awdd", | ||
:name => "hello_network_cred", | ||
:userid => "admin", | ||
) | ||
expect(network_credential.options.keys).to match_array(network_credential.class::EXTRA_ATTRIBUTES.keys) | ||
|
||
cloud_credential = expected_configuration_script.authentications.find_by( | ||
:type => manager_class::VmwareCredential | ||
:type => manager_class::AmazonCredential | ||
) | ||
expect(cloud_credential).to have_attributes( | ||
:name => "dev-vc60", | ||
:userid => "[email protected]", | ||
:name => "hello_aws_cred", | ||
:userid => "ABC", | ||
) | ||
expect(cloud_credential.options.keys).to match_array(cloud_credential.class::EXTRA_ATTRIBUTES.keys) | ||
|
||
scm_credential = expected_configuration_script_source.authentication | ||
expect(scm_credential).to have_attributes( | ||
:name => "db-github", | ||
:userid => "syncrou" | ||
:name => "hello_scm_cred", | ||
:userid => "admin" | ||
) | ||
expect(scm_credential.options.keys).to match_array(scm_credential.class::EXTRA_ATTRIBUTES.keys) | ||
end | ||
|
||
def assert_playbooks | ||
expect(expected_configuration_script_source.configuration_script_payloads.first).to be_an_instance_of(manager_class::Playbook) | ||
expect(expected_configuration_script_source.configuration_script_payloads.count).to eq(8) | ||
expect(expected_configuration_script_source.configuration_script_payloads.map(&:name)).to include('start_ec2.yml') | ||
expect(expected_configuration_script_source.configuration_script_payloads.count).to eq(61) | ||
expect(expected_configuration_script_source.configuration_script_payloads.map(&:name)).to include('jboss-standalone/site.yml') | ||
end | ||
|
||
def assert_configuration_script_sources | ||
expect(automation_manager.configuration_script_sources.count).to eq(6) | ||
expect(automation_manager.configuration_script_sources.count).to eq(32) | ||
|
||
expect(expected_configuration_script_source).to be_an_instance_of(manager_class::ConfigurationScriptSource) | ||
expect(expected_configuration_script_source).to have_attributes( | ||
:name => 'DB_Github', | ||
:description => 'DB Playbooks', | ||
:name => 'hello_repo', | ||
:description => '', | ||
:scm_type => 'git', | ||
:scm_url => 'https://github.com/syncrou/playbooks', | ||
:scm_branch => 'master', | ||
:scm_url => 'https://github.com/jameswnl/ansible-examples', | ||
:scm_branch => '', | ||
:scm_clean => false, | ||
:scm_delete_on_update => false, | ||
:scm_update_on_launch => true, | ||
:scm_update_on_launch => false, | ||
:status => 'successful' | ||
) | ||
expect(expected_configuration_script_source.authentication.name).to eq('db-github') | ||
expect(expected_configuration_script_source.authentication.name).to eq('hello_scm_cred') | ||
end | ||
|
||
def assert_configured_system | ||
expect(expected_configured_system).to have_attributes( | ||
:type => manager_class::ConfiguredSystem.name, | ||
:hostname => "Ansible-Host", | ||
:manager_ref => "3", | ||
:hostname => "hello_vm", | ||
:manager_ref => "242", | ||
:virtual_instance_ref => "4233080d-7467-de61-76c9-c8307b6e4830", | ||
) | ||
expect(expected_configured_system.counterpart).to eq(expected_counterpart_vm) | ||
|
@@ -170,53 +184,53 @@ def assert_configured_system | |
|
||
def assert_configuration_script_with_nil_survey_spec | ||
expect(expected_configuration_script).to have_attributes( | ||
:description => "Ansible-JobTemplate-Description", | ||
:manager_ref => "80", | ||
:name => "Ansible-JobTemplate", | ||
:name => "hello_template", | ||
:description => "test job", | ||
:manager_ref => "571", | ||
:survey_spec => {}, | ||
:variables => {'abc' => 123}, | ||
:variables => {}, | ||
) | ||
expect(expected_configuration_script.inventory_root_group).to have_attributes(:ems_ref => "2") | ||
# expect(expected_configuration_script.inventory_root_group).to have_attributes(:ems_ref => "1") | ||
expect(expected_configuration_script.parent.name).to eq('hello_world.yml') | ||
expect(expected_configuration_script.parent.configuration_script_source.manager_ref).to eq('37') | ||
# expect(expected_configuration_script.parent.configuration_script_source.manager_ref).to eq('37') | ||
end | ||
|
||
def assert_configuration_script_with_survey_spec | ||
system = automation_manager.configuration_scripts.where(:name => "Ansible-JobTemplate-Survey").first | ||
system = automation_manager.configuration_scripts.where(:name => "hello_template_with_survey").first | ||
expect(system).to have_attributes( | ||
:name => "Ansible-JobTemplate-Survey", | ||
:description => "Ansible-JobTemplate-Description", | ||
:manager_ref => "81", | ||
:variables => {'abc' => 123} | ||
:name => "hello_template_with_survey", | ||
:description => "test job with survey spec", | ||
:manager_ref => "572", | ||
:variables => {} | ||
) | ||
survey = system.survey_spec | ||
expect(survey).to be_a Hash | ||
expect(survey['spec'].first['question_name']).to eq('Survey') | ||
expect(survey['spec'].first['question_name']).to eq('example question') | ||
end | ||
|
||
def assert_inventory_root_group | ||
expect(expected_inventory_root_group).to have_attributes( | ||
:name => "Dev-VC60", | ||
:ems_ref => "2", | ||
:name => "hello_inventory", | ||
:ems_ref => "103", | ||
:type => "ManageIQ::Providers::AutomationManager::InventoryRootGroup", | ||
) | ||
end | ||
|
||
private | ||
|
||
def expected_configured_system | ||
@expected_configured_system ||= automation_manager.configured_systems.where(:hostname => "Ansible-Host").first | ||
@expected_configured_system ||= automation_manager.configured_systems.where(:hostname => "hello_vm").first | ||
end | ||
|
||
def expected_configuration_script | ||
@expected_configuration_script ||= automation_manager.configuration_scripts.where(:name => "Ansible-JobTemplate").first | ||
@expected_configuration_script ||= automation_manager.configuration_scripts.where(:name => "hello_template").first | ||
end | ||
|
||
def expected_inventory_root_group | ||
@expected_inventory_root_group ||= automation_manager.inventory_groups.where(:name => "Dev-VC60").first | ||
@expected_inventory_root_group ||= automation_manager.inventory_groups.where(:name => "hello_inventory").first | ||
end | ||
|
||
def expected_configuration_script_source | ||
@expected_configuration_script_source ||= automation_manager.configuration_script_sources.find_by(:name => 'DB_Github') | ||
@expected_configuration_script_source ||= automation_manager.configuration_script_sources.find_by(:name => 'hello_repo') | ||
end | ||
end |
Oops, something went wrong.