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

Seed plugin ansible playbooks #17185

Merged
merged 13 commits into from
Apr 6, 2018
88 changes: 88 additions & 0 deletions app/models/embedded_ansible_worker/object_management.rb
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
module EmbeddedAnsibleWorker::ObjectManagement
extend ActiveSupport::Concern

CONSOLIDATED_PLUGIN_PLAYBOOKS_TEMPDIR = Pathname.new("/var/lib/awx_consolidated_source").freeze

def ensure_initial_objects(provider, connection)
ensure_organization(provider, connection)
ensure_credential(provider, connection)
ensure_inventory(provider, connection)
ensure_host(provider, connection)
ensure_plugin_playbooks_project_seeded(provider, connection)
end

def remove_demo_data(connection)
Expand Down Expand Up @@ -53,4 +56,89 @@ def ensure_host(provider, connection)
:variables => {'ansible_connection' => "local"}.to_yaml
).id
end

def ensure_plugin_playbooks_project_seeded(provider, connection)
clean_consolidated_plugin_directory
copy_plugin_ansible_content

commit_git_plugin_content
chown_playbooks_tempdir

project = find_default_project(connection, provider.default_project)
if project
update_playbook_project(project, provider.default_organization)
else
provider.default_project = create_playbook_project(connection, provider.default_organization).id
end
# Note, we don't remove the temporary directory CONSOLIDATED_PLUGIN_PLAYBOOKS_TEMPDIR here because
# 1) It shouldn't use too much disk space
# 2) There isn't a synchronous way to import the git project into ansible so we'd need to poll ansible
# and remove it AFTER it was cloned.
end

private

def clean_consolidated_plugin_directory
FileUtils.rm_rf(self.class.consolidated_plugin_directory)
end

def copy_plugin_ansible_content
FileUtils.mkdir_p(self.class.consolidated_plugin_directory)

Vmdb::Plugins.instance.registered_ansible_content.each do |content|
FileUtils.cp_r(Dir.glob("#{content.path}/*"), self.class.consolidated_plugin_directory)
end
end

def chown_playbooks_tempdir
FileUtils.chown_R('awx', 'awx', self.class.consolidated_plugin_directory)
end

def commit_git_plugin_content
Dir.chdir(self.class.consolidated_plugin_directory) do
require 'rugged'
repo = Rugged::Repository.init_at(".")
index = repo.index
index.add_all("*")
index.write

options = {}
options[:tree] = index.write_tree(repo)
options[:author] = options[:committer] = { :email => "system@localhost", :name => "System", :time => Time.now.utc }
options[:message] = "Initial Commit"
options[:parents] = []
options[:update_ref] = 'HEAD'
Rugged::Commit.create(repo, options)
end
end

def find_default_project(connection, project_id)
return unless project_id
connection.api.projects.find(project_id)
rescue AnsibleTowerClient::ResourceNotFoundError
nil
end

def update_playbook_project(project, organization)
project.update_attributes!(self.class.playbook_project_attributes.merge(:organization => organization))
end

def create_playbook_project(connection, organization)
connection.api.projects.create!(self.class.playbook_project_attributes.merge(:organization => organization).to_json)
end

class_methods do
def consolidated_plugin_directory
CONSOLIDATED_PLUGIN_PLAYBOOKS_TEMPDIR
end

def playbook_project_attributes
{
:name => "#{I18n.t('product.name')} Default Project".freeze,
:scm_type => "git".freeze,
:scm_url => "file://#{consolidated_plugin_directory}".freeze,
:scm_update_on_launch => false
}.freeze
end
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ def default_host
get_default_ansible_object("host")
end

def default_project
get_default_ansible_object("project")
end

def default_organization=(org)
set_default_ansible_object("organization", org)
end
Expand All @@ -39,6 +43,10 @@ def default_host=(host)
set_default_ansible_object("host", host)
end

def default_project=(project)
set_default_ansible_object("project", project)
end

def delete_ansible_object(name)
default_ansible_objects.find_by(:name => name).try(:destroy)
end
Expand Down
1 change: 1 addition & 0 deletions lib/vmdb/plugins.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module Vmdb
class Plugins
include Singleton

attr_reader :registered_ansible_content
attr_reader :registered_automate_domains

def initialize
Expand Down
44 changes: 44 additions & 0 deletions spec/models/embedded_ansible_worker_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
expect(cred_collection).to receive(:create!).and_return(cred_resource)
expect(inv_collection).to receive(:create!).and_return(inv_resource)
expect(host_collection).to receive(:create!).and_return(host_resource)
expect(subject).to receive(:ensure_plugin_playbooks_project_seeded)

subject.ensure_initial_objects(provider, api_connection)
end
Expand Down Expand Up @@ -135,6 +136,49 @@
end
end

describe "#ensure_plugin_playbooks_project_seeded" do
let!(:tmp_dir) { Pathname.new(Dir.mktmpdir("consolidated_ansible_playbooks")) }
let!(:expected_attributes) do
{
:name => "ManageIQ Default Project",
:scm_type => "git",
:scm_url => "file://#{tmp_dir}",
:scm_update_on_launch => false,
:organization => 42
}
end

before do
provider.default_organization = 42
allow(EmbeddedAnsibleWorker).to receive(:consolidated_plugin_directory).and_return(tmp_dir)
allow(subject).to receive(:chown_playbooks_tempdir)
end

after do
FileUtils.rm_rf(tmp_dir)
end

it "creates a git project as the provider's default project" do
expect(proj_collection).to receive(:create!)
.with(expected_attributes.to_json)
.and_return(double(:id => 1234))

subject.ensure_plugin_playbooks_project_seeded(provider, api_connection)
expect(Dir.exist?(tmp_dir.join(".git"))).to be_truthy
expect(provider.default_project).to eq(1234)
end

it "updates an existing project" do
project = double(:id => 1234)
expect(subject).to receive(:find_default_project).and_return(project)
expect(project).to receive(:update_attributes!)
.with(expected_attributes)
.and_return(double(:id => 1234))

subject.ensure_plugin_playbooks_project_seeded(provider, api_connection)
end
end

describe "#start_monitor_thread" do
let(:pool) { double("ConnectionPool") }

Expand Down