Skip to content
Open
160 changes: 160 additions & 0 deletions lib/puppet/provider/foreman_location/rest_v3.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# frozen_string_literal: true

Puppet::Type.type(:foreman_location).provide( # rubocop:disable Metrics/BlockLength
:rest_v3,
parent: Puppet::Type.type(:foreman_resource).provider(:rest_v3)
) do
desc 'foreman_location configures a location in foreman.'
confine feature: %i[json oauth]

def initialize(value = {})
super(value)
@property_flush = {}
end

def location # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
@location ||= begin
loc_search = search('locations', 'name', resource[:name]).first

return nil if loc_search.nil?

path = "api/v2/locations/#{loc_search['id']}"
req = request(:get, path)

unless success?(req)
raise Puppet::Error, "Error making GET request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

result = JSON.parse(req.body)
debug("Using Foreman Location '#{resource[:name]}' with: #{result}")
result
end
end

def id
location['id'] if location
end

def exists?
!id.nil?
end

def create # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
debug("Creating Foreman Location #{resource[:name]}")

path = 'api/v2/locations'
payload = {
location: {
name: resource[:name],
parent_id: resource[:parent] ? location_id(resource[:parent]) : nil,
description: resource[:description],
ignore_types: resource[:select_all_types],
domain_ids: domain_ids(resource[:domains]),
organization_ids: organization_ids(resource[:organizations])
}
}
req = request(:post, path, {}, payload.to_json)

return if success?(req)

raise Puppet::Error, "Error making POST request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

def destroy
debug("Destroying Foreman Location #{resource[:name]}")

path = "api/v2/locations/#{id}"
req = request(:delete, path)

unless success?(req)
raise Puppet::Error, "Error making DELETE request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

@location = nil
end

def flush
return if @property_flush.empty?

debug("Calling API to update properties for Foreman Location #{resource[:name]} with: #{@property_flush}")

path = "api/v2/locations/#{id}"
req = request(:put, path, {}, { location: @property_flush }.to_json)

return if success?(req)

raise Puppet::Error, "Error making PUT request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

def parent
location && location['parent_name'] ? locations['parent_name'].split('/')[-1] : nil
end

def parent=(value)
if value.nil?
@property_flush[:parent_id] = nil
else
parent_id = location_id(value)

raise Puppet::Error, "Could not find Foreman Location with name #{value} as parent." if parent_id.nil?

@property_flush[:parent_id] = parent_id
end
end

def description
location ? location['description'] : nil
end

def description=(value)
@property_flush[:description] = value
end

def select_all_types
location ? location['select_all_types'] : []
end

def select_all_types=(value)
@property_flush[:ignore_types] = value
end

def domains
location ? location['domains'].reject { |d| d['inherited'] }.map { |d| d['name'] } : nil
end

def domain_ids(domains)
return nil if domains.nil?

domains.map do |domain|
res = search('domains', 'name', domain).first

raise Puppet::Error, "Could not find Foreman Domain with name '#{domain}'" if res.nil?

res['id']
end
end

def domains=(value)
@property_flush[:domain_ids] = domain_ids(value)
end

def organizations
location ? location['organizations'].reject { |o| o['inherited'] }.map { |o| o['name'] } : nil
end

def organization_ids(orgs)
return nil if orgs.nil?

orgs.map do |organization|
org_id = organization_id(organization)

raise Puppet::Error, "Could not find Foreman Organization with name '#{organization}'" if org_id.nil?

org_id
end
end

def organizations=(value)
@property_flush[:organization_ids] = organization_ids(value)
end
end
160 changes: 160 additions & 0 deletions lib/puppet/provider/foreman_organization/rest_v3.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
# frozen_string_literal: true

Puppet::Type.type(:foreman_organization).provide( # rubocop:disable Metrics/BlockLength
:rest_v3,
parent: Puppet::Type.type(:foreman_resource).provider(:rest_v3)
) do
desc 'foreman_organization configures a organization in foreman.'
confine feature: %i[json oauth]

def initialize(value = {})
super(value)
@property_flush = {}
end

def organization # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
@organization ||= begin
org_search = search('organizations', 'name', resource[:name]).first

return nil if org_search.nil?

path = "api/v2/organizations/#{org_search['id']}"
req = request(:get, path)

unless success?(req)
raise Puppet::Error, "Error making GET request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

result = JSON.parse(req.body)
debug("Using Foreman Organization '#{resource[:name]}' with: #{result}")
result
end
end

