Module Failure but Successful Run - ansible

What are some of the common causes/solutions for an unsuccessful playbook run that uses a custom Ansible module? Even though all of my changes have been made, I am getting "Module Failure" despite using
module.exit_json(changed=True)
Here's the error:
fatal: [localhost -> localhost]: FAILED! => {
"changed": false,
"module_stderr": "",
"module_stdout": "{'id-list': [8], 'item-name': 'abc'}\n\n{\"msg\": \"Successfully ran\", \"invocation\":
{\"module_args\": {\"username\": \"admin-user\", \"ansible_tag_id\":
8, \"ansible_item_id\": 31, \"host\": \"tester\", \"state\":
\"present\", \"password\": \"VALUE_SPECIFIED_IN_NO_LOG_PARAMETER\"}},
\"changed\": true, \"success\": true}\n",
"msg": "MODULE FAILURE",
"rc": 0 }
Here's the main code with some items filtered.
def main():
argument_spec = host_argument_spec()
argument_spec.update(dict(
host=dict(type='str', required=True),
state=dict(type='str', default='present', choices=['present']),
interfaces=dict(type='dict', required=True)
))
module = AnsibleModule(argument_spec)
state = module.params['state']
host = remote_conn(module)
if host is None and state == 'absent':
module.exit_json(msg="Host: %s, State %s" % (host, state), changed=False)
else:
has_changed = create_items_in_host(module, host)
if has_changed:
module.exit_json(msg="Successfully ran", changed=has_changed, success=True)
else:
module.exit_json(changed=has_changed)
Based on the output, I'm convinced that I'm hitting the exit_json with the success message.
Is there something else I have to set in the params of the module to be successful?

Related

Reading Slack Event Data with AWS Lambda and Python

I am currently using AWS Lambda to talk to slack and read in commands. I am at the point where Lambda can respond to commands, but I am still receiving some errors in the log files.
15:47:25
'user': KeyError Traceback (most recent call last): File "/var/task/lambda_function.py", line 36, in lambda_handler slack_userID = slack_event["user"] KeyError: 'user'
'user': KeyError
Traceback (most recent call last):
File "/var/task/lambda_function.py", line 36, in lambda_handler
slack_userID = slack_event["user"]
KeyError: 'user'
The weird one about this error is that I know that particular line is working.
# Grab the Slack channel data.
slack_event = data['event']
slack_userID = slack_event["user"]
slack_text = slack_event["text"]
channel_id = slack_event["channel"]
slack_reply = ""
I have printed out each one of these lines and they return the expected data in slack. Can someone nudge me in the right direction here? Why would user be a key error? When I print out the variable 'slack_event' I get the following:
{'type': 'message', 'user': 'U7D1RQ9MM', 'text': '!addme', 'ts': '1521660489.000390', 'channel': 'G9PLK7B3M', 'event_ts': '1521660489.000390'}
From what I found online, this is a dictionary and I am accessing it correctly. The same expected results are returned when I print out 'slack_userID', 'slack_text', and 'channel_id'. Here is the rest of my code if this helps at all:
################################
# Slack Lambda handler.
################################
import boto3
import logging
import os
import urllib
from boto3.dynamodb.conditions import Key, Attr
# Grab data from the environment.
BOT_TOKEN = os.environ["BOT_TOKEN"]
ASSET_TABLE = os.environ["ASSET_TABLE"]
REGION_NAME = os.getenv('REGION_NAME', 'us-east-2')
dynamo = boto3.resource('dynamodb', region_name=REGION_NAME, endpoint_url="https://dynamodb.us-east-2.amazonaws.com")
# Define the URL of the targeted Slack API resource.
SLACK_URL = "https://slack.com/api/chat.postMessage"
def getAssetExistance(asset):
dynamoTable = dynamo.Table('Assets')
response = dynamoTable.query(KeyConditionExpression=Key('userID').eq(asset))
return bool(response)
def lambda_handler(data, context):
# Slack challenge answer.
if "challenge" in data:
return data["challenge"]
# Grab the Slack channel data.
slack_event = data['event']
slack_userID = slack_event["user"]
slack_text = slack_event["text"]
channel_id = slack_event["channel"]
slack_reply = ""
# Ignore bot messages.
if "bot_id" in slack_event:
slack_reply = ""
else:
# Start data sift.
if slack_text.startswith("!networth"):
slack_reply = "Your networth is: "
elif slack_text.startswith("!price"):
command,asset = text.split()
slack_reply = "The price of a(n) %s is: " % (asset)
elif slack_text.startswith("!addme"):
if getAssetExistance(slack_userID):
slack_reply = "User %s already exists" % (slack_userID)
else:
slack_reply = "Adding user: %s" % (slack_userID)
dynamo.update_item(TableName=ASSET_TABLE,
Key={'userID':{'S':slack_userID}},
AttributeUpdates= {
'resources':{
'Action': 'ADD',
'Value': {'N': '1000'}
}
}
)
# We need to send back three pieces of information:
data = urllib.parse.urlencode(
(
("token", BOT_TOKEN),
("channel", channel_id),
("text", slack_reply)
)
)
data = data.encode("ascii")
# Construct the HTTP request that will be sent to the Slack API.
request = urllib.request.Request(
SLACK_URL,
data=data,
method="POST"
)
# Add a header mentioning that the text is URL-encoded.
request.add_header(
"Content-Type",
"application/x-www-form-urlencoded"
)
# Fire off the request!
urllib.request.urlopen(request).read()
# Everything went fine.
return "200 OK"
I appreciate any help. Thanks. :)

