diff --git a/ansible/playbooks/paas/main.yml b/ansible/playbooks/paas/main.yml index 00b3e201..4a7f7c1a 100644 --- a/ansible/playbooks/paas/main.yml +++ b/ansible/playbooks/paas/main.yml @@ -16,10 +16,27 @@ ansible.builtin.file: path: /etc/ansible/facts.d state: directory - owner: "root" - group: "root" + owner: root + group: root mode: '0755' + - name: Save Public IP as local fact + when: fact_instance.location == 'frontends' + block: + - name: Get ipinfo.io (if backend instance, delegate_to the first frontend) + ansible.builtin.uri: + url: https://ipinfo.io + http_agent: curl/7.81.0 + register: register_uri + check_mode: false + + - name: Set ipinfo local_fact + ansible.builtin.copy: + content: | + {{ register_uri.json | to_nice_json }} + dest: /etc/ansible/facts.d/ipinfo.fact + mode: '0644' + - name: Install mandatories packages ansible.builtin.apt: pkg: diff --git a/ansible/playbooks/paas/metrology.yml b/ansible/playbooks/paas/metrology.yml index ac821230..78b63ab1 100644 --- a/ansible/playbooks/paas/metrology.yml +++ b/ansible/playbooks/paas/metrology.yml @@ -42,7 +42,6 @@ - mongodb_exporter - blackbox_exporter - nginx_exporter - - scan_exporter - dns_exporter - script_exporter - nvidia_gpu_exporter diff --git a/ansible/playbooks/paas/roles/blackbox_exporter/templates/default.j2 b/ansible/playbooks/paas/roles/blackbox_exporter/templates/default.j2 index c5556fa6..3f0fe429 100644 --- a/ansible/playbooks/paas/roles/blackbox_exporter/templates/default.j2 +++ b/ansible/playbooks/paas/roles/blackbox_exporter/templates/default.j2 @@ -1,2 +1,2 @@ ARGS="--config.file=/etc/blackbox_exporter/config.yaml \ ---web.listen-address=127.0.0.1:9115" +--web.listen-address={% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:9115" diff --git a/ansible/playbooks/paas/roles/dns_exporter/templates/default.j2 b/ansible/playbooks/paas/roles/dns_exporter/templates/default.j2 index 03de3a9a..ec64b2ac 100644 --- a/ansible/playbooks/paas/roles/dns_exporter/templates/default.j2 +++ b/ansible/playbooks/paas/roles/dns_exporter/templates/default.j2 @@ -1 +1 @@ -ARGS="-L 127.0.0.1 -c /etc/dns_exporter/config.yml" +ARGS="-L {% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %} -c /etc/dns_exporter/config.yml" diff --git a/ansible/playbooks/paas/roles/node_exporter/templates/default.j2 b/ansible/playbooks/paas/roles/node_exporter/templates/default.j2 index 1289c4c7..389cb76c 100644 --- a/ansible/playbooks/paas/roles/node_exporter/templates/default.j2 +++ b/ansible/playbooks/paas/roles/node_exporter/templates/default.j2 @@ -1,5 +1,5 @@ ARGS="--log.level=info \ ---web.listen-address={{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}:9100 \ +--web.listen-address={% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:9100 \ --web.telemetry-path=/metrics \ --collector.diskstats.ignored-devices='^(ram|loop|fd|(h|s|v|xv)d[a-z]|nbd|nvme[0-9]+n[0-9]+p|md|dm-)[0-9]+$' \ --collector.filesystem.mount-points-exclude='^/(dev(/shm)?|proc|run(/.+)?|sys|var/tmp|(var/lib|home)/(docker|kubelet)/.+)($|/)' \ diff --git a/ansible/playbooks/paas/roles/prometheus/templates/config.j2 b/ansible/playbooks/paas/roles/prometheus/templates/config.j2 index 36b81926..500ee307 100644 --- a/ansible/playbooks/paas/roles/prometheus/templates/config.j2 +++ b/ansible/playbooks/paas/roles/prometheus/templates/config.j2 @@ -66,12 +66,19 @@ scrape_configs: regex: "^(__tmp_keep_me)$" static_configs: -{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project %} +{% if hostvars[inventory_hostname].nomad_mode == 'single' %} + - targets: ['127.0.0.1:9100'] + labels: + instance: "{{ inventory_hostname }}" + project: "{{ prometheus_project }}" +{% elif hostvars[inventory_hostname].nomad_mode == 'cluster' %} +{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project and item != inventory_hostname %} - targets: ['{{ hostvars[item]['ansible_' + hostvars[item].nomad_iface]['ipv4']['address'] }}:9100'] labels: instance: "{{ item }}" project: "{{ prometheus_project }}" {% endfor %} +{% endif %} scrape_interval: 60s scrape_timeout: 59s @@ -91,7 +98,7 @@ scrape_configs: params: script: [speedtest] static_configs: - - targets: ['127.0.0.1:9469'] + - targets: ['{% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:9469'] labels: instance: "{{ inventory_hostname }}" project: "{{ prometheus_project }}" @@ -104,7 +111,7 @@ scrape_configs: regex: "^(go_|prometheus_|promhttp_).*" source_labels: [__name__] static_configs: - - targets: ['127.0.0.1:9469'] + - targets: ['{% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:9469'] labels: instance: "{{ inventory_hostname }}" project: "{{ prometheus_project }}" @@ -115,7 +122,7 @@ scrape_configs: regex: "^(go_|prometheus_|promhttp_).*" source_labels: [__name__] static_configs: - - targets: ['127.0.0.1:15353'] + - targets: ['{% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:15353'] labels: instance: "{{ inventory_hostname }}" project: "{{ prometheus_project }}" @@ -135,7 +142,7 @@ scrape_configs: - source_labels: ["__address__"] target_label: "instance" - target_label: "__address__" - replacement: "127.0.0.1:15353" + replacement: "{% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:15353" - target_label: "monitor" replacement: "{{ inventory_hostname }}" static_configs: @@ -150,10 +157,19 @@ scrape_configs: regex: "^(go_|prometheus_|promhttp_).*" source_labels: [__name__] static_configs: +{% if hostvars[inventory_hostname].nomad_mode == 'single' %} - targets: ['127.0.0.1:9323'] labels: instance: "{{ inventory_hostname }}" project: "{{ prometheus_project }}" +{% elif hostvars[inventory_hostname].nomad_mode == 'cluster' %} +{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project and item != inventory_hostname %} + - targets: ['{{ hostvars[item]['ansible_' + hostvars[item].nomad_iface]['ipv4']['address'] }}:9323'] + labels: + instance: "{{ item }}" + project: "{{ prometheus_project }}" +{% endfor %} +{% endif %} - job_name: "scan_exporter" metric_relabel_configs: @@ -161,7 +177,7 @@ scrape_configs: regex: "^(go_|prometheus_|promhttp_).*" source_labels: [__name__] static_configs: - - targets: ['127.0.0.1:2112'] + - targets: ['{% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:2112'] labels: instance: "{{ inventory_hostname }}" project: "{{ prometheus_project }}" @@ -178,13 +194,19 @@ scrape_configs: tls_config: insecure_skip_verify: true static_configs: -{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project %} +{% if hostvars[inventory_hostname].nomad_mode == 'single' %} + - targets: ['127.0.0.1:9558'] + labels: + instance: "{{ inventory_hostname }}" + project: "{{ prometheus_project }}" +{% elif hostvars[inventory_hostname].nomad_mode == 'cluster' %} +{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project and item != inventory_hostname %} - targets: ['{{ hostvars[item]['ansible_' + hostvars[item].nomad_iface]['ipv4']['address'] }}:9558'] labels: instance: "{{ item }}" project: "{{ prometheus_project }}" {% endfor %} - +{% endif %} - job_name: "nvidia_gpu_exporter" metric_relabel_configs: - action: drop @@ -194,13 +216,19 @@ scrape_configs: format: ['prometheus'] metrics_path: /metrics static_configs: -{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project %} +{% if hostvars[inventory_hostname].nomad_mode == 'single' %} + - targets: ['127.0.0.1:9835'] + labels: + instance: "{{ inventory_hostname }}" + project: "{{ prometheus_project }}" +{% elif hostvars[inventory_hostname].nomad_mode == 'cluster' %} +{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project and item != inventory_hostname %} - targets: ['{{ hostvars[item]['ansible_' + hostvars[item].nomad_iface]['ipv4']['address'] }}:9835'] labels: instance: "{{ item }}" project: "{{ prometheus_project }}" {% endfor %} - +{% endif %} - job_name: "nomad_exporter" metric_relabel_configs: - action: drop @@ -214,13 +242,19 @@ scrape_configs: tls_config: insecure_skip_verify: true static_configs: -{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project %} +{% if hostvars[inventory_hostname].nomad_mode == 'single' %} + - targets: ['127.0.0.1:4646'] + labels: + instance: "{{ inventory_hostname }}" + project: "{{ prometheus_project }}" +{% elif hostvars[inventory_hostname].nomad_mode == 'cluster' %} +{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project and item != inventory_hostname %} - targets: ['{{ hostvars[item]['ansible_' + hostvars[item].nomad_iface]['ipv4']['address'] }}:4646'] labels: instance: "{{ item }}" project: "{{ prometheus_project }}" {% endfor %} - +{% endif %} - job_name: 'mimir_exporter' nomad_sd_configs: - server: "https://{{ nomad_primary_master_address | default(hostvars[inventory_hostname]['ansible_' + hostvars[inventory_hostname].nomad_iface]['ipv4']['address']) }}:4646" @@ -246,16 +280,22 @@ scrape_configs: tls_config: insecure_skip_verify: true static_configs: -{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project %} +{% if hostvars[inventory_hostname].nomad_mode == 'single' %} + - targets: ['127.0.0.1:9080'] + labels: + instance: "{{ inventory_hostname }}" + project: "{{ prometheus_project }}" +{% elif hostvars[inventory_hostname].nomad_mode == 'cluster' %} +{% for item in groups['infrastructure'] | default([]) if item.split('.')[4] == prometheus_project and item != inventory_hostname %} - targets: ['{{ hostvars[item]['ansible_' + hostvars[item].nomad_iface]['ipv4']['address'] }}:9080'] labels: instance: "{{ item }}" project: "{{ prometheus_project }}" {% endfor %} - +{% endif %} - job_name: 'blackbox' static_configs: - - targets: ['127.0.0.1:9115'] + - targets: ['{% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:9115'] labels: instance: "{{ inventory_hostname }}" project: "{{ prometheus_project }}" diff --git a/ansible/playbooks/paas/roles/promtail/templates/config.yaml.j2 b/ansible/playbooks/paas/roles/promtail/templates/config.yaml.j2 index 50a2def9..0bac2b9b 100644 --- a/ansible/playbooks/paas/roles/promtail/templates/config.yaml.j2 +++ b/ansible/playbooks/paas/roles/promtail/templates/config.yaml.j2 @@ -1,5 +1,6 @@ server: - http_listen_address: {{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }} + http_listen_address: {% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %} + http_listen_port: 9080 grpc_listen_port: 0 log_level: warn diff --git a/ansible/playbooks/paas/roles/scan_exporter/tasks/uninstall.yml b/ansible/playbooks/paas/roles/scan_exporter/tasks/uninstall.yml new file mode 100644 index 00000000..38e55e99 --- /dev/null +++ b/ansible/playbooks/paas/roles/scan_exporter/tasks/uninstall.yml @@ -0,0 +1,20 @@ +--- +- name: Scan_exporter | Stopped scan_exporter + ansible.builtin.service: + name: scan_exporter + state: stopped + enabled: false + ignore_errors: true + +- name: Scan_exporter | Remove configuration + ansible.builtin.file: + path: "{{ item.path }}" + state: absent + loop: + - path: /etc/default/scan_exporter + - path: /etc/scan_exporter/config.yml + - path: /etc/systemd/system/scan_exporter.service + +- name: Scan_exporter | Daemon reload + ansible.builtin.systemd_service: + daemon_reload: true diff --git a/ansible/playbooks/paas/roles/scan_exporter/templates/config.yml.j2 b/ansible/playbooks/paas/roles/scan_exporter/templates/config.yml.j2 index 23e26b10..81b86a2b 100644 --- a/ansible/playbooks/paas/roles/scan_exporter/templates/config.yml.j2 +++ b/ansible/playbooks/paas/roles/scan_exporter/templates/config.yml.j2 @@ -10,7 +10,7 @@ tcp_period: 6h targets: [] {% else %} targets: -{% for host in groups['infrastructure'] if (fact_instance.location in ['frontends', 'frontends_vrack'] and host != inventory_hostname) %} +{% for host in groups['infrastructure'] if (host.split(".")[1] == 'frontends' and host != inventory_hostname) %} - name: "{{ host }}" ip: "{{ hostvars[host].ansible_local.ipinfo.ip }}" queries_per_sec: 500 diff --git a/ansible/playbooks/paas/roles/scan_exporter/templates/default.j2 b/ansible/playbooks/paas/roles/scan_exporter/templates/default.j2 index d9990808..940faadc 100644 --- a/ansible/playbooks/paas/roles/scan_exporter/templates/default.j2 +++ b/ansible/playbooks/paas/roles/scan_exporter/templates/default.j2 @@ -1 +1 @@ -ARGS="-metric.addr 127.0.0.1:2112 -config /etc/scan_exporter/config.yml" +ARGS="-metric.addr {% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:2112 -config /etc/scan_exporter/config.yml" diff --git a/ansible/playbooks/paas/roles/script_exporter/templates/default.j2 b/ansible/playbooks/paas/roles/script_exporter/templates/default.j2 index 4bfa0fb3..a3fde25f 100644 --- a/ansible/playbooks/paas/roles/script_exporter/templates/default.j2 +++ b/ansible/playbooks/paas/roles/script_exporter/templates/default.j2 @@ -1 +1 @@ -ARGS="--config.files=/etc/script_exporter/config.yml" +ARGS="--config.files=/etc/script_exporter/config.yml --web.listen-address={% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:9469" diff --git a/ansible/playbooks/paas/roles/systemd_exporter/templates/default.j2 b/ansible/playbooks/paas/roles/systemd_exporter/templates/default.j2 index f64efe14..53d370e3 100644 --- a/ansible/playbooks/paas/roles/systemd_exporter/templates/default.j2 +++ b/ansible/playbooks/paas/roles/systemd_exporter/templates/default.j2 @@ -1,2 +1,2 @@ -ARGS="--web.listen-address={{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}:9558 \ +ARGS="--web.listen-address={% if hostvars[inventory_hostname].nomad_mode == 'single' %}127.0.0.1{% else %}{{ hostvars[inventory_hostname]['ansible_' + nomad_iface]['ipv4']['address'] }}{% endif %}:9558 \ --systemd.collector.unit-include=docker.service|promtail.service|coredns.service|prometheus.service|blackbox_exporter.service|node_exporter.service|scan_exporter.service" diff --git a/ansible/playbooks/paas/scan_exporter.yml b/ansible/playbooks/paas/scan_exporter.yml new file mode 100644 index 00000000..cfb1171f --- /dev/null +++ b/ansible/playbooks/paas/scan_exporter.yml @@ -0,0 +1,10 @@ +--- +- name: Uninstall scan_exporter + any_errors_fatal: true + hosts: "{{ hosts_limit | default('infrastructure') }}" + gather_facts: true + become: true + pre_tasks: + - name: Uninstall scan_exporter + ansible.builtin.include_role: + name: scan_exporter \ No newline at end of file diff --git a/ansible/playbooks/saas/image.yml b/ansible/playbooks/saas/image.yml index 8cbd717a..cc8bb94a 100644 --- a/ansible/playbooks/saas/image.yml +++ b/ansible/playbooks/saas/image.yml @@ -69,6 +69,7 @@ schema: catalogs_create data: name: "{{ image_definition.name }}" + forkable: "{{ image_definition.forkable | default(false) }}" version: "{{ image_version }}" force_basic_auth: true status_code: 200 diff --git a/ansible/playbooks/saas/mimirtools.yml b/ansible/playbooks/saas/mimirtools.yml index c683a0ea..cf617e17 100644 --- a/ansible/playbooks/saas/mimirtools.yml +++ b/ansible/playbooks/saas/mimirtools.yml @@ -23,6 +23,10 @@ state: directory mode: '0755' + - name: Get alertmanager configuration + set_fact: + alertmanager: "{{ lookup('simple-stack-ui', type='secret', key=endpoint, subkey='alertmanager', missing='warn') | from_json }}" + tasks: - name: Deploy configuration ansible.builtin.include_role: diff --git a/ansible/playbooks/saas/operate.yml b/ansible/playbooks/saas/operate.yml index d10aa5be..9259fba0 100644 --- a/ansible/playbooks/saas/operate.yml +++ b/ansible/playbooks/saas/operate.yml @@ -7,6 +7,9 @@ - name: catalog prompt: Catalog item private: false + - name: project + prompt: project name + private: false - name: domain prompt: Domain name private: false diff --git a/ansible/playbooks/saas/roles/adguard/templates/nomad.hcl b/ansible/playbooks/saas/roles/adguard/templates/nomad.hcl index 3bb996f3..26129dc0 100644 --- a/ansible/playbooks/saas/roles/adguard/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/adguard/templates/nomad.hcl @@ -45,7 +45,7 @@ job "{{ domain }}" { driver = "docker" config { - image = "{{ software }}:{{ softwares.adguard.version }}" + image = "{{ docker_private_registry.url }}/adguard:{{ softwares.adguard.version }}" network_mode = "host" privileged = "true" volumes = [ diff --git a/ansible/playbooks/saas/roles/freqtrade/README.md b/ansible/playbooks/saas/roles/freqtrade/README.md new file mode 100644 index 00000000..f680977e --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/README.md @@ -0,0 +1,21 @@ +# Role: `freqtrade` + +## How to use this Ansible role? + +1. Create your private user_data repository + +2. Configure your software variable on UI + +``` +strategy: MyCustomStrategy +config: myconfig +``` + +3. Configure your secret yaml configuration + +``` +git_user_data: + repo: http://mydomain.com/muser/myrepo.git + version: latest + token: s3cret! +``` \ No newline at end of file diff --git a/ansible/playbooks/saas/roles/freqtrade/defaults/main.yml b/ansible/playbooks/saas/roles/freqtrade/defaults/main.yml new file mode 100644 index 00000000..ed97d539 --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/defaults/main.yml @@ -0,0 +1 @@ +--- diff --git a/ansible/playbooks/saas/roles/freqtrade/tasks/backup.yml b/ansible/playbooks/saas/roles/freqtrade/tasks/backup.yml new file mode 100644 index 00000000..ed97d539 --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/tasks/backup.yml @@ -0,0 +1 @@ +--- diff --git a/ansible/playbooks/saas/roles/freqtrade/tasks/build.yml b/ansible/playbooks/saas/roles/freqtrade/tasks/build.yml new file mode 100644 index 00000000..f1029407 --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/tasks/build.yml @@ -0,0 +1,12 @@ +--- +- name: Include upstream variables + ansible.builtin.include_vars: upstream.yml + +- name: Set custom variables + ansible.builtin.set_fact: + image_version: "{{ latest_version }}" + image_definition: "{{ image }}" + +- name: End playbook if no new version + ansible.builtin.meta: end_host + when: softwares[catalog_image_name] is defined and softwares[catalog_image_name].version == image_version diff --git a/ansible/playbooks/saas/roles/freqtrade/tasks/destroy.yml b/ansible/playbooks/saas/roles/freqtrade/tasks/destroy.yml new file mode 100644 index 00000000..e69de29b diff --git a/ansible/playbooks/saas/roles/freqtrade/tasks/main.yml b/ansible/playbooks/saas/roles/freqtrade/tasks/main.yml new file mode 100644 index 00000000..436fa0c5 --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/tasks/main.yml @@ -0,0 +1,32 @@ +--- +- name: Create default directories + ansible.builtin.file: + path: "{{ item }}" + state: directory + owner: 1000 + group: 1000 + mode: '0755' + loop: + - "{{ software_path }}/db" + delegate_to: "{{ software.instance }}" + +- name: Checkout user data configurations + ansible.builtin.git: + repo: "{{ (lookup('simple-stack-ui', type='secret', key=domain, subkey='git_user_data', missing='error') | from_json).repo }}" + dest: "{{ software_path }}/freqtrade" + delegate_to: "{{ software.instance }}" + +- name: Copy nomad job to destination + ansible.builtin.template: + src: nomad.hcl + dest: "/var/tmp/{{ domain }}.nomad" + owner: root + group: root + mode: '0600' + become: true + delegate_to: "{{ software.instance }}" + +- name: Run nomad job + ansible.builtin.include_role: + name: nomad + tasks_from: job_run.yml diff --git a/ansible/playbooks/saas/roles/freqtrade/tasks/restore.yml b/ansible/playbooks/saas/roles/freqtrade/tasks/restore.yml new file mode 100644 index 00000000..ed97d539 --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/tasks/restore.yml @@ -0,0 +1 @@ +--- diff --git a/ansible/playbooks/saas/roles/freqtrade/templates/nomad.hcl b/ansible/playbooks/saas/roles/freqtrade/templates/nomad.hcl new file mode 100644 index 00000000..dd2425c8 --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/templates/nomad.hcl @@ -0,0 +1,91 @@ +job "{{ domain }}" { + region = "{{ fact_instance.region }}" + datacenters = ["{{ fact_instance.datacenter }}"] + type = "service" + +{% if software.constraints is defined and software.constraints.location is defined %} + constraint { + attribute = "${meta.location}" + set_contains = "{{ software.constraints.location }}" + } +{% endif %} + + constraint { + attribute = "${meta.instance}" + set_contains = "{{ software.instance }}" + } + + group "freqtrade" { + + count = 1 + + restart { + attempts = 2 + interval = "10m" + delay = "15s" + mode = "fail" + } + + network { + port "http" { + to = 8080 + } + } + + service { + name = "http" + port = "http" + provider = "nomad" + tags = [ + {{ lookup('template', '../../traefik/templates/traefik_tag.j2') | indent(8) }} + ] + check { + name = "traefik" + type = "tcp" + interval = "60s" + timeout = "30s" + check_restart { + limit = 3 + grace = "90s" + ignore_warnings = false + } + } + } + + task "freqtrade" { + + driver = "docker" + + kill_signal = "SIGTERM" + + env { +{% for env in (lookup('simple-stack-ui', type='secret', key=domain, subkey='additional_env', missing='warn') | from_json) | default(litellm_env) %} + {{ env.key }} = "{{ env.value }}" +{% endfor %} + } + config { + image = "freqtradeorg/freqtrade:{{ softwares.freqtrade.version }}" + volumes = [ + "{{ software_path }}/freqtrade/user_data:/freqtrade/user_data:rw", + "{{ software_path }}/db:/db:rw" + ] + ports = ["http"] + + command = "trade" + args = [ + "--config", + "/freqtrade/user_data/{{ software.config }}.json", + "--db-url", + "sqlite:////db/tradesv3{{ software.strategy }}.sqlite", + "--strategy", + "{{ software.strategy }}" + ] + } + + resources { + cpu = {{ size[software.size].cpu }} + memory = {{ size[software.size].memory }} + } + } + } +} diff --git a/ansible/playbooks/saas/roles/freqtrade/vars/main.yml b/ansible/playbooks/saas/roles/freqtrade/vars/main.yml new file mode 100644 index 00000000..af56e93c --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/vars/main.yml @@ -0,0 +1,11 @@ +--- +image: + build: false + forkable: false + upstream: + source: github + user: freqtrade + repo: freqtrade + type: release + labels: {} + name: freqtrade diff --git a/ansible/playbooks/saas/roles/freqtrade/vars/upstream.yml b/ansible/playbooks/saas/roles/freqtrade/vars/upstream.yml new file mode 100644 index 00000000..74d50b0a --- /dev/null +++ b/ansible/playbooks/saas/roles/freqtrade/vars/upstream.yml @@ -0,0 +1,2 @@ +--- +latest_version: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/releases/latest', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN') }) | from_json).get('tag_name') | replace('v', '') }}" diff --git a/ansible/playbooks/saas/roles/homeassistant/templates/nomad.hcl b/ansible/playbooks/saas/roles/homeassistant/templates/nomad.hcl index 68e101f1..663016dd 100644 --- a/ansible/playbooks/saas/roles/homeassistant/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/homeassistant/templates/nomad.hcl @@ -67,9 +67,14 @@ job "{{ domain }}" { config { image = "homeassistant/home-assistant:{{ softwares.homeassistant.version }}" + privileged = "true" volumes = [ - "/data/{{ domain }}/config:/config:rw" + "/data/{{ domain }}/config:/config:rw", + "/run/dbus:/run/dbus:ro" ] + + cap_add = ["net_admin", "net_raw"] + ports = ["homeassistant"] } diff --git a/ansible/playbooks/saas/roles/litellm/vars/upstream.yml b/ansible/playbooks/saas/roles/litellm/vars/upstream.yml index e8085f91..95b30dd7 100644 --- a/ansible/playbooks/saas/roles/litellm/vars/upstream.yml +++ b/ansible/playbooks/saas/roles/litellm/vars/upstream.yml @@ -1,3 +1,3 @@ --- upstream_versions: "{{ (lookup('url', 'https://api.github.com/repos/' + image.upstream.user + '/' + image.upstream.repo + '/tags', headers={'Accept': 'application/vnd.github+json', 'Authorization': 'Bearer ' + lookup('ansible.builtin.env', 'GITHUB_API_TOKEN') })) }}" -latest_version: "{{ upstream_versions | community.general.json_query('[].name') | select('match', '^(v|r)?\\d{1,4}(\\.\\d{1,4})(\\.\\d{1,4})(-stable)$') | community.general.version_sort | last | replace('v', '') }}" \ No newline at end of file +latest_version: "{{ upstream_versions | from_json | community.general.json_query('[].name') | select('match', '^(v)?\\d{1,4}(\\.\\d{1,4})(\\.\\d{1,4})(-stable)$') | community.general.version_sort | last | replace('v', '') }}" \ No newline at end of file diff --git a/ansible/playbooks/saas/roles/mimir/README.md b/ansible/playbooks/saas/roles/mimir/README.md index 0c600f91..11baffa9 100644 --- a/ansible/playbooks/saas/roles/mimir/README.md +++ b/ansible/playbooks/saas/roles/mimir/README.md @@ -12,3 +12,17 @@ www.domain.com: domain_alias: domain.com # (string) Primary domain name for the application. ipfilter: [] # (list) List of allowed IPs for access control (empty for unrestricted access). basic_auth: False # (bool) Enable/disable HTTP Basic Authentication (True/False). +``` + +# Configure alertmanager + +If you want to send alertmanager alert to a custom receiver, add a secret to your domain in the UI: + +``` +alertmanager: + receivers: + - name: default + webhook_configs: + - url: https://www.myreceiver.com/api/webhook/ + send_resolved: true +``` \ No newline at end of file diff --git a/ansible/playbooks/saas/roles/mimir/templates/user.alertmanager.yml.j2 b/ansible/playbooks/saas/roles/mimir/templates/user.alertmanager.yml.j2 index 8b620f0c..c3422568 100644 --- a/ansible/playbooks/saas/roles/mimir/templates/user.alertmanager.yml.j2 +++ b/ansible/playbooks/saas/roles/mimir/templates/user.alertmanager.yml.j2 @@ -7,14 +7,10 @@ route: repeat_interval: 90m group_interval: 5m group_wait: 60s - receiver: http_remote_api + receiver: default routes: - #- receiver: telegram_receiver - # match_re: - # severity: critical|warning - # continue: true - - receiver: http_remote_api + - receiver: default match_re: severity: critical|warning continue: true @@ -27,17 +23,7 @@ inhibit_rules: # Apply inhibition if the alertname is the same. equal: ['alertname', 'cluster', 'service'] -receivers: - - name: 'http_remote_api' - webhook_configs: - - url: 'https://remote_api/api/alerts/trigger' - http_config: - authorization: - credentials: "credz" - send_resolved: true +receivers: {% if alertmanager.receivers is not defined %}[]{% endif %} + +{{ alertmanager.receivers | default('') | to_nice_yaml(indent=4) }} -# - name: telegram_receiver -# telegram_configs: -# - api_url: 'https://api.telegram.org' -# bot_token: '{{ notifications.telegram.token | default('') }}' -# chat_id: {{ notifications.telegram.chat_id | default('') }} diff --git a/ansible/playbooks/saas/roles/nomad/templates/backup.hcl.j2 b/ansible/playbooks/saas/roles/nomad/templates/backup.hcl.j2 index 1c0e4b1a..9d1f18ff 100644 --- a/ansible/playbooks/saas/roles/nomad/templates/backup.hcl.j2 +++ b/ansible/playbooks/saas/roles/nomad/templates/backup.hcl.j2 @@ -49,17 +49,16 @@ job "{{ nomad_job_name }}" { } } -{% if restic_backup is defined and restic_backup %} task "{{ domain }}-export" { driver = "docker" env { - RESTIC_SERVER = "{{ restic_server }}" - RESTIC_HOST = "{{ restic_host }}" - RESTIC_SNAPSHOTS = "{{ restic_snapshots }}" + RESTIC_SERVER = "{{ lookup('simple-stack-ui', type='project', key=project, subkey='restic_server', missing='error') }}" + RESTIC_HOST = "{{ lookup('simple-stack-ui', type='project', key=project, subkey='restic_host', missing='error') }}" + RESTIC_SNAPSHOTS = "{{ lookup('simple-stack-ui', type='project', key=project, subkey='restic_snapshots', missing='error') }}" RESTIC_REPOSITORY = "{{ domain | lower }}" - RESTIC_PASSWORD = "{{ lookup('simple-stack-ui', type='secret', key=restic_server, subkey='passwd', missing='error') }}" - AWS_ACCESS_KEY_ID = "{{ lookup('simple-stack-ui', type='secret', key=restic_server, subkey='user', missing='error') }}" - AWS_SECRET_ACCESS_KEY = "{{ lookup('simple-stack-ui', type='secret', key=restic_server, subkey='passwd', missing='error') }}" + RESTIC_PASSWORD = "{{ lookup('simple-stack-ui', type='project', key=project, subkey='restic_passwd', missing='error') }}" + AWS_ACCESS_KEY_ID = "{{ lookup('simple-stack-ui', type='project', key=project, subkey='restic_user', missing='error') }}" + AWS_SECRET_ACCESS_KEY = "{{ lookup('simple-stack-ui', type='project', key=project, subkey='restic_passwd', missing='error') }}" } config { image = "alpine:latest" @@ -73,7 +72,6 @@ job "{{ nomad_job_name }}" { memory_max = 1024 } } -{% endif %} task "{{ domain }}-clean" { lifecycle { diff --git a/ansible/playbooks/saas/roles/traefik/templates/nomad.hcl b/ansible/playbooks/saas/roles/traefik/templates/nomad.hcl index cf901f86..b083df5f 100644 --- a/ansible/playbooks/saas/roles/traefik/templates/nomad.hcl +++ b/ansible/playbooks/saas/roles/traefik/templates/nomad.hcl @@ -61,7 +61,7 @@ job "{{ domain }}" { } } - task "traefik" { + task "{{ domain }}" { driver = "docker" diff --git a/ansible/playbooks/saas/roles/wordpress/files/backup b/ansible/playbooks/saas/roles/wordpress/files/backup index aeade5c1..9012362b 100644 --- a/ansible/playbooks/saas/roles/wordpress/files/backup +++ b/ansible/playbooks/saas/roles/wordpress/files/backup @@ -6,3 +6,12 @@ tar -czf /var/backup/data.tgz -C /var/www/html . echo "Backup database..." /usr/bin/wp-cli db export --allow-root --path=/var/www/html /var/backup/dump.sql + +echo "Upgrade core..." +/usr/bin/wp-cli core update --allow-root --path=/var/www/html + +echo "Upgrade plugins..." +/usr/bin/wp-cli plugin update --all --allow-root --path=/var/www/html + +echo "Upgrade themes..." +/usr/bin/wp-cli theme update --all --allow-root --path=/var/www/html \ No newline at end of file diff --git a/ansible/requirements.yml b/ansible/requirements.yml index 1e3d1860..07162301 100644 --- a/ansible/requirements.yml +++ b/ansible/requirements.yml @@ -3,10 +3,10 @@ collections: - name: cloud.terraform version: 4.0.0 - name: community.general - version: 10.2.0 + version: 12.0.1 - name: community.docker - version: 4.0.0 + version: 5.0.1 - name: community.postgresql - version: 3.12.0 + version: 4.1.0 - name: ansible.eda - version: 2.8.0 + version: 2.10.0 diff --git a/ansible/rulebook.yml b/ansible/rulebook.yml index 9eb42898..61aa3a4c 100644 --- a/ansible/rulebook.yml +++ b/ansible/rulebook.yml @@ -91,6 +91,7 @@ name: playbooks/saas/operate.yml extra_vars: hosts_limit: "{{ event.payload.meta.hosts }}" + project: "{{ event.payload.project }}" catalog: "{{ event.payload.catalog }}" domain: "{{ event.payload.domain }}" task: "{{ event.payload.task }}" diff --git a/ui/index.js.map b/ui/index.js.map index 2e07593c..e4be137c 100644 --- a/ui/index.js.map +++ b/ui/index.js.map @@ -249,7 +249,7 @@ "auth": 1, "params": "id:string", "id": "softwares_update", - "input": "*size:String, domain_alias:String, *exposition:String", + "input": "*instance:String, *software:UID, *size:String, *domain:String, domain_alias:String, *exposition:String", "name": "Update software" }, { @@ -522,7 +522,7 @@ { "name": "Softwares/update", "params": "*id:UID", - "input": "*size:String, domain_alias:String, *exposition:String" + "input": "*instance:String, *software:UID, *size:String, *domain:String, domain_alias:String, *exposition:String" }, { "name": "Softwares/update_version", diff --git a/ui/public/forms/catalogs.html b/ui/public/forms/catalogs.html index 9bdce250..ddd84de3 100644 --- a/ui/public/forms/catalogs.html +++ b/ui/public/forms/catalogs.html @@ -25,7 +25,7 @@ @@ -56,15 +53,9 @@ var model = exports.model; if(typeof model.item.id == 'undefined'){ $('#info').attr('hidden', true); - $('#instance').attr('hidden', false); - $('#software').attr('hidden', false); - $('#domain').attr('hidden', false); } else { $('#info').attr('hidden', false); - $('#instance').attr('hidden', true); - $('#software').attr('hidden', true); - $('#domain').attr('hidden', true); } header.reconfigure({ title: model.item.id ? '@(Update software)' : '@(Add software)' }); @@ -78,7 +69,6 @@ CLRELOAD('cl'); SETTER('notify/success', '@(Done)'); caller.exec('refresh'); - caller.exec('refreshGraph'); }); }; }); diff --git a/ui/public/img/freqtrade.png b/ui/public/img/freqtrade.png new file mode 100644 index 00000000..644982b5 Binary files /dev/null and b/ui/public/img/freqtrade.png differ diff --git a/ui/schemas/softwares.js b/ui/schemas/softwares.js index c623c947..9e8a2c4a 100644 --- a/ui/schemas/softwares.js +++ b/ui/schemas/softwares.js @@ -144,7 +144,7 @@ NEWSCHEMA('Softwares', function (schema) { schema.action('update', { name: 'Update software', params: '*id:UID', - input: '*size:String, domain_alias:String, *exposition:String', + input: '*instance:String, *software:UID, *size:String, *domain:String, domain_alias:String, *exposition:String', action: async function ($, model) { const rules = { size: { regex: REGEX_SOFTWARES.size, comment: REGEX_SOFTWARES.size.comment }, @@ -220,6 +220,7 @@ NEWSCHEMA('Softwares', function (schema) { const payload = { meta: { hosts: item.instance }, + project: item.instance.split('.').pop(), type: 'saas-operate', catalog: catalogName, domain: item.domain,