I'm in the process of setting up Ansible to take over for a puppet install.
I see puppet manifest that is setting up a ypbind file, and it pushes out a slightly different version of the yp.conf file based on hostname.
So I have the following puppet definitions:
class ypbind {
file {'yp.conf':
ensure => file,
content => template("ypbind/yp.conf.erb"),
owner => 'root',
group => 'root',
mode => '0644',
notify => Service['ypbind'],
path => '/etc/yp.conf',
}
service {'ypbind':
enable => true,
ensure => running,
}
}
Followed by this template (domains and IPs sanitized)
<% case
when #hostname =~/(^[p|d]NY-)/ -%>
#New York Data Center NIS
domain NY1.domain.com IP1
domain NY2.domain.com IP2
domain SF1.domain.com IP3
<%when #hostname =~/(^[p|d]SF-)/ -%>
#San Fran Data Center NIS
domain SF1.domain.com IP1
domain SF2.domain.com IP2
domain NY1.domain.com IP3
<% else -%>
#Default to NY DC
domain NY1.domain.com IP1
domain NY2.domain.com IP2
<% end -%>
My question is how do I replicate this logic using Ansible?
I think I figured out a way to do it with hostname, but I'd have to use multiple files. Is there a way to do the same thing in ansible as this puppet example?
---
- hosts: all
sudo: yes
gather_facts: yes
user: ansible
tasks:
- name: update NY ypbind
template: src=/etc/ansible/files/yp.conf.NY dest=/etc/yp.conf mode=0644 owner=root group=root
notify: restart ypbind
when: ansible_hostname | match('^[p|d]NY-test01')
- name: update SF ypbind
template: src=/etc/ansible/files/yp.conf.SF dest=/etc/yp.conf mode=0644 owner=root group=root
notify: restart ypbind
when: ansible_hostname | match('^[p|d]SF-test01')
handlers:
- name: restart ypbind
- service: name=ypbind state=restarted
I think after research, I'd just use the jinja2 template system, just not sure how quite yet...
For anyone else that might be interested, it turned out to be pretty simple. It was just the following.
ypbind.yaml
---
- hosts: all
sudo: yes
gather_facts: yes
user: ansible
tasks:
- name: update NY ypbind
template: src=/etc/ansible/files/yp.conf.j2 dest=/etc/yp.conf mode=0644 owner=root group=root
notify: restart ypbind
handlers:
- name: restart ypbind
service: name=ypbind state=restarted
yp.conf.j2
{% if ansible_hostname |match ('^[p|d]sf-') %}
domain SF.domain.com server 10.200.0.1
domain SF.domain.com server 10.200.0.2
domain NY.domain.com server 10.201.0.1
{% else %}
domain NY.domain.com server 10.201.0.1
domain NY.domain.com server 10.201.0.2
domain SF.domain.com server 10.200.0.1
{% endif %}
Related
I have a question regarding this syntax in the file haproxy.cfg when setting up a loadbalancer for 2 webservers. I have to distribute the weight (70/20) over 2 webservers over the port 80.
Is this correct?
And do i need to specify the {{ Port }} or not?
Management server -> Loadbalancer -> 2 webservers
Is this port 80 only on the left side, right side or both sides?
(file: roles/loadbalancer/templates/haproxy.cfg)
# main frontend which proxys to the backends
#---------------------------------------------------------------------
frontend main
bind {{ Port }}
acl url_static path_beg -i /static /images /javascript /stylesheets
acl url_static path_end -i .jpg .gif .png .css .js
use_backend static if url_static
default_backend app
#---------------------------------------------------------------------
# static backend for serving up images, stylesheets and such
#---------------------------------------------------------------------
backend static
balance roundrobin
server static 127.0.0.1:4331 check
#---------------------------------------------------------------------
# round robin balancing between the various backends
#---------------------------------------------------------------------
backend app
balance roundrobin
server {{ server1Name }} {{ server1IP }} check weight 70
server {{ server2Name }} {{ server2IP }} check weight 30
# server app3 127.0.0.1:5003 check
# server app4 127.0.0.1:5004 check
(file: roles/loadbalancer/vars/main.yml)
---
# vars file for roles/loadbalancer
Port: "{{ hostvars['node1']['ansible_port'] }}"
server1Name: "{{ hostvars['webnode1']['inventory_hostname'] }}"
server1IP: "{{ hostvars['webnode1']['ansible_host'] }}"
server2Name: "{{ hostvars['webnode2']['inventory_hostname'] }}"
server2IP: "{{ hostvars['webnode2']['ansible_host'] }}"
Yes in the server line have the port be there after the ip.
server {{ server1Name }} {{ server1IP }}:{{server1port}} check weight 70
You can find here the full documentation of the server keyword
Hello community i am running the below ansible playbook through azure cli.
Also i get similar results from an Ubuntu 18.04.4 LTS.
Also i have raised a github issue: https://github.com/Azure/Ansible/issues/21
What i mean using Azure CLI?
Go to Azure:
-> Create a new Cloud Shell
-> Ansible is already installed
-> create a new yml file. Copy the below script.
-> Run the below playbook. With this command ansible-playbook nameofyourfile.yml
-> The below script fails
- hosts: localhost
connection: local
vars:
resource_group: ansibleResourceGroupName
webapp_name: ansibleWebAppName
plan_name: ansibleWebPlanName
location: westeurope
server_name: AnisbleDemoSqlServer
database_name: AnsibleDemoSqlDatabase
tasks:
- name: Create a resource group
azure_rm_resourcegroup:
name: "{{ resource_group }}"
location: "{{ location }}"
- name: Create App Service on Linux with dotnetcore
azure_rm_webapp:
resource_group: "{{ resource_group }}"
name: "{{ webapp_name }}"
plan:
resource_group: "{{ resource_group }}"
name: "{{ plan_name }}"
is_linux: true
sku: S1
number_of_workers: 1
frameworks:
- name: "dotnetcore"
version: "3.1"
- name: Create (or update) SQL Server
azure_rm_sqlserver:
resource_group: "{{ resource_group }}"
name: "{{ server_name }}"
location: "{{ location }}"
admin_username: panoskarajohn
admin_password: Testpasswordxyz12!
- name: Create (or update) SQL Database
azure_rm_sqldatabase:
resource_group: "{{ resource_group }}"
server_name: "{{ server_name }}"
name: "{{ database_name }}"
location: "{{ location }}"
- name: Create (or update) Firewall Rule
azure_rm_sqlfirewallrule:
resource_group: "{{ resource_group }}"
server_name: "{{ server_name }}"
name: firewallruleAllowAll
start_ip_address: 0.0.0.0.
end_ip_address: 255.255.255.255
My sqlserver is created.
But the firewall rule fails, with an unauthorised error.
At the end i have provided the errors
Also when i try to do it manually to add a firewall rule through the azure portal.
Everything is deactivated. Also the add client ip seems to be inactive.
Also even with the choices i am allowed to change, the save button is unresponsive.
The whole firewalls page seems unresponsive.
See image for more info.
When i create through the azure portal a new sql server, everything seems to operate.
Any help is appreciated.
Error i get:
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Error creating the Firewall Rule instance: 400 Client Error: Bad Request for url: -> Some url.
When i click on the url i get this json -> {"error":{"code":"AuthenticationFailed","message":"Authentication failed. The 'Authorization' header is missing."}}
Ansible Version for my Ubuntu Machine
ansible 2.9.6
config file = None
configured module search path = [u'/home/pkaragiannis/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python2.7/dist-packages/ansible
executable location = /usr/local/bin/ansible
python version = 2.7.17 (default, Nov 7 2019, 10:07:09) [GCC 7.4.0]
Ansible Output from Ubuntu VM
PLAY [localhost] ***************************************************************************************
TASK [Gathering Facts] *********************************************************************************
ok: [localhost]
TASK [Create a resource group] *************************************************************************
changed: [localhost]
TASK [Create App Service on Linux with dotnetcore] *****************************************************
changed: [localhost]
TASK [Create (or update) SQL Server] *******************************************************************
[WARNING]: Azure API profile latest does not define an entry for SqlManagementClient
changed: [localhost]
TASK [Create (or update) SQL Database] *****************************************************************
changed: [localhost]
TASK [Create (or update) Firewall Rule] ****************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Error creating the Firewall Rule instance: 400 Client Error: Bad Request for url: https://management.azure.com/subscriptions/******-*****-*******/resourceGroups/ansibleResourceGroupName/providers/Microsoft.Sql/servers/AnisbleDemoSqlServer/firewallRules/firewallruleAllowAll?api-version=2014-04-01"}
PLAY RECAP *********************************************************************************************
localhost : ok=5 changed=4 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
When you want to create the SQL server and the firewall rules for it, I see you use the service principal to authenticate. So first of all, the service principal should have the Contributor role of the subscription or the resource group that you would use.
Log in with the service principal, and then the Azure CLI command to create the SQL server and the firewall rules:
az sql server create -l westus -g mygroup -n myserver -u myadminuser -p myadminpassword
az sql server firewall-rule create -g mygroup -s myserver -n myrule --start-ip-address 1.2.3.4 --end-ip-address 5.6.7.8
With the Ansible, it should also work and I did not see any problems in the code. Just set the credentials for it with the service principal correctly.
Update:
Here is the screenshot of the ansible:
Update-1:
Here is the YAML file of above screenshot:
- hosts: localhost
connection: local
tasks:
- name: Create (or update) SQL Server
azure_rm_sqlserver:
resource_group: mygroup
name: mysqlname
location: eastus
admin_username: username
admin_password: password
- name: Create (or update) Firewall Rule
azure_rm_sqlfirewallrule:
resource_group: mygroup
server_name: mysqlname
name: FirewallRule1
start_ip_address: 10.0.17.62
end_ip_address: 10.0.17.62
I would like to monitor multiple logs on the universal forwarder. How can i do this? Also when I set forward-server am running out in error. with Enable boot-start somehow i have to accept license manually to finish up the installation. Any suggestions, please?
- name: connect forward server to Splunk server
command: "{{ splunkbin }} add forward-server {{ item }} -auth {{ splunkcreds }}"
with_items: "{{ splunkserver }}"
when: splunkserver is defined
notify: restart_splunk
- name: Enable Boot Start
command: "{{ splunkbin }} enable boot-start"
- name: add temporary monitor to create directory
command: "{{ splunkbin }} add monitor /etc/hosts -auth {{ splunkcreds }}"
notify: restart_splunk
Use the following to accept the license without prompting
- name: Enable Boot Start
command: "{{ splunkbin }} enable boot-start --accept-license"
I'm new in ansible, I'm setting up my new instance in digitalocean for configuring new user. Basically, I have the playbook for setting up it and everythings okay when I run the playbook but when I tried to check if my password is working it didn't work.
I did the
sudo apt-get update
to if the password is working. It didn't.
---
- name: Configure Server
hosts: sample_server
gather_facts: no
remote_user: root
vars:
username: sample_user
password: sample_password
tasks:
- name: Update apt cache
apt: update_cache=yes
- name: Safe aptitude upgrade
apt: upgrade=safe
async: 600
poll: 5
- name: Add my user
user:
name: "{{ username }}"
password: "{{ password }}"
update_password: always
shell: /bin/bash
groups: sudo
append: yes
generate_ssh_key: yes
ssh_key_bits: 2048
state: present
- name: Add my workstation user's public key to the new user
authorized_key:
user: "{{ username }}"
key: "{{ lookup('file', 'certificates/id_rsa.pub') }}"
state: present
- name: Change SSH port
lineinfile:
dest: /etc/ssh/sshd_config
regexp: "^Port"
line: "Port 30000"
state: present
# notify:
# - Restart SSH
- name: Remove root SSH access
lineinfile:
dest: /etc/ssh/sshd_config
regexp: "^PermitRootLogin"
line: "PermitRootLogin no"
state: present
# notify:
# - Restart SSH
- name: Remove password SSH access
lineinfile:
dest: /etc/ssh/sshd_config
regexp: "^PasswordAuthentication"
line: "PasswordAuthentication no"
state: present
# notify:
# - Restart SSH
- name: Reboot the server
service: name=ssh state=restarted
handlers:
- name: Restart SSH
service: name=ssh state=restarted
Any idea for this. Thanks
Ansible user module takes passwords as crypted values and jinja2 filters have the capability to handle the generation of encrypted passwords. You can modify your user creation task like this:
password: "{{ password | password_hash('sha512') }}"
Hope that will help you
I want to provision Windows host that is in subnet accessible only with Linux jump host.
Windows machine uses winrm connection method.
Linux jump server is available via SSH.
I have no problem accessing windows host if available directly with:
ansible_connection: winrm
If I try to delegate the task to the Linux jump server (that has direct access to Windows) by:
- name: Ping windows
hosts: windows_machines
tasks:
- name: ping
win_ping:
delegate_to: "{{ item }}"
with_items: "{{ groups['jump_servers'][0] }}"
it tries to connect to establish WINRM connection to the jump host. Not exactly what I had in mind.
Note that for windows_machines group I have group_vars defined:
ansible_port: 5986
ansible_connection: winrm
ansible_winrm_server_cert_validation: ignore
How should I provision Windows hosts via a bastion host?
My priority was to have all the configuration in one place and not distribute part of Ansible to the bastion/jump host. I went for establishing ssh tunnel for the 5986 port.
Here is the complete task:
- name: Tunneled configuration of Windows host in a subnet
hosts: windows
connection: local #This is the trick to connect to localhost not actual host
gather_facts: no
tasks:
- name: First setup a tunnel
local_action: command ssh -Nf -4 -o ControlPersist=1m -o ControlMaster=auto -o ControlPath="~/.ssh/mux2win-%r#%h:%p" -o StrictHostKeyChecking=no -o PasswordAuthentication=no -o UserKnownHostsFile="/dev/null" -i {{ hostvars[item].ansible_ssh_private_key_file }} {{ hostvars[item].ansible_ssh_user }}#{{ hostvars[item].ansible_host }} -L {{ ansible_port }}:{{ actual_host }}:{{ ansible_port }}
with_items:
- "{{ groups['jump_servers'][0] }}" #I know my topology so I know which host to use
- name: (optional) Second ensure it is up
local_action: command ssh -O check -S "~/.ssh/mux2win-%r#%h:%p" {{ hostvars[item].ansible_ssh_user }}#{{ hostvars[item].ansible_host }}
with_items:
- "{{ groups['jump_servers'][0] }}"
# ------- actual windows tasks (from ansible examples) ------------
- name: Ping
connection: local
win_ping:
- name: test raw module- run ipconfig
raw: ipconfig
register: ipconfig
- debug: var=ipconfig
- name: Test stat module- test stat module on file
win_stat: path="C:/Windows/win.ini"
register: stat_file
- debug: var=stat_file
- name: Check stat_file result
assert:
that:
- "stat_file.stat.exists"
- "not stat_file.stat.isdir"
- "stat_file.stat.size > 0"
- "stat_file.stat.md5"
# ------- end of actual windows tasks ------------
- name: Stop the tunnel. It would stop anyway after 1m.
local_action: command ssh -O stop -S "~/.ssh/mux2win-%r#%h:%p" {{ hostvars[item].ansible_ssh_user }}#{{ hostvars[item].ansible_host }}
with_items:
- "{{ groups['jump_servers'][0] }}"
For this to work I had to modify slightly the inventory file:
[windows]
windows1 ansible_host=127.0.0.1 ansible_ssh_user=Administrator actual_host=192.168.0.2 (...)
Ansible can connect by accessing 5986 port on local host, so ansible_host has to be set to 127.0.0.1 and to have the information on the actual ip of the Windows machine a custom variable actual_host is set.
That's not what the delegate_to option on a task does.
Instead, delegate_to will make sure that the task only runs against a specific node rather than the group that is listed in the role/playbook.
So for example you may have a role that sets up MySQL on a cluster of boxes that are defined generically but then want to do specific configuration/tasks on the master alone, leaving the master to then replicate these out to the slaves.
You can do SSH proxying where you forward SSH connections through a bastion/jump host but that obviously needs your connection to be SSH throughout which doesn't help you.
The only thing I can think of to help you here would be to use Ansible directly from the bastion/jump host possibly triggered by Ansible (or anything else really) from your machine outside of the protected zone.