86 | );
87 | }
88 | ```
89 |
90 | (Man beachte die hervorgehobenen Zeilen 6 und 7)
91 |
92 | ---
93 |
94 | ## Beispiel in Bash
95 |
96 | ```bash
97 | # Check what Linux we are on
98 | uname -a
99 | ```
100 |
101 | ---
102 |
103 | ## Code-Beispiel
104 |
105 | Elliot Alderson wäre stolz.
106 |
107 | 
108 |
109 | ---
110 |
111 | ## Katzenbild
112 |
113 | 
114 |
115 | ---
116 |
117 | # Lab 01: Aufgabe
118 |
119 | Beschreibung der Aufgabe
120 |
121 | - Akzeptanzkriterium 1
122 | - Akzeptanzkriterium 2
123 | - Akzeptanzkriterium 3
124 |
125 | ---
126 |
127 | 
128 |
129 | ---
130 |
131 | 
132 |
133 | ---
134 |
135 | # Linkliste
136 |
137 | - Ein tolles Projekt: [[klick!]](https://github.com/stdevel/katprep/)
138 | - Tolles Produkt-Benutzerhandbuch: [[klick!]](https://access.redhat.com/documentation/en-us/red_hat_satellite/6.5/)
139 | - Tolleres Online-Forum: [[klick!]](https://community.icinga.com/)
140 |
141 | ---
142 |
143 | class: center, middle
144 |
145 | ## Danke für die Aufmerksamkeit
146 |
147 | ### (jetzt bitte wieder aufwachen)
148 |
149 | 
150 |
--------------------------------------------------------------------------------
/Ansible/lab.yml:
--------------------------------------------------------------------------------
1 | ---
2 | - name: Prepare lab environment
3 | hosts: all
4 | become: true
5 | gather_facts: false
6 | tasks:
7 | - name: Fix keyboard layout
8 | command: "/bin/localectl set-keymap de-nodeadkeys"
9 | changed_when: false
10 |
11 | - name: Install core utilities
12 | yum:
13 | name: "{{ core_packages }}"
14 | state: installed
15 | ignore_errors: true
16 | vars:
17 | core_packages:
18 | - dos2unix
19 | - vim
20 | - bind-utils
21 | - epel-release
22 | - python3-pytest
23 |
24 | - name: Install Python modules
25 | pip:
26 | name:
27 | - testinfra
28 |
29 | - name: Disable firewall as we also like to live dangerously
30 | service:
31 | name: firewalld
32 | state: stopped
33 | enabled: false
34 |
35 | - name: Disable SELinux as this is a lab environment
36 | selinux:
37 | policy: targeted
38 | state: permissive
39 |
--------------------------------------------------------------------------------
/Ansible/test_generic.py:
--------------------------------------------------------------------------------
1 | """
2 | Deployment unit tests
3 | Generic tests
4 | """
5 | import os
6 | import testinfra.utils.ansible_runner
7 |
8 |
9 | def test_software(host):
10 | """
11 | Check whether required software packages are installed
12 | """
13 | packages = [
14 | "vim-common",
15 | "bind-utils",
16 | "epel-release",
17 | "python3-pytest"
18 | ]
19 | for pkg in packages:
20 | _pkg = host.package(pkg)
21 | assert _pkg.is_installed
22 |
23 | def test_firewall(host):
24 | """
25 | Check whether firewall is disabled
26 | """
27 | firewalld = host.service("firewalld")
28 | assert firewalld.is_enabled == False
29 | assert firewalld.is_running == False
30 |
31 | def test_selinux(host):
32 | """
33 | Check whether SELinux is in Permissive mode
34 | """
35 | sebool = host.run("getenforce")
36 | assert sebool.stdout.lower().strip() == "permissive"
37 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Release 1.4, 21.08.2020
2 |
3 | - title slide uses the title from config file
4 | - added automatic agenda generation based on first-level-headings
5 | - add linter configurations
6 | - added lab tests for participants based on [Commander](https://github.com/commander-cli/commander)
7 | - added Ansible lab configuration
8 | - added lab configuration unit tests
9 |
10 | # Release 1.3, 22.06.2020
11 |
12 | - added footnotes and in-line syntax highlightning
13 | - fixed smaller issues (updated example, changed font size, simplified pipeline)
14 | - fixed some bugs while building the presentation
15 | - implemented handout feature
16 | - implemented watermark function (for customer presentations)
17 |
18 | # Release 1.1, 09.03.2020
19 |
20 | - implemented basic SVA theme
21 |
22 | # Release 1.0, 20.02.2020
23 |
24 | - initial release
25 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | When contributing to this repository, please first discuss the change you wish to make via issue,
4 | email, or any other method with the owners of this repository before making a change.
5 |
6 | Please note we have a code of conduct, please follow it in all your interactions with the project.
7 |
8 | ## Pull Request Process
9 |
10 | 1. Ensure any install or build dependencies are removed before the end of the layer when doing a build.
11 | 2. Update the README.md with details of changes to the interface, this includes new environment variables, exposed ports, useful file locations and container parameters.
12 | 3. Increase the version numbers in any examples files and the README.md to the new version that this Pull Request would represent. The versioning scheme we use is [SemVer](http://semver.org/).
13 | 4. You may merge the Pull Request in once you have the sign-off of two other developers, or if you do not have permission to do that, you may request the second reviewer to merge it for you.
14 |
15 | ## Code of Conduct
16 |
17 | ### Our Pledge
18 |
19 | In the interest of fostering an open and welcoming environment, we as
20 | contributors and maintainers pledge to making participation in our project and
21 | our community a harassment-free experience for everyone, regardless of age, body
22 | size, disability, ethnicity, gender identity and expression, level of experience,
23 | nationality, personal appearance, race, religion, or sexual identity and
24 | orientation.
25 |
26 | ### Our Standards
27 |
28 | Examples of behavior that contributes to creating a positive environment
29 | include:
30 |
31 | * Using welcoming and inclusive language
32 | * Being respectful of differing viewpoints and experiences
33 | * Gracefully accepting constructive criticism
34 | * Focusing on what is best for the community
35 | * Showing empathy towards other community members
36 |
37 | Examples of unacceptable behavior by participants include:
38 |
39 | * The use of sexualized language or imagery and unwelcome sexual attention or advances
40 | * Trolling, insulting/derogatory comments, and personal or political attacks
41 | * Public or private harassment
42 | * Publishing others' private information, such as a physical or electronic address, without explici permission
43 | * Other conduct which could reasonably be considered inappropriate in a professional setting
44 |
45 | ### Our Responsibilities
46 |
47 | Project maintainers are responsible for clarifying the standards of acceptable
48 | behavior and are expected to take appropriate and fair corrective action in
49 | response to any instances of unacceptable behavior.
50 |
51 | Project maintainers have the right and responsibility to remove, edit, or
52 | reject comments, commits, code, wiki edits, issues, and other contributions
53 | that are not aligned to this Code of Conduct, or to ban temporarily or
54 | permanently any contributor for other behaviors that they deem inappropriate,
55 | threatening, offensive, or harmful.
56 |
57 | ### Scope
58 |
59 | This Code of Conduct applies both within project spaces and in public spaces
60 | when an individual is representing the project or its community. Examples of
61 | representing a project or community include using an official project e-mail
62 | address, posting via an official social media account, or acting as an appointed
63 | representative at an online or offline event. Representation of a project may be
64 | further defined and clarified by project maintainers.
65 |
66 | ### Enforcement
67 |
68 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
69 | reported by contacting the project team at github@sva.de. All
70 | complaints will be reviewed and investigated and will result in a response that
71 | is deemed necessary and appropriate to the circumstances. The project team is
72 | obligated to maintain confidentiality with regard to the reporter of an incident.
73 | Further details of specific enforcement policies may be posted separately.
74 |
75 | Project maintainers who do not follow or enforce the Code of Conduct in good
76 | faith may face temporary or permanent repercussions as determined by other
77 | members of the project's leadership.
78 |
79 | ### Attribution
80 |
81 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
82 | available at [http://contributor-covenant.org/version/1/4][version]
83 |
84 | [homepage]: http://contributor-covenant.org
85 | [version]: http://contributor-covenant.org/version/1/4/
86 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README-remarkjs.md:
--------------------------------------------------------------------------------
1 | # remark
2 |
3 | [](https://travis-ci.org/gnab/remark)
4 | [](https://cdnjs.com/libraries/remark)
5 | [](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4ADT275DY7JTG)
6 |
7 | A simple, in-browser, markdown-driven slideshow tool targeted at people who know their way around HTML and CSS, featuring:
8 |
9 | - Markdown formatting, with smart extensions
10 | - Presenter mode with markdown formatted speaker notes and cloned slideshow view
11 | - Syntax highlighting, supporting a range of languages
12 | - Slide scaling, thus similar appearance on all devices / resolutions
13 | - Simple markdown templates for customized slides
14 | - Touch support for smart phones and pads, i.e. swipe to navigate slides
15 |
16 | Check out [this remark slideshow](http://gnab.github.com/remark) for a brief introduction.
17 |
18 | To render your Markdown-based slideshow on the fly, checkout [Remarkise](https://gnab.github.io/remark/remarkise).
19 |
20 | ### Getting Started
21 |
22 | It takes only a few, simple steps to get up and running with remark:
23 |
24 | 1. Create an HTML file to contain your slideshow (see boilerplate below)
25 | 2. Open the HTML file in a decent browser
26 | 3. Edit the Markdown and/or CSS styles as needed, save and refresh!
27 | 4. Press `C` to clone a display; then press `P` to switch to presenter mode. Open help menu with `h`.
28 |
29 | See any of the boilerplate-*.html files, or just copy the boilerplate HTML below to start:
30 |
31 | ```html
32 |
33 |
34 |
35 | Title
36 |
37 |
49 |
50 |
51 |
70 |
72 |
75 |
76 |
77 | ```
78 |
79 | ### How To Use remark
80 |
81 | The [wiki](http://github.com/gnab/remark/wiki) pages contain all the how-to, templating, and API help.
82 |
83 | ### Real-world remark slideshows
84 |
85 | On using remark:
86 |
87 | - [The Official remark Slideshow](http://gnab.github.com/remark)
88 | - [Coloured Terminal Listings in remark](http://joshbode.github.com/remark/ansi.html) by [joshbode](https://github.com/joshbode)
89 |
90 | Other interesting stuff:
91 |
92 | - [gnab.github.com/editorjs](http://gnab.github.com/editorjs)
93 | - [judoole.github.com/GroovyBDD](http://judoole.github.com/GroovyBDD)
94 | - [bekkopen.github.com/infrastruktur-som-kode](http://bekkopen.github.com/infrastruktur-som-kode)
95 | - [ivarconr.github.com/Test-Driven-Web-Development/slides](http://ivarconr.github.com/Test-Driven-Web-Development/slides)
96 | - [havard.github.com/node.js-intro-norwegian](http://havard.github.com/node.js-intro-norwegian)
97 | - [mobmad.github.com/js-tdd-erfaringer](http://mobmad.github.com/js-tdd-erfaringer)
98 | - [roberto.github.com/ruby-sinform-2012](http://roberto.github.com/ruby-sinform-2012)
99 | - [http://asmeurer.github.io/python3-presentation/slides.html](http://asmeurer.github.io/python3-presentation/slides.html)
100 | - [Lecture notes using remark](http://keysan.me/ee361/)
101 | - [Time series analysis: theory and practice (a course using Remark)](http://jmlilly.net/course.html)
102 |
103 | ### Printing
104 |
105 | Converting to PDF is primarily supported via Chrome's Print to PDF feature. Note that the styling is not exact; See [#50](https://github.com/gnab/remark/issues/50#issuecomment-223887379) for some recommended CSS to add to your styles.
106 |
107 | Alternatively, you can use [DeckTape](https://github.com/astefanutti/decktape), a PDF exporter for HTML presentation frameworks that provides support for remark.
108 |
109 | ### Contributors
110 |
111 | Thanks goes to these people for their contributions:
112 |
113 | - Aaron Meurer
114 | - Adam Obeng
115 | - Adam Strzelecki
116 | - Aleksandar Trifunovic
117 | - Alexander Brett
118 | - Alex Claman
119 | - Alex Y. Wagner
120 | - Allan Jiang
121 | - Amin Bandali
122 | - Andrea Georgieva
123 | - Andrew Gaul
124 | - Andrey Ustyuzhanin
125 | - Antonin Stefanutti
126 | - Axel Rauschmayer
127 | - Baron Schwartz
128 | - Bastian Venthur
129 | - Bengt Lüers
130 | - Benjamin Stigsen
131 | - Bernát Kalló
132 | - bobappleyard
133 | - Brandon Keepers
134 | - Breno Polanski
135 | - Bruno Fagundez
136 | - bugdone
137 | - Cameron Daigle
138 | - Chris Kanich
139 | - Christian Dreier
140 | - Christopher McClellan
141 | - Christoph Gnip
142 | - cjwit
143 | - Claudio Bley
144 | - Daan van Berkel
145 | - Daniel Stankiewicz
146 | - Daniel Wang
147 | - Danny Tuppeny
148 | - Dan Steingart
149 | - datamike
150 | - Dave Henderson
151 | - David Richards
152 | - derickfay
153 | - Dirk Husemann
154 | - Erwänn Mest
155 | - Fabian
156 | - Felix C. Stegerman
157 | - Florian Rathgeber
158 | - follower
159 | - Gerard Capes
160 | - gnab
161 | - Grégoire Pineau
162 | - Gurjeet Singh
163 | - Hadrien Frank Cardinal de Cuzey
164 | - Hiroshi Fukada
165 | - Hubert Chen
166 | - Hunter-Github
167 | - hydroid7
168 | - Ivo Wever
169 | - J_4lexander
170 | - Jason
171 | - Jason Underhill
172 | - Jérôme Petazzoni
173 | - Jimmy Merrild Krag
174 | - Joe Beda
175 | - Joel Porquet
176 | - Johannes Wienke
177 | - Julien Wajsberg
178 | - kellyoconor
179 | - kerim
180 | - kernc
181 | - Kim Joar Bekkelund
182 | - Lauro Caetano
183 | - Loreia
184 | - Marcel Schilling
185 | - Markus Schanz
186 | - Martin
187 | - Martin 'Hasan' Bramwell
188 | - Mathias Bynens
189 | - Matthew
190 | - Mears-UFL
191 | - mhor
192 | - Michael Byrne
193 | - Michael Grosser
194 | - Michael Mol
195 | - Michael Sanford
196 | - Mike Pennisi
197 | - Morton Fox
198 | - mrbald
199 | - Nicolas Hart
200 | - Oleksiy Syvokon
201 | - Ole Petter Bang
202 | - Ozan K
203 | - Pavel Boldyrev
204 | - Pedro
205 | - Pedro Martin
206 | - Peter Jausovec
207 | - petitviolet
208 | - Pi-Hsun Shih
209 | - pille1842
210 | - piranha
211 | - pospi
212 | - Psychos-Yi
213 | - punkish
214 | - Radovan Bast
215 | - Rahul Bansal
216 | - Rasmus Vestergaard Hansen
217 | - rasmusvhansen
218 | - Renato Alves
219 | - rglepe
220 | - Rich Trott
221 | - Roberto Soares
222 | - Robert Perce
223 | - Robert Szmurło
224 | - Robin Berjon
225 | - Rolf
226 | - Rostyk
227 | - Russell Keith-Magee
228 | - Ryan Thomson
229 | - Sarah Binney
230 | - Scott Hewitt
231 | - Sebastian Pipping
232 | - Sequoia McDowell
233 | - Shane Curcuru
234 | - Shaun Hammill
235 | - siba prasad samal
236 | - Simon Hengel
237 | - Stian Mathiassen
238 | - stu-b-doo
239 | - Sylvain Abélard
240 | - Takashi Kanemoto
241 | - Tej Chajed
242 | - Thomas Ballinger
243 | - Tobias Løfgren
244 | - Todd Brannam
245 | - Todd Gureckis
246 | - Tome Tanasovski
247 | - Tom Kraak
248 | - Torgeir Thoresen
249 | - tripu
250 | - vdepabk2t
251 | - William Ghelfi
252 | - Willi Rath
253 | - Wouter Sioen
254 | - Yihui Xie
255 | - Yinhe Zhang
256 | - Yohan Lasorsa
257 | - Yoshiya Hinosawa
258 |
259 | ### License
260 |
261 | remark is licensed under the MIT license. See LICENSE for further
262 | details.
263 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # training-as-code
2 |
3 | This is a training template based on [remark.js (*v.0.15.0*)](https://github.com/gnab/remark). It is based on Markdown/JavaScript/HTML and offers the following advantages over conventional presentation software such as LibreOffice Impress and Microsoft PowerPoint:
4 |
5 | - It only requires a web browser
6 | - It also works on smartphones, tablets and other touch-optimized devices
7 | - It can be used with version control systems such as **Git** as content is ``text/plain``
8 | - You can use **any text editor** and operating system you like to create and display presentations
9 | - It's **free** (*and hip!*)
10 |
11 | ## Automatic builds
12 |
13 | When used in GitLab all Markdown documents (``*.md``) will be automatically build into a HTML presentation and PDF document which can then be downloaded as job artifact. This allows distributing your slides easily.
14 |
15 | To manually create/update the HTML presentation, run the ``build.py`` utility. It requires Python 3.
16 |
17 | ### Handout
18 |
19 | A handout will be created from the file `handout.md`.
20 | It has only basic styling applied to it.
21 |
22 | ## Usage
23 |
24 | Clone this repository and have a look at the [example training (`01-content.md`)](01-content.md).
25 | The format is markdown, you can leverage an editor such as [VSCodium](https://github.com/VSCodium/vscodium) and to edit the file and preview changes:
26 |
27 | 
28 | 
29 |
30 | Check out the following websites for more information about Markdown:
31 |
32 | - [https://www.markdowntutorial.com/](https://www.markdowntutorial.com/)
33 | - [https://www.markdownguide.org/](https://www.markdownguide.org/)
34 |
35 | You can also check-out the [official remark.js website](https://remarkjs.com) for further examples.
36 |
37 | ### Presenter View
38 |
39 | The presenter should download the artifact from the _collect files_ pipeline job and extract these to wherever (s)he pleases.
40 | Then open `presentation.html` with your browser.
41 |
42 | Press `?` to see a list of all available commands.
43 |
44 | Pressing `p` will open a presenter view that shows the current slide, the next slide and speaker notes.
45 |
46 | ### Multi-Screen Setup
47 |
48 | A common setup has one screen that presents to the audience and another that shows the information for the speaker.
49 |
50 | To achieve this press `c` in the presentation in order to clone it.
51 | The screens are linked and moving forward on the clone will move the other forward aswell.
52 |
53 | You can move the window to another screen and sent it into fullscreen in most browsers by `F11`?
54 |
55 | By then pressing `p` on the cloned presentation you will have your presenter view there.
56 |
57 | ## Markdown macros
58 |
59 | remark.js uses some Markdown, macros - e.g. for resizing images:
60 |
61 | ```markdown
62 | 
63 | ```
64 |
65 | The value before the colon represents an alternative text in case the image cannot be loaded. The value describes the image width in percentage.
66 |
67 | New slides are defined by the following line:
68 |
69 | ```markdown
70 | ---
71 | ```
72 |
73 | In order to add presentation notes, use the following code before the next slide:
74 |
75 | ```markdown
76 | ???
77 |
78 | Notes
79 | ```
80 |
81 | Incremental slides (*slides that add more information after a button press*) can be added with the following:
82 |
83 | ```markdown
84 | This is already visible
85 |
86 | --
87 |
88 | This text will only be visible when going to the next element.
89 |
90 | ```
91 |
92 | ## Tweaks
93 |
94 | ### Set title
95 |
96 | You can simply change the title by altering the [``settings.ini``](settings.ini) file:
97 |
98 | ```ini
99 | [meta]
100 | title=Zeit unproduktiv vergeuden leicht gemacht
101 | ```
102 |
103 | ### Change screen ratio
104 |
105 | By default, the ratio **16:9** is selected, but you can also override this in [``settings.ini``](settings.ini) by changing the ``ratio`` line:
106 |
107 | ```ini
108 | [layout]
109 | ratio=4:3
110 | ```
111 |
112 | ### Set customer name as watermark
113 |
114 | Before sending presentations to customers you can set their company name as watermark. To do so, edit [``settings.ini``](settings.ini):
115 |
116 | ```ini
117 | [meta]
118 | title=Zielgruppenorientierte Memes in Präsentationen
119 | customer=Simone Giertz Ltd.
120 | ```
121 |
122 | While the customer name could be removed from `presentation.html`, it can't be changed in the PDF version.
123 |
124 | # Deploying lab environment
125 |
126 | ## Local
127 |
128 | Ensure meeting the following requirements:
129 |
130 | - Install [HashiCorp Vagrant](https://vagrantup.com)
131 | - Install a supported hypervisor, such as:
132 | - [Oracle VirtualBox](https://virtualbox.org)
133 | - [VMware Workstation Player](https://www.vmware.com/products/workstation-player/workstation-player-evaluation.html), [VMware Workstation Pro](https://www.vmware.com/products/workstation-pro.html) or [VMware Fusion](https://www.vmware.com/products/fusion.html)
134 | - libvirt/KVM
135 | - [Parallels Desktop](https://www.parallels.com/)
136 | - [Microsoft Hyper-V](https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/)
137 |
138 | For deploying the lab on a local machine, simply clone this repository to a host and switch to the `Vagrant` folder. Run the following command to create and configure the VM:
139 |
140 | ```shell
141 | $ vagrant up
142 | Bringing machine 'default' up with 'virtualbox' provider...
143 | ==> default: Importing base box 'centos/8'...
144 | ==> default: Matching MAC address for NAT networking...
145 | ==> default: Checking if box 'centos/8' version '1905.1' is up to date...
146 | ...
147 | PLAY RECAP *********************************************************************
148 | default : ok=5 changed=3 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
149 | ```
150 |
151 | ## Cloud
152 |
153 | For deploying the lab in the cloud, a provider-specific configuration needs to be created within the [`Terraform`](terraform/) folder.
154 |
155 | Creating the environment differs per provider, but mostly the following commands are necessary:
156 |
157 | ```shell
158 | $ terraform init
159 | $ ssh-keygen -f clouduser
160 | $ cp azureuser ../../Ansible/files
161 | $ terraform plan -var-file=credentials-.tfvars
162 | $ terraform apply -var-file=credentials-.tfvars
163 | ```
164 |
165 | To configure the VMs using Ansible after creating the VMs, run the following commands:
166 |
167 | ```shell
168 | $ ansible-playbook -i inventory.py ../../ansible/node.yml --flush-cache
169 | ```
170 |
171 | # Testing
172 |
173 | ## VM customization
174 |
175 | For the VM customization, unit tests can be found in the [`Ansible`](ansible/) folder. To run them, execute the following command within the VM:
176 |
177 | ```shell
178 | $ pytest-3 /vagrant/ansible/test_generic.py
179 | === test session starts ===
180 | platform linux -- Python 3.6.8, pytest-3.4.2, py-1.5.3, pluggy-0.6.0
181 | rootdir: /vagrant/ansible, inifile:
182 | plugins: testinfra-5.2.2
183 | collected 3 items
184 | test_generic.py ... [100%]
185 |
186 | === 3 passed in 0.09 seconds ===
187 | ```
188 |
189 | When using a cloud environment, you can also leverage Ansible from your Terraform configuration to run the tests:
190 |
191 | ```shell
192 | $ py.test --connection=ansible --ansible-inventory=inventory.py ../../Ansible/test_generic.py --sudo
193 | ```
194 |
195 | Note that this will require **dynamic inventory**.
196 |
197 | ## Participant lab solution
198 |
199 | Participants can easily check whether they succeeded a lab by running the following command:
200 |
201 | ```shell
202 | $ lab 1
203 | Checking lab 1
204 |
205 | [1/2] Checking Good Task... Success!
206 | [2/2] Checking Bad Task... Failure!
207 |
208 | Errors in 1 task
209 | ```
210 |
211 | `1` needs to be replaced with the lab number.
212 |
213 | # Automated validation of lab solutions
214 |
215 | Automated testing of lab solutions can be performed by placing test definition, written in [commander](https://github.com/SimonBaeumer/commander) syntax, in the `labs/test` directory.
216 |
217 | When working with the example Vagrantfile in `vagrant`, the command `lab` becomes available inside the VM. Using it inside of the ``labs`` folder, which is placed inside the users home directory checks for either a single lab, or the whole suite can be performed. See ``lab -h`` for more information.
218 |
219 | # Pipeline configuration
220 |
221 | A [GitLab CI/CD](.gitlab-ci.yml) configuration is part of this repository. It executes the following tasks:
222 |
223 | 1. Render HTML from Markdown files
224 | 2. Build PDF presentation for sharing with participants
225 | 3. Create handout PDF from `handout.md`
226 | 4. Collect all the files necessary for a training (*presentations, additional content and handout*)
227 |
228 | It should be easy to migrate this logic to other pipelines such as **GitHub Actions**.
229 |
230 | # Further notes
231 |
232 | See also the official [remark.js README](README-remarkjs.md) for more details.
233 |
--------------------------------------------------------------------------------
/Terraform/README.md:
--------------------------------------------------------------------------------
1 | # Terraform
2 |
3 | This folder contains provider-specific code.
4 |
5 | ## TODO
6 |
7 | - Create a folder for your provider (*e.g. `Azure`*) and add your code
8 |
--------------------------------------------------------------------------------
/Vagrant/.gitignore:
--------------------------------------------------------------------------------
1 | .vagrant
--------------------------------------------------------------------------------
/Vagrant/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | # vi: set ft=ruby :
3 |
4 | Vagrant.configure("2") do |config|
5 | config.vm.network "private_network", ip: "192.168.24.99"
6 | config.vm.box = "centos/8"
7 | # copy Lab tools
8 | config.vm.provision "file", source: "../Ansible", destination: "/vagrant/ansible"
9 | config.vm.provision "file", source: "../labs", destination: "/home/vagrant/labs"
10 | config.vm.provision "file", source: "../tools/lab", destination: "/tmp/lab"
11 | config.vm.provision "shell", privileged: true, inline: <<-SHELL
12 | mv /tmp/lab /usr/local/bin/lab
13 | curl -Lo /usr/local/bin/commander https://github.com/commander-cli/commander/releases/download/v2.2.0/commander-linux-amd64
14 | yum install -y python3
15 | chmod +x /usr/local/bin/commander /usr/local/bin/lab
16 | SHELL
17 | config.vm.provision "ansible_local" do |ansible|
18 | ansible.playbook = "ansible/lab.yml"
19 | end
20 | end
21 |
--------------------------------------------------------------------------------
/assets/imgs/cat_hacker.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/assets/imgs/cat_hacker.gif
--------------------------------------------------------------------------------
/assets/imgs/doge.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/assets/imgs/doge.jpg
--------------------------------------------------------------------------------
/assets/imgs/hacker.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/assets/imgs/hacker.gif
--------------------------------------------------------------------------------
/assets/imgs/obama_micdrop.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/assets/imgs/obama_micdrop.gif
--------------------------------------------------------------------------------
/assets/labs/lab01_01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/assets/labs/lab01_01.png
--------------------------------------------------------------------------------
/assets/labs/lab01_02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/assets/labs/lab01_02.png
--------------------------------------------------------------------------------
/build.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | This script builds the presentation by filling the boilerplate with content
5 | """
6 |
7 | import codecs
8 | import configparser
9 | import glob
10 | import re
11 | from itertools import zip_longest
12 | from math import ceil
13 |
14 |
15 | IGNORED_DOCS = [
16 | "CHANGELOG.md",
17 | "README.md",
18 | "README-remarkjs.md",
19 | "handout.md",
20 | "labs.md"
21 | ]
22 | """
23 | IGNORED_DOCS: documents that will never be imported
24 | """
25 |
26 | SLIDE_DIVIDER = '\n---\n'
27 | POINTS_PER_AGENDA_SLIDE = 9
28 | AGENDA_TEMPLATE = """
29 | # Agenda {counter}
30 | {points}
31 |
32 | """
33 |
34 |
35 | def main():
36 | """
37 | Main function, starts the logic based on parameters.
38 | """
39 | config = read_config('settings.ini')
40 | slides = render_slides(read_slides(), config)
41 |
42 | template = read_template('template.html')
43 |
44 | rendered_template = render_metadata(template, config)
45 | rendered_template = rendered_template.replace('{{ content }}', slides)
46 |
47 | write_file("presentation.html", rendered_template)
48 |
49 |
50 | def read_config(filename):
51 | config = configparser.ConfigParser()
52 | config.read(filename, encoding='utf-8')
53 | return config
54 |
55 |
56 | def read_template(filename):
57 | with open(filename) as file_:
58 | return file_.read()
59 |
60 |
61 | def read_slides():
62 | slides = []
63 | for file in sorted(glob.iglob("*.md")):
64 | if file not in IGNORED_DOCS:
65 | with open(file, 'r', encoding="utf-8") as slide_file:
66 | content = slide_file.read()
67 |
68 | slides.extend(
69 | [slide.strip() for slide in content.split(SLIDE_DIVIDER)]
70 | )
71 |
72 | if not slides:
73 | raise RuntimeError("No slides loaded. "
74 | "Please add some slides or adjust IGNORED_DOCS.")
75 |
76 | return slides
77 |
78 |
79 | def render_slides(slides, config):
80 | agenda = create_agenda(slides)
81 | print("On our agenda: {}".format(', '.join(agenda)))
82 | rendered_agenda = render_agenda(agenda)
83 |
84 | combined_slides = SLIDE_DIVIDER.join(slides)
85 |
86 | rendered_slides = render_metadata(combined_slides, config)
87 | rendered_slides = rendered_slides.replace('{{ agenda }}', rendered_agenda)
88 |
89 | return rendered_slides
90 |
91 |
92 | def create_agenda(slides):
93 | agenda = []
94 | for slide in slides[1:]: # ignore title slide
95 | title = get_title(slide)
96 | if not title:
97 | continue
98 |
99 | if title not in agenda:
100 | agenda.append(title)
101 |
102 | return agenda
103 |
104 |
105 | def get_title(slide):
106 | match = re.match(r'^(class: .*\n+){0,1}#\s+(?P.*)$', slide, flags=re.MULTILINE)
107 | if match:
108 | title = match.group('title').strip()
109 | return title
110 |
111 |
112 | def render_agenda(agenda):
113 | if not agenda:
114 | # Avoid having an empty slide.
115 | return ("Unable to detect agenda. "
116 | "Please add at least one first-level heading (`# Title`) "
117 | "or remove the `{{ agenda }}` tag from your slides.")
118 |
119 | slide_count = ceil(len(agenda) / POINTS_PER_AGENDA_SLIDE)
120 |
121 | filled_agenda = []
122 | for index, agenda_points in enumerate(chunks(agenda, POINTS_PER_AGENDA_SLIDE)):
123 | if slide_count < 2:
124 | count = ''
125 | else:
126 | count = '{index}/{count}'.format(index=index + 1,
127 | count=slide_count)
128 |
129 | topics = ['- %s' % t for t in agenda_points if t is not None]
130 | points = '\n'.join(topics)
131 |
132 | filled_agenda.append(AGENDA_TEMPLATE.format(counter=count,
133 | points=points))
134 |
135 | return SLIDE_DIVIDER.join(filled_agenda)
136 |
137 |
138 | def chunks(iterable, count):
139 | "Collect data into fixed-length chunks or blocks"
140 | # chunks('ABCDEFG', 3) --> ABC DEF Gxx"
141 | args = [iter(iterable)] * count
142 | return zip_longest(*args)
143 |
144 |
145 | def render_metadata(slides, metadata):
146 | rendered = slides.replace('{{ title }}', metadata['meta']['title'])
147 | customer = metadata['meta'].get('customer', '')
148 | rendered = rendered.replace('{{ customer }}', customer)
149 | rendered = rendered.replace('{{ ratio }}', metadata['layout']['ratio'])
150 |
151 | if customer:
152 | slideFormat = f"%current% | %total% - KOPIE: {customer}"
153 | else:
154 | slideFormat = "%current% | %total%"
155 |
156 | rendered = rendered.replace('{{ slideNumberFormat }}', slideFormat)
157 |
158 | return rendered
159 |
160 |
161 | def write_file(filename, content):
162 | with codecs.open(filename, "w", "utf-8") as file_:
163 | file_.write(content)
164 |
165 | if __name__ == "__main__":
166 | main()
167 |
--------------------------------------------------------------------------------
/css/Inter-Light.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/css/Inter-Light.otf
--------------------------------------------------------------------------------
/css/Inter-Regular.otf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/css/Inter-Regular.otf
--------------------------------------------------------------------------------
/css/sva.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: "Inter-Light";
3 | src: url("Inter-Light.otf") format("opentype");
4 | }
5 | @font-face {
6 | font-family: "Inter-Regular";
7 | src: url("Inter-Regular.otf") format("opentype");
8 | }
9 |
10 | body {
11 | font-family: "Inter-Light";
12 | font-weight: 150;
13 | font-style: normal;
14 | color: black;
15 | line-height: 25px;
16 | vertical-align: super;
17 | margin: 0px 0px 19px 0px;
18 | }
19 |
20 | strong {
21 | font-family: "Inter-Regular";
22 | }
23 |
24 | ul ol {
25 | font-size: 14px;
26 | font-style: normal;
27 | font-weight: 300;
28 | text-transform: uppercase;
29 | text-align: left;
30 | }
31 |
32 | ul li:before {
33 | content: ">";
34 | padding-right: 8px;
35 | }
36 |
37 | ul li {
38 | background: 0 0 !important;
39 | border: 0 !important;
40 | display: block;
41 | text-decoration: none;
42 | list-style-type: none;
43 | }
44 |
45 | li {
46 | padding-bottom: 15px;
47 | }
48 |
49 | h1, h2, h3 {
50 | margin: 0 0 20px 0;
51 | /*line-height: 1.0;*/
52 | font-weight: 300;
53 | font-style: normal;
54 | text-transform: uppercase;
55 | }
56 |
57 | .remark-slide-content h1 {
58 | color: #2a6ab2;
59 | font-size: 60px;
60 | font-weight: normal;
61 | }
62 |
63 | .remark-slide-content h2 {
64 | color: #98aacd;
65 | font-size: 50px;
66 | }
67 |
68 | .remark-slide-content h3 {
69 | color: #bdc7dd;
70 | font-size: 40px;
71 | }
72 |
73 | .remark-slide-content h1:before {
74 | content: "//";
75 | padding-right: 8px;
76 | }
77 |
78 | .remark-slide-content table {
79 | width: 100%;
80 | }
81 |
82 | .remark-slide-content table td {
83 | padding: 5px;
84 | }
85 |
86 | .remark-slide-content table th {
87 | background-color:#98aacd;
88 | }
89 |
90 | .remark-slide-content table td {
91 | background-color: #e7ecf3;
92 | }
93 |
94 |
95 | a {
96 | color: #2a6ab2;
97 | }
98 |
99 | strong {
100 | font-weight: bold;
101 | }
102 |
103 | .remark-slide-content {
104 | font-size: 32px;
105 | line-height: 1.2;
106 | }
107 |
108 | .remark-slide-number {
109 | bottom: 12px;
110 | opacity: 1;
111 | position: absolute;
112 | left: 20px;
113 | right: auto;
114 | font-size: 12px;
115 | font-family: sans-serif;
116 | color: #999;
117 | }
118 |
119 | .remark-slide-number img {
120 | padding: 0 20px 0 0;
121 | }
122 |
123 | .hljs {
124 | font-size: 24px;
125 | }
126 | .remark-code-line-highlighted { background-color: #e7ecf3; }
127 |
128 | .footnote {
129 | position: absolute;
130 | bottom: 3em;
131 | }
132 |
133 | .red { color: #fa0000; }
134 |
135 | .small {
136 | font-size: 24px;
137 | }
138 |
--------------------------------------------------------------------------------
/handout.md:
--------------------------------------------------------------------------------
1 | # Handout
2 |
3 | Dies ist ein Beispiel-Handout.
4 |
5 | ## Überschrift 2
6 |
7 | * Eine Liste
8 | * mit
9 | * vielen Punkten
10 |
11 | ### Weitere Auszeichnungen
12 |
13 | Hier geht _kursiver Text_,
14 |
15 | es gibt **fetten Text**
16 |
17 | und `monospace Text`.
18 |
19 | ### Code-Beispiel
20 |
21 | ```Python
22 | import json
23 |
24 | null = None
25 |
26 | d = {
27 | "abc": "def",
28 | "foo": 1,
29 | "bar": null
30 | }
31 | ```
32 |
--------------------------------------------------------------------------------
/handout.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/handout.pdf
--------------------------------------------------------------------------------
/imgs/sva.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/imgs/sva.jpg
--------------------------------------------------------------------------------
/labs.md:
--------------------------------------------------------------------------------
1 | # Demo training
2 |
3 | ## Lab Guide
4 |
5 | ---
6 |
7 | ## Formatting
8 |
9 | | Format | Description |
10 | | ------ | ----------- |
11 | | **Note** | Important hint |
12 | | `command` | Shell output or command name |
13 |
14 | ---
15 |
16 | ## Lab 01: Demo
17 |
18 | TODO: Lab description
19 |
20 | 1. Task 1
21 | 2. Task 2
22 | 3. Yet another task you need to fulfill
23 |
24 | ```shell
25 | $ example command
26 | Lorem ipsum doloret...
27 | ```
28 |
--------------------------------------------------------------------------------
/labs/tests/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/labs/tests/.gitkeep
--------------------------------------------------------------------------------
/labs/tests/lab-1-task-1-Good Task.yaml:
--------------------------------------------------------------------------------
1 | tests:
2 | succeeds:
3 | command: exit 1
4 | exit-code: 1
--------------------------------------------------------------------------------
/labs/tests/lab-1-task-2-Bad Task.yaml:
--------------------------------------------------------------------------------
1 | tests:
2 | fails:
3 | command: exit 1
4 | exit-code: 0
--------------------------------------------------------------------------------
/presentation.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/presentation.pdf
--------------------------------------------------------------------------------
/screenshots/browser.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/screenshots/browser.jpg
--------------------------------------------------------------------------------
/screenshots/vscodium.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/svalabs/training-as-code/dbcbdbe056e8bd88ccb082501bc3fff08962a1c8/screenshots/vscodium.jpg
--------------------------------------------------------------------------------
/settings.ini:
--------------------------------------------------------------------------------
1 | [meta]
2 | title=SVA Demo-Präsentation
3 | customer=
4 |
5 | [layout]
6 | ratio=16:9
--------------------------------------------------------------------------------
/template.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ title }}
5 |
6 |
7 |
8 |
9 |
14 |
15 |
17 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/tools/lab:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | import os
3 | import re
4 | import subprocess
5 | import argparse
6 | import sys
7 |
8 | TEST_PATH = ''
9 |
10 |
11 | def get_labs():
12 | labs = set()
13 | lab_pattern = re.compile(r'lab-(\d+)-')
14 | for f in get_test_files():
15 | result = lab_pattern.search(f)
16 |
17 | if not result:
18 | continue
19 |
20 | lab = int(result.group(1))
21 | labs.add(lab)
22 |
23 | if not labs:
24 | print(f"No lab tests found")
25 | exit(1)
26 |
27 | return list(labs)
28 |
29 |
30 | def get_lab_test(lab):
31 | tasks = []
32 | for f in get_test_files():
33 | if f.startswith(f'lab-{lab}'):
34 | tasks.append(os.path.join(TEST_PATH, f))
35 | return tasks
36 |
37 |
38 | def get_test_files():
39 | try:
40 | files = os.listdir(TEST_PATH)
41 | except FileNotFoundError:
42 | print("Test folder not found. Are you in the labs directory?")
43 | exit(1)
44 | else:
45 | return files
46 |
47 |
48 | def run_single_check(lab):
49 | tasks = get_lab_test(lab)
50 |
51 | print(f"Checking lab {lab}\n")
52 |
53 | if not tasks:
54 | print(f"No tests defined for lab {lab}")
55 | exit(1)
56 |
57 | lab_task_pattern = re.compile(fr'lab-{lab}-task-(\d+)-(.+)\.(?:yaml|yml)')
58 | success_counter = 0
59 |
60 | for task in tasks:
61 | task_match = lab_task_pattern.search(task)
62 |
63 | if not task_match:
64 | print(f"Invalid task test name {task}. Please contact your instructor.")
65 | exit(1)
66 |
67 | task_num = task_match.group(1)
68 | task_name = task_match.group(2)
69 |
70 | print(f"[{task_num}/{len(tasks)}] Checking {task_name}...", end=" ")
71 |
72 | try:
73 | output = subprocess.check_output(['commander', 'test', task])
74 | except subprocess.CalledProcessError:
75 | print("\033[1;31mFailure!\033[0m")
76 | # TODO: Give some reasons here
77 | # Question is question is how much of the commander output to use
78 | else:
79 | print("\033[1;32mSuccess! \033[0m")
80 | success_counter += 1
81 |
82 | if success_counter == len(tasks):
83 | print("\033[1;32mAll tasks correct! \033[0m\n")
84 | else:
85 | print(
86 | f"\n\033[1;31mErrors in {len(tasks) - success_counter} "
87 | f"{'tasks' if len(tasks) - success_counter > 1 else 'task'}\033[0m\n")
88 |
89 |
90 | def run_full_check():
91 | labs = get_labs()
92 | for lab in labs:
93 | run_single_check(lab)
94 |
95 |
96 | if __name__ == '__main__':
97 | parser = argparse.ArgumentParser(description='check lab solutions for correctness.')
98 |
99 | parser.add_argument('check', nargs='?', default=None)
100 | parser.add_argument('--workdir', required=False, default="/home/vagrant/labs")
101 | parser.add_argument('--testpath', required=False, default="./tests")
102 | args = parser.parse_args()
103 |
104 | TEST_PATH = args.testpath
105 | os.chdir(args.workdir)
106 |
107 | if args.check:
108 | run_single_check(args.check)
109 | else:
110 | run_full_check()
111 |
--------------------------------------------------------------------------------