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

Fixes #15979 - Add API for Ansible roles #26

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/controllers/ansible_roles_controller.rb
Expand Up @@ -47,6 +47,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, '/asnible/ansible_roles/obsolete', N_('Obsolete Ansible roles')
Copy link
Member

Choose a reason for hiding this comment

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

typo, I'll fix it on merge.

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)
assert response['results'].length > 0
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
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
31 changes: 31 additions & 0 deletions test/unit/services/ui_roles_importer_test.rb
@@ -0,0 +1,31 @@
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