Why does creating a droplet via Ansible fail complaining about "dopy" dependency? - ansible

I'm trying to create a droplet on DigitalOcean using Ansible. I have written the following script for that
- name: launch DO droplet
hosts: localhost
gather_facts: False
tasks:
- name: spin up DO droplet
local_action:
module: digital_ocean
state=present
command=droplet
name=test1
api_token=***
ssh_key_ids=DigitalOcean_MAC
size_id=2gb
region_id=ams2
image_id=ubuntu-18-04-x64
wait_timeout=500
register: my_droplet
- name: print info about my_droplet
local_action:
module: debug
msg="ID is {{ my_droplet.droplet.id }} IP is {{ my_droplet.droplet.ip_address }}"
- name: Add new droplet to host group
local_action: add_host hostname={{ my_droplet.droplet.ip_address }} groupname=launched
- name: Wait for SSH to come up
local_action: wait_for host={{ my_droplet.droplet.ip_address }} port=22 delay=60 timeout=320 state=started
I'm executing it via
ansible-playbook create_droplet.yml -c local -i localhosts
But I'm always getting the following error
> PLAY [launch DO droplet]
> ****************************************************************************************************************
>
> TASK [spin up DO droplet]
> *************************************************************************************************************** fatal: [localhost -> localhost]: FAILED! => {"changed": false, "msg":
> "dopy >= 0.3.2 required for this module"} to retry, use: --limit
> #/Users/wim/Dropbox/Programming/Ansible/DigitalOcean/create_droplet.retry
>
> > PLAY RECAP
> > ****************************************************************************************************************************** localhost : ok=0 changed=0 unreachable=0
> > failed=1
I'm installing that dopy thing using:
sudo pip install 'dopy>=0.3.5,<=0.3.5'
But also that does not help.
Any suggestions what's wrong...or is there another way to create a droplet on DigitalOcean.

sudo pip install 'dopy>=0.3.5,<=0.3.5'
Won't help without knowing what ansible_python_interpreter you are using, since -c local requires the local that ansible is using to contain the module, and not whatever random python you ran pip against. I have a strong suspicion ansible will default to /usr/bin/python which might be fine, but I'm guessing in your circumstance it's not otherwise you wouldn't be asking this question.
It is very likely you can achieve success via ansible-playbook -e ansible_python_interpreter=$(which python) ... since the pip from your $PATH is probably the same from the python on your path. You can, of course, be certain via python -c "import dopy" in that same terminal and ensure nothing explodes.

Related

Whats the best way in Ansible to check if a command is available?

I use the following block to detect if homebrew is already installed. In a new version, homebrew it is installed in the /opt/ folder and my “solution” is no longer working. What is a better way to check if a command is available?
- name: Check if homebrew is installed
stat:
path: "/usr/local/bin/brew"
register: "homebrew_check"
Considerations I know which and command -v but assumed there should be something in Ansible itself, am I wrong?
In respect to a
... way to check if a command is available
and which was
installed directly from a binary through a script and does not leave any traces in a package manager
it might also be feasible to check directly the version of it. To do so in example
---
- hosts: test.example.com
become: no
gather_facts: no
tasks:
- name: Gather installed Java version, if there is any
shell:
cmd: java -version 2>&1 | head -1 | cut -d '"' -f 2
register: result
check_mode: false
changed_when: false
failed_when: result.rc != 0 and result.rc != 127
- name: Set default version, if there is no
set_fact:
result:
stdout_lines: "0.0.0_000"
when: "'command not found' in result.stdout"
check_mode: false
- name: Report result
debug:
msg: "{{ result.stdout_lines }}"
check_mode: false
Based on the installed version an installer or updater could be called to install or update to the latest version if necessary.
Also, one could just check if the file exists somewhere via find_module.
Using which or command in a command task would be ok here IMO since homebrew is installed directly from a binary through a script and does not leave any traces in a package manager.
Meanwhile, since ansible has support for Homebrew, we can use the community.general.homebrew module to test if it is available.
Notes:
since I don't have Homebrew I tested my script only in that situation. Meanwhile you should get the expected result testing on a machine where it is available.
this method depends on the configured path to find Homebrew. Here I'm using a local connection to my local machine. When using a remote target, ansible will connect via ssh and use sh by default with a non-login shell (not loading any shell init files like login, .bashrc, ...). If your binary is installed outside the available path for the task, you'll get a false negative response.
Here is the idea, adapt to your needs.
The playbooks:
---
- name: Test homebrew presence
hosts: localhost
gather_facts: false
tasks:
- name: Check if homebrew is available
block:
- name: try using homebrew in check_mode (no changes)
homebrew:
update_homebrew: true
check_mode: true
- name: Homebrew available
debug:
msg: Homebrew is installed
rescue:
- name: No homebrew
debug:
msg: Homebrew is not installed
Gives (without homebrew):
PLAY [Test homebrew presence] ***********************************************
TASK [try using homebrew in check_mode (no changes)] ************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Failed to find required executable \"brew\" in paths: /usr/local/bin:/home/user/.local/bin:/home/user/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"}
TASK [No homebrew] **********************************************************
ok: [localhost] => {
"msg": "Homebrew is not installed"
}
PLAY RECAP ******************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=1 ignored=0