def id
organization['id'] if organization
end

def exists?
!id.nil?
end

def create # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
debug("Creating Foreman Organization #{resource[:name]}")

path = 'api/v2/organizations'
payload = {
organization: {
name: resource[:name],
parent_id: resource[:parent] ? organization_id(resource[:parent]) : nil,
description: resource[:description],
ignore_types: resource[:select_all_types],
domain_ids: domain_ids(resource[:domains]),
location_ids: location_ids(resource[:locations])
}
}
req = request(:post, path, {}, payload.to_json)

return if success?(req)

raise Puppet::Error, "Error making POST request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

def destroy
debug("Destroying Foreman Organization #{resource[:name]}")

path = "api/v2/organizations/#{id}"
req = request(:delete, path)

unless success?(req)
raise Puppet::Error, "Error making DELETE request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

@organization = nil
end

def flush
return if @property_flush.empty?

debug("Calling API to update properties for Foreman Organization #{resource[:name]} with: #{@property_flush}")

path = "api/v2/organizations/#{id}"
req = request(:put, path, {}, { organization: @property_flush }.to_json)

return if success?(req)

raise Puppet::Error, "Error making PUT request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

def parent
organization && organization['parent_name'] ? organization['parent_name'].split('/')[-1] : nil
end

def parent=(value)
if value.nil?
@property_flush[:parent_id] = nil
else
parent_id = organization_id(value)

raise Puppet::Error, "Could not find Foreman Organzation with name #{value} as parent." if parent_id.nil?

@property_flush[:parent_id] = parent_id
end
end

def description
organization ? organization['description'] : nil
end

def description=(value)
@property_flush[:description] = value
end

def select_all_types
organization ? organization['select_all_types'] : []
end

def select_all_types=(value)
@property_flush[:ignore_types] = value
end

def domains
organization ? organization['domains'].reject { |d| d['inherited'] }.map { |d| d['name'] } : nil
end

def domain_ids(domains)
return nil if domains.nil?

domains.map do |domain|
res = search('domains', 'name', domain).first

raise Puppet::Error, "Could not find Foreman Domain with name '#{domain}'" if res.nil?

res['id']
end
end

def domains=(value)
@property_flush[:domain_ids] = domain_ids(value)
end

def locations
organization ? organization['locations'].reject { |l| l['inherited'] }.map { |l| l['name'] } : nil
end

def location_ids(locations)
return nil if locations.nil?

locations.map do |location|
location_id = location_id(location)

raise Puppet::Error, "Could not find Foreman Location with name '#{location}'" if location_id.nil?

location_id
end
end

def locations=(value)
@property_flush[:location_ids] = location_ids(value)
end
end
21 changes: 21 additions & 0 deletions lib/puppet/provider/foreman_resource/rest_v3.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,4 +131,25 @@ def error_message(response)
JSON.parse(response.body)['error']['full_messages'].join(' ') rescue "Response: #{response.code} #{response.message}"
end
end

def search(resource, key, value)
path = "api/v2/#{resource}"
req = request(:get, path, { search: %(#{key}="#{value}"), per_page: 'all' })

unless success?(req)
raise Puppet::Error, "Error making GET request to Foreman at #{request_uri(path)}: #{error_message(req)}"
end

JSON.parse(req.body)['results']
end

def location_id(name)
res = search('locations', 'name', name).first
res.nil? ? nil : res['id']
end

def organization_id(name)
res = search('organizations', 'name', name).first
res.nil? ? nil : res['id']
end
end
37 changes: 37 additions & 0 deletions lib/puppet/type/foreman_location.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

require 'puppet_x/foreman/common'

Puppet::Type.newtype(:foreman_location) do
desc 'foreman_location configures a location in foreman.'

instance_eval(&PuppetX::Foreman::Common::REST_API_COMMON_PARAMS)

newparam(:name) do
desc 'The name of the location'
end

newproperty(:parent) do
desc 'The name of the parent location'
end

newproperty(:description) do
desc 'The description of this location'
end

newproperty(:select_all_types, array_matching: :all) do
desc 'List of resource types for which to "Select All"'
end

newproperty(:domains, array_matching: :all) do
desc 'A list of domain names to allow for this location'
end

newproperty(:organizations, array_matching: :all) do
desc 'A list of organization names to allow for this location'
end

autorequire(:foreman_location) do
self[:parent] if self[:ensure] == :present
end
end
Loading