Skip to content

Commit

Permalink
Use variables from ansible_facts
Browse files Browse the repository at this point in the history
to allow ANSIBLE_INJECT_FACT_VARS to become false
  • Loading branch information
kleini committed Nov 28, 2024
1 parent 09c6fee commit c7e8348
Show file tree
Hide file tree
Showing 33 changed files with 59 additions and 56 deletions.
3 changes: 3 additions & 0 deletions .config/molecule/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,8 @@ platforms:
privileged: true
cgroup_parent: docker.slice
command: /lib/systemd/systemd
provisioner:
env:
ANSIBLE_INJECT_FACT_VARS: false
verifier:
name: testinfra
4 changes: 2 additions & 2 deletions examples/promtail-multiple-logs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
- localhost
labels:
job: messages
instance: "{{ ansible_fqdn }}"
instance: "{{ ansible_facts['fqdn'] }}"
__path__: /var/log/messages
- targets:
- localhost
labels:
job: nginx
instance: "{{ ansible_fqdn }}"
instance: "{{ ansible_facts['fqdn'] }}"
__path__: /var/log/nginx/*.log
4 changes: 2 additions & 2 deletions roles/alloy/tasks/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
- name: Include RedHat/Rocky setup
ansible.builtin.include_tasks:
file: setup-RedHat.yml
when: ansible_os_family in ['RedHat', 'Rocky']
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']

- name: Include Debian/Ubuntu setup
ansible.builtin.include_tasks:
file: setup-Debian.yml
when: ansible_os_family == 'Debian'
when: ansible_facts['os_family'] == 'Debian'

- name: Alloy systemd override
when: alloy_systemd_override | length > 0
Expand Down
2 changes: 1 addition & 1 deletion roles/alloy/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# tasks file for alloy
- name: Include OS specific variables
ansible.builtin.include_vars:
file: "{{ ansible_os_family }}.yml"
file: "{{ ansible_facts['os_family'] }}.yml"

- name: Preflight
ansible.builtin.include_tasks:
Expand Down
4 changes: 2 additions & 2 deletions roles/alloy/tasks/uninstall.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
name: "alloy"
state: absent
autoremove: true
when: ansible_os_family in ['RedHat', 'Rocky']
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']

- name: Uninstall Alloy deb package
ansible.builtin.apt:
name: "alloy"
state: absent
purge: true
when: ansible_os_family == 'Debian'
when: ansible_facts['os_family'] == 'Debian'

- name: Ensure that Alloy firewalld rule is not present - tcp port {{ __alloy_server_http_listen_port }}
ansible.posix.firewalld: # noqa ignore-errors
Expand Down
2 changes: 1 addition & 1 deletion roles/alloy/vars/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ __alloy_arch_map:
armv6l: 'arm'
armv7l: 'arm'
aarch64: 'arm64'
__alloy_arch: "{{ __alloy_arch_map[ansible_architecture] | default(ansible_architecture) }}"
__alloy_arch: "{{ __alloy_arch_map[ansible_facts['architecture']] | default(ansible_facts['architecture']) }}"
6 changes: 3 additions & 3 deletions roles/grafana/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ All variables which can be overridden are stored in [defaults/main.yml](defaults
| `grafana_rhsm_subscription` | | rhsm subscription name (redhat subscription-manager) |
| `grafana_rhsm_repo` | | rhsm repository name (redhat subscription-manager) |
| `grafana_apt_release_channel` | stable | Apt release chanel (stable or beta) |
| `grafana_apt_arch` | {{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }} | Apt architecture |
| `grafana_apt_arch` | {{ 'arm64' if ansible_facts['architecture'] == 'aarch64' else 'amd64' }} | Apt architecture |
| `grafana_apt_repo` | deb [arch={{ grafana_apt_arch }} signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com/ {{ grafana_apt_release_channel }} main | Apt repository string |
| `grafana_apt_key` | https://apt.grafana.com/gpg.key | Apt repository gpg key |
| `grafana_instance` | {{ ansible_fqdn \| default(ansible_host) \| default(inventory_hostname) }} | Grafana instance name |
| `grafana_instance` | {{ ansible_facts['fqdn'] \| default(ansible_host) \| default(inventory_hostname) }} | Grafana instance name |
| `grafana_logs_dir` | /var/log/grafana | Path to logs directory |
| `grafana_data_dir` | /var/lib/grafana | Path to database directory |
| `grafana_address` | 0.0.0.0 | Address on which Grafana listens |
| `grafana_port` | 3000 | port on which Grafana listens |
| `grafana_cap_net_bind_service` | false | Enables the use of ports below 1024 without root privileges by leveraging the 'capabilities' of the linux kernel. read: http://man7.org/linux/man-pages/man7/capabilities.7.html |
| `grafana_url` | "http://{{ grafana_address }}:{{ grafana_port }}" | Full URL used to access Grafana from a web browser |
| `grafana_api_url` | "{{ grafana_url }}" | URL used for API calls in provisioning if different from public URL. See [this issue](https://github.com/cloudalchemy/ansible-grafana/issues/70). |
| `grafana_domain` | "{{ ansible_fqdn \| default(ansible_host) \| default('localhost') }}" | setting is only used in as a part of the `root_url` option. Useful when using GitHub or Google OAuth |
| `grafana_domain` | "{{ ansible_facts['fqdn'] \| default(ansible_host) \| default('localhost') }}" | setting is only used in as a part of the `root_url` option. Useful when using GitHub or Google OAuth |
| `grafana_server` | { protocol: http, enforce_domain: false, socket: "", cert_key: "", cert_file: "", enable_gzip: false, static_root_path: public, router_logging: false } | [server](http://docs.grafana.org/installation/configuration/#server) configuration section |
| `grafana_security` | { admin_user: admin, admin_password: "" } | [security](http://docs.grafana.org/installation/configuration/#security) configuration section |
| `grafana_database` | { type: sqlite3 } | [database](http://docs.grafana.org/installation/configuration/#database) configuration section |
Expand Down
6 changes: 3 additions & 3 deletions roles/grafana/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ grafana_rhsm_subscription: ""
grafana_rhsm_repo: ""

grafana_apt_release_channel: stable
grafana_apt_arch: "{{ 'arm64' if ansible_architecture == 'aarch64' else 'amd64' }}"
grafana_apt_arch: "{{ 'arm64' if ansible_facts['architecture'] == 'aarch64' else 'amd64' }}"
grafana_apt_repo: "deb [arch={{ grafana_apt_arch }} signed-by=/usr/share/keyrings/grafana.key] https://apt.grafana.com/ {{ grafana_apt_release_channel }} main"
grafana_apt_key: "https://apt.grafana.com/gpg.key"

Expand All @@ -19,7 +19,7 @@ grafana_use_provisioning: true
# Should the provisioning be kept synced. If true, previous provisioned objects will be removed if not referenced anymore.
grafana_provisioning_synced: false

grafana_instance: "{{ ansible_fqdn | default(ansible_host) | default(inventory_hostname) }}"
grafana_instance: "{{ ansible_facts['fqdn'] | default(ansible_host) | default(inventory_hostname) }}"

grafana_logs_dir: "/var/log/grafana"
grafana_data_dir: "/var/lib/grafana"
Expand All @@ -34,7 +34,7 @@ grafana_cap_net_bind_service: false
# External Grafana address. Variable maps to "root_url" in grafana server section
grafana_url: "http://{{ grafana_address }}:{{ grafana_port }}"
grafana_api_url: "{{ grafana_url }}"
grafana_domain: "{{ ansible_fqdn | default(ansible_host) | default('localhost') }}"
grafana_domain: "{{ ansible_facts['fqdn'] | default(ansible_host) | default('localhost') }}"

# Additional options for grafana "server" section
# This section WILL omit options for: http_addr, http_port, domain, and root_url, as those settings are set by variables listed before
Expand Down
4 changes: 2 additions & 2 deletions roles/grafana/tasks/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@

- name: "Prepare yum/dnf"
when:
- "ansible_pkg_mgr in ['yum', 'dnf']"
- "ansible_facts['pkg_mgr'] in ['yum', 'dnf']"
- "(grafana_manage_repo)"
environment: "{{ grafana_environment }}"
block:
Expand Down Expand Up @@ -66,7 +66,7 @@

- name: "Prepare apt"
when:
- "ansible_pkg_mgr == 'apt'"
- "ansible_facts['pkg_mgr'] == 'apt'"
- "(grafana_manage_repo)"
environment: "{{ grafana_environment }}"
block:
Expand Down
10 changes: 5 additions & 5 deletions roles/grafana/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
params:
skip: true
files:
- "{{ ansible_distribution | lower }}-{{ ansible_distribution_version | lower }}.yml"
- "{{ ansible_distribution | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
- "{{ ansible_os_family | lower }}-{{ ansible_distribution_major_version | lower }}.yml"
- "{{ ansible_distribution | lower }}.yml"
- "{{ ansible_os_family | lower }}.yml"
- "{{ ansible_facts['distribution'] | lower }}-{{ ansible_facts['distribution']_version | lower }}.yml"
- "{{ ansible_facts['distribution'] | lower }}-{{ ansible_facts['distribution']_major_version | lower }}.yml"
- "{{ ansible_facts['os_family'] | lower }}-{{ ansible_facts['distribution']_major_version | lower }}.yml"
- "{{ ansible_facts['distribution'] | lower }}.yml"
- "{{ ansible_facts['os_family'] | lower }}.yml"
paths:
- "vars/distro"
tags:
Expand Down
2 changes: 1 addition & 1 deletion roles/grafana/vars/distro/debian.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
grafana_package: "grafana{% if ansible_architecture == 'armv6l' %}-rpi{% endif %}{{ (grafana_version != 'latest') | ternary('=' ~ grafana_version, '') }}"
grafana_package: "grafana{% if ansible_facts['architecture'] == 'armv6l' %}-rpi{% endif %}{{ (grafana_version != 'latest') | ternary('=' ~ grafana_version, '') }}"
_grafana_dependencies:
- apt-transport-https
- adduser
Expand Down
2 changes: 1 addition & 1 deletion roles/grafana_agent/tasks/preflight/systemd.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
- name: Assert usage of systemd as an init system
ansible.builtin.assert:
that: ansible_service_mgr == 'systemd'
that: ansible_facts['service_mgr'] == 'systemd'
msg: This role only works with systemd

- name: Get systemd version # noqa command-instead-of-module
Expand Down
2 changes: 1 addition & 1 deletion roles/grafana_agent/templates/EnvironmentFile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Grafana Agent Environment File
AGENT_MODE={{ grafana_agent_mode }}

GOMAXPROCS={{ ansible_processor_vcpus|default(ansible_processor_count) }}
GOMAXPROCS={{ ansible_facts['processor_vcpus']|default(ansible_facts['processor_count']) }}

{% for key, value in grafana_agent_env_file_vars.items() %}
{{key}}={{value}}
Expand Down
4 changes: 2 additions & 2 deletions roles/grafana_agent/vars/main.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ _download_cpu_arch_map:
armv7l: armv7
armv6l: armv6

_grafana_agent_cpu_arch: "{{ _download_cpu_arch_map[ansible_architecture] | default(ansible_architecture) }}"
_grafana_agent_cpu_arch: "{{ _download_cpu_arch_map[ansible_facts['architecture']] | default(ansible_facts['architecture']) }}"

# set the go os family
_grafana_agent_os_family: "{{ ansible_system | lower }}"
_grafana_agent_os_family: "{{ ansible_facts['system'] | lower }}"

# set the name of the archive file to download
_grafana_agent_download_archive_file: "grafana-agent-{{ _grafana_agent_os_family }}-{{ _grafana_agent_cpu_arch }}.zip"
Expand Down
4 changes: 2 additions & 2 deletions roles/loki/tasks/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@
- name: Include RedHat/Rocky setup
ansible.builtin.include_tasks:
file: setup-RedHat.yml
when: ansible_os_family in ['RedHat', 'Rocky']
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']

- name: Include Debian/Ubuntu setup
ansible.builtin.include_tasks:
file: setup-Debian.yml
when: ansible_os_family == 'Debian'
when: ansible_facts['os_family'] == 'Debian'

- name: Check if Loki default dir is present
ansible.builtin.stat:
Expand Down
2 changes: 1 addition & 1 deletion roles/loki/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# tasks file for loki
- name: Include OS specific variables
ansible.builtin.include_vars:
file: "{{ ansible_os_family }}.yml"
file: "{{ ansible_facts['os_family'] }}.yml"

- name: Deploy Loki service
ansible.builtin.include_tasks:
Expand Down
4 changes: 2 additions & 2 deletions roles/loki/tasks/uninstall.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
name: "loki"
state: absent
autoremove: true
when: ansible_os_family in ['RedHat', 'Rocky']
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']

- name: Uninstall Loki deb package
ansible.builtin.apt:
name: "loki"
state: absent
purge: true
when: ansible_os_family == 'Debian'
when: ansible_facts['os_family'] == 'Debian'

- name: Ensure that Loki firewalld rule is not present - tcp port {{ loki_http_listen_port }}
ansible.posix.firewalld: # noqa ignore-errors
Expand Down
2 changes: 1 addition & 1 deletion roles/loki/vars/Debian.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ __loki_arch_map:
armv7l: 'arm'
aarch64: 'arm64'

__loki_arch: "{{ __loki_arch_map[ansible_architecture] | default(ansible_architecture) }}"
__loki_arch: "{{ __loki_arch_map[ansible_facts['architecture']] | default(ansible_facts['architecture']) }}"
2 changes: 1 addition & 1 deletion roles/loki/vars/RedHat.yml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
__loki_arch: "{{ ansible_architecture }}"
__loki_arch: "{{ ansible_facts['architecture'] }}"
2 changes: 1 addition & 1 deletion roles/mimir/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# defaults file for mimir
mimir_version: "latest"
mimir_uninstall: false
__mimir_arch: "{{ arch_mapping[ansible_architecture] | default('amd64') }}"
__mimir_arch: "{{ arch_mapping[ansible_facts['architecture']] | default('amd64') }}"
mimir_download_url_rpm: "https://github.com/grafana/mimir/releases/download/{{ mimir_version }}/{{ mimir_version }}_{{ __mimir_arch }}.rpm"
mimir_download_url_deb: "https://github.com/grafana/mimir/releases/download/{{ mimir_version }}/{{ mimir_version }}_{{ __mimir_arch }}.deb"
mimir_working_path: "/var/lib/mimir"
Expand Down
4 changes: 2 additions & 2 deletions roles/mimir/tasks/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
- name: Include RedHat/Rocky setup
ansible.builtin.include_tasks:
file: setup-Redhat.yml
when: ansible_os_family in ['RedHat', 'Rocky']
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']

- name: Include Debian/Ubuntu setup
ansible.builtin.include_tasks:
file: setup-Debian.yml
when: ansible_os_family == 'Debian'
when: ansible_facts['os_family'] == 'Debian'

- name: Check if Mimir default dir is present
ansible.builtin.stat:
Expand Down
4 changes: 2 additions & 2 deletions roles/mimir/tasks/uninstall.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
name: "mimir"
state: absent
autoremove: true
when: ansible_os_family in ['RedHat', 'Rocky']
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']

- name: Uninstall Mimir deb package
ansible.builtin.apt:
name: "mimir"
state: absent
purge: true
when: ansible_os_family == 'Debian'
when: ansible_facts['os_family'] == 'Debian'

- name: Ensure that Mimir firewalld rule is not present - tcp port {{ mimir_http_listen_port }}
ansible.posix.firewalld: # noqa ignore-errors
Expand Down
4 changes: 2 additions & 2 deletions roles/opentelemetry_collector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Available variables with their default values are listed below (`defaults/main.y
|---------------|-------------|---------------|
| `otel_collector_version` | Version of OpenTelemetry Collector to install. | `"0.90.1"` |
| `otel_collector_binary_url` | URL for downloading the OpenTelemetry Collector binary. This URL is constructed based on the collector version, type, and architecture. | `"https://github.com/open-telemetry/opentelemetry-collector-releases/releases/download/v{{ otel_collector_version }}/{% if otel_collector_type == 'contrib' %}otelcol-contrib_{{ otel_collector_version }}_linux_{{ otel_collector_arch }}{% else %}otelcol_{{ otel_collector_version }}_linux_{{ otel_collector_arch }}{% endif %}.tar.gz"` |
| `arch_mapping` | Mapping of `ansible_architecture` values to OpenTelemetry Collector binary architecture names. | See below\* |
| `otel_collector_arch` | Architecture for the OpenTelemetry Collector binary, determined based on the `ansible_architecture` fact. | `"{{ arch_mapping[ansible_architecture] | default('amd64') }}"` |
| `arch_mapping` | Mapping of `ansible_facts['architecture']` values to OpenTelemetry Collector binary architecture names. | See below\* |
| `otel_collector_arch` | Architecture for the OpenTelemetry Collector binary, determined based on the `ansible_facts['architecture']` fact. | `"{{ arch_mapping[ansible_facts['architecture']] | default('amd64') }}"` |
| `otel_collector_service_name` | The service name for the OpenTelemetry Collector. | `"otel-collector"` |
| `otel_collector_type` | Type of the OpenTelemetry Collector (`contrib` includes additional components). | `contrib` |
| `otel_collector_executable` | The executable name of the OpenTelemetry Collector, changes based on the collector type. | `{% if otel_collector_type == 'contrib' %}otelcol-contrib{% else %}otelcol{% endif %}` |
Expand Down
2 changes: 1 addition & 1 deletion roles/opentelemetry_collector/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ arch_mapping:
i386: i386
ppc64le: ppc64le

otel_collector_arch: "{{ arch_mapping[ansible_architecture] | default('amd64') }}"
otel_collector_arch: "{{ arch_mapping[ansible_facts['architecture']] | default('amd64') }}"
otel_collector_service_name: "otel-collector"
otel_collector_type: contrib
otel_collector_executable: "{% if otel_collector_type == 'contrib' %}otelcol-contrib{% else %}otelcol{% endif %}"
Expand Down
2 changes: 1 addition & 1 deletion roles/opentelemetry_collector/tasks/install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

- name: Determine the architecture for OpenTelemetry Collector binary
set_fact:
otel_collector_arch: "{{ arch_mapping[ansible_architecture] | default('amd64') }}"
otel_collector_arch: "{{ arch_mapping[ansible_facts['architecture']] | default('amd64') }}"
vars:
arch_mapping:
x86_64: amd64
Expand Down
8 changes: 4 additions & 4 deletions roles/promtail/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ promtail_scrape_configs:
- localhost
labels:
job: messages
instance: "{{ ansible_fqdn }}"
instance: "{{ ansible_facts['fqdn'] }}"
__path__: /var/log/messages
- targets:
- localhost
labels:
job: nginx
instance: "{{ ansible_fqdn }}"
instance: "{{ ansible_facts['fqdn'] }}"
__path__: /var/log/nginx/*.log
```
The `scrape_configs` block configures how Promtail can scrape logs from a series of targets using a specified discovery method. [All possible values for `scrape_configs`](https://grafana.com/docs/loki/latest/clients/promtail/configuration/#scrape_configs). ⚠️ This configuration is mandatory. By default, it's empty, and the example above serves as a simple illustration for inspiration.
Expand Down Expand Up @@ -145,13 +145,13 @@ No Dependencies
- localhost
labels:
job: messages
instance: "{{ ansible_fqdn }}"
instance: "{{ ansible_facts['fqdn'] }}"
__path__: /var/log/messages
- targets:
- localhost
labels:
job: nginx
instance: "{{ ansible_fqdn }}"
instance: "{{ ansible_facts['fqdn'] }}"
__path__: /var/log/nginx/*.log
roles:
- role: grafana.grafana.promtail
Expand Down
4 changes: 2 additions & 2 deletions roles/promtail/defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ promtail_scrape_configs: []
# - localhost
# labels:
# job: messages
# instance: "{{ ansible_fqdn }}"
# instance: "{{ ansible_facts['fqdn'] }}"
# __path__: /var/log/messages
# - targets:
# - localhost
# labels:
# job: nginx
# instance: "{{ ansible_fqdn }}"
# instance: "{{ ansible_facts['fqdn'] }}"
# __path__: /var/log/nginx/*.log

# not set by default
Expand Down
2 changes: 1 addition & 1 deletion roles/promtail/molecule/default/converge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- localhost
labels:
job: test
instance: "{{ ansible_fqdn }}"
instance: "{{ ansible_facts['fqdn'] }}"
__path__: /var/log/last*
roles:
- role: grafana.grafana.promtail
4 changes: 2 additions & 2 deletions roles/promtail/tasks/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@
- name: Include RedHat/Rocky setup
ansible.builtin.include_tasks:
file: setup-RedHat.yml
when: ansible_os_family in ['RedHat', 'Rocky']
when: ansible_facts['os_family'] in ['RedHat', 'Rocky']

- name: Include Debian/Ubuntu setup
ansible.builtin.include_tasks:
file: setup-Debian.yml
when: ansible_os_family == 'Debian'
when: ansible_facts['os_family'] == 'Debian'

- name: Ensure that Promtail position path exists
ansible.builtin.file:
Expand Down
2 changes: 1 addition & 1 deletion roles/promtail/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# tasks file for promtail
- name: Include OS specific variables
ansible.builtin.include_vars:
file: "{{ ansible_os_family }}.yml"
file: "{{ ansible_facts['os_family'] }}.yml"

- name: Deploy Promtail service
ansible.builtin.include_tasks:
Expand Down
Loading

0 comments on commit c7e8348

Please sign in to comment.