How to specify an environment (dev,stage, prod) within playbook so win_lineinfile can insert applicable variable

Due to a lot of complexities we currently clone our prod systems into a dev and test environment (each environment is completely isolated). I’ve got Ansible running currently in the dev environment where I’ve built a bunch of plays.

We’re about to deploy the changes made in the dev environment to the test environment - will need to build a new Ansible box - this will have access to the same source control for where the current plays are stored for the dev environment.

The hostnames and IP’s are identical in dev/test and prod (for this project).

In one of the playbooks I need to use the win_lineinfile module to insert/replace a line of code in a web.config file - the code that needs to be inserted I want based upon an environment variable (dev, test or prod) so this play can be used in dev/stage and prod. Each environment would need a different section of code in the web.config file.

E.G dev = devintegration.server.example

test = testintegration.server.example

I’m not too sure on how to go about this…

I’m currently running the plays manually - but my next step is to then build projects and run them via AWX.

Not sure how others do it, but I have vars files called e.g. project_dev.yaml, project_prod.yaml. I load these where needed via include_vars, specifying the file as e.g. “project_{{ env }}.yaml”

Then I specify the environment on the command line using -e, e.g. “-e env=prod”

This has the added advantage of preventing the playbook from running at all if I forget the env variable or if I provide one that doesn’t having a matching vars file.

Plus you can (if you want to) refer to the “env” variable in conditions.

Regards, K.

Thanks for your response Karl - that sounds like a clever way of doing it that I’ll also try.

Do you also use AWX or Tower? If so - can this environment also be specified when running a play via AWX/Tower?

Sorry, can’t speak about AWX or Tower, I don’t know anything about them.

In an automated scenario, you could also generate Ansible code and execute the generated playbooks.

Regards, K.

We use a similar setup (in our case the variable is called ‘domain’) with Tower. You can easily specify additional variables with each template you want to run.
In our case, as we have a number of systems that require logins - we use custom credentials, which can supply any variables.

kind regards
Pshem

I use group_vars for this.

in each environment I have a different inventory and in the inventory, all my groups of hosts are added as child groups of a group which contains group variables for this environment.

Here’s a simplified example.

$ cat dev.inventory
`

dev inventory

[appservers]
host3
host4

[dbservers]
host5
host6

[webservers]
host1
host2

add host groups to environment-specific group for dev

[dev_group:children]
appservers
dbservers
webservers

end of dev inventory

`

$ cat test.inventory
`

test inventory

[appservers]
host3
host4

[dbservers]
host5
host6

[webservers]
host1
host2

add host groups to environment-specific group for test environment

[test_group:children]
appservers
dbservers
webservers

end of test inventory

`

$ cat group_vars/dev_group/settings
`

And how do you “pick a different inventory”? with -i on the command line?

Regards, K.

Sometimes, but like OP I have a different ansible machine in each environment so you can set ANSIBLE_INVENTORY=inventory in user profile too.

Thanks for your response Pshem - might have more questions after I get some projects configured…

Thanks Jon - that sounds like another good way of doing it. Could you also combine this into a similar method as mentioned by Karl where an environment must be specified otherwise the plays won’t run?

Thinking about this some more - my only concern is a few tasks in the plays depending on the environment - so both methods mentioned above will work fine… I could just have a condition specified in the play for specific tasks.

Is this what you’d normally do?

As an example - in the DEV environment I need to delete a DFS target and re-create it with a different target path - I only want this to be actioned for DEV.

Regardless of whether you do it with groups or or not, you can always define a variable in one environment and not in another and use a “when… is defined” condition or similar to decide whether to do something. If you need more granularity, give the variable different values and test the actual value in your when condition.

For something that could be destructive in a production environment, I suggest you try to find a method that will stop your playbook running at all if you forget something, or make sure your default is the non-destructive path. That’s why I like my env variable, because the playbook can’t run if I forget it altogether. Of course, it still doesn’t help me if I accidentally type “prod” instead of “dev”! I get around that by not running my playbooks directly. Instead I use a script that double checks me if I say “prod”. It’s saved me more than once :slight_smile:

Regards, K.

I do like the safe guard of specifying the environment when running the play - pretty new to Ansible so mistakes could easily happen.

Do you include the vars file within the playbook sub-directory or within a global inventory sub-directory? E.G inventory → vars → all -->> project_dev.yaml

I have my environment vars file in the playbook directory for the project, but Ansible is very flexible. I’m not sure how you would do it with groups.

There’s an argument for NOT putting it anywhere that Ansible can find automatically; that way you force it to be specified explicitly.

Regards, K.

I’ve added a few variables into the dev.yml file - this is being called via include_vars.

I have a few lines of powershell I want to run via win_shell… can I user the variable within dev.yml in the win_shell command?

E.G (within dev.yml)

source_repo = \server1\repo$

within win_shell module… get-childitem -path " {{ source_repo ))" …blah blah

So far I’m getting an error about “source repo” being an undefined variable.

OK i just noticed something obvious below - source_repo should just reference a server, need an addtional variable for the path on the server.

I still need to know whether it’s possible to use variables within a playbook and reference them in a powershell command via win_shell.

Sorry - I’m mistaken. My original code is fine referencing the UNC path of remote server.