Created
November 21, 2018 14:10
-
-
Save LadyNamedLaura/cab8cd9aeb58849164799df1c1a9afe7 to your computer and use it in GitHub Desktop.
update_fixtures.rb
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
require 'yaml' | |
require 'json' | |
require 'pathname' | |
require 'digest/sha1' | |
require 'optparse' | |
require 'ostruct' | |
options = OpenStruct.new | |
options.from_metadata = false | |
options.paths = [] | |
options.puppetfile = nil | |
parser = OptionParser.new do |opts| | |
opts.accept(Pathname) do |path| | |
(Pathname.new path).cleanpath() | |
end | |
opts.banner = "Usage: update_fixtures.rb [options] [module]" | |
opts.on("-m", "--modulepath=PATH", Pathname, | |
'local module paths to load') do |path| | |
options.paths.push path | |
end | |
opts.on("-p", "--puppetfile=FILE", Pathname, | |
"path to the puppetfile") do | path| | |
p "puppetfie: #{path}" | |
end | |
opts.on("-r", "--recursive", "Walk the given directories in search of modules to update") do |r| | |
options.recursive = r | |
end | |
opts.on('--from-metadata', | |
'Get dependency data from metadata.json') do |m| | |
options.from_metadata = m | |
end | |
opts.on_tail("-h", "--help", "Show this message") do | |
puts opts | |
exit | |
end | |
end | |
parser.parse! | |
if ARGV.empty? | |
puts parser | |
exit | |
end | |
if options.puppetfile.nil? | |
options.treeroot = Pathname.pwd | |
else | |
options.treeroot = options.puppetfile.dirname | |
end | |
while options.puppetfile.nil? | |
if (options.treeroot+'Puppetfile').file? | |
options.puppetfile = (options.treeroot+'Puppetfile') | |
else | |
options.treeroot = options.treeroot.dirname | |
end | |
if options.treeroot.to_s == '/' | |
raise 'no Puppetfile found' | |
end | |
end | |
CACHEDIR=options.treeroot+'.modulecache' | |
CACHEDIR.mkpath | |
class PuppetModule | |
def initialize(fname) | |
@author, @name = fname.split(/[\/-]/) | |
end | |
def author | |
@author | |
end | |
def name | |
@name | |
end | |
def fullname | |
"#{@author}-#{@name}" | |
end | |
def install | |
end | |
def metadata | |
return @metadata unless @metadata.nil? | |
install | |
@metadata = JSON.parse((path+'metadata.json').read) | |
end | |
def path | |
CACHEDIR+fullname+version+name | |
end | |
def installed? | |
(path + 'metadata.json').file? | |
end | |
end | |
class ForgeModule < PuppetModule | |
def initialize(fname,version) | |
super(fname) | |
@version = version | |
end | |
def version | |
@version | |
end | |
def install | |
return if installed? | |
system("puppet module install -f -i #{path.dirname} -v #{version} #{fullname}") | |
end | |
def as_local | |
LocalModule.new () | |
end | |
def fixturetype | |
"forge_modules" | |
end | |
def fixture(options) | |
{ | |
name => { | |
'repo' => fullname, | |
'ref' => version, | |
} | |
} | |
end | |
end | |
class GitModule < PuppetModule | |
def initialize(fname, repourl, ref) | |
super(fname) | |
@url = repourl | |
@ref = ref | |
end | |
def version | |
@ref | |
end | |
def install | |
return if installed? | |
clonepath = CACHEDIR+'.gitrepos'+Digest::SHA1.hexdigest(@url) | |
unless clonepath.directory? | |
system("git clone --bare #{@url} #{clonepath}") | |
end | |
path.mkpath() | |
gitenv={ | |
'GIT_DIR' => clonepath.to_s, | |
'GIT_WORK_TREE' => path.to_s, | |
} | |
system(gitenv,"git checkout -qf #{version}") | |
end | |
def fixturetype | |
"repositories" | |
end | |
def fixture(options) | |
{ | |
name => { | |
'repo' => @url, | |
'ref' => @ref, | |
} | |
} | |
end | |
end | |
class LocalModule < PuppetModule | |
def initialize(name, path) | |
super("local/#{name}") | |
@path = path | |
end | |
def fixturetype | |
"symlinks" | |
end | |
def fixture(options) | |
if options.has_key? :relpath | |
relpath = path.relative_path_from(options[:relpath]) | |
if relpath.to_s == '.' | |
p = '#{source_dir}' | |
else | |
p = '#{source_dir}/'+relpath.to_s | |
end | |
else | |
p = path.to_s | |
end | |
{ | |
@name => p | |
} | |
end | |
def path | |
@path | |
end | |
end | |
class ModuleLib | |
def initialize(hash={}) | |
@lib = hash | |
end | |
def add(mod) | |
@lib[mod.name] = mod | |
end | |
def addall(otherlib) | |
@lib.update otherlib.modules | |
end | |
def has?(name) | |
name = name.split(/[\/-]/).last | |
@lib.has_key?(name) | |
end | |
def get(name) | |
name = name.split(/[\/-]/).last | |
@lib[name] | |
end | |
def get_with_dependencies(name) | |
mods = ModuleLib.new | |
mods.add(get(name)) | |
newmods = [get(name)] | |
while newmods.any? do | |
nextmods = [] | |
newmods.each do |newmod| | |
newmod.metadata['dependencies'].each do |dep| | |
next if mods.has? dep['name'] | |
next unless has? dep['name'] | |
depmod = get dep['name'] | |
nextmods.push depmod | |
mods.add depmod | |
end | |
end | |
newmods = nextmods | |
end | |
mods | |
end | |
def modules | |
@lib | |
end | |
def by_fixturetype(type) | |
modules.select {|k,v| v.fixturetype == type} | |
end | |
def to_fixtures(options) | |
fixtures = {} | |
['repositories','forge_modules','symlinks'].each do |type| | |
temp = {} | |
by_fixturetype(type).each do |name, mod| | |
temp.update mod.fixture(options) | |
end | |
fixtures[type] = Hash[ temp.sort_by { |key, val| key } ] | |
end | |
{ | |
'fixtures' => fixtures | |
} | |
end | |
def import_from_puppetfile(filename) | |
PuppetFileBinding.new(self).get.eval(File.read(filename), filename.to_s) | |
end | |
def import_from_dir(dir) | |
dir = Pathname.new dir | |
dir = dir.realpath() | |
dir.each_child do |child| | |
add LocalModule.new child.basename, child | |
end | |
end | |
class PuppetFileBinding | |
def initialize(library) | |
@library = library | |
end | |
def mod(name, version = nil, git: nil, ref: nil, tag: nil) | |
if git.nil? | |
@library.add ForgeModule.new(name, version) | |
elsif tag.nil? | |
@library.add GitModule.new(name, git, ref) | |
else | |
@library.add GitModule.new(name, git, tag) | |
end | |
end | |
def get | |
binding | |
end | |
end | |
end | |
def find_modules(path) | |
return [] unless path.directory? | |
return [path.realpath] if (path + 'metadata.json').file? | |
modules = [] | |
path.each_child do |child| | |
modules += find_modules child | |
end | |
return modules | |
end | |
# main | |
all = ModuleLib.new | |
all.import_from_puppetfile(options.puppetfile) | |
options.paths.each {|path| all.import_from_dir(path)} | |
modules = [] | |
ARGV.each do |argument| | |
if options.recursive | |
modules = find_modules(Pathname.new(argument)) | |
else | |
modules = [Pathname.new(argument).realpath] | |
end | |
end | |
modules.each do |moddir| | |
fixturesfile = moddir+'.fixtures.yml' | |
lib = ModuleLib.new(all.modules) | |
mod = LocalModule.new(moddir.basename, moddir) | |
lib.add(mod) | |
if options.from_metadata | |
outlib = lib.get_with_dependencies(mod.name) | |
else | |
outlib = ModuleLib.new | |
# work from existing .fixturs.yml | |
data = YAML.load(fixturesfile.read) | |
data['fixtures'].each do |type, fixtures| | |
fixtures.each_key do |name| | |
outlib.add(lib.get(name)) | |
end | |
end | |
end | |
fixturesfile.open("w") do |file| | |
file.write(outlib.to_fixtures(:relpath => moddir).to_yaml) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment