inspec/lib/bundles/inspec-init/cli.rb

102 lines
3.4 KiB
Ruby
Raw Normal View History

2016-02-14 10:59:02 +00:00
# encoding: utf-8
require 'pathname'
2016-02-14 20:26:37 +00:00
module Init
2016-02-14 10:59:02 +00:00
class CLI < Inspec::BaseCLI
2016-02-14 20:26:37 +00:00
namespace 'init'
2016-02-14 10:59:02 +00:00
2016-08-18 18:10:09 +00:00
# TODO: find another solution, once https://github.com/erikhuda/thor/issues/261 is fixed
def self.banner(command, _namespace = nil, _subcommand = false)
"#{basename} #{subcommand_prefix} #{command.usage}"
end
def self.subcommand_prefix
namespace
end
2016-02-14 10:59:02 +00:00
# read template directoy
template_dir = File.join(File.dirname(__FILE__), 'templates')
Dir.glob(File.join(template_dir, '*')) do |template|
relative = Pathname.new(template).relative_path_from(Pathname.new(template_dir))
# register command for the template
2016-02-14 20:26:37 +00:00
desc "#{relative} NAME", "Create a new #{relative}"
2016-02-14 10:59:02 +00:00
option :overwrite, type: :boolean, default: false,
desc: 'Overwrites existing directory'
define_method relative.to_s.to_sym do |name|
generator(relative.to_s, { name: name }, options)
end
end
private
# 1. iterate over all files
# 2. read content in erb
# 3. write to target
2016-02-14 20:26:37 +00:00
def generator(type, attributes = {}, options = {}) # rubocop:disable Metrics/AbcSize
2016-02-14 10:59:02 +00:00
# path of this script
dir = File.dirname(__FILE__)
# look for template directory
base_dir = File.join(dir, 'templates', type)
# prepare glob for all subdirectories and files
template = File.join(base_dir, '**', '{*,.*}')
# Use the name attribute to define the path to the profile.
profile_path = attributes[:name]
# Use slashes (\, /) to split up the name into an Array then use the last entry
# to reset the name of the profile.
attributes[:name] = attributes[:name].split(%r{\\|\/}).last
# Generate the full target path on disk
target = Pathname.new(Dir.pwd).join(profile_path)
2016-02-14 20:26:37 +00:00
puts "Create new #{type} at #{mark_text(target)}"
2016-02-14 10:59:02 +00:00
# check that the directory does not exist
if File.exist?(target) && !options['overwrite']
error "#{mark_text(target)} exists already, use --overwrite"
exit 1
end
2016-02-14 20:26:37 +00:00
# ensure that target directory is available
FileUtils.mkdir_p(target)
2016-02-14 10:59:02 +00:00
# iterate over files and write to target path
Dir.glob(template) do |file|
relative = Pathname.new(file).relative_path_from(Pathname.new(base_dir))
destination = Pathname.new(target).join(relative)
if File.directory?(file)
li "Create directory #{mark_text(relative)}"
FileUtils.mkdir_p(destination)
elsif File.file?(file)
2016-02-14 20:26:37 +00:00
li "Create file #{mark_text(relative)}"
2016-02-14 10:59:02 +00:00
# read & render content
content = render(File.read(file), attributes)
# write file content
File.write(destination, content)
else
2016-02-14 20:26:37 +00:00
puts "Ignore #{file}, because its not an file or directoy"
2016-02-14 10:59:02 +00:00
end
end
end
# This is a render helper to bind hash values to a ERB template
def render(content, hash)
# create a new binding class
cls = Class.new do
hash.each do |key, value|
define_method key.to_sym do
value
end
end
# expose binding
define_method :bind do
binding
end
end
ERB.new(content).result(cls.new.bind)
end
end
# register the subcommand to Inspec CLI registry
2016-02-14 20:26:37 +00:00
Inspec::Plugins::CLI.add_subcommand(Init::CLI, 'init', 'init TEMPLATE ...', 'Scaffolds a new project', {})
2016-02-14 10:59:02 +00:00
end