inspec/lib/bundles/inspec-init/cli.rb
Miah Johnson a084187b21 When a profile is created with init, the last item after a / is the (#3175)
profile name. eg "with/slash" would result in a profile created in the
"with" directory named "slash"

Add test for inspec init, and updated other for new output.

Clean up profiles created during testing and place them in temporary
directories.

Describe our test a bit better.
Check that the profile was created in the right location.
Check that the profile is named correctly.

Signed-off-by: Miah Johnson <miah@chia-pet.org>
2018-07-05 15:37:18 -04:00

101 lines
3.4 KiB
Ruby

# encoding: utf-8
require 'pathname'
module Init
class CLI < Inspec::BaseCLI
namespace 'init'
# 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
# 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
desc "#{relative} NAME", "Create a new #{relative}"
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
def generator(type, attributes = {}, options = {}) # rubocop:disable Metrics/AbcSize
# 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)
puts "Create new #{type} at #{mark_text(target)}"
# check that the directory does not exist
if File.exist?(target) && !options['overwrite']
error "#{mark_text(target)} exists already, use --overwrite"
exit 1
end
# ensure that target directory is available
FileUtils.mkdir_p(target)
# 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)
li "Create file #{mark_text(relative)}"
# read & render content
content = render(File.read(file), attributes)
# write file content
File.write(destination, content)
else
puts "Ignore #{file}, because its not an file or directoy"
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
Inspec::Plugins::CLI.add_subcommand(Init::CLI, 'init', 'init TEMPLATE ...', 'Scaffolds a new project', {})
end