Skip to content

Latest commit

 

History

History
964 lines (647 loc) · 31.1 KB

README.md

File metadata and controls

964 lines (647 loc) · 31.1 KB

teaster

Teaster: automate your dirty tester work and take time for a relaxing tea.

alt text

Auto Installation

  • sudo zypper in docker
  • sudo zypper in docker-compose
  • sudo systemctl start docker

finally run docker-compose upinto the root dir

Manual Installation

You can install all the necessary parts manually :)

Please, follow the below instructions

Install rabbitmq

sudo zypper in rabbitmq-server rabbitmq-server-plugins

sudo systemctl start rabbitmq-server

sudo rabbitmq-plugins enable rabbitmq_management

Install docker

sudo zypper in docker

Set conf for celery tasks

sudo rabbitmqctl add_user celery celery

sudo rabbitmqctl add_vhost celery

sudo rabbitmqctl set_user_tags celery celery

sudo rabbitmqctl set_permissions -p celery celery ".*" ".*" ".*"

Setup a dev env

click here

Activate your dev env and install all the deps

antonio@linux-h1g7:~/dev/teaster> workon teaster

(teaster) antonio@linux-h1g7:~/dev/teaster> sudo pip install -r requirements.txt

Run and test the system

⚠️ teaster is just a POC and it is in the early stage of its hard life. Does not exist any validation for the input requests yet and unit tests cover just a little part of the entire codebase. So what teaster does well untill now is: it crashes 💥 and make you feel frustated :)

Create a couple

See all the steps below

Run a input interface

(teaster) ➜  teaster git:(master) ✗ python main.py 
 * Serving Flask app "main" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 208-391-154

Run a consumer

Before running a consumer, be sure to have rabbitmq-server up and running

sudo systemctl status rabbitmq-server

then run your consumer

(teaster) ➜  teaster git:(master) ✗ python consumer_leap.py 
 [Consumer] registering a consumer to teaster localhost
 [Consumer] response registration 
{
    "id": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b", 
    "product": "leap:42.3", 
    "runenv": "docker"
}

registration result 
{
    "id": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b", 
    "product": "leap:42.3", 
    "runenv": "docker"
}
consumer, connecting to rabbit: 
{
    "exchange": "test", 
    "exchange_type": "direct", 
    "host": "localhost", 
    "queue": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b", 
    "routing": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b", 
    "vhost": null, 
    "wait_for_rabbit": false
}
 [*] Waiting for messages. To exit press CTRL+C

As you can see above, what a consumer does:

  1. it registers itself to the system

    During this phase an id is generated by the system for the consumer. You can use this id to send requests to that specific consumer. A queue named with that id is created on rabbitmq.

  2. It connects to the new created queue (see id before)

  3. It waits for a new message

You can verify that a consumer now exists from:

  1. rabbitmq side
(teaster) ➜  teaster git:(master) ✗ sudo rabbitmqctl list_consumers -p /
Listing consumers
6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b	<[email protected]>
  1. teaster side
(teaster) ➜  teaster git:(master) ✗ curl http://localhost:5000/consumers
{
    "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b": {
        "id": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b", 
        "product": "leap:42.3", 
        "runenv": "docker"
    }
}

Run celery input interface

It accepts building request for your celery tasks

(teaster) ➜  teaster git:(master) ✗ python icelery.py
 * Serving Flask app "icelery" (lazy loading)
 * Environment: production
   WARNING: Do not use the development server in a production environment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://0.0.0.0:6000/ (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 208-391-154

Run your celery workers

Be sure to have docker up and running

sudo systemctl status docker

(teaster) ➜  teaster git:(master) ✗ celery worker -A icelery.celery --loglevel=info
 
 -------------- celery@linux-peu5 v4.2.2 (windowlicker)
