Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create/Update/Delete Ansible Tower Projects and Credentials via queue #14305

Merged
merged 5 commits into from
Mar 14, 2017
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,68 @@ def create_in_provider(manager_id, params)
connection.api.projects.create!(params)
end

refresh(manager)
find_by!(:manager_id => manager.id, :manager_ref => project.id)
end

def create_in_provider_queue(manager_id, params)
manager = ExtManagementSystem.find(manager_id)
queue(manager.my_zone, nil, "create_in_provider", [manager_id, params], "Creating #{name}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The last argument will be logged when creating the Queue item. Can you change that to include the ems_ref for the project being created? Something like "Creating #{name} with name #{params['name']}" maybe...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@blomquisg name or manager_ref(the native Tower ID), or id (vmdb record ID), which one is better?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So ended up using name here because this object is not created yet. The update/delete are using manager_ref now. Done!

end

def provider_object(connection = nil)
(connection || connection_source.connect).api.projects.find(manager_ref)
end

private

def refresh(manager)
# Get the record in our database
# TODO: This needs to be targeted refresh so it doesn't take too long
task_ids = EmsRefresh.queue_refresh_task(manager)
task_ids.each { |tid| MiqTask.wait_for_taskid(tid) }

find_by!(:manager_id => manager.id, :manager_ref => project.id)
end

def create_in_provider_queue(manager_id, params)
def queue(zone, instance_id, method_name, args, action)
task_opts = {
:action => "Creating Ansible Tower Project",
:action => action,
:userid => "system"
}

manager = ExtManagementSystem.find(manager_id)

queue_opts = {
:args => [manager_id, params],
:class_name => "ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScriptSource",
:method_name => "create_in_provider",
:args => args,
:class_name => name,
:method_name => method_name,
:priority => MiqQueue::HIGH_PRIORITY,
:role => "ems_operations",
:zone => manager.my_zone
:zone => zone
}

queue_opts[:instance_id] = instance_id if instance_id
MiqTask.generic_action_with_callback(task_opts, queue_opts)
end
end

def provider_object(connection = nil)
(connection || connection_source.connect).api.projects.find(manager_ref)
def update_in_provider(params)
params.delete(:task_id) # in case this is being called through update_in_provider_queue which will stick in a :task_id
manager.with_provider_connection do |connection|
connection.api.projects.find(manager_ref).update_attributes!(params)
end
self.class.send('refresh', manager)
reload
end

def update_in_provider_queue(params)
self.class.send('queue', manager.my_zone, id, "update_in_provider", [params], "Updating #{self.class.name}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same basic comment. The "Updating ..." action should contain an ID for the thing being updated. If there's an error in updating, we'll want to know which one caused the problem.

end

def delete_in_provider
manager.with_provider_connection do |connection|
connection.api.projects.find(manager_ref).destroy!
end
self.class.send('refresh', manager)
end

def delete_in_provider_queue
self.class.send('queue', manager.my_zone, id, "delete_in_provider", [], "Deleting #{self.class.name}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end
end
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,64 @@ def create_in_provider(manager_id, params)
connection.api.credentials.create!(params)
end

refresh(manager)
find_by!(:resource_id => manager.id, :manager_ref => credential.id)
end

def create_in_provider_queue(manager_id, params)
manager = ExtManagementSystem.find(manager_id)
queue(manager.my_zone, nil, "create_in_provider", [manager_id, params], "Creating #{name}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end

private

def refresh(manager)
# Get the record in our database
# TODO: This needs to be targeted refresh so it doesn't take too long
task_ids = EmsRefresh.queue_refresh_task(manager)
task_ids.each { |tid| MiqTask.wait_for_taskid(tid) }

find_by!(:resource_id => manager.id, :manager_ref => credential.id)
end

def create_in_provider_queue(manager_id, params)
def queue(zone, instance_id, method_name, args, action)
task_opts = {
:action => "Creating #{name}",
:action => action,
:userid => "system"
}

manager = ExtManagementSystem.find(manager_id)

queue_opts = {
:args => [manager_id, params],
:args => args,
:class_name => name,
:method_name => "create_in_provider",
:method_name => method_name,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't work for the instance methods. You'll have to pass in the id of the current instance in order to have it look up the instance to call the method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See here:

# :instance_id (if using an instance method...an id)

Copy link
Contributor Author

@jameswnl jameswnl Mar 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes!!!
It was in my mind, and it slippppped...

:priority => MiqQueue::HIGH_PRIORITY,
:role => "ems_operations",
:zone => manager.my_zone
:zone => zone
}

queue_opts[:instance_id] = instance_id if instance_id
MiqTask.generic_action_with_callback(task_opts, queue_opts)
end
end

def update_in_provider(params)
params.delete(:task_id) # in case this is being called through update_in_provider_queue which will stick in a :task_id
resource.with_provider_connection do |connection|
connection.api.credentials.find(manager_ref).update_attributes!(params)
end
self.class.send('refresh', resource)
reload
end

def update_in_provider_queue(params)
self.class.send('queue', resource.my_zone, id, "update_in_provider", [params], "Updating #{self.class.name}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end

def delete_in_provider
resource.with_provider_connection do |connection|
connection.api.credentials.find(manager_ref).destroy!
end
self.class.send('refresh', resource)
end

def delete_in_provider_queue
self.class.send('queue', resource.my_zone, id, "delete_in_provider", [], "Deleting #{self.class.name}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

end
end
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
require 'ansible_tower_client'

describe ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScriptSource do
let(:finished_task) { FactoryGirl.create(:miq_task, :state => "Finished") }
let(:manager) { FactoryGirl.create(:provider_ansible_tower, :with_authentication).managers.first }
let(:atc) { double("AnsibleTowerClient::Connection", :api => api) }
let(:api) { double("AnsibleTowerClient::Api", :projects => projects) }

context "create through API" do
let(:finished_task) { FactoryGirl.create(:miq_task, :state => "Finished") }
let(:provider) { FactoryGirl.create(:provider_ansible_tower, :with_authentication) }
let(:manager) { provider.managers.first }
let(:atc) { double("AnsibleTowerClient::Connection", :api => api) }
let(:api) { double("AnsibleTowerClient::Api", :projects => projects) }
let(:projects) { double("AnsibleTowerClient::Collection", :create! => project) }
let(:project) { AnsibleTowerClient::Project.new(nil, project_json) }
let(:projects) { double("AnsibleTowerClient::Collection", :create! => project) }
let(:project) { AnsibleTowerClient::Project.new(nil, project_json) }

let(:project_json) do
params.merge(
Expand Down Expand Up @@ -46,7 +46,9 @@
it ".create_in_provider_queue" do
EvmSpecHelper.local_miq_server
task_id = described_class.create_in_provider_queue(manager.id, params)
expect(MiqTask.find(task_id)).to have_attributes(:name => "Creating Ansible Tower Project")
expect(MiqTask.find(task_id)).to have_attributes(
:name => "Creating ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScriptSource"
)
expect(MiqQueue.first).to have_attributes(
:args => [manager.id, params],
:class_name => "ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScriptSource",
Expand All @@ -65,4 +67,56 @@ def store_new_project(project, manager)
)
end
end

context "Delete through API" do
let(:projects) { double("AnsibleTowerClient::Collection", :find => tower_project) }
let(:tower_project) { double("AnsibleTowerClient::Project", :destroy! => nil, :id => 1) }
let(:project) { described_class.create!(:manager => manager, :manager_ref => tower_project.id) }

it "#delete_in_provider" do
expect(AnsibleTowerClient::Connection).to receive(:new).and_return(atc)
expect(EmsRefresh).to receive(:queue_refresh_task).and_return([finished_task])
project.delete_in_provider
end

it "#delete_in_provider_queue" do
task_id = project.delete_in_provider_queue
expect(MiqTask.find(task_id)).to have_attributes(:name => "Deleting ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScriptSource")
expect(MiqQueue.first).to have_attributes(
:instance_id => project.id,
:args => [],
:class_name => "ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScriptSource",
:method_name => "delete_in_provider",
:priority => MiqQueue::HIGH_PRIORITY,
:role => "ems_operations",
:zone => manager.my_zone
)
end
end

context "Update through API" do
let(:projects) { double("AnsibleTowerClient::Collection", :find => tower_project) }
let(:tower_project) { double("AnsibleTowerClient::Project", :update_attributes! => {}, :id => 1) }
let(:project) { described_class.create!(:manager => manager, :manager_ref => tower_project.id) }

it "#update_in_provider" do
expect(AnsibleTowerClient::Connection).to receive(:new).and_return(atc)
expect(EmsRefresh).to receive(:queue_refresh_task).and_return([finished_task])
expect(project.update_in_provider({})).to be_a(described_class)
end

it "#update_in_provider_queue" do
task_id = project.update_in_provider_queue({})
expect(MiqTask.find(task_id)).to have_attributes(:name => "Updating ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScriptSource")
expect(MiqQueue.first).to have_attributes(
:instance_id => project.id,
:args => [{:task_id => task_id}],
:class_name => "ManageIQ::Providers::AnsibleTower::AutomationManager::ConfigurationScriptSource",
:method_name => "update_in_provider",
:priority => MiqQueue::HIGH_PRIORITY,
:role => "ems_operations",
:zone => manager.my_zone
)
end
end
end
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
require 'ansible_tower_client'

describe ManageIQ::Providers::AnsibleTower::AutomationManager::Credential do
let(:finished_task) { FactoryGirl.create(:miq_task, :state => "Finished") }
let(:manager) { FactoryGirl.create(:provider_ansible_tower, :with_authentication).managers.first }
let(:atc) { double("AnsibleTowerClient::Connection", :api => api) }
let(:api) { double("AnsibleTowerClient::Api", :credentials => credentials) }

context "Create through API" do
let(:finished_task) { FactoryGirl.create(:miq_task, :state => "Finished") }
let(:provider) { FactoryGirl.create(:provider_ansible_tower, :with_authentication) }
let(:manager) { provider.managers.first }
let(:atc) { double("AnsibleTowerClient::Connection", :api => api) }
let(:api) { double("AnsibleTowerClient::Api", :credentials => credentials) }
let(:credentials) { double("AnsibleTowerClient::Collection", :create! => credential) }
let(:credential) { AnsibleTowerClient::Credential.new(nil, credential_json) }

Expand Down Expand Up @@ -42,7 +42,6 @@
end

it ".create_in_provider_queue" do
EvmSpecHelper.local_miq_server
task_id = described_class.create_in_provider_queue(manager.id, params)
expect(MiqTask.find(task_id)).to have_attributes(:name => "Creating ManageIQ::Providers::AnsibleTower::AutomationManager::Credential")
expect(MiqQueue.first).to have_attributes(
Expand All @@ -63,4 +62,56 @@ def store_new_credential(credential, manager)
)
end
end

context "Delete through API" do
let(:credentials) { double("AnsibleTowerClient::Collection", :find => credential) }
let(:credential) { double("AnsibleTowerClient::Credential", :destroy! => nil, :id => 1) }
let(:ansible_cred) { described_class.create!(:resource => manager, :manager_ref => credential.id) }

it "#delete_in_provider" do
expect(AnsibleTowerClient::Connection).to receive(:new).and_return(atc)
expect(EmsRefresh).to receive(:queue_refresh_task).and_return([finished_task])
ansible_cred.delete_in_provider
end

it "#delete_in_provider_queue" do
task_id = ansible_cred.delete_in_provider_queue
expect(MiqTask.find(task_id)).to have_attributes(:name => "Deleting ManageIQ::Providers::AnsibleTower::AutomationManager::Credential")
expect(MiqQueue.first).to have_attributes(
:instance_id => ansible_cred.id,
:args => [],
:class_name => "ManageIQ::Providers::AnsibleTower::AutomationManager::Credential",
:method_name => "delete_in_provider",
:priority => MiqQueue::HIGH_PRIORITY,
:role => "ems_operations",
:zone => manager.my_zone
)
end
end

context "Update through API" do
let(:credentials) { double("AnsibleTowerClient::Collection", :find => credential) }
let(:credential) { double("AnsibleTowerClient::Credential", :update_attributes! => {}, :id => 1) }
let(:ansible_cred) { described_class.create!(:resource => manager, :manager_ref => credential.id) }

it "#update_in_provider" do
expect(AnsibleTowerClient::Connection).to receive(:new).and_return(atc)
expect(EmsRefresh).to receive(:queue_refresh_task).and_return([finished_task])
expect(ansible_cred.update_in_provider({})).to be_a(described_class)
end

it "#update_in_provider_queue" do
task_id = ansible_cred.update_in_provider_queue({})
expect(MiqTask.find(task_id)).to have_attributes(:name => "Updating ManageIQ::Providers::AnsibleTower::AutomationManager::Credential")
expect(MiqQueue.first).to have_attributes(
:instance_id => ansible_cred.id,
:args => [{:task_id => task_id}],
:class_name => "ManageIQ::Providers::AnsibleTower::AutomationManager::Credential",
:method_name => "update_in_provider",
:priority => MiqQueue::HIGH_PRIORITY,
:role => "ems_operations",
:zone => manager.my_zone
)
end
end
end