Skip to content

Commit

Permalink
Fixes #15979 - Add API for Ansible roles
Browse files Browse the repository at this point in the history
  • Loading branch information
Ondrej Prazak authored and dLobatog committed Sep 1, 2016
1 parent f6f1a78 commit 3a7067d
Show file tree
Hide file tree
Showing 17 changed files with 215 additions and 50 deletions.
2 changes: 1 addition & 1 deletion app/controllers/ansible_roles_controller.rb
Expand Up @@ -50,6 +50,6 @@ def find_proxy
end

def create_importer
@importer = ForemanAnsible::RolesImporter.new(@proxy)
@importer = ForemanAnsible::UiRolesImporter.new(@proxy)
end
end
52 changes: 52 additions & 0 deletions app/controllers/api/v2/ansible_roles_controller.rb
@@ -0,0 +1,52 @@
module Api
module V2
# API controller for Ansible Roles
class AnsibleRolesController < ::Api::V2::BaseController
include ::Api::Version2

before_action :find_resource, :only => [:show, :destroy]
before_action :find_proxy, :only => [:import, :obsolete]
before_action :create_importer, :only => [:import, :obsolete]

api :GET, '/ansible/ansible_roles/:id', N_('Show role')
param :id, :identifier, :required => true
def show
end

api :GET, '/ansible/ansible_roles', N_('List Ansible roles')
param_group :search_and_pagination, ::Api::V2::BaseController
def index
@ansible_roles = resource_scope_for_index
end

api :DELETE, '/ansible/ansible_roles/:id', N_('Deletes Ansible role')
param :id, :identifier, :required => true
def destroy
process_response @ansible_role.destroy
end

api :POST, '/ansible/ansible_roles/import', N_('Import Ansible roles')
param :proxy, Hash, N_('Smart Proxy to import from')
def import
@imported = @importer.import!
end

api :POST, '/ansible/ansible_roles/obsolete', N_('Obsolete Ansible roles')
param :proxy, Hash, N_('Smart Proxy to import from')
def obsolete
@obsoleted = @importer.obsolete!
end

private

def find_proxy
return nil unless params[:proxy]
@proxy = SmartProxy.authorized(:view_smart_proxies).find(params[:proxy])
end

def create_importer
@importer = ForemanAnsible::ApiRolesImporter.new(@proxy)
end
end
end
end
16 changes: 16 additions & 0 deletions app/services/foreman_ansible/api_roles_importer.rb
@@ -0,0 +1,16 @@
module ForemanAnsible
# imports Ansible roles through API
class ApiRolesImporter < RolesImporter
def import!
new_roles = import_role_names[:new]
new_roles.map(&:save)
new_roles
end

def obsolete!
obsolete_roles = import_role_names[:obsolete]
obsolete_roles.map(&:destroy)
obsolete_roles
end
end
end
20 changes: 1 addition & 19 deletions app/services/foreman_ansible/roles_importer.rb
Expand Up @@ -7,7 +7,7 @@ def initialize(proxy = nil)
@ansible_proxy = proxy
end

def import!
def import_role_names
return import_roles remote_roles if ansible_proxy
import_roles local_roles
end
Expand All @@ -19,24 +19,6 @@ def import_roles(roles)
detect_changes imported
end

def finish_import(changes)
return unless changes.present?
create_new_roles changes['new'] if changes['new']
delete_old_roles changes['obsolete'] if changes['obsolete']
end

def create_new_roles(changes)
changes.values.each do |new_role|
::AnsibleRole.create(JSON.parse(new_role))
end
end

def delete_old_roles(changes)
changes.values.each do |old_role|
::AnsibleRole.find(JSON.parse(old_role)['id']).destroy
end
end

def detect_changes(imported)
changes = {}.with_indifferent_access
old, changes[:new] = imported.partition { |role| role.id.present? }
Expand Down
26 changes: 26 additions & 0 deletions app/services/foreman_ansible/ui_roles_importer.rb
@@ -0,0 +1,26 @@
module ForemanAnsible
# imports ansible roles through UI
class UiRolesImporter < RolesImporter
def import!
import_role_names
end