---- **** ----- 
--- * ***  * -- Linux-4.12.14-lp150.12.16-default-x86_64-with-glibc2.2.5 2019-03-31 12:50:41
-- * - **** --- 
- ** ---------- [config]
- ** ---------- .> app:         icelery:0x7fbf0ac45250
- ** ---------- .> transport:   amqp://celery:**@localhost:5672/celery
- ** ---------- .> results:     disabled://
- *** --- * --- .> concurrency: 4 (prefork)
-- ******* ---- .> task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- 
 -------------- [queues]
                .> celery           exchange=celery(direct) key=celery
                

[tasks]
  . icelery.build_docker

[2019-03-31 12:50:42,123: INFO/MainProcess] Connected to amqp://celery:**@127.0.0.1:5672/celery
[2019-03-31 12:50:42,408: INFO/MainProcess] mingle: searching for neighbors
[2019-03-31 12:50:43,705: INFO/MainProcess] mingle: all alone
[2019-03-31 12:50:43,757: INFO/MainProcess] celery@linux-peu5 ready.

Create a couple (submit your first request)

1 create and a new github/gitlab project

echo "# deleteme" >> README.md
git init
git add README.md
git commit -m "first commit"
git remote add origin https://github.com/kinderp/deleteme.git
git push -u origin master
  1. prepare a request
import requests

payload = {
        "id":"6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b",
        "provenv":["zypper --non-interactive in telnet","zypper --non-interactive in vim"], 
        "yourtag":"registry.gitlab.com/caristia/antonio_suse/new_image", 
        "reproducer":{
            "prova":"",
            "repo":"https://github.com/kinderp/deleteme.git"
        }

}

r = requests.post("http://localhost:5000/couples", json=payload)
  • id is the consumer's id you want to reach out
  • provenv is a list of commands to install your rpms (--non-ineteractive is important, teaster is not smart enough)
  • yourtag is the name of your image (it will be pushed into your docker registry)
  • reproducer.repo is the git url where teaster will commit a new Dockerfile for your runtime env

  1. input interface output

    • it receives the request and publishes that onto the correct queue using the id field
