mirror of
https://github.com/inspec/inspec
synced 2024-11-23 13:13:22 +00:00
update simulator generator script
This commit is contained in:
parent
6fc201458f
commit
76fc43fd36
1 changed files with 119 additions and 79 deletions
|
@ -10,46 +10,6 @@ input_dir = File.expand_path(File.join(File.dirname(__FILE__), '../content'))
|
|||
output_dir = File.expand_path(File.join(File.dirname(__FILE__), '../app/responses'))
|
||||
simulator = 'inspec-simulator'
|
||||
|
||||
puts '---> Load Content'
|
||||
|
||||
# Load tutorial instructions
|
||||
demos = YAML.load(File.read(File.join(input_dir, 'tutorial.yml')))['demos']
|
||||
tutorial_instructions = demos.map { |x| [x['title'], x['desc']] }
|
||||
|
||||
# extract commands from instructions
|
||||
commands = demos.map { |x| x['desc'] }.map { |x| x.scan(/```(.*?)```/m) }.flatten.map(&:strip).map { |x| x.split("\n") }
|
||||
|
||||
puts '---> Prepare Simulation Commands'
|
||||
|
||||
# find out if we have a single command or a multiline shell command
|
||||
cmds = commands.map { |x|
|
||||
cmd = x.join("\n")
|
||||
if cmd.include?('describe')
|
||||
cmd
|
||||
else
|
||||
x
|
||||
end
|
||||
}
|
||||
tutorial_commands = cmds.flatten
|
||||
|
||||
# Pull shell commands out so they can be handled
|
||||
# This is currently done by checking if the command includes the word inspec :/
|
||||
no_shell_tutorial_commands = tutorial_commands.select { |a| a.include?('inspec') && a != 'inspec shell' }
|
||||
shell_tutorial_commands = tutorial_commands.reject { |a| a.include?('inspec') }
|
||||
|
||||
# escape the shell commands for echo
|
||||
shell_tutorial_commands.map! { |x|
|
||||
Shellwords.escape(x)
|
||||
}
|
||||
# Add 'echo' and ' | inspec shell' to shell commands to enable inspec shell command functionality
|
||||
shell_commands = shell_tutorial_commands.map { |x| 'echo ' + x + ' | inspec shell' }
|
||||
|
||||
# extract commands
|
||||
extra_commands = YAML.load(File.read(File.join(input_dir, 'commands.yml')))['commands']
|
||||
|
||||
# Merge the output
|
||||
commands = no_shell_tutorial_commands + extra_commands + shell_commands
|
||||
|
||||
# Create key given command
|
||||
def create_key(command)
|
||||
formatted_command = command.gsub(/\W/, '_')
|
||||
|
@ -57,56 +17,103 @@ def create_key(command)
|
|||
not_too_long + '.txt'
|
||||
end
|
||||
|
||||
puts '---> Create json files for web tutorial'
|
||||
|
||||
def indent(text)
|
||||
' ' + text
|
||||
end
|
||||
|
||||
# Create commands.json file
|
||||
commands_file = File.new(File.join(output_dir, 'commands.json'), 'w')
|
||||
commands_json = {}
|
||||
commands.each { |x|
|
||||
commands_json[x] = {
|
||||
'key' => create_key(x),
|
||||
# indicates if the command is part of the tutorial.yml
|
||||
'extra' => extra_commands.include?(x),
|
||||
# loads all commands from tutorial.yml
|
||||
def load_tutorial_commands(demos)
|
||||
# extract commands from instructions
|
||||
raw_commands = demos.map { |x| x['desc'] }.map { |x| x.scan(/```(.*?)```/m) }.flatten.map(&:strip).map { |x| x.split("\n") }
|
||||
|
||||
# find out if we have a single command or a multiline shell command
|
||||
tutorial_commands = raw_commands.map { |x|
|
||||
cmd = x.join("\n")
|
||||
if cmd.include?('describe')
|
||||
cmd
|
||||
else
|
||||
x
|
||||
end
|
||||
}.flatten
|
||||
|
||||
# Pull shell commands out so they can be handled
|
||||
# This is currently done by checking if the command includes the word inspec :/
|
||||
no_shell_tutorial_commands = tutorial_commands.select { |a| a.include?('inspec') && a != 'inspec shell' }
|
||||
commands = no_shell_tutorial_commands.map {|cmd|
|
||||
{
|
||||
'key' => create_key(cmd),
|
||||
'command' => cmd,
|
||||
'simulator_cmd' => cmd,
|
||||
'extra' => false,
|
||||
'shell' => 'sh',
|
||||
}
|
||||
}
|
||||
}
|
||||
puts JSON.generate(commands_json)
|
||||
commands_file.write(JSON.generate(commands_json))
|
||||
puts indent("Wrote #{commands_file.path}")
|
||||
|
||||
# Create instructions.json file
|
||||
instructions_file = File.new(File.join(output_dir, 'instructions.json'), 'w')
|
||||
tutorial_instructions.map! { |set| [set[0], GitHub::Markup.render('instructions.markdown', set[1])] }
|
||||
puts JSON.generate(tutorial_instructions)
|
||||
instructions_file.write(JSON.generate(tutorial_instructions))
|
||||
puts indent("Wrote #{instructions_file.path}")
|
||||
# special handling for InSpec shell commands
|
||||
shell_tutorial_commands = tutorial_commands.reject { |a| a.include?('inspec') }
|
||||
commands += shell_tutorial_commands.map {|cmd|
|
||||
# Add 'echo' and ' | inspec shell' to shell commands to enable inspec shell command functionality
|
||||
simulator_cmd = 'echo ' + Shellwords.escape(cmd) + ' | inspec shell'
|
||||
{
|
||||
'key' => create_key(simulator_cmd),
|
||||
'command' => cmd,
|
||||
'simulator_cmd' => simulator_cmd,
|
||||
'extra' => false,
|
||||
'shell' => 'inspec',
|
||||
}
|
||||
}
|
||||
commands
|
||||
end
|
||||
|
||||
# Generate command results files
|
||||
require 'docker'
|
||||
fail "#{simulator} docker image is not available" unless Docker::Image.exist?(simulator)
|
||||
# load all commands from commands.yml
|
||||
def load_extra_commands(extra_commands)
|
||||
extra_commands.map {|cmd|
|
||||
{
|
||||
'key' => create_key(cmd),
|
||||
'command' => cmd,
|
||||
'simulator_cmd' => cmd,
|
||||
'extra' => true,
|
||||
'shell' => 'sh',
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
# start container and get id
|
||||
Docker.options[:read_timeout] = 3 * 60
|
||||
container = Docker::Container.create('Cmd' => ['/bin/sh'], 'Image' => simulator, 'Tty' => true)
|
||||
container.start
|
||||
puts "---> Run simulation on Container #{container.id}"
|
||||
# Create Train connection
|
||||
backend = Train.create('docker', { host: container.id })
|
||||
conn = backend.connection
|
||||
def generate_webapp_instructions(demos, output_dir)
|
||||
# Create instructions.json file
|
||||
instructions_file = File.new(File.join(output_dir, 'instructions.json'), 'w')
|
||||
tutorial_instructions = demos.map { |x| [x['title'], x['desc']] }
|
||||
tutorial_instructions.map! { |set| [set[0], GitHub::Markup.render('instructions.markdown', set[1])] }
|
||||
instructions_file.write(JSON.generate(tutorial_instructions))
|
||||
puts indent("Wrote #{instructions_file.path}")
|
||||
end
|
||||
|
||||
# Loop over commands
|
||||
commands.each do |command|
|
||||
puts indent("Run `#{command}`")
|
||||
cmd = conn.run_command(command)
|
||||
def generate_webapp_commands(commands, output_dir)
|
||||
# Create commands.json file
|
||||
commands_file = File.new(File.join(output_dir, 'commands.json'), 'w')
|
||||
commands_file.write(JSON.generate(commands))
|
||||
puts indent("Wrote #{commands_file.path}")
|
||||
end
|
||||
|
||||
def run_command(command, conn, output_dir)
|
||||
puts indent("Run `#{command['command']}` on `#{command['shell']}`")
|
||||
cmd = conn.run_command(command['simulator_cmd'])
|
||||
cmd.stdout
|
||||
|
||||
# save the result and put it in inspec/www/app/responses with command as filename
|
||||
result = cmd.stdout
|
||||
|
||||
key = create_key(command)
|
||||
# filter inspec shell welcome message
|
||||
welcome = "To find out how to use it, type: [1mhelp[0m\n\n"
|
||||
# To find out how to use it, type: [1mhelp[0m
|
||||
idx = result.index(welcome)
|
||||
if command['shell'] == 'inspec' && !idx.nil?
|
||||
# find welcome message
|
||||
index = idx + welcome.length
|
||||
# also remove the command before the welcome message
|
||||
result = result.slice(index, result.length - index)
|
||||
end
|
||||
|
||||
key = command['key']
|
||||
filename = File.join(output_dir, key.to_s)
|
||||
out_file = File.new(filename, 'w')
|
||||
result.lines.each do |line|
|
||||
|
@ -117,6 +124,39 @@ commands.each do |command|
|
|||
puts indent("Wrote #{filename}")
|
||||
end
|
||||
|
||||
# close train connection and stop container
|
||||
conn.close
|
||||
container.kill
|
||||
def generate_simulation_files(simulator, commands, output_dir)
|
||||
require 'docker'
|
||||
fail "#{simulator} docker image is not available" unless Docker::Image.exist?(simulator)
|
||||
|
||||
# start container and get id
|
||||
Docker.options[:read_timeout] = 3 * 60
|
||||
container = Docker::Container.create('Cmd' => ['/bin/sh'], 'Image' => simulator, 'Tty' => true)
|
||||
container.start
|
||||
puts indent("Run simulation on Container #{container.id}")
|
||||
# Create Train connection
|
||||
backend = Train.create('docker', { host: container.id })
|
||||
conn = backend.connection
|
||||
|
||||
# Loop over sh commands
|
||||
commands.each do |command|
|
||||
run_command(command, conn, output_dir)
|
||||
end
|
||||
|
||||
# close train connection and stop container
|
||||
conn.close
|
||||
container.kill
|
||||
end
|
||||
|
||||
# start workflow
|
||||
puts '---> Load Content'
|
||||
# Load tutorial instructions
|
||||
demos = YAML.load(File.read(File.join(input_dir, 'tutorial.yml')))['demos']
|
||||
commands = load_tutorial_commands(demos)
|
||||
|
||||
extra_commands = YAML.load(File.read(File.join(input_dir, 'commands.yml')))['commands']
|
||||
commands += load_extra_commands(extra_commands)
|
||||
|
||||
puts '---> Create files for web app'
|
||||
generate_webapp_instructions(demos, output_dir)
|
||||
generate_webapp_commands(commands, output_dir)
|
||||
generate_simulation_files(simulator, commands, output_dir)
|
||||
|
|
Loading…
Reference in a new issue