diff --git a/autotest/autotest.py b/autotest/autotest.py
index dbed5408..de9d237b 100755
--- a/autotest/autotest.py
+++ b/autotest/autotest.py
@@ -1,14 +1,21 @@
#!/usr/bin/env python
+import logging
import os
import re
import subprocess
import sys
-def print_snippet(snippet):
- print(78*'-')
- print(snippet)
- print(78*'-')
+logging.basicConfig(level=logging.DEBUG)
+
+def hrule():
+ return "="*int(os.environ.get("COLUMNS", "80"))
+
+# A "snippet" is something that the user is supposed to do in the workshop.
+# Most of the "snippets" are shell commands.
+# Some of them can be key strokes or other actions.
+# In the markdown source, they are the code sections (identified by triple-
+# quotes) within .exercise[] sections.
class Snippet(object):
@@ -28,26 +35,22 @@ class Slide(object):
def __init__(self, content):
Slide.current_slide += 1
self.number = Slide.current_slide
+
# Remove commented-out slides
# (remark.js considers ??? to be the separator for speaker notes)
content = re.split("\n\?\?\?\n", content)[0]
self.content = content
+
self.snippets = []
exercises = re.findall("\.exercise\[(.*)\]", content, re.DOTALL)
for exercise in exercises:
- if "```" in exercise and "
`" in exercise:
- print("! Exercise on slide {} has both ``` and
` delimiters, skipping."
- .format(self.number))
- print_snippet(exercise)
- elif "```" in exercise:
+ if "```" in exercise:
for snippet in exercise.split("```")[1::2]:
self.snippets.append(Snippet(self, snippet))
- elif "
`" in exercise:
- for snippet in re.findall("
`(.*)`", exercise):
- self.snippets.append(Snippet(self, snippet))
else:
- print(" Exercise on slide {} has neither ``` or
` delimiters, skipping."
- .format(self.number))
+ logging.warning("Exercise on slide {} does not have any ``` snippet."
+ .format(self.number))
+ self.debug()
def __str__(self):
text = self.content
@@ -55,6 +58,9 @@ class Slide(object):
text = text.replace(snippet.content, ansi("7")(snippet.content))
return text
+ def debug(self):
+ logging.debug("\n{}\n{}\n{}".format(hrule(), self.content, hrule()))
+
def ansi(code):
return lambda s: "\x1b[{}m{}\x1b[0m".format(code, s)
@@ -64,96 +70,51 @@ content = open(sys.argv[1]).read()
for slide in re.split("\n---?\n", content):
slides.append(Slide(slide))
-is_editing_file = False
-placeholders = {}
+actions = []
for slide in slides:
for snippet in slide.snippets:
content = snippet.content
- # Multi-line snippets should be ```highlightsyntax...
- # Single-line snippets will be interpreted as shell commands
+ # Extract the "method" (e.g. bash, keys, ...)
+ # On multi-line snippets, the method is alone on the first line
+ # On single-line snippets, the data follows the method immediately
if '\n' in content:
- highlight, content = content.split('\n', 1)
+ method, data = content.split('\n', 1)
else:
- highlight = "bash"
- content = content.strip()
- # If the previous snippet was a file fragment, and the current
- # snippet is not YAML or EDIT, complain.
- if is_editing_file and highlight not in ["yaml", "edit"]:
- print("! On slide {}, previous snippet was YAML, so what do what do?"
- .format(slide.number))
- print_snippet(content)
- is_editing_file = False
- if highlight == "yaml":
- is_editing_file = True
- elif highlight == "placeholder":
- for line in content.split('\n'):
- variable, value = line.split(' ', 1)
- placeholders[variable] = value
- elif highlight == "bash":
- for variable, value in placeholders.items():
- quoted = "`{}`".format(variable)
- if quoted in content:
- content = content.replace(quoted, value)
- del placeholders[variable]
- if '`' in content:
- print("! The following snippet on slide {} contains a backtick:"
- .format(slide.number))
- print_snippet(content)
- continue
- print("_ "+content)
- snippet.actions.append((highlight, content))
- elif highlight == "edit":
- print(". "+content)
- snippet.actions.append((highlight, content))
- elif highlight == "meta":
- print("^ "+content)
- snippet.actions.append((highlight, content))
- elif highlight == "keys":
- print("K "+content)
- snippet.actions.append((highlight, content))
- else:
- print("! Unknown highlight {!r} on slide {}.".format(highlight, slide.number))
-if placeholders:
- print("! Remaining placeholder values: {}".format(placeholders))
+ method, data = content.split(' ', 1)
+ actions.append((slide, snippet, method, data))
-actions = sum([snippet.actions for snippet in sum([slide.snippets for slide in slides], [])], [])
-
-# Strip ^{ ... ^} for now
-def strip_curly_braces(actions, in_braces=False):
- if actions == []:
- return []
- elif actions[0] == ("meta", "^{"):
- return strip_curly_braces(actions[1:], True)
- elif actions[0] == ("meta", "^}"):
- return strip_curly_braces(actions[1:], False)
- elif in_braces:
- return strip_curly_braces(actions[1:], True)
- else:
- return [actions[0]] + strip_curly_braces(actions[1:], False)
-
-actions = strip_curly_braces(actions)
try:
i = int(open("nextstep").read())
+ logging.info("Loaded next step ({}) from file.".format(i))
except Exception as e:
- print("Could not read nextstep file ({}), initializing to 0.".format(e))
+ logging.warning("Could not read nextstep file ({}), initializing to 0.".format(e))
i = 0
+
+keymaps = { "^C": "\x03" }
+
while True:
with open("nextstep","w") as f:
f.write(str(i))
- typ, cmd = actions[i]
- print_snippet(cmd)
- print("i={} shall we execute the snippet above with {}?".format(i, typ))
+ slide, snippet, method, data = actions[i]
+ data = data.strip()
+ print(hrule())
+ print(slide.content.replace(snippet.content, ansi(7)(snippet.content)))
+ print(hrule())
+ print("[{}] Shall we execute that snippet above?".format(i))
command = raw_input()
if command == "":
- if typ in ["bash", "keys"]:
- if typ=="keys" and cmd=="^C":
- print("^C detected")
- cmd="\x03"
- subprocess.check_call(["tmux", "send-keys", "{}\n".format(cmd)])
+ if method=="keys" and data in keymaps:
+ print("Mapping {!r} to {!r}.".format(data, keymaps[data]))
+ data = keymaps[data]
+ if method in ["bash", "keys"]:
+ data = re.sub("\n +", "\n", data)
+ if method == "bash":
+ data += "\n"
+ subprocess.check_call(["tmux", "send-keys", "{}".format(data)])
else:
- print "DO NOT KNOW HOW TO HANDLE", typ, cmd
+ print "DO NOT KNOW HOW TO HANDLE {} {!r}".format(method, data)
i += 1
elif command.isdigit():
i = int(command)
diff --git a/docs/dashboard.md b/docs/dashboard.md
index 3f593de7..21ef54b6 100644
--- a/docs/dashboard.md
+++ b/docs/dashboard.md
@@ -91,6 +91,8 @@ The goo.gl URL expands to:
(You will have to work around the TLS certificate validation warning)
+
+
]
- We have three authentication options at this point:
diff --git a/docs/kubectlexpose.md b/docs/kubectlexpose.md
index 30dd00dc..1010ca18 100644
--- a/docs/kubectlexpose.md
+++ b/docs/kubectlexpose.md
@@ -69,6 +69,8 @@ The `LoadBalancer` type is currently only available on AWS, Azure, and GCE.
kubectl get pods -w
```
+
+
]
The `-w` option "watches" events happening on the specified resources.
diff --git a/docs/kubectlscale.md b/docs/kubectlscale.md
index 6744789c..d3a82786 100644
--- a/docs/kubectlscale.md
+++ b/docs/kubectlscale.md
@@ -10,6 +10,8 @@
kubectl get deployments -w
```
+
+
- Now, create more `worker` replicas:
```bash
kubectl scale deploy/worker --replicas=10
diff --git a/docs/ourapponkube.md b/docs/ourapponkube.md
index 8d3ba86f..bb5b6c75 100644
--- a/docs/ourapponkube.md
+++ b/docs/ourapponkube.md
@@ -348,6 +348,8 @@ We should now see the `worker`, well, working happily.
- Open the web UI in your browser (http://node-ip-address:3xxxx/)
+
+
]
--
diff --git a/docs/prereqs-k8s.md b/docs/prereqs-k8s.md
index 739730ec..428d1ded 100644
--- a/docs/prereqs-k8s.md
+++ b/docs/prereqs-k8s.md
@@ -65,6 +65,8 @@ class: extra-details
- Go to [container.training](http://container.training/) to view these slides
- Join the chat room on @@CHAT@@
+
+
]
---
@@ -73,6 +75,12 @@ class: pic, in-person

+
+
---
class: in-person
@@ -102,11 +110,7 @@ done
```
- Type `exit` or `^D` to come back to node1
-
+
]
diff --git a/docs/rollout.md b/docs/rollout.md
index cbcbd529..4d98fc03 100644
--- a/docs/rollout.md
+++ b/docs/rollout.md
@@ -79,6 +79,8 @@
kubectl get deployments -w
```
+
+
- Update `worker` either with `kubectl edit`, or by running:
```bash
kubectl set image deploy worker worker=$REGISTRY/worker:$TAG
diff --git a/docs/sampleapp.md b/docs/sampleapp.md
index 8a43c3c0..aa6fe9d3 100644
--- a/docs/sampleapp.md
+++ b/docs/sampleapp.md
@@ -264,6 +264,8 @@ class: extra-details
- In your browser, you need to enter the IP address of your node
+
+
]
You should see a speed of approximately 4 hashes/second.
@@ -316,9 +318,25 @@ class: extra-details
- run `top` to see CPU and memory usage (you should see idle cycles)
-- run `vmstat 3` to see I/O usage (si/so/bi/bo)
+
+
+- run `vmstat 1` to see I/O usage (si/so/bi/bo)
(the 4 numbers should be almost zero, except `bo` for logging)
+
+
]
We have available resources.