[CoupleList:post] arrived data: 
{
    "id": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b", 
    "provenv": [
        "zypper --non-interactive in telnet", 
        "zypper --non-interactive in vim"
    ], 
    "reproducer": {
        "prova": "", 
        "repo": "https://github.com/kinderp/deleteme.git"
    }, 
    "yourtag": "registry.gitlab.com/caristia/antonio_suse/new_image"
}
[CoupleList:post] producer, connecting to rabbit: 
{
    "exchange": "test", 
    "exchange_type": "direct", 
    "host": "localhost", 
    "queue": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b", 
    "routing": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b", 
    "vhost": null, 
    "wait_for_rabbit": false
}
 [*] Published message: {"provenv": ["zypper --non-interactive in telnet", "zypper --non-interactive in vim"], "reproducer": {"repo": "https://github.com/kinderp/deleteme.git", "prova": ""}, "yourtag": "registry.gitlab.com/caristia/antonio_suse/new_image", "id": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b"}
127.0.0.1 - - [31/Mar/2019 13:12:02] "POST /couples HTTP/1.1" 200 -

  1. consumer output
  • it just dequeues the request and creates a runtime source (a Dockerfile in this case)
  • it sends a building request for this Dockerfile to the celery interface
 [x] Received '{"provenv": ["zypper --non-interactive in telnet", "zypper --non-interactive in vim"], "reproducer": {"repo": "https://github.com/kinderp/deleteme.git", "prova": ""}, "yourtag": "registry.gitlab.com/caristia/antonio_suse/new_image", "id": "6dd47d81e014ad9de81161951814bf50e4e1246bb7a43404ffb84ab31ef7d18b"}'

FROM opensuse:42.3


WORKDIR /workdir
COPY . /workdir

RUN zypper --non-interactive in telnet && \ 
    zypper --non-interactive in vim 

CMD None
  1. celery input interface output
127.0.0.1 - - [31/Mar/2019 13:27:14] "POST /build_docker HTTP/1.1" 200 -
  1. worker output
[2019-03-31 13:27:14,130: WARNING/ForkPoolWorker-1] https://github.com/kinderp/deleteme.git
[2019-03-31 13:27:14,131: WARNING/ForkPoolWorker-1] 1232456abc
[2019-03-31 13:27:14,131: WARNING/ForkPoolWorker-1] opensuse
[2019-03-31 13:27:14,132: WARNING/ForkPoolWorker-1] ==Cloning...==
Username for 'https://github.com': kinderp
Password for 'https://[email protected]': 
[2019-03-31 13:27:25,422: WARNING/ForkPoolWorker-1] ==Building...==

... A lot of output ...

[2019-03-31 13:29:05,146: WARNING/ForkPoolWorker-1] {u'progressDetail': {}, u'aux': {u'Tag': u'latest', u'Digest': u'sha256:ec733ee8182c33da16543909fba2c74cec9cd84e7cd007b918a832c70d75c867', u'Size': 1156}}
[2019-03-31 13:29:05,147: INFO/ForkPoolWorker-1] Task icelery.build_docker[bd16221d-d4c0-4c21-b7d5-9adaf73029f8] succeeded in 111.017807808s: None

Verify the result

At the end of this process a new docker image is appeared

➜  deleteme git:(master) docker images|grep antonio_suse
registry.gitlab.com/caristia/antonio_suse/new_image   latest              bcf7e2ce44ed        5 minutes ago       238MB

A dockerfile has been pushed on deleteme project (in a new branch named opensuse, it is a static name but it will be fixed)

➜  deleteme git:(master) ls
README.md

➜  deleteme git:(master) git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

➜  deleteme git:(master) git pull
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 5 (delta 2), reused 3 (delta 0), pack-reused 0
Unpacking objects: 100% (5/5), done.
From https://github.com/kinderp/deleteme
 * [new branch]      opensuse   -> origin/opensuse
Already up to date.

➜  deleteme git:(master) ls
README.md

➜  deleteme git:(master) git checkout opensuse 
Branch 'opensuse' set up to track remote branch 'opensuse' from 'origin'.
Switched to a new branch 'opensuse'

➜  deleteme git:(opensuse) ls
Dockerfile  README.md

➜  deleteme git:(opensuse) cat Dockerfile 

FROM opensuse:42.3


WORKDIR /workdir
COPY . /workdir

RUN zypper --non-interactive in telnet && \ 
    zypper --non-interactive in vim 

CMD None

The new image has been pushed on your personal registry so it's ready to be pulled from another machine In this case we just remove the image and re-pull it to verify

➜  deleteme git:(opensuse) docker rmi $(docker images -qa)
➜  deleteme git:(opensuse) docker images|grep antonio_suse

➜  deleteme git:(opensuse) docker login registry.gitlab.com

Login Succeeded
➜  deleteme git:(opensuse) docker pull registry.gitlab.com/caristia/antonio_suse/new_image
Using default tag: latest
latest: Pulling from caristia/antonio_suse/new_image
adec38add5d1: Already exists 
935c6b6c3290: Already exists 
545e84933fdc: Pull complete 
3c034a37c68e: Pull complete 
Digest: sha256:ec733ee8182c33da16543909fba2c74cec9cd84e7cd007b918a832c70d75c867
Status: Downloaded newer image for registry.gitlab.com/caristia/antonio_suse/new_image:latest
➜  deleteme git:(opensuse) docker run -it registry.gitlab.com/caristia/antonio_suse/new_image /bin/bash
9e7a756c12a5:/workdir # ls
Dockerfile  README.md

So a new couple (run env, prov env) has been correctly created

Create a triple

Now you have your runtime env for testing. It's time to create a reproducer.

➜  deleteme git:(opensuse) cat reproducer.sh 
#!/bin/bash

echo 'i am a reproducer :)'

and push it (remember that you are on opensuse branch)

➜  deleteme git:(opensuse) ✗ git add reproducer.sh 

➜  deleteme git:(opensuse) ✗ git commit -m"added reproducer"
[opensuse d723885] added reproducer
 1 file changed, 3 insertions(+)
 create mode 100644 reproducer.sh

➜  deleteme git:(opensuse) git push
Username for 'https://github.com': kinderp
Password for 'https://[email protected]': 
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 362 bytes | 362.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://github.com/kinderp/deleteme.git
   3fb0c41..d723885  opensuse -> opensuse

Now that you have a reproducer you can submit a triple creation request and teaster will put your reproducer on top of your runtime env.

create a request as below, be sure to use the correct consumer id and fill the reproducer.command field with the correct name of your reproducer on github (teaster is not smart enough to add x permission until now)

import requests

payload = {
        "id":"56b2479526326f276d6f426689f561f21c8563b561b2f4ba20f89895286f2dbf",
        "provenv":["zypper --non-interactive in telnet","zypper --non-interactive in vim"], 
        "yourtag":"registry.gitlab.com/caristia/antonio_suse/new_image", 
        "reproducer":{
            "command":"chmod u+x reproducer.sh && sh reproducer.sh",
            "repo":"https://github.com/kinderp/deleteme.git"
        }

}

r = requests.post("http://localhost:5000/triples", json=payload)

You will see a very similar output to the previous couple request. Let's verify that all has gone fine.

Verify the result

If you run your container this time without -it you will execute your reproducer, let's see.

(teaster) ➜  teaster git:(triple) ✗ docker run --name test_triple registry.gitlab.com/caristia/antonio_suse/new_image 
i am a reproducer :)

