Adding new environment variables

I’ve added some new environment variables to an existing, deployed project, which I want to serve as defaults for all environments, in group_vars/all/main.yml, since I found in there a structure called wordpress_env_defaults.

I ran vagrant provision to get this deployed to my development box, and the vars appeared in the .env file.

I then ran ansible-playbook server.yml -e env=staging to get this on to the staging server, but the new variables have not found their way into the .env file on that server.

What am I doing wrong?

Nothing :slight_smile: You just need to run a deploy to staging. .env generation is part of the deploy process on remote servers.

I did, and just tried again, to make sure. Those values are not in the .env file.

On staging, the values I’ve added to group_vars/staging/wordpress_sites.yml in the env structure are there, but the ones in group_vars/all/main.yml in wordpress_env_defaults are not.

On development, everything I expect to be present in the .env file is there.

I note that there is another wordpress_env_defaults structure in deploy.yml. Is that a clue or red herring?

No, not a red herring. Thanks for reminding me about this. For remote environments the defaults are in deploy.yml. Unfortunately this is necessary since the variables referenced within them are different on remote/dev environments.

So where should I put vars which I want to appear in local and remote environments? I’d rather not have them in two separate places in the codebase.

Are the values the same for local and remote? I’d probably put them in wordpress_sites I guess. So while at least they are in multiple files, it’s the same (conceptual) place.

Yes, same values for local and remote. The idea was that some environments might override them.

Is there no way to have them in a single file? Can I make a group_vars/all/wordpress_sites.yml and put them here, for example?

Unfortunately not since wordpress_sites is a dictionary. You can only override the entire thing which isn’t useful.

edit: actually, see this too: http://stackoverflow.com/a/25131711

Well the wordpress_env_defaults is having the env dictionaries merged into it at least in some cases.

Would you call this a bug (or a missing feature)? It seems very unintuitive to me that variables set in group_vars/all/main.yml would affect local but not remote domains.

As for the link you gave, that sounds a little dangerous. I don’t think I’ll be going that route.

1 Like

Not sure what it is, but it would be an improvement if it worked as you wanted. Just not sure how it would be fixed :frowning:

You can report it on the repo if you want to.

General comment for Trellis
If it turns out that the group_vars/all defaults actually only apply to dev (I haven’t checked), they could be moved somewhere into group_vars/dev, to avoid the confusion that they don’t apply to remotes.


Global env for @bjn
I haven’t tested, but I’m guessing you could create your custom env as a dictionary in group_vars/all/main.yml:

custom_env:
  env_var_1: value_1
  env_var_2: value_2

Then, in your wordpress_sites for production and staging…

wordpress_sites:
  example.com:
    ...
    env: "{{ custom_env }}"

Ansible combine filter examples
The above should avoid having to override the entire wordpress_sites dictionary. If it doesn’t work, I think you can still use the combine filter to amend portions of the dictionary (example in Trellis, Ansible docs, other reply at SO).

A while back I tried amending wordpress_sites. Here are my notes:

I haven’t digested for whether this is a good idea yet, but the combine filter could reduce redundancy for about half the vars in wordpress_sites (e.g., local_path, repo, branch, repo_subtree_path, multisite, etc.).

Trellis uses with_dict: wordpress_sites in various places, but it could use…

with_dict: wordpress_sites | combine(wordpress_sites_for_group, recursive=True)

…where wordpress_sites is defined in group_vars/all (loaded with lots of values) and wordpress_sites_for_group is defined in group_vars/<environment> (only the values that need to be changed for environment/group).

Demo: Create this as combine.yml and run ansible-playbook combine.yml

- name: Combine filter
  gather_facts: false
  hosts: localhost

  vars:
    wordpress_sites:
      example.com:
        site_hosts:
          - example.com
        env:
          wp_env: production
        bunch_of_global_vars: e.g., from group_vars/all
    wordpress_sites_for_group:
      example.com:
        site_hosts:
          - example.dev
        env:
          wp_env: development
        specific_vars: e.g., from group_vars/development

  tasks:
    - debug:
        msg: "{{ item }}"
      with_dict: wordpress_sites | combine(wordpress_sites_for_group, recursive=True)

Result:

example.com:
  site_hosts:
    - example.dev
  env:
    wp_env: development
  bunch_of_global_vars: e.g., from group_vars/all
  specific_vars: e.g., from group_vars/development

The part to note in the result is that it has both specific_vars and bunch_of_global_vars and the other values were overridden by the dev group values.

1 Like

That looks great to me. But I’m very keen doing absolute minimum tinkering. I’m going to be handing this project off to another developer at some point and so want it to be as close to stock Trellis as I can get it. The closer to your docs my project is, the fewer docs I need to write!

It’d be great if this could be used in future versions (and if you were to add it to Trellis I may backport the changes into my project to make use of it) but for now I will stick to duplicating the config I need in multiple environments.

1 Like