commit 6c50019d6d4c04eb87f666e5e8e6d99783d65a3b Author: Sven Ketelsen Date: Tue Mar 30 04:36:33 2021 +0200 feat: setup servers on hetzner cloud diff --git a/README.md b/README.md new file mode 100644 index 0000000..ebd77d1 --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Prepare ansible Installation +Install ansible with Python. + + pip3 install ansible + +Install library jmespath (https://jmespath.org/). Will be used to parse JSON data. + + pip3 install jmespath + +Install ansible role for managing hetzner cloud servers. + + pip3 install hcloud + ansible-galaxy collection install hetzner.hcloud + +# Setup +Create/Start servers for stage-dev + + ansible-playbook -i stage-dev provisioning.yml --vault-password-file ~/vault-pass diff --git a/group_vars/all/plain.yml b/group_vars/all/plain.yml new file mode 100644 index 0000000..383db28 --- /dev/null +++ b/group_vars/all/plain.yml @@ -0,0 +1,12 @@ +--- + +domain: smardigo.digital + +hetzner_server_type: cx11 +hetzner_server_image: ubuntu-20.04 + +hetzner_ssh_keys: + - sven.ketelsen@arxes-tolina.de + +#hetzner_authentication_token: "< see vault >" +#digitalocean_authentication_token: "< see vault >" \ No newline at end of file diff --git a/group_vars/all/vault.yml b/group_vars/all/vault.yml new file mode 100644 index 0000000..19414bf --- /dev/null +++ b/group_vars/all/vault.yml @@ -0,0 +1,15 @@ +$ANSIBLE_VAULT;1.1;AES256 +62366361333863393564663466393361633166613434303036363563306634316161326432336262 +3331653631666639623366326238323465333736653532660a333335643632353633303037663631 +37636163613537313035633433313439326134303532346434373533643865343466336433643837 +3764666639343265630a393463306363653962333561353161336264306664656163386232333438 +39396232303938393961393065306433643232343766356235363562623431623437613134353135 +38633433643365613434636531616134303835626661643835633437343262646534346562663165 +39393762333565336339663130383461383931643165386635376532316137366165356336353964 +65656235626362353937373065386131386139663334653438376138353436613434343639646134 +62663936323033366265316361343039383531376230396466366331383632383163646433316631 +62356364303662366630396535626232613566336430616536623561623333643333393434613863 +62336632333465366363303164373331336436393830636133366263383163336362343366653762 +39643762393864626366383731626366643831653238303532663964363537393031663836343338 +34643735306335313030343664313361356361316633613530353361346232326261366239383662 +6163326466643334646436383366363531633066313335323336 diff --git a/host_vars/dev-elastic-stack-01.yml b/host_vars/dev-elastic-stack-01.yml new file mode 100644 index 0000000..750465d --- /dev/null +++ b/host_vars/dev-elastic-stack-01.yml @@ -0,0 +1,7 @@ +--- + +hetzner_server_type: cx21 + +hetzner_ssh_keys: + - stefan@curow.de + - sven.ketelsen@arxes-tolina.de diff --git a/host_vars/dev-elastic-stack-02.yml b/host_vars/dev-elastic-stack-02.yml new file mode 100644 index 0000000..750465d --- /dev/null +++ b/host_vars/dev-elastic-stack-02.yml @@ -0,0 +1,7 @@ +--- + +hetzner_server_type: cx21 + +hetzner_ssh_keys: + - stefan@curow.de + - sven.ketelsen@arxes-tolina.de diff --git a/host_vars/dev-elastic-stack-03.yml b/host_vars/dev-elastic-stack-03.yml new file mode 100644 index 0000000..750465d --- /dev/null +++ b/host_vars/dev-elastic-stack-03.yml @@ -0,0 +1,7 @@ +--- + +hetzner_server_type: cx21 + +hetzner_ssh_keys: + - stefan@curow.de + - sven.ketelsen@arxes-tolina.de diff --git a/keys/peter.heise/id_rsa.pub b/keys/peter.heise/id_rsa.pub new file mode 100644 index 0000000..45d916a --- /dev/null +++ b/keys/peter.heise/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDPiWNJzb4vqgkjsRjl1C5oTQbyEvsBPfBuVf3AL9Ssw7RJb8hl3VqVegJ1HqNe1/j4R04a53ND5qy93GBAYOI3iNKiWq2Cd9DM9QHN+EiNG7eo0wkr/VhBh5bh6knn12RXX1T0xnR9jeB3rIQWyJyR+PTSEz4oul+QjlKB8uO7LLmsoqVpVqGhj7xtoVIEfJPMCEBMjj/jc3rGK1ezrXBGCTFEQPl5b+XRy9kybv5hf6W02yPm82RRozG3/3zObiNPX/ajt5mHB09CTq5JLeLFlfftpcLEON1CDpzACm7cIvnYoHKltaGjkZaprxpPApkKLiPe8zVUYiG0wt5qYUXS/AQ5u6I0vFA+5H3fEYZMalp4fwf4OWFxqJQH97sivQe/q7SnOA70GiClri9qWt6r6/LP7du7UySvOWVX8R6CuD3OdaAHXng1UWLDwqP9r2XshQIVo90vz9vLVP2k7bBchxignmD7WL4VnEG5bhhf487xhK3+YCG8TWtGO8MXDp0= pheise@fedora-vm diff --git a/keys/stefan.curow/id_rsa.pub b/keys/stefan.curow/id_rsa.pub new file mode 100644 index 0000000..fc85b11 --- /dev/null +++ b/keys/stefan.curow/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAscASzHdu85wUZUNYLHNJSbee3uQxApRXBV90twEFdUI8I4MmKVeGOi5zTat4VXqAGFgJ8CAUGM1rwC6azi1SDzikPVbV8QtqeRK1P1KVkknyBepe4t/DrhelQudJ2VM2wuDgCtbHWgvVfh3vd7IF5pThPke/oa8H2rACfM8pSTpn5AVPnTotM/8aTgEt1YDoDS+59CG/mGCMTvZ/EkYhIVIFEkNcaMn0Xwx0q3X2VuanA5Zu6BClybwE45A/kRZo7nXtEa33Mvr2yqkoC9DRP9l3d1K2wiIn3X8DBsgM+ZWsriS8Tt7UzOyHzyu7+ZlEvb4ek6ta/weKMbtJl/X3VQ== scurow \ No newline at end of file diff --git a/keys/sven.ketelsen/id_rsa.pub b/keys/sven.ketelsen/id_rsa.pub new file mode 100644 index 0000000..d0ebe21 --- /dev/null +++ b/keys/sven.ketelsen/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDiP5IHm3hTbO/DBEwVoEFvbiOX56d67Q4fPWkmJlLAygQ40kRJj2ijzYNCryh4JSxXxOVu42c79Lzyxt1h/OhayGOatdAyEe/GIQB0YI4G5UmIxZecZCxOT3Uqj4j0+LDHH8QFkJUI59FpznM9VezwciL2Dxc2dA8lrEtKJVoZuCxHSx84GwzqBZdIhyNSSGvXu/ZP/KpT8ACAx5F5PJ3D+B+3pYuYLnzsYJ8Y4RYCoQ8bIX89txJ7bF2lrMmPeE3t2ms4bAh+QbohED0SksQKt1xEt9gt/Be+cRdrdts5XYfdKyd4iAFtzuRVOUTt4OcwqrFsiDeJRLK8taMH9Fz sven.ketelsen@arxes-tolina.de \ No newline at end of file diff --git a/keys/vanphuong.ma/id_rsa.pub b/keys/vanphuong.ma/id_rsa.pub new file mode 100644 index 0000000..5dd2e7c --- /dev/null +++ b/keys/vanphuong.ma/id_rsa.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDHgUkCCGkqAYt+WsTs0jnjVsZfIJdQoStX6hvV3l4K7UBJyGBmg7NxAZk053GYs2R6Ryg3S/Hqe4JeGX1XSxJTtpzPusBmvrEl4ei94h6F6IxeAyTjMrks3uS/n7awz4j6VcDW2OoHMbFl6VP8KPiWCjChG4Kz9peg9FhwFi9THlgr4cgSMjPjOfSoL43xWVOx+NC/JyFCBXD//WzsB02ceC71GG4W3RW8gAgNW9JOgdihP+qkA6oh68MBEPWr5uUolfoyQLSTGpE//YDCqgXyKCG1+bJ4UOZ3UC0nYayY/hWUIkPxHbZ5zCTYZ2Z2ah5u/QxGOryHFENbAu46MeKzPtoY3bfqfnfmB6C/rWTqUKIPBaKgaI104Lo1C+nmwhOiSewEKFZgoAzCoRWP+HoCDSceJyW9VlgoFR30nfFOaTnJ9N3um0YRZ+B5jDJOXE2+MoKBybfm/Johh/RKVWJvlrgUl7YuTTK0hd03FdRYEytReY/eQyNyXjqo9qmKwBk= vanphuong.ma@4K6N2X2 \ No newline at end of file diff --git a/provisioning.yml b/provisioning.yml new file mode 100644 index 0000000..6c1169f --- /dev/null +++ b/provisioning.yml @@ -0,0 +1,19 @@ +--- + +- name: 'apply setup to {{ host | default("all") }}' + hosts: '{{ host | default("all") }}' + serial: "{{ serial_number | default(1) }}" + gather_facts: no + become: no + + pre_tasks: + - name: "Check if ansible version is at least 2.10.x" + assert: + that: + - ansible_version.major >= 2 + - ansible_version.minor >= 10 + msg: "The ansible version has to be at least ({{ ansible_version.full }})" + + roles: + - role: hcloud + when: "'hcloud' in group_names" diff --git a/roles/_digitalocean/defaults/main.yml b/roles/_digitalocean/defaults/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/_digitalocean/defaults/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/_digitalocean/handlers/main.yml b/roles/_digitalocean/handlers/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/_digitalocean/handlers/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/_digitalocean/meta/main.yml b/roles/_digitalocean/meta/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/_digitalocean/meta/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/_digitalocean/tasks/domain.yml b/roles/_digitalocean/tasks/domain.yml new file mode 100644 index 0000000..13515e4 --- /dev/null +++ b/roles/_digitalocean/tasks/domain.yml @@ -0,0 +1,60 @@ +--- + +- name: Read DNS entry for {{ record_name }}.{{ domain }} from digitalocean + uri: + url: "https://api.digitalocean.com/v2/domains/{{ domain }}/records?name={{ record_name }}.{{ domain }}" + headers: + accept: application/json + authorization: Bearer {{ digitalocean_authentication_token }} + return_content: yes + register: domain_records_response + delegate_to: 127.0.0.1 + +- name: Save DNS entry as variable (fact) + set_fact: + domain_records_response_json: "{{ domain_records_response.json }}" + +- name: Parse DNS entry for {{ record_name }}.{{ domain }} + set_fact: + domain_record: "{{ domain_records_response_json.domain_records | json_query(jmesquery) | first | default({'name': '-', 'ip': '-'}) }}" + vars: + jmesquery: '[*].{id: id, name: name, ip: data}' + +- name: Print DNS entry for {{ record_name }}.{{ domain }} + debug: + msg: "{{ domain_record }}" + +- name: Delete DNS entry for <{{ record_name }}> if necessary + uri: + method: DELETE + url: "https://api.digitalocean.com/v2/domains/{{ domain }}/records/{{ domain_record.id }}" + headers: + authorization: Bearer {{ digitalocean_authentication_token }} + return_content: yes + status_code: 204 + when: + domain_record.ip != '-' + and record_data != domain_record.ip + delegate_to: 127.0.0.1 + +- name: Create DNS entry for <{{ record_name }}> if necessary + uri: + method: POST + url: "https://api.digitalocean.com/v2/domains/{{ domain }}/records" + headers: + authorization: Bearer {{ digitalocean_authentication_token }} + body: '{{ create_record | to_json }}' + body_format: json + return_content: yes + status_code: 201 + vars: + create_record: + type: 'A' + ttl: 1800 + data: "{{ record_data }}" + name: "{{ record_name }}" + when: + domain_record.ip == '-' + or record_data != domain_record.ip + or record_name != domain_record.name + delegate_to: 127.0.0.1 \ No newline at end of file diff --git a/roles/_digitalocean/vars/main.yml b/roles/_digitalocean/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/_digitalocean/vars/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/hcloud/defaults/main.yml b/roles/hcloud/defaults/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/hcloud/defaults/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/hcloud/handlers/main.yml b/roles/hcloud/handlers/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/hcloud/handlers/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/hcloud/meta/main.yml b/roles/hcloud/meta/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/hcloud/meta/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/hcloud/tasks/main.yml b/roles/hcloud/tasks/main.yml new file mode 100644 index 0000000..96d54aa --- /dev/null +++ b/roles/hcloud/tasks/main.yml @@ -0,0 +1,43 @@ +--- + +### tags: + +- name: Create a new server {{ inventory_hostname }} + hcloud_server: + api_token: "{{ hetzner_authentication_token }}" + name: "{{ inventory_hostname }}" + server_type: "{{ hetzner_server_type }}" + image: "{{ hetzner_server_image }}" + ssh_keys: "{{ hetzner_ssh_keys }}" + state: present + delegate_to: 127.0.0.1 + +- name: Gather current server infos + hcloud_server_info: + api_token: "{{ hetzner_authentication_token }}" + register: hetzner_server_infos + delegate_to: 127.0.0.1 + +- name: Save current server infos as variable (fact) + set_fact: + hetzner_server_infos_json: "{{ hetzner_server_infos.hcloud_server_info }}" + delegate_to: 127.0.0.1 + +- name: Read ip for {{ inventory_hostname }} + set_fact: + stage_server_ip: "{{ item.ipv4_address }}" + when: item.name == inventory_hostname + with_items: "{{ hetzner_server_infos_json }}" + +- name: Print the gathered infos + debug: + var: stage_server_ip + delegate_to: 127.0.0.1 + +- name: "Setup DNS configuration for {{ inventory_hostname }}" + include_role: + name: _digitalocean + tasks_from: domain + vars: + record_data: "{{ stage_server_ip }}" + record_name: "{{ inventory_hostname }}" diff --git a/roles/hcloud/vars/main.yml b/roles/hcloud/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/hcloud/vars/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/hetzner-state/defaults/main.yml b/roles/hetzner-state/defaults/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/hetzner-state/defaults/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/hetzner-state/handlers/main.yml b/roles/hetzner-state/handlers/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/hetzner-state/handlers/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/hetzner-state/meta/main.yml b/roles/hetzner-state/meta/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/hetzner-state/meta/main.yml @@ -0,0 +1 @@ +--- diff --git a/roles/hetzner-state/tasks/main.yml b/roles/hetzner-state/tasks/main.yml new file mode 100644 index 0000000..df11951 --- /dev/null +++ b/roles/hetzner-state/tasks/main.yml @@ -0,0 +1,10 @@ +--- + +### tags: + +- name: Ensure the server {{ inventory_hostname }} is {{ hetzner_state }} + hcloud_server: + api_token: "{{ hetzner_authentication_token }}" + name: "{{ inventory_hostname }}" + state: "{{ hetzner_state }}" + delegate_to: 127.0.0.1 diff --git a/roles/hetzner-state/vars/main.yml b/roles/hetzner-state/vars/main.yml new file mode 100644 index 0000000..ed97d53 --- /dev/null +++ b/roles/hetzner-state/vars/main.yml @@ -0,0 +1 @@ +--- diff --git a/stage-dev b/stage-dev new file mode 100644 index 0000000..f21271c --- /dev/null +++ b/stage-dev @@ -0,0 +1,10 @@ +[hcloud] +dev-elastic-stack-01 +dev-elastic-stack-02 +dev-elastic-stack-03 + +[stage_dev:children] +hcloud + +[all:children] +stage_dev diff --git a/start.yml b/start.yml new file mode 100644 index 0000000..f8dd0e3 --- /dev/null +++ b/start.yml @@ -0,0 +1,21 @@ +--- + +- name: 'apply setup to {{ host | default("all") }}' + hosts: '{{ host | default("all") }}' + serial: "{{ serial_number | default(5) }}" + gather_facts: no + become: no + + pre_tasks: + - name: "Check if ansible version is at least 2.10.x" + assert: + that: + - ansible_version.major >= 2 + - ansible_version.minor >= 10 + msg: "The ansible version has to be at least ({{ ansible_version.full }})" + + roles: + - role: hetzner-state + vars: + hetzner_state: 'started' + when: "'hcloud' in group_names" diff --git a/stop.yml b/stop.yml new file mode 100644 index 0000000..3711047 --- /dev/null +++ b/stop.yml @@ -0,0 +1,21 @@ +--- + +- name: 'apply setup to {{ host | default("all") }}' + hosts: '{{ host | default("all") }}' + serial: "{{ serial_number | default(5) }}" + gather_facts: no + become: no + + pre_tasks: + - name: "Check if ansible version is at least 2.10.x" + assert: + that: + - ansible_version.major >= 2 + - ansible_version.minor >= 10 + msg: "The ansible version has to be at least ({{ ansible_version.full }})" + + roles: + - role: hetzner-state + vars: + hetzner_state: 'stopped' + when: "'hcloud' in group_names"