Passing shell= true for a subprocess call

I have a function which is basically an abstraction of the Python subprocess Popen function as follows:
from subprocess import Popen,PIPE, STDOUT
import shlex
def run_process(process):
"""Runs commands in a separate process"""
try:
print "Running command %s" %process
process = process.encode("utf-8")
command = shlex.split(process)
proc = Popen(command, stdout=PIPE, stderr=STDOUT)
cmd_output, cmd_error = proc.communicate()
if proc.returncode != 0:
print "Received a non-zero (%d) return code for command %s" % (proc.returncode, process)
return {"output": cmd_output.strip(), "rc": proc.returncode}
except Exception, err:
print "Error running command %s: %s" %(process, err)
Hence to check the uptime on a system I can do the following :
In [31]: run_process('uptime')
Running command uptime
Out[31]:
{'output': '16:03 up 3 days, 6:42, 6 users, load averages: 1.56 1.87 1.88',
'rc': 0}
Works as expected. However for some commands which involve a |(pipe),I need to set the shell parameter of Popen to True. How can i pass this to the run_command() function so that shell can be set True for such commands ?

Python traceback and attribute errors for AWS and Boto3

Working on getting this script running on Python 3 from earlier version 2 and still getting some traceback and Attribute errors. Below is the error and below that the script in its current state: Special thanks for #Madlania Kalunder for sorting the printing issues. Now I know things are close but need some help.
Traceback (most recent call last):
File "ec2-instances.py", line 97, in <module> sys.exit(main())
File "ec2-instances.py", line 78, in main hosts=(list_instances)(filter)
File "ec2-instances.py", line 18, in list_instances
name = (item for item in i.tags if item ["Key"] == "Name" ).next()
AttributeError: 'generator' object has no attribute 'next'
Below is the code. Sorry for formatting issues here and thanks in advance for the help.
#!/usr/bin/env python
import boto3
import sys
import argparse
import paramiko
def list_instances(Filter):
ec2 = boto3.resource('ec2')
instances = ec2.instances.filter(Filters=Filter)
(columns_format) = ("%-3s %-26s %-16s %-16s %-20s %-12s %-12s %-16s")
print ((columns_format) % ("num", "Name", "Public IP", "Private IP", "ID", "Type", "VPC", "Status"))
num = 1
hosts = []
name = {}
for i in instances:
try:
name = (item for item in i.tags if item ["Key"] == "Name" ).next()
except StopIteration:
name['Value'] = ''
print (columns_format) % (
num,
name['Value'],
i.public_ip_address,
i.private_ip_address,
i.id,
i.instance_type,
i.vpc_id,
i.state['Name']
)
num = num + 1
item={'id': i.id, 'ip': i.public_ip_address, 'hostname': name ['Value'], 'status': i.state['Name'],}
hosts.append(item)
return hosts
def execute_cmd(host,user,cmd):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(host, username=user)
stdin, stdout, stderr = ssh.exec_command(cmd)
stdout=stdout.read()
stderr=stderr.read()
ssh.close()
return stdout,stderr
except paramiko.AuthenticationException as exception:
return "Authentication Error trying to connect into the host %s with the user %s. Plese review your keys" % (host, user), e
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--name',
help="Filter result by name.")
parser.add_argument('-t', '--type',
help="Filer result by type.")
parser.add_argument('-s', '--status',
help="Filter result by status." )
parser.add_argument('-e', '--execute',
help="Execute a command on instances")
parser.add_argument('-u', '--user', default="ubuntu",
help="User to run commands if -e option is used.\
Ubuntu user is used by default")
arg = parser.parse_args()
# Default filter if no options are specified
filter=[]
if arg.name:
filter.append({'Name': 'tag-value', 'Values': ["*" + arg.name + "*"]})
if arg.type:
filter.append({'Name': 'instance-type', 'Values': ["*" + arg.type + "*"]})
if arg.status:
filter.append({'Name': 'instance-state-name', 'Values': ["*" + arg.status + "*"]})
hosts=list_instances(filter)
names = ""
if arg.execute:
for item in hosts:
names = names + " " + item["hostname"] + "(" + item["id"] + ")"
print ("\nCommand to execute: %s") % arg.execute
print ("Executed by: %s") % arg.user
print ("Hosts list: %s\n") % names
for item in hosts:
if item["status"] == 'running':
print ("::: %s (%s)") % (item["hostname"], item["id"])
stdout,stderr = execute_cmd(item["ip"], arg.user, arg.execute)
print (stdout)
print (stderr)
else:
print ("::: %s (%s) is not running (command execution skiped)") % (item["hostname"], item["id"])
if __name__ == '__main__':
sys.exit(main())
Got some help from a colleague and here is the now correct/working version. More print issues needed fixing with () to include the % and removing the specific exception rule. Also corrected the .next to include the generator.
#!/usr/bin/env python
import boto3
import sys
import argparse
import paramiko
def list_instances(Filter):
ec2 = boto3.resource('ec2')
instances = ec2.instances.filter(Filters=Filter)
(columns_format) = ("%-3s %-26s %-16s %-16s %-20s %-12s %-12s %-16s")
print ((columns_format) % ("num", "Name", "Public IP", "Private IP", "ID", "Type", "VPC", "Status"))
num = 1
hosts = []
name = {}
for i in instances:
try:
name = next(item for item in i.tags if item["Key"] == "Name")
except:
name['Value'] = ''
print ((columns_format) % (
num,
name['Value'],
i.public_ip_address,
i.private_ip_address,
i.id,
i.instance_type,
i.vpc_id,
i.state['Name']
))
num = num + 1
item={'id': i.id, 'ip': i.public_ip_address, 'hostname': name ['Value'], 'status': i.state['Name'],}
hosts.append(item)
return hosts
def execute_cmd(host,user,cmd):
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh.connect(host, username=user)
stdin, stdout, stderr = ssh.exec_command(cmd)
stdout=stdout.read()
stderr=stderr.read()
ssh.close()
return stdout,stderr
except paramiko.AuthenticationException as exception:
return "Authentication Error trying to connect into the host %s with the user %s. Plese review your keys" % (host, user), e
def main():
parser = argparse.ArgumentParser()
parser.add_argument('-n', '--name',
help="Filter result by name.")
parser.add_argument('-t', '--type',
help="Filer result by type.")
parser.add_argument('-s', '--status',
help="Filter result by status." )
parser.add_argument('-e', '--execute',
help="Execute a command on instances")
parser.add_argument('-u', '--user', default="ubuntu",
help="User to run commands if -e option is used.\
Ubuntu user is used by default")
arg = parser.parse_args()
# Default filter if no options are specified
filter=[]
if arg.name:
filter.append({'Name': 'tag-value', 'Values': ["*" + arg.name + "*"]})
if arg.type:
filter.append({'Name': 'instance-type', 'Values': ["*" + arg.type + "*"]})
if arg.status:
filter.append({'Name': 'instance-state-name', 'Values': ["*" + arg.status + "*"]})
hosts=list_instances(filter)
names = ""
if arg.execute:
for item in hosts:
names = names + " " + item["hostname"] + "(" + item["id"] + ")"
print (("\nCommand to execute: %s") % arg.execute)
print (("Executed by: %s") % arg.user)
print (("Hosts list: %s\n") % names)
for item in hosts:
if item["status"] == 'running':
print (("::: %s (%s)") % (item["hostname"], item["id"]))
stdout,stderr = execute_cmd(item["ip"], arg.user, arg.execute)
print (stdout)
print (stderr)
else:
print (("::: %s (%s) is not running (command execution skiped)") % (item["hostname"], item["id"]))
if __name__ == '__main__':
sys.exit(main())

