foreman_ansible 1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of foreman_ansible might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Rakefile +6 -27
- data/app/controllers/ansible_roles_controller.rb +55 -0
- data/app/controllers/api/v2/ansible_roles_controller.rb +52 -0
- data/app/controllers/foreman_ansible/concerns/hosts_controller_extensions.rb +11 -10
- data/app/helpers/foreman_ansible/ansible_plugin_helper.rb +8 -0
- data/app/helpers/foreman_ansible/ansible_reports_helper.rb +6 -4
- data/app/helpers/foreman_ansible/ansible_roles_helper.rb +17 -3
- data/app/helpers/foreman_ansible/hosts_helper_extensions.rb +4 -3
- data/app/lib/actions/foreman_ansible/play_host_roles.rb +56 -0
- data/app/lib/actions/foreman_ansible/play_hosts_roles.rb +26 -0
- data/app/lib/proxy_api/ansible.rb +28 -0
- data/app/models/ansible_role.rb +8 -0
- data/app/models/concerns/foreman_ansible/has_many_ansible_roles.rb +13 -0
- data/app/models/concerns/foreman_ansible/host_managed_extensions.rb +5 -1
- data/app/models/concerns/foreman_ansible/hostgroup_extensions.rb +19 -0
- data/app/models/host_ansible_role.rb +0 -2
- data/app/models/hostgroup_ansible_role.rb +8 -0
- data/app/overrides/ansible_roles_tab.rb +2 -2
- data/app/overrides/hostgroup_ansible_roles_tab.rb +14 -0
- data/app/services/foreman_ansible/api_roles_importer.rb +16 -0
- data/app/services/foreman_ansible/fact_importer.rb +2 -1
- data/app/services/foreman_ansible/inventory_creator.rb +37 -5
- data/app/services/foreman_ansible/playbook_creator.rb +3 -4
- data/app/services/foreman_ansible/proxy_selector.rb +19 -0
- data/app/services/foreman_ansible/roles_importer.rb +42 -15
- data/app/services/foreman_ansible/ui_roles_importer.rb +26 -0
- data/app/views/ansible_roles/import.html.erb +51 -0
- data/app/views/ansible_roles/index.html.erb +30 -0
- data/app/views/ansible_roles/welcome.html.erb +14 -0
- data/app/views/api/v2/ansible_roles/import.json.rabl +3 -0
- data/app/views/api/v2/ansible_roles/index.json.rabl +3 -0
- data/app/views/api/v2/ansible_roles/obsolete.json.rabl +3 -0
- data/app/views/api/v2/ansible_roles/show.json.rabl +3 -0
- data/app/views/foreman_ansible/ansible_roles/_select_tab_content.html.erb +6 -0
- data/app/views/foreman_ansible/{hosts/_tab_title.html.erb → ansible_roles/_select_tab_title.html.erb} +0 -0
- data/config/routes.rb +25 -2
- data/db/migrate/20160705082036_create_ansible_role.rb +2 -1
- data/db/migrate/20160706074540_create_join_table_hosts_ansible_roles.rb +1 -0
- data/db/migrate/20160707195442_create_host_ansible_roles.rb +1 -0
- data/db/migrate/20160729094457_add_columns_to_ansible_role.rb +12 -0
- data/db/migrate/20160802153302_create_join_table_hostgroup_ansible_roles.rb +10 -0
- data/db/migrate/20160805094233_add_primary_key_hostgroup_ansible_roles.rb +6 -0
- data/db/seeds.d/{62-ansible_proxy_feature.rb → 62_ansible_proxy_feature.rb} +0 -0
- data/lib/foreman_ansible.rb +1 -0
- data/lib/foreman_ansible/engine.rb +54 -4
- data/lib/foreman_ansible/version.rb +1 -1
- data/locale/en/foreman_ansible.po +139 -2
- data/locale/foreman_ansible.pot +200 -8
- data/test/factories/ansible_proxy.rb +7 -0
- data/test/factories/ansible_roles.rb +2 -2
- data/test/fixtures/ansible_permissions.yml +11 -0
- data/test/functional/ansible_roles_controller_test.rb +16 -0
- data/test/functional/api/v2/ansible_roles_controller_test.rb +24 -0
- data/test/functional/hosts_controller_test.rb +65 -24
- data/test/support/fixture_support.rb +25 -0
- data/test/support/foreman_tasks/task.rb +47 -0
- data/test/support/foreman_test_helper_additions.rb +22 -0
- data/test/test_plugin_helper.rb +5 -2
- data/test/unit/ansible_role_test.rb +6 -2
- data/test/unit/concerns/host_managed_extensions_test.rb +37 -0
- data/test/unit/concerns/hostgroup_extensions_test.rb +36 -0
- data/test/unit/fact_importer_test.rb +11 -8
- data/test/unit/fact_parser_test.rb +2 -0
- data/test/unit/fact_sparser_test.rb +1 -0
- data/test/unit/helpers/foreman_ansible/ansible_reports_helper_test.rb +1 -0
- data/test/unit/host_ansible_role_test.rb +10 -0
- data/test/unit/hostgroup_ansible_role_test.rb +19 -0
- data/test/unit/lib/foreman_ansible_core/playbook_runner_test.rb +28 -0
- data/test/unit/lib/proxy_api/ansible_test.rb +23 -0
- data/test/unit/services/api_roles_importer_test.rb +28 -0
- data/test/unit/services/proxy_selector_test.rb +28 -0
- data/test/unit/services/roles_importer_test.rb +17 -0
- data/test/unit/services/ui_roles_importer_test.rb +30 -0
- metadata +108 -14
- data/app/jobs/foreman_ansible/run_playbook_job.rb +0 -28
- data/app/services/foreman_ansible/role_player.rb +0 -26
- data/app/views/foreman_ansible/hosts/_tab_content.html.erb +0 -4
- data/lib/tasks/foreman_ansible_tasks.rake +0 -40
@@ -0,0 +1,11 @@
|
|
1
|
+
---
|
2
|
+
view_ansible_roles:
|
3
|
+
name: view_ansible_roles
|
4
|
+
resource_type: AnsibleRole
|
5
|
+
created_at: "2013-12-04 08:41:04.321867"
|
6
|
+
updated_at: "2013-12-04 08:41:04.321867"
|
7
|
+
destroy_ansible_roles:
|
8
|
+
name: destroy_ansible_roles
|
9
|
+
resource_type: AnsibleRole
|
10
|
+
created_at: "2013-12-04 08:41:04.321867"
|
11
|
+
updated_at: "2013-12-04 08:41:04.321867"
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
# functional tests for AnsibleRolesController
|
3
|
+
class AnsibleRolesControllerTest < ActionController::TestCase
|
4
|
+
setup do
|
5
|
+
@role = FactoryGirl.create(:ansible_role)
|
6
|
+
end
|
7
|
+
|
8
|
+
basic_index_test
|
9
|
+
|
10
|
+
test 'should destroy role' do
|
11
|
+
assert_difference('AnsibleRole.count', -1) do
|
12
|
+
delete :destroy, { :id => @role.id }, set_session_user
|
13
|
+
end
|
14
|
+
assert_redirected_to ansible_roles_url
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
module Api
|
4
|
+
module V2
|
5
|
+
class AnsibleRolesControllerTest < ActionController::TestCase
|
6
|
+
setup do
|
7
|
+
@role = FactoryGirl.create(:ansible_role)
|
8
|
+
end
|
9
|
+
|
10
|
+
test 'should get index' do
|
11
|
+
get :index, {}, set_session_user
|
12
|
+
response = JSON.parse(@response.body)
|
13
|
+
refute_empty response['results']
|
14
|
+
assert_response :success
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'should destroy' do
|
18
|
+
delete :destroy, { :id => @role.id }, set_session_user
|
19
|
+
assert_response :ok
|
20
|
+
refute AnsibleRole.exists?(@role.id)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -1,36 +1,77 @@
|
|
1
1
|
require 'test_plugin_helper'
|
2
|
+
require 'dynflow/testing'
|
3
|
+
Mocha::Mock.send :include, Dynflow::Testing::Mimic
|
4
|
+
require 'support/foreman_tasks/task'
|
2
5
|
|
6
|
+
# Ensure Hosts controller can CRUD ansible roles
|
3
7
|
class HostsControllerExtensionsTest < ActionController::TestCase
|
8
|
+
include Support::ForemanTasks::Task
|
9
|
+
|
4
10
|
tests ::HostsController
|
5
11
|
|
6
|
-
|
7
|
-
|
8
|
-
|
12
|
+
context 'role assignment' do
|
13
|
+
setup do
|
14
|
+
@role = FactoryGirl.create(:ansible_role)
|
15
|
+
end
|
16
|
+
|
17
|
+
test 'create a host with ansible roles' do
|
18
|
+
host = { :name => 'foo',
|
19
|
+
:managed => false,
|
20
|
+
:ansible_role_ids => [@role.id] }
|
21
|
+
post :create, { :host => host }, set_session_user
|
22
|
+
assert_redirected_to host_url(assigns('host'))
|
23
|
+
assert assigns('host').ansible_roles, [@role]
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'update a host with ansible roles' do
|
27
|
+
host = FactoryGirl.create(:host, :managed => false)
|
28
|
+
post :update, { :id => host.id,
|
29
|
+
:host => { :ansible_role_ids => [@role.id] } },
|
30
|
+
set_session_user
|
31
|
+
assert_redirected_to host_url(assigns('host'))
|
32
|
+
assert assigns('host').ansible_roles, [@role]
|
33
|
+
end
|
9
34
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
set_session_user
|
16
|
-
|
17
|
-
|
35
|
+
test 'delete a host with ansible roles' do
|
36
|
+
host = FactoryGirl.create(:host,
|
37
|
+
:managed => false,
|
38
|
+
:ansible_roles => [@role])
|
39
|
+
assert_include @role.hosts, host
|
40
|
+
delete :destroy, { :id => host.id }, set_session_user
|
41
|
+
assert_redirected_to hosts_url
|
42
|
+
assert @role.hosts.empty?
|
43
|
+
end
|
18
44
|
end
|
19
45
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
46
|
+
context 'playing roles' do
|
47
|
+
setup do
|
48
|
+
@host = FactoryGirl.create(:host, :managed => false)
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'redirect to task if successful' do
|
52
|
+
task_stub = new_task_stub(@host)
|
53
|
+
task_to_redirect = ForemanTasks::Task.new
|
54
|
+
task_stub.stubs(:to_model).returns(task_to_redirect)
|
55
|
+
task_to_redirect.stubs(:persisted?).returns(true)
|
56
|
+
task_to_redirect.stubs(:id).returns(1)
|
57
|
+
get :play_roles, { :id => @host.id }, set_session_user
|
58
|
+
end
|
59
|
+
|
60
|
+
test 'shows errors when not successful' do
|
61
|
+
HostsController.any_instance.expects(:async_task).
|
62
|
+
raises(::Foreman::Exception.new('Oh foo'))
|
63
|
+
get :play_roles, { :id => @host.id }, set_session_user
|
64
|
+
assert flash[:error].present?
|
65
|
+
assert_redirected_to host_path(@host)
|
66
|
+
end
|
26
67
|
end
|
27
68
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
69
|
+
private
|
70
|
+
|
71
|
+
def new_task_stub(host)
|
72
|
+
assert_async_task(::Actions::ForemanAnsible::PlayHostRoles,
|
73
|
+
host) do |action_host|
|
74
|
+
assert_equal host, action_host
|
75
|
+
end
|
35
76
|
end
|
36
77
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ForemanAnsible
|
2
|
+
module PluginFixtures
|
3
|
+
FIXTURE_MAPPING = {
|
4
|
+
:ansible_permissions => :permissions
|
5
|
+
}.freeze
|
6
|
+
|
7
|
+
def self.add_fixtures(new_fixture_path)
|
8
|
+
FileUtils.cp(Dir.glob("#{Rails.root}/test/fixtures/*"), new_fixture_path)
|
9
|
+
copy_plugin_fixtures new_fixture_path
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.copy_plugin_fixtures(new_fixture_path)
|
13
|
+
FIXTURE_MAPPING.each do |key, value|
|
14
|
+
fixture_path = "#{ForemanAnsible::Engine.root}/test/fixtures/#{key}.yml"
|
15
|
+
break unless File.exist?(fixture_path)
|
16
|
+
File.open("#{new_fixture_path}/#{value}.yml", 'a') do |file|
|
17
|
+
File.open(fixture_path, 'r').each do |line|
|
18
|
+
next if line =~ /---/
|
19
|
+
file.write line
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Support
|
2
|
+
module ForemanTasks
|
3
|
+
module Task
|
4
|
+
def stub_tasks!
|
5
|
+
@controller.stubs(:sync_task).returns(build_task_stub)
|
6
|
+
@controller.stubs(:async_task).returns(build_task_stub)
|
7
|
+
end
|
8
|
+
|
9
|
+
def build_task_stub
|
10
|
+
task_attrs = [:id, :label, :pending, :username, :started_at, :ended_at,
|
11
|
+
:state, :result, :progress, :input, :humanized,
|
12
|
+
:cli_example].inject({}) { |a, e| a.update e => nil }
|
13
|
+
task_attrs[:output] = {}
|
14
|
+
|
15
|
+
stub('task', task_attrs).mimic!(::ForemanTasks::Task)
|
16
|
+
end
|
17
|
+
|
18
|
+
def assert_async_task(expected_action_class, *args_expected)
|
19
|
+
assert_foreman_task(true, expected_action_class, *args_expected)
|
20
|
+
end
|
21
|
+
|
22
|
+
def assert_sync_task(expected_action_class, *args_expected)
|
23
|
+
assert_foreman_task(false, expected_action_class, *args_expected)
|
24
|
+
end
|
25
|
+
|
26
|
+
def assert_foreman_task(async, expected_action_class, *args_expected)
|
27
|
+
block ||= block_from_args(args_expected)
|
28
|
+
method = async ? :async_task : :sync_task
|
29
|
+
task_stub = build_task_stub
|
30
|
+
@controller.
|
31
|
+
expects(method).
|
32
|
+
with do |action_class, *args|
|
33
|
+
expected_action_class == action_class && block.call(*args)
|
34
|
+
end.
|
35
|
+
returns(task_stub)
|
36
|
+
task_stub
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def block_from_args(args_expected)
|
42
|
+
->(*_) { true } if args_expected.empty?
|
43
|
+
->(*args) { args == args_expected }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "#{ForemanAnsible::Engine.root}/test/support/fixture_support"
|
2
|
+
# loads the permissions for foreman_ansible and makes them available in tests
|
3
|
+
module AnsiblePermissionTestCase
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
extend ActiveRecord::TestFixtures
|
8
|
+
|
9
|
+
new_fixture_path = Dir.mktmpdir('ansible_fixtures')
|
10
|
+
self.fixture_path = new_fixture_path
|
11
|
+
ForemanAnsible::PluginFixtures.add_fixtures(new_fixture_path)
|
12
|
+
fixtures(:all)
|
13
|
+
load_fixtures(ActiveRecord::Base)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ActiveSupport
|
18
|
+
#:nodoc
|
19
|
+
class TestCase
|
20
|
+
include AnsiblePermissionTestCase
|
21
|
+
end
|
22
|
+
end
|
data/test/test_plugin_helper.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
def sample_facts_file
|
4
|
-
File.read(
|
5
|
-
|
4
|
+
File.read(
|
5
|
+
File.join(
|
6
|
+
ForemanAnsible::Engine.root, 'test', 'fixtures', 'sample_facts.json'
|
7
|
+
)
|
8
|
+
)
|
6
9
|
end
|
7
10
|
|
8
11
|
def facts_json
|
@@ -1,8 +1,12 @@
|
|
1
|
-
|
1
|
+
require 'test_plugin_helper'
|
2
2
|
|
3
|
+
# Tests for the behavior of Ansible Role, currently only validations
|
3
4
|
class AnsibleRoleTest < ActiveSupport::TestCase
|
4
5
|
should have_many(:host_ansible_roles)
|
5
6
|
should have_many(:hosts).through(:host_ansible_roles).dependent(:destroy)
|
6
7
|
should validate_presence_of(:name)
|
7
|
-
|
8
|
+
context 'with new role' do
|
9
|
+
subject { AnsibleRole.new(:name => 'foo') }
|
10
|
+
should validate_uniqueness_of(:name)
|
11
|
+
end
|
8
12
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
# Tests for the behavior of Host with roles, checks inheritance, etc
|
4
|
+
class HostManagedExtensionsTest < ActiveSupport::TestCase
|
5
|
+
before do
|
6
|
+
@role1 = FactoryGirl.create(:ansible_role)
|
7
|
+
@role2 = FactoryGirl.create(:ansible_role)
|
8
|
+
@role3 = FactoryGirl.create(:ansible_role)
|
9
|
+
|
10
|
+
@hostgroup_parent = FactoryGirl.create(:hostgroup,
|
11
|
+
:ansible_roles => [@role2])
|
12
|
+
@hostgroup = FactoryGirl.create(:hostgroup, :parent => @hostgroup_parent)
|
13
|
+
@host = FactoryGirl.build_stubbed(:host, :ansible_roles => [@role1])
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#all_ansible_roles' do
|
17
|
+
test 'returns assigned roles for host without a hostgroup' do
|
18
|
+
@host.all_ansible_roles.must_equal [@role1]
|
19
|
+
end
|
20
|
+
|
21
|
+
test 'returns assigned and inherited roles for host with a hostgroup' do
|
22
|
+
@host.hostgroup = @hostgroup
|
23
|
+
@host.all_ansible_roles.must_equal [@role1, @role2]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe '#inherited_ansible_roles' do
|
28
|
+
test 'returns empty array for host without hostgroup' do
|
29
|
+
@host.inherited_ansible_roles.must_equal []
|
30
|
+
end
|
31
|
+
|
32
|
+
test 'returns roles inherited from a hostgroup' do
|
33
|
+
@host.hostgroup = @hostgroup
|
34
|
+
@host.inherited_ansible_roles.must_equal [@role2]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'test_plugin_helper'
|
2
|
+
|
3
|
+
# Tests for the behavior of Hostgroup with roles, checks inheritance, etc
|
4
|
+
class HostgroupExtensionsTest < ActiveSupport::TestCase
|
5
|
+
before do
|
6
|
+
@role1 = FactoryGirl.create(:ansible_role)
|
7
|
+
@role2 = FactoryGirl.create(:ansible_role)
|
8
|
+
@role3 = FactoryGirl.create(:ansible_role)
|
9
|
+
|
10
|
+
@hostgroup_parent = FactoryGirl.create(:hostgroup,
|
11
|
+
:ansible_roles => [@role2])
|
12
|
+
@hostgroup = FactoryGirl.create(:hostgroup, :ansible_roles => [@role1])
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#all_ansible_roles' do
|
16
|
+
test 'returns assigned roles without any parent hostgroup' do
|
17
|
+
@hostgroup.all_ansible_roles.must_equal [@role1]
|
18
|
+
end
|
19
|
+
|
20
|
+
test 'returns assigned and inherited roles with a parent hostgroup' do
|
21
|
+
@hostgroup.parent = @hostgroup_parent
|
22
|
+
@hostgroup.all_ansible_roles.must_equal [@role1, @role2]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe '#inherited_ansible_roles' do
|
27
|
+
test 'returns empty array for hostgroup without any parent' do
|
28
|
+
@hostgroup.inherited_ansible_roles.must_equal []
|
29
|
+
end
|
30
|
+
|
31
|
+
test 'returns roles inherited from a chain of parents' do
|
32
|
+
@hostgroup.parent = @hostgroup_parent
|
33
|
+
@hostgroup.inherited_ansible_roles.must_equal [@role2]
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -1,22 +1,25 @@
|
|
1
1
|
require 'test_plugin_helper'
|
2
2
|
|
3
3
|
module ForemanAnsible
|
4
|
+
# Test for the facts importer - only verify that given
|
5
|
+
# a set of facts it's able to import them
|
4
6
|
class FactImporterTest < ActiveSupport::TestCase
|
5
7
|
setup do
|
6
|
-
@host = FactoryGirl.
|
8
|
+
@host = FactoryGirl.build(:host)
|
7
9
|
end
|
8
10
|
|
9
11
|
test 'add new facts adds all fact names in the fixture' do
|
10
12
|
@fact_importer = FactImporter.new(@host, facts_json)
|
11
13
|
facts_to_be_added = FactSparser.sparse(facts_json[:ansible_facts]).keys +
|
12
|
-
|
14
|
+
FactSparser.unsparse(facts_json[:ansible_facts]).keys
|
13
15
|
@fact_importer.send(:add_new_facts)
|
14
|
-
assert
|
16
|
+
assert((facts_to_be_added - FactName.all.map(&:name)).empty?)
|
15
17
|
end
|
16
18
|
|
17
19
|
test 'missing_facts returns facts we do not have in the database' do
|
18
20
|
@fact_importer = FactImporter.new(@host, facts_json)
|
19
|
-
@fact_importer.expects(:db_facts).
|
21
|
+
@fact_importer.expects(:db_facts).
|
22
|
+
returns('ansible_cmdline' => 'fakevalue')
|
20
23
|
refute @fact_importer.send(:missing_facts).include?('ansible_cmdline')
|
21
24
|
end
|
22
25
|
|
@@ -36,12 +39,12 @@ module ForemanAnsible
|
|
36
39
|
@fact_importer.counters[:added] = 0
|
37
40
|
assert_difference('@host.fact_values.count', 1) do
|
38
41
|
@fact_importer.send(:add_fact_value, 'missing_value', missing_fact)
|
42
|
+
@host.save
|
43
|
+
# We have to save the host in order to ensure @host.fact_values.count
|
44
|
+
# resolves properly (otherwise) :add_fact_value just won't save the
|
45
|
+
# relation
|
39
46
|
end
|
40
47
|
end
|
41
48
|
end
|
42
|
-
|
43
|
-
test 'add_fact_value works for hosts that have not been created yet' do
|
44
|
-
end
|
45
49
|
end
|
46
50
|
end
|
47
|
-
|