I'm trying to create a formula to manage MySQL accounts on multiple database servers. I'm trying to re-use a macro from a macro.sls
file, and use environment variables to specify connection settings. However, putting environment files in the state files for each database server doesn't work; it only works when I put them in the macro.sls
file. This is not desired since I want to be able to update users on multiple database servers at once. See below:
# Example of "db_user" macro in mysql_user-mgmt/macro.sls
{%- macro db_user(user, password_hash, require_state="None") %}
{{ user }}:
mysql_user.present:
- connection_charset: {{ db_charset }}
- connection_host: {{ db_host }}
- connection_pass: {{ db_pass }}
- connection_port: {{ db_port }}
- connection_user: {{ db_user }}
- host: "%"
- password_hash: "{{ password_hash }}"
{%- if require_state != "None" %}
- require:
- {{ require_state }}
{%- endif %}
{%- endmacro %}
Example db-server1.sls state file using macro
# My mysql_user-mgmt/db-server1.sls file
{%- import "mysql_user-mgmt/macro.sls" as macro -%}
{%- set db_charset = salt['environ.get']('SERVER1_DB_CHAR') -%}
{%- set db_host = salt['environ.get']('SERVER1_DB_HOST') -%}
{%- set db_pass = salt['environ.get']('SERVER1_DB_PASS') -%}
{%- set db_port = salt['environ.get']('SERVER1_DB_PORT') -%}
{%- set db_user = salt['environ.get']('SERVER1_DB_USER') -%}
{{ macro.db_user("someUser", "<MYSQL HASHED PASSWORD>") }}
...and the output then I try to run the salt-call state.sls mysql_user-mgmt.db-server1
command
# Output of running `salt-call state.sls mysql_user-mgmt.db-server1`
local:
- Rendering SLS 'base:mysql_user-mgmt.db-server1' failed: Jinja variable 'db_charset' is undefined
/var/cache/salt/minion/files/base/mysql_user-mgmt/macro.sls(4):
---
{%- macro db_user(user, password_hash, require_state="None") %}
{{ user }}:
mysql_user.present:
- connection_charset: {{ db_charset }} <======================
- connection_host: {{ db_host }}
- connection_pass: {{ db_pass }}
- connection_port: {{ db_port }}
- connection_user: {{ db_user }}
- host: "%"
[...]
---
I believe what you should do is to pass variables as a parameters to the marco like this:
{%- macro db_user(
user,
password_hash,
db_charset,
db_host,
db_pass,
db_port,
db_user,
require_state="None"
) %}
{{ user }}:
mysql_user.present:
- connection_charset: {{ db_charset }}
- connection_host: {{ db_host }}
- connection_pass: {{ db_pass }}
- connection_port: {{ db_port }}
- connection_user: {{ db_user }}
- host: "%"
- password_hash: "{{ password_hash }}"
{%- if require_state != "None" %}
- require:
- {{ require_state }}
{%- endif %}
{%- endmacro %}
and then call a macro like this:
{%- import "mysql_user-mgmt/macro.sls" as macro -%}
{%- set db_charset = salt['environ.get']('SERVER1_DB_CHAR') -%}
{%- set db_host = salt['environ.get']('SERVER1_DB_HOST') -%}
{%- set db_pass = salt['environ.get']('SERVER1_DB_PASS') -%}
{%- set db_port = salt['environ.get']('SERVER1_DB_PORT') -%}
{%- set db_user = salt['environ.get']('SERVER1_DB_USER') -%}
{{ macro.db_user(
"someUser",
"<MYSQL HASHED PASSWORD>",
"db_charset",
"db_host",
"db_pass",
"db_port",
"db_user"
) }}
I'm writing this code from my head - so there might be some errors in syntax, but the logic should be correct.