def finish_import(changes)
return unless changes.present?
create_new_roles changes['new'] if changes['new']
delete_old_roles changes['obsolete'] if changes['obsolete']
end

def create_new_roles(changes)
changes.values.each do |new_role|
::AnsibleRole.create(JSON.parse(new_role))
end
end

def delete_old_roles(changes)
changes.values.each do |old_role|
::AnsibleRole.find(JSON.parse(old_role)['id']).destroy
end
end
end
end
3 changes: 3 additions & 0 deletions app/views/api/v2/ansible_roles/import.json.rabl
@@ -0,0 +1,3 @@
collection @imported => :imported

extends 'api/v2/ansible_roles/show'
3 changes: 3 additions & 0 deletions app/views/api/v2/ansible_roles/index.json.rabl
@@ -0,0 +1,3 @@
collection @ansible_roles

extends 'api/v2/ansible_roles/show'
3 changes: 3 additions & 0 deletions app/views/api/v2/ansible_roles/obsolete.json.rabl
@@ -0,0 +1,3 @@
collection @obsoleted => :obsoleted

extends 'api/v2/ansible_roles/show'
3 changes: 3 additions & 0 deletions app/views/api/v2/ansible_roles/show.json.rabl
@@ -0,0 +1,3 @@
object @ansible_role

attributes :name, :created_at, :updated_at
16 changes: 16 additions & 0 deletions config/routes.rb
Expand Up @@ -17,5 +17,21 @@
post :confirm_import
end
end

namespace :api do
scope '(:apiv)',
:module => :v2,
:defaults => { :apiv => 'v2' },
:apiv => /v1|v2/,
:constraints => ApiConstraints.new(:version => 2) do

resources :ansible_roles, :only => [:show, :index, :destroy] do
collection do
put :import
put :obsolete
end
end
end
end
end
end
9 changes: 6 additions & 3 deletions lib/foreman_ansible/engine.rb
Expand Up @@ -32,13 +32,16 @@ class Engine < ::Rails::Engine
{ :hosts => [:play_roles, :multiple_play_roles] },
:resource_type => 'Host::Managed'
permission :view_ansible_roles,
{ :ansible_roles => [:index] },
{ :ansible_roles => [:index],
:'api/v2/ansible_roles' => [:index, :show] },
:resource_type => 'AnsibleRole'
permission :destroy_ansible_roles,
{ :ansible_roles => [:destroy] },
{ :ansible_roles => [:destroy],
:'api/v2/ansible_roles' => [:destroy, :obsolete] },
:resource_type => 'AnsibleRole'
permission :import_ansible_roles,
{ :ansible_roles => [:import, :confirm_import] },
{ :ansible_roles => [:import, :confirm_import],
:'api/v2/ansible_roles' => [:import] },
:resource_type => 'AnsibleRole'
end

Expand Down
24 changes: 24 additions & 0 deletions test/functional/api/v2/ansible_roles_controller_test.rb
@@ -0,0 +1,24 @@
require 'test_plugin_helper'

module Api
module V2
class AnsibleRolesControllerTest < ActionController::TestCase
setup do
@role = FactoryGirl.create(:ansible_role)
end

test 'should get index' do
get :index, {}, set_session_user
response = JSON.parse(@response.body)
refute_empty response['results']
assert_response :success
end

test 'should destroy' do
delete :destroy, { :id => @role.id }, set_session_user
assert_response :ok
refute AnsibleRole.exists?(@role.id)
end
end
end
end
4 changes: 2 additions & 2 deletions test/support/fixture_support.rb
Expand Up @@ -10,9 +10,9 @@ def self.add_fixtures(new_fixture_path)
end

