From beb19b9277bece30cafbb67aa9b347f0288fab3f Mon Sep 17 00:00:00 2001
From: James Molet <jmolet@redhat.com>
Date: May 22 2018 15:07:43 +0000
Subject: adding docker compose


---

diff --git a/docker/client_secrets.json b/docker/client_secrets.json
new file mode 100644
index 0000000..1b0dd62
--- /dev/null
+++ b/docker/client_secrets.json
@@ -0,0 +1,11 @@
+{
+    "web": {
+        "redirect_uris": ["http://localhost:5004/"],
+        "token_uri": "https://iddev.fedorainfracloud.org/openidc/Token",
+        "auth_uri": "https://iddev.fedorainfracloud.org/openidc/Authorization",
+        "client_id": "D-e69a1ac7-30fa-4d18-9001-7468c4f34c3c",
+        "client_secret": "qgz8Bzjg6nO7JWCXoB0o8L49KfI5atLF",
+        "userinfo_uri": "https://iddev.fedorainfracloud.org/openidc/UserInfo",
+        "token_introspection_uri": "https://iddev.fedorainfracloud.org/openidc/TokenInfo"
+    }
+}
diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml
new file mode 100644
index 0000000..080333e
--- /dev/null
+++ b/docker/docker-compose.yml
@@ -0,0 +1,69 @@
+version: '2.1'
+services:
+  rdb:
+    image: postgres:9.5.2
+    restart: always
+    environment:
+      POSTGRES_USER: resultsdb
+      POSTGRES_PASSWORD: resultsdb
+      POSTGRES_DB: resultsdb
+      POSTGRES_INITDB_ARGS: "--auth='ident' --auth='trust'"
+    healthcheck:
+      test: ["CMD-SHELL", "pg_isready -U postgres"]
+      interval: 30s
+      timeout: 30s
+      retries: 3
+
+  resultsdb:
+    image: "docker-registry.engineering.redhat.com/factory2/resultsdb:latest"
+    volumes:
+      - ./resultsdb-settings.py:/etc/resultsdb/settings.py:ro,Z
+      - ./resultsdb.conf:/etc/httpd/conf.d/resultsdb.conf:ro,Z
+    ports:
+      - 5001:5001
+    depends_on:
+      rdb:
+        condition: service_healthy
+
+  wdb:
+    image: postgres:9.5.2
+    restart: always
+    environment:
+      POSTGRES_USER: waiverdb
+      POSTGRES_PASSWORD: waiverdb
+      POSTGRES_DB: waiverdb
+      POSTGRES_INITDB_ARGS: "--auth='ident' --auth='trust'"
+
+  waiverdb:
+    image: "docker-registry.engineering.redhat.com/factory2/waiverdb:latest"
+    environment:
+      DATABASE_PASSWORD: waiverdb
+      SECRET_KEY: waiverdb
+    entrypoint: /bin/sh -i -c "waiverdb wait-for-db && waiverdb db upgrade && python3-gunicorn --bind 0.0.0.0:5004 --access-logfile=- waiverdb.wsgi:app"
+    volumes:
+      - ./waiverdb-settings.py:/etc/waiverdb/settings.py:ro,Z
+      - ./client_secrets.json:/etc/secret/client_secrets.json:ro,Z
+    ports:
+     - 5004:5004
+    user: '0'
+    depends_on:
+      - wdb
+
+  gmemcached:
+    image: "docker.io/modularitycontainers/memcached"
+
+  greenwave:
+    image: "quay.io/factory2/greenwave:latest"
+    volumes:
+      - ./greenwave-settings.py:/etc/greenwave/settings.py:ro,Z
+      - ../conf/policies/:/etc/greenwave/policies/:ro,Z
+    depends_on:
+      - gmemcached
+      - resultsdb
+      - waiverdb
+    ports:
+      - 8080:8080
+
+networks:
+  default:
+    driver: bridge
diff --git a/docker/greenwave-settings.py b/docker/greenwave-settings.py
new file mode 100644
index 0000000..dcd489d
--- /dev/null
+++ b/docker/greenwave-settings.py
@@ -0,0 +1,17 @@
+SECRET_KEY = 'greenwave'
+HOST = '0.0.0.0'
+PORT = 8080
+DEBUG = False
+POLICIES_DIR = '/etc/greenwave/policies/'
+WAIVERDB_API_URL = 'http://waiverdb:5004/api/v1.0'
+RESULTSDB_API_URL = 'http://resultsdb:5001/api/v2.0'
+CACHE = {
+  # 'backend': "dogpile.cache.null",
+  'backend': "dogpile.cache.memcached",
+  'expiration_time': 1,  # 1 is 1 second, keep to see that memcached
+                         # service is working
+  'arguments': {
+    'url': 'gmemcached:11211',
+    'distributed_lock': True
+  }
+}
diff --git a/docker/resultsdb-settings.py b/docker/resultsdb-settings.py
new file mode 100644
index 0000000..85471e1
--- /dev/null
+++ b/docker/resultsdb-settings.py
@@ -0,0 +1,11 @@
+SECRET_KEY = 'resultsdb'
+SQLALCHEMY_DATABASE_URI = 'postgresql+psycopg2://resultsdb:resultsdb@rdb:5432/resultsdb'
+FILE_LOGGING = False
+LOGFILE = '/var/log/resultsdb/resultsdb.log'
+SYSLOG_LOGGING = False
+STREAM_LOGGING = True
+RUN_HOST= '0.0.0.0'
+RUN_PORT = 5001
+MESSAGE_BUS_PUBLISH = False
+MESSAGE_BUS_PLUGIN = 'fedmsg'
+MESSAGE_BUS_KWARGS = {'modname': 'resultsdb'}
diff --git a/docker/waiverdb-settings.py b/docker/waiverdb-settings.py
new file mode 100644
index 0000000..3d4d568
--- /dev/null
+++ b/docker/waiverdb-settings.py
@@ -0,0 +1,9 @@
+DATABASE_URI = 'postgresql+psycopg2://waiverdb:waiverdb@wdb/waiverdb'
+HOST = '0.0.0.0'
+PORT = 5004
+#AUTH_METHOD = 'OIDC'
+AUTH_METHOD = 'dummy'
+MESSAGE_BUS_PUBLISH = False
+SUPERUSERS = ['dummy']
+#OIDC_CLIENT_SECRETS = '/etc/secret/client_secrets.json'
+RESULTSDB_API_URL = 'http://resultsdb:5001/api/v2.0'
diff --git a/docs/dev-guide.rst b/docs/dev-guide.rst
index d3ea10f..f60c478 100644
--- a/docs/dev-guide.rst
+++ b/docs/dev-guide.rst
@@ -55,6 +55,16 @@ The functional tests assume you have ResultsDB and WaiverDB git checkouts in
 find them in a different location by passing ``RESULTSDB`` or ``WAIVERDB``
 environment variables.
 
