Browse Source

WIP nginx-user scenery

WIP Idempotence with docker inspect --type=image
tags/v1.2.0^2^2
Lyz 1 year ago
parent
commit
930d5c1ded
Signed by: Lyz <lyz@riseup.net> GPG Key ID: 6C7D7C1612CDE02F

+ 17
- 0
molecule/nginx-user/INSTALL.rst View File

@@ -0,0 +1,17 @@
1
+*******
2
+Install
3
+*******
4
+
5
+Requirements
6
+============
7
+
8
+* Vagrant
9
+* Virtualbox, Parallels, VMware Fusion, VMware Workstation or VMware Desktop
10
+* python-vagrant
11
+
12
+Install
13
+=======
14
+
15
+.. code-block:: bash
16
+
17
+  $ sudo pip install python-vagrant

+ 56
- 0
molecule/nginx-user/create.yml View File

@@ -0,0 +1,56 @@
1
+---
2
+- name: Create
3
+  hosts: localhost
4
+  connection: local
5
+  gather_facts: False
6
+  no_log: "{{ not lookup('env', 'MOLECULE_DEBUG') | bool }}"
7
+  vars:
8
+    molecule_file: "{{ lookup('env', 'MOLECULE_FILE') }}"
9
+    molecule_instance_config: "{{ lookup('env', 'MOLECULE_INSTANCE_CONFIG') }}"
10
+    molecule_yml: "{{ lookup('file', molecule_file) | molecule_from_yaml }}"
11
+  tasks:
12
+    - name: Create molecule instance(s)
13
+      molecule_vagrant:
14
+        instance_name: "{{ item.name }}"
15
+        instance_interfaces: "{{ item.interfaces | default(omit) }}"
16
+        instance_raw_config_args: "{{ item.instance_raw_config_args | default(omit) }}"
17
+
18
+        platform_box: "{{ item.box }}"
19
+        platform_box_version: "{{ item.box_version | default(omit) }}"
20
+        platform_box_url: "{{ item.box_url | default(omit) }}"
21
+
22
+        provider_name: "{{ molecule_yml.driver.provider.name }}"
23
+        provider_memory: "{{ item.memory | default(omit) }}"
24
+        provider_cpus: "{{ item.cpus | default(omit) }}"
25
+        provider_raw_config_args: "{{ item.raw_config_args | default(omit) }}"
26
+
27
+        state: up
28
+      register: server
29
+      with_items: "{{ molecule_yml.platforms }}"
30
+
31
+    # Mandatory configuration for Molecule to function.
32
+
33
+    - name: Populate instance config dict
34
+      set_fact:
35
+        instance_conf_dict: {
36
+          'instance': "{{ item.Host }}",
37
+          'address': "{{ item.HostName }}",
38
+          'user': "{{ item.User }}",
39
+          'port': "{{ item.Port }}",
40
+          'identity_file': "{{ item.IdentityFile }}", }
41
+      with_items: "{{ server.results }}"
42
+      register: instance_config_dict
43
+      when: server.changed | bool
44
+
45
+    - name: Convert instance config dict to a list
46
+      set_fact:
47
+        instance_conf: "{{ instance_config_dict.results | map(attribute='ansible_facts.instance_conf_dict') | list }}"
48
+      when: server.changed | bool
49
+
50
+    - name: Dump instance config
51
+      copy:
52
+        # NOTE(retr0h): Workaround for Ansible 2.2.
53
+        #               https://github.com/ansible/ansible/issues/20885
54
+        content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
55
+        dest: "{{ molecule_instance_config }}"
56
+      when: server.changed | bool

+ 36
- 0
molecule/nginx-user/destroy.yml View File

@@ -0,0 +1,36 @@
1
+---
2
+
3
+- name: Destroy
4
+  hosts: localhost
5
+  connection: local
6
+  gather_facts: False
7
+  no_log: "{{ not lookup('env', 'MOLECULE_DEBUG') | bool }}"
8
+  vars:
9
+    molecule_file: "{{ lookup('env', 'MOLECULE_FILE') }}"
10
+    molecule_instance_config: "{{ lookup('env',' MOLECULE_INSTANCE_CONFIG') }}"
11
+    molecule_yml: "{{ lookup('file', molecule_file) | molecule_from_yaml }}"
12
+  tasks:
13
+    - name: Destroy molecule instance(s)
14
+      molecule_vagrant:
15
+        instance_name: "{{ item.name }}"
16
+        platform_box: "{{ item.box }}"
17
+        provider_name: "{{ molecule_yml.driver.provider.name }}"
18
+        force_stop: "{{ item.force_stop | default(True) }}"
19
+
20
+        state: destroy
21
+      register: server
22
+      with_items: "{{ molecule_yml.platforms }}"
23
+
24
+    # Mandatory configuration for Molecule to function.
25
+
26
+    - name: Populate instance config
27
+      set_fact:
28
+        instance_conf: {}
29
+
30
+    - name: Dump instance config
31
+      copy:
32
+        # NOTE(retr0h): Workaround for Ansible 2.2.
33
+        #               https://github.com/ansible/ansible/issues/20885
34
+        content: "{{ instance_conf | to_json | from_json | molecule_to_yaml | molecule_header }}"
35
+        dest: "{{ molecule_instance_config }}"
36
+      when: server.changed | bool

+ 2
- 0
molecule/nginx-user/files/htpasswd View File

@@ -0,0 +1,2 @@
1
+testuser:$2y$05$vXnk299Xwr1RjEcwhJvHC.w7UnxuucId7y3wb5iOgSjkKCYaPZeFq
2
+

+ 36
- 0
molecule/nginx-user/molecule.yml View File

@@ -0,0 +1,36 @@
1
+---
2
+dependency:
3
+  name: galaxy
4
+driver:
5
+  name: vagrant
6
+  provider:
7
+    name: libvirt
8
+lint:
9
+  name: yamllint
10
+platforms:
11
+  - name: deploy-docker-nginx-user
12
+    box: debian/stretch64
13
+    instance_raw_config_args:
14
+      - "vm.synced_folder '.', '/vagrant', disabled: true"
15
+provisioner:
16
+  name: ansible
17
+  lint:
18
+    name: ansible-lint
19
+scenario:
20
+  name: nginx-user
21
+  test_sequence:
22
+    - destroy
23
+    - lint
24
+    - dependency
25
+    - syntax
26
+    - create
27
+    - prepare
28
+    - converge
29
+    - idempotence
30
+    - side_effect
31
+    - verify
32
+    - destroy
33
+verifier:
34
+  name: testinfra
35
+  lint:
36
+    name: flake8

+ 90
- 0
molecule/nginx-user/playbook.yml View File

@@ -0,0 +1,90 @@
1
+---
2
+- name: '[Pretask] Install pip, and curl'
3
+  hosts: all
4
+  tasks:
5
+    - name: Install required packages
6
+      become: true
7
+      package:
8
+        name: "{{ item }}"
9
+        state: present
10
+      with_items:
11
+        - python-pip
12
+        - curl
13
+
14
+- name: '[Pretask] Install docker'
15
+  hosts: all
16
+  roles:
17
+    - role: docker
18
+
19
+- name: '[Pretask] Configure docker-registry on /etc/hosts'
20
+  hosts: deploy-docker-registry-instance
21
+  tasks:
22
+    - name: Configure docker-registry on /etc/hosts
23
+      become: True
24
+      lineinfile:
25
+        path: /etc/hosts
26
+        state: present
27
+        line: '127.0.0.1  docker-registry'
28
+
29
+- name: '[Pretask] Configure docker basic authentication'
30
+  hosts: deploy-docker-registry-instance
31
+  tasks:
32
+    - name: Create registry/auth directory
33
+      become: True
34
+      file:
35
+        path: /root/docker/registry/auth/
36
+        state: directory
37
+
38
+    - name: Copy the htpasswd
39
+      become: True
40
+      copy:
41
+        src: htpasswd
42
+        dest: /root/docker/registry/auth/htpasswd
43
+
44
+
45
+- name: '[Pretask] Install registry on the registry instance'
46
+  hosts: deploy-docker-registry-instance
47
+  vars:
48
+    docker_command: /usr/bin/docker run -i --name {{ registry_service_name }} -p 127.0.0.1:5000:5000 --rm -v {{ registry_data }}:/var/lib/registry -v {{ registry_auth }}:/var/lib/auth -v {{ registry_config }}/:/etc/docker/registry -e "REGISTRY_AUTH=htpasswd" -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" -e REGISTRY_AUTH_HTPASSWD_PATH=/var/lib/auth/htpasswd registry:2
49
+  roles:
50
+    - role: docker-registry
51
+
52
+
53
+- name: Build nginx from image
54
+  hosts: all
55
+  vars:
56
+    remote_build: True
57
+    docker_image: nginx
58
+    service_name: image-nginx
59
+    docker_data_directories:
60
+      - "/root/docker/image-nginx/data"
61
+      - "/root/docker/image-nginx/auth"
62
+    docker_registry: "docker-registry:5000"
63
+    docker_registry_read: "{{ docker_registry }}"
64
+    registry_user: testuser
65
+    registry_password: testpassword
66
+    docker_image_tag: latest
67
+    docker_command: /usr/bin/docker run --rm -i --name "{{ service_name }}" -p 8080:80 "{{ docker_registry_read }}/{{ service_name }}"
68
+  roles:
69
+    - role: deploy-docker
70
+
71
+- name: Build nginx from git
72
+  hosts: all
73
+  vars:
74
+    remote_build: True
75
+    git_repository: https://github.com/nginxinc/docker-nginx
76
+    git_repository_destination: /tmp/docker-nginx
77
+    git_repository_extra_path: stable/stretch
78
+    git_repository_tag: master
79
+    service_name: git-nginx
80
+    docker_data_directories:
81
+      - "/root/docker/git-nginx/data"
82
+      - "/root/docker/git-nginx/auth"
83
+    docker_registry: "docker-registry:5000"
84
+    docker_registry_read: "{{ docker_registry }}"
85
+    registry_user: testuser
86
+    registry_password: testpassword
87
+    docker_image_tag: latest
88
+    docker_command: /usr/bin/docker run --rm -i --name "{{ service_name }}" -p 8081:80 "{{ docker_registry_read }}/{{ service_name }}"
89
+  roles:
90
+    - role: deploy-docker

