# Welcome!

| :exclamation: NOTE - this project has been archived. Please see [this blog post](https://nrelabs.io/2021/12/goodbye-for-now/) for more details. :exclamation: |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------- |

## Welcome!

[NRE Labs](https://nrelabs.io/) is an open-source project and website for making it easy to learn advanced infrastructure topics like automation. It accomplishes this by using real virtual environments that are provisioned on-demand and presented interactively in your web browser.

![](/files/-M-fpDMh2HNuGZwQ--Ge)

It's powered by the [Antidote](https://github.com/nre-learning/antidote) platform, which provides an abstraction to enable curriculum-as-code, meaning all learning materials can be represented as simple text files, stored in a Git repository.

This documentation is intended for people who want to get involved in contributing to the NRE Labs project. If this describes you, please follow the navigation to the left. It's probably best to follow it from top to bottom. However, if you're looking for more information about the project in general, head on over to <https://nrelabs.io>.

> This documentation is managed by [Gitbook](https://www.gitbook.com/) and the source is hosted in the [nrelabs-docs](https://github.com/nre-learning/nrelabs-docs) repository.


# First Steps

So, you want to contribute to the NRE Labs curriculum! Great, and thank you! Please read on for some helpful hints that will guide you along the process and ensure your time is spent wisely.

Before you get started, please read the [NRE Labs Curriculum Standards](https://github.com/nre-learning/nrelabs-curriculum/blob/master/CONTRIBUTING.md). This is **the** document used by all content reviewers to ensure curriculum quality remains high, and all contributions must adhere to these standards.

> **NOTE for Open Source Maintainers -** we would love the opportunity to host tutorials for your project. If you've created or are maintaining an open source project you should have the right of first refusal for contributing a lesson on your project in the NRE Labs curriculum.

{% embed url="<https://www.youtube.com/watch?v=HOU5k77RQNc>" %}
This video will walk you through some of the basics.
{% endembed %}

Some helpful tips before getting started:

* **Communicate your Idea** - The NRE Labs curriculum should be treated like any other open source project. It's built via contributions from all over the world, all the time. So before getting started, you should first spend time communicating your plans with the rest of the community. Peruse the [existing GitHub issues](https://github.com/nre-learning/nrelabs-curriculum/issues) to see if anyone is already working on something similar to what you have in mind. Maybe someone else is looking to build a similar lesson, and this gives you the opportunity to let them know, and combine forces. lf you are looking to collaborate on a lesson, [opening an issue](https://github.com/nre-learning/nrelabs-curriculum/issues/new) is often a good way to see if anyone in the community is interested in helping out.
* **Do You Need New or Changed Images?** - If your lesson will require new software images not already in the curriculum (or edits to an existing image), we have a dedicated document for handling [Endpoint Images in NRE Labs](/other-resources/nre-labs-endpoint-images), and you should definitely read this first. In the event that you need a new image or a modified image for your lesson, this must be handled **first**, ahead of any content contributions that may need them.

## Create a Fork and Branch

The NRE Labs curriculum is maintained on [GitHub](https://github.com/nre-learning/nrelabs-curriculum). As is the case with many open source projects, contributing to the NRE Labs curriculum involves a workflow called "Fork and Pull". This workflow involves making your own copy of the curriculum (known as a "fork"), making changes there, and then submitting a Pull Request to bring your changes back into the main curriculum repository.

If you're not familiar with Git, we actually [have a lesson that you might find useful](https://nrelabs.io/labs/?lessonSlug=git-version-control\&lessonStage=0). It's not specific to the NRE Labs curriculum, but if you're totally new to Git, it deals with all of the fundamentals you'll need to return to this document and follow the instructions to contribute to the curriculum.

> Before you get started, please ensure you've [added your SSH key to your GitHub profile](https://help.github.com/en/github/authenticating-to-github/adding-a-new-ssh-key-to-your-github-account). These instructions will assume that you've already done this, and will use SSH-based URLs for cloning and pushing commits.

To do this, click the "Fork" button in the top right of the [NRE Labs Curriculum repository](https://github.com/nre-learning/nrelabs-curriculum):

![](/files/-M-cr4HQhpVQe2G6c19w)

Next, GitHub will ask you where you want to place the fork. Remember, this is like making a copy, so it's asking where you want the copy of that repository to go. Usually, people select their own username. Doing that will result in a repository under your own GitHub username like so:

```
https://github.com/<your username here>/nrelabs-curriculum
```

Now that you have created a fork, you need to create a **local** copy of that fork so that you can actually work with the files. This is called ["cloning" the repository](https://git-scm.com/book/en/v1/Git-Basics-Getting-a-Git-Repository#Cloning-an-Existing-Repository):

{% tabs %}
{% tab title="SSH" %}

```
git clone git@github.com:<insert your username here>/nrelabs-curriculum.git
cd nrelabs-curriculum/
```

{% endtab %}

{% tab title="HTTP" %}

```
git clone http://github.com/<insert your username here>/nrelabs-curriculum.git
cd nrelabs-curriculum/
```

{% endtab %}
{% endtabs %}

This will result in a new directory at your current path called`nrelabs-curriculum`. Next, enter this directory and create a new branch (replacing `new-branch-name`with the name of your choice):

```
cd nrelabs-curriculum/
git checkout -b new-branch-name
```

## Bootstrap Your Content

Next, you'll need the [Antidote CLI](/antidote/the-antidote-cli). This is the command-line tool for bootstrapping new content for NRE Labs like lessons. Install this tool using the instructions provided, and then [follow the instructions here](/antidote/the-antidote-cli/create-curriculum-resources) to bootstrap a new curriculum resource such as a lesson. These interactive wizards will create a skeleton copy of a new resource within your existing curriculum directory, which you can then use as a starting point.

{% embed url="<https://www.youtube.com/watch?v=G3sM_5rk2yc>" %}
Here's a light introduction to using the Antidote CLI to bootstrap an example lesson
{% endembed %}

Once finished with the initial bootstrap, you'll also want to [validate your local curriculum](/antidote/the-antidote-cli/validating-an-existing-curriculum). This validation step can identify any problems with what you've built, and is a necessary next step after the initial bootstrap. The NRE Labs CI pipeline uses this command to validate that the curriculum is well-formed, so it's worth it to run this locally yourself first.

If you run into problems here, you may consider moving to the next phase, and open a pull request anyways. This way, maintainers will be able to see what you've done thus far, and provide suggestions.


# Open a Pull Request

In [First Steps](/creating-contributing/getting-started), you learned to use the `antidote`CLI tool to bootstrap and validate your new content. It is now time to push these changes to GitHub, and open a Pull Request. This will allow you to use the [Preview Service](/creating-contributing/preview-your-changes) to see your new content in action, as well as eventually get this content merged into the main curriculum repository.

{% embed url="<https://www.youtube.com/watch?v=mfEVoV7FiE0>" %}
This video is a brief introduction to opening a PR for NRE Labs
{% endembed %}

## Commit and Push

Once you've made some changes, you might be wanting to save your progress in Git so that you can track your progress. It's generally good practice to [make commits](https://git-scm.com/book/en/v1/Git-Basics-Recording-Changes-to-the-Repository#Committing-Your-Changes) somewhat often so that if you make mistakes, you can roll back easily.

Once you've made some commits, you'll want to "push" them. This ensures that the branch you have locally is replicated to your fork:

```
git push origin <your branch>
```

## Create a Pull Request

Once you have commits pushed, you can open a Pull Request, which is a way of saying "I have changes in my fork that I would like you to pull into the main repository". You may feel like you should wait to open a Pull Request until you're "done", which is totally okay. However, opening a Pull Request early, even right as you're starting work is not only okay too, but also encouraged. Any commits you push after opening the Pull Request will get added automatically, and it gives you a chance to open a dialog with reviewers. So don't be afraid to go down this path early.

If you navigate to the GitHub page for your fork, you'll notice that there's a little bar that says you're X commits ahead of the main repository, with some buttons next to it that let you open a Pull Request:

![](/files/-M-crTcLG-1UVV8-bgdd)

Make sure the correct branch is selected in the drop-down to the left, and then click "Pull Request" on the right. This will take you to the upstream repository to open a new Pull Request:

![](/files/-M-crXvXIRp1K-m2mWf-)

Be descriptive here - let folks know what you're working on and what state it's in. Feel free to use the description to summarize any outstanding work you have to do, if you're not quite finished.

Note the dropdown gives two options for opening a Pull Request. If you're not finished with your work, feel free to open a "draft" pull request - this gives reviewers a clear signal that you're not done, so any comments will be given in that light.

## Fixing Problems

When you open a Pull Request, there are a number of automated processes that take place. First, a series of automated checks run on your contribution to ensure it meets basic technical standards. The [Antidote CLI tool](/antidote/the-antidote-cli) is actually used behind the scenes to validate the syntax of all curriculum resources, and a few additional scripts kick off to do basic housekeeping things like ensuring the CHANGELOG is updated.

If any of these checks fail, the GitHub status checks will indicate this failure. Reviews or automated reviews won't take place until these checks pass, so if you see a failure, click through to the TravisCI build information to see where the failure happened.

![](/files/-M5OlUu7RAAZDZMZtJlC)

Once your Pull Request is open, you're ready to start using the [Preview Service](/creating-contributing/preview-your-changes) to see a live preview of your changes.


# Preview Your Changes

When building your content, eventually you'll reach the point where you want to see how it will appear on the NRE Labs site. This is possible simply by opening a Pull Request, which we covered in the previous step.

When you open a Pull Request, like any other software project, a series of automated checks take place to ensure some of the basics are in place. These include things like checking to make sure the CHANGELOG has been updated, some simple spellchecking, and validation of the lesson layout and metadata.

When you open a Pull Request, these checks immediate appear in the portion of the page highlighted in red below:

![](/files/-MWyjhFS71O8KSWuWWb0)

These basic checks happen first and if there are any problems here, the automated process stops, and will not continue until those problems are addressed.

![](/files/-MWyk9TEap7L3C3tULwA)

At any stage, including failures like the one pictured above, you can click on "Details" to the right of each check, to get more information about the progress of each check. Note that all checks labeled "Required" **must** pass in order for your Pull Request to be accepted, but that doesn't mean that if it does pass that your PR can be merged immediately - other changes may be requested by project maintainers beyond the simple checks performed here.

If the initial checks do pass, your contribution will go through a build process, which should only take a few minutes or less. This process will first build any [endpoint images](/other-resources/nre-labs-endpoint-images) that have changed in your PR:

![](/files/-MWykcaIyRTLX2b7lmIc)

This is another step that could fail. For instance, if your image's Dockerfile contains some kind of error, or something else causes the build process to fail, the corresponding check above will fail, and you can click "Details" to view the build logs for that step. This will allow you to see exactly what failed, and identify a next step for fixing the problem.

![](/files/-MWykpqU7JVCjtQ5i_Ob)

> You should first ensure that your images [build on their own](/antidote/object-reference/images#building-an-image) on your local machine before pushing them into your Pull Request. Please do not use this system as a way of iterating through the creation of an image from scratch, but rather as a last step to ensure an image that you believe is close to being finished, truly satisfies the requirements of the NRE Labs platform.

Once you've made the necessary changes to resolve any problems that have come up until now, you should get something that looks like the below screenshot, indicating a successful preview deployment.

![](/files/-MWylZx-mY2wZQAgicyH)

The check annotated with the number "1" is the main preview check, and you can click "Details" to be taken to a page that contains not only the link to your preview, but some other helpful troubleshooting information. The check labeled "2" contains logs for the preview infrastructure itself. Combined, these should provide you with some tools to troubleshoot if things go wrong, so do check them out.

If you click on "Details" for the main preview check, you'll see the following page:

![](/files/-MWymh1w67aEjI42Af19)

When you click the "Open Preview" link contained there, you'll notice it will take you to a semi-random URL, like:

```
https://preview-123abcde.nrelabs.io/
```

This is a randomly-generated URL for the preview for your pull request, and a new one is generated every time you make a change. This is not just a single lesson, but rather a self-contained instance of the **full NRE Labs platform**. This means that your preview URL will take you to what looks like the main NRE Labs site, but in fact this site is updated with the changes you've made. So, to see your changes, go through the lesson catalog and find your lesson, and launch it, just like you would on the main NRE Labs site.

More than likely, you'll still want to change things. Maybe the lesson works great, but you made a typo, or forgot to include a command in the lesson guide. Or maybe you forgot to install a dependency in the endpoint image. This is fine, and expected - simply continue to push commits to the branch you pushed as part of opening a Pull Request in the previous step, and a new preview will be built from the beginning.

> Please try to consolidate your commits, so the preview system can keep up with generating previews for everyone. Don't just push a bunch of small commits and minor changes, rather, try to bunch your changes into a few commits and push when you feel you have made all the changes you wanted to make. The project maintainers reserve the right to close Pull Requests and take other preventative actions in response to abusive behavior. If needed, maintainers may also request that you squash your commits prior to merging, or else they'll have to squash them on merge as a last resort.


# Review and Merge

**ALL** contributions to the NRE Labs curriculum must be done via a Pull Request, and Pull Requests can only be merged to `master`with an approving review from a project maintainer. This is **not** a hostile, arbitrary gate-keeping function, but rather a way of ensuring quality remains high for the curriculum.

With the exception of very small Pull Requests to fix things like typos, the chance that your Pull Request will be merged immediately with no suggested changes is very low. However, the good news is, that's okay, and expected. The job of a project maintainer is to get pull requests **merged**, not closed. So, you should expect that your pull request will likely generate questions, and probably some suggested changes. However, you can also expect the following behavior from any project maintainer:

* All comments/questions will be constructive in nature, aimed at helping you as a contributor, and the overall project grow.
* We always want to end every pull request in a "merge" if at all possible. Every question or suggestion is aimed at putting you closer to getting your contribution into the project.

All reviews will be aimed at keeping the quality of the curriculum high. Please read the [Curriculum Quality Standards](/other-resources/curriculum-quality-standards) and do your best to ensure that your content strives to meet those standards - it will make the review process a lot smoother.

Once your Pull Request is merged, it will be automatically included in the next [release of the curriculum](/other-resources/curriculum-release-process), and published on the site when that process finishes.


# Curriculum Quality Standards

NRE Labs is a **learning** platform. While there are certainly tools in the platform for creating compelling, interactive experiences, the goal of NRE Labs is not merely to demonstrate a piece of technology. These tools are supporting elements for the greater mission to educate and edify the learner and the infrastructure community as a whole.

This document is meant to provide guidance so that any contributed content can be well-aligned towards this mission. As you consider contributing to the curriculum, please approach it with a teacher's mindset. Always be asking yourself: "How can I meaningfully and tangibly improve the day-to-day experiences of the learner?" If you can learn to think this way, you'll find you'll be much better aligned with the spirit of the project.

Please read this document and its guidance thoughtfully. Doing so will make the review and ultimately, the acceptance of your contribution much smoother.

## NRE Labs' Guiding Principles

### The Learner Must LEARN Something

You'll notice that we rarely (if ever) use the term "users", but rather "learners" when referring to people who consume the content on NRE Labs. This is intentional; it helps us to keep our eyes on the mission of education, rather than pushing a certain tech stack or product feature.

From the beginning of the project, the goal of NRE Labs has been to tangibly improve the day-to-day lives of infrastructure professionals. The past few decades have been plagued with talk of people losing their jobs due to automation, and infrastructure professionals being "replaced by programmers". This project took a different approach, of not talking down to, but rather empowering these professionals with the skills they need to not only keep pace with the changing technology landscape, but to get ahead. There is no other goal that is more central to the NRE Labs project. It is our "[Raison d'être](https://www.merriam-webster.com/dictionary/raison%20d%27%C3%AAtre)".

The NRE Labs project is so much more than a collection of docker images that we let people play with in a web-based environment. This is certainly a great feature of the platform, but these are meaningless without compelling, well thought-out content that allows the learner to come away from this experience with real skills they can apply immediately.

These skills must also be reasonably portable. While it's totally acceptable to use a specific tool or technology to illustrate a concept, lessons that focus too deeply on the specific features/functionality of a given tool or product (to the point where the learner must use that exact same tool or product to get any value out of that content) are not appropriate for NRE Labs. Instead, lessons must focus on the concepts and principles, using specific tools or products as an illustration of an example of how those concepts can be achieved, leaving room for others.

So in short:

* **The Learner Must Acquire Tangible Skills From the Content** - It's not enough to have them run some commands - how can they take the underlying core principles behind the content and use them to improve their day-to-day?
* **Learned Skills Should be Portable** - Where at all possible, these skills must be widely applicable beyond a specific technology or stack. Can the learner take these skills and reasonably apply them in their own environment?

### The Learner Must DO Something

Complex subjects like automation can be especially hard to learn by simply reading a blog post. At some point you have to get practical experience before anything "sticks". So much of what modern infrastructure professionals are expected to know these days are acquired not only through textbooks or video courses, but by years of practical experience.

One of the biggest ways NRE Labs helps the learner adopt new skills is by giving them an opportunity to actually interact with relevant technologies in a very hands-on way. If our goal is to truly edify the learner, this "learning by doing" is how we make this possible.

However, this interactivity is a balancing act. What we aim for is to provide **the simplicity of a blog post, with the interactivity of a home lab**. When writing your content, try to keep this aim in mind. Content should provide a [compelling lesson guide](/antidote/object-reference/lessons/stages#lab-guides), with illustrative images and videos where possible, to help the learner understand what they're expected to accomplish in your lesson. This should be joined with tools like [Endpoint Images](/other-resources/nre-labs-endpoint-images) and [Presentations](/antidote/object-reference/lessons/presentations) to bring this content to life with real, interactive experiences. Break your content up into [Stages](/antidote/object-reference/lessons/stages), and build on concepts learned in previous stages to accomplish the broader purpose for your Lesson. Aim to give the learner a sense that they've really accomplished something, and that the time they spend in the NRE Labs curriculum will give them a tangible return on their investment.

It's also important that when you build interactive examples that you ensure this interactivity is at an appropriate level. If for instance, you build a lesson that shows a script that you built to solve a certain problem, perhaps it would be useful to first spend a few stages walking through the script, maybe having the learner run the commands in the script line-by-line. Don't just build a lesson for the purpose of having the learner run a few scripts: break those scripts down into the basic concepts and principles, so that the learner can learn from your thought process, and then write their **own** scripts.

Finally, there are some things you may want to do in the lesson environment that are not strictly relevant to the concept you want to teach. Maybe you need to run a script to prepare the environment at runtime so the learner can experience a specific workflow or aspect of a tool or technology stack. In this case, consider using [Endpoint Images](/other-resources/nre-labs-endpoint-images) and [Endpoint Configurations](/antidote/object-reference/lessons/endpoint-configuration) to prep the lesson environment behind the scenes, so that when a learner loads a lesson, they're given an environment that has already been prepared for them. It's important that the interactive steps that we give to the learner remain focused on the task at hand - anything outside of that scope can and should be automated by the NRE Labs platform using these tools.

So, to summarize:

* **Lessons Must be Appropriately Interactive -** Balance good content with useful interactivity.
* **Give the Learner Superpowers** - Don't just show the end result, teach the learner how to get there themselves.
* **Focus On the Task at Hand** - If a task needs to be done, but isn't core to the concepts you're trying to teach, try baking it into the [Endpoint Image](/other-resources/nre-labs-endpoint-images) or run via [Endpoint Configurations](/antidote/object-reference/lessons/endpoint-configuration) to keep learner's focus where it needs to be.

## Contribution Process

Generally we try to keep process to a minimum. However, to ensure quality remains high, there are a few things that any contribution must adhere to.

**ALL** contributions to the NRE Labs curriculum must be done via a Pull Request, and Pull Requests can only be merged to `master` if the latest commit on that Pull Request's branch satisfies all of these requirements:

1. Passes all GitHub CI checks
2. Has a valid "accepted" review from a curriculum maintainer.

Note that the goal for **each and every review** is not to nitpick or make it difficult to contribute to NRE Labs, but rather to ensure the content is reflected in the best light possible. Be patient and willing to adapt to feedback.

## Content Outline

From time to time, a reviewer may ask you for an outline of your planned content. This is an easy way for you to communicate the "big picture" for your content so that everyone can get on the same page with what your lesson is trying to teach.

For this purpose, you can think of an outline in the same way that someone would write a "table of contents" for a book. This can simply be a bulleted list where each entry is a [lesson stage](/antidote/object-reference/lessons/stages) you plan to create. In each bullet, briefly name and describe each stage and what you expect the learner to get out of it.

While there is no strict requirement for providing an outline ahead of time, you're encouraged to provide one **as early as possible**, to ensure that if there are any problems, they can be addressed early. For simple contributions, you may choose to provide this your contribution's Pull Request. For complex content, or especially if your content requires new [Endpoint Images](/other-resources/nre-labs-endpoint-images), a separate Issue ahead of time would be immensely helpful.

Well thought-out outlines should answer the following questions:

* How will this content be chunked, if appropriate, into separate [stages](/antidote/object-reference/lessons/stages)? Put each stage in its own bullet point.
* In each stage, what will the learner actually **do** interactively, and what skills will they expect to pick up along the way, that they can apply to their day job?
* Is the relevance to the learner clear from this lesson? How easy is it for people to link this content with their day-to-day?
* Does each lesson stage hit the target length of 5-10 minutes?

## General Quality and Technical Tips

Here are some helpful tips on general quality or various technical aspects of building NRE Labs content. Don't stress out too much about these; do your best, and we'll help you work things out during the review process.

* Are the lesson guides easy to follow? Are they well-written, with appropriate chunking, punctuation/grammar, and visuals?
* If you're creating or modifying images, have you read the guide on [NRE Labs Endpoint Images](/other-resources/nre-labs-endpoint-images)?
* Does the lesson appropriately take advantage of Antidote's features, such as [lesson guide types](/antidote/object-reference/lessons/stages#lab-guides), diverse [presentations](/antidote/object-reference/lessons/presentations), lesson diagrams or videos?
* Ensure that any [configurations](/antidote/object-reference/lessons/endpoint-configuration) you use treat each stage atomically. Don't assume that the learner will view each stage in order.


# Curriculum Release Process

The NRE Labs curriculum is managed like any software project, with regular, planned release cycles. The lifecycle of a curriculum release is performed in four discrete steps.

### Step 1 - Release Kickoff

A post will be created in the [Project Management](https://discuss.nrelabs.io/c/project-management/10) forum topic to notify everyone that the work on this release has begun, with the title "Release Kickoff...". This forum thread should serve as the center of all release planning discussions, and all are welcome to participate. If you have something you think should be included in or excluded from the release plan, speak up there.

In this first kickoff, we'll begin gathering ideas for things we want to get done in this release. These will be retrieved from various sources:

* Open issues or PRs in the curriculum repo - comb and triage; Which are ready to be worked on, or are most imminent?
* Ideas from the community not yet documented formally
* Tasks needed for updating the curriculum to be compatible with a new platform version (if applicable)
* Any tasks that need to be done to bring the existing curriculum in line with the targeted Antidote platform version

While the kickoff is meant to get a starter list together, it's likely that more ideas will come up at any time in the release cycle. This is normal, and expected. However, the first week of a release cycle should strive to ensure the really important things are well-documented and if possible, assigned.

Another very important task for this initial meeting is to decide which Antidote platform this curriculum release will [target](/other-resources/curriculum-release-process#appendix-platform-targeting). Once this is determined, the [preview service](/creating-contributing/preview-your-changes) will be updated to use this version to ensure compatibility.

A project plan for the release that represents the work discussed in the previous week will be posted to the [projects list](https://github.com/nre-learning/nrelabs-curriculum/projects) and presented to attendees. This is a kanban-board style project planning tool that allows all to easily see the state of work for a given release.

Finally, a post will be created in the [Project Management](https://discuss.nrelabs.io/c/project-management/10) forum topic to notify everyone that the work on this release has begun, with the title "Release Kickoff...". This forum thread should serve as the center of all release planning discussions, and all are welcome to participate. If you have something you think should be included in or excluded from the release plan, speak up there.

> Not all work fits neatly into a release plan, and that's okay. Especially in the curriculum, contributions of any kind can reasonably take place at any time. The purpose of a release plan isn't to put limits on the work that can be done for a release, but rather to ensure that the important things that really **need** to get done are accounted for. If you want to work on something that's not explicitly asked for in the release plan, that's totally fine.

### Step 2 - Development Work

Once a release cycle is kicked off, the only thing left to do is....do the work! At this point, a relatively complete list of things to do for this release should be captured in a Github project, which will be linked to in the community forum kickoff post. Contributors can use this as a guide, or do other work they think is useful.

The [curriculum contribution guide](/creating-contributing/contributing-content) should be consulted repeatedly to ensure you're on the right track with respect to curriculum contributions. All of those guidelines apply here. It's important for contributions to follow this lifecycle, so that release managers can properly coordinate work across the project.

### Step 3 - Testing Phase

At some point, the list of tasks that are meant to be tackled for a given release are complete, and it's time to initiate the process of cutting a release, and getting it into production.

The first step in this process is to ensure the latest changes in the `master` branch of the curriculum are properly represented in the PTR. This should automatically happen nightly, but someone from the NRE Labs Ops team will make sure this is true.

A forum topic will be posted to [Curriculum Project Management](https://discuss.nrelabs.io/c/curriculum-project-management)\_ with the title "Testing Curriculum Release vX.X.X". This will contain a link to the testing procedure, and a summary of the CHANGELOG at that point in time, so that new content can be tested properly. For a minimum of seven days from the date of the post, contributors should test the site as it exists in PTR, and submit feedback.

The best way to provide feedback is via a response to that original forum topic, or a Github issue in the curriculum repository.

> Instead of submitting feedback, you may feel like you can just fix it yourself in a Pull Request. This is always welcome and appreciated, and is often the easiest way to make your first contribution to the curriculum. So, don't be shy! See the [curriculum contribution guide](/creating-contributing/contributing-content) for more info on how to do this.

The curriculum maintainers will stay on top of feedback and strive to ensure that all problems are either fixed via a Pull Request, or documented via an Issue for a future release. The Testing Phase will not end until the maintainers are comfortable that the latest `master`, as represented via the PTR site represents a healthy curriculum.

### Step 4 - Release and Deployment

Once the testing phase has completed, the NRE Labs Ops team will execute a workflow that creates the target version release for the curriculum, and will deploy this version to production.

In addition, if this curriculum release is meant to target a new version of the Antidote platform, the production site should also be updated accordingly.

In the following week (or at most two), the cycle will repeat, and a new release kickoff will take place.

### Appendix - Platform Targeting

The NRE Labs curriculum is released separately from the underlying Antidote platform. As a result, the platform's release cycle will charge ahead with new features, and it's up to the curriculum release planning to "target" a stable version of the platform to develop against. The below image shows an **example** of how this might work:

![](/files/-M-cpsD8-B0POJhhtjNm)

At the time the curriculum started on its own release cycle, `v0.4.0` of the platform was released simultaneously with `v1.0.0` of the NRE Labs curriculum. In the future, the curriculum may want to release a new version before `v0.5.0` of the platform is ready. In this case, the curriculum, starting with `v1.1.0` will continue to target `v0.4.0` until a suitable stable platform release is ready.


# NRE Labs Endpoint Images

The primary purpose of NRE Labs is to provide education on modern network engineering and automation principles. So, while this purpose is often accomplished by including specific tools, software, or other technologies, let us not lose sight of this over-arching mission.

That said, one of the biggest benefits of the NRE Labs platform is to use real software in real environments, spun up on demand, to provide compelling interactive experiences in which this learning can take place. In NRE Labs, we accomplish this through [Endpoint Images](/antidote/object-reference/images). These are pre-built docker images that we reference from Lesson definitions to power the learner experience.

If you're looking for technical details on how Endpoint images work, and how to create or add them to the curriculum, please head on over to the [Images object reference](/antidote/object-reference/images). The remainder of this document will instead help you understand the higher-level process for dealing with Images within the NRE Labs curriculum, and answer some frequently-asked questions.

## Do You Need a New Image?

**NRE Labs curriculum images are where all the complexity lies**. To make things easy for the learner, we have to take on a lot of the complexity that would normally be on their plate, and instead do it ourselves using prebuilt [Docker images](/antidote/object-reference/images), and other tools like [endpoint configuration](/antidote/object-reference/lessons/endpoint-configuration). As a content author, you should be aware that if you choose to go this direction, you need to be willing and able to shoulder this complexity.

In general, new curriculum content like [Lessons](/antidote/object-reference/lessons) should take advantage of the Endpoint images that already exist. Images are not meant to be used once, for one lesson - they are meant to be standalone resources that could be used in multiple lessons as the need arises.

There are a few options you should consider before you decide to create a new image. They are, in order:

1. There are a number of existing images that are designed to be very multi-purpose. For instance, the `utility` image comes with Python and a bunch of automation-related libraries pre-installed.
2. If you just want to share some basic files or scripts into the lesson environment, consider using an existing image like `utility`, and using NRE Labs' built-in [directory mapping](/antidote/antidote-architecture/lesson-directory-mapping) to make those files available.
3. Maybe there's an existing image that's just missing a dependency. Consider augmenting an existing image, by simply adding a step to that image's `Dockerfile`, or maybe a `requirements.txt` file if applicable.
4. If none of these options work for you, read the [Images reference](/antidote/object-reference/images) for the technical details on how to create an image. You can contribute a new image on its own, or as part of a content contribution that uses this new image.

> Currently the best place to see details on existing images is to look at the NRE Labs curriculum repository manually. In the future, we'll have some better tooling around this.

## Commercial Software

NRE Labs is aimed at educating about modern infrastructure engineering processes. While open source software has had a dramatic impact on this space over the last decade (which is well-represented by the presence of open-source in the NRE Labs curriculum) it's not possible for the NRE Labs project to **only** include open source software. Most infrastructure professionals are not able to avoid commercial software entirely, and neither can this curriculum.

All commercial software in the curriculum will continue to adhere to the [Curriculum Quality Standards](/other-resources/curriculum-quality-standards). Whether open source or commercial, the technology is never the sole focus of the content - it is the skill-sets that a learner can acquire. While we'll continue to have a healthy mix of open and closed software, no matter what, the focus will be on the content and improving the skills of the infrastructure professional.

All contributions that adhere to the spirit of the project are welcome. We already have network operating systems from Juniper, and Cumulus Networks (with more on the way), and software from Red Hat Ansible. This is in addition to the myriad of open source tools and projects that are heavily featured in our curriculum.

Commercial software that has been contributed doesn't have to be publicly downloadable. We have mechanisms in place that allow us to control where the commercial software is distributed, giving the learner access to the software only through the NRE Labs portal. Reach out to us via [the community forums](https://discuss.nrelabs.io/c/general-discussion/6) or [via email](mailto:nrelabs@gmail.com) for more details on this.


# Git Tips

The Antidote project does everything in the open. All configurations, curriculum resources, and source code can be found in one of the GitHub repositories in the [`nre-learning`](https://github.com/nre-learning) organization. As a result, no matter where you want to contribute to the Antidote project, you're likely able to do so by contributing to one of these repositories.

However, not everyone that wants to contribute knows how Git works, and even for those that do, the way the Antidote project uses Git to accept contributions may not exactly match with previous experience. This document is aimed at covering everything you'll need to know to contribute to any Antidote repository. Other pages within this documentation explain the specifics of contributing to the curriculum, the underlying platform, the development environment, or even the documentation itself, but they all have one common theme - at some point, in order to contribute, you will need to work with Git or Github.

So, those pages will focus on the specific details and repositories they cover, but will inevitably link here. So, this document will apply to any Git repository those pages might reference, even though we'll use some specific examples here for illustrative purposes.

> This is **not** meant to be a tutorial on Git or Github. While you certainly don't need to be a Git expert to work with Antidote repositories (especially if you're only interacting with Github), you will always be well-served to get some basics under your belt. This [`basic introduction`](https://git-scm.com/book/en/v1/Git-Basics) is highly recommended reading, and we will be making some references to the terms contained within. In addition, if you don't have a Github account, sign up for one [here](https://github.com/join). There's really no getting around it, if you wish to interact with the Antidote project in nearly any capacity.

The [`nrelabs-curriculum`](http://github.com/nre-learning/nrelabs-curriculum) repository is probably one of the most popular repositories in the Antidote project. While not technically part of the Antidote platform, it is the flagship curriculum developed for the platform, and is what powers the [NRE Labs](https://nrelabs.io) site. For the vast majority of examples, we'll be using this repository to illustrate the concepts, but for the most part, everything applies to any Antidote repository.

## "Watching" for Activity Notifications

One of the easiest ways to start getting involved with the Antidote project is to just pay close attention to what's going on. In addition to making sure you're aware of new threads on the [`community site`](https://discuss.nrelabs.io/)(which you should totally do), a leading way to do this is to "Watch" the Antidote repositories relevant to you. You can do this by navigating to one of the repositories, and clicking the "Watch" drop-down at the top right of the page:

![](/files/-M-cqNxpXaqMIaoXUt38)

Make sure you also take a look at your [notification settings](https://github.com/settings/notifications) to ensure that not only are you notified for new issues and Pull Requests, but also that the email address is one that you check often. Notifications at this level are always relevant and technical, and represent the true nature of discussion going on with the project. So if you're willing to turn notifications on for anything, this is the time to do it.

## How and When to Open an Issue

The [community forums](https://discuss.nrelabs.io/) are the best place to go for general discussions and support with developing lessons, or even working with code on the Antidote platform. However, sometimes it's necessary to make more of a definitive statement, such as "I think I'm encountering a bug, here's what I'm seeing", or "I really with Antidote did X". In these cases, where such a statement may not have an immediate answer but clearly represents some level of work to satisfy, a GitHub Issue is often the best place to post that.

Issues aren't restricted only to folks to have pushed code or other content to a repository. If you have constructive feedback, that is just as valuable a contribution, and opening a new Issue is a great way to do that. Examples include:

* Bug reports (even if you're not quite sure it's a bug)
* Feature requests
* Help with an error

Every repository has an "Issues" tab that you can click to take you to the currently open Issues for that repository:

![](/files/-M-cqcFJLPDD_5LhQxew)

There's a big green button at the top left of that page (once you click the Issues tab) that said "New Issue". Clicking that will take you to a form where you can provide a title and description. For some Antidote repositories, these fields will be pre-populated with a framework of the kind of information that would be very helpful to anyone that looks into things for you. In general, follow the guidance that's there, but post as much detail as you can, and be ready to provide more if asked.

## Using Labels to Identify Work Complexity

If you have poked around at the open issues, you may notice that some of them have colorful tags attached to them. GitHub calls these "labels", and they are useful for providing additional categorization for issues or pull requests.

Lots of folks approach open source projects with some enthusiasm and willingness to get involved, but often don't know where to start. It's pretty difficult to look at a list of bug reports and have any idea how far the rabbit hole goes for any of them. The best way to get started with a project is to take on a task that gets you that experience without requiring you to spin your wheels for weeks, which is super demotivating.

For you, we've created complexity ratings in the form of GitHub Issue labels, and try our best to apply them to each issue on the Antidote repositories:

![](/files/-M-cqggc1-Q6ytBBGfjz)

These are things like enhancements or bug-fixes that we've set aside that are relatively approachable, and don't require you to know how everything works in order to satisfy them. What this means for you, is you can easily get a look at a repositories low-hanging fruit tasks by filtering issues by the `complexity: low` label. For the `nrelabs-curriculum` repository, [this URL gets you straight there](https://github.com/nre-learning/nrelabs-curriculum/labels/complexity%3A%20low).

However, nearly all Antidote repositories have the same taxonomy, so no matter where your interests lie, this mechanism is in place for you to identify those "entrance ramp" tasks. If you lean more towards web or front-end development, the [complexity: low tag in antidote-web](https://github.com/nre-learning/antidote-web/labels/complexity%3A%20low) may interest you. If you like to work on back-end systems, or with languages like Python or Go, [the same tag in antidote-core ](https://github.com/nre-learning/antidote-web/labels/complexity%3A%20low)may interest you.


# Jupyter Notebooks

> This guide is meant to help learners understand how to use Jupyter-based lesson guides within a lesson. If you're a content author that wishes to know more about using Jupyter notebooks in your lesson, please see "[Writing Lab Guides with Jupyter Notebooks](/antidote/object-reference/lessons/stages#writing-lab-guides-with-jupyter-notebooks)".&#x20;

If you encounter a jupyter notebook within a lesson, you might be initially overwhelmed with the number of buttons and options. Don't worry about that - you really only need to know a few key things.

![](/files/-M-fGcFXi3rHZY6tI4nk)

The above image shows the toolbar for a jupyter notebook. You'll find this immediately below the dropdown selector where you can navigate between the labs within a lesson. The main thing you will use here is the "run" button. This is what allows you to execute a selected snippet of code. For instance, in the below image, we have a python snippet embedded in the lab guide. We've selected it, and can execute the code within using this "run" button:

![](/files/-M-fGg6WUB8SJhhr4HyI)

Depending on the snippet, you might see some output below.

![](/files/-M-fGidqV35JhnC9zIPb)

Note that you might not get any output. This depends on whether or not the code being executed is meant to produce output, and/or how long it takes to process the instruction.

Also note that most jupyter notebooks expect that you'll run all of the snippets in order. Not doing this might result in some errors. Just follow the instructions in the lab guide if you get stuck.

Finally, you can edit the contents of a notebook! The text and code provided is just part of the lab, but the great thing about jupyter notebooks is that you can play around with them, and download a modified version.

![](/files/-M-fGlKpIxhs2sCUr6jW)

Play around with editing the code provided and running it again! Experiment and learn!


# Tips and FAQs

## How are you running network devices in this thing?

Everything in Antidote is executed in Kubernetes, so everything has to be a container. On the surface, this may seem like a barrier to being able to run virtual networking images, which are commonly available as virtual machines. Indeed, a common misconception is that the two models are mutually exclusive, but they're not.

At the end of the day, a container is just a highly configured process, and QEMU can execute virtual machines easily with a single command. We build all of this into a container image, so that in essence, when the container is started, the virtual machine is started as well.

See :ref:`architecture <architecture>` for more details on this and other aspects of images within Antidote.

## Do you only support Junos?

Definitely not. In fact, the underlying Antidote platform doesn't care at all what operating system a lesson endpoint uses, only that it's accessible via the ports described in a [Presentation](/antidote/object-reference/lessons/presentations).

[As of v1.1.0](https://github.com/nre-learning/nrelabs-curriculum/releases/tag/v1.1.0), the NRE Labs curriculum includes and makes use of a Cumulus VX image as well, and we have plans to add even more in the near future. Any other networking vendor that is interested in donating a virtual image for their kit and is willing to abide by the project's [governance document](https://github.com/nre-learning/proposals/blob/master/governance.md) and the [code of conduct](https://github.com/nre-learning/proposals/blob/master/codeofconduct.md) is welcome to participate in the project.

##


# Architecture

Antidote is a platform for providing an on-demand, interactive learning experience that removes all of the usual complexity of setting up your own lab environment, and instead does it all behind the scenes, giving the user a purely web-based portal to interact with.

To make this happen, Antidote plays a role in a broader technology stack, which we'll overview below:

![](/files/-M2smmvthE_PcFZCFxCG)

### Curriculum

All of the lessons and labs are defined as a standalone curriculum. This model makes it easier for contributors to develop interactive content - they don't need to be web developers to add content to the NRE Labs experience.

The Antidote platform is built to treat this as a modular component. For instance, the [NRE Labs curriculum](https://github.com/nre-learning/nrelabs-curriculum) is the flagship curriculum that is powering the [NRE Labs](https://nrelabs.io) site, but it is possible to develop a different curriculum and deploy it on top of Antidote if you wish, in your own environment.&#x20;

### Platform

This is where the custom software components of Antidote live. In particular, [Syringe](https://github.com/nre-learning/syringe) provides an upstream API for provisioning lesson resources, then makes the relevant calls to Kubernetes to make sure the relevant, specific compute resources and policies are instantiate&#x64;*.* [Antidote-web](https://github.com/nre-learning/antidote-web) consumes the API offered by Syringe and is responsible for providing a fully web-based experience for interacting with lesson resources.

### Kubernetes

Kubernetes was selected as a common substrate for the Antidote platform for better portability between cloud providers or on-premises deployments. Aside from performance considerations, the underlying cloud or bare-metal infrastructure doesn't matter; as long as the Antidote platform is deployed on a Kubernetes cluster, that's all that matters. We recommend running Kubernetes on a bare-metal cluster (while not strictly required), and it must support CNI.

> Why not Hosted Kubernetes? There are two main constraints we need to solve before moving into something like GKE:
>
> * There is currently no hosted Kubernetes offering that gives the performance of bare-metal. For the NRE Labs site, this is absolutely necessary.
> * The current networking model uses a CNI plugin to make the lesson networking work. All of the existing hosted kubernetes options from the major cloud providers have rather strict networking models and don't let you bring your own CNI plugin.

### Infrastructure

This part is a lot more flexible. While we recommend baremetal for performance reasons, there's no technical requirement for it. Anywhere you are able to stand up a Kubernetes cluster should work, such as on-prem servers, virtualization environments, cloud (IaaS), etc.

## Lesson Resources

Lesson resources will be started over the infrastructure for each connected learner in parallel, isolated, according to the lesson specification.

Lesson resources will typically be inter-networked Kubernetes PODs (containers) which will be available for each learner.

In the following figure, the platform runs the same example lesson for 2 learners in parallel. Each lesson instance contains 2 resources (`vqfx1` and `linux1`), running inside their own Kubernetes "namespaces". A learner learner may then interact with the resources as dedicated virtual machines, using Web consoles connected via SSH to the right resources.

![](/files/-LzL4RHifagSUWt7Irk_)

##

*


# Antidote Services

The Antidote platform is composed of two services:

* `antidote-web`
* `antidoted`

Antidote-Core is where the real work gets done in the Antidote project. It's responsible for taking in lesson definitions via [a YAML file](/antidote/object-reference/lessons) and any configs, scripts, etc used in the lesson, and providing them to the front-end via its API.

## Configuring Antidote

Antidote is configured through a YAML file. Since typically Antidote is deployed within Kubernetes, the ideal way to do this is through a ConfigMap.

If you're using [antidote-selfmedicate](https://github.com/nre-learning/antidote-selfmedicate) to spin up an instance of Antidote yourself, a configuration file is provided for you.

(should have a sample config file in the antidote-core repo, and just link to it here)


# Lesson Directory Mapping

There are two ways to get your "stuff" into a lesson:

* Image
* Directory

The decision here depends on the nature of that "stuff". Is the stuff lesson specific? If so, probably best to put it into the lesson directory. Is it part of the software used within an image? Build it into the endpoint image itself. Also for large files, it's often better to download it during build time and place it into the image (see [Images - Large or Sensitive Files](/antidote/object-reference/images#large-or-sensitive-files)).

Putting your "stuff" (scripts, configs, etc) into a Docker image isn't the only way to get it into a lesson. At this point, you probably know that Antidote lessons are defined with simple text files, and those files are stored in a Git repository. What you might not know is that when a lesson is instantiated, the full directory that contained that lesson in the Git repository is made available to each lesson endpoint.

Every endpoint that's instantiated in a lesson has that lesson's directory mapped to it, and all of its contents. If you just want to run a set of bash or Python commands, or you have a script you wish to show, you likely don't need to do anything beyond simply placing those files into the lesson directory, or putting a set of commands into a lesson guide.

The `utility` image, for example, comes preloaded with Python and a bash shell, so can satisfy a lot of use cases here. You simply reference this image when defining an endpoint in your lesson definition, and any files you place in the lesson directory will be made available at runtime to the configured directory. In NRE Labs, this is the `/antidote` directory.

## How do I get my "stuff" into a lesson?

It's quite rare to have a lesson in mind that doesn't also include some kind of custom "thing". This could be a simple script you wrote or downloaded and wish to show it in your lesson, configuration or data files used by an application, or full-blown software you'd like to be installed and running or available within the environment. At the end of the day, your goal is to get this "stuff" into your lesson definition.

In the **vast majority of cases**, the best way to do this is simply to store those files in your lesson's directory tree. When your lesson is launched, this lesson directory is mapped via volume to every container that runs in a lesson (at `/antidote`) so just by having those files in that directory, you'll have access to them at runtime.

You can also create an [Endpoint Image](/antidote/object-reference/images) if you're looking for a more complicated software installation to be available in your lesson.


# Lesson Networking

Kubernetes provides a lot of great primitives for managing the individual resources that make up a lesson programmatically, but with one major caveat - the networking model is not very conducive to running network devices. The popular use case for Kubernetes is to deploy simple applications within containers that have a single network interface, `eth0`.

Since we want to run network devices with multiple network interfaces that are connected together in a dynamic way, we need to do some creative stuff on the back-end to make things work. This is a part of the design that's still getting worked out, so the documentation on this will be necessarily light until we have a more solid foundation here. However, the TL;DR for how things currently work is as follows:

![](/files/-LzL4XPTeNGuhGxSRvrL)

* Every Kubernetes pod is connected to the "main" network via its `eth0` interface. This is nothing new. However, because we're using [Multus](https://github.com/intel/multus-cni), we can provision multiple networks for a pod.
* When we schedule lesson resources, we use affinity rules to ensure all of a lessons' resources are scheduled onto the same host.
* Depending on the resource type, and the connections described in the [lesson definition](/antidote/object-reference/lessons),

  we may also connect additional interfaces to a pod, connected to other networks.
* Since all pods are on the same host, if we need to connect pods together directly, such as in a specified network topology, we can simply create a linux bridge and add the relevant interfaces. In the future, we will do away with affinity rules and use overlay networking instead of the simple linux bridge.
* For security reasons, network access outside the lesson namespace is disabled. All lessons should be totally self-contained and not rely on external resources to properly function when the lesson is being run.

NetworkServiceMesh is an alternative to Multus that may allow us to accomplish the same goal of running multiple network interfaces out of a pod, but without the requirement of using a custom CNI plugin. It also doesn't directly integrate with whatever CNI plugin IS in use (we ran into some issues with Weave+Multus, which is why we use linux bridges and therefore host affinities). Further exploration is needed, but if NSM satisfies performance and scale considerations, we're seriously considering moving to it.

DNS in Antidote is [provided by Kubernetes](https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/) So, if you want to reach vqfx1, simply query for `vqfx1`. You will be directed to the corresponding service in your namespace. Note that each lesson + session combination gets its own namespace, which means `vqfx1` is locally significant to your lesson specifically.


# The Antidote CLI

The Antidote platform also comes with a CLI tool called `antidote`, which is meant to be used primarily by curriculum authors to validate or create new curriculum content like lessons.

You can always find the latest release[ here](https://github.com/nre-learning/syringe/releases/latest), where pre-compiled binaries for Antidote have been posted. For convenience, shell commands for downloading the latest version of this tool on your system are below:

{% tabs %}
{% tab title="macOS" %}

```
curl -Lo antidote.tar.gz https://github.com/nre-learning/antidote-core/releases/download/v0.7.0/antidote-darwin-amd64.tar.gz
tar xvzf antidote.tar.gz
./antidote -h
```

{% endtab %}

{% tab title="Windows (x64)" %}

```
$ProgressPreference = 'SilentlyContinue'
Invoke-WebRequest https://github.com/nre-learning/antidote-core/releases/download/v0.7.0/antidote-windows-amd64.zip -O antidote.zip
Expand-Archive -Force -LiteralPath 'antidote.zip' -DestinationPath .
.\antidote.exe -h
```

{% endtab %}

{% tab title="Linux (x64)" %}

```
curl -Lo antidote.tar.gz https://github.com/nre-learning/antidote-core/releases/download/v0.7.0/antidote-linux-amd64.tar.gz
tar xvzf antidote.tar.gz
./antidote -h
```

{% endtab %}
{% endtabs %}

Note that this will result in the `antidote` binary being made available in the current directory. You may wish to either add this directory to your PATH, or move the binary to one that already is. The remainder of this documentation will assume you've done this, so that you can simply run the command `antidote` from anywhere. You can of course instead run the binary via the relative path shown in the final command above if you wish, it will work fine the same way.


# Create Curriculum Resources

The `antidote`tool comes with the ability quickly bootstrap a new resource, such as a lesson. This provides you with an interactive wizard that walks you through all of the fields within a resource definition, and creates a barebones framework for that lesson. In the case of a lesson, this not only creates the required `lesson.meta.yaml` file, but also all of the files and directories required by that lesson.

You can access this wizard by simply running `antidote <resource> create`. So, to create a new lesson, run `antidote lesson create`. You'll immediately be presented with a series of prompts to provide the necessary information to bootstrap that lesson:

{% embed url="<https://www.youtube.com/watch?v=G3sM_5rk2yc>" %}

> Similar commands may exist for other resources like `images` and `collections`.

Note that this tooling isn't designed to build a finished lesson, only a starting point. There's still a lot left to do at the end of these wizards, so pay close attention to the hints at the end of the wizard for next steps.

Next thing you'll want to do is bookmark the [Antidote Object Reference](/antidote/object-reference). All curriculum resources, such as lessons, are defined "as-code", meaning they are all defined using simple text files stored in Git. This documentation is vital for knowing what kind of things you can use to create an awesome lesson, so read that carefully, and follow the instructions there, whether you're creating a new lesson, or modifying an existing one.


# Validating an Existing Curriculum

One of the things `syrctl` can do for us is validate lesson content to make sure it has all of the basics to work properly. This is done via the sub-command `syrctl validate`. This command is directed at a curriculum directory in order to work: for instance, we have the NRE Labs curriculum installed locally:

```
~$ ls -lha
total 68K
drwxr-xr-x  6 mierdin mierdin 4.0K Apr 21 22:52 .
drwxr-xr-x 10 mierdin mierdin 4.0K Apr 15 23:19 ..
drwxrwxr-x  3 mierdin mierdin 4.0K Apr 17 17:39 collections
drwxr-xr-x  8 mierdin mierdin 4.0K Apr 23 21:27 .git
drwxr-xr-x 18 mierdin mierdin 4.0K Apr  6 12:49 images
drwxr-xr-x  5 mierdin mierdin 4.0K Apr 21 22:52 lessons
-rw-r--r--  1 mierdin mierdin 5.2K Apr 21 22:54 CHANGELOG.md
-rwxr-xr-x  1 mierdin mierdin  500 Apr 15 15:19 check-changelog.sh
-rw-rw-r--  1 mierdin mierdin    0 Apr 21 13:04 curriculum.meta.yaml
-rw-r--r--  1 mierdin mierdin   33 Apr  6 12:49 .dockerignore
-rw-r--r--  1 mierdin mierdin  573 Apr  6 12:49 .gitignore
-rw-r--r--  1 mierdin mierdin  12K Apr  6 12:49 LICENSE
-rw-r--r--  1 mierdin mierdin 1.1K Apr 15 18:56 README.md
-rw-r--r--  1 mierdin mierdin  288 Apr  6 12:49 .travis.yml
-rwxr-xr-x  1 mierdin mierdin  288 Apr 15 15:19 validate-lessons.share
```

We're already `cd`'d into this directory, so we just need to run `syrctl validate .` to instruct syrctl to validate the local directory:

```
~$ syrctl validate .
INFO[0000] Successfully imported lesson 14: Introduction to YAML --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 0, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 16: Using Jinja for Configuration Templates --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 0, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 17: Version Control with Git --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 0, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 19: Working with REST APIs --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 3, CONNECTIONS: 4 
INFO[0000] Successfully imported lesson 22: Introduction to Python --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 0, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 23: Linux Basics --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 0, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 12: Network Unit Testing with JSNAPY --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 3, CONNECTIONS: 3 
INFO[0000] Successfully imported lesson 13: Multi-Vendor Network Automation with NAPALM --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 1, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 15: Event-Driven Network Automation with StackStorm --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 3, CONNECTIONS: 3 
INFO[0000] Successfully imported lesson 18: End-to-End Network Testing with ToDD --- BLACKBOX: 0, IFR: 0, UTILITY: 2, DEVICE: 1, CONNECTIONS: 2 
INFO[0000] Successfully imported lesson 24: Junos Automation with PyEZ --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 1, CONNECTIONS: 1 
INFO[0000] Successfully imported lesson 25: Juniper Extension Toolkit (JET) --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 1, CONNECTIONS: 1 
INFO[0000] Successfully imported lesson 26: Vendor-Neutral Network Configuration with OpenConfig --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 1, CONNECTIONS: 1 
INFO[0000] Successfully imported lesson 29: Using Robot Framework for Automated Testing --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 1, CONNECTIONS: 1 
INFO[0000] Successfully imported lesson 30: Network Automation with Salt --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 1, CONNECTIONS: 1 
INFO[0000] Successfully imported lesson 31: Terraform & Junos --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 3, CONNECTIONS: 3 
INFO[0000] Successfully imported lesson 21: Automating the Troubleshooting Chain --- BLACKBOX: 2, IFR: 0, UTILITY: 2, DEVICE: 3, CONNECTIONS: 6 
INFO[0000] Successfully imported lesson 32: Automated STIG Compliance Validation --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 1, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 33: Quick and Easy Device Inventory --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 2, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 34: Automated Device Configuration Backup --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 2, CONNECTIONS: 0 
INFO[0000] Successfully imported lesson 35: Device Specific Template Generation --- BLACKBOX: 0, IFR: 0, UTILITY: 1, DEVICE: 2, CONNECTIONS: 0 
INFO[0000] Imported 21 lesson definitions.              
All detected lesson files imported successfully.
```

This runs the exact same logic that `syringed` would use to load lessons on the server-side, so this is a really handy way to make sure the basics of curriculum definitions are done correctly.

On the [NRE Labs Curriculum repository](https://github.com/nre-learning/nrelabs-curriculum), we're actually running `syrctl validate` on every new Pull Request to ensure things are set up properly, as much as possible.

There are things it won't check - like the validity of a network configuration, or that your Docker image is built properly, but in terms of the things that Syringe requires, it will give you confidence in a stable starting point, rather than reading through a list of points in this doc.


# Object Reference

Antidote is a platform for bringing otherwise complicated technical learning material to the masses, by taking care of the complexity behind the scenes, out of sight of the learner. To that end, there are a variety of tools we make available to you, the lesson author / teacher to make this possible.

Some tools are designed to make things easier to teach, others makes things easier to learn, other things do both. Please read through this portion of the documentation so you don't miss out on any useful tools you can leverage to really make your content stand out.

In Antidote, all curriculum content is defined through a set of types, usually represented either as YAML files, or as properties of a type that is represented in a YAML file. We'll loosely refer to these things as "objects", and they (as well as any supporting files) are stored within a Git repository, forming a curriculum. This section of the documentation is meant to be used as a reference - all supported Antidote objects are defined and explained in these sections.

It's important to note that while this portion of the documentation is designed to inform about details, the vast majority of what's contained here is available through the various creation wizards of [the `antidote` CLI tool](/antidote/the-antidote-cli).


# Images

To understand images within NRE Labs, the first place you should probably look is the set of [existing images in the NRE Labs curriculum](https://github.com/nre-learning/nrelabs-curriculum/tree/master/images). Familiarize yourself with the images that are there, and take a look at what they have in common.

Next, you should read the document on [NRE Labs Endpoint Images](/other-resources/nre-labs-endpoint-images) to understand some of the higher-level principles and processes for Images within the NRE Labs curriculum. This document will assume you've read that and have decided to build your own image.

Once finished with this document, you can open a Pull Request to the NRE Labs curriculum to add a new folder to the [images directory,](https://github.com/nre-learning/nrelabs-curriculum/tree/master/images) with all of the files mentioned below.

## Building an Image

In Antidote and NRE Labs, Endpoint Images are just Docker images that we use within the context of a lesson. As a result, the vast majority of what you need to know to build an Endpoint image is contained in any reasonable Docker tutorial, especially content that focuses on building images. For now, start with tutorials like the ones below, and learn the basics of Docker images:

* [Docker: Getting Started](https://docs.docker.com/get-started/)
* [Dockerfile Best Practices](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/)
* [Interactive Katacoda Lesson on Docker](https://www.katacoda.com/courses/docker/2)

Some tips for building an image:

* **Keep it lightweight** - don't import the entire internet into your image. If your image needs more than 4GB of memory to run, and more cores than you have fingers, you've made a wrong turn. Include only that which is nece
* **Keep it simple** - Endpoints in NRE Labs are for learning - they're not meant to be highly-available or fault-tolerant. Deploy the simplest version of your software when building images - the [StackStorm](https://github.com/nre-learning/nrelabs-curriculum/tree/master/images/stackstorm) image is a good example of this - all services running in a single container. This is **fine**.
* **Use trusted, lightweight base images** - Default to using trusted images like `debian` or `centos` as your base image. This not only helps to keep image size down, but also helps us keep a handle of what's running in our images. Use [multi-stage builds](https://docs.docker.com/develop/develop-images/multistage-build/) if you need to keep the final image size to a reasonable number.
* **Include the entire source** - in addition to the required files listed below, any scripts, configs, or misc. files needed to run "docker build" must be provided in any Pull Request. The only exception to this is [Large or Sensitive Files](/antidote/object-reference/images#large-or-sensitive-files).

Note also that in most cases, images need to be built to be interactive. Anything configured within the [Endpoints](/antidote/object-reference/lessons/endpoints) and [Presentations](/antidote/object-reference/lessons/presentations) sections of a lesson definition will require some kind of network access, such as a running HTTP or SSH server. Even lesson endpoints that don't have explicit presentations will still have some kind of server, such as an API. Make sure you've considered this in building your image - some kind of network access will be necessary at runtime.

## Required Files

There are a few extra files needed by every image that are specific to NRE Labs:

### Makefile

Images are automatically built using our back-end CI/CD workflows, and require a Makefile to be put in place that supports a particular way of being called. You may include steps of your own if needed, but at a minimum, the Makefile **must** contain the following (please insert your own image name):

```
# SHELL=/bin/bash

TARGET_VERSION ?= latest

all: docker

docker:
	docker build --pull --no-cache -t antidotelabs/<image name here>:$(TARGET_VERSION) .
	docker push antidotelabs/<image name here>:$(TARGET_VERSION)
```

### Dockerfile

All images must also come with a [Dockerfile](https://github.com/nre-learning/nrelabs-curriculum/blob/master/images/utility/Dockerfile). This allows us to build our own image, rather than directly using a third-party image. All necessary steps to customize this base image should be done here.

### Image Definition

To use an image within NRE Labs, images must come with a meta-data file called `images.meta.yaml`. This is similar to the [meta-data file for lessons](/antidote/object-reference/lessons) but much simpler.

The best way to create a new image definition is using the [`antidote` command-line interface](/antidote/the-antidote-cli), using the `antidote image create` subcommand. This will walk you through an interactive wizard that creates a new image definition with all the relevant fields. Note that this doesn't automatically provide any other required files, like Makefiles or Dockerfiles. You're still on the hook for doing this.

Read the below for an example image definition, with comments in-line:

```yaml
---

# Uniquely identify the image
slug: stackstorm

# Brief description of the image
description: stackstorm

# Should this image be run with privileges? (assume no)
privileged: false

# Username and password for connecting via an SSH presentation
sshUser: antidote
sshPassword: antidotepassword

# Username and password used for configuration scripts
configUser: antidote
configPassword: antidotepassword

# List of network interfaces for this image
networkInterfaces:
  - 'eth0'
```

## Large or Sensitive Files

Occasionally, such as for [commercial software](/other-resources/nre-labs-endpoint-images#commercial-software), we need to include sensitive files in the build process. This might be a commercial network operating system image, or perhaps a license file.

If your image requires a large file (pretty much anything over 10MB) that already exists somewhere else on the internet, rather than trying to put it in the lesson directory, add a step to your Dockerfile or Makefile to download those files from their original location (preferably with integrity verification using SHA256 hash or similar).&#x20;

If you have a large or sensitive files you wish to include in an NRE Labs image, but don't want those files to be publicly available, the NRE Labs project also maintains a private cloud storage bucket that is accessible only within our build system, and these are downloaded during the build process. [Get in touch with us](https://discuss.nrelabs.io/) and we'll help you figure out a way to get these into the curriculum safely.


# Lessons

Lessons are the quintessential curriculum resource. When Syringe starts, it looks for lesson definitions within the configured curriculum directory, loads them into memory, and serves them directly via its API.&#x20;

Lessons are primarily defined using a `lesson.meta.yaml` file. This is written in YAML, and contains a series of fields for making a lesson work.&#x20;

If you're feeling overwhelmed, don't worry. This file can be broken up into sections, and we'll do this to explain it, piece by piece. For now, let's just focus on the top portion:

```yaml
---

# A human-readable title for your lesson
lessonName: Network Unit Testing with JSNAPY

#
lessonSlug: unit-testing-jsnapy
category: tools
lessonDiagram: https://raw.githubusercontent.com/nre-learning/nrelabs-curriculum/v0.3.2/lessons/lesson-12/lessondiagram.png
tier: prod
prereqs:
  - 14  # YAML
  - 23  # Linux
description: Unit testing your network devices is one of the fundamental building blocks to CI/CD for networking. In this lesson, we'll explore the use of an open source tool - JSNAPy - for doing just this with Junos devices.
slug: JSNAPy
tags:
- jsnapy
- test
- unit test
- testing
collection: 1
```

> Some of these fields are required, some aren't. Some have a length requirement, and others don't. For guidance here, you should definitely get up to speed with the [`syrctl`](broken://pages/-LzL5JfXsD5YyqmCA4DF#the-syringe-client-syrctl) tool. That tool has a validation function you can run on a curriculum, and it will let you know if anything needs fixed.

* `lessonName` The human-readable name for a lesson. Kind of like a blog post title.
* `lessonSlug` A unique ID for this lesson. You can assign this yourself, as long as it's unique in this curriculum.
* `category` The category for this lesson - supported options are "fundamentals", "tools", and "workflows"
* `lessonDiagram` An internet-accessible URL to an image to use as a diagram for this lesson
* `tier` The environment this lesson is meant to run in. Options are "local", "ptr", and "prod"
* `prereqs` A list of lesson IDs that a learner should go to first, to prepare for this lesson properly.&#x20;
* `description` A slightly more long-form explanation of what's included in this lesson
* `slug` Ideally, a very short (1-3 words) summary of this lesson. Used for searching.
* `tags` A list of keywords that are included in this lesson. Used for searching.

The remaining sections are explained in separate documents:

* The `endpoints` section is explained in [endpoints](/antidote/object-reference/lessons/endpoints).
* The `connections` section is explained in [connections](/antidote/object-reference/lessons/connections).
* The `stages` section is explained in [stages](/antidote/object-reference/lessons/stages).


# Authors


# Stages

When learning any topic, it's important to be able to break it up into reasonable "chunks". No one wants to start at a wall of learning material they know will take them the better part of an afternoon to get through.

In Antidote, lessons are broken up into Stages. The intention behind Stages is to provide a logical place to "break up" lesson content. You can think of them like chapters in a textbook; where the goal of an Algebra textbook is to teach algebra, we really only care about linear equations in Chapter 1. Those not only provided bounded structures for learning, where the learner is able to more easily wrap their head around the content and feel like they've accomplished something, it also helps them understand the path in front of them.

In any lesson, Stages are defined using the `stages` stanza in the lesson definition file:

```
stages:
- id: 1
  description: No BGP config - tests fail

- id: 2
  description: Correct BGP config - tests pass
```

When a lesson is loaded in the web front-end, these stages show up as a continuum that the user can select, underneath the lab guide:

![](/files/-M-fQqPy7XIOWYmCNNf2)

While the Stage definition seems simple, there's a lot that goes on when a user navigates between Stages by selecting something in that drop-down:

* All Endpoints with a [`configurationType`](/antidote/object-reference/lessons/endpoint-configuration)  will be reconfigured accordingly. This happens

  when a lesson is initially loaded
* Endpoint health checks as described in [Presentations](/antidote/object-reference/lessons/presentations) are **not** done between stages. Presentations are static for the whole lesson, regardless of Stage. They're done when the lesson is initially loaded.
* When a stage ID is omitted, the default is to load the first one, but this isn't a requirement for users. Each lesson URL includes a Stage ID, which means hyperlinks to any stage in any lesson are honored. What this means for lesson builders is that while your Stages can (and should) have a natural progression, you should not rely on users to have done something themselves in Stage 1 in order for Stage 2 to work. If you have the user accomplish a task in Stage 2, you should still overwrite all configs yourself to the expected value in Stage 2's configurations.

Each Stage has a particular directory structure that you should be aware of. As with most things involving curriculum resource definition, most of this is enforced by `syrctl` so you can validate this structure yourself, but here are some general rules:

```
.
├── jsnapy_config.yaml
├── jsnapy_tests.yaml
├── lessondiagram.png
├── lesson.meta.yaml
├── stage1
│   ├── configs
│   │   ├── vqfx1.txt
│   │   ├── vqfx2.txt
│   │   └── vqfx3.txt
│   └── guide.md
└── stage2
    ├── configs
    │   ├── vqfx1.txt
    │   ├── vqfx2.txt
    │   └── vqfx3.txt
    └── guide.md
```

* Each stage must have a corresponding directory called `stage<N>` where `N` is the stage ID.
* Each stage directory must have a `configs` directory, where all of the files related to [Endpoint configuration](/antidote/object-reference/lessons/endpoint-configuration) should be kept.
* Each stage directory must also have either a markdown-based lesson guide, or a jupyter notebook to be used for the same. We'll get into the differences between these in the next few sections.

### Lab Guides

All NRE Labs lessons come with lab guides. These are meant to be instructions the learner can follow along with so they're not spinning your wheels, wondering what to do with a lesson. It is also meant to include snippets of code or commands for them to execute, or have executed for them.

**TODO** - State in the lesson guide docs to not put any top-level headers, we'll do that for you. Just start right into your first paragraph.

There are two options for lesson guides in Antidote today:

* `Markdown <Writing Lab Guides with Markdown>`
* `Jupyter Notebooks <Writing Lab Guides with Jupyter Notebooks>`

You can choose either of these options **on a per-stage basis**. This means that Stage 1 can have a Markdown lesson guide, Stage 2 a Jupyter notebook, and Stage 3 back to Markdown, if you want. The `NRE Labs NAPALM lesson <https://labs.networkreliability.engineering/labs/?lessonId=13&lessonStage=1>`\_ is a good example of a lesson that leverages both options. The sections below will explain how to use either option.

## Writing Lab Guides with Markdown

The simplest option by far is to write lab guides with [`Markdown`](https://daringfireball.net/projects/markdown/syntax). This is an extremely popular, simple formatting syntax for creating rich documents from plain-text sources. Most of the time when you see a `README` file on a GitHub repository, the chances are very good that it's written in Markdown. What Github does is translate the raw text of the file into richly formatted, rendered versions appropriate for viewing in a web browser.

To enable this same experience for Antidote, lesson guides can be written in Markdown, and `antidote-web` will take care of translating the source file into HTML to be presented to the user.

You don't have to use self-medicate to preview the HTML version for your Markdown documents. While every Markdown renderer is a bit different, and there might be some minor differences within the Antidote front-end, if you're just looking for some basic HTML preview functionality, there are plenty of tools to do this:

* Keeping in the spirit of doing everything in the browser, [Dillinger](https://dillinger.io/) is **very handy** for

  working on lesson guides with a constant preview.
* Most popular text editors also have markdown preview functionality built in or available via plugin. For example, there's good support for this in [VS Code](https://code.visualstudio.com/docs/languages/markdown).
* There are a number of CLI tools available as well for doing the conversion yourself, such as [`Pandoc`](https://pandoc.org/), if you are so inclined.

While native Markdown is perfectly fine, there's one feature built into `antidote-web` you should be aware of that really uplevels your lesson guide. In Markdown, you can wrap a bit of text with triple-backticks, and it will preserve the formatting you use within that block. This is very useful for code or CLI commands, where the structure is very important.

````
```
echo "Hello World!"
```
````

Markdown-based lab guides include the ability to add a "Run this snippet" button to automatically run the contents of a code snippet in a given terminal tab. This is extremely useful and recommended to allow users to quickly execute your examples without having to type it out themselves.

To do this, the lesson author only needs to add some HTML underneath each snippet:

````
```
echo "Hello World!"
```
<button type="button" class="btn btn-primary btn-sm" onclick="runSnippetInTab('linux1', this)">Run this snippet</button>
````

Most of the HTML shown above can remain the same, but in the above example `linux1` refers to the tab where this snippet should be executed. The front-end will switch to the tab named accordingly and paste that text automatically. So, you'll need to edit this to point to the tab you want.

Also, when you're adding a snippet to a lesson guide, sometimes you may want an extra newline run at the end. For example, if you are executing some Python code, and your snippet ends on a loop, or a conditional, you need an extra newline to get the interpreter to understand you're done defining the loop.

The solution to this is to use `<pre>` tags in lieu of the traditional triple-backtick for embedding code in Markdown:

```
<pre>
echo "Hello World!"
</pre>
<button type="button" class="btn btn-primary btn-sm" onclick="runSnippetInTab('linux1', this)">Run this snippet</button>
```

These are rendered exactly the same way in the lesson guide, but the latter is interpreted much more literally when being pasted into the terminal window, meaning the extra newline is executed like any other character.

Finally, when you have a lesson guide ready, place it in the stage directory as `guide.md`. This is where the Antidote platform will look for this lesson guide.

## Writing Lab Guides with Jupyter Notebooks

> This section is focused on lesson authors looking to use Jupyter notebooks in the creation of a lesson. [See here](/other-resources/the-learners-guide-to-jupyter-notebooks) if you're looking for an overview of how to **use** lesson guides in NRE Labs.

Many folks who have invested time in education on automation or related topics have some experience with [Jupyter notebooks](https://jupyter.org/). Jupyter notebooks are awesome in their own right, and it's not fair to force folks to convert that content to Markdown just to get it working with Antidote. So, Antidote natively supports the use of Jupyter notebooks as lab guides in lieu of a Markdown-based guide.

> Fair warning - Jupyter notebooks offer a lot more functionality than Markdown-based lab guides, but they do add a layer of complexity as a result. So, if you're starting from scratch, it's *probably* best to start with Markdown-based lab guides. However, the choice is yours.

Even cooler - any lesson that uses a Jupyter notebook is automatically provisioned a background Endpoint dedicated to running that notebook, that is run alongside all other Endpoints for that lesson. That means that you can take advantage of Kubernetes DNS when referring to other Endpoints in your notebooks. If you want to send a REST API request to an Endpoint with the name of `webapp`, you can refer to it via the hostname `webapp`, right in the notebook. No need to figure out IP addresses for stuff.

To use a Jupyter notebook as a lesson guide in an Antidote lesson, you need only add the line `jupyterLabGuide: true` to each Stage that requires it in your lesson definition. Here's an example of a lesson that uses Jupyter notebooks for stages 1, 2, and 4, but uses the traditional Markdown format for stage 3:

```
stages:
- id: 1
  description: Get device facts
  jupyterLabGuide: true
- id: 2
  description: Get information with NAPALM "getter" functions
  jupyterLabGuide: true
- id: 3
  description: The NAPALM Command-Line Utility
- id: 4
  description: Make configuration changes with NAPALM
  jupyterLabGuide: true
```

When you do this, you will need to make sure that a jupyter notebook titled `notebook.ipynb` is in all relevant stage directories. This obviates the need for a `guide.md` file.

If you're starting from scratch and wish to write a Jupyter notebook, your best bet is to follow an [online Jupyter notebook tutorial](https://www.codecademy.com/articles/how-to-use-jupyter-notebooks) to get it started. Or you can copy one from an existing lesson into your lesson, and once spun up, you can use the Jupyter GUI to edit and download the revised notebook.


# Endpoints

A foundational concept within Antidote is the ability to run the software or appliances needed to educate the learner about a particular topic. It's nice to have lesson guides that walk through a concept, but the whole point of the Antidote project was to provide that ease of use without sacrificing any of the interactivity that comes with being able to play with the tech directly.

At its core, an Endpoint is simply a Docker container that is built to run some software. This could be a simple Bash/CLI environment, it could be a web server, or even a full-blown network device. While the technical implementation of these endpoints is done by Images, Lessons refer to these Image through Endpoint definitions as described here. Bottom line, if you want the user to interact with something in your lesson, you need Endpoints.

Generally, Endpoints are configured within the :ref:`lesson definition <lessons>` file, `lesson.meta.yaml`, which can be found at the root of any lesson directory. Within this file, Endpoints are declared under the `endpoints` key, like so:

```
endpoints:
- name: linux1
  image: antidotelabs/utility
  presentations:
  - name: cli
    port: 22
    type: ssh

- name: vqfx1
  image: antidotelabs/vqfx-snap1
  configurationType: napalm-junos
  presentations:
  - name: cli
    port: 22
    type: ssh
  additionalPorts: [830]
```

A few points about the above:

* The `name` field is up to you to define - you can call each endpoint whatever you want, provided all endpoints

  have a unique name.
* The `image` field is a DockerHub-compatible image reference, which is passed directly to the underlying Kubernetes infrastructure to run your image. [See here for more information on images](/antidote/object-reference/images).
* The `configurationType` field is optional, and allows you to specify what kind of automatic

  configuration should be done for this endpoint. [See here for more information on endpoint configuration](/antidote/object-reference/lessons/endpoint-configuration).
* The `presentations` field is also optional, and allows you to specify ways that this endpoint should be presented to the user. This could be a CLI terminal, or even a web application with it's own tab. [See here for more information on endpoint presentations](/antidote/object-reference/lessons/presentations).
* The `additionalPorts` field allows you to specify any additional ports that should be opened for this endpoint. By default, only the ports listed in a `presentation` are opened. So, this field allows you to directly specify ports that should be opened regardless of the presentations that are configured.

## Health Checks

In order to know if a lesson is running, Syringe will perform health checks on endpoints based on each endpoint's configured `presentations` field. By default, for every Presentation, Syringe will perform a basic TCP connection periodically as a heartbeat to ensure that these presentations are accessible. This means that each endpoint must be able to provide connectivity on every port opened by a Presentation.

Some endpoints may not have any Presentations - in this case, the `additionalPorts` field is required, and must have at least one port configured. Syringe will then use the first port in this list to perform a health check, and will mark the endpoint as healthy.

Once all endpoints are viewed as healthy, based on these health checks, the lesson will move into the configuration stage, or if no configuration is necessary, will move directly into the Ready state, so that the web front-end can start offering the content to the learner.


# Presentations

At this point, hopefully you understand how :ref:`Endpoints <endpoints>` provide a basis for creating an interactive learning experience. However, there's no interactivity unless those Endpoints are made accessible somehow to the learner. Enter Presentations.

## Defining a Presentation

You can specify a list of Presentations on an Endpoint to indicate how you want that Endpoint to be "presented" to the learner. A simple example is shown below. In this case, we're offering a single Presentation for an Endpoint, that provides SSH terminal access to that endpoint over port 22:

```
endpoints:
- name: linux1
  image: antidotelabs/utility
  presentations:
  - name: cli
    port: 22
    type: ssh
```

As you can see, each Presentation in the list has three fields for you to specify:

* `name` - The name of the presentation. This can be whatever you want, as long as it's relatively short and

  unique for that endpoint.
* `port` - The port that Antidote should use to access the container for this Presentation.
* `type` - This controls the type of presentation being offered. Currently supported options are `ssh` and `http`.

You can get creative with Presentations. First and foremost, you probably noticed that the `presentations` attribute is plural form, and provided as a YAML list. This is because you can have multiple Presentations to the same Endpoint:

```
endpoints:
- name: linux1
  image: antidotelabs/utility
  presentations:
  - name: cli1
    port: 22
    type: ssh
  - name: cli2
    port: 22
    type: ssh
  - name: web
    port: 80
    type: http
```

These will all be shown as individual tabs in the web front-end, and they will be disambiguated via their Presentation name. For instance, the example above will result in tabs `linux1-cli1`, `linux1-cli2`, and `linux1-web`.

Finally, in some cases you don't want **any** presentations. A common example of this is some kind of endpoint that you need to access from another Endpoint via REST API. You want to provide a Presentation to the user to execute some kind of tool or script, but the Endpoint offering the REST API merely needs to exist in the environment and respond to queries.

In this case, merely omit the `presentations` field entirely, but note that in this case`additionalPorts` becomes a required field, and must specify at least one port.

```
endpoints:

- name: linux1
  image: antidotelabs/utility
  presentations:
  - name: cli
    port: 22
    type: ssh

- name: restapi
  image: antidotelabs/utility
  additionalPorts: [80]
```

Because the above Endpoint `restapi` didn't have any presentations, we needed to ensure at least one port was provided in `additionalPorts`. The learner can then access the `linux1` endpoint and use the tooling in that Endpoint to access the REST API of `restapi`.

## Presentation Options

There are some implementation details for each of the available presentation types specified in the `type` field that you should be aware of.

### SSH

**Usage:** `type: ssh`

This one is pretty straightforward. A very common use case for interacting with Endpoints is to provide an interactive CLI (Command Line Interface) terminal in the Antidote front-end. This is accomplished by connecting directly to the Endpoint via SSH, and using that connection to provide the experience to the web.

As long as your Endpoint is configured to listen on the port you specify in the Presentation for SSH connections with the username `antidote` and `antidotepassword`, Antidote will take care of connecting it to the user on the front-end.

### HTTP&#x20;

**Usage:** `type: http`

Not all content is best shown via the CLI. Sometimes you want to be able to show some kind of web-based portal that's running on an Endpoint, such as a self-service application, which interacts with other Endpoints on the back-end.

In this case, the `http` type can be used. A tab will be opened for this Presentation, but instead of a terminal, the tab contents will show the web application you provide in the Endpoint (in an `iframe`). A few considerations for this option:

* HTTPS is not currently supported. We need to iron out a few wrinkles in the implementation first, and we'll support either protocol, very soon. For now, use HTTP, and the Antidote load balancer will serve the content from a reverse proxy that provides HTTPS.


# Connections

In Antidote, [Lesson Endpoints](/antidote/object-reference/lessons/endpoints) are spun up as containers within a Kubernetes cluster. As a result, they all have a single `eth0` network interface by default. However, as NRE Labs is designed to teach complex infrastructure topics, often a single network interface is not enough. This document will explain how we use a concept called "Connections" to provide multiple interconnections directly between Lesson endpoints.

Imagine you have a lesson definition with three endpoints: `vqfx1`, `vqfx2`, and `vqfx3`. You can think of these like nodes in a graph topology, as all networks are. So, if Endpoints are nodes, then the edges, or the connections between these nodes, are `connections`:

```
connections:
- a: vqfx1
  b: vqfx2
- a: vqfx2
  b: vqfx3
- a: vqfx3
  b: vqfx1
```

This is a simple list of connections from `a` to `b`. The first connection is from `vqfx1` to `vqfx2` and so on. Antidote will create virtual networks for each Connection, and then attach Endpoints to them.

## How will these networks show up in my lesson?

The way these networks will be made available will depend on how the image is built. If a native container, `net1`, `net2`, and so forth. If a VM-in-container, it could be anything. In the future we may go with a solution like Kata containers by default, which could also add a wrinkle.

At the moment, the best place to know which network interfaces will be available to you is to consult the the image metadata files, which includes a list of network interfaces that the image makes available to be used. This is an ordered list, and interfaces are consumed in order of the Connections that reference that endpoint.


# Endpoint Configuration

One of the best attributes of the Antidote platform is that it takes on as much complexity as is needed on the back-end in order to provide a seamless learning experience to the user on the front-end. A big part of this is the ability to automatically configure all lesson endpoints to fit the scenario being used to teach a concept, so that when the learner is ready to take on a subject, they aren't distracted by fiddling with configurations to "prep" the lesson.

Much of this advantage is gleaned from the fact that all Endpoints are started from Docker images, which start the same way each time. All Endpoint software dependencies, configurations, scripts, etc. are built right into the image. However, it's not always possible to put **everything** into this image at build time. For instance, a network device can be built as a Docker image, but depending on the Lesson or Stage, might have wildly different configurations, in order to teach a particular concept. For this, Antidote offers the ability to configure Endpoints dynamically once they're started from their base image.

> Don't overdo it with endpoint configuration. The fact that Antidote is powered by containers which are cryptographically guaranteed to start from the same base image each time is a huge advantage and it's useful to bake configurations into the container image wherever possible. So, use the configuration options below, but in proper balance with an already fairly functional base image configuration.

To accomplish this configuration, the Antidote project maintains a `configurator` image, which has all of the necessary prerequisites for performing Endpoint configuration. When Antidote needs to perform a configuration for lesson Endpoints, such as when a lesson is initially loaded, or when the user is navigating to a new Stage, Antidote will spin up one configuration pod per lesson endpoint to perform the relevant configuration steps, and will populate those pods with a few useful environment variables that can be consumed by the configuration scripts defined by the lesson author. They are described below:

| Variable                     | Description                                                                                                               |
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| ANTIDOTE\_TARGET\_HOST       | Set to the IP address of the endpoint. Useful because this is always dynamic                                              |
| ANSIBLE\_HOST\_KEY\_CHECKING | Set to "False" so that Ansible is able to connect to any image if used (we don't pre-populate our images with known keys) |

Endpoints are individually configured on a per-stage basis, and the Antidote platform provides several mechanisms for accomplishing this, so lesson builders have options when it comes to configuring their Endpoints.

Specifying which configuration type you want to use for your endpoint is fairly straightforward, but there are some underlying implications you should be aware of for each option, which we'll explain below.

## Configuration Options

### NAPALM&#x20;

**Usage:** `configurationType: napalm-<driver>`

One of the most popular use cases for configuring endpoints between stages is putting a network configuration into place that's relevant to the concepts being taught. You may want to have three virtual switches in a topology but based on the stage being viewed, the configuration might need to change. This is a very common scenario.

Rather than write a custom Python script or Ansible playbook to simply load a config onto a network device, you can use the [NAPALM](https://github.com/napalm-automation/napalm) configuration option shown here.

To use this option, you need to specify a specially formatted `configurationType` value. This configuration option uses the `napalm-<driver>` syntax, where `<driver>` is the name of the [NAPALM driver](https://napalm.readthedocs.io/en/latest/support/#general-support-matrix) you wish to use. For instance, if the network device is running Junos, you'll specify `configurationType: napalm-junos`. Anything after the hyphen is passed directly to NAPALM, so make sure you're using the right driver name.

This configuration option will look for a file with the extension `.txt`, which is named identically to the endpoint you wish to configure. For instance, a configuration for a device called `vqfx1` will be named `vqfx1.txt`. A configuration file must exist for every endpoint that uses this option, in the config directory of every stage.

Some network images use IP masquerade (NAT) for the management interface, which means you don't need to worry about the IP configuration for this interface - it's usually static per that image's configuration. The "outer" address is assigned automatically from a container level, and the inner virtual machine doesn't need to worry about it. However, in some cases, NAT is not used, and you need to be able to leverage the environment passed to the configuration pod to ensure you get the right address. If this describes you, read on. If not, you can safely ignore the next paragraph.

As mentioned previously, all configuration pods are started with the environment variable `SYRINGE_TARGET_HOST` set to the IP address of the endpoint within Kubernetes. This is useful because this is assigned dynamically and you might want to use this in your configuration. So, instead of applying the configuration directly to the device, the configuration environment will first render the source file as a Jinja2 template. If you reference the variable `mgmt_addr` anywhere in the config using Jinja syntax (e.g. `{{ mgmt_addr }}`), it will be replaced with the IP address of the management interface. The subnet mask of this interface must be configured according to the CNI configuration in place. Normally this is a `/12`.

This will use NAPALM's `load-merge` function to load the resulting config onto the device, and commit it.

### Python&#x20;

**Usage:** `configurationType: python`

If you wish, you can use a custom Python script to make the necessary configuration changes. If you specify the above `configurationType` value, you'll need to make sure that for every endpoint that uses this option, a file named `<endpoint>.py` is present in the config directory for each stage.

### Ansible&#x20;

**Usage:** `configurationType: ansible`

If you wish, you can use an Ansible playbook to make the necessary configuration changes. If you specify the above `configurationType` value, you'll need to make sure that for every endpoint that uses this option, a file named `<endpoint>.yml` is present in the config directory for each stage for every endpoint that uses this option.


# Collections

With any curriculum, there are natural categorizations that arise from its content. For instance, in the automation space, you have fundamental skills, tools, and then the application of those tools. Further, you have categorization within each of those - maybe according to language or level of difficulty.

Sometimes a second axis of categorization is needed. Some lessons which have little to nothing in common technically, are tightly aligned around some other theme. For instance, a group of technically unrelated lessons might all be contributed by the same organization, and it would be nice to be able to see them all in one place, with some references to where users can learn more about that organization. Or maybe some lessons operate under some kind of constraint, such as only being useful on a certain vendor's equipment.

Enter collections. These are a new resource type in Syringe that allows you to define all of the metadata necessary for describing such a grouping. Just like other resource types, collections are defined in a simple YAML definition, and Antidote takes care of nicely rendering it in the web UI:

![](/files/-M-fnUEuVLtgYnURtvW9)

Once defined, other resources like lessons are able to reference the ID(s) of the collection they belong to, if applicable. See the `collection` field in [lesson definitions](/antidote/object-reference/lessons).

> An important note, especially if you're looking to create a collection for your company. This is totally acceptable - nay, encouraged - as long it's done the right way. Collections aren't a sales pitch. You can talk about your company and give a brief overview, but stay away from language like "we're the best" in favor of simply and succinctly describing what you do, why you have contributed to NRE Labs, and what users can expect to see from you here.

## Defining a Collection

Defining a collection is fairly straightforward. There's a bit of metadata, and a few description fields for you to populate. There are also some fields for pointing users to a relevant website or contact email, where appropriate. This is useful to give users a place to go after they find your content, and want to find out more about the person or organization behind it.

```
---
id: 7
title: Red Hat
image: https://raw.githubusercontent.com/nre-learning/nrelabs-curriculum/master/collections/redhat/redhat.jpg
website: https://www.redhat.com
contactEmail: "customerservice@redhat.com"

# Why should users view your collection?
briefDescription: |
    Red Hat is the world’s leading provider of enterprise open source solutions, using a community-powered approach to deliver high-performing Linux, cloud, container, and Kubernetes technologies.

# Why should users continue and view your lessons?
longDescription: |
    Red Hat is the world’s leading provider of enterprise open source solutions, using a community-powered approach to deliver high-performing Linux, cloud, container, and Kubernetes technologies.
    
    We help you standardize across environments, develop cloud-native applications, and integrate, automate, secure, and manage complex environments with award-winning support, training, and consulting services.

type: vendor
tier: prod

```

This collection definition is just an example. You should look at the [existing collection definitions](https://github.com/nre-learning/nrelabs-curriculum/tree/master/collections) for inspiration. Note also that not every field picture above is required. Some are optional. Using the`syrctl validate` command will be useful for identifying which fields you need to provide no matter what.

As with lesson definitions, follow the [NRE Labs curriculum contribution guide](/creating-contributing/contributing-content) in order to get your collection added to the NRE Labs curriculum.


# Development

If you're interested in digging into the actual code and contributing to the Antidote project, this set of documents will help.

## Familiarize Yourself

First, you should take a look at the [Architecture section](/antidote/antidote-architecture). It's likely you don't need to know how the whole thing works, as most contributions here are to a very specific component, but the context to which your contributing is important.

From a code perspective, the Antidote platform is separated into two main parts:

* [antidote-web](https://github.com/nre-learning/antidote-web) - this is the web front-end for the platform. If you lean more towards front-end development, such as HTML, CSS, and Javascript, this repository is a good place to start. Note that antidote-web forms the basis for the web front-end, but depends on a few other repositories for certain functionality:
  * [antidote-ui-components](https://github.com/nre-learning/antidote-ui-components) - houses web components for various portions of the application
  * [nre-styles](https://github.com/nre-learning/nre-styles) - stylesheets used by antidote-web and other project sites
  * [antidote-localizations](https://github.com/nre-learning/antidote-localizations) - localization strings for the copy within the platform application
* [antidote-core](https://github.com/nre-learning/antidote-core) - this is the core set of services that power the "back end" of Antidote. It is here that we integrate with Kubernetes and provide an API for `antidote-web` to consume. It is also here where we maintain any command-line tooling, such as the `antidote` command.

> The `README.md` file for both `antidote-web` and `antidote-core` contain instructions for building the software, and, if applicable, running tests. Please refer to those for more information.

The first thing you should do for any repository mentioned above that is of any interest to you, is to "[Watch](/other-resources/nre-labs-git-repositories#watching-for-activity-notifications)" it. Any activity that takes place in this repository will generate a notification for you. You can control how you're notified in your GitHub settings, but we recommend enabling email notifications. It's a great way to make sure you're at least aware of what's going on. If you aren't interested, you can always just delete the email.

## Pull Request Reviews

A good way to get familiar with the code is to "[Watch](/other-resources/nre-labs-git-repositories#watching-for-activity-notifications)" a repository, and when someone opens a PR, provide a constructive review. Many of the core platform developers open pull requests as soon as they start working on a feature or a bugfix, which often gives a large window of time where the pull request is open and questions can be asked, even on specific lines of code that changed.

Any constructive comments or questions here are not only appreciated, but it's often the best way to get insight into how the platform works, as you're inserting yourself right into where the work is actually getting done, without having to write a single line of code yourself. You don't have to be a platform developer or even consider yourself a developer at all to be curious and ask questions. We'd love to have you and help you get more familiar with how things work within the Antidote platform.

## Contribute

In almost every repostory, we have [labeled issues by complexity](/other-resources/nre-labs-git-repositories#using-issues-to-identify-low-hanging-fruit), so you can see at-a-glance which issues have been identified for the express purpose of getting started with the project. You can use this to get an estimate for how much work a given task is expected to take. For your first contribution, you may want to stick with "low complexity".

For simple enhancements or fixes, feel free to open a Pull Request at any time. If you're not quite ready for a review, open the pull request as a "draft", or otherwise indicate that it's a work-in-progress. Please fill out the template description so reviewers can make sense of your contribution more easily.

For big contributions, know that the more communication you provide ahead of time, the better - especially if you're new to the platform. It's often work opening an issue in advance, so we can have a discussion about the intended outcome of the contribution, and how we can make sure it melds well with the project as a whole.


# Antidote Release Process

The Antidote platform is comprised of multiple subprojects, which all need to be coordinated to release the Antidote platform as a cohesive unit. The lifecycle of a release of the Antidote platform is performed in four discrete steps, which are outlined in the following sections.

### 1 - Release Kickoff

A post will be created in the [Project Management](https://discuss.nrelabs.io/c/project-management/10) forum topic to notify everyone that the work on this release has begun, with the title "Release Kickoff...". This forum thread should serve as the center of all release planning discussions, and all are welcome to participate. If you have something you think should be included in or excluded from the release plan, speak up there.

In this first kickoff, we'll begin gathering ideas for things we want to get done in this release. These will be retrieved from various sources:

* First we start with the [Antidote v1.0 Roadmap](https://github.com/nre-learning/proposals/blob/master/antidote-v1.0/roadmap.md).

  Are there any milestones for the upcoming release we need to hit?
* Second, we comb through the issues for the repos and triage accordingly. Which are ready to

  be worked on, or are most imminent, according to complexity labels?

While the kickoff is meant to get a starter list together, it's likely that more ideas will come up at any time in the release cycle. This is normal, and expected. However, the first week of a release cycle should strive to ensure the really important things are well-documented and if possible, assigned.

A project plan for the release that represents the work discussed in the previous week will be posted to the [nre-learning org's projects list](https://github.com/orgs/nre-learning/projects) and presented to attendees. This is a kanban-board style project planning tool that allows all to easily see the state of work for a given release.

> Not all work fits neatly into a release plan, and that's okay. Contributions of any kind can reasonably take place at any time. The purpose of a release plan isn't to put limits on the work that can be done for a release, but rather to ensure that the important things that really **need** to get done are accounted for. If you want to work on something that's not explicitly asked for in the release plan, that's totally fine.

### 2 - Development Work

Once a release cycle is kicked off, the only thing left to do is....do the work! At this point, a relatively complete list of things to do for this release should be captured in a Github project, which will be linked to in the community forum kickoff post. Contributors can use this as a guide, or do other work they think is useful.

The [Platform Development Guide](/antidote/development) should be consulted repeatedly to ensure you're on the right track with respect to platform contributions. All of those guidelines apply here. It's important for contributions to follow this lifecycle, so that release managers can properly coordinate work across the project.

### 3 - Testing Phase

Once the tasks identified for this release have been finished, we will freeze `master` for all platform projects and begin a round of end-to-end testing.

The [test curriculum](https://github.com/nre-learning/antidote-test-curriculum) has been constructed for the purpose of testing all of the Antidote platform features. This curriculum should be updated to ensure not only compatibility with any platform changes, but also that all of the features of the platform are suitably used and tested.

A forum topic will be posted to [Platform Project Management](https://community.networkreliability.engineering/c/platform-project-management) with the title "Testing Antidote Release vX.X.X". This will contain a link to the testing procedure, and a summary of the CHANGELOG at that point in time, so that new features can be tested properly. For a minimum of seven days from the date of the post, contributors should submit feedback to this forum thread, or as Github issues.

### 4 - Release and Deployment

Once the testing phase has completed, the NRE Labs Ops team will execute a workflow that creates a release for all relevant platform projects. This will create docker images for everything with appropriate tags, as well as provide compiled binaries for Syringe.

After the release is finished, it's entirely up to those in charge of the [NRE Labs curriculum release process](/other-resources/curriculum-release-process) when or if this platform release is used in production for the NRE Labs site.

In the following week (or at most two), the cycle will repeat, and a new release kickoff will take place.


# Tools for Presenters

We maintain a page on the NRE Labs site called "[NRE Labs in the Wild](https://nrelabs.io/community/nre-labs-in-the-wild/)". We try to keep this updated with any presentations with public recordings that are either about or include NRE Labs.

![](/files/-M9eYpd1qy62bGWQBfyn)

If you'd like to give your own presentation on NRE Labs, both PDF and ODP formats [are available here](https://github.com/nre-learning/nre-resources/tree/master/presentations). Download these and modify as you need for your own NRE Labs presentations. This repository also houses other resources like hi-res logos that you might find useful.

The following video was recorded as an example for this presentation. You can use it as inspiration for your own presentation to whatever degree you wish:

{% embed url="<https://www.youtube.com/watch?v=i4zvlLyHYFg>" %}


# Help! I'm Not A Developer!

If you're not a developer, but you want to find other ways to contribute, have no fear! We've got you covered.

For the NRE Labs project as a whole, putting everything in Git is central to the spirit of the project. “Curriculum as Code” is part of what makes NRE Labs tick - instead of storing the curriculum behind closed doors, it's published for all to not only see, but also contribute to.

We've taken this idea and extended it to all aspects of the project, not just the curriculum, or the technical bits of the Antidote platform. **Everything** we do is represented in a GitHub repository somewhere under the `nre-learning` org. For example:

* The [NRE Labs Website and Blog](https://nrelabs.io) is powered by a static site generator called Hugo, which takes simple [Markdown](https://daringfireball.net/projects/markdown/syntax) files located in our [nre-blog repo](https://github.com/nre-learning/nre-blog) and renders them automatically into static HTML pages. This makes the blog much easier to manage, while also allowing folks to contribute without having to be web developers.
* All of the documentation you're reading here is sourced from [a GitHub repository as well](https://github.com/nre-learning/nrelabs-docs), and rendered into this nice view by a service called GitBook. It is also written in Markdown. If you want to contribute to these docs, you can either open a pull request to this repository, or get in touch with us, and we may be able to work something else out.
* Our governance and technical planning docs are written in Markdown and added as Pull Requests to the [proposals repository](https://github.com/nre-learning/proposals). Not only does this allow anyone to easily contribute to these, but this public model means all can participate in their formation. Pull Requests here are open to all to review at any time.

The end result of this is a model that is public and open to all by default. No matter what you're talking about, whether core platform software, or blogs on the latest developments in the world of DevOps and NRE, it's all done on GitHub.

That said - it might be easy to assume that you have to have a developer skill-set in order to work with GitHub. Not so! You just need some tools and a little knowledge about plaintext formatting languages, which are outlined below.

### What You Need

First, you need to install two things on your computer:

* A decent text editor. I recommend [VSCode](https://code.visualstudio.com/download) - it's free, simple enough while still being robust, and includes support for the things we will want to use it for.
* The [Github client](https://desktop.github.com/). This is also cross-platform, and gives you the benefits of Github without having to do anything on the command-line.

Next, as all of the above projects use Markdown as a simple plaintext formatting language, you really should [spend some time understanding it](https://guides.github.com/features/mastering-markdown/).

Finally, the guide on [NRE Labs Git repositories](/other-resources/nre-labs-git-repositories) will cover how we use Git and GitHub, and will contain links to other learning resources if you're new to Git.


# (Legacy) Local Preview

> Self-Medicate is a collection of scripts that allow you to run the software stack that powers the NRE Labs stack on your laptop. Historically, this was the only possibile way to preview any curriculum contributions.
>
> However, with the introduction of the [NRE Labs Preview Service](/creating-contributing/preview-your-changes), this is no longer formally supported as a primary function for this tool. We will continue to maintain and provide self-medicate as a generally useful reference deployment, and you are welcome to continue to use self-medicate if you wish, but you will likely not receive a lot of support, so you are on your own. For the vast majority of curriculum contributions, please use the [Preview Service](/creating-contributing/preview-your-changes) as part of the normal contribution process.

If you've made changes to the NRE Labs curriculum and are looking to contribute them, you'll probably want to find a way to run them locally yourself before opening a pull request. The [selfmedicate](https://github.com/nre-learning/antidote-selfmedicate) tool is a way to get a local version of NRE Labs running on your own machine. This allows you to see how your lesson actually performs, before you open a Pull Request.

### Preparing the Environment

In the last section, you cloned your fork of the NRE Labs curriculum to your own machine. If this is still the working directory in your shell, navigate to the parent directory like so:

```
cd ../
```

The important thing at this point is that your shell should currently be located at the parent directory of the NRE Labs curriculum. Next, clone and enter the selfmedicate repository:

```
git clone https://github.com/nre-learning/antidote-selfmedicate
cd antidote-selfmedicate/
```

{% hint style="info" %}
**Please remember** that changes are being made to selfmedicate all the time. If you encounter issues, the very first thing you should try before you open an issue is to make sure you have the latest copy of this repository by doing a `git pull` on the master branch.
{% endhint %}

For maximum compatibility across operating systems, we deploy selfmedicate in a Vagrant environment, so that it can run in a consistent, properly configured virtual machine with all of the dependencies needed. As a result, you'll need a hypervisor. Selfmedicate officially supports [Virtualbox](https://www.virtualbox.org/wiki/Downloads) as it is widely supported across operating systems as well as the automation we'll use to get everything spun up on top of it.

Next, you'll need [Vagrant](https://www.vagrantup.com/docs/installation/). Vagrant allows us to define a virtual environment in the selfmedicate repository that automatically contains all of the software dependencies needed to make Antidote work.

{% hint style="info" %}
The Self-Medicate `Vagrantfile` starts a VM with 4GB of RAM and 2 vCPUs by default. While this is not a strict requirement, it's a reasonable default. You're free to edit this if you know what you're doing.
{% endhint %}

There are some required Vagrant plugins as well (you only need to run these once).

```
vagrant plugin install vagrant-vbguest
vagrant plugin install vagrant-hostsupdater
```

To start the Vagrant environment for selfmedicate, run:

```
vagrant up
```

Once this is done, the environment should be ready to access at the URL shown by the script.&#x20;

## The Selfmedicate Script

In the last section, we started a Vagrant machine with all of the prerequisites installed for running the Antidote platform. In this section, we'll dive a little bit into the selfmedicate tool specifically, so you are able to use it to iterate on lesson content and quickly preview the changes you've made.

These instructions assume you've followed the previous section, and now have a running Vagrant machine. If not, please do that now before continuing.

Open an SSH connection to the Vagrant machine:

```
vagrant ssh
```

The rest of the selfmedicate instructions will take place within this environment.

The `selfmedicate.sh` script is our one-stop shop for managing the development environment. This script has several subcommands:

```
./selfmedicate.sh -h
Usage: selfmedicate.sh <subcommand> [options]
Subcommands:
    start    Start local instance of Antidote
    reload   Reload Antidote components
    stop     Stop local instance of Antidote
    resume   Resume stopped Antidote instance

options:
-h, --help                show brief help
```

In **rare** circumstances, you might need to run the `start`, `stop`, or `resume` commands. However, these commands have been wired up to the Vagrant environment in such a way that this shouldn't be necessary.

The main command you'll probably want to run within the Vagrant environment is the `reload` subcommand. This allows Antidote to re-import curriculum content:

```
./selfmedicate reload
```

### Troubleshooting Self-Medicate

The vast majority of all setup activities are performed by the `selfmedicate` script. The idea is that this script shoulders the burden of downloading all the appropriate software and building is so that you can quickly get to focusing on lesson content. However, issues can still happen. This section is meant to direct you towards the right next steps should something go wrong and you need to intervene directly.

> The `selfmedicate` script is designed to make it easy to configure a local minikube environment with everything related to Antidote installed on top. However, you'll always be well-served by becoming familiar with `minikube` or even Kubernetes itself so that you are more able to troubleshoot the environment when things go wrong.

Before asking for help, please first answer these questions:

* Have you read this page in its entirety?
* Have you run a `git pull` on the latest `master` branch of the Self-Medicate and Curriculum repos?
* Have you looked at the [Common Selfmedicate Issues](/misc/previewing-locally#common-self-medicate-issues)?

If you answered "yes" to all of these questions, please [open an issue on the selfmedicate repository](https://github.com/nre-learning/antidote-selfmedicate/issues/new) and ensure you follow the instructions provided there.

The self-medicate tool comes with a `debug` subcommand which runs a series of commands for extracting information that will be needed for any troubleshooting activity. To run this subcommand and place all output in a file called `selfmedicatedebug.txt`, run the below:

```
./selfmedicate.sh debug > selfmedicatedebug.txt
```

When opening an issue on the Self-Medicate repository linked above, this information will be required to move forward with troubleshooting any issues, so please [create a new Github Gist](https://gist.github.com/) and paste the link into the relevant spot in your issue. **Please do not paste the debug contents into a Github Issue directly**.

### Common Self-Medicate Issues

> All of the steps below assume a working Vagrant environment, and a working persistent connection to this virtual machine via `vagrant ssh`.

#### Cannot Connect to the Web Front-End

It's likely that the pods for running the Antidote platform aren't running yet. Try getting the current pods:

```
~$ kubectl get pods
NAME                                        READY   STATUS    RESTARTS   AGE
antidote-web-99c6b9d8d-pj55w                2/2     Running   0          12d
nginx-ingress-controller-694479667b-v64sm   1/1     Running   0          12d
syringe-fbc65bdf5-zf4l4                     1/1     Running   4          12d
```

You should see something similar to the above. The exact pod names will be different, but you should see the same numbers under the `READY` column, and all entries under the `STATUS` column should read `Running` as above.

In some cases the `STATUS` column may read `ContainerCreating`. In this case, it's likely that the images for each pod is still being downloaded to your machine. You can verify this by "describing" the pod that's not `Ready` yet:

```
kubectl describe pods -n=kube-system kube-multus-ds-amd64-ddxqc
Name:               kube-multus-ds-amd64-ddxqc
....truncated....
Events:
Type    Reason     Age   From               Message
----    ------     ----  ----               -------
Normal  Scheduled  19s   default-scheduler  Successfully assigned kube-system/kube-multus-ds-amd64-ddxqc to minikube
Normal  Pulling    17s   kubelet, minikube  pulling image "nfvpe/multus:latest"
```

In this example, we're still waiting for the image to download - the most recent event indicates that the image is being pulled. The `selfmedicate.sh` script has some built-in logic to wait for these downloads to finish before moving to the next step, but in case that doesn't work, this can help you understand what's going on behind the scenes.

If you're seeing something else, it's likely that something is truly broken, and you likely won't be able to get the environment working without some kind of intervention. Please [open an issue on the antidote-selfmedicate repository](https://github.com/nre-learning/antidote-selfmedicate/issues/new) with a full description of what you're seeing.

#### Lesson Times Out While Loading

Let's say you've managed to get into the web front-end, and you're able to navigate to a lesson, but the lesson just hangs forever at the loading screen. Eventually you'll see some kind of error message that indicates the lesson timed out while trying to start.

This can have a number of causes, but one of the most common is that the images used in a lesson failed to download within the configured timeout window. This isn't totally uncommon, since the images tend to be fairly large, and on some internet connections, this can take some time.

There are a few things you can try. For instance, `kubectl describe pods <pod name>`, as used in the previous section, can tell you if a given pod is still downloading an image.

We can also use docker commands to check the list of docker images that have been successfully pulled:

```
docker image list
```


