Skip to content

Commit f77663a

Browse files
authored
feat: Add NGINX Agent config template (#750)
1 parent 536e5d3 commit f77663a

File tree

7 files changed

+297
-26
lines changed

7 files changed

+297
-26
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ BREAKING CHANGES:
1010

1111
FEATURES:
1212

13+
- Add support for templating the entire NGINX Agent configuration file.
1314
- Add support for installing and configuring the NGINX Plus HA keepalived package.
1415
- Add validation tasks to check the Ansible version, the Jinja2 version, whether the required Ansible collections for this role are installed, and whether you are trying to install a valid NGINX module.
1516
- Add support for installing NGINX Open Source on Alpine Linux 3.20.

defaults/main/agent.yml

+100-12
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,107 @@
11
---
2-
# Install NGINX Agent.
2+
# Install the NGINX Agent.
33
# Requires access to either the NGINX stub_status or the NGINX Plus REST API.
44
nginx_agent_enable: false
55

6-
# Specify the NGINX Agent data plane key/token.
7-
# This is required to authenticate the NGINX Agent with the NGINX One SaaS control plane available in F5 Distributed Cloud.
8-
# Default is null.
9-
nginx_agent_data_plane_key: null
106

11-
# Specify the control plane server host and port.
7+
########################################################################################################################
8+
# The following parameters let you configure the static configuration file of NGINX Agent. #
9+
# By default, the config produced is as close a match to the default config provided by NGINX Agent upon installation. #
10+
########################################################################################################################
11+
12+
# Configure the NGINX Agent.
13+
nginx_agent_configure: false
14+
15+
# Specify the NGINX Agent API host and port. Optionally, specify the path to the cert and key.
16+
# Default is not enabled.
17+
# nginx_agent_api:
18+
# host: 127.0.0.1
19+
# port: 8081
20+
# cert: /path/to/cert
21+
# key: /path/to/key
22+
23+
# Specify the control plane server host, port, and data plane key/token.
24+
# The data plane key is required to authenticate NGINX Agent with the NGINX One SaaS control plane available in F5 Distributed Cloud.
1225
# Default is the NGINX One SaaS control plane available in F5 Distributed Cloud.
13-
nginx_agent_server_host: agent.connect.nginx.com
14-
nginx_agent_server_port: 443
26+
# nginx_agent_server:
27+
# host: agent.connect.nginx.com
28+
# port: 443
29+
# data_plane_key: ''
30+
31+
# Enable TLS communication between data plane and control plane.
32+
# Optionally, specify the path to the TLS certificate, key, and CA certificate to enable mTLS.
33+
# nginx_agent_tls:
34+
# enable: true
35+
# skip_verify: false
36+
# cert: /path/to/cert
37+
# key: /path/to/key
38+
# ca: /path/to/ca
39+
40+
# Specify the log level and path.
41+
# Default is info for the log level and /var/log/nginx-agent/ for the log path.
42+
nginx_agent_log:
43+
level: info
44+
path: /var/log/nginx-agent/
45+
46+
# Specify NGINX specific options within NGINX Agent.
47+
# Default is to not exclude any logs, to use the default socket path and to not treat warnings as errors.
48+
nginx_agent_nginx:
49+
exclude_logs: '""'
50+
socket: '"unix:/var/run/nginx-agent/nginx.sock"'
51+
# treat_warnings_as_errors: false
52+
53+
# Specify how often NGINX Agent polls the dataplane.
54+
# Default is 30s for poll interval and 24h for report interval.
55+
nginx_agent_dataplane_status:
56+
poll_interval: 30s
57+
report_interval: 24h
58+
59+
# Specify how often NGINX Agent reports metrics to the control plane.
60+
# Default is 20 for the buffer/bulk size, 1m for report interval, 15s for collection interval and aggregated for mode.
61+
nginx_agent_metrics:
62+
bulk_size: 20
63+
report_interval: 1m
64+
collection_interval: 15s
65+
mode: aggregated
66+
67+
# NGINX Open Source default config paths.
68+
# Default can be seen below.
69+
# nginx_agent_config_dirs: '"/etc/nginx:/usr/local/etc/nginx:/usr/share/nginx/modules"'
70+
71+
# Internal NGINX Agent queue size.
72+
# Default is 100.
73+
# nginx_agent_queue_size: 100
74+
75+
# NGINX Agent features.
76+
# Default is an empty list. See https://docs.nginx.com/nginx-agent/configuration/configuration-overview/ for more details.
77+
# nginx_agent_features: []
78+
79+
# NGINX Agent extensions.
80+
# Default is an empty list. To enable NGINX App Protect reporting within NGINX Agent, use the 'nginx-app-protect' extension as below.
81+
# nginx_agent_extensions: ['nginx-app-protect']
82+
83+
# NGINX Agent NGINX App Protect settings.
84+
# Default is not enabled.
85+
# nginx_agent_app_protect:
86+
# report_interval: 15s
87+
# precompiled_publication: true
88+
89+
90+
#############################################################################################
91+
# The following parameters let you configure the dynamic configuration file of NGINX Agent. #
92+
# By default, nothing is configured. #
93+
#############################################################################################
94+
95+
# Configure the NGINX Agent dynamic configuration file.
96+
# NOTE: This will only run if the NGINX Agent dynamic configuration file has not yet been modified externally.
97+
# If you want to force push a dynamic configuration file, use the 'nginx_agent_configure_dynamic_force' parameter below.
98+
# Default is false.
99+
nginx_agent_configure_dynamic: false
100+
# Force pushing a new dynamic configuration file to NGINX Agent.
101+
# NOTE: This will overwrite any changes made to the dynamic configuration file by a control plane, and might lead to unexpected behavior.
102+
# Default is false.
103+
nginx_agent_configure_dynamic_force: false
15104

16-
# Enable TLS communication between data plane and control plane
17-
# Default is true.
18-
nginx_agent_tls_enable: true
19-
nginx_agent_tls_skip_verify: false
105+
# Specify the NGINX Agent instance group and tags.
106+
# nginx_agent_instance_group: my_instance_group
107+
# nginx_agent_tags: [ansible, dev, qa]

handlers/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
- name: (Handler) Start NGINX Agent
4747
ansible.builtin.service:
4848
name: nginx-agent
49-
state: started
49+
state: restarted
5050
enabled: true
5151

5252
- name: (Handler) Start logrotate

molecule/agent/converge.yml

+21-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,24 @@
77
name: ansible-role-nginx
88
vars:
99
nginx_agent_enable: true
10-
nginx_agent_data_plane_key: "{{ lookup('env', 'AGENT_DATA_PLANE_KEY') }}"
10+
nginx_agent_configure: true
11+
nginx_agent_server:
12+
host: agent.connect.nginx.com
13+
port: 443
14+
data_plane_key: "{{ lookup('env', 'AGENT_DATA_PLANE_KEY') }}"
15+
nginx_agent_tls:
16+
enable: true
17+
skip_verify: false
18+
nginx_agent_nginx:
19+
exclude_logs: '""'
20+
socket: '"unix:/var/run/nginx-agent/nginx.sock"'
21+
treat_warnings_as_errors: false
22+
nginx_agent_config_dirs: '"/etc/nginx:/usr/local/etc/nginx:/usr/share/nginx/modules"'
23+
nginx_agent_queue_size: 100
24+
nginx_agent_extensions: ['metrics']
25+
nginx_agent_api:
26+
host: 127.0.0.1
27+
port: 8081
28+
nginx_agent_configure_dynamic: true
29+
nginx_agent_instance_group: ansible_instance_group
30+
nginx_agent_tags: ['ansible', 'dev']

tasks/agent/install-agent.yml

+40-12
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,16 @@
11
---
2+
- name: (Alpine Linux/Debian/SLES OSs) Install NGINX Agent nstat prerequisite
3+
ansible.builtin.package:
4+
name: iproute2
5+
state: present
6+
when: ansible_facts['os_family'] in ['Alpine', 'Debian', 'Suse']
7+
8+
- name: (Red Hat OSs) Install NGINX Agent nstat prerequisite
9+
ansible.builtin.package:
10+
name: iproute
11+
state: present
12+
when: ansible_facts['os_family'] == "RedHat"
13+
214
- name: Manage NGINX Agent repository
315
ansible.builtin.include_tasks: "{{ role_path }}/tasks/agent/setup-{{ ansible_facts['os_family'] | lower }}.yml"
416
when: ansible_facts['os_family'] in ['Alpine', 'Debian', 'RedHat', 'Suse']
@@ -8,18 +20,34 @@
820
name: nginx-agent
921
state: present
1022

11-
- name: Configure NGINX Agent
12-
ansible.builtin.blockinfile:
13-
backup: true
23+
- name: Dynamically generate NGINX Agent static configuration file
24+
ansible.builtin.template:
25+
src: nginx-agent/nginx-agent.conf.j2
26+
dest: /etc/nginx-agent/nginx-agent.conf
1427
mode: "0644"
15-
path: /etc/nginx-agent/nginx-agent.conf
16-
block: |
17-
server:
18-
{{ ("token: " + nginx_agent_data_plane_key) if nginx_agent_data_plane_key is defined and nginx_agent_data_plane_key | length > 0 }}
19-
host: {{ nginx_agent_server_host }}
20-
grpcPort: {{ nginx_agent_server_port }}
28+
backup: true
29+
when: nginx_agent_configure | bool
30+
notify: (Handler) Start NGINX Agent
31+
32+
- name: Check if the NGINX Agent dynamic configuration file has been modified
33+
ansible.builtin.lineinfile:
34+
path: /var/lib/nginx-agent/agent-dynamic.conf
35+
line: '# agent-dynamic.conf'
36+
state: present
37+
check_mode: true
38+
changed_when: false
39+
when:
40+
- nginx_agent_configure_dynamic | bool
41+
- not nginx_agent_configure_dynamic_force | bool
42+
register: default_conf
2143

22-
tls:
23-
enable: {{ nginx_agent_tls_enable }}
24-
skip_verify: {{ nginx_agent_tls_skip_verify }}
44+
- name: Dynamically generate NGINX Agent dynamic configuration file if it has not been externally modified
45+
ansible.builtin.template:
46+
src: nginx-agent/agent-dynamic.conf.j2
47+
dest: "{{ (ansible_facts['system'] | lower is not search('bsd')) | ternary('/var/lib/nginx-agent/agent-dynamic.conf', '/var/db/nginx-agent/agent-dynamic.conf') }}"
48+
mode: "0644"
49+
backup: true
50+
when:
51+
- nginx_agent_configure_dynamic | bool
52+
- (default_conf['msg'] is defined and default_conf['msg'] != 'line added') or nginx_agent_configure_dynamic_force | bool
2553
notify: (Handler) Start NGINX Agent
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{{ ansible_managed | comment }}
2+
3+
{% if nginx_agent_instance_group is defined %}
4+
instance_group: {{ nginx_agent_instance_group }}
5+
{% endif %}
6+
{% if nginx_agent_tags is defined %}
7+
tags:
8+
{% for tag in nginx_agent_tags %}
9+
- {{ tag }}
10+
{% endfor %}
11+
{% endif %}
+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
{{ ansible_managed | comment }}
2+
3+
{% if nginx_agent_server is defined and nginx_agent_server is mapping %}
4+
server:
5+
{% if nginx_agent_server['data_plane_key'] is defined %}
6+
token: {{ nginx_agent_server['data_plane_key'] }}
7+
{% endif %}
8+
host: {{ nginx_agent_server['host'] }}
9+
grpcPort: {{ nginx_agent_server['port'] }}
10+
{% endif %}
11+
12+
{% if nginx_agent_tls is defined and nginx_agent_tls is mapping %}
13+
tls:
14+
enable: {{ nginx_agent_tls['enable'] | bool }}
15+
skip_verify: {{ nginx_agent_tls['skip_verify'] | bool }}
16+
{% if nginx_agent_tls['cert'] is defined %}
17+
cert: {{ nginx_agent_tls['cert'] }}
18+
{% endif %}
19+
{% if nginx_agent_tls['key'] is defined %}
20+
key: {{ nginx_agent_tls['key'] }}
21+
{% endif %}
22+
{% if nginx_agent_tls['ca'] is defined %}
23+
ca: {{ nginx_agent_tls['ca'] }}
24+
{% endif %}
25+
{% endif %}
26+
27+
{% if nginx_agent_log is defined and nginx_agent_log is mapping %}
28+
log:
29+
{% if nginx_agent_log['level'] is defined %}
30+
level: {{ nginx_agent_log['level'] }}
31+
{% endif %}
32+
{% if nginx_agent_log['path'] is defined %}
33+
path: {{ nginx_agent_log['path'] }}
34+
{% endif %}
35+
{% endif %}
36+
37+
{% if nginx_agent_nginx is defined and nginx_agent_nginx is mapping %}
38+
nginx:
39+
{% if nginx_agent_nginx['exclude_logs'] is defined %}
40+
exclude_logs: {{ nginx_agent_nginx['exclude_logs'] }}
41+
{% endif %}
42+
{% if nginx_agent_nginx['socket'] is defined %}
43+
socket: {{ nginx_agent_nginx['socket'] }}
44+
{% endif %}
45+
{% if nginx_agent_nginx['treat_warnings_as_errors'] is defined and nginx_agent_nginx['treat_warnings_as_errors'] is boolean %}
46+
treat_warnings_as_errors: {{ nginx_agent_nginx['treat_warnings_as_errors'] | ternary('true', 'false') }}
47+
{% endif %}
48+
{% endif %}
49+
50+
{% if nginx_agent_dataplane_status is defined and nginx_agent_dataplane_status is mapping %}
51+
dataplane:
52+
status:
53+
{% if nginx_agent_dataplane_status['poll_interval'] is defined %}
54+
poll_interval: {{ nginx_agent_dataplane_status['poll_interval'] }}
55+
{% endif %}
56+
{% if nginx_agent_dataplane_status['report_interval'] is defined %}
57+
report_interval: {{ nginx_agent_dataplane_status['report_interval'] }}
58+
{% endif %}
59+
{% endif %}
60+
61+
{% if nginx_agent_metrics is defined and nginx_agent_metrics is mapping %}
62+
metrics:
63+
{% if nginx_agent_metrics['bulk_size'] is defined and nginx_agent_metrics['bulk_size'] is number %}
64+
bulk_size: {{ nginx_agent_metrics['bulk_size'] }}
65+
{% endif %}
66+
{% if nginx_agent_metrics['report_interval'] is defined %}
67+
report_interval: {{ nginx_agent_metrics['report_interval'] }}
68+
{% endif %}
69+
{% if nginx_agent_metrics['collection_interval'] is defined %}
70+
collection_interval: {{ nginx_agent_metrics['collection_interval'] }}
71+
{% endif %}
72+
{% if nginx_agent_metrics['mode'] is defined %}
73+
mode: {{ nginx_agent_metrics['mode'] }}
74+
{% endif %}
75+
{% endif %}
76+
77+
{% if nginx_agent_config_dirs is defined %}
78+
config_dirs: {{ nginx_agent_config_dirs }}
79+
{% endif %}
80+
81+
{% if nginx_agent_queue_size is defined and nginx_agent_queue_size is number %}
82+
queue_size: {{ nginx_agent_queue_size }}
83+
{% endif %}
84+
85+
{% if nginx_agent_features is defined and nginx_agent_features is not mapping and nginx_agent_features is not string and nginx_agent_features | length > 0 %}
86+
features:
87+
{% for feature in nginx_agent_features %}
88+
{{ "- " + feature }}
89+
{% endfor %}
90+
{% endif %}
91+
92+
{% if nginx_agent_extensions is defined and nginx_agent_extensions is not mapping and nginx_agent_extensions is not string and nginx_agent_extensions | length > 0 %}
93+
extensions:
94+
{% for extension in nginx_agent_extensions %}
95+
{{ "- " + extension }}
96+
{% endfor %}
97+
{% endif %}
98+
99+
{% if nginx_agent_app_protect is defined and nginx_agent_app_protect is mapping %}
100+
nginx_app_protect:
101+
{% if nginx_agent_app_protect['report_interval'] is defined %}
102+
report_interval: {{ nginx_agent_app_protect['report_interval'] }}
103+
{% endif %}
104+
{% if nginx_agent_app_protect['precompiled_publication'] is defined and nginx_agent_app_protect['precompiled_publication'] is boolean %}
105+
precompiled_publication: {{ nginx_agent_app_protect['precompiled_publication'] | ternary('true', 'false') }}
106+
{% endif %}
107+
{% endif %}
108+
109+
{% if nginx_agent_api is defined and nginx_agent_api is mapping %}
110+
api:
111+
{% if nginx_agent_api['host'] is defined %}
112+
host: {{ nginx_agent_api['host'] }}
113+
{% endif %}
114+
{% if nginx_agent_api['port'] is defined %}
115+
port: {{ nginx_agent_api['port'] }}
116+
{% endif %}
117+
{% if nginx_agent_api['cert'] is defined %}
118+
cert: {{ nginx_agent_api['cert'] }}
119+
{% endif %}
120+
{% if nginx_agent_api['key'] is defined %}
121+
key: {{ nginx_agent_api['key'] }}
122+
{% endif %}
123+
{% endif %}

0 commit comments

Comments
 (0)