mirror of
https://github.com/inspec/inspec
synced 2025-02-17 06:28:40 +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'))
|
output_dir = File.expand_path(File.join(File.dirname(__FILE__), '../app/responses'))
|
||||||
simulator = 'inspec-simulator'
|
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
|
# Create key given command
|
||||||
def create_key(command)
|
def create_key(command)
|
||||||
formatted_command = command.gsub(/\W/, '_')
|
formatted_command = command.gsub(/\W/, '_')
|
||||||
|
@ -57,56 +17,103 @@ def create_key(command)
|
||||||
not_too_long + '.txt'
|
not_too_long + '.txt'
|
||||||
end
|
end
|
||||||
|
|
||||||
puts '---> Create json files for web tutorial'
|
|
||||||
|
|
||||||
def indent(text)
|
def indent(text)
|
||||||
' ' + text
|
' ' + text
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create commands.json file
|
# loads all commands from tutorial.yml
|
||||||
commands_file = File.new(File.join(output_dir, 'commands.json'), 'w')
|
def load_tutorial_commands(demos)
|
||||||
commands_json = {}
|
# extract commands from instructions
|
||||||
commands.each { |x|
|
raw_commands = demos.map { |x| x['desc'] }.map { |x| x.scan(/```(.*?)```/m) }.flatten.map(&:strip).map { |x| x.split("\n") }
|
||||||
commands_json[x] = {
|
|
||||||
'key' => create_key(x),
|
# find out if we have a single command or a multiline shell command
|
||||||
# indicates if the command is part of the tutorial.yml
|
tutorial_commands = raw_commands.map { |x|
|
||||||
'extra' => extra_commands.include?(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
|
# special handling for InSpec shell commands
|
||||||
instructions_file = File.new(File.join(output_dir, 'instructions.json'), 'w')
|
shell_tutorial_commands = tutorial_commands.reject { |a| a.include?('inspec') }
|
||||||
tutorial_instructions.map! { |set| [set[0], GitHub::Markup.render('instructions.markdown', set[1])] }
|
commands += shell_tutorial_commands.map {|cmd|
|
||||||
puts JSON.generate(tutorial_instructions)
|
# Add 'echo' and ' | inspec shell' to shell commands to enable inspec shell command functionality
|
||||||
instructions_file.write(JSON.generate(tutorial_instructions))
|
simulator_cmd = 'echo ' + Shellwords.escape(cmd) + ' | inspec shell'
|
||||||
puts indent("Wrote #{instructions_file.path}")
|
{
|
||||||
|
'key' => create_key(simulator_cmd),
|
||||||
|
'command' => cmd,
|
||||||
|
'simulator_cmd' => simulator_cmd,
|
||||||
|
'extra' => false,
|
||||||
|
'shell' => 'inspec',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
commands
|
||||||
|
end
|
||||||
|
|
||||||
# Generate command results files
|
# load all commands from commands.yml
|
||||||
require 'docker'
|
def load_extra_commands(extra_commands)
|
||||||
fail "#{simulator} docker image is not available" unless Docker::Image.exist?(simulator)
|
extra_commands.map {|cmd|
|
||||||
|
{
|
||||||
|
'key' => create_key(cmd),
|
||||||
|
'command' => cmd,
|
||||||
|
'simulator_cmd' => cmd,
|
||||||
|
'extra' => true,
|
||||||
|
'shell' => 'sh',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
# start container and get id
|
def generate_webapp_instructions(demos, output_dir)
|
||||||
Docker.options[:read_timeout] = 3 * 60
|
# Create instructions.json file
|
||||||
container = Docker::Container.create('Cmd' => ['/bin/sh'], 'Image' => simulator, 'Tty' => true)
|
instructions_file = File.new(File.join(output_dir, 'instructions.json'), 'w')
|
||||||
container.start
|
tutorial_instructions = demos.map { |x| [x['title'], x['desc']] }
|
||||||
puts "---> Run simulation on Container #{container.id}"
|
tutorial_instructions.map! { |set| [set[0], GitHub::Markup.render('instructions.markdown', set[1])] }
|
||||||
# Create Train connection
|
instructions_file.write(JSON.generate(tutorial_instructions))
|
||||||
backend = Train.create('docker', { host: container.id })
|
puts indent("Wrote #{instructions_file.path}")
|
||||||
conn = backend.connection
|
end
|
||||||
|
|
||||||
# Loop over commands
|
def generate_webapp_commands(commands, output_dir)
|
||||||
commands.each do |command|
|
# Create commands.json file
|
||||||
puts indent("Run `#{command}`")
|
commands_file = File.new(File.join(output_dir, 'commands.json'), 'w')
|
||||||
cmd = conn.run_command(command)
|
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
|
cmd.stdout
|
||||||
|
|
||||||
# save the result and put it in inspec/www/app/responses with command as filename
|
# save the result and put it in inspec/www/app/responses with command as filename
|
||||||
result = cmd.stdout
|
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)
|
filename = File.join(output_dir, key.to_s)
|
||||||
out_file = File.new(filename, 'w')
|
out_file = File.new(filename, 'w')
|
||||||
result.lines.each do |line|
|
result.lines.each do |line|
|
||||||
|
@ -117,6 +124,39 @@ commands.each do |command|
|
||||||
puts indent("Wrote #{filename}")
|
puts indent("Wrote #{filename}")
|
||||||
end
|
end
|
||||||
|
|
||||||
# close train connection and stop container
|
def generate_simulation_files(simulator, commands, output_dir)
|
||||||
conn.close
|
require 'docker'
|
||||||
container.kill
|
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…
Add table
Reference in a new issue