def self.copy_plugin_fixtures(new_fixture_path)
FIXTURE_MAPPING.each do |key, value|
FIXTURE_MAPPING.each do |key, value|
fixture_path = "#{ForemanAnsible::Engine.root}/test/fixtures/#{key}.yml"
return unless File.exists?(fixture_path)
break unless File.exist?(fixture_path)
File.open("#{new_fixture_path}/#{value}.yml", 'a') do |file|
File.open(fixture_path, 'r').each do |line|
next if line =~ /---/
Expand Down
2 changes: 1 addition & 1 deletion test/support/foreman_test_helper_additions.rb
Expand Up @@ -6,7 +6,7 @@ module AnsiblePermissionTestCase
included do
extend ActiveRecord::TestFixtures

new_fixture_path = Dir.mktmpdir("ansible_fixtures")
new_fixture_path = Dir.mktmpdir('ansible_fixtures')
self.fixture_path = new_fixture_path
ForemanAnsible::PluginFixtures.add_fixtures(new_fixture_path)
fixtures(:all)
Expand Down
28 changes: 28 additions & 0 deletions test/unit/services/api_roles_importer_test.rb
@@ -0,0 +1,28 @@
require 'test_plugin_helper'
# unit tests for ApiRolesImporter
class ApiRolesImporterTest < ActiveSupport::TestCase
setup do
@importer = ForemanAnsible::ApiRolesImporter.new
first_name = 'test_user.test_name'
second_name = 'some_user.some_role'
@test_roles = [AnsibleRole.new(:name => first_name),
AnsibleRole.new(:name => second_name)]
end

test 'should import roles' do
@importer.stubs(:import_role_names).returns(:new => @test_roles)
res = @importer.import!
assert_equal 2, res.count
assert AnsibleRole.find_by :name => @test_roles.first.name
assert AnsibleRole.find_by :name => @test_roles.last.name
end

test 'should obsolete roles' do
@importer.stubs(:import_role_names).returns(:obsolete => @test_roles)
@test_roles.map(&:save)
res = @importer.obsolete!
assert_equal 2, res.count
refute AnsibleRole.find_by :name => @test_roles.first.name
refute AnsibleRole.find_by :name => @test_roles.last.name
end
end
24 changes: 0 additions & 24 deletions test/unit/services/roles_importer_test.rb
Expand Up @@ -14,28 +14,4 @@ class RolesImporterTest < ActiveSupport::TestCase
assert_equal role.name, changes[:new].first.name
assert_equal @role.name, changes[:obsolete].first.name
end

test 'should create new role' do
changed_roles
refute AnsibleRole.find_by(:name => @new_role[:name])
@importer.create_new_roles(@changes['new'])
assert AnsibleRole.find_by(:name => @new_role[:name])
end

test 'should delete old roles' do
changed_roles
assert AnsibleRole.find_by(:name => @role.name)
@importer.delete_old_roles(@changes['obsolete'])
refute AnsibleRole.find_by(:name => @role.name)
end

private

def changed_roles
new_role_name = 'test_role.foreman'
@new_role = { :id => nil, :name => new_role_name }
@changes = { 'new' => { 'test_role.foreman' => @new_role.to_json },
'obsolete' => { @role.name => @role.to_json }
}
end
end
30 changes: 30 additions & 0 deletions test/unit/services/ui_roles_importer_test.rb
@@ -0,0 +1,30 @@
require 'test_plugin_helper'
# unit tests for UiRolesImporter
class UiRolesImporterTest < ActiveSupport::TestCase
setup do
changed_roles
@importer = ForemanAnsible::UiRolesImporter.new
end

test 'should create new role' do
refute AnsibleRole.find_by(:name => @new_role[:name])
@importer.create_new_roles(@changes['new'])
assert AnsibleRole.find_by(:name => @new_role[:name])
end

test 'should delete old roles' do
assert AnsibleRole.find_by(:name => @role.name)
@importer.delete_old_roles(@changes['obsolete'])
refute AnsibleRole.find_by(:name => @role.name)
end

private

def changed_roles
@role = FactoryGirl.create(:ansible_role)
new_role_name = 'test_role.foreman'
@new_role = { :id => nil, :name => new_role_name }
@changes = { 'new' => { 'test_role.foreman' => @new_role.to_json },
'obsolete' => { @role.name => @role.to_json } }
end
end

0 comments on commit 3a7067d

Please sign in to comment.