New to Ansible I'm experimenting with setting up a website under IIS.
I can create and configure an application pool, but I'm struggling with the website. The basic site works, HTTPS/SSL is still troublesome, but I read there are some bugs in the win_iis_website/win_iis_webbinding scripts that are being worked on. The part I'm stuck with are IIS' features per site.
In IIS (in the GUI) there are sub-features that can be configured for a site:
I was unable to find how to configure these using Ansible (more specifically Ansible's win_iis_website module).
I'm looking to configure ASP, Handler mappings, URL rewrites and Default documents.
Is there any way to do so?
My current yml for creating the site looks like this:
- name: create new website {{ websitename}}
win_iis_website:
name: "{{ websitename}}"
state: started
port: 443
ip: *
ssl: true
hostname: "{{ websitename }}"
application_pool: "{{ websitename }}"
physical_path: c:\inetpub\wwwroot\{{ websitename }}
parameters: logfile.directory:c:\inetpub\logs\
register: website
I am currently making Playbooks for IIS and indeed to perform the configuration there is no particular module that allows you to modify the functions of the sections, I looked in some places and the information was very scarce, there are modules for applicationPool, but for this you have to use win_shell as follows
- name: Name of playbook
win_shell: |
<PowerShell command>
You can base on the CIS BENCHMARK guide of IIS.
Check the win_feature module:
- name: Install IIS Web-Server with sub features and management tools
win_feature:
name: Web-Server
state: present
restart: True
include_sub_features: True
include_management_tools: True
if you want to do in a more controlled manner, check the installed features with the command:
Get-WindowsFeature
And add like:
- name: Install IIS
win_feature:
name: "Web-Filtering,Web-Dir-Browsing,Web-Default-Doc"
state: present
restart: no
include_sub_features: no
include_management_tools: yes
Related
lets say I have a playbook:
---
- name
host: testserver
become_method = sudo
become_user = root
tasks:
- name: copystuff
module: copy
do stuff
- name: copy stuff
delegate_to: localhost
module: copy
do stuff
I have same user with the same password on both localhost and the testserver. But on testserver, I have to use sudo to beocme a root but on localhost I have to use dzdo to become a root.
So I was wondering if there is a way for me use either one, if one method does not work?
Yes, that's what hostvars are designed to do: declare vars per host.
You can do that in your inventory file, as shown in the fine manual, if you have an inventory file (or in most dynamic inventory sources). Or, if you are running with a more ad-hoc inventory list (such as -i machine1,localhost,machine99) then you can use a conditional set_fact: to declare that hostvar after ansible has started running:
- set_fact:
ansible_become_method: dzdo
when: inventory_hostname == "localhost"
so long as you do that before using a task that has become: yes on it
The pre_tasks: keyword may interest you, too
I wanted to deploy multiple VMS from my ansible-playbook, so I used split function and I am getting the error of dict does not have user_inout error. Please have a look at my code.
Code:
- name: os system
pause:
prompt: |
Which os do you want to use?
1- Windows Server
2- CentOS_7
3- CentOs_8
4- Ubuntu
5- Others
register: os_system
- set_fact:
o_name: "{{ os_system.user_input.split(',') }}"
- name: Domain Decision
pause:
prompt: Do you want your PC in Domain
register: decision
when: 'item|string == "1"'
with_items:
- "{{ o_name }}"
- set_fact:
dec: "{{ decision.user_input.split(',') }}"
Now my real issue, if the user chooses option 1,2 then it will be split by set_fact for os_system and according to that input it will decide for the domain decision my main issue is that while the task is at set_fact for the decision, it will give me the error like this:
Error:
fatal: [x.x.x.x]: FAILED! => {
"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'user_input'\n\nThe error appears to be in '/home/x.x.x.x/sites/playbook.yml': line 82, column 6, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - set_fact:\n ^ here\n"
}
IF I remove the loop from task domain decision, then set_fact works very perfectly.
When you want to collect user input, it can be in two ways:
Interactive (prompted), using vars_prompt.
Through variables (non-prompted). For example, you could have users create a file with variables and load with vars_file.
I would prefer the second approach if possible.
However, to get user input interactively through prompts:
- hosts: my_hosts
vars_prompt:
- name: os_system
prompt: |
Which os do you want to use?
1- Windows Server
2- CentOS_7
3- CentOs_8
4- Ubuntu
5- Others
private: no
tasks:
- set_fact:
o_name: "{{ os_system.split(',') }}"
You should note that by splitting the input of 1,2 - you will not get OS name. You will again have to set a fact based on the number (1 = Windows Server). IMHO this is unnecessary complication.
A much better option would be to have users create a variables file like below:
my_vars.yml:
os_choices:
- { name: Windows Server, domain: yes }
- { name: CentOS_7, domain: no }
And load it in play using:
- hosts: my_hosts
vars_file:
- my_vars.yml
I have a project that is built with an azure pipeline, the artifacts are sent to both the File Share and Azure DevOps. A self hosted agent is currently used for the pipeline that builds my project. Now I want to deploy my artifacts on a physical computer in the network of my company. Artifacts are installation files that support "silent installation mode", so I can install everything by executing corresponding files with PowerShell.
My question is: What should I do to achieve my goal? I considered that I would simply create a release pipeline (I use Microsoft's classic UI editor for pipelines) and add the necessary tasks. In the end everything will look something like this:
Copy artifacts from the computer on which the product was built (A)
to the computer on which the product is to be installed (B).
Perform the installation of services that are required for the main
application.
Perform the installation from the main application. Is this the
right course of action or should I choose something else?
One more question. It is not entirely clear to me how I should divide the deployment stages, because: Step 1 is still done by the agent on the computer A. Steps 2 and 3 should already do another agent. Hence, an agent must be also present on the computer B (in total I need two agents, one for the build pipeline on the computer A and one on the target computer B). Is that correct?
Deploy artifacts to physical machine with Azure Pipelines
I think you are very close to the answer, but I am not sure whether the advice I provided is the best, because it is more a matter of taste, you can check my suggestions below.
We could achieve this by one agent on the computer A:
Use the Remote Copy task to copy the artifact to the computer B by the agent on the computer A.
Use the Powershell execute install files with command line arguments on remote computer the agent on the computer A.
In this case, we do not need to create a new agent on the computer B, and also no need to divide the deployment stages.
We have a web application that has a similar requirement, we need to include location specific files when we deploy our application to that location.
I'm not sure this is the best route, but we incorporated using Ansible in our deployment pipeline. Our Ansible playbook utilizes the hosts file which contains variables for the location and the jar version to be deployed.
Again, our situation is different, but the same should work.
For instance, you may be able to something like this...
Your Ansible inventory (hosts) file may look like this
[servers]
xxx.xxx.xxx.xxx
[all:vars]
app_name=mfgweb
env=qa
app_version=2020.03.4
*** If your artifact is a jar file
jar_group=com.somegroup
jar_name=some_jar <-- note: no extentsion
jar_version=2019.11.3
Your playbook may look something like this
---
- hosts: localhost
connection: local
tasks:
- name: Find old working directories
find:
paths: /tmp
patterns: 'ansible.*'
file_type: directory
age: 2d
register: tmp_dirs
- name: Cleanup old working directories
file:
path: "{{ item }}"
state: absent
loop: "{{ tmp_dirs.files | map(attribute='path') | list }}"
- name: Create working directory
tempfile:
state: directory
suffix: work
register: workdir
- name: Download artifact
maven_artifact:
group_id: "{{ jar_group }}"
artifact_id: "{{ jar_name }}"
version: "{{ jar_version }}"
repository_url: "{{ artifacts_url }}"
username: "{{ artifacts_user }}"
password: "{{ artifacts_password }}"
verify_checksum: never
dest: "{{ workdir.path }}/{{ app_name }}/"
This is just a sample, but you would be able to install required software in you playbook using yum and/or pip.
I have instance for beta sites and one for production. I set up CodeDeploy tool to deploy changes via Bitbucket UI to the server.
I know that there is an option to create additional deployment groups and set different instances for particular group. But my appspec.yml file stores destinations to beta site only destination: /var/www/html/beta-site.site.com.
Is there a best practice to set directories for specific group/instance?
I found a solution for this issue. I created folders with aliases on prod and beta servers and updated appspec.yml paths accordingly:
On production server:
/var/www/html-aliases/site -> /var/www/html/site.com
On beta server:
/var/www/html-aliases/site -> /var/www/html/beta.site.com
So my appspec.yml configs looks like this now:
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html-aliases/site
permissions:
- object: /var/www/html-aliases/site
pattern: "**"
owner: username
group: www
mode: 444
type:
- file
- object: /var/www/html-aliases/site
pattern: "**"
owner: username
group: www
mode: 555
type:
- directory
We are trying to create and install packages on Azure using Ansible. We are able to create the instance using Ansible Azure module but we are stuck at installing the packages once the VM is created because we don't know what the IP address of the newly created VM is.
We want to complete this in single run. Is this possible?
I've not used the Azure module so could be wrong but you should be able to use register to store some data about the instances you've just created.
You can then pass this data into a dynamically defined host group in a task by iterating through the output of the first task by using the add_host module.
So your playbook may look something like:
- hosts: local
connection: local
tasks:
- name : Create Windows instance
azure :
name: "ben-Winows-23"
hostname: "win123"
os_type: windows
enable_winrm: yes
subscription_id: "{{ azure_sub_id }}"
management_cert_path: "{{ azure_cert_path }}"
role_size: Small
image: 'bd507d3a70934695bc2128e3e5a255ba__RightImage-Windows-2012-x64-v13.5'
location: 'East Asia'
password: "xxx"
storage_account: benooytes
user: admin
wait: yes
virtual_network_name: "{{ vnet_name }}"
register : azure
- name : Debug Azure output
debug :
var : azure
### Assumes that the output from the previous task has an instances key which in turn has a public_ip key. This may need updating to give the proper path to a resolvable hostname or connectable IP. Use the output of the debug task to help with this. ###
- name : Add new instance to host group
add_host :
hostname : {{ item.public_ip }}
groupname : launched
with_items : azure.instances
### Only target newly launched instances from previous play ###
- hosts: launched
tasks:
- name : Start foo service and make it auto start
win_service :
name : foo
start_mode : auto
state : started
- name : Do some thing else
...