Getting python dependency issue when configuring droplet at boot time in digital ocean

I am using ansible playbook to create droplet in digital ocean and want to configure it at boot time using ansible. Droplet is creating successfully but when i am trying to configure it at boot time its giving python dependency issue. I am aware about it but now i am confused how we can install it during boot time or on the fly? Below is the my ansible playbook:
---
- hosts: localhost
tasks:
- name: Create new DO Droplet
digital_ocean:
state: present
command: droplet
name: ansibletest
api_token: xyz123
size_id: '1gb'
region_id: ams3
image_id: '39739486'
ssh_key_ids: '23625890'
register: my_droplet
- name: print info about my_droplet
local_action:
module: debug
msg= "ID is {{ my_droplet.droplet.id }} IP is {{ my_droplet.droplet.ip_address }}"
- name: Add new droplet to host group
local_action: add_host hostname={{ my_droplet.droplet.ip_address }} groupname=launched
- name: Wait for SSH to come up
local_action: wait_for host={{ my_droplet.droplet.ip_address }} port=22 delay=60 timeout=320 state=started
- hosts: launched
become: true
gather_facts: True
tasks:
- name: installing redis server
apt: name=redis-server state=latest
Below is the error which i got and its related to python dependency on remote client.
fatal: [188.26.76.45]: FAILED! => {"changed": false, "module_stderr": "Shared connection to 188.166.71.116 closed.\r\n", "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n", "msg": "MODULE FAILURE", "rc": 127}
I didn't phase this issue in AWS because EC2 instance have python2.7. Can you please help me to fix this issue so i can configure digital ocean droplet at boot time using ansible. Any guidance will be appreciated.
I have run the playbook using the below command:
ansible-playbook droplet.yml --key-file "/etc/ansible/tek.pem"
Thanks.
You can configure the instance using the raw: module, which requires only ssh access.
You can see an example of that kind of thing in the kubespray bootstrap role, but the tl;dr is:
- hosts: launched
gather_facts: no
become: yes
tasks:
- raw: |
set -e
# but you are responsible for your own idempotent behavior
if [ -x /usr/bin/python ]; then exit 0; fi
export DEBIAN_FRONTEND=noninteractive
apt-get update
apt-get install -y python
# now, in theory, you can resume using ansible modules
# and can do the equivalent of "gather_facts: yes"
- setup:
- # etc etc

Ansible ec2: "boto required for this module"

When I run this simple Ansible playbook:
- name: EC2 Test Example
hosts: localhost
connection: local
gather_facts: False
tasks:
- name: EC2 Instance
ec2:
# Amazon EC2 key pair name
key_name: my-key-pair
# Amazon EC2 Security Group
group: my-security-group
instance_type: t2.micro
# Latest from https://wiki.debian.org/Cloud/AmazonEC2Image/Jessie
image: ami-221ea342
wait: yes
register: ec2
I run with venv/bin/ansible-playbook -i localhost, playbook.yml:
PLAY [EC2 Test Example] ********************************************************
TASK [EC2 Instance] ************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "boto required for this module"}
to retry, use: --limit #/Users/admin/temp/ansec2/playbook.retry
PLAY RECAP *********************************************************************
localhost : ok=0 changed=0 unreachable=0 failed=1
So obviously, I have boto installed in the venv that I'm using as well as my default system Python:
➜ ansec2 venv/bin/pip list
Package Version
--------------- --------
ansible 2.2.1.0
boto 2.45.0
boto3 1.4.4
botocore 1.5.4
...
I've read a few similar posts and I don't see a working solution.
The root cause of your problem is the -i localhost, hack. You don't need to use it anymore in Ansible.
You can just run:
ansible-playbook playbook.yml
And with connection: local in the play Ansible will use the Python executable set by venv.
When you use the -i localhost, hack, Ansible calls its default /usr/bin/python.
In this case you still can add the ansible_python_interpreter parameter to tell Ansible to use this specific environment:
ansible-playbook -i localhost, playbook.yml --extra-vars "ansible_python_interpreter=/Users/admin/temp/ansec2/venv/bin/python"
But I think you should avoid it and use the first method.
In my case the message was because I was missing boto, although I had boto3. So I did pip install boto and that fixed it.
If you already have boto installed for the python interpreter you want to use (as the OP does), then you can tell Ansible to use that python interpreter like so:
ansible-playbook --extra-vars "ansible_python_interpreter=/path/to/desired/python" playbook.yml
If you want to use python3, this can be
ansible-playbook --extra-vars "ansible_python_interpreter=$(command -v python3)" playbook.yml
If instead you do not have boto installed yet, you must install it with pip first before running your playbook. If you want to install boto for your python3 interpreter, you can do so with this command:
python3 -m pip install boto
If you want to install boto for a different python interpreter, use
/path/to/desired/python -m pip install boto

