Last active
December 15, 2015 19:18
-
-
Save paaloeye/5309999 to your computer and use it in GitHub Desktop.
Puppet: Get file content for File resource with content attribute
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Purpose: Get content of file from Puppet catalog | |
# | |
# Usage: ruby file.rb args | |
# Args: | |
# | Name | Desc | Default | |
# ------------------------------------------ | |
# | node | | | |
# | path | \ | |
# | environment | production \ | |
# | |
# Environment variables: | |
# ----------------------------------------------------------- | |
# | NO_SSL=1 | Don't use SSL | 0 | |
# | MASTER | FQDN of master | puppet | |
# ----------------------------------------------------------- | |
# | |
require 'rubygems' | |
require 'json' | |
require 'pp' | |
require 'net/http' | |
require 'openssl' | |
require 'uri' | |
require 'pry' | |
require 'fileutils' | |
require 'pathname' | |
def define_func(name, &body) | |
$context ||= context_default | |
define_method(name) do |*args| | |
body.call($context, *args) | |
end | |
end | |
def context_default | |
{ | |
:no_ssl => ENV['NO_SSL'].nil? ? false : true, | |
:environment => 'production', | |
:master => ENV['MASTER'].nil? ? 'puppet' : ENV['MASTER'], | |
:key => '/Users/paulche/tmp/var/puppet/ssl/private_keys/host.vagrant.local.pem', | |
:cert => '/Users/paulche/tmp/var/puppet/ssl/certs/host.vagrant.local.pem', | |
:cacert => '/Users/paulche/tmp/var/puppet/ssl/certs/ca.pem', | |
:tmpdir => '/Users/paulche/tmp/concat-puppet' | |
} | |
end | |
define_func(:retrieve_catalog) do |context| | |
rest = "catalog/#{context[:node]}" | |
res = get_https_content(rest,{'accept' => 'pson'}) | |
JSON.load(res)["data"]["resources"] | |
end | |
define_func(:context) do |context| | |
context | |
end | |
define_func(:get_https_content) do |context, rest, headers| | |
uri = URI.parse("https://#{context[:master]}:8140/#{context[:environment]}/#{rest}") | |
http = Net::HTTP.new(uri.host, uri.port) | |
http.use_ssl = true | |
if context[:no_ssl] | |
http.verify_mode = OpenSSL::SSL::VERIFY_NONE | |
else | |
http.cert = OpenSSL::X509::Certificate.new(File.read(context[:cert])) | |
http.ca_file = context[:cacert] | |
http.key = OpenSSL::PKey::RSA.new(File.read(context[:key])) | |
http.verify_mode = OpenSSL::SSL::VERIFY_PEER | |
end | |
request = Net::HTTP::Get.new(uri.request_uri) | |
headers.each do |k,v| | |
request[k] = v | |
end | |
response = http.request(request) | |
response.body | |
end | |
define_func(:setup) do |context,args| | |
usage_proc = proc { $stderr.puts "Usage: ruby file.rb node path [environment]"; exit(0) } | |
fail_proc = proc { $stderr.puts "ERROR: Try --help"; exit(2) } | |
case args.count | |
when 0 | |
usage_proc.call | |
when 1 | |
if args.first == '--help' | |
usage_proc.call | |
else | |
fail_proc.call | |
end | |
when 2 | |
context[:node] = args[0] | |
context[:path] = args[1] | |
when 3 | |
context[:node] = args[0] | |
context[:path] = args[1] | |
context[:environment] = args[2] | |
else | |
fail_proc.call | |
end | |
end | |
define_func(:setup_concat) do |context, catalog| | |
FileUtils.mkdir(context[:tmpdir]) unless File.exists?(context[:tmpdir]) | |
end | |
define_func(:concat_wrap) do |context, catalog| | |
FileUtils.mkdir_p("#{context[:tmpdir]}/concat/fragments") unless File.exists?("#{context[:tmpdir]}/concat/fragments") | |
context[:safe_path] = context[:path].gsub(%r{[/\n]},"_") | |
find = Regexp.new("#{context[:safe_path]}/fragments/.+") | |
fragments = catalog.select { |el| el['type'] == 'File' and el['title'] =~ find } | |
res = concat_exec(catalog, fragments) | |
FileUtils.rm_rf context[:tmpdir] | |
res | |
end | |
define_func(:concat_exec) do |context, catalog, fragments| | |
fragments.each do |el| | |
title = el['title'] | |
basename = Pathname.new(title).basename | |
tmpdir = "#{context[:tmpdir]}/concat/fragments" | |
to_write = if content = el['parameters']['content'] | |
content | |
elsif src = el['parameters']['source'] | |
get_https_content("file_content#{URI(src).path}", {'accept' => '*/*'}) | |
else | |
end | |
File.open("#{tmpdir}/#{basename}", :mode => 'w' ) { |f| f.write(to_write) } | |
end | |
# Retreive concatfragments.sh | |
exec_title = "concat_#{context[:path]}" | |
exec_resource = catalog.detect { |el| el['type'] == 'Exec' and el['title'] == exec_title } | |
exec_resource['parameters']['command'] =~ /^([^ ]+) -o/ | |
resource = catalog.detect { |el| el['type'] == 'File' and el['title'] == $1 } | |
concat = get_https_content("file_content#{URI(resource['parameters']['source']).path}", {'accept' => '*/*'}) | |
File.open("#{context[:tmpdir]}/concat.sh", :mode => 'w' ) { |f| f.write(concat) } | |
FileUtils.chmod 0777, "#{context[:tmpdir]}/concat.sh" | |
# Reduce fragments to signle file | |
exec_resource['parameters']['command'] =~ /^([^ ]+) -o ([^ ]+) -d ([^ ]+)(.*)$/ | |
exec = "#{context[:tmpdir]}/concat.sh -o #{context[:tmpdir]}/concat.out -d #{context[:tmpdir]}/concat #{$4}" | |
Kernel.system(exec) | |
File.read("#{context[:tmpdir]}/concat.out") | |
end | |
# | |
# Main part | |
# | |
# | |
# Plot | |
# 1. Get catalog | |
# 2. Determine type of file: | |
# * template | |
# Print content of file | |
# * source | |
# Retrive content of file via second request | |
# Print content of file | |
# * concat | |
# Get all fragment | |
# Find out type of fragment | |
# source | |
# Retrive content of file via second request | |
# template | |
# Return content param | |
# | |
def main | |
setup ARGV | |
path = context[:path] | |
catalog = retrieve_catalog | |
# 2. Find out type of file | |
file_resource = catalog.detect do |el| | |
el['type'] == 'File' and \ | |
(el['parameters'] \ | |
and (!el['parameters']['alias'] or (el['parameters']['alias'] !~ /^concat/)) \ | |
and (!el['parameters']['path'] and el['title'] == path) \ | |
or (el['parameters']['path'] and el['parameters']['path'] == path)) | |
end | |
if file_resource | |
# source, template types | |
if src = file_resource['parameters']['source'] | |
puts get_https_content("file_content#{URI(src).path}", {'accept' => '*/*'}) | |
exit(0) | |
elsif content = file_resource['parameters']['content'] | |
puts content | |
exit(0) | |
end | |
else | |
# either concat or not_found | |
if catalog.detect { |el| el['type'] == 'Concat' and el['parameters']['path'] == path } | |
# Concat type | |
# _etc_motd/fragments | |
# /var/lib/puppet/concat/_etc_motd/fragments/02_motd_header2 | |
setup_concat | |
puts concat_wrap(catalog) | |
exit(0) | |
else | |
$stderr.puts "File wasn't found in the catalog" | |
exit(41) | |
end | |
end | |
end | |
main |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment