Skip to content

Commit

Permalink
optimize command simulator auto-generation
Browse files Browse the repository at this point in the history
  • Loading branch information
chris-rock committed Sep 15, 2016
1 parent 913a8fd commit 90e3b86
Show file tree
Hide file tree
Showing 60 changed files with 565 additions and 411 deletions.
6 changes: 6 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ group :integration do
gem 'kitchen-dokken'
end

group :simulator do
gem 'github-markup'
gem 'redcarpet'
gem 'docker-api'
end

group :tools do
gem 'pry', '~> 0.10'
gem 'rb-readline'
Expand Down
4 changes: 2 additions & 2 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ task lint: [:rubocop]
# update command output for demo
desc 'Run inspec commands and save results to www/app/responses'
task :update_demo do
commands = 'tasks/command_simulator.rb'
ruby commands
ruby 'www/tutorial/scripts/build_simulator_runtime.rb'
ruby 'www/tutorial/scripts/run_simulator_recording.rb'
end

# run tests
Expand Down
94 changes: 0 additions & 94 deletions tasks/command_simulator.rb

This file was deleted.

3 changes: 2 additions & 1 deletion www/tutorial/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ app/*.map
app/**/*.js
app/**/*.map

!webpack.config.js
!webpack.config.js
scripts/simulator/filesystem/examples/profile/*
48 changes: 16 additions & 32 deletions www/tutorial/README.md
Original file line number Diff line number Diff line change
@@ -1,61 +1,45 @@
# Welcome to the InSpec Tutorial
-----------------------------------------------------------


## The InSpec whaaaat? What is this thing?

This is an Angular 2 app that uses Xterm (https://github.com/sourcelair/xterm.js/) to simulate a terminal.
'Ok, but why?'
To give people an easy quick introduction to inspec and all it can do! Give it a try,
To give people an easy quick introduction to InSpec and all it can do! Give it a try,
learn a thing or two, tell us what you'd like to know more about, and have fun exploring!


## How to run it

run `npm install` to load dependencies
run `npm run start` to open in your browser @ localhost:8080

-----------------------------------------------------------

## How does it work???

Well, let me tell you a story of a file named `tutorial.yml`, who lives in a directory named `inspec/www/tutorial/tutorial_files`.

This kind, informational file was full of content, and oh so desired to spread its knowledge.
But it knew not how to do so, for it was a simple yml file.
Well, let me tell you a story of a file named `tutorial.yml`, who lives in a directory named `content`. This kind, informational file was full of content, and oh so desired to spread its knowledge. But it knew not how to do so, for it was a simple yml file.

Then, from around the corner, came a sweet little ruby file, whose only wish was to help people
do the things they needed to do. It's name, in fact, was `command_simulator.rb`, and it lived in a
nearby directory named `inspec/tasks`. And, aha, a match was found.
do the things they needed to do. It's name, in fact, was `run_simulator_recording.rb`, and it lived in a nearby directory named `scripts`. And, aha, a match was found.

And so command_simulator kindly took tutorialyml by the hand, and said 'let me help you! I can parse you, and help you help others'.
And so `run_simulator_recording.rb` kindly took `tutorial.yml` by the hand, and said 'let me help you! I can parse you, and help you help others'.
And thus it began...
command_simulator parsed tutorialyml to find the instructions and commands that are noted in the instructions.
After that, the real fun began: command_simulator worked and worked to format the commands and prepare them.
She created json files for instructions and commands, and used Train with MixLib:Shellout in the background to
run the commands and record the output to some .txt files in the `www/tutorial/app/responses` directory.
Pleased with her work, command_simulator turned to her friend the webapp, and said to her: 'take these json files, and show them to the people.'
`run_simulator_recording.rb` parsed `tutorial.yml` to find the instructions and commands that are noted in the instructions. After that, the real fun began: `run_simulator_recording.rb` worked and worked to format the commands and prepare them.
She created `.json` files for instructions and commands, and used [Train](https://github.com/chef/train) in the background to run the commands and record the output to some .txt files in the `app/responses` directory.
Pleased with her work, `run_simulator_recording.rb` turned to her friend the webapp, and said to her: 'take these json files, and show them to the people.'

Webapp then went and found her friend xterm, and said, why let's do this together, for two heads are always better than one!
And so webapp said to her dear friend angular2, please help me make this work! and angular2 came running, as friends always do.
And so angular2 met xterm, and as they shook hands, they knew they would be good friends together. So they put their heads together,
and made some decisions about what each one's role would be. Xterm claimed responsiblity for creating the terminal view,
and made some decisions about what each one's role would be. Xterm claimed responsibility for creating the terminal view,
reading the user's input, and displaying it. App then explained she could take that final user input sent over by xterm and
and transform it into a regular expression, which she could then use to match against the information in the commandsjson file,
and transform it into a regular expression, which she could then use to match against the information in the `commands.json` file,
matching the user's input against the key and then retrieving the associated value's txt file.
And it was so. :)


## How to generate content for tutorial/update the tutorial

To generate content for the tutorial, update the tutorial.yml and/or commands.yml file and
run `bundle exec rake update_demo` from the root of inspec project.
** The github-markdown gem is causing some problems with this right now. Please run the ruby file directly for the moment:
`ruby tasks/command_simulator.rb`

This will create/update three json files (commands.json, instructions.json, extra_commands.json)
and the .txt files for the app/responses/ directory (generated from the commands included in the tutorial.yml)
Those are the files required by the app to create the demo content.

To generate content for the tutorial, update the `tutorial.yml` and/or `commands.yml` file and
run `bundle exec rake update_demo` from the root of inspec project. This will create/update three json files (`commands.json` and `instructions.json`)
and the `.txt` files for the `app/responses/` directory (generated from the commands included in the `tutorial.yml`). Those are the files required by the app to create the demo content.

----------------------------------------------------------
## Author:

### Author: Victoria Jeffrey
Victoria Jeffrey
87 changes: 36 additions & 51 deletions www/tutorial/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,17 @@ export class AppComponent implements OnInit {
matchFound: boolean; // helps to handle no match found response
counter: number = 0; // keeps track of step number count
userCommand: string; // used to display better error msg when no match is found
extraCmds: string = ''; // used to display extra commands available (from commands.yml)

// arrays of data parsed from json files
commandsArray: any = [];
commands: any = [];
instructionsArray: any = [];

constructor(private http: Http) { }

ngOnInit() {
// load json files
this.getInstructions();
this.getResponses();
this.getExtraCmds();
this.getCommands();
}

ngAfterViewChecked() {
Expand All @@ -65,18 +63,29 @@ export class AppComponent implements OnInit {
this.counter -= 1;
}
this.response = this.black + 'prev' + msg;
} else if (step === 'last') {
this.counter = totalSteps - 1
this.response = this.black + 'last' + msg;
}
this.displayInstructions();
}

extraCmds() {
let cmds = this.commands
let extra = Object.keys(cmds).filter(function(key){
return cmds[key]['extra'] == true
});
return extra
}

// display instructions based on value of counter and
// format text to remove triple backticks. if the user has reached
// then end of the demo, display a message containing extra commands that have been
// enabled in the demo
displayInstructions() {
if (this.counter === this.instructionsArray.length - 1) {
this.title = "the end; that's all folks!";
this.instructions = "here are some other commands you can try out: \r\n\r\n" + this.extraCmds;
this.instructions = "here are some other commands you can try out: \r\n\r\n" + this.extraCmds();
} else {
if (this.instructionsArray[this.counter][1]) {
this.title = this.instructionsArray[this.counter][0];
Expand All @@ -102,21 +111,12 @@ export class AppComponent implements OnInit {
else if (command.match(/^prev\s*/)) {
this.updateInstructions('prev');
}
else if (command.match(/^last\s*/)) {
this.updateInstructions('last');
}
else if (this.shell === 'inspec-shell') {
this.parseInspecShell(command);
}
else if (command.match(/^ls\s*/)) {
this.response = this.white + "README.md";
}
else if (command.match(/^pwd\s*/)) {
this.response = this.white + "anonymous-web-user/inspec";
}
else if (command.match(/^cat\s*README.md\s*/i)) {
this.response = this.white + "Only a few commands are implemented in this terminal. Please follow the demo";
}
else if (command.match(/^less\s*README.md\s*/i)) {
this.response = this.white + "Only a few commands are implemented in this terminal. Please follow the demo.";
}
else {
this.checkCommand(command);
}
Expand Down Expand Up @@ -156,25 +156,26 @@ export class AppComponent implements OnInit {
}

// takes the command as input, replaces all white space with regex whitespace matcher
// and creates a new regex. check if the regex matches any of the keys in the commandsArray
// and creates a new regex. check if the regex matches any of the keys in the commands
// if it matches, we set matchFound to true and call displayResult. if it doesn't match,
// we display a default error message
checkCommand(command) {
let dir = 'app/responses/';
let cmd = command.replace(/ /g,"\\s*")
let regexcmd = new RegExp(('^'+cmd+'$'), 'm')
this.matchFound = false;
for (var i = 0; i < this.commandsArray.length; i++) {
let object = this.commandsArray[i]
for (let key in object) {
if (key.match(regexcmd)) {
this.matchFound = true;
let value = object[key];
this.http.get(dir + value).subscribe(data => {
this.displayResult(command, data);
},
err => console.error(err));
}

// iterate over commands and try to match the command with the input
let cmds = Object.keys(this.commands)
for (var i = 0; i < cmds.length; i++) {
let cmd = cmds[i];
if (cmd.match(regexcmd)) {
this.matchFound = true;
let key = this.commands[cmd]['key'];
this.http.get(dir + key).subscribe(data => {
this.displayResult(command, data);
},
err => console.error(err));
}
}
// if no match is found, we check if the command entered was inspec exec something
Expand Down Expand Up @@ -209,7 +210,7 @@ export class AppComponent implements OnInit {
// load json file for instructions and save to instructionsArray
// call displayInstructions to load first set of instructions
getInstructions() {
this.http.get('tutorial_files/instructions.json')
this.http.get('app/responses/instructions.json')
.subscribe(data => {
this.instructionsArray = JSON.parse(data['_body']);
this.displayInstructions();
Expand All @@ -218,30 +219,14 @@ export class AppComponent implements OnInit {
);
}

// load json file for commands and push each object to commandsArray
getResponses() {
this.http.get('tutorial_files/commands.json')
// load json file for commands and push each object to commands
getCommands() {
this.http.get('app/responses/commands.json')
.subscribe(data => {
let result = JSON.parse(data['_body']);
for (var i = 0; i < result.length; i++) {
let object = result[i][0];
this.commandsArray.push(object);
}
},
err => console.error(err)
);
}

// load json file for extra commands to display extra commands available to user
getExtraCmds() {
this.http.get('tutorial_files/extra_commands.json')
.subscribe(data => {
let result = JSON.parse(data['_body']);
for (var i = 0; i < result.length; i++) {
this.extraCmds += result[i] + "\r\n";
}
this.commands = result
},
err => console.error(err)
);
}
}
}
1 change: 1 addition & 0 deletions www/tutorial/app/responses/cat_README_md.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Only a few commands are implemented in this terminal. Please follow the demo.
Loading

0 comments on commit 90e3b86

Please sign in to comment.