commit 46f99a7fd4ab509f6cae8ada3bbff32bd83a5d5f
Author: Kacper Donat <kadet1090@gmail.com>
Date:   Thu Mar 11 22:41:37 2021 +0100

    Basic services

diff --git a/.ansible-lint b/.ansible-lint
new file mode 100644
index 0000000..c99d80a
--- /dev/null
+++ b/.ansible-lint
@@ -0,0 +1,2 @@
+skip_list:
+  - '306'
\ No newline at end of file
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..03d2cbb
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,10 @@
+root=true
+
+[*]
+end_of_line = lf
+insert_final_newline = true
+indent_style = space
+charset = utf-8
+
+[*.{yaml,yml}]
+indent_size = 2
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fa075d1
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/.vagrant/
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..0c07503
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,11 @@
+{
+    "yaml.schemaStore.enable": false,
+    "yaml.schemas": {
+        "https://json.schemastore.org/ansible-playbook": [
+            "${workspaceFolder}/*.yaml",
+        ],
+        "https://raw.githubusercontent.com/compose-spec/compose-spec/master/schema/compose-spec.json": [
+            "/services/*/stack.yml"
+        ]
+    }
+}
diff --git a/Vagrantfile b/Vagrantfile
new file mode 100644
index 0000000..5a8ebfe
--- /dev/null
+++ b/Vagrantfile
@@ -0,0 +1,12 @@
+# -*- mode: ruby -*-
+# vi: set ft=ruby :
+
+Vagrant.configure("2") do |config|
+  config.vm.box = "generic/debian10"
+
+  config.vm.network "private_network", ip: "192.168.33.10"
+
+  config.vm.provider "virtualbox" do |vb|
+     vb.memory = 2048
+  end
+end
diff --git a/init.yaml b/init.yaml
new file mode 100644
index 0000000..65ee66e
--- /dev/null
+++ b/init.yaml
@@ -0,0 +1,35 @@
+---
+- hosts: all
+  become: yes
+
+  vars_files:
+    - vars/services.yml
+    - vars/environment.yml
+
+  roles:
+    - geerlingguy.docker
+    - geerlingguy.pip
+
+  tasks:
+    - name: "Add '{{ ansible_user }}' to docker group"
+      user:
+        user: "{{ ansible_user }}"
+        groups: docker
+        append: yes
+        
+    - name: Init a new swarm with default parameters
+      community.docker.docker_swarm:
+        state: present
+        advertise_addr: "{{ swarm_addr|default(omit) }}"
+
+    - name: Init docker network for ingress
+      community.docker.docker_network:
+        name: traefik
+        scope: swarm
+        driver: overlay
+
+    - name: Deploy services
+      include_tasks: tasks/deploy.yml
+      vars: 
+        service: "{{ item }}"
+      loop: "{{ services }}"
diff --git a/inventory/vagrant.ini b/inventory/vagrant.ini
new file mode 100644
index 0000000..1dd1457
--- /dev/null
+++ b/inventory/vagrant.ini
@@ -0,0 +1,7 @@
+[main]
+192.168.33.10
+
+[main:vars]
+ansible_user=vagrant
+ansible_ssh_private_key_file=./.vagrant/machines/default/virtualbox/private_key
+ansible_ssh_common_args='-o StrictHostKeyChecking=no'
\ No newline at end of file
diff --git a/services.yaml b/services.yaml
new file mode 100644
index 0000000..7792848
--- /dev/null
+++ b/services.yaml
@@ -0,0 +1,14 @@
+---
+- hosts: all
+  become: yes
+
+  vars_files:
+    - vars/environment.yml
+    - vars/services.yml
+
+  tasks:
+    - name: Deploy services
+      include_tasks: tasks/deploy.yml
+      vars:
+        service: "{{ item }}"
+      loop: "{{ services }}"
diff --git a/services/helloworld/stack.yml b/services/helloworld/stack.yml
new file mode 100644
index 0000000..aab7980
--- /dev/null
+++ b/services/helloworld/stack.yml
@@ -0,0 +1,13 @@
+version: "{{ compose_version }}"
+
+services:
+  rest:
+    image: thomaspoignant/hello-world-rest-json
+    deploy:
+      labels:
+        - traefik.enable=true
+        - traefik.http.routers.{{ service }}.rule=Host(`kadet.local`) && PathPrefix(`/hello/`)
+        - traefik.http.services.{{ service }}.loadbalancer.server.port=8080
+        - traefik.http.routers.{{ service }}.middlewares={{ service }}-strip
+        - traefik.http.middlewares.{{ service }}-strip.stripprefix.prefixes=/hello/
+    networks: ['traefik']
diff --git a/services/helloworld/vars/main.yml b/services/helloworld/vars/main.yml
new file mode 100644
index 0000000..2e00210
--- /dev/null
+++ b/services/helloworld/vars/main.yml
@@ -0,0 +1,2 @@
+---
+service_port: 80
diff --git a/services/traefik/config/traefik.yaml b/services/traefik/config/traefik.yaml
new file mode 100644
index 0000000..afd4031
--- /dev/null
+++ b/services/traefik/config/traefik.yaml
@@ -0,0 +1,136 @@
+################################################################
+#
+# Configuration sample for Traefik v2.
+#
+# For Traefik v1: https://github.com/traefik/traefik/blob/v1.7/traefik.sample.toml
+#
+################################################################
+
+################################################################
+# Global configuration
+################################################################
+global:
+  checkNewVersion: true
+  sendAnonymousUsage: true
+
+################################################################
+# EntryPoints configuration
+################################################################
+
+# EntryPoints definition
+#
+# Optional
+#
+entryPoints:
+  web:
+    address: :80
+
+  websecure:
+    address: :443
+
+################################################################
+# Traefik logs configuration
+################################################################
+
+# Traefik logs
+# Enabled by default and log to stdout
+#
+# Optional
+#
+#log:
+  # Log level
+  #
+  # Optional
+  # Default: "ERROR"
+  #
+#  level: DEBUG
+
+  # Sets the filepath for the traefik log. If not specified, stdout will be used.
+  # Intermediate directories are created if necessary.
+  #
+  # Optional
+  # Default: os.Stdout
+  #
+#  filePath: log/traefik.log
+
+  # Format is either "json" or "common".
+  #
+  # Optional
+  # Default: "common"
+  #
+#  format: json
+
+################################################################
+# Access logs configuration
+################################################################
+
+# Enable access logs
+# By default it will write to stdout and produce logs in the textual
+# Common Log Format (CLF), extended with additional fields.
+#
+# Optional
+#
+#accessLog:
+  # Sets the file path for the access log. If not specified, stdout will be used.
+  # Intermediate directories are created if necessary.
+  #
+  # Optional
+  # Default: os.Stdout
+  #
+#  filePath: /path/to/log/log.txt
+
+  # Format is either "json" or "common".
+  #
+  # Optional
+  # Default: "common"
+  #
+#  format: json
+
+################################################################
+# API and dashboard configuration
+################################################################
+
+# Enable API and dashboard
+#
+# Optional
+#
+#api:
+  # Enable the API in insecure mode
+  #
+  # Optional
+  # Default: false
+  #
+#  insecure: true
+
+  # Enabled Dashboard
+  #
+  # Optional
+  # Default: true
+  #
+#  dashboard: false
+
+################################################################
+# Ping configuration
+################################################################
+
+# Enable ping
+#ping:
+  # Name of the related entry point
+  #
+  # Optional
+  # Default: "traefik"
+  #
+#  entryPoint: traefik
+
+################################################################
+# Docker configuration backend
+################################################################
+
+providers:
+  file:
+    directory: "/etc/traefik/dynamic"
+  # Enable Docker configuration backend
+  docker:
+    endpoint: "unix:///var/run/docker.sock"
+    swarmMode: true
+    exposedByDefault: false
diff --git a/services/traefik/stack.yml b/services/traefik/stack.yml
new file mode 100644
index 0000000..0b2ad56
--- /dev/null
+++ b/services/traefik/stack.yml
@@ -0,0 +1,16 @@
+version: "{{ compose_version }}"
+
+services:
+  traefik:
+    image: traefik:v2.4
+    ports:
+      - 80:80
+      - 443:443
+    volumes:
+      - ./config/traefik.yaml:/etc/traefik/traefik.yaml
+      - /var/run/docker.sock:/var/run/docker.sock
+    deploy:
+      placement:
+        constraints:
+          - node.role == manager
+    networks: ['traefik']
diff --git a/tasks/deploy.yml b/tasks/deploy.yml
new file mode 100644
index 0000000..5d6ed79
--- /dev/null
+++ b/tasks/deploy.yml
@@ -0,0 +1,43 @@
+---
+- name: 'Include vars for "{{ service }}" service'
+  include_vars: "{{ file }}"
+  with_fileglob: "{{ services_root }}/{{ service }}/vars/*"
+  loop_control:
+    loop_var: file
+
+- name: 'Ensure "{{ service }}" service config directory exist'
+  file:
+    path: "{{ remote_services_root }}/{{ service }}"
+    state: directory
+    recurse: true
+    owner: "{{ ansible_user }}"
+
+- name: 'Ensure "{{ service }}" service config directory exist'
+  file:
+    path: "{{ remote_services_root }}/{{ service }}/config"
+    state: directory
+    recurse: true
+    owner: "{{ ansible_user }}"
+
+- name: 'Synchronise "{{ service }}" configuration'
+  template:
+    src: "{{ services_root }}/{{ service }}/stack.yml"
+    dest: "{{ remote_services_root }}/{{ service }}/stack.yml"
+
+- name: 'Include vars for "{{ service }}" service'
+  copy: 
+    src: "{{ file }}"
+    dest: "{{ remote_services_root }}/{{ file | replace(services_root, '') }}"
+  with_fileglob: "{{ services_root }}/{{ service }}/config/*"
+  loop_control:
+    loop_var: file
+
+- name: 'Deploy "{{ service }}" docker stack'
+  community.docker.docker_stack:
+    name: "{{ service }}"
+    compose:
+      - "{{ remote_services_root }}/{{ service }}/stack.yml"
+      - version: "{{ compose_version }}" 
+        networks:
+          traefik:
+            external: true
diff --git a/vars/environment.yml b/vars/environment.yml
new file mode 100644
index 0000000..e31ffbc
--- /dev/null
+++ b/vars/environment.yml
@@ -0,0 +1,9 @@
+---
+docker_install_compose: no
+pip_install_packages:
+  - docker
+  - jsondiff
+  - pyyaml
+ansible_python_interpreter: /usr/bin/python3  
+pip_package: python3-pip
+pip_executable: pip3
diff --git a/vars/services.yml b/vars/services.yml
new file mode 100644
index 0000000..dbe8392
--- /dev/null
+++ b/vars/services.yml
@@ -0,0 +1,6 @@
+---
+services_root: "{{ './services' | realpath }}"
+services: "{{ lookup('pipe', 'ls -1 ' + services_root).split('\n') | list }}"
+remote_services_root: /var/services
+
+compose_version: "3.7"