+Docker Compose
+==============
+
+For development you may want to bring up quick instances of Greenwave /
+WaiverDB / ResultsDB / all of the above. For more information on that see:
+
+.. toctree::
+   :maxdepth: 2
+
+   docker-compose
 
 Building the documentation
 ==========================
diff --git a/docs/docker-compose.rst b/docs/docker-compose.rst
new file mode 100644
index 0000000..b65a4f9
--- /dev/null
+++ b/docs/docker-compose.rst
@@ -0,0 +1,207 @@
+Docker-compose for greenwave
+===========================================
+
+Rationale
+---------
+
+I was tasked with getting the functional greenwave tests working with
+remote deployed servers in openshift.  During this task I ran into many
+bugs and it was hard to determine where the errors were happening.  I
+had to tackle errors simultaneously in openshift, my greenwave patches,
+the other services greenwave depends on, their dependencies, and the
+general issues with stuffing things into containers.  In its current
+state I see two extremes of developing:  1) running everything manually
+on your bare metal machines, 2) running a full deployment in openshift
+using the existing templates.  I needed a nice middle ground that let me
+iterate my changes quickly and isolate complexities to zero in on these
+bugs.  I found that docker-compose is a great solution to this.
+
+What is docker-compose
+----------------------
+
+There are many online resources explaining how to use this tool but I
+like to explain its purpose through its history.  Before kubernetes or
+indeed any docker's management tools were invented, you only had
+docker's cli.  As the complexity of a microservice topology
+increased, you started to have these increasingly longer docker commands
+that had to be run in a certain order.  They were usually stuffed in a
+bash script somewhere.  Version 0 of docker-compose was a simple python
+program that parsed a developer friendly yaml describing a toplogy into
+these commands.  With version 1, docker upstream picked up the project
+and bought it to feature parity with docker cli.  With version 2 they
+made use of the [then] new docker api, and added useful features such as
+health checks on containers.  Finally with version 3, they redesigned
+everything to be consistent with the docker-verse, and added docker
+swarm functionality which lets you deploy these compositions to a remote
+server.
+
+Where it fits into our current container usage
+----------------------------------------------
+
+With version 3 of docker-compose its use case overlaps with the things
+openshift currently does.  However I think its greatest utility lies
+along its original intention of being a great developer tool. It allows
+you to bring up many containers quickly and easily on your local
+machine.  I think it can co-exist with openshift as openshift gives you
+everything you need to run containers in a self contained environment
+and  it handles production concerns such as user and access management. 
+Docker-compose, on the other hand, provides bare-bone containers, and is
+potentially much easier to use.
+
+To illuminate this fact consider our openshift templates, as of this
+writing, require over 819 lines of code to deploy six containers; to
+launch them today you need to run a series of commands such as: 
+
+**maximum openshift**
+
+.. code-block:: console
+
+    oc process -f resultsdb/openshift/resultsdb-test-template.yaml -p TEST_ID=123 -p RESULTSDB_IMAGE=docker-registry.engineering.redhat.com/csomh/resultsdb:latest | oc apply -f - &&
+    oc process -f waiverdb/openshift/waiverdb-test-template.yaml -p TEST_ID=123 -p WAIVERDB_APP_VERSION=latest | oc apply -f - &&
+    oc process -f greenwave/openshift/greenwave-test-template.yaml -p TEST_ID=123 -p GREENWAVE_IMAGE=quay.io/factory2/greenwave:latest | oc apply -f
+
+In comparison, this same thing is accomplished with a single
+docker-compose.yml in about 70 lines with the command
+``docker-compose up``.  This is because openshift templates are based
+off of kubernetes manifests.  These manifests are a direct dump of the
+state of a current running kubernetes and it contains mappings to all
+the objects needed in order to migrate between instances.  Due to that
+fact I don't think manifests were designed with ease of use in mind.
+Kubernetes itself has another project that aims to solve this developer
+usage called Charts. 
+
+Quick How To
+------------
+
+Installation
+~~~~~~~~~~~~
+
+To run docker-compose you need to be able to run the regular docker
+command line.  Once you have that working you can install compose with:
+
+``{yum|dnf|brew} install docker-compose``
+
+You now can write a docker-compose.yml.  See the `docker-compose reference`_
+for a full description, but for the purposes of greenwave I will
+use the example files in \ ``greenwave/docker/``.
+
+The first thing you will notice is that each of the
+resultsdb/waiverdb/greenwave configs are in separate files and not
+in-lined into the template.  This means you can edit them quickly in
+your favorite editor with the correct syntax highlighting, and not have
+to worry about conflicting yaml indentation or any weird jinja snafus as
+you would in an openshift template.
+
+docker-compose.yml format
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+First section of the file is the version.
+
+**docker-compose.yml**
+
+.. code-block:: yaml
+
+    version: '2.1'
+
+I selected this version because it gives me a little more control
+over local running containers (health checks) and I don't need the docker
+swarm functionality of version 3.
+
+**docker-compose-yml**
+
+.. code-block:: yaml
+
+    services:
+      rdb:
+        image: postgres:9.5.2
+        restart: always
+        environment:
+          POSTGRES_USER: resultsdb
+          POSTGRES_PASSWORD: resultsdb
+          POSTGRES_DB: resultsdb
+          POSTGRES_INITDB_ARGS: "--auth='ident' --auth='trust'"
+        healthcheck:
+          test: ["CMD-SHELL", "pg_isready -U postgres"]
+          interval: 30s
+          timeout: 30s
+          retries: 3
+
+This defines what containers are run.  The first container, \ ``rdb``, is
+an off the shelf postgres from the docker hub.  It is set to restart
+itself on failures, and it has some basic settings which are set through
+environment variables as is docker best practice.  It also has a simple
+health check which is shell command that checks if a postgres server is
+running.  Note that the this container is "pingable" from any other
+container simply by running: ``ping rdb``. 
+
+**docker-compose.yml**
+
+.. code-block:: yaml
+
+      resultsdb:
+        image: "docker-registry.engineering.redhat.com/factory2/resultsdb:latest"
+        volumes:
+          - ./resultsdb-settings.py:/etc/resultsdb/settings.py:ro,Z
+          - ./resultsdb.conf:/etc/httpd/conf.d/resultsdb.conf:ro,Z
+        ports:
+          - 5001:5001
+        depends_on:
+          rdb:
+            condition: service_healthy
+
+ 
+
+The second service is ``resultsdb``.  Its running our own built
+resultsdb image.  Note here that we don't have to actually push an image
+anywhere, we can reuse a local image simply by supplying the appropriate
+name.  We are mounting resultsdb's config files in as volumes.  The
+config files are at the same level as there docker-compose.yml, and they
+are being mounted to the proper locations on the resultsdb server.  The
+ports section here simply exposes port 5001 to my development box's
+5001.  This means resultsdb is reachable from my own terminal
+at \ ``localhost:5001``.   Finally this service depends on its database,
+and the \ ``depends_on`` directive tells docker-compose to always start
+the rdb container first, and in this case, wait for it to boot properly
+before starting resultsdb.
+
+This continues on for the waiverdb and greenwave services, and I will
+omit their walk through for brevity, unless someone asks.
+
+Using docker-compose
+~~~~~~~~~~~~~~~~~~~~
+
+Here is my selection of useful docker-compose commands.  There are many
+more and you can do most the things regular docker gives you.
+
+**docker-compose cli**
+
+.. code-block:: console
+
+    # start in the right directory
+    cd wherever/greenwave/docker/
+
+    # give me all services
+    docker-compose up
+
+    # run the services as a daemon in the background
+    docker-compose up -d
+
+    # kill everything
+    docker-compose down
+
+    # give me just a resultsdb and a waiverdb and their dependent services
+    docker-compose up resultsdb waiverdb
+
+    # screw it, give me a bash shell on the waiverdb so I can poke things
+    docker-compose exec waiverdb /bin/bash
+
+    # give me the a log of all the greenwave events
+    docker-compose logs greenwave
+
+If you were for example developing greenwave and running it on your own
+(invoking it manually) you might try setting
+``WAIVERDB_API_URL = 'http://localhost:5004/api/v1.0'`` and
+``RESULTSDB_API_URL = 'http://localhost:5001/api/v2.0'`` and then
+running: ``docker-compose up -d resultsdb waiverdb``
+
+.. _docker-compose reference: https://docs.docker.com/compose/compose-file/compose-file-v2/
\ No newline at end of file
diff --git a/functional-tests/conftest.py b/functional-tests/conftest.py
index 5774b49..504ffe2 100644
--- a/functional-tests/conftest.py
+++ b/functional-tests/conftest.py
@@ -162,7 +162,9 @@ def greenwave_server(tmpdir_factory, resultsdb_server, waiverdb_server):
                 'expiration_time': 300,
                 'arguments': {'filename': %r},
             }
-            """ % cache_file.strpath))
+            RESULTSDB_API_URL = '%sapi/v2.0'
+            WAIVERDB_API_URL = '%sapi/v1.0'
+            """ % (cache_file.strpath, resultsdb_server, waiverdb_server)))
 
         # We also update the config file for *this* process, as well as the server subprocess,
         # because the fedmsg consumer tests actually invoke the handler code in-process.