Your reproducer has been inserted on top of your runenv and now can be shared easily.

Delete test_triple container and the associated image (you should delete also the container created during couple phase)

(teaster) ➜  teaster git:(triple) ✗ docker rm test_triple
test_triple
teaster) ➜  teaster git:(triple) ✗ docker rmi $(docker images -qa)
Untagged: registry.gitlab.com/caristia/antonio_suse/new_image:latest
Untagged: registry.gitlab.com/caristia/antonio_suse/new_image@sha256:f7f13bc05cd6c39cbf1024f156e2fc4bdf8724e270b4afa59356cf8bb09f7b0c
Deleted: sha256:634af52888bcab13c3a8626ec8006550a096be4cbe577a1698fe29d1e7e91d33
Deleted: sha256:5e6c026602db588ad56499e002d618a8e570e51f17008fd7bf3d4fbb4d8c5b8f
Deleted: sha256:fa2859d62cb8b4f5afe685383add59355abef3b7ad2684d8308ca120e4828119
Deleted: sha256:8b3e40b03c3cf0e4d04ad92e29b83e69098e147e8a4db86dd20cfae767ffca05
Deleted: sha256:caccaf2c751098c32780b66ef022a0e3f2f62177cbd31f5835d7f0d827c08026
(teaster) ➜  teaster git:(triple) ✗ docker images|grep antonio_suse                                

pull and rerun your reproducer

(teaster) ➜  teaster git:(triple) ✗ docker pull registry.gitlab.com/caristia/antonio_suse/new_image 
Using default tag: latest
latest: Pulling from caristia/antonio_suse/new_image
adec38add5d1: Already exists 
935c6b6c3290: Already exists 
d3f94c2bd985: Pull complete 
bc5ba9e9ff9a: Pull complete 
Digest: sha256:f7f13bc05cd6c39cbf1024f156e2fc4bdf8724e270b4afa59356cf8bb09f7b0c
Status: Downloaded newer image for registry.gitlab.com/caristia/antonio_suse/new_image:latest

(teaster) ➜  teaster git:(triple) ✗ docker run --name test_triple_other_tester registry.gitlab.com/caristia/antonio_suse/new_image:latest
i am a reproducer :)

Good, we have a working reproducer and it can be shared easily. We are happy \o/ :)

Introduction

Here just some definitions to speak the same language.

As a tester your work can be summarized in these steps:

  1. Get instructions from bugzilla page and try to build a reprodcer.

    A reproducer can be:

    • a cli reproducer (a bash script or an openqa testmodule)
    • a gui reproducer (an openqa testmodule + needles)

    Any reproducer needs a runtime environment to be executed.

    A runtime environment can be:

    • a container
    • a virtual machine

    A runtime environment + reproducer can be packed in a automation environments.

    An automation environment contains:

    • a runtime environment
    • all the provisioned software (before or after). to be consistent we'll name that provisioning environment
    • a reproducer

    An automation environment can be represented by a tuple:

    (runtime env, provisioning env, reproducer)

    All the possible combinations of these three components create an automation environment:

    Cli automation environments

    • (container, packages before update, script bash)
    • (container, packages after update, script bash)
    • (container + openqa instance, packages before update, openqa testmodule)
    • (cotaniner + openqa instance, packages after update, openqa testmodule)
    • (vm, packages before update, script bash)
    • (vm, packages after update, script bash)
    • (vm + openqa instance, packages before update, openqa testmodule)
    • (vm + openqa instance, packages after update, openqa testmodule)

    Gui automation environments

    • (container + openqa instance, packages before update, openqa testmodule + needles)
    • (cotaniner + openqa instance, packages after update, openqa testmodule + needles)
    • (vm + openqam instance, packages before update, openqa testmodule + needles)
    • (vm + openqa instance, packages after update, openqa testmodule + needles)
  2. Provisioning of the runtime environment (and installation tests)

    We need to be sure that the packages we are testing can be installed on top of our runtime environment. We are helped on that by tools like mtui but sometimes it needs some manual work and anyway it's not a completely automated process.

  3. Reproducing

    Reproduce the bug before and after (update and downgrade) Even during this phase mtui is our friend.

  4. Comparison

In this scenario just only the first phase (the mental process to figure out the better reproducer) really requires an human intellectual intervention.

The same reproducer is applied (manually) to different products. So all the steps of the entire process are repeated by testers with a lof of wasting time.

As a tester before going through all the entire process i want:

Know if a tester has already worked on that bug, in other words if a reproducer for that particul bug already exists for other products. (We do that manually searching for a bug in qam.suse)

if it's the first time that bug is tested (no reproducer for that bug)

(a)

  1. Concentrate just only on the reproducer
  2. Get automagically a runtime env + a provisioning env (e.g. a container with all provisioned packages)
  3. Once finished creating the reproducer, pack all (run env, prov env, reproducer) and push that one somewheree and share with all other testers in the future. In other words we're creating the tuple, the automation environment.

if a reproducer already exists:

(b)

  1. Get automagically an automation environment with the testing package installed (provisioning) and the reproducer ready to be executed
  2. Chose the runtime environment i like (container or vm)
  3. Run the reproducer (before and after)
  4. Compare the results (before and after)

In the first case (a) we build an automation environment joining our reproducer,the packages and the runtime environment. In the second one (b) we use an automation envinronment to test our bugs.

