text:
# molecule-ansible-docker-vagrant
[![Build Status](https://travis-ci.org/jonashackt/molecule-ansible-docker-vagrant.svg?branch=master)](https://travis-ci.org/jonashackt/molecule-ansible-docker-vagrant)
[![CircleCI](https://circleci.com/gh/jonashackt/molecule-ansible-docker-vagrant.svg?style=svg)](https://circleci.com/gh/jonashackt/molecule-ansible-docker-vagrant)
[![versionansible](https://img.shields.io/github/pipenv/locked/dependency-version/jonashackt/molecule-ansible-docker-vagrant/ansible?color=brightgreen)](https://docs.ansible.com/ansible/latest/index.html)
[![versionmolecule](https://img.shields.io/github/pipenv/locked/dependency-version/jonashackt/molecule-ansible-docker-vagrant/molecule?color=brightgreen)](https://molecule.readthedocs.io/en/latest/)
[![versiontestinfra](https://img.shields.io/github/pipenv/locked/dependency-version/jonashackt/molecule-ansible-docker-vagrant/testinfra?color=brightgreen)](https://testinfra.readthedocs.io/en/latest/)
[![versionawscli](https://img.shields.io/github/pipenv/locked/dependency-version/jonashackt/molecule-ansible-docker-vagrant/awscli?color=brightgreen)](https://aws.amazon.com/cli/)

Example project showing how to test Ansible roles with Molecule using Testinfra and a multiscenario approach with Vagrant, Docker & AWS EC2 as the infrastructure under test.

[![asciicast](https://asciinema.org/a/214914.svg)](https://asciinema.org/a/214914)

There are already two blog posts complementing this repository:
* [Test-driven infrastructure development with Ansible & Molecule](https://blog.codecentric.de/en/2018/12/test-driven-infrastructure-ansible-molecule/)
* [Continuous Infrastructure with Ansible, Molecule & TravisCI](https://blog.codecentric.de/en/2018/12/test-driven-infrastructure-ansible-molecule/)
* [Continuous cloud infrastructure with Ansible, Molecule & TravisCI on AWS](https://blog.codecentric.de/en/2019/01/ansible-molecule-travisci-aws/)

## Table of Contents
* [TDD for Infrastructure code with Molecule!](#tdd-for-infrastructure-code-with-molecule)
* [Prerequisites](#prerequisites)
* [Project structure](#project-structure)
* [Molecule configuration](#molecule-configuration)
* [Execute Molecule](#execute-molecule)
* [Multi-Scenario Molecule setup](#multi-scenario-molecule-setup)
* [Ubuntu based Docker-in-Docker builds](#ubuntu-based-docker-in-docker-builds)
  * [Docker-in-Docker with ubuntu:bionic](#docker-in-docker-with-ubuntubionic)
  * [Testing the Docker-in-Docker installation](#testing-the-docker-in-docker-installation)
* [Molecule with AWS EC2 as the infrastructure provider](#molecule-with-aws-ec2-as-the-infrastructure-provider)
  * [Configure Molecule to use EC2](#configure-molecule-to-use-ec2)
  * [Having a look into the create.yml](#having-a-look-into-the-createyml)
  * [Install & configure AWS CLI](#install--configure-aws-cli)
  * [Configure Region & VPC subnet id](#configure-region--vpc-subnet-id)
  * [Choosing an Ubuntu 18.04 AMI](#choosing-an-ubuntu-1804-ami)
  * [Creating a EC2 instance with Molecule](#creating-a-ec2-instance-with-molecule)
  * [Run a first Test on EC2 with Molecule](#run-a-first-test-on-ec2-with-molecule)
  * [Cleaning up](#cleaning-up)
  * [Final check: molecule test](#final-check-molecule-test)
* [Use TravisCI to execute Molecule with EC2 infrastructure](#use-travisci-to-execute-molecule-with-ec2-infrastructure)
  * [Problems with boto on Travis](#problems-with-boto-on-travis)
* [Use CircleCI to execute Molecule with EC2 infrastructure](#use-circleci-to-execute-molecule-with-ec2-infrastructure)
  * [Schedule regular CircleCI builds with workflow triggers & cron](#schedule-regular-circleci-builds-with-workflow-triggers--cron)

## TDD for Infrastructure code with Molecule!

[Molecule](https://molecule.readthedocs.io/en/latest/#) seems to be a pretty neat TDD framework for testing Infrastructur-as-Code using Ansible. As previously announced on September 26 2018 [Ansible treats Molecule as a first class citizen](https://groups.google.com/forum/#!topic/ansible-project/ehrb6AEptzA) from now on - backed by Redhat also.

Molecule executes the following steps:

![tdd-for-iac](https://yuml.me/diagram/scruffy/class/[Given:%20Spin%20up%20Infrastructure%20with%20Docker%20or%20Vagrant%20or%20Other]->[When:%20Execute%20Ansible%20Playbooks/Roles],[When:%20Execute%20Ansible%20Playbooks/Roles]->[Then:%20Assert%20with%20Testinfra],[Then:%20Assert%20with%20Testinfra]->[Cleanup%20Infrastructure])

In the `Then` phase Molecule executes different [Verifiers](https://molecule.readthedocs.io/en/latest/configuration.html#verifier), one of them is [Testinfra](https://testinfra.readthedocs.io/en/latest/), where you can write Unittest with a Python DSL.

> Beware of old links to v1 of Molecule! As I followed blog posts that were just from a year or two ago, I walked into the trap of using Molecule v1. This is especially problematic if you try to install Molecule via `homebrew` where you currently also get the v1 version. So always double check, if there´s no `/v1/` in the docs´ url:

![current-docs-url](screenshots/current-docs-url.png)

Just start here: [Molecule docs](https://molecule.readthedocs.io/en/latest/configuration.html)

## Prerequisites

* `brew cask install virtualbox`
* `brew cask install vagrant`

> Please don´t install Ansible and Molecule with homebrew on Mac, but always with pip3 since you only get old versions and need to manually install testinfra, ansible, flake8 and other packages

And as we learned with [pulumi-python-aws-ansible](https://github.com/jonashackt/pulumi-python-aws-ansible) and escpecially in [Replace direct usage of virtualenv and pip with pipenv](https://github.com/jonashackt/pulumi-python-aws-ansible#replace-direct-usage-of-virtualenv-and-pip-with-pipenv), we should use a great Python dependency management tool like [pipenv](https://github.com/pypa/pipenv) instead of no or non-pinned (`requirements.txt`) dependencies.

Therefore let's install `pipenv`:

```
pip3 install pipenv
```

Then create a virtual environment for the current project (pinned to Python 3.7+):

```
pipenv shell --python 3.7
```

And finally install needed pip packages with:

```
pipenv install ansible molecule
```

> For using Vagrant with Molecule we also need `python-vagrant` module installed
* `pipenv install python-vagrant`

## Project structure

To initialize a new Molecule powered Ansible role named `docker` with the Vagrant driver and the Testinfra verifier you have to execute the following command:

`molecule init role --driver-name vagrant --role-name docker --verifier-name testinfra`

This will give:

`--> Initializing role docker...
 Successfully initialized new role in /Users/jonashecht/dev/molecule-ansible-vagrant/docker.`

Molecule introduces a well known project structure (at least for a Java developer like me):

![projectstructure](screenshots/projectstructure.png)

As you may notice the role standard directory `tasks` is now accompanied by a `tests` directory inside the `molecule` folder where the Testinfra testcases reside.

This repository uses [a Ansible role](docker/tasks/main.yml) that installs Docker into an Ubuntu Box:

```yaml
- name: add Docker apt key
  apt_key:
    url: https://download.docker.com/linux/ubuntu/gpg
    id: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88
    state: present
  ignore_errors: true

- name: add docker apt repo
  apt_repository:
    repo: "deb [arch=amd64] https://download.docker.com/linux/ubuntu {{ ansible_lsb.codename }} stable"
    update_cache: yes
  become: true

- name: install Docker apt package
  apt:
    pkg: docker-ce
    state: latest
    update_cache: yes
  become: true

- name: add vagrant user to docker group.
  user:
    name: vagrant
    groups: docker
    append: yes
  become: true
```

With Testinfra we can assert on things we want to achieve with our Ansible role: Install the `docker` package and add the user `vagrant` to the group `docker`. Testinfra uses [pytest](https://docs.pytest.org/en/latest/example/index.html) to execute the tests. Our testcases could be found in [test_docker.py](docker/molecule/tests/test_docker.py):

```python
import testinfra.utils.ansible_runner

testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
    '.molecule/ansible_inventory').get_hosts('all')

def test_is_docker_installed(host):
    package_docker = host.package('docker-ce')

    assert package_docker.is_installed

def test_vagrant_user_is_part_of_group_docker(host):
    user_vagrant = host.user('vagrant')

    assert 'docker' in user_vagrant.groups

```

__More Testinfra code examples:__

As you´re not an in-depth Python hacker (like me), you´ll be maybe also interested in example code. Have a look at:

https://github.com/philpep/testinfra#quick-start

https://github.com/openmicroscopy/ansible-role-prometheus/blob/0.2.0/tests/test_default.py

https://github.com/mongrelion/ansible-role-docker/blob/master/molecule/default/tests/test_default.py

https://blog.octo.com/test-your-infrastructure-topology-on-aws/

## Molecule configuration

The [molecule.yml](docker/molecule/vagrant-ubuntu/molecule.yml) configures Molecule:

```
scenario:
  name: vagrant-ubuntu

driver:
  name: vagrant
  provider:
    name: virtualbox
platforms:
  - name: vagrant-ubuntu
    box: ubuntu/bionic64
    memory: 512
    cpus: 1
    provider_raw_config_args:
    - "customize [ 'modifyvm', :id, '--uartmode1', 'disconnected' ]"

provisioner:
  name: ansible
  lint:
    name: ansible-lint
    enabled: false
  playbooks:
    converge: playbook.yml

lint:
  name: yamllint
  enabled: false
verifier:
  name: testinfra
  directory: ../tests/
  env:
    # get rid of the DeprecationWarning messages of third-party libs,
    # see https://docs.pytest.org/en/latest/warnings.html#deprecationwarning-and-pendingdeprecationwarning
    PYTHONWARNINGS: "ignore:.*U.*mode is deprecated:DeprecationWarning"
  lint:
    name: flake8
  options:
    # show which tests where executed in test output
    v: 1

```

We have some specialties here. First thing is the follow addition to the `platforms` key:

```
    provider_raw_config_args:
    - "customize [ 'modifyvm', :id, '--uartmode1', 'disconnected' ]"
```

Without this configuration Molecule isn´t able to spin up "standard" Vagrant Ubuntu boxes like `ubuntu/bionic64` and `ubuntu/xenial64`. If you do a `tail -f /var/folders/5p/l1cc1kqd69n_qxrftgln7xdm0000gn/T/molecule/docker/default/vagrant-ubuntu-docker.err`, you see errors like this:

```
There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

Command: ["startvm", "64c5ca1e-0f7c-4dea-bc07-8144a56a0029", "--type", "headless"]

Stderr: VBoxManage: error: RawFile#0 failed to create the raw output file /usr/local/lib/python2.7/site-packages/molecule/provisioner/ansible/playbooks/vagrant/ubuntu-bionic-18.04-cloudimg-console.log (VERR_ACCESS_DENIED)
```

This is a workaround until https://github.com/ansible/molecule/issues/1556 gets fixed. This shouldn´t be necessary to be configured.

The second thing is `PYTHONWARNINGS: "ignore:.*U.*mode is deprecated:DeprecationWarning"` environment variable definition. If you don´t configure this you´ll end up with bloated test logs like this:

![verify-with-deprecation-warnings](screenshots/verify-with-deprecation-warnings.png)

If you use the `PYTHONWARNINGS` environment variable you gather beautiful and __green__ test executions:

![verify-with-deprecation-warnings-ignored](screenshots/verify-with-deprecation-warnings-ignored.png)

In case everything runs green you may notice that there´s is no hint which tests were executed. But I think that´s rather a pity since we want to see our whole test suite executed. That was the whole point why we even started to use a testing framework like Molecule!

But luckily there´s a way to get those tests shown inside our output. As Molecule uses [Testinfra](https://testinfra.readthedocs.io/en/latest/invocation.html) which itself leverages [pytest](https://docs.pytest.org/en/latest/) to execute our test cases and Testinfra is able to invoke pytest with additional properties. And pytest has [many options we can experiment with](https://docs.pytest.org/en/latest/reference.html#configuration-options). To configure a more verbose output for our tests in Molecule, add the following to the `verifier` section of your `molecule.yml`:

```
verifier:
  name: testinfra
...
  options:
    # show which tests where executed in test output
    v: 1
...
```

If we now execute a `molecule verify` we should see a much nicer overview of which test cases where executed:

![verify-with-pytest-verbose](screenshots/verify-with-pytest-verbose.png)

## Execute Molecule

Now we´re able to run our first test. Go into `docker` directory and run:

`molecule test`

As Molecule has different phases, you can also explicitely run `molecule converge` or `molecule verify` - the commands will recognice required upstream phases like `create` and skips them if they where already run before (e.g. if the Vagrant Box is running already).

# Multi-Scenario Molecule setup

With Molecule we could not only test our Ansible roles against one infrastructure setup - but we can use multiple of them! We only need to leverage the power of [Molecule scenarios](https://molecule.readthedocs.io/en/latest/configuration.html#scenario).

To get an idea on how this works I sligthly restructured the repository. We started out with the Vagrant driver / scenario. Now after also implementing a Docker driver in this repository on it´s own: https://github.com/jonashackt/molecule-ansible-docker I integrated it into this repository.

And because Docker is the default Molecule driver for testing Ansible roles I changed the name of the Vagrant scenario to `vagrant-ubuntu`. Don´t forget to install `docker`:

```
pip3 install docker
```

Using `molecule test` as we´re used to will now execute the Docker (e.g. `default`) scenario. This change results in the following project structure:

![multi-scenario-projectstructure](screenshots/multi-scenario-projectstructure.png)

To execute the `vagrant-ubuntu` Scenario you have to explicitely call it´s name:

```
molecule test --scenario-name vagrant-ubuntu
```

[![asciicast](https://asciinema.org/a/213352.svg)](https://asciinema.org/a/213352)

All the files which belong only to a certain scenario are placed inside the scenarios directory. For example in the Docker scenario this is `Dockerfile.js` and in Vagrant one this is `prepare.yml`. Also the `molecule.yml` files have to access the `playbook.yml` and the testfiles differently since they are now separate from the scenario directory to be [able to reuse them over all scenarios](https://molecule.readthedocs.io/en/latest/examples.html#sharing-across-scenarios):

```
...
provisioner:
  name: ansible
...
  playbooks:
    converge: ../playbook.yml
...
verifier:
  name: testinfra
  directory: ../tests/
...
```

Now we can also integrate & use TravisCI in this repository since the [default scenario Docker is supported on Travis](https://molecule.readthedocs.io/en/latest/testing.html#travis-ci)! :)

![travisci-molecule-executing-testinfra-tests](screenshots/travisci-molecule-executing-testinfra-tests.png)

## Ubuntu based Docker-in-Docker builds

As we don´t have a Vagrant environment in a Cloud CI system available for us right now (see https://github.com/jonashackt/vagrant-ansible-on-appveyor), we should be enable us somehow to test our Ansible role only with the Docker driver.

The standard Docker-in-Docker image provided by Docker Inc is based on Alpine Linux (see https://stackoverflow.com/a/53459483/4964553 & the `dind` tags in https://hub.docker.com/_/docker/). But our role is designed for Ubuntu and thus uses the `apt` package manager instead of `apk`. So we can´t use the standard Docker-in-Docker image.

But there should be a way to do Docker-in-Docker installation with a Ubuntu base image like `ubuntu:bionic`! And there is :)

Let´s assume the [standard Ubuntu Docker installation](https://docs.docker.com/install/linux/docker-ce/ubuntu/#install-docker-ce-1) our starting point. Everything described there is done inside our Ansible role under test __docker__ inside the playbook [docker/tasks/main.yml](docker/tasks/main.yml).

All the extra steps needed to install Docker inside a Ubuntu Docker container will be handled inside the `prepare` step. Therefore we´ll use [Molecules´ prepare.yml playbook](https://molecule.readthedocs.io/en/latest/configuration.html#id12):

> The prepare playbook executes actions which bring the system to a given state prior to converge. It is executed after create, and only once for the duration of the instances life. This can be used to bring instances into a particular state, prior to testing.

### Configure a custom prepare step

The Docker-in-Docker build is only used ([and should only be used](https://jpetazzo.github.io/2015/09/03/do-not-use-docker-in-docker-for-ci/)) inside our CI pipeline. The `prepare` step inside our Molecule test suites´s `default` Docker scenario will be only executed for testing purposes.

So let´s configure our `default` Docker scenario to use a `prepare.yml` which could be done inside the `molecule.yml`:

```yaml
...
  playbooks:
    prepare: prepare-docker-in-docker.yml
    converge: ../playbook.yml
...
```

### Docker-in-Docker with ubuntu:bionic

Now we should have a look into the [prepare-docker-in-docker.yml](docker/molecule/default/prepare-docker-in-docker.yml):

```yaml
# Prepare things only necessary in Ubuntu Docker-in-Docker scenario
- name: Prepare
  hosts: all
  tasks:
  - name: install gpg package
    apt:
      pkg: gpg
      state: latest
      update_cache: true
    become: true

    # We need to anticipate the installation of Docker before the role execution...
  - name: use our role to install Docker
    include_tasks: ../../tasks/main.yml

  - name: create /etc/docker
    file:
      state: directory
      path: /etc/docker

  - name: set storage-driver to vfs via daemon.json
    copy:
      content: |
        {
          "storage-driver": "vfs"
        }
      dest: /etc/docker/daemon.json

  # ...since we need to start Docker in a complete different way
  - name: start Docker daemon inside container see https://stackoverflow.com/a/43088716/4964553
    shell: "/usr/bin/dockerd -H unix:///var/run/docker.sock > dockerd.log 2>&1 &"
```

As the `ubuntu:bionic` Docker image is sligthly stripped down compared to a "real" Ubuntu virtual machine, we need to install the `gpg` package at first.

After that the Docker installation has to be executed just in the same way as on a virtual machine using Vagrant. So we simply re-use the existing Docker role here - so we´re not forced to copy code!

Then really being able to run Docker-in-Docker we need to do three things:

1. Run Docker with `--priviledged` (which should really only be used inside our CI environment, because it grant´s full access to the host environment (see https://hub.docker.com/_/docker/))
2. Use the [storage-driver `vfs`](https://docs.docker.com/storage/storagedriver/vfs-driver/#configure-docker-with-the-vfs-storage-driver), which is slow & inefficient but is the only one guaranteed to work regardless of underlying filesystems
3. Start the Docker daemon with `/usr/bin/dockerd -H unix:///var/run/docker.sock > dockerd.log 2>&1 &`, or otherwise you´ll run into errors like `Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?` (see https://stackoverflow.com/a/43088716/4964553)

You may noticed that __2.__ & __3.__ are handled by our `prepare-docker-in-docker.yml` already. To enable the __1.__ `--priviledged` mode we need to configure Molecules´ Docker driver inside the `molecule.yml`:

```yaml
...
driver:
  name: docker
platforms:
  - name: docker-ubuntu
    image: ubuntu:bionic
    privileged: true
...
```

### Testing the Docker-in-Docker installation

The last step - or the first, if you leverage the power of Test-Driven-Development (TDD) - was to create a suitable testcase. This test should verify whether the Docker-in-Docker installation was successful.

Therefore we can use the [hello-world](https://hub.docker.com/_/hello-world/) Docker image. Let´s execute a `docker run hello-world` straight inside our test case `test_run_hello_world_container_successfully` in our test suite [test_docker.py](docker/molecule/tests/test_docker.py):

```
def test_run_hello_world_container_successfully(host):
    hello_world_ran = host.run("docker run hello-world")

    assert 'Hello from Docker!' in hello_world_ran.stdout
```

This will verify that

1. the Docker client is able to contact the Docker daemon
2. the Docker daemon successfully pulled the image `hello-world` from the Docker Hub
3. the Docker daemon created a new container from that image and runs the executable inside
4. the Docker daemon streamed the executables output containing `Hello from Docker!` to the Docker client, which send it to the terminal

# Molecule with AWS EC2 as the infrastructure provider

Now that we successfully used Vagrant & Docker as infrastructure providers for Molecule, we should now start to use a cloud provider like AWS.

We should be able to use [Molecule's EC2 driver](https://molecule.readthedocs.io/en/latest/configuration.html#ec2), which itself uses [Ansible's ec2 module](http://docs.ansible.com/ansible/latest/ec2_module.html) to interact with AWS.

First we need to install the [Boto Python packages](https://pypi.org/project/boto/). They will provide interfaces to Amazon Web Services:

```
pip3 install boto boto3
```

### Configure Molecule to use EC2

Then we just init a new Molecule scenario inside our existing multi scenario project called `aws-ec2-ubuntu`. Therefore we can leverage Molecule's `molecule init scenario` command:

```
cd molecule-ansible-docker-vagrant/docker

molecule init scenario --driver-name ec2 --role-name docker --scenario-name aws-ec2-ubuntu
```

That should create a new directory `aws-ec2-ubuntu` inside the `docker/molecule` folder.  We'll integrate the results into our multi scenario project in a second.

Now let's dig into the generated `molecule.yml`:

```yaml
scenario:
  name: aws-ec2-ubuntu

driver:
  name: ec2
platforms:
  - name: instance
    image: ami-a5b196c0
    instance_type: t2.micro
    vpc_subnet_id: subnet-6456fd1f

provisioner:
  name: ansible
  lint:
    name: ansible-lint
    enabled: false
  playbooks:
    converge: ../playbook.yml

lint:
  name: yamllint
  enabled: false

verifier:
  name: testinfra
  directory: ../tests/
  env:
    # get rid of the DeprecationWarning messages of third-party libs,
    # see https://docs.pytest.org/en/latest/warnings.html#deprecationwarning-and-pendingdeprecationwarning
    PYTHONWARNINGS: "ignore:.*U.*mode is deprecated:DeprecationWarning"
  lint:
    name: flake8
  options:
    # show which tests where executed in test output
    v: 1
```

As we already tuned the `molecule.yml` files for our other scenarios like `docker` and `vagrant-ubuntu`, we know what to change here. `provisioner.playbook.converge` needs to be configured, so the one `playbook.yml` could be found.

Also the `verifier` section has to be enhanced to gain all the described advantages like supressed deprecation warnings and the better test result overview.

As you may noticed, the driver now uses `ec2` and the platform is already pre-configured with a concrete Amazon Machine Image (AMI) and `instance_type` etc. I just tuned the instance name to `aws-ec2-ubuntu`, like we did in our Docker and Vagrant scenarios.

### Having a look into the create.yml

The generated `create.yml` and `destroy.yml` Ansible playbooks look rather stunning - especially to AWS newbees. Let's have a look into the `create.yml`:

```yaml
- name: Create
  hosts: localhost
  connection: local
  gather_facts: false
  no_log: "{{ not (lookup('env', 'MOLECULE_DEBUG') | bool or molecule_yml.provisioner.log|default(false) | bool) }}"
  vars:
    ssh_user: ubuntu
    ssh_port: 22

    security_group_name: molecule
    security_group_description: Security group for testing Molecule
    security_group_rules:
      - proto: tcp
        from_port: "{{ ssh_port }}"
        to_port: "{{ ssh_port }}"
        cidr_ip: '<IP_ADDRESS>/0'
      - proto: icmp
        from_port: 8
        to_port: -1
        cidr_ip: '<IP_ADDRESS>/0'
    security_group_rules_egress:
      - proto: -1
        from_port: 0
        to_port: 0
        cidr_ip: '<IP_ADDRESS>/0'

    keypair_name: molecule_key
    keypair_path: "{{ lookup('env', 'MOLECULE_EPHEMERAL_DIRECTORY') }}/ssh_key"
  tasks:
    - name: Create security group
      ec2_group:
        name: "{{ security_group_name }}"
        description: "{{ security_group_name }}"
        rules: "{{ security_group_rules }}"
        rules_egress: "{{ security_group_rules_egress }}"

    - name: Test for presence of local keypair
      stat:
        path: "{{ keypair_path }}"
      register: keypair_local

    - name: Delete remote keypair
      ec2_key:
        name: "{{ keypair_name }}"
        state: absent
      when: not keypair_local.stat.exists

    - name: Create keypair
      ec2_key:
        name: "{{ keypair_name }}"
      register: keypair

    - name: Persist the keypair
      copy:
        dest: "{{ keypair_path }}"
        content: "{{ keypair.key.private_key }}"
        mode: 0600
      when: keypair.changed

    - name: Create molecule instance(s)
      ec2:
        key_name: "{{ keypair_name }}"
        image: "{{ item.image }}"
        instance_type: "{{ item.instance_type }}"
        vpc_subnet_id: "{{ item.vpc_subnet_id }}"
        group: "{{ security_group_name }}"
        instance_tags:
          instance: "{{ item.name }}"
        wait: true
        assign_public_ip: true
        exact_count: 1
        count_tag:
          instance: "{{ item.name }}"
      register: server
      with_items: "{{ molecule_yml.platforms }}"
      async: 7200
      poll: 0

    - name: Wait for instance(s) creation to complete
      async_status:
        jid: "{{ item.ansible_job_id }}"
      register: ec2_jobs
      until: ec2_jobs.finished
      retries: 300
      with_items: "{{ server.results }}"

    # Mandatory configuration for Molecule to function.

    - name: Populate instance config dict
      set_fact:
        instance_conf_dict: {
          'instance': "{{ item.instances[0].tags.instance }}",
          'address': "{{ item.instances[0].public_ip }}",
          'user': "{{ ssh_user }}",
          'port': "{{ ssh_port }}",
          'identity_file': "{{ keypair_path }}",
          'instance_ids': "{{ item.instance_ids }}", }
      with_items: "{{ ec2_jobs.results }}"
      register: instance_config_dict
      when: server.changed | bool

    - name: Convert instance config dict to a list
      set_fact:
        instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
      when: server.changed | bool

    - name: Dump instance config
      copy:
        content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
        dest: "{{ molecule_instance_config }}"
      when: server.changed | bool

    - name: Wait for SSH
      wait_for:
        port: "{{ ssh_port }}"
        host: "{{ item.address }}"
        search_regex: SSH
        delay: 10
        timeout: 320
      with_items: "{{ lookup('file', molecule_instance_config) | molecule_from_yaml }}"

    - name: Wait for boot process to finish
      pause:
        minutes: 2

```

If we skim over the code, we notice the usage of Ansible's [ec2_group module](https://docs.ansible.com/ansible/latest/modules/ec2_group_module.html). It is used to maintains AWS EC2 security groups. Using the parameters `rules` and `rules_egress`, it configures appropriate firewall inbound and outbound rules.

Thereafter Ansible's [ec2_key module](https://docs.ansible.com/ansible/latest/modules/ec2_key_module.html) is used to create a new EC2 key pair & store it locally, if non exists on your local machine already.

And then the [ec2 module](https://docs.ansible.com/ansible/latest/modules/ec2_module.html) takes over, which is able to create or terminate AWS EC2 instances without the need to hassle with the GUI.

Waiting for the EC2 instance to come up, the `create.yml` playbook uses the [async_status module](https://docs.ansible.com/ansible/latest/modules/async_status_module.html) on the pre-registered variable `server.results` from the `ec2` module.

The following Ansible module are solely used to create an inline Ansible inventory, which is finally used to connect into the EC2 instance via SSH.

The generated `destroy.yml` playbook is just the opposite to the `create.yml` playbook and tears the created EC2 instance down.

### Install & configure AWS CLI

Now let's give our configuration a shot. Just be sure to meet some prerequisites.

First we need to sure to have the [AWS CLI installed](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html). We can also do this via pip package manager with:

```
pipenv install awscli
```

Now we should check, if AWS CLI was successfully installed. The `aws --version` command should print out sometime like:

```
$ aws --version
aws-cli/1.16.80 Python/3.7.2 Darwin/18.2.0 botocore/1.12.70
```

Now configure the AWS CLI to use the correct credentials. [According to the AWS docs](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html#cli-quick-configuration), the fastest way to accomplish that is to run `aws configure`:

```
$ aws configure
AWS Access Key ID [None]: <REDACTED_AWS_ACCESS_KEY>
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: eu-central-1
Default output format [None]: json
```

### Configure Region & VPC subnet id

As there currently is a discrepancy in the UX of Molecule, where every configuration parameter is generated correctly by a `molecule init --driver-name ec2` command and picked up from `~/.aws/credentials`. __Except__ the `region` configuration from `~/.aws/config`!

Running a Molecule test without setting the region correctly as environment variable, currently results [in the (already documented) error](https://github.com/ansible/molecule/issues/1570):

```
"msg": "Either region or ec2_url must be specified",
```

So for now we need to set the region manually before running our Molecule tests against EC2:

```
export EC2_REGION=eu-central-1
```

And there's another thing to do: We need to configure the correct `vpc_subnet_id` inside our `molecule.yml` - if not, we get an error like this:

```
    "    raise self.ResponseError(response.status, response.reason, body)",
    "boto.exception.EC2ResponseError: EC2ResponseError: 400 Bad Request",
    "<?xml version=\"1.0\" encoding=\"UTF-8\"?>",
    "<Response><Errors><Error><Code>InvalidSubnetID.NotFound</Code><Message>The subnet ID 'subnet-6456fd1f' does not exist</Message></Error></Errors><RequestID>1c971ba2-0d86-4335-9445-d989e988afce</RequestID></Response>"
]
```

We need to somehow figure out the correct VPC subnet id of our region. Therefore, you can simply use Ansible to gather that for you by using the [ec2_vpc_subnet_facts module](https://docs.ansible.com/ansible/latest/modules/ec2_vpc_subnet_facts_module.html):

```
    - name: Gather facts about all VPC subnets
      ec2_vpc_subnet_facts:
```

This will give the correct String inside the field `subnets.id`:

```
    ok: [localhost] => {
        "changed": false,
        "invocation": {
            "module_args": {
                "aws_access_key": null,
                ...
            }
        },
        "subnets": [
            {
                "assign_ipv6_address_on_creation": false,
                "availability_zone": "eu-central-1b",
                "availability_zone_id": "euc1-az3",
                ...
                "id": "subnet-a2efa1d9",
                ...
            },

```

As an alternative you can use AWS CLI with `aws ec2 describe-subnets` to find the correct ID inside the field `Subnets.SubnetId`:

```
$ aws ec2 describe-subnets

{
    "Subnets": [
        {
            "AvailabilityZone": "eu-central-1b",
            "AvailabilityZoneId": "euc1-az3",
            ...
            "SubnetId": "subnet-a2efa1d9",
            ...
        },
        {
            "AvailabilityZone": "eu-central-1c",
            ...
        },
        {
            "AvailabilityZone": "eu-central-1a",
            ...
        }
    ]
}
```

Now head over to your [molecule.yml](docker/molecule/aws-ec2-ubuntu/molecule.yml) and edit the `vpc_subnet_id` to contain the correct value:

```
scenario:
  name: aws-ec2-ubuntu

driver:
  name: ec2
platforms:
  - name: aws-ec2-ubuntu
    image: ami-a5b196c0
    instance_type: t2.micro
    vpc_subnet_id: subnet-a2efa1d9
...
```

### Choosing an Ubuntu 18.04 AMI

[As stated here[(https://askubuntu.com/a/1031156/451114), Amazon has a "official" Ubuntu 18.04 AMI - but this one isn't available under the free tier right now.

But the official image is just the same as from Canonical, which could be found with the [ubuntu Amazon EC2 AMI Locator](https://cloud-images.ubuntu.com/locator/ec2/):

Fill in your region - e.g. for me this is `eu-central-1` - together with the desired Ubuntu version - like `18.04 LTS` - and the site should filter all available AMI images in this region:

![ubuntu-Amazon-EC2-AMI-Locator](screenshots/ubuntu-Amazon-EC2-AMI-Locator.png)

Now choose the AMI id with the __Instance Type__ `hvm:ebs-ssd`, which means that our EC2 instance will use Amazon Elastic Block Storage memory. Only this instance type is eligible for the free tier. In our region the the correct AMI id for Ubuntu 18.04 is `ami-080d06f90eb293a27`. We need to configure this inside our [molecule.yml](docker/molecule/aws-ec2-ubuntu/molecule.yml):

```
scenario:
  name: aws-ec2-ubuntu

driver:
  name: ec2
platforms:
  - name: aws-ec2-ubuntu
    image: ami-080d06f90eb293a27
    instance_type: t2.micro
    vpc_subnet_id: subnet-a2efa1d9
...
```

### Creating a EC2 instance with Molecule

Now we should have everything prepared. Let's try to run our first Molecule test on AWS EC2 (including `--debug` so that we see what's going on):

```
molecule --debug create --scenario-name aws-ec2-ubuntu
```

We could have a sneak peak into our Ansible EC2 Management console under https://eu-central-1.console.aws.amazon.com/ec2/v2/home?region=eu-central-1. We should see our EC2 instance starting up:

![aws-ec2-management-console-instance-startup](screenshots/aws-ec2-management-console-instance-startup.png)

If everything went fine, the `molecule create` command should succeed and your EC2 console should show the running EC2 instance:

![aws-ec2-management-console-instance-running](screenshots/aws-ec2-management-console-instance-running.png)

### Run a first Test on EC2 with Molecule

Now let's try to run our Ansible role against our new EC2 instance with Molecule:

```
molecule converge --scenario-name aws-ec2-ubuntu
```

That should just work fine. We then could head over to the verify-phase:

```
molecule verify --scenario-name aws-ec2-ubuntu
```

This should successfully execute our Testinfra test suite described in [test_docker.py](docker/molecule/tests/test_docker.py) onto our EC2 instance. If everything ran fine, it should give something like:

![aws-molecule-verify-success](screenshots/aws-molecule-verify-success.png)

If the last test function fails with an error like:
```
docker: Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
```
you maybe have to add `sudo ` to the `docker run hello-world` statement:

```
def test_run_hello_world_container_successfully(host):
    hello_world_ran = host.run("sudo docker run hello-world")

    assert 'Hello from Docker!' in hello_world_ran.stdout
```

### Cleaning up

Finally it's time to clean up. Let's run a `molecule destroy` command to tear down or EC2 instance:

```
molecule --debug destroy --scenario-name aws-ec2-ubuntu
```

If that command went well, we can have a look into our AWS EC2 management console again:

![aws-ec2-management-console-instance-terminated](screenshots/aws-ec2-management-console-instance-terminated.png)

Our instance should have reached the state `terminated`, which is simmilar to `stopped` state - just for instances that used EBS storage (see the [AWS EC2 Instance Lifecycle chart](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html) for more info).

Here's a full asciinema cast of all the steps:

[![asciicast](https://asciinema.org/a/220434.svg)](https://asciinema.org/a/220434)

### Final check: molecule test

As you may remember, Molecule provides the consecutive list of steps that run one by one. For introductory reasons we choosed to execute each step manually.

But having everything configured and in place right now, we should be able to run the command that summarizes all the others: `molecule test`:

```
molecule test --scenario-name aws-ec2-ubuntu
```

## Use TravisCI to execute Molecule with EC2 infrastructure

My ultimate goal of the whole Molecule journey was to be able to let TravisCI create Cloud environments and execute Ansible roles on them.

So we should bring all the things learned togehter now:

> Using Molecule to develop and test an Ansible role - togehter with the infrastructure provider AWS EC2 - automatically executed by TravisCI after commits or regularly with TravisCI cron jobs.

So let's do it! First we need to configure TravisCI. Therefore we need to enhance our [.travis.yml](.travis.yml). As we need the same python package additions as locally, we need to install `boto`, `boto3` and `awscli`:

```yaml
sudo: required
language: python

env:
- EC2_REGION=eu-central-1

services:
- docker

install:
- pip install molecule docker

# install AWS related packages
- pip install boto boto3
- pip install --upgrade awscli
# configure AWS CLI
- aws configure set aws_access_key_id $AWS_ACCESS_KEY
- aws configure set aws_secret_access_key $AWS_SECRET_KEY
- aws configure set default.region $DEPLOYMENT_REGION
# show AWS CLI config
- aws configure list

script:
- cd docker
# Molecule Testing Travis-locally with Docker
- molecule test
# Molecule Testing on AWS EC2
- molecule create --scenario-name aws-ec2-ubuntu
- molecule converge --scenario-name aws-ec2-ubuntu
- molecule verify --scenario-name aws-ec2-ubuntu
- molecule destroy --scenario-name aws-ec2-ubuntu
```

After that, we need to configure our AWS CLI to use the correct credentials and AWS region. This can be achieved by usind the `aws configure set` command. Then we need to head over to the settings tab of our TravisCI project (for the current project this can be found at https://travis-ci.org/jonashackt/molecule-ansible-docker-vagrant/settings) and insert the three environment variables `AWS_ACCESS_KEY`, `AWS_SECRET_KEY` and `DEPLOYMENT_REGION`:

![travisci-aws-settings-env-variables](screenshots/travisci-aws-settings-env-variables.png)

The last part is to add the molecule commands to the `script` section of the `.travis.yml`.

### Problems with boto on Travis

As https://github.com/boto/boto/issues/3717 suggests, there are currently problems with the AWS connection library boto on TravisCI. They result in errors like:

```
        "msg": "Traceback (most recent call last):\n  File \"/home/travis/.ansible/tmp/ansible-tmp-1547040777.3-69673074739502/async_wrapper.py\", line 147, in _run_module\n    (filtered_outdata, json_warnings) = _filter_non_json_lines(outdata)\n  File \"/home/travis/.ansible/tmp/ansible-tmp-1547040777.3-69673074739502/async_wrapper.py\", line 88, in _filter_non_json_lines\n    raise ValueError('No start of json char found')\nValueError: No start of json char found\n",
        "stderr": "Traceback (most recent call last):\n  File \"/home/travis/.ansible/tmp/ansible-tmp-1547040777.3-69673074739502/AnsiballZ_ec2.py\", line 113, in <module>\n    _ansiballz_main()\n  File \"/home/travis/.ansible/tmp/ansible-tmp-1547040777.3-69673074739502/AnsiballZ_ec2.py\", line 105, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/travis/.ansible/tmp/ansible-tmp-1547040777.3-69673074739502/AnsiballZ_ec2.py\", line 48, in invoke_module\n    imp.load_module('__main__', mod, module, MOD_DESC)\n  File \"/tmp/ansible_ec2_payload_y3lfWH/__main__.py\", line 552, in <module>\n  File \"/home/travis/virtualenv/python2.7.14/lib/python2.7/site-packages/boto/__init__.py\", line 1216, in <module>\n    boto.plugin.load_plugins(config)\nAttributeError: 'module' object has no attribute 'plugin'\n",
        "stderr_lines": [
            "Traceback (most recent call last):",
            "  File \"/home/travis/.ansible/tmp/ansible-tmp-1547040777.3-69673074739502/AnsiballZ_ec2.py\", line 113, in <module>",
            "    _ansiballz_main()",
            "  File \"/home/travis/.ansible/tmp/ansible-tmp-1547040777.3-69673074739502/AnsiballZ_ec2.py\", line 105, in _ansiballz_main",
            "    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)",
            "  File \"/home/travis/.ansible/tmp/ansible-tmp-1547040777.3-69673074739502/AnsiballZ_ec2.py\", line 48, in invoke_module",
            "    imp.load_module('__main__', mod, module, MOD_DESC)",
            "  File \"/tmp/ansible_ec2_payload_y3lfWH/__main__.py\", line 552, in <module>",
            "  File \"/home/travis/virtualenv/python2.7.14/lib/python2.7/site-packages/boto/__init__.py\", line 1216, in <module>",
            "    boto.plugin.load_plugins(config)",
            "AttributeError: 'module' object has no attribute 'plugin'"
        ]
    }

    PLAY RECAP *********************************************************************
    localhost                  : ok=6    changed=4    unreachable=0    failed=1

ERROR:
The command "molecule --debug create --scenario-name aws-ec2-ubuntu" exited with 2.
```

To fix this, there are two changes needed inside our [.travis.yml](.travis.yml). We need to set `sudo: false` and use the environment variable `BOTO_CONFIG=/dev/null`:

```yaml
sudo: false
language: python

env:
- EC2_REGION=eu-central-1 BOTO_CONFIG="/dev/null"
...
```

And we need to add the `BOTO_CONFIG` environment variable to the same line as the already existing variable - otherwise Travis starts multiple builds with only one variable set to each build! See the docs (https://docs.travis-ci.com/user/environment-variables/#defining-multiple-variables-per-item)

> If you need to specify several environment variables for each build, put them all on the same line in the env array

Now head over to Travis and have a look into the log. It should look green and somehow like this: https://travis-ci.org/jonashackt/molecule-ansible-docker-vagrant/builds/477365844

## Use CircleCI to execute Molecule with EC2 infrastructure

As TravisCI is just one example of a cloud CI provider, let's use another one also - so let's just pick [CircleCI](https://circleci.com), let's go with this CI tool!

> Using Molecule to develop and test an Ansible role - togehter with the infrastructure provider AWS EC2 - automatically executed by CircleCI after commits or regularly with CircleCI scheduled jobs.

So let's do it! First we need to configure CircleCI. Therefore we need to create a [.circleci/config.yml](.circleci/config.yml). As we need the same python package additions as locally, we need to install `boto`, `boto3` and `awscli`:

```yaml
version: 2
jobs:
  build:
    docker:
      - image: circleci/python:3.6.1

    environment:
      EC2_REGION: eu-central-1

    working_directory: ~/molecule-ansible-docker-vagrant

    steps:
      - checkout

      - run:
          name: Install Molecule dependencies
          command: |
            pip install molecule docker

      - run:
          name: Run Molecule Testing CircleCI-locally with Docker
          command: |
            cd docker
            molecule test

      - run:
          name: Install Molecule AWS dependencies
          command: |
            pip install boto boto3
            pip install --upgrade awscli

      - run:
          name: configure AWS CLI
          command: |
            aws configure set aws_access_key_id ${AWS_ACCESS_KEY}
            aws configure set aws_secret_access_key ${AWS_SECRET_KEY}
            aws configure set default.region ${EC2_REGION}
            aws configure list

      - run:
          name: Run Molecule Testing on AWS EC2
          command: |
            cd docker
            molecule create --scenario-name aws-ec2-ubuntu
            molecule converge --scenario-name aws-ec2-ubuntu
            molecule verify --scenario-name aws-ec2-ubuntu
            molecule destroy --scenario-name aws-ec2-ubuntu

```

After that, we need to configure our AWS CLI to use the correct credentials and AWS region. This can be achieved by usind the `aws configure set` command. Then we need to head over to the settings tab of our CircleCI project (for the current project this can be found at https://circleci.com/gh/jonashackt/molecule-ansible-docker-vagrant/edit#env-vars) and insert the three environment variables `AWS_ACCESS_KEY` & `AWS_SECRET_KEY`:

![circleci-aws-settings-env-variables](screenshots/circleci-aws-settings-env-variables.png)

The last part is to add the molecule commands to our `.circleci/config.yml`.

### CircleCI gives Permission denied error at pip install

Using `circleci/python` Docker image it seems that you can't simply use `pip install xyz`:

```
PermissionError: [Errno 13] Permission denied: '/usr/local/lib/python3.6/site-packages/ptyprocess'
```

This error is also [reported here](https://discuss.circleci.com/t/circleci-python-docker-images-disallow-pip-install-due-to-directory-ownership/12504). To avoid this error, we need to use `sudo` to be able to install the pip packages successfully:

```yaml
version: 2
jobs:
  build:
    docker:
      - image: circleci/python:3.6.1
...
    steps:
      - checkout

      - run:
          name: Install Molecule dependencies
          command: |
            sudo pip install molecule docker

      - run:
          name: Run Molecule Testing CircleCI-locally with Docker
          command: |
            cd docker
            molecule test
```

### "msg": "Error connecting: Error while fetching server API version: ('Connection aborted.', FileNotFoundError(2, 'No such file or directory'))"

Molecule needs a Docker service available. Since CircleCI is mostly using pure Docker-based images to run it's CI jobs, there's no Docker service inside the Docker containers available. But there's help! [The docs state](https://circleci.com/docs/2.0/building-docker-images/):

> If your job requires docker or docker-compose commands, add the setup_remote_docker step into your .circleci/config.yml

We need to use `- setup_remote_docker`

```yaml
version: 2
jobs:
  build:
    docker:
      - image: circleci/python:3.6.1
...
    steps:
      - checkout

      - setup_remote_docker:
```

> Don't use `docker_layer_caching: true`, if you only have the free tier available (see https://github.com/jonashackt/molecule-ansible-docker-vagrant/issues/5)!!

Now head over to CircleCI and have a look into the log. It should look green and somehow like this: https://circleci.com/gh/jonashackt/molecule-ansible-docker-vagrant/16 :

![circleci-aws-full-run-docker-aws](screenshots/circleci-aws-full-run-docker-aws.png)

### Schedule regular CircleCI builds with workflow triggers & cron

As the docs at https://circleci.com/docs/2.0/triggers/#scheduled-builds state, we need to add the `workflows` section inside our [.circleci/config.yml](.circleci/config.yml) to be able to use cron-scheduled builds. First we introduce a `on-commit:` workflow, which will just be triggered by a normal git commit/push. Nothing new here.

But the second workflow item `weekly-schedule:` gets us where we wanted to be: using the `cron` trigger we can configure to run our Molecule tests e.g. once on friday 04:45 PM every week:

```yaml
workflows:
  version: 2
  on-commit:
    jobs:
      - build
  weekly-schedule:
    triggers:
      - schedule:
          # 17:55 every friday (see https://en.wikipedia.org/wiki/Cron)
          cron: "55 17 * * 5"
          filters:
            branches:
              only:
                - master
    jobs:
      - build
```

Now we should see our builds triggered by this cron regularly:

![circleci-cron-weekly-schedule](screenshots/circleci-cron-weekly-schedule.png)

Just mind the `UTC+2` timezone - for me, configuring `17:55` actually means, that my job will be scheduled to run at `19:55` - so don't think your config is wrong, maybe you're just in another timezone :)


text:
# Loyal card admin dashboard
## Background
I am a regular coffee consumer and see lots of the coffee shop use paper-based cards to reward customers with regular purchases. There are lots of paper waste of this solution and the data is not tracked and the stamp verification can be hacked easily.
So the idea is to create a digital loyalty card solution to reduce the paper usage that can protect our environment to some extent. Also, as the spreading of the COVID-19, this solution also reduces the unnecessary contact during the business activity as the whole process is contactless. Meanwhile, this digital solution will keep the data for reporting and future big-data analysis for the customer coffee consumption behavior if the data collection is accumulated to a certain amount, and the scan verification on the one time QR code token can make sure the security of the system.
This is a MVP (Most viable product) that verifies that the solution is feasible and makes sure the core functionalities are achieved, there will be an ongoing development roadmap to extend the features of this solution.
The whole solution consists of three components, `core-service` , `admin-dashboard` and `client-mobile-app`.
## Introduction
This`admin-dashboard` will be used by the shop staff to scan the customer generated QR Code while purchase, also the dashboard will provide the report and insights of the sales data.
### Highlights
- This project was bootstrapped with [Create React App]([https://github.com/facebook/create-react-app](https://github.com/facebook/create-react-app)).
- Make use of Material UI to build the backend component.
- Use JWT for authentication with the backend `core-service`
- Use browser Camara API for the QR Code scanning.
- Deployed to Github pages
## Getting started
### Prerequisites
1. Node: any version starting with 10.16.0 or greater
  - run `node --version` to check current node version
  - If you need to upgrade or install [NodeJs]([http://nodejs.org/](http://nodejs.org/)) : suggest to install via [Node Version Manager NVM]([https://github.com/creationix/nvm](https://github.com/creationix/nvm))
2. A clone or download of this repo on your local machine
### Installation
1. `cd` to the project root
2. `npm install`to install the npm dependencies
### Running locally
- `npm run start` to start the development server.
### Deployment
- You can run the `npm run deploy` to deploy the project directly to Github Pages.
- Will integrate Github Action to achive continous deployment to Github Pages (WIP).

license: MIT

repository: loyal-card/admin-dashboard

branch_name: refs/heads/master

extension: md

gha_language: JavaScript

gha_license_id: MIT

license_type: permissive

repo_name: loyal-card/admin-dashboard


text:
# react-firebase

The ReactJS Tutorial with Firebase integration.

## Getting started

To get started, simply clone or download this repo and install the dependencies.

#### Clone this repo

```bash
git clone https://github.com/tobysteward/react-firebase.git
cd react-firebase
```

#### Installing dependencies

```bash
$ npm install && bower install
```

## Demo

Hosted on Firebase at [https://reactfb.firebaseapp.com](https://reactfb.firebaseapp.com/)

repository: tobysteward/react-firebase

repo_name: tobysteward/react-firebase


text:
![teamwork](https://media.giphy.com/media/65HR2UL6nn6XMSUoRA/giphy.gif)

# What Google Learned From Its Quest To Build A Perfect Team
-----
### We've all been a part of a team at some point or another in our lives. We could have been on a team at work or at school. Even partnerships are a team. Let's look at some fundamentals of how a truly exceptional team operates.

**After reading this [article](https://www.nytimes.com/2016/02/28/magazine/what-google-learned-from-its-quest-to-build-the-perfect-team.html) from *The New York Times Magazine*, it is clear that there is more to a great team than just high performers. There is SO, SO MUCH MORE. Some key takeaways:**

* Employee performance optimization IS NOT enough these days-- we have to dig deeper into what makes a great team well...GREAT
* Collaborative activities are growing as modern work is becoming team-based (Why do you think you always see the **"must be a team player"** on those job descriptions you were looking at?)
* Groups tend to innovate faster, find better solutions to problems and report higher job satisfaction
* Combining the best people together or grouping people based on personality traits and tendencies isn't the answer

## PROJECT ARISTOTLE studied hundreds of Google's teams to figure out what made some teams excel and others fail

**As you can imagine, a lot of data was gathered but no patterns emerged as quickly as they'd hoped. So, They focused their research on **GROUP NORMS** and quickly found patterns emerge**

![normal](https://media.giphy.com/media/QQoRQ2Gf1i7MA/giphy.gif)

* It turns out, that the researchers concluded that understanding and influencing group norms were the keys to improving Google’s teams
* The researchers eventually concluded that what distinguished the ‘good’ teams from the dysfunctional groups was how teammates treated one another.
* The right norms, in other words, could raise a group’s collective intelligence, whereas the wrong norms could hobble a team, even if, individually, all the members were exceptionally bright.
* First, on the good teams, members spoke in roughly the same proportion, a phenomenon the researchers referred to as ‘equality in distribution of conversational turn-taking
* good teams members were skilled at intuiting how others felt based on their tone of voice, their expressions and other nonverbal cues

## ABOVE ALL ELSE, WHAT TRULY CAN HELP A TEAM TO SUCCEED IS PSYCHOLOGICAL SAFETY...
>"The behaviors that create psychological safety — conversational turn-taking and empathy — are part of the same unwritten rules we often turn to, as individuals, when we need to establish a bond. And those human bonds matter as much at work as anywhere else. In fact, they sometimes matter more."

**More Key Takeaways:**

* We want to be ourselves at work, not put parts of ourselves away in a box and then pretend to be someone else when we're at work
* We need to feel free to share, to shine, to fail, to be vulnerable when we are at work (within reason of course)
* We want to be heard
* We need to focus a bit more on empathy and sensitivity in teamwork
* Sometimes success of a team is not measured by productivity, but rather experiences

### "Project Aristotle is a reminder that when companies try to optimize everything, it’s sometimes easy to forget that success is often built on experiences — like emotional interactions and complicated conversations and discussions of who we want to be and how our teammates make us feel — that can’t really be optimized."


text:
# C++ Prediction Library Installation

## Prerequisites

* C++ 17 Compiler. (g++7, clang++4.0, MSVC19.0 or newer)
* CMake 3.5+
* Third-Party
    * OpenCV3.2+. (**[OpenCV 4+](https://docs.opencv.org/trunk/d7/d9f/tutorial_linux_install.html) is highly recommended**)
    * [CUDA 10.2](https://developer.nvidia.com/cuda-downloads), [CuDNN 7.6.5](https://docs.nvidia.com/deeplearning/cudnn/install-guide/index.html), [TensorRT 7.0](https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html).
    * gFlags(for CLI/examples/tests)

> Other versions of the packages may also work but not tested.

> **About TensorRT installation**
>
> - For Linux users, you highly recommended to install it in a system-wide setting. You can install TensorRT7 via the [debian distributions](https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html#installing-debian) or [NVIDIA network repo](https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html#maclearn-net-repo-install).
> - Different TensorRT version requires specific CUDA and CuDNN version. For specific CUDA and CuDNN requirements of TensorRT7, please refer to [this](https://docs.nvidia.com/deeplearning/tensorrt/support-matrix/index.html#platform-matrix).
> - Also, for Ubuntu 18.04 users, this [3rd party blog](https://ddkang.github.io/2020/01/02/installing-tensorrt.html) may help you.

## Build On Ubuntu 18.04

```bash
# >>> Install OpenCV3+ and other dependencies.
sudo apt -y install cmake libopencv-dev libgflags-dev
# !Note that the APT version OpenCV3.2 on Ubuntu18.04 has some trouble on Cameras Newer version is suggested.
# You are highly recommended to install OpenCV 4+ from scratch also for better performance.

# >>> Install dependencies to run the scripts in `${REPO}/scripts`
sudo apt install python3-dev python3-pip

# >>> Install CUDA/CuDNN/TensorRT: https://docs.nvidia.com/deeplearning/tensorrt/install-guide/index.html#installing-debian

# >>> Build HyperPose
git clone https://github.com/tensorlayer/hyperpose.git
cd hyperpose
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release && cmake --build .
```

## Build with User Codes

You can directly write codes and execute it under the hyperpose repository.

- **Step 1**: Write your own codes in `hyperpose/examples/user_codes` with suffix `.cpp`.
- **Step 2**:

```bash
mkdir -p build && cd build
cmake .. -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_USER_CODES=ON   # BUILD_USER_CODES is by default on
cmake --build .
```

- **Step 3**: Execute your codes!

Just go to [Quick Start](../quick_start/prediction.md) to test your installation.


text:
# NServiceBus FileWatcher Demo

Quick PoC for a prospective customer

## Start

- Open FileWatcherDemo.sln in Visual Studio 2017 or higher
- Build
- Setup Start projects to FileWatcherService, Platform and Receiver
- F5
- By default Receiver will be started as `destination1` but it is possible to start more instances by providing a console argument like `destination2`
- Sample files are available in `Files` folder
  - Copy `destination1.success.txt` into `FileWatcherService\bin\Debug\net462\input` to send a command that will succeed
  - Copy `destination1.transient.txt` into `FileWatcherService\bin\Debug\net462\input` to send a command that will be retried once
  - Copy `destination1.permanent.txt` into `FileWatcherService\bin\Debug\net462\input` to send a command that will fail all attemps
- Permanently failed commands can be sent back by using the Failed Messages view in the opened browser window and will then succeed

## Multiple destinations

- Start like above
- Open command window or powershell in `Receiver\bin\Debug\net462` and run `Receiver.exe destination2`
- Copy the `destination1.*.txt` files and rename them to `destination2.*.txt`
- Copy them like before into `FileWatcherService\bin\Debug\net462\input` to see how messages get sent to the new destination


text:
# Rselect

> A simple and accessible select for the web.

## Install

`npm install rselect` or `yarn add rselect`

## Live Playground

For more examples you can check out the storybook.

* Clone this repo on your machine.
* `yarn install`
* `yarn run storybook`
* Visit `http://localhost:9001/`.

live demo: http://client.zarendar-application.win/

repository: zarendar/rselect

repo_name: zarendar/rselect


text:
# HelpscoutSpark

An Helpscout integration package for [Laravel Spark](https://spark.laravel.com/) that allows you to add information about tickets created by customers in Helpscout.

It includes two separate functions:
1. It adds an endpoint for a [Helpscout Dynamic App](https://developer.helpscout.com/custom-apps/dynamic/) to display information about the user's billing plan and historical data.
2. It accepts webhooks from Helpscout and processes them based on rules that you set up. By default, it will tag each new ticket with the user's current billing plan.

## Installation

This version requires [PHP](https://php.net) 7, and supports Laravel 5.5+ and Spark 5+.

To get the latest version, simply require the project using [Composer](https://getcomposer.org):

```
$ composer require keithbrink/helpscout-app-spark
```

## Configuration - Custom App

Create a custom app in Helpscout, and point the callback URL to your app URL + the following endpoint:

```/helpscout-spark-app/custom-app```

Add the secret key for the custom app in your .env file:

```HS_SPARK_CUSTOM_APP_SECRET=xxxxxx```

## Configuration - Webhook Rules

Create a new app in Helpscout (under My Apps), and add the following keys in your .env file:

```
HS_AUTH_TYPE=client_credentials
HS_APP_ID=xxx
HS_APP_SECRET=xxx
```

Then, create a new webhook for the endpoint:

```/helpscout-spark-app/webhooks```

and add your secret key in your .env file:

```
HS_SPARK_WEBHOOK_SECRET=xxx
```

## Usage

Out of the box, you will have a custom app with the user's current billing plan and other customer data on each ticket, and the webhook will add a tag for the user's current billing plan to each ticket that is created.

It is simple to add your own information to either the custom app or new rules to handle Helpscout webhooks.

## Add Custom App Items

To add more items to the custom app, simply copy the `KeithBrink/HelpscoutSpark/CustomAppData/Items/Plan`, including extending the `BaseItem` and implementing the `ItemContract`.

Change the `getValue` and `getName` function to whatever you like.

Then, add your rule in your `AppServiceProvider` register function:

```
\KeithBrink\HelpscoutSpark\CustomAppData\Items::$items[] = YourItem::class;
```

## Add Webhook Rule

To add another webhook rule, simply copy the `KeithBrink/HelpscoutSpark/WebhookRules/Rules/TagConversationWithPlan`, including extending the BaseRule and implementing the RuleContract.

The `parseWebhook` function accepts the webhook, here you should set any properties that you will need from the webhook.

Then, handle the webhook, including interacting with the Helpscout API if necessary, in the `handle` function.

Then, add your rule in your `AppServiceProvider` register function:

```
\KeithBrink\HelpscoutSpark\WebhookRules\Rules::$rules[] = YourRule::class;
```

## License

HelpscoutSpark is licensed under [The MIT License (MIT)](LICENSE).

repository: keithbrink/helpscout-app-spark

repo_name: keithbrink/helpscout-app-spark


text:
### Release Steps
Create 2 virtualenv to generate package for both python 2 & 3

```bash
virtualenv -p /usr/bin/python3 venv
virtualenv -p /usr/bin/python2 venv2
# activate python3 venv
 source venv/bin/activate
 pip install -r requirements.txt
 python3 setup.py sdist bdist_wheel
 deactivate
  # switch to python2  venv2
 source venv2/bin/activate
 pip install -r requirements.txt
 python2.7 setup.py sdist bdist_wheel
 # Check for Markdown  error
 twine check dist/*
 # Replace the 0.5 with current version
 twine upload dist/superhooks-0.5.tar.gz
 twine upload dist/superhooks-0.5-py2-none-any.whl
 twine upload dist/superhooks-0.5-py3-none-any.whl
 ```

repository: seanbreckenridge/superhooks

repo_name: seanbreckenridge/superhooks


text:
+++
title = "Left vs Right Brain Test"
date = "2009-10-20"
delicious = [ 'a:3:{s:5:"count";s:1:"0";s:9:"post_tags";s:0:"";s:4:"time";s:10:"1282616148";}' ]
reddit = [ 'a:2:{s:5:"count";s:1:"0";s:4:"time";s:10:"1282616148";}' ]
categories = [ "Personal" ]
topics = [ "Random" ]
+++

I just took an online test to determine which side of the brain you favor, right or left. Here are my results:

## Right Brain/ Left Brain Quiz

The higher of these two numbers below indicates which side of your brain has dominance in your life. Realising your right brain/left brain tendency will help you interact with and to understand others.

  Left Brain Dominance: <meter value="5" min="1" max="10">Left Brain Dominance</meter> 5/10

  Right Brain Dominance: <meter value="5" min="1" max="10">Right Brain Dominance</meter> 5/10

What does this mean? Here’s the breakdown:

### Left Hemisphere Style

Draws on previously accumulated, organized information

#### Rational

* Responds to verbal instructions
* Problem solves by logically and sequentially looking at the parts of things
* Looks at differences
* Is planned and structured
* Prefers established, certain information
* Prefers talking and writing
* Prefers multiple choice tests
* Controls feelings
* Prefers ranked authority structures

#### Sequential

* Is a splitter: distinction important
* Is logical, sees cause and effect

### Right Hemisphere Style

Draws on unbounded qualitative patterns that are not organized into sequences, but that cluster around images

#### Intuitive

* Responds to demonstrated instructions
* Problem solves with hunches, looking for patterns and configurations
* Looks at similarities
* Is fluid and spontaneous
* Prefers elusive, uncertain information
* Prefers drawing and manipulating objects
* Prefers open ended questions
* Free with feelings
* Prefers collegial authority structures

#### Simultaneous

* Is a lumper: connectedness important
* Is analogic, sees correspondences, resemblances

Brains are cool! [Take the test for yourself](http://www.intelliscript.net/test_area/questionnaire/questionnaire.cgi?q=right_brain_left_brain_2); it only takes two minutes.

repository: bronzehedwick/chrisdeluca

branch_name: refs/heads/main

repo_name: bronzehedwick/chrisdeluca


text:
---
published: true
title: House of the Dead Overkill
tags: games wii zombie
---
> charges you with mowing down waves of infected, blood-thirsty zombies in a last-ditch effort to survive Bayou City and uncover the horrific truth behind the origins of the House of the Dead.  - [wii](https://wiki.dolphin-emu.org/index.php?title=House_of_the_Dead%3A_Overkill)

- [soundtrack](https://www.youtube.com/watch?v=YqgMEVHpRKk)

![caption](https://wiki.dolphin-emu.org/images/thumb/f/f5/House_of_the_Dead_Overkill.jpg/450px-House_of_the_Dead_Overkill.jpg)


text:
#RadReveal [![Build Status](https://travis-ci.org/joelarson4/radReveal.svg)](https://travis-ci.org/joelarson4/radReveal)
RadReveal is JavaScript library to help you create add-ons for [Reveal.js - the HTML Presentation Framework](http://lab.hakim.se/reveal-js/).

Check out the demo slideshow to see how RadReveal works.

##Why isn't _everybody_ hacking Reveal.js?

[Reveal.js](http://lab.hakim.se/reveal-js/) rocks!  Web Developers seem to love Reveal.js, as evidenced by the fact that every other presentation on JavaScript seems to use it.  Personally, I love Reveal.js because it is hackable.

But not a lot of people customize or extend it -- despite the fact that Reveal.js builds in extensibility.  Or, if people are extending Reveal.js, they aren't sharing!

Maybe that's because, the out of the box, Reveal.js is not _easy_ to extend...

##The solution? RadReveal

I put together RadReveal after noticing that every presentation I was doing had some level of customization, and the types of things I was doing had a lot in common.  So I consolidated what I'd done into a simple to use library, RadReveal.

RadReveal provides these benefits.

* Makes customizing Reveal.js easy.
* Attach behaviors to slides using data attributes.
* Encourages small, shareable packages.

If you didn't already, take a look at the demo slideshow to see RadReveal in action.

#How to create a RadReveal add-on

Note: I plan to write a lot more on this soon, including some skeleton example repos you can check out and use.

##Running the demo slideshow locally
To run the demo slideshow locally, simply:

    git clone https://github.com/joelarson4/radReveal.git
    cd radReveal
    npm install

Now you should be able to run demo.html in your browser.

Note that you may need to `sudo npm install` to get everything installed properly.

##API JsDoc for RadReveal

You may want to to skip to [the API documentation for the library](https://github.com/joelarson4/radReveal/blob/master/radReveal.md).

##Simple example

What does an add-on look like?

`example.js` - the addon script

```javascript
var RadReveal = require('rad-reveal');

RadReveal.register({
  name: 'example',
  initialize: function(radConfig, slides) {
    for(var s = 0, len = slides.length; s < len; s++) {
      slides[s].className += ' ' + radConfig.addClass;
    }
  }
});
```

`index.html` modifications for initializing RadReveal and Reveal.js

```html
<script src="node_modules/reveal.js/lib/js/head.min.js"></script>
<script src="node_modules/reveal.js/js/reveal.js"></script>
<script src="node_modules/rad-reveal/build/radReveal.min.js"></script>
```
```javascript
RadReveal.initialize({ //replace Reveal.initialize w/ RadReveal.initialize
  ...normal Reveal configuration goes here
  dependencies: [
    {
      src: 'somepath/example.js',
      radName: 'example',
      radConfig: { addClass: 'example' }
    }
    ...other plugins go here
  ]
});
...
```

So what happens when you run this?

1. `RadReveal.initialize` calls `Reveal.initialize` for you, passing in the configuration.
2. `Reveal.initialize` loads dependencies, including `rad-example.js`.
3. The example add-on registers itself with an `initialize` function.
4. After Reveal is initialized, RadReveal triggers example's `initialize` function.
5. When calling `initialize`, RadReveal passes in the `radConfig` value and all slides defined.
6. `example` add-on does whatever it wants to.  In this example, the add-on appends a class `example` to every slide.

##Beyond initialize

You can run your code only for certain slides with an attribute by using `attributeEventListeners`.

```javascript
RadReveal.register({
  name: 'example',
  attributeEventListeners: {
    'data-rad-example': {
      setup: someFunction
    }
  }
});
```

Each slide with the `data-rad-example` attribute will have `someFunction` called after RadReveal initialization completes.

The listener function is called with four arguments:

* `attrVal` - the value of the attribute for this slide.
* `slideObj` - an object representing the slide.
* `event` - the event object.
* `radEventName` - the name of the event.

You could use this to do something to the slide element itself.  For example, we could add a class based on the value of the attribute.

```javascript
function addTheClass(attrVal, slideObj, event, radEventName) {
  slideObj.element.className += ' ' + attrVal;
}

RadReveal.register({
  name: 'example',
  attributeEventListeners: {
    'data-rad-example': {
      setup: addTheClass
    }
  }
});
```

So, this slide:

```html
<section data-rad-example="totallyRad">
```

would end up having an additional class of `totallyRad` added to it:

```html
<section data-rad-example="totallyRad" class="totallyRad">
```

which is a silly example but illustrates the point.

##Trigger something upon showing/hiding a slide

You can also register to run something on showing/arriving or hiding/leaving a slide with an attribute.

```javascript
RadReveal.register({
  name: 'example',
  attributeEventListeners: {
    'data-rad-example': {
      shown: anotherFunction,
      hidden: andAnotherFunction
    }
  }
});
```

This means that `anotherFunction` will run each time a slide is displayed with a `data-rad-example` attribute, and then when you leave that slide `andAnotherFunction` will run.

##The functionRunner example add-on.

The core RadReveal repo includes `functionRunner`, a simple add-on that triggers a function to run for any slide with a `data-rad-functionrunner-{eventName}` attribute.
There is also [API documentation for functionRunner](https://github.com/joelarson4/radReveal/blob/master/functionRunner.md).

For example, here is a slide with a `data-rad-functionrunner-setup` attr:

```html
<section data-rad-functionrunner-setup='{ "root" : "bar", "func" : "baz" }'>
```

and the page has a (global) object defined:

```javascript
var bar = {
  value: 'Hello world!',
  baz: function(slideObj, event, radEventName) {
    var span = document.createElement('span');
    span.innerHTML = radEventName + ': ' + this.value;
    slideObj.element.appendChild(span);
  }
}
```

Together this results in `setup: Hello world!` text being appended to the slide one time at setup (before any slides are shown).

You can also pass arguments through a functionRunner attribute.  This slide has a `data-rad-functionrunner-shown` attr:

```html
<section data-rad-functionrunner-shown='{ "func" : "foo", "args": ["shown", "2"] }'>
```

and the page has a (global) function defined:

```javascript
function foo(arg0, arg1, slideObj, event, radEventName) {
  var span = document.createElement('span');
  span.className = 'functionRunnerAdded';
  span.innerHTML =  radEventName + ': ' + arg0 + ' at ' + arg1;
  slideObj.element.appendChild(span);
}
```

which results in `shown: shown at 2` being appending to the slide every time it is shown.

Likewise you could use the attribute name `data-rad-functionrunner-hidden` to run a function when leaving the slide.

You also can use the same attributes on inner/vertical slides.

#In closing
Before you go, a few more things you should know.

##Browser support
I need to put more effort into formalizing my policy and approach on this, as well as testing IE.  Currently I am manually testing this in recent versions of Chrome (40.0) and Firefox (31.4), and running automated tests in PhantomJS (1.9.8).

I am making an assumption that devs using Reveal.js are able to keep fairly up to date with browsers.  I realize this limits slide-sharing capabilities but I think that's a tradeoff worth making.  I'm also very open to help figuring out a better approach.  Please feel free to file an issue and tell me why I'm wrong and what I can do better!

##More addons coming

* I have a several other addons in prototype that I will clean up and release (as separate repos) soon.
* I will list these on main RadReveal README.
* And hopefully remember to update this slide!

##Please write your own add-ons!

The dream would be a tiny ecosystem of well written addons that folks can use to make **rad** presentations.

repository: anvaka/radReveal

repo_name: anvaka/radReveal


text:
# AAS-18-290_3dof
# Please cite the following paper if you publish work using this code:
@article{gaudet2018deep,
  title={Deep Reinforcement Learning for Six Degree-of-Freedom Planetary Powered Descent and Landing},
  author={Gaudet, Brian and Linares, Richard and Furfaro, Roberto},
  journal={arXiv preprint arXiv:1810.08719},
  year={2018}
}
## virtual environment should include:
### Tensorflow 1.4
### Python 3.5
### Matplotlib
### Scipy
### jupyter
### scikit-learn

### 1.) Download this repository
### 2.) cd to appropriate directory in Run
### 3.) open jupyter from the virtual environment
### 4.) run the notebook


text:
OULibraries.alma-z3950-gateway
=========

Alma Z39.50 Gateway for OU Libraries

Requirements
------------

CentOS 7.x
Apache
MariaDB

Role Variables
--------------

See defaults/main.yml here and in roles noted as dependencies.

Dependencies
------------

```
- src: https://github.com/OULibraries/ansible-role-apache2
  version: v2016-10-17.0
  name: OULibraries.apache2

- src: https://github.com/OULibraries/ansible-role-centos7
  version: v2016-10-21.0
  name: OULibraries.centos7

- src: https://github.com/OULibraries/ansible-role-mariadb
  version: v2016-09-26.0
  name: OULibraries.mariadb

- src: https://github.com/OULibraries/ansible-role-users
  version: v2016-11-14.0
  name: OULibraries.users
```

Example Playbook
----------------

License
-------

[MIT](https://github.com/OULibraries/ansible-role-zlma-z3950-gateway/blob/master/LICENSE)

Author Information
------------------

Jason Sherman


text:
# Ramularia lapsanae (Desm.) Sacc., 1882 SPECIES

#### Status
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
Fungi italica 17-28: tab. 995 (549) (1882)

#### Original name
Oidium fusisporioides f. lapsanae Desm.

### Remarks
null

repository: mdoering/backbone

repo_name: mdoering/backbone


text:
---
layout: post
title: "Markdown Syntax Guide"
date: 2011-11-22 18:13
comments: true
categories: [网文]
tags: [guide,markdown,syntax]
---
## Markdown Syntax Guide
Markdown Syntax Guide
The Allura code uses markdown syntax everywhere to allow you to create rich
text markup, and extends markdown in several ways to allow for quick linking
to other artifacts in your project.

Markdown was created to be easy to read, easy to write, and still readable in plain text format.

Links
Reference Links
Artifact Links
Text
Blockquotes
Preformatted Text
Lists
Tables
Headers
Horizontal Rules
Images
Escapes
More Headers
Code Highlighting
Includes
Neighborhood Notifications
Download Button
Project Screenshots
Thanks
Links
Most URLs will automatically be turned into links. To be explicit, just write it like this:

<http://someurl>

<EMAIL_ADDRESS>
Output:

http://someurl

<EMAIL_ADDRESS>
To use text for the link, write it:

[like this](http://someurl)Output:

like this

You can add a *title* (which shows up under the cursor):

[like this](http://someurl "this title shows up when you hover")Output:

like this

Reference Links
You can also put the [link URL][1] below the current paragraph
like [this][2].

   [1]: http://url
   [2]: http://another.url "A funky title"
Output:

You can also put the link URL below the current paragraph like this.

Here the text "link URL" gets linked to "http://url", and the lines showing "[1]: http://url" won't show anything.

Or you can use a [shortcut][] reference, which links the text "shortcut" to the link named "[shortcut]" on the next paragraph.

Or you can use a [shortcut][] reference, which links the text
"shortcut" to the link named "[shortcut]" on the next paragraph.

[shortcut]: http://goes/with/the/link/name/textOutput:

Or you can use a shortcut reference, which links the text "shortcut" to the link named "shortcut" on the next paragraph.

Artifact Links
Any existing forge resource can be linked with surrounding square brackets ie [MyPage] or [#123].

Links to resources in other tools can be explicitly referenced by adding a tool identifier prefix to the link. So for instance `[developerwiki:MyPage]` can refer to a wiki page in a `developerwiki` instance. You can also link to tickets with `[tickets:#123]` assuming there's a 123 ticket in a Tracker instance mounted at `tickets`. The same is true for forums, or any of the other tools you have installed. You can even link to tickets in a subproject with `[subproject.tickets:#123]`.

[MyPage]
[developerwiki:MyPage]
[#123]
[tickets:#123]
No example output is available for this one because it only works on real artifacts. Try it in your project!

Text
Use * or _ to emphasize things:

*this is in italic*  and _so is this_

**this is in bold**  and __so is this__

***this is bold and italic***  and ___so is this___
Output:

this is in italic and so is this

this is in bold and so is this

this is bold and italic and so is this

You can strike through text using HTML like this:

<s>this is strike through text</s>
Output:

this is strike through text

Just write paragraphs like in a text file and they will display how
you would expect.  A blank line separates paragraphs.

So this is a new paragraph. But any text on adjacent lines
will all end up
in the same paragraph.
Output:

Just write paragraphs like in a text file and they will display how
you would expect. A blank line separates paragraphs.

So this is a new paragraph. But any text on adjacent lines
will all end up
in the same paragraph.

Blockquotes
Use the > character in front of a line, just like in email

> Use it if you're quoting a person, a song or whatever.

> You can use *italic* or lists inside them also.
And just like with other paragraphs,
all of these lines are still
part of the blockquote, even without the > character in front.

To end the blockquote, just put a blank line before the following
paragraph.

You can use italic or lists inside them also. And just like with other paragraphs, all of these lines are still part of the blockquote, even without the > character in front.

To end the blockquote, just put a blank line before the following
paragraph.

Preformatted Text
If you want some text to show up exactly as you write it, without Markdown doing anything to it, just indent every line by at least 4 spaces (or 1 tab).

    This line won't *have any markdown* formatting applied.
    I can even write HTML and it will show up as text.
    This is great for showing program source code, or HTML or even
    Markdown. this won't show up as HTML but
    exactly as you see it in this text file.

As a shortcut you can use backquotes to do the same thing while
inside a normal pargraph.  `This won't be *italic* or **bold**
at all.`
Output:

This line won't *have any markdown* formatting applied.
I can even write HTML and it will show up as text.
This is great for showing program source code, or HTML or even
Markdown. this won't show up as HTML but
exactly as you see it in this text file.
As a shortcut you can use backquotes to do the same thing while
inside a normal pargraph. This won't be *italic* or **bold**
at all.

Lists
* an asterisk starts an unordered list
* and this is another item in the list
+ or you can also use the + character
- or the - character

To start an ordered list, write this:

1. this starts a list *with* numbers
+  this will show as number "2"
*  this will show as number "3."
9. any number, +, -, or * will keep the list going.
    * just indent by 4 spaces (or tab) to make a sub-list
        1. keep indenting for more sub lists
    * here i'm back to the second level
Output:

an asterisk starts an unordered list
and this is another item in the list
or you can also use the + character
or the - character
To start an ordered list, write this:

this starts a list with numbers
this will show as number "2"
this will show as number "3."
any number, +, -, or * will keep the list going.
just indent by 4 spaces (or tab) to make a sub-list
keep indenting for more sub lists
here i'm back to the second level
Tables
You can create tables using pipes and dashes like this:

  First Header  | Second Header
  ------------- | -------------
  Content Cell  | Content Cell
  Content Cell  | Content Cell
Output:

First Header Second Header
Content Cell Content Cell
Content Cell Content Cell

You can use markdown syntax within table cells for formatting:

  First Header   | Second Header
  -------------  | -------------
  *Content Cell* | Content Cell
  Content Cell   | Content Cell
Output:

First Header Second Header
Content Cell Content Cell
Content Cell Content Cell

You can also create tables using HTML code.

Headers
Just put 1 or more dashes or equals signs (--- or ===) below the title.

This is a huge header
==================

this is a smaller header
------------------
Output:

This is a huge header
this is a smaller header
Horizontal Rule
Just put three or more *'s or -'s on a line:

----------------
Output:

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

Or, you can use single spaces between then, like this:

* * *
Output:

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

or

- - - - - - -
Output:

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

Make sure you have a blank line above the dashes, though, or else:

you will get a header
---
Output:

you will get a header
Images
To include an image, just put a "!" in front of a text link:

![alternate text](https://sourceforge.net/images/icon_linux.gif)
Output:

The "alternate text" will show up if the browser can't load the image.

You can also use a title if you want, like this:

![tiny arrow](https://sourceforge.net/images/icon_linux.gif "tiny arrow")
Output:

To reference an attached image, just use the img macro. You can add more attributes:

[[img src=attached-image.jpg alt=foobar]]
Output:

Escapes
What if you want to just show asterisks, not italics?

* this shows up in italics: *a happy day*
* this shows the asterisks: \*a happy day\*
Output:

this shows up in italics: a happy day
this shows the asterisks: *a happy day*
The backslashes will disappear and leave the asterisks.

You can do the same with any of the characters that have a special meaning
for Markdown.

HTML tags may need to be escaped.  will be interpreted as a bold tag. Entity codes will be used. <foobar> isn't allowed and will be dropped, so you probably want to escape it:

this will be bold
you should escape <unknown> tags
< special entities work
&lt; if you want to escape it
Output:

this will be bold
you should escape <unknown> tags
< special entities work
< if you want to escape it

Individual ampersands (&) and less-than signs (<) are fine, they will be shown as expected.

More Headers
More ways of doing headers:

# this is a huge header #
## this is a smaller header ##
### this is even smaller ###
#### more small ####
##### even smaller #####
###### smallest still: `<h6>` header
Output:

this is a huge header
this is a smaller header
this is even smaller
more small
even smaller
smallest still:
 header
You can use up to 6 # characters at the beginning of the line.

Code Highlighting
The Code highlighting used in the newforge is based on (http://www.freewisdom.org/projects/python-markdown/CodeHilite). It follows the same syntax as regular Markdown code blocks, except that there are two ways to tell the highlighter what language to use for the code block.

If the first line of the codeblock contains a shebang, the language is derived from that and line numbers are used.

    #!/usr/bin/python
    # Code goes here ...
Output:

1
2 #!/usr/bin/python
# Code goes here ...

If the first line contains a shebang, but the shebang line does not contain a path (a single / or even a space) or If the first line begins with three or more colons, the text following the colons identifies the language. In both cases, the first line is removed from the code block before processing.

    :::python
    # Code goes here ...
Output:

# Code goes here ...
You can also designate a code block by surrounding it with lines of tildes. The type of code highlighting to apply will be inferred based on the code within, or you can specify like above.

~~~~~~
My code
~~~~~~
Output:

My code
Includes
You can embed another wiki page directly:

[[include ref=SamplePage]]
No example output is available for this one because it only works on real wiki pages. Try it in your wiki!

Neighborhood Notifications
You can list updates from all projects in a neighborhood by tool type. Max_number (default is 5) and sort (default is pubdate) are optional:

[[neighborhood_feeds tool_name=Wiki max_number=10 sort=pubdate]]
Neighborhood Blog Posts
You can view blog posts from all projects in a neighborhood. Max_number (default is 5) and sort (default is timestamp) are optional:

[[neighborhood_blog_posts max_number=10 sort=timestamp]]
Project Blog Posts
You can view blog posts from all blogs in a project. Max_number (default is 5), mount point (leave empty to view posts from all blog tools in a project), and sort (default is timestamp) are optional:

[[project_blog_posts max_number=10 sort=timestamp mount_point=news]]
Download Button
You can display a download button that links to the best download available for the active project. Please note that if you use this macro and there is no download associated with your project, the button will not appear.

[[download_button]]
Project Screenshots
You can show all the screenshots for the current project as thumbnails that are linked to the full-size image.

[[project_screenshots]]
Thanks
Thanks to John Gruber and Aaron Swartz for creating Markdown.

This page is based on some examples from Greg Schueler<EMAIL_ADDRESS>

branch_name: refs/heads/source

extension: markdown


text:
## Production Docker Image

This image is a lightweight version of the dev_vpp_agent image. It contains:

- the `vpp-agent`, `agentctl` and `vpp-agent-ctl` binaries
- installed VPP ready to be used

### Getting a pre-built image from Dockerhub
For a quick start with the VPP Agent, you can use pre-build Docker images with
the Agent and VPP on [Dockerhub](https://hub.docker.com/r/ligato/vpp-agent/).
```
docker pull ligato/vpp-agent
```

### Building locally
At first you need to have built of downloaded the `dev_vpp_agent` image.
To build the production image on your local machine, type:
```
./build.sh
```
This will build `prod_vpp_agent` image with agent and vpp files taken from dev image.

#### Verifying a created image
You can verify the newly built image as follows:

```
docker images
```

You should see something this:

```
REPOSITORY                                            TAG                 IMAGE ID            CREATED             SIZE
prod_vpp_agent                                        latest              e33a5551b504        7 days ago          404 MB
...
```
Get the details of the newly built image:

```
docker image inspect prod_vpp_agent
docker image history prod_vpp_agent
```

#### Shrinking the Image
Prod_vpp_agent image can be shrunk by typing command:

```
./shrink.sh
```

This will build a new image with the name `prod_vpp_agent_shrink` which
has removed installation-related files (about 150MB). It is using the docker
export and import commands, but due to a [Docker issue][1] it will fail on
dockers older than 1.13.

```
REPOSITORY                                            TAG                 IMAGE ID            CREATED             SIZE
prod_vpp_agent_shrink                                 latest              446b271cce26        2 days ago          257 MB
prod_vpp_agent                                        latest              e33a5551b504        2 days ago          404 MB

```
---

### Starting the Image
By default, the VPP & the Agent processes will be started automatically
in the container. This is useful, for example, in deployments with Kubernetes,
as described in this [README](../k8s/README.md). However, this option is
not really required for development purposes. This default behavior can
be overridden by specifying another container entrypoint, e.g. bash, as
we do in the following steps described below.

To start the locally built image, type:
```
sudo docker run -it --name vpp_agent --privileged --rm prod_vpp_agent bash
```

To start the downloaded pre-built image, type:
```
docker run -it --name vpp-agent --rm ligato/vpp-agent
```

To open another terminal:
```
sudo docker exec -it vpp_agent bash
```

### Running VPP and the Agent
You can use the image the same way as the development image, see this
[README](../dev_vpp_agent/README.md).

[1]: https://github.com/moby/moby/issues/26173

repository: lukasmacko/c-vpp

repo_name: lukasmacko/c-vpp


text:
# kiwi.vim

Syntax highlighting for the [Kiwi](https://github.com/allending/Kiwi)
Objective-C test framework.

## Installation

### With [Vundle](https://github.com/gmarik/vundle)

Add:

```
Bundle 'Keithbsmiley/kiwi.vim'
```

To your `.vimrc` and run `BundleInstall` from within vim or `vim
+BundleInstall +qall` from the command line

### With [Pathogen](https://github.com/tpope/vim-pathogen)

```
cd ~/.vim/bundle
git clone https://github.com/Keithbsmiley/kiwi.vim.git
```

### Setup

You can set the syntax for a file manually with `set syntax=kiwi` I
recommend you do this in your `.vimrc` detecting your typical test
filename.

```
autocmd BufNewFile,BufRead *Spec.m setlocal syntax=kiwi foldmethod=syntax
```

This changes the `syntax` to `kiwi` whenever a file named `*Spec.m` is
read or written (written sets the syntax correctly for newly created
files) You may also have to set the default `filetype` to Objective-C. I
use something like:

```
autocmd BufNewFile,BufRead *.h,*.m,*.pch setlocal filetype=objc
```

You can also install
[cocoa.vim](https://github.com/msanders/cocoa.vim/) which adds some
Objective-C highlighting features (automatically used by kiwi.vim if
it's accessible).

### Known issues

If you find any other issues or have any recommendations on how to solve
these let me know via issues/pull requests


text:
[![Build Status](https://travis-ci.org/maropu/hivemall-spark.svg?branch=master)](https://travis-ci.org/maropu/hivemall-spark)
[![License](http://img.shields.io/:license-Apache_v2-blue.svg)](https://github.com/maropu/hivemall-spark/blob/master/LICENSE)

This is a simple wrapper implementation of [Hivemall](https://github.com/myui/hivemall/) for Spark.
This can make highly scalable machine learning algorithms available in DataFrame and HiveContext.

Quick Installation
--------------------

```
// Fetch an initialization script for hivemall-spark
# wget https://raw.githubusercontent.com/maropu/hivemall-spark/master/scripts/ddl/define-udfs.sh

// Download Spark-v1.5.1 from 'http://spark.apache.org/downloads.html' and
// invoke an interactive shell
# $SPARK_HOME/bin/spark-shell --packages maropu:hivemall-spark:0.0.6

scala> :load define-udfs.sh
```

Hivemall in DataFrame
--------------------
[DataFrame](https://spark.apache.org/docs/latest/sql-programming-guide.html#dataframes) is a distributed collection
of data with names, types, and qualifiers.
To apply Hivemall fuctions in DataFrame, you type codes below;

```
// Assume that an input format is as follows:
//   1.0,[1:0.5,3:0.3,8:0.1]
//   0.0,[2:0.1,3:0.8,7:0.4,9:0.1]
//   ...
scala> val trainRdd = sc.textFile(...).map(HmLabeledPoint.parse)

scala> :paste

sqlContext.createDataFrame(trainRdd)
  .train_logregr(add_bias($"feature"), $"label")
  .groupby("feature")
  .agg("weight"->"avg")
```

More details can be found in [tutorials](./tutorials).

Hivemall in HiveContext
--------------------
For those try Hivemall in [HiveContext](https://spark.apache.org/docs/latest/sql-programming-guide.html#hive-tables),
run a script to register the user-defined functions of Hivemall in spark-shell and
say a SQL statements as follows;

```
scala> :paste

sql("
  SELECT feature, AVG(weight) AS weight
    FROM (
      SELECT train_logregr(add_bias(features), label AS(feature, weight)
        FROM trainTable
    ) model
    GROUP BY feature")
```

Hivemall in Spark Streaming
--------------------
Spark Streaming is an extension of the core Spark API that enables scalable,
high-throughput, fault-tolerant stream processing of live data streams.
A Hivemall model built from a batch of training data can be easily
applied into these streams;

```
// Assume that an input streaming format is as follows:
//   1.0,[1:0.5,3:0.3,8:0.1]
//   0.0,[2:0.1,3:0.8,7:0.4,9:0.1]
//   ...
scala> val testData = ssc.textFileStream(...).map(LabeledPoint.parse)

scala> :paste

testData.predict { case testDf =>
  // Explode features in input streams
  val testDf_exploded = ...

  val predictDf = testDf_exploded
    .join(model, testDf_exploded("feature") === model("feature"), "LEFT_OUTER")
    .select($"rowid", ($"weight" * $"value").as("value"))
    .groupby("rowid").sum("value")
    .select($"rowid", sigmoid($"SUM(value)"))

  predictDf
}

```

Support Status
--------------------
Hivemall v0.4.1-alpha.6 is currently incorporated in hivemall-spark and the most functions can be available in HiveContext.
On the other hand, functions listed below are available in DataFrame:

* regression

* binary/multiclass classification

* nearest neighbors

* some utility functions

API Documentations
--------------------
TBW

System Requirements
--------------------

* Spark 1.6.1

Presentations
------------

 * [Hivemall Meetup#1](http://eventdots.jp/event/458208) - [Slide](http://www.slideshare.net/maropu0804/20150512-hivemall-meetup1)

 * [Cloudera World Tokyo 2015](https://groups.google.com/forum/#!topic/hadoop-jp/ZanMFB3F4LQ) - [Slide](http://www.slideshare.net/maropu0804/cloudera-world-tokyo-2015)

TODO
--------------------

* Support python APIs for Hivemall