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 temporary inventory when execute a playbook #14008

Merged
merged 2 commits into from
Feb 23, 2017

Conversation

bzwei
Copy link
Contributor

@bzwei bzwei commented Feb 21, 2017

Create a temporary inventory and add hosts to it before job execution in the preprocess step.
Delete the temporary inventory after job execution in the postprocess step

Every job template is created with default inventory Demo Inventory which contains localhost. Demo Inventory comes with tower installation. We can change it if the embedded tower will configure a formal localhost inventory.

Temporary is created with default organization which has id = 1. Again we can change it if the embedded tower will configure a formal default organization.

Will skip the temporary inventory creation/deletion if the playbook runs at localhost.

https://www.pivotaltracker.com/story/show/140142225

@bzwei
Copy link
Contributor Author

bzwei commented Feb 21, 2017

@gmcculloug @bdunne @syncrou


def create_inventory(action, hosts)
manager(action).with_provider_connection do |connection|
inventory = connection.api.inventories.create(:name => inventory_name(action), :organization => 1)
Copy link
Contributor

Choose a reason for hiding this comment

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

Would we want .create! and destroy! - so we could bubble up an Exception?


def create_inventory(action, hosts)
manager(action).with_provider_connection do |connection|
inventory = connection.api.inventories.create(:name => inventory_name(action), :organization => 1)
Copy link
Member

Choose a reason for hiding this comment

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

Using .tap will further indent the hosts.split call making the nesting more visible.

def create_inventory(action, hosts)
  manager(action).with_provider_connection do |connection|
    connection.api.inventories.create(:name => inventory_name(action), :organization => 1).tap do |inventory|
      hosts.split(',').each do |host|
        connection.api.hosts.create(:name => host, :inventory => inventory.id)
      end
    end
  end
end

Copy link
Member

Choose a reason for hiding this comment

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

Maybe the host creation logic should be split into another private method to reduce complexity, what do you think?

@@ -73,4 +90,29 @@ def extra_vars_from_dialog

params.blank? ? {} : {:extra_vars => params}
end

def create_inventory(action, hosts)
Copy link
Member

Choose a reason for hiding this comment

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

The name of this method could be improved, maybe create_inventory_and_hosts, since it is creating more than just an Ansible Tower Inventory.

@@ -89,7 +89,7 @@ def self.build_parameter_list(name, description, info)
:description => description || '',
:project => playbook.configuration_script_source.manager_ref,
:playbook => playbook.name,
:inventory => tower.inventory_root_groups.first.ems_ref,
:inventory => tower.inventory_root_groups.find_by!(:name => 'Demo Inventory').ems_ref,
Copy link
Member

Choose a reason for hiding this comment

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

The inventory name should probably be a constant on the manager. It can then be reused by the setup scripting that we discussed with @gtanzillo @carbonin and @gmcculloug.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not sure where should the constant be replaced. We can refactor once the solution is finalized.

Copy link
Member

Choose a reason for hiding this comment

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

@bzwei Agreed, please open a pivotal story to track this work.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@@ -12,40 +15,95 @@
end

let(:executed_service) do
basic_service.tap do |service|
FactoryGirl.create(:service_ansible_playbook, :options => provision_options).tap do |service|
allow(service).to receive(:job).with(action).and_return(tower_job)
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this build the relation rather than stubbing it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We cannot stub method for tower_job later in the tests if build a relation here.

Copy link
Member

Choose a reason for hiding this comment

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

Then it sounds like it shouldn't be shared, but don't fix in this PR.

)
context 'basic service' do
it 'prepares job options from service template' do
expect(basic_service).to receive(:create_inventory)
Copy link
Member

Choose a reason for hiding this comment

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

You could probably write this expectation like this, then you wouldn't have to wrap the line and rubocop would be much happier.

hosts = config_info_options.fetch_path(:config_info, :provision, :hosts)
expect(basic_service).to receive(:create_inventory).with(action, hosts).and_return(double(:id => 10))

:credential_id => dialog_options['dialog_credential_id'],
:hosts => dialog_options['dialog_hosts']
:credential_id => dialog_options['dialog_credential'],
:hosts => (dialog_options['dialog_hosts'] || '').strip.presence
Copy link
Member

Choose a reason for hiding this comment

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

Why add the || ''? #presence will still return nil...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if dialog_options['dialog_hosts'] is nil

Copy link
Member

Choose a reason for hiding this comment

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

dialog_options['dialog_hosts'].to_s.strip.presence


def create_inventory(action, hosts)
manager(action).with_provider_connection do |connection|
inventory = connection.api.inventories.create!(:name => inventory_name(action), :organization => 1)
Copy link
Member

Choose a reason for hiding this comment

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

You could do:

def create_inventory(action, hosts)
  manager(action).with_provider_connection do |connection|
    connection.api.inventories.create!(:name => inventory_name(action), :organization => 1).tap do |inventory|
      hosts.split(',').each do |host|
        connection.api.hosts.create(:name => host, :inventory => inventory.id)
      end
    end
  end
end

The tap further indents the host creation and better represents the flow.

@@ -38,30 +39,46 @@ def job(action)
service_resources.find_by!(:name => action, :resource_type => 'OrchestrationStack').try(:resource)
end

def postprocess(action)
hosts = options.fetch_path(job_option_key(action), :inventory)
delete_inventory(action) unless hosts.blank? || hosts == 'localhost'
Copy link
Member

Choose a reason for hiding this comment

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

Why not delete the inventory if it only contains 'localhost'?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

localhost uses the default inventory that cannot be deleted.

@bzwei bzwei force-pushed the playbook_hosts branch 4 times, most recently from 07d0ea4 to 423fe43 Compare February 22, 2017 15:07
@@ -12,40 +15,95 @@
end

let(:executed_service) do
basic_service.tap do |service|
FactoryGirl.create(:service_ansible_playbook, :options => provision_options).tap do |service|
allow(service).to receive(:job).with(action).and_return(tower_job)
Copy link
Member

Choose a reason for hiding this comment

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

Then it sounds like it shouldn't be shared, but don't fix in this PR.

manager(action).with_provider_connection do |connection|
connection.api.inventories.create!(:name => inventory_name(action), :organization => 1).tap do |inventory|
hosts.split(',').each do |host|
connection.api.hosts.create(:name => host, :inventory => inventory.id)
Copy link
Contributor

Choose a reason for hiding this comment

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

s/create/create!/

@miq-bot
Copy link
Member

miq-bot commented Feb 22, 2017

Checked commits bzwei/manageiq@0dd941a~...c76637f with ruby 2.2.6, rubocop 0.47.1, and haml-lint 0.20.0
4 files checked, 0 offenses detected
Everything looks good. 🏆

@syncrou
Copy link
Contributor

syncrou commented Feb 22, 2017

👍 Looks good to me (once it can get to green.)

@gmcculloug gmcculloug merged commit e85e92e into ManageIQ:master Feb 23, 2017
@gmcculloug gmcculloug added this to the Sprint 55 Ending Feb 27, 2017 milestone Feb 23, 2017
@bzwei bzwei deleted the playbook_hosts branch February 23, 2017 16:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants