Skip to content

Instantly share code, notes, and snippets.

@chadh
Created January 28, 2016 18:46
Show Gist options
  • Select an option

  • Save chadh/1db218429aa4575ef7c0 to your computer and use it in GitHub Desktop.

Select an option

Save chadh/1db218429aa4575ef7c0 to your computer and use it in GitHub Desktop.
Puppet provider for pulp rpm repo
require 'json'
Puppet::Type::type(:pulp_repo).provide(:rpm) do
commands :pulp_admin => 'pulp-admin'
commands :mongoexport => 'mongoexport'
# magically define all getter methods (Thanks, Luke!)
mk_resource_methods
# query the pulp_database and merge some fields from multiple tables
def self.get_repos
ret = []
# Even though using 'commands' above allows us to just call mongoexport as
# a function, that combines stderr and stdout, which results in these
# commands failing. So we have to simulate the magic functionality
cmd = Puppet::Util::which 'mongoexport'
output = Puppet::Util::Execution::execute([cmd, '--jsonArray', '--db', 'pulp_database', '--collection', 'repos'], { :combine => false })
repos = JSON.parse(output)
output = Puppet::Util::Execution::execute([cmd, '--jsonArray', '--db', 'pulp_database', '--collection', 'repo_importers'], { :combine => false })
importers = JSON.parse(output)
output = Puppet::Util::Execution::execute([cmd, '--jsonArray', '--db', 'pulp_database', '--collection', 'repo_distributors'], { :combine => false })
distributors = JSON.parse(output)
repos.each do |r|
m = {}
m[:id] = r['id']
m[:description] = r['description']
m[:display_name] = r['display_name']
# m[:note] = r['note']
importers.each do |i|
if r['id'] == i['repo_id']
m[:feed] = i['config']['feed']
break
end
end
distributors.each do |d|
if r['id'] == d['repo_id']
m[:relative_url] = d['config']['relative_url']
m[:serve_http] = d['config']['http']
m[:serve_https] = d['config']['https']
break
end
end
# Puppet internals need a :name field
m[:name] = m[:id]
m[:ensure] = :present
ret.push(m)
end
ret
end
def self.instances
get_repos.collect do |r|
new(r)
end
end
def self.prefetch(resources)
instances.each do |prov|
if resource = resources[prov.name]
resource.provider = prov
end
end
end
def initialize(value={})
super(value)
# let's keep "should" values in @property_flush
@property_flush = {}
# :new [currently] indicates to flush whether to create or update
@property_flush[:new] = false
end
def exists?
@property_hash[:ensure] == :present
end
def create
@property_flush[:new] = true
@property_flush[:ensure] = :present
end
def destroy
@property_flush[:ensure] = :absent
end
# define setter methods to keep track of values that need to be updated
# mk_resource_methods actually does something similar, but it stores values
# in @property_hash. I'm following Gary Larizza's blog and using a different
# hash for storing updates. Might not be necessary, but it's explicit
[ # :note,
:feed,
:display_name,
:description,
:schedules,
:serve_http,
:serve_https
].each do |x|
define_method("#{x}=") do |value|
Puppet.debug("adding [#{value}] to @property_flush[#{x}]")
@property_flush[x] = value
end
end
# all of the calls to pulp-admin that change the system happen here.
# The argument string is based on properties that need to be updated
def set_repos
if @property_flush[:ensure] == :absent
Puppet.debug("calling pulp-admin with #{resource[:id]}")
pulp_admin('rpm','repo','delete',"--repo-id=#{resource[:id]}")
return
end
argarr = Array.new
argarr << "--repo-id" << resource[:id]
@property_flush.each do |k,v|
if k == :new or k == :ensure or k == :name or k == :id
next
end
# notes are added on the command line like "--note 'foo=bar' --note 'baz=x'"
# if k == :note
# v.each do |kk,vv|
# argarr << "--note" << "#{kk}='#{vv}'"
# end
# next
# end
argarr << "--#{k.to_s.gsub(/_/,'-')}" << v
end
@property_hash.each do |k,v|
if k == :ensure or k == :name or k == :id
next
end
if @property_flush.has_key?(k)
next
end
argarr << "--#{k.to_s.gsub(/_/,'-')}" << v
end
if @property_flush[:new]
pulp_admin('rpm','repo','create',*argarr)
else
pulp_admin('rpm','repo','update',*argarr)
end
end
def flush
set_repos
# This is a little bit annoying because it is querying everything just to
# get the state of a single repo, but at least it only happens when there
# is a change to a repo (so not very frequently)
cur = self.class.get_repos.detect { |r| r[:id] == resource[:id] }
if cur == nil
@property_hash = {}
else
@property_hash = cur
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment