diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml new file mode 100644 index 0000000..1fbc673 --- /dev/null +++ b/.github/workflows/e2e.yml @@ -0,0 +1,20 @@ +name: E2E +on: + workflow_dispatch: + push: + +jobs: + e2e: + runs-on: ubuntu-latest + steps: + - name: Checkout the codebase + uses: actions/checkout@v3 + - uses: actions/setup-python@v4 + with: + python-version: 3.8.9 + - name: Install dependencies + run: make deps + - name: Test Backup & Restore + run: make e2e + env: + VAULT_KEY: "${{ secrets.VAULT_KEY }}" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..f22b79a --- /dev/null +++ b/Makefile @@ -0,0 +1,17 @@ +e2e: test clean + +test: + cp -r tests/host_vars . + cp tests/ansible.cfg . + cp tests/docker-compose.yml . + cp tests/playbook.yml . + ansible-playbook playbook.yml + +clean: + rm -r host_vars + rm ansible.cfg + rm docker-compose.yml + rm playbook.yml + +deps: + pip install -r requirements.txt diff --git a/roles/docker_s3_backup/tasks/main.yml b/roles/docker_s3_backup/tasks/main.yml index 7f0eb95..a22efe9 100644 --- a/roles/docker_s3_backup/tasks/main.yml +++ b/roles/docker_s3_backup/tasks/main.yml @@ -5,6 +5,12 @@ - name: Determine backup timestamp. ansible.builtin.set_fact: backup_time="{{ ansible_date_time.iso8601 }}" +- name: Install Python dependencies + ansible.builtin.pip: + name: + - docker + - boto3 + - name: Stop a container community.docker.docker_container: name: "{{ container_backup }}" diff --git a/roles/docker_s3_volume_restore/defaults/main.yml b/roles/docker_s3_volume_restore/defaults/main.yml index 0572726..a95ae63 100644 --- a/roles/docker_s3_volume_restore/defaults/main.yml +++ b/roles/docker_s3_volume_restore/defaults/main.yml @@ -7,7 +7,7 @@ docker_s3_volume_restore_force: false # backup in the s3 backup. The format which is expected has the prefix of volume_name/volume_name_* # this is the format the the "docker_s3_backup" role updloads them with. docker_s3_volume_restore_latest_s3_key: false -docker_s3_volume_restores: [] +docker_volume_s3_restores: [] # docker_volume_s3_restores: # - volume_name: "linkding_data" # s3_key: "linkding_data/linkding_data-2022-09-01T21:32:54Z.tar.gz" diff --git a/tests/ansible.cfg b/tests/ansible.cfg new file mode 100644 index 0000000..a99d3fe --- /dev/null +++ b/tests/ansible.cfg @@ -0,0 +1,3 @@ +[defaults] +roles_path = roles +vault_password_file=tests/vault_key.sh diff --git a/tests/docker-compose.yml b/tests/docker-compose.yml new file mode 100755 index 0000000..85d3d04 --- /dev/null +++ b/tests/docker-compose.yml @@ -0,0 +1,16 @@ +--- +version: '3.2' +services: + portainer: + image: portainer/portainer-ce + container_name: portainer + ports: + - 9000:9000 + volumes: + - portainer_data:/data + - /var/run/docker.sock:/var/run/docker.sock + +volumes: + portainer_data: + external: true + name: portainer_data diff --git a/tests/host_vars/localhost.yml b/tests/host_vars/localhost.yml new file mode 100644 index 0000000..43235ad --- /dev/null +++ b/tests/host_vars/localhost.yml @@ -0,0 +1,44 @@ +$ANSIBLE_VAULT;1.1;AES256 +61396462383161346163353864613039623137313932386635643566333036626662353166303336 +3134363137336332663437363465353037643033663434350a316238663232353139623936343637 +65653862376431336435396539643266363735636339663662316439613637653935613566626338 +3338666636313234380a366166663233363032666430323864323032653830656233386330643233 +37613334663739373764633862373235623335303864383930316463633835663930363266343365 +38303666306338393836336134366139386165343764353938613339303566336365636232663330 +63366662343666396431653932373064653038666238373236613464613462343764383830653365 +64636330646162663939333762633538343833343563666563363330653435333665643035386133 +63356561316434613336353639356639383566343637656532663230353131376265363931376635 +64616565623362346264333564633335623933636435636433643163623166333765346235663136 +32653234653239386238653739366336643034336634363762346462363638646230653164313138 +36663836616366366461633762336133366235633165343363323861353934373530653363643233 +34663263303263373737643632663036666632306234313261333163376163656131356138306464 +63373836316637623062383461623266346164646364313062346133623031663738633133343564 +30363636383264636636336637396432396432623766623561396164656638353233303661396464 +39306337323932363839373337316531653166373837646233303235353631616663366333616532 +30306662633066316230383636643862633734623235306565343937376132323965346166386261 +61383163313539663063323161353331626638343063396433336437346437396265633439343532 +31386636303131626331353761323337643062393837373737613335643432643032323835643466 +31353166386131323034623738303037646433333466396162346163663933313462616336303265 +63643465643337396237386662393433633034613938623834613830373135633134633166633265 +63323330353830613832646433393439383739616465616635623464306432373864313133306338 +31666139313838396663656361363661643138366134336539356130333862626365343637363063 +36336462643866666262636466633730376562643630643937643130353930646231323138323366 +34663038623937336337366461393935366630346264306430626434643365656562386633393265 +34366465376263303036333934386362346234356335363835643361333366376361383962383464 +30623066653937303535316433393261373563363632393433653862356536336337333934316435 +39373230313235356437303637343266633063653639323936396661633535373532666432613766 +64336130616461656132353365343832646639653663623434323337326537663663306565643835 +30336262636239666339616437363061323435613238376661353435326436373063613463353561 +30396366636165386131616533326631323738373161313265383630363866663666663066343661 +31633331326634323463333839363662623430326566333764376130643238613761663332383039 +37653235393732313231336334373730626430363437646362363365646161336230313236316335 +36613835336632353266653234353839316438346565656637333833313136313663643764353535 +65316163363939656638663636376535663239626365366337346132376161353636366465383038 +35353930316166346163656234386338613037646261366462333231386137646165393465653864 +39666366623631326663386235653565343336613263333136393838303061643564633234643565 +30643631613737376665653736656663633233653661613164626163323535633836316462343661 +34643039653765383266326130326565396630306261313461353137333665656130343833303839 +34303937656439663661323861656334633566653834383438636133636130306366633732356430 +66393832316639343439336562356634383061616163646465626162666364656138653232666534 +63653533633032646632613836636333306331376639316264663332333362373434323864343561 +353937383136613266333838653236623462 diff --git a/tests/playbook.yml b/tests/playbook.yml new file mode 100644 index 0000000..6a112a7 --- /dev/null +++ b/tests/playbook.yml @@ -0,0 +1,106 @@ +--- +- hosts: localhost + connection: local + become: true + + tasks: + - name: Install Docker Module for Python + pip: + name: + - docker + - docker-compose + - boto3 + + - name: Remove Portainer + docker_compose: + project_src: 'tests' + state: absent + + - name: Remove portainer volume + docker_volume: + name: portainer_data + state: absent + + - name: Create portainer volume + docker_volume: + name: portainer_data + state: present + + - name: Deploy Portainer + docker_compose: + project_src: 'tests' + state: present + + + - name: Portainer | Wait for ready + uri: + url: http://localhost:9000 + method: GET + status_code: 200 + register: result + until: result.status == 200 + retries: 60 + delay: 1 + + - debug: msg="{{result}}" + + - name: Register Portainer Admin User + uri: + url: http://localhost:9000/api/users/admin/init + method: POST + body: + Username: admin + Password: "adminadminadmin" + status_code: 200 + body_format: json + register: result + until: result.status == 200 + retries: 60 + delay: 1 + + - name: Backup Portainer + include_role: + name: docker_s3_backup + vars: + container_backup: portainer + + - name: Remove Portainer + docker_compose: + project_src: 'tests' + state: absent + + - name: Remove portainer volume + docker_volume: + name: portainer_data + state: absent + + - name: Restore Portainer Volume + include_role: + name: docker_s3_volume_restore + vars: + docker_s3_volume_restore_latest_s3_key: true + docker_volume_s3_restores: + - volume_name: portainer_data + + - name: Deploy Portainer + docker_compose: + project_src: 'tests' + state: present + + - name: Auth as old user + uri: + url: http://localhost:9000/api/auth + method: POST + body: + Username: admin + Password: "adminadminadmin" + status_code: 200 + body_format: json + register: result + until: result.status == 200 + retries: 60 + delay: 1 + + - assert: + that: + - result.status == 200 diff --git a/tests/vault_key.sh b/tests/vault_key.sh new file mode 100755 index 0000000..79cc370 --- /dev/null +++ b/tests/vault_key.sh @@ -0,0 +1,2 @@ +#!/bin/bash +echo "${VAULT_KEY}"