Python Connect to device by wifi on Ubuntu

Welcome I have a problem with connecting with device by wifi on Ubuntu 16.04. I have found page where someone explain how to do that :
https://wifi.readthedocs.io/en/latest/wifi_command.html#tutorial
I have gone step by step like author show:
In terminal:
$ pip install wifi
sudo wifi scan
# wifi connect --ad-hoc essid
and after that I wrote password.
But when I have done that I got an error like that :
Traceback (most recent call last):
File "/usr/local/bin/wifi", line 202, in
args.func(args)
File "/usr/local/bin/wifi", line 90, in connect_command
scheme.activate()
File "/home/krzysztof/.local/lib/python2.7/site-packages/wifi/scheme.py", line 172, in activate
subprocess.check_output(['/sbin/ifdown', self.interface], stderr=subprocess.STDOUT)
File "/usr/lib/python2.7/subprocess.py", line 574, in check_output
raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command '['/sbin/ifdown', 'wlan0']'
returned non-zero exit status 1
I am sure that password which I wrote is correct.
I have made it second way by using
$ WIFI_CLI_NAME=cool-wifi pip install wifi
but effect is the same.
I found either example code at Github :
import wifi
def Search():
wifilist = []
cells = wifi.Cell.all('wlan0')
for cell in cells:
wifilist.append(cell)
return wifilist
def FindFromSearchList(ssid):
wifilist = Search()
for cell in wifilist:
if cell.ssid == ssid:
return cell
return False
def FindFromSavedList(ssid):
cell = wifi.Scheme.find('wlan0', ssid)
if cell:
return cell
return False
def Connect(ssid, password):
cell = FindFromSearchList(ssid)
if cell:
savedcell = FindFromSavedList(cell.ssid)
# Already Saved from Setting
if savedcell:
savedcell.activate()
return cell
# First time to conenct
else:
if cell.encrypted:
if password:
scheme = Add(cell, password)
try:
scheme.activate()
# Wrong Password
except wifi.exceptions.ConnectionError:
Delete(ssid)
return False
return cell
else:
return False
else:
scheme = Add(cell)
try:
scheme.activate()
except wifi.exceptions.ConnectionError:
Delete(ssid)
return False
return cell
return False
def Add(cell, password=None):
if not cell:
return False
scheme = wifi.Scheme.for_cell('wlan0', cell.ssid, cell, password)
scheme.save()
return scheme
def Delete(ssid):
if not ssid:
return False
cell = FindFromSavedList(ssid)
if cell:
cell.delete()
return True
return False
if __name__ == '__main__':
# Search WiFi and return WiFi list
print Search()
# Connect WiFi with password & without password
print Connect('OpenWiFi')
print Connect('ClosedWiFi', 'password')
# Delete WiFi from auto connect list
print Delete('DeleteWiFi')
enter code here
But I have got error during compilation :
I have saved this file to polacz.py and after that I made sudo chmod +x polacz.py
and ./polacz.py
./polacz.py: linia 6: syntax error by unexpectable marker ('
./polacz.py: linia 6: `def Search():'

Stop verbose in ansible.playbook.PlayBook

I am using ansible in my CLi. So all error-handling I want to do by myself and I don't want to give extra information that might disoriented an user.
When I tried to run ansible playbook in python code and I've receive verbose msg's:
PLAY [Role] ***************************************************************
GATHERING FACTS ***************************************************************
ok: [127.0.0.1]
TASK: [base-devel-go | Install go lang support] *******************************
ok: [127.0.0.1]
I use ansible-playbook as source for my flow. Now I see a lot of verbose stuff. I want hide it but I couldn't find how to do this?:
playbook = params["playbook"]
inventory = ansible.inventory.Inventory(hosts)
inventory.set_playbook_basedir(os.path.dirname(playbook))
stats = callbacks.AggregateStats()
playbook_cb = callbacks.PlaybookCallbacks(verbose=utils.VERBOSITY)
runner_cb = callbacks.PlaybookRunnerCallbacks(
stats, verbose=utils.VERBOSITY)
params["inventory"] = inventory
params["stats"] = stats
params["callbacks"] = playbook_cb
params["runner_callbacks"] = runner_cb
pb = ansible.playbook.PlayBook(**playbook_params)
pr = pb.run()
I tried to find in callbacks.py but my level of python is less to find answer
It's simplest way to disable output.
I am using ansible in CLi. So when I run it thought python bindings -> there are output. But I found way to disable it:
from ansible import callbacks
# pylint: disable=too-many-arguments
def display(msg, color=None, stderr=False,
screen_only=False, log_only=True, runner=None):
# prevent a very rare case of interlaced multiprocess I/O
callbacks.log_flock(runner)
msg2 = msg
if color:
msg2 = stringc(msg, color)
if not log_only:
if not stderr:
try:
print msg2
except UnicodeEncodeError:
print msg2.encode('utf-8')
else:
try:
print >>sys.stderr, msg2
except UnicodeEncodeError:
print >>sys.stderr, msg2.encode('utf-8')
if callbacks.constants.DEFAULT_LOG_PATH != '':
while msg.startswith("\n"):
msg = msg.replace("\n", "")
if not screen_only:
if color == 'red':
logging.error(msg)
else:
logging.info(msg)
callbacks.log_unflock(runner)
# disable verbose
callbacks.display = display

Resources