Merge pull request #2 from tcpcloud/compose

Introduce docker.client.compose
diff --git a/README.rst b/README.rst
index d2c20f5..ce18ed7 100644
--- a/README.rst
+++ b/README.rst
@@ -27,6 +27,11 @@
 Client
 ------
 
+Container
+~~~~~~~~~
+
+.. code-block:: yaml
+
     docker:
       client:
         container:
@@ -43,6 +48,35 @@
             volumes:
               - /srv/volumes/jenkins:/var/jenkins_home
 
+Compose
+~~~~~~~
+
+Install docker-compose using Pip (default is distribution package)
+
+.. code-block:: yaml
+
+    docker:
+      client:
+        compose:
+          django_web:
+            # Run up action, any positional argument to docker-compose CLI
+            # If not defined, only docker-compose.yml is generated
+            status: up
+            environment:
+              SOMEVAR: somevalue
+            service:
+              db:
+                image: postgres
+              web:
+                image: djangoapp
+                volumes:
+                  - /srv/volumes/django:/srv/django
+                ports:
+                  - 8000:8000
+                depends_on:
+                  - db
+
+
 Registry
 --------
 
diff --git a/docker/client.sls b/docker/client.sls
new file mode 100644
index 0000000..0ed5638
--- /dev/null
+++ b/docker/client.sls
@@ -0,0 +1,14 @@
+{% from "docker/map.jinja" import client with context %}
+{%- if client.enabled %}
+
+include:
+  - docker.client.container
+  {%- if client.compose is defined %}
+  - docker.client.compose
+  {%- endif %}
+
+docker_python:
+  pkg.installed:
+    - names: {{ client.pkgs }}
+
+{%- endif %}
diff --git a/docker/client/compose.sls b/docker/client/compose.sls
new file mode 100644
index 0000000..e1ee3a7
--- /dev/null
+++ b/docker/client/compose.sls
@@ -0,0 +1,78 @@
+{% from "docker/map.jinja" import client with context %}
+
+include:
+  - docker.client
+
+{%- if client.compose.source.engine == 'pkg' %}
+docker_compose:
+  pkg.installed:
+    - names: {{ client.compose.source.pkgs }}
+{%- elif client.compose.source.engine == 'pip' %}
+docker_compose_python_pip:
+  pkg.installed:
+    - name: python-pip
+
+docker_compose:
+  pip.installed:
+    - name: docker-compose
+    - require:
+      - pkg: docker_compose_python_pip
+{%- endif %}
+
+{%- for app, compose in client.compose.iteritems() %}
+{%- if compose.service is defined %}
+
+docker_{{ app }}_dir:
+  file.directory:
+    - name: {{ client.compose.base }}/{{ app }}
+    - makedirs: true
+
+docker_{{ app }}_compose:
+  file.managed:
+    - name: {{ client.compose.base }}/{{ app }}/docker-compose.yml
+    - source: salt://docker/files/docker-compose.yml
+    - template: jinja
+    - defaults:
+        app: {{ app }}
+        service: {{ compose.service }}
+    - require:
+        - file: docker_{{ app }}_dir
+
+{%- if compose.environment is defined %}
+docker_{{ app }}_env:
+  file.managed:
+    - name: {{ client.compose.base }}/{{ app }}/.env
+    - source: salt://docker/files/docker-env
+    - template: jinja
+    - user: {{ compose.user|default("root") }}
+    - mode: 640
+    - defaults:
+        env: {{ compose.environment }}
+    - require:
+        - file: docker_{{ app }}_dir
+{%- else %}
+docker_{{ app }}_env:
+  file.absent:
+    - name: {{ client.compose.base }}/{{ app }}/.env
+{%- endif %}
+
+{%- if compose.status is defined %}
+docker_{{ app }}_{{ compose.status }}:
+  cmd.run:
+    - name: '{% if client.compose.source.engine == 'pip' %}/usr/local/bin/{%
+    endif %}docker-compose {{ compose.status }} -d'
+    - cwd: {{ client.compose.base }}/{{ app }}
+    - user: {{ compose.user|default("root") }}
+    - require:
+        {%- if client.compose.source.engine == 'pkg' %}
+        - pkg: docker_compose
+        {%- elif client.compose.source.engine == 'pip' %}
+        - pip: docker_compose
+        {%- endif %}
+    - watch_in:
+      - file: docker_{{ app }}_env
+      - file: docker_{{ app }}_compose
+{%- endif %}
+
+{%- endif %}
+{%- endfor %}
diff --git a/docker/client/container.sls b/docker/client/container.sls
index cd9d914..53758f3 100644
--- a/docker/client/container.sls
+++ b/docker/client/container.sls
@@ -3,7 +3,7 @@
 include:
   - docker.client
 