Use Cases

  • Autoregister (uc#0)

    Actors:

       - A consumer: it wants to inform the system about its presence and capabilities. 
                     A consumer is able to handle only a runtime env and only a product
    

    Input:

       - (run env, product) e.g. (docker, sle12sp3)
    

    Output:

       - a consumer id. 
         The system assigns an id to the consumer. 
    

    Description:

       - Before starting its lifecycle the consumer needs to inform the system 
         about which particular run env and product it is able to handle
    
  • Search for a consumer (uc#1)

    Actors:

       - Started by guy: He wants to know if does exist a consumer able to handle (run env, product) 
                         for a prov env.
       - Tester        : same above.
    
       A consumer can handle only one run env and only one product.
       A prov env are the packages to test.
    

    Input:

       - (run env, product) e.g. (docker, sle12sp3)
    

    Output:

       - a consumer id or an error. 
    

    Description:

       -  Search for a consumer that is able to create a couple for a particular product
          and a particular run env.
       -  The system responds with a consumer id in case of success or some sort of error.
    
  • Search for a reproducer (uc#2)

    Actors:

       - Started by guy: He wants to know if already exist a reprodcuer for a bug.
       - Tester        : same above.
    

    Input:

       - (bug_id, reproducer_type) 
    

    Output:

       - (reproducer_id, link to the reproducer)
       
       link to a bash script
       link to a testmodule
       link to testmodule and needles
    

    Description:

       -  Search for a reproducer
       -  The system responds with a reproducer id and a link to view the reproducer or an error.
       -  The reproduer id will be used to forward the triple creation request 
          (run env, prov env, reproducer) to the correct consumer. 
          See above uc#1 to search for the correct consumer for a run env and a product 
    
  • Create a triple (uc#3)

    In this case the reproducer already exists. We got an id from #uc2.

    Actors:

       - Started by guy: He wants to create the triple 
                         (run env, prov env, reproducer) for a new update in the queue.
       - Tester        : He wants to create the couple 
                         (run env, prov env, reproducer) to investigate about something.
       - A consumer    : It knows how to handle that particular run env and product. 
                         It contacts the builder.
       - A builder     : It creates the triple: an automation env
    
       The first 2 actors must know:
       1. the consumer id   (from uc#1)
       2. the reproducer id (from uc#2)
    

    Input:

       - (consumer id, reproducer id, prov env) e.g. (1234, xxxxx, [a.x.y.z])
    

    Output:

       - An url poiting to (run env, prov env, reproducer). 
       
          A registry url:
          hashicorp/precise64
          opensuse/tumbleweed 
    

    Description:

       -  The first 2 actors submit the request to the consumer, using the correct id.
          The consumer creates or modifies the source (Dockerfile, Vagranfile) for 
          provisioning of the testing packages and reproducer. 
          Then the consumer forwards the modified source to the builder (destionation).
          The builder builds (run env, prov env, reproducer) 
          
    (Note) the building process will be an asynchronous process so we need some sort of notification.
    
  • Create a couple (uc#4)

    In this case the reproducer does not exist. We got an error from #uc2.

    Actors:

       - Started by guy: He wants to create the couple 
                         (run env, prov env) for a new update in the queue.
       - Tester        : He wants to create the couple 
                         (run env, prov env) to investigate about something.
       - A consumer    : It knows how to handle that particular run env and product. 
                         It contacts the builder.
       - A builder     : It creates the run env.
    
       The first 2 actors must know:
       1. the consumer id (from uc#1) 
    

    Input:

       - (consumer id, prov env) e.g. (1234, [a.x.y.z])
    

    Output:

       - An url poiting to (run env, prov env). 
       
          A registry url:
          hashicorp/precise64
          opensuse/tumbleweed 
    

    Description:

       -  The first 2 actors submit the request to the consumer, using the correct id.
          The consumer creates or modifies the source (Dockerfile, Vagranfile) 
          for provisioning of testing packages. 
          Then the consumer forwards the modified source to the builder (destionation).
          The builder builds (run env, prov env) 
          
    (Note) the building process will be an asynchronous process so we need some sort of notification.
    
  • Share a reproducer (uc#5)

    Actors:

       - Tester        : He wants to share a reproducer for a particular bug.
    

    Input:

       - (bug id, reproducer) 
    

    Output:

       - (link to the reproducer) or an error
       
       link to a bash script
       link to a testmodule
       link to testmodule and needles
    

    Description:

       -  The tester sends the reproducer.
          The system saves the reproducer somewhere and returns a link.
    

Class analysis

Some notes about classes and patterns

Class analysis for run time source creation

  1. We'll use a Factory Method to instance the concrete RuntimeSource
  2. We'll use a Adapter to create a RuntimeeSourceFeed concrete object from json data requests. In this way, we put all the creation logic into the adapter and we are free to change the internal interface holding the external one (flask reuqest) always the same.

  RuntimeSourceFeed: 

        it represents all the infos needed to feed Dockerfile or Vagrantfile templates.
        it is an abstract class and defines the interface for all the concrete RuntimeSourceFeed objects
        RuntimeSourceFeedDocker,RuntimeSourceFeedVagrant

  RuntimeSourceFeedDocker: it is a concrete class. 
                           it contains all the data needed to fill a Dockerfile Template


  RuntimeSourceFeedVagrant: it is a concrete class.
                            it contains all the data needed to fill a Vagrantfile Template

  RuntimeSource: 

        it is an abstract class and defines the interface for all the concrete RuntimeSource objects
        RuntimeSourceDocker,RuntimeSourceVagrant

        A runtime source concrete object is created by a RuntimeSourceCreator factory object from:
        1. A RuntimeSourceTemplate concrete object (template)
        2. A RuntimeSourceFeed concrete object     (data filling the gaps)
        We'll use jinja2 for templating.


  RuntimeSourceDocker: it is a concrete class. 
                       it implements RuntimeSource's interface. 
                       it represents a Dockerfile


  RuntimeSourceVagrant: it is a concrete class. 
                        it implements RuntimeSource's interface. 
                        it represents a Vagranfile

  RuntimeSourceTemplate: it is an abstract class.
                         it defines the interface for the templates object instances
                         RuntimeSourceTemplateDocker, RuntimeSourceTemplateVagrant


  RuntimeSourceTemplateDocker: 

  RuntimeSourceTemplateVagrant:

  RuntimeSourceCreator: it declares the factory method that creates a RuntimeSource object
                        In order to create a RuntimeSourceObject it needs:
                        1. A RuntimeSourceTemplate concrete object (template)
                        2. A RuntimeSourceFeed concrete object     (data filling the gaps)


  RuntimeSourceCreator: it defines the interface for the concrete runtime creator objects: 

  RuntimeSourceCreatorDocker: concrete creator for RuntimeSourceDocker objects
                              it overrides the RuntimeSourceCreator's factory method.
                              it to create a concrete RuntimeSourceDocker instance.

  RuntimeSourceCreatorVagrant: concrete creator for RuntimeSourceVagrant objects.
                               it overrides the RuntimeSourceCreator's factory method 
                               it creates a concrete RuntimeSourceVagrant instance.

Factory Method's actors

  • Product: RuntimeSource
  • ConcreteProduct: RuntimeSourceDocker, RuntimeSourceVagrant
  • Crator: RuntimeSourceCreator
  • ConcreteCreator : RuntimeSourceCreatorDocker, RuntimeSourceCreatorVagrant

What does teaster do for you?

  1. accept requests to create the couple (runtime environment, provisioning environment) and publish that one somewhere
  2. accept requests to create the tuple (runtime environment, provisioning environment, reproducer). So it create an automation env and make it available to the tester.

Who create the couple and the triple? Consumer!

it's a consumer. A consumer get in input a request for an environment and works to produce in output the required env. A consumer knows how to handle only a specific product. So sle15 and sle12sp3 need two different consumer.

What Does a consumer know?

  • a source

    it contain infos to create the required environment.

    For example:

    if the required env is a container a source will be the url for a Dockerfile if the required env is a vm it will be the Vagranfile (Docker is a specifi instance of a container runtime env and Vagrant it is for vm runtime env. any instance of a runtime env cuold be taken in consideration)

  • a destination

    an url to build the environment.

    For example:

    if the required env is a container, a url will point to a service that will build the image (from the Dockerfile) for us.

The builder

it builds our environment, it is bound to the url knokn by the consumer. It get infos (Dockerfile, Vagrantfile) from the consumer.

For example:

  • docker builder
  • vagrant builder

Set up dev environment

  1. pip install virtualenvwrapper

  2. mkdir $HOME/dev

  3. sudo find / -name virtualenvwrapper.sh

  4. Add three lines to your shell startup file (.bashrc, .profile, etc.) to set the location where the virtual environments should live, the location of your development project directories, and the location of the script installed with this package:

export WORKON_HOME=$HOME/.virtualenvs
export PROJECT_HOME=$HOME/dev
source /usr/local/bin/virtualenvwrapper.sh # use the path obtained at point 3
  1. cd $HOME/dev; git clone https://github.com/kinderp/teaster.git; cd $HOME/dev/teaster

  2. mkvirtualenv teaster

Activate and deativate your env using workon and deactivate commands, see here for details https://virtualenvwrapper.readthedocs.io/en/latest/install.html

Set up the infrastructure

  1. Install docker and docker-compose
  2. cd $HOME/dev/teaster
  3. docker-compose up