Ansible: Shared connection to xxx closed

Hello guys I make a simple playbook to practice with Ansible but I have a problem when I try to run the playbook (ansible-playbook -i hosts.ini playbook.yml) to configure an instance ec2 the output returns:
> fatal: [XX.XXX.XXX.XXX]: FAILED! => {
> "changed": false,
> "failed": true,
> "invocation": {
> "module_name": "setup"
> },
> "module_stderr": "Shared connection to XXX.XXX.XXX.XXX closed.\r\n",
> "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n",
> "msg": "MODULE FAILURE" } to retry, use: --limit #/home/douglas/Ansible/ansible_praticing/projeto2.retry
>
> PLAY RECAP
> *********************************************************************
> XX.XXX.XXX.XXX : ok=0 changed=0 unreachable=0 failed=1
When I try to connect with the instance via ssh -i ~/.ssh/key.pem ubuntu#public.ip it works well but the provisioning not.
My playbook:
- hosts: projeto
sudo: True
remote_user: ubuntu
vars_files:
- vars.yml
tasks:
- name: "Update"
apt: update_cache=yes
- name: "Install the Ansible"
apt: name=ansible state=latest
- name: "Installt the mysql"
apt:
args:
name: mysql-server
state: latest
- name: "Install the Nginx"
apt:
args:
name: nginx
state: latest
My hosts.ini is also ok (with public ip of aws ec2 instance) and I put the public key (~/.ssh/id_rsa.pem of local machine) in the ~/.ssh/authorized_keys file, inside of the instance.
In the last week (Friday) this playbook was working well.
What am I doing wrong?
Maybe my answer is too late but I faced the same problem today. I have an Ubuntu 16.04 instance running on my EC2. I think, since it has Python 3 (Python 3.5) as its default Python installation. Hence, ansible is not able to find the required Python directory (/usr/bin/python). I got around this issue by changing the ansible Python interpreter to Python 3.
I added ansible_python_interpreter=/usr/bin/python3 to my inventory file and did not have to change the playbook.
Reference - http://docs.ansible.com/ansible/latest/python_3_support.html

Ansible playbook error

I am testing with ansible, what I'm trying to do is install apache2 on another ubuntu server, I already have the group "test" defined with 1 ip. but what happens is that ansible throws me some errors when executing it, I've searched a lot of sites and a lot of people have had this issue, but on different situations and I amd starting to get frustrated with it. Can somebody help me?
Ansible Playbook:
---
- hosts: test
sudo: yes
tasks:
- name: Check if Im sudo
command: echo $USER
- name: install packages
apt: name:apache2 update_cache=yes state=latest
notify: start apache2
handlers:
- name: start apache2
service: name=apache2 state=started
STDOUT
root#ip-172-31-35-33:/etc/ansible/example# ansible-playbook example.yml
PLAY [test] *******************************************************************
GATHERING FACTS ***************************************************************
ok: [172.31.36.176]
TASK: [Check if Im sudo] ******************************************************
changed: [172.31.36.176]
TASK: [install packages] ******************************************************
failed: [172.31.36.176] => {"failed": true}
msg: this module requires key=value arguments (['name:apache2', 'update_cache=yes', 'state=latest'])
FATAL: all hosts have already failed -- aborting
PLAY RECAP ********************************************************************
to retry, use: --limit #/root/example.retry
172.31.36.176 : ok=2 changed=1 unreachable=0 failed=1
BTW, the host is reachable, I can ssh into it, even with ansible, this is the proof
root#ip-172-31-35-33:/etc/ansible/example# ansible -m shell -a "ifconfig | grep 'inet addr'" test
172.31.36.176 | success | rc=0 >>
inet addr:172.31.36.176 Bcast:172.31.47.255 Mask:255.255.240.0
inet addr:127.0.0.1 Mask:255.0.0.0
another thing is that I'm able to install apache2 by hand on the other server, BUT IT IS NOT INSTALLED BECAUSE I WANT TO INSTALL IT USING ANSIBLE
Thanks
Within an individual task, Ansible requires you to make the choice between standard YAML syntax and their own parsed version with equals signs. In this task, you are mixing the two:
- name: install packages
apt: name:apache2 update_cache=yes state=latest
notify: start apache2
This could be either written:
- name: install packages
apt:
name: apache2
update_cache: yes
state: latest
notify: start apache2
Or:
- name: install packages
apt: name=apache2 update_cache=yes state=latest
notify: start apache2
YAML also allows for using bracket and comma syntax to allow you to specify your key-value information on the same line:
- name: install packages
apt: {name: apache2, update_cache: yes, state: latest}
notify: start apache2
Any of these are valid.
You're using a colon where an equal is needed. You need to change the name:apache2 to name=apache2.

Resources