-{%- for name, container in client.container.items() %}
+{%- for name, container in client.get('container', {}).iteritems() %}
   {%- set id = name %}
   {%- set required_containers = [] %}
 
diff --git a/docker/files/docker-compose.yml b/docker/files/docker-compose.yml
new file mode 100644
index 0000000..eb92739
--- /dev/null
+++ b/docker/files/docker-compose.yml
@@ -0,0 +1,12 @@
+version: '2'
+services:
+  {%- for name, srv in service.iteritems() %}
+  {{ name }}:
+    {%- for key, value in srv.iteritems() %}
+    {{ key }}: {{ value }}
+    {%- endfor %}
+  {%- endfor %}
+
+{#-
+  vim: syntax=jinja
+-#}
diff --git a/docker/files/docker-env b/docker/files/docker-env
new file mode 100644
index 0000000..552a8ee
--- /dev/null
+++ b/docker/files/docker-env
@@ -0,0 +1,7 @@
+{%- for key, value in env.iteritems() %}
+{{ key }}="{{ value }}"
+{%- endfor %}
+
+{#-
+  vim: syntax=jinja
+-#}
diff --git a/docker/map.jinja b/docker/map.jinja
index 40e83c5..d475371 100644
--- a/docker/map.jinja
+++ b/docker/map.jinja
@@ -21,6 +21,13 @@
 {% set client = salt['grains.filter_by']({
     'default': {
         'pkgs': ['python-docker'],
+        'compose': {
+          'base': '/etc/docker/compose',
+          'source': {
+            'engine': 'pkg',
+            'pkgs': ['docker-compose'],
+          },
+        },
     },
 }, grain='os', merge=salt['pillar.get']('docker:client')) %}
 
diff --git a/tests/pillar/client_compose.sls b/tests/pillar/client_compose.sls
new file mode 100644
index 0000000..a948072
--- /dev/null
+++ b/tests/pillar/client_compose.sls
@@ -0,0 +1,23 @@
+docker:
+  client:
+    enabled: true
+    compose:
+      source:
+        engine: pip
+      django_web:
+        # Run up action, any positional argument to docker-compose CLI
+        # If not defined, only docker-compose.yml is generated
+        status: up
+        environment:
+          SOMEVAR: somevalue
+        service:
+          db:
+            image: postgres
+          web:
+            image: djangoapp
+            volumes:
+              - /srv/volumes/django:/srv/django
+            ports:
+              - 8000:8000
+            depends_on:
+              - db
diff --git a/tests/pillar/client_container.sls b/tests/pillar/client_container.sls
new file mode 100644
index 0000000..3565b52
--- /dev/null
+++ b/tests/pillar/client_container.sls
@@ -0,0 +1,16 @@
+docker:
+  client:
+    enabled: true
+    container:
+      jenkins:
+        # Don't start automatically
+        start: false
+        restart: unless-stopped
+        image: jenkins:2.7.1
+        ports:
+          - 8081:8080
+          - 50000:50000
+        environment:
+          JAVA_OPTS: "-Dhudson.footerURL=https://www.example.com"
+        volumes:
+          - /srv/volumes/jenkins:/var/jenkins_home
diff --git a/tests/pillar/host_single.yml b/tests/pillar/host_single.sls
similarity index 100%
rename from tests/pillar/host_single.yml
rename to tests/pillar/host_single.sls
diff --git a/tests/run_tests.sh b/tests/run_tests.sh
index ab84ffb..3f42101 100755
--- a/tests/run_tests.sh
+++ b/tests/run_tests.sh
@@ -130,13 +130,6 @@
     done
 }
 
-real_run() {
-    for pillar in ${PILLARDIR}/*.sls; do
-        state_name=$(basename ${pillar%.sls})
-        salt_run --id=${state_name} state.sls ${FORMULA_NAME} || (log_err "Execution of ${FORMULA_NAME}.${state_name} failed"; exit 1)
-    done
-}
-
 _atexit() {
     RETVAL=$?
     trap true INT TERM EXIT
@@ -162,9 +155,6 @@
     run)
         run
         ;;
-    real-run)
-        real_run
-        ;;
     *)
         prepare
         run