+ 9
- 0
molecule/nginx-user/prepare.yml View File

@@ -0,0 +1,9 @@
1
+---
2
+- name: Prepare
3
+  hosts: all
4
+  gather_facts: False
5
+  tasks:
6
+    - name: Install python for Ansible
7
+      raw: test -e /usr/bin/python || (apt -y update && apt install -y python-minimal)
8
+      become: True
9
+      changed_when: False

+ 4
- 0
molecule/nginx-user/requirements.yml View File

@@ -0,0 +1,4 @@
1
+- src: git+https://git.digitales.cslabrecha.org/ansible-roles/docker.git
2
+  version: v1.0.1
3
+- src: git+https://git.digitales.cslabrecha.org/ansible-roles/docker-registry.git
4
+  version: feature/26

+ 3
- 0
molecule/nginx-user/templates/daemon.json.j2 View File

@@ -0,0 +1,3 @@
1
+{
2
+  "insecure-registries" : ["{{ hostvars['ui-registry-registry-instance'].ansible_default_ipv4.address }}:5000"]
3
+}

+ 9
- 0
molecule/nginx-user/templates/main.yml.j2 View File

@@ -0,0 +1,9 @@
1
+- name: Converge
2
+  hosts: all
3
+  vars:
4
+    docker_registry: "{{ hostvars['ui-registry-registry-debian-stretch64'].ansible_default_ipv4.address }}:5000"
5
+    docker_registry_read: "{{ hostvars['ui-registry-registry-debian-stretch64'].ansible_default_ipv4.address }}:5000"
6
+    docker_command: /usr/bin/docker run --rm --name "{{ service_name }}" -i -p 127.0.0.1:8080:8080 "{{ docker_registry_read }}/{{ service_name }}" --registry "{{ docker_registry_read }}"
7
+  roles:
8
+    - role: ui-registry
9
+

+ 96
- 0
molecule/nginx-user/tests/test_default.py View File

@@ -0,0 +1,96 @@
1
+import os
2
+import pytest
3
+import testinfra.utils.ansible_runner
4
+
5
+testinfra_hosts = testinfra.utils.ansible_runner.AnsibleRunner(
6
+    os.environ['MOLECULE_INVENTORY_FILE']).get_hosts('all')
7
+
8
+
9
+@pytest.mark.parametrize("package", [
10
+    ("docker-ce"),
11
+    ("python-pip"),
12
+])
13
+def test_required_packages_exist(host, package):
14
+    pkg = host.package(package)
15
+    assert pkg.is_installed
16
+
17
+
18
+@pytest.mark.parametrize("pip_package", [
19
+    ("docker-py"),
20
+])
21
+def test_required_pip_packages_exist(host, pip_package):
22
+    pip_packages = host.pip_package.get_packages()
23
+    assert pip_package in pip_packages
24
+
25
+
26
+# Test remotely build from image
27
+
28
+@pytest.mark.parametrize("directories", [
29
+    ("/root/docker/"),
30
+    ("/root/docker/image-nginx/data"),
31
+    ("/root/docker/image-nginx/auth"),
32
+])
33
+def test_required_directories_exist(host, directories):
34
+    with host.sudo():
35
+        directory = host.file(directories)
36
+        assert directory.exists
37
+        assert directory.user == 'root'
38
+        assert directory.group == 'root'
39
+        assert oct(directory.mode) == '0700'
40
+
41
+
42
+def test_build_nginx_image_is_downloaded(host):
43
+    with host.sudo():
44
+        registry_exist = host.check_output(
45
+            'docker inspect --type=image docker-registry:5000/image-nginx',
46
+        )
47
+        assert not registry_exist == 'Error: No such image: ' + \
48
+                                     'docker-registry:5000/image-nginx'
49
+
50
+
51
+def test_build_nginx_is_enabled_and_running(host):
52
+    service = host.service('image-nginx')
53
+    assert service.is_enabled
54
+    assert service.is_running
55
+
56
+
57
+def test_build_nginx_is_working(host):
58
+    build_nginx_exist = host.check_output('curl localhost:8080')
59
+    assert '<h1>Welcome to nginx!</h1>' in build_nginx_exist
60
+
61
+
62
+# Test remotely build from git
63
+
64
+
65
+@pytest.mark.parametrize("directories", [
66
+    ("/root/docker/"),
67
+    ("/root/docker/git-nginx/data"),
68
+    ("/root/docker/git-nginx/auth"),
69
+])
70
+def test_required_directories_exist_for_git_build(host, directories):
71
+    with host.sudo():
72
+        directory = host.file(directories)
73
+        assert directory.exists
74
+        assert directory.user == 'root'
75
+        assert directory.group == 'root'
76
+        assert oct(directory.mode) == '0700'
77
+
78
+
79
+def test_image_nginx_image_is_downloaded(host):
80
+    with host.sudo():
81
+        registry_exist = host.check_output(
82
+            'docker inspect --type=image docker-registry:5000/git-nginx',
83
+        )
84
+        assert not registry_exist == 'Error: No such image: ' + \
85
+                                     'docker-registry:5000/git-nginx'
86
+
87
+
88
+def test_image_nginx_is_enabled_and_running(host):
89
+    service = host.service('git-nginx')
90
+    assert service.is_enabled
91
+    assert service.is_running
92
+
93
+
94
+def test_image_nginx_is_working(host):
95
+    build_nginx_exist = host.check_output('curl localhost:8081')
96
+    assert '<h1>Welcome to nginx!</h1>' in build_nginx_exist

+ 34
- 3
tasks/main.yml View File

@@ -105,6 +105,37 @@
105 105
     password: "{{ registry_password }}"
106 106
   when: remote_build == True
107 107
 
108
+- name: Test if image exists
109
+  become: True
110
+  command: docker inspect --type=image "{{ docker_registry }}/{{ service_name }}"
111
+  register: image_exists
112
+  changed_when: false
113
+  failed_when: false
114
+
115
+- name: Debug 0
116
+  debug:
117
+    var: image_exists
118
+- name: Debug 1
119
+  debug:
120
+    var: image_exists
121
+  when:
122
+  - image_exists.rc != '0'
123
+- name: Debug 2
124
+  debug:
125
+    var: image_exists
126
+  when:
127
+  - image_exists.rc != 0
128
+- name: Debug 3
129
+  debug:
130
+    var: image_exists
131
+  when:
132
+  - not image_exists.rc == 0
133
+- name: Debug 4
134
+  debug:
135
+    var: image_exists
136
+  when:
137
+  - not image_exists.rc == '0'
138
+
108 139
 - name: Clone git repository remotely
109 140
   git:
110 141
     repo: "{{ git_repository }}"
@@ -113,6 +144,7 @@
113 144
   register: git_cloned
114 145
   when:
115 146
     - docker_image is not defined
147
+    - image_exists.rc != '0'
116 148
     - remote_build == True
117 149
 
118 150
 - name: Build docker image remotely and push it to a registry with tag latest
@@ -124,8 +156,8 @@
124 156
     push: yes
125 157
   when:
126 158
     - docker_image is not defined
159
+    - image_exists.rc != 0
127 160
     - remote_build == True
128
-    - git_cloned.changed == True
129 161
 
130 162
 - name: Build docker image remotely and push it to a registry with real tag
131 163
   become: True
@@ -136,8 +168,8 @@
136 168
     push: yes
137 169
   when:
138 170
     - docker_image is not defined
171
+    - image_exists.rc != 0
139 172
     - remote_build == True
140
-    - git_cloned.changed == True
141 173
 
142 174
 - name: Build docker image remotely and push it to a registry
143 175
   become: True
@@ -148,7 +180,6 @@
148 180
   when:
149 181
     - docker_image is not defined
150 182
     - remote_build == True
151
-    - git_cloned.changed == True
152 183
 
153 184
 - name: Download image remotely from public registry
154 185
   become: True

Loading…
Cancel
Save