Copying snapshot of extras modules

This commit is contained in:
James Cammarata
2014-09-26 01:01:01 +00:00
committed by Matt Clay
parent 8afa090417
commit d4b117843a
100 changed files with 25242 additions and 0 deletions

View File

@@ -0,0 +1,143 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
---
module: campfire
version_added: "1.2"
short_description: Send a message to Campfire
description:
- Send a message to Campfire.
- Messages with newlines will result in a "Paste" message being sent.
version_added: "1.2"
options:
subscription:
description:
- The subscription name to use.
required: true
token:
description:
- API token.
required: true
room:
description:
- Room number to which the message should be sent.
required: true
msg:
description:
- The message body.
required: true
notify:
description:
- Send a notification sound before the message.
required: false
choices: ["56k", "bell", "bezos", "bueller", "clowntown",
"cottoneyejoe", "crickets", "dadgummit", "dangerzone",
"danielsan", "deeper", "drama", "greatjob", "greyjoy",
"guarantee", "heygirl", "horn", "horror",
"inconceivable", "live", "loggins", "makeitso", "noooo",
"nyan", "ohmy", "ohyeah", "pushit", "rimshot",
"rollout", "rumble", "sax", "secret", "sexyback",
"story", "tada", "tmyk", "trololo", "trombone", "unix",
"vuvuzela", "what", "whoomp", "yeah", "yodel"]
# informational: requirements for nodes
requirements: [ urllib2, cgi ]
author: Adam Garside <adam.garside@gmail.com>
'''
EXAMPLES = '''
- campfire: subscription=foo token=12345 room=123 msg="Task completed."
- campfire: subscription=foo token=12345 room=123 notify=loggins
msg="Task completed ... with feeling."
'''
def main():
try:
import urllib2
except ImportError:
module.fail_json(msg="urllib2 is required")
try:
import cgi
except ImportError:
module.fail_json(msg="cgi is required")
module = AnsibleModule(
argument_spec=dict(
subscription=dict(required=True),
token=dict(required=True),
room=dict(required=True),
msg=dict(required=True),
notify=dict(required=False,
choices=["56k", "bell", "bezos", "bueller",
"clowntown", "cottoneyejoe",
"crickets", "dadgummit", "dangerzone",
"danielsan", "deeper", "drama",
"greatjob", "greyjoy", "guarantee",
"heygirl", "horn", "horror",
"inconceivable", "live", "loggins",
"makeitso", "noooo", "nyan", "ohmy",
"ohyeah", "pushit", "rimshot",
"rollout", "rumble", "sax", "secret",
"sexyback", "story", "tada", "tmyk",
"trololo", "trombone", "unix",
"vuvuzela", "what", "whoomp", "yeah",
"yodel"]),
),
supports_check_mode=False
)
subscription = module.params["subscription"]
token = module.params["token"]
room = module.params["room"]
msg = module.params["msg"]
notify = module.params["notify"]
URI = "https://%s.campfirenow.com" % subscription
NSTR = "<message><type>SoundMessage</type><body>%s</body></message>"
MSTR = "<message><body>%s</body></message>"
AGENT = "Ansible/1.2"
try:
# Setup basic auth using token as the username
pm = urllib2.HTTPPasswordMgrWithDefaultRealm()
pm.add_password(None, URI, token, 'X')
# Setup Handler and define the opener for the request
handler = urllib2.HTTPBasicAuthHandler(pm)
opener = urllib2.build_opener(handler)
target_url = '%s/room/%s/speak.xml' % (URI, room)
# Send some audible notification if requested
if notify:
req = urllib2.Request(target_url, NSTR % cgi.escape(notify))
req.add_header('Content-Type', 'application/xml')
req.add_header('User-agent', AGENT)
response = opener.open(req)
# Send the message
req = urllib2.Request(target_url, MSTR % cgi.escape(msg))
req.add_header('Content-Type', 'application/xml')
req.add_header('User-agent', AGENT)
response = opener.open(req)
except urllib2.HTTPError, e:
if not (200 <= e.code < 300):
module.fail_json(msg="unable to send msg: '%s', campfire api"
" returned error code: '%s'" %
(msg, e.code))
except Exception, e:
module.fail_json(msg="unable to send msg: %s" % msg)
module.exit_json(changed=True, room=room, msg=msg, notify=notify)
# import module snippets
from ansible.module_utils.basic import *
main()

View File

@@ -0,0 +1,192 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2013 Matt Coddington <coddington@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
module: flowdock
version_added: "1.2"
author: Matt Coddington
short_description: Send a message to a flowdock
description:
- Send a message to a flowdock team inbox or chat using the push API (see https://www.flowdock.com/api/team-inbox and https://www.flowdock.com/api/chat)
options:
token:
description:
- API token.
required: true
type:
description:
- Whether to post to 'inbox' or 'chat'
required: true
choices: [ "inbox", "chat" ]
msg:
description:
- Content of the message
required: true
tags:
description:
- tags of the message, separated by commas
required: false
external_user_name:
description:
- (chat only - required) Name of the "user" sending the message
required: false
from_address:
description:
- (inbox only - required) Email address of the message sender
required: false
source:
description:
- (inbox only - required) Human readable identifier of the application that uses the Flowdock API
required: false
subject:
description:
- (inbox only - required) Subject line of the message
required: false
from_name:
description:
- (inbox only) Name of the message sender
required: false
reply_to:
description:
- (inbox only) Email address for replies
required: false
project:
description:
- (inbox only) Human readable identifier for more detailed message categorization
required: false
link:
description:
- (inbox only) Link associated with the message. This will be used to link the message subject in Team Inbox.
required: false
validate_certs:
description:
- If C(no), SSL certificates will not be validated. This should only be used
on personally controlled sites using self-signed certificates.
required: false
default: 'yes'
choices: ['yes', 'no']
version_added: 1.5.1
# informational: requirements for nodes
requirements: [ urllib, urllib2 ]
'''
EXAMPLES = '''
- flowdock: type=inbox
token=AAAAAA
from_address=user@example.com
source='my cool app'
msg='test from ansible'
subject='test subject'
- flowdock: type=chat
token=AAAAAA
external_user_name=testuser
msg='test from ansible'
tags=tag1,tag2,tag3
'''
# ===========================================
# Module execution.
#
def main():
module = AnsibleModule(
argument_spec=dict(
token=dict(required=True),
msg=dict(required=True),
type=dict(required=True, choices=["inbox","chat"]),
external_user_name=dict(required=False),
from_address=dict(required=False),
source=dict(required=False),
subject=dict(required=False),
from_name=dict(required=False),
reply_to=dict(required=False),
project=dict(required=False),
tags=dict(required=False),
link=dict(required=False),
validate_certs = dict(default='yes', type='bool'),
),
supports_check_mode=True
)
type = module.params["type"]
token = module.params["token"]
if type == 'inbox':
url = "https://api.flowdock.com/v1/messages/team_inbox/%s" % (token)
else:
url = "https://api.flowdock.com/v1/messages/chat/%s" % (token)
params = {}
# required params
params['content'] = module.params["msg"]
# required params for the 'chat' type
if module.params['external_user_name']:
if type == 'inbox':
module.fail_json(msg="external_user_name is not valid for the 'inbox' type")
else:
params['external_user_name'] = module.params["external_user_name"]
elif type == 'chat':
module.fail_json(msg="%s is required for the 'inbox' type" % item)
# required params for the 'inbox' type
for item in [ 'from_address', 'source', 'subject' ]:
if module.params[item]:
if type == 'chat':
module.fail_json(msg="%s is not valid for the 'chat' type" % item)
else:
params[item] = module.params[item]
elif type == 'inbox':
module.fail_json(msg="%s is required for the 'inbox' type" % item)
# optional params
if module.params["tags"]:
params['tags'] = module.params["tags"]
# optional params for the 'inbox' type
for item in [ 'from_name', 'reply_to', 'project', 'link' ]:
if module.params[item]:
if type == 'chat':
module.fail_json(msg="%s is not valid for the 'chat' type" % item)
else:
params[item] = module.params[item]
# If we're in check mode, just exit pretending like we succeeded
if module.check_mode:
module.exit_json(changed=False)
# Send the data to Flowdock
data = urllib.urlencode(params)
response, info = fetch_url(module, url, data=data)
if info['status'] != 200:
module.fail_json(msg="unable to send msg: %s" % info['msg'])
module.exit_json(changed=True, msg=module.params["msg"])
# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
main()

View File

@@ -0,0 +1,99 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
---
module: grove
version_added: 1.4
short_description: Sends a notification to a grove.io channel
description:
- The M(grove) module sends a message for a service to a Grove.io
channel.
options:
channel_token:
description:
- Token of the channel to post to.
required: true
service:
description:
- Name of the service (displayed as the "user" in the message)
required: false
default: ansible
message:
description:
- Message content
required: true
url:
description:
- Service URL for the web client
required: false
icon_url:
description:
- Icon for the service
required: false
validate_certs:
description:
- If C(no), SSL certificates will not be validated. This should only be used
on personally controlled sites using self-signed certificates.
required: false
default: 'yes'
choices: ['yes', 'no']
version_added: 1.5.1
author: Jonas Pfenniger <zimbatm@zimbatm.com>
'''
EXAMPLES = '''
- grove: >
channel_token=6Ph62VBBJOccmtTPZbubiPzdrhipZXtg
service=my-app
message=deployed {{ target }}
'''
BASE_URL = 'https://grove.io/api/notice/%s/'
# ==============================================================
# do_notify_grove
def do_notify_grove(module, channel_token, service, message, url=None, icon_url=None):
my_url = BASE_URL % (channel_token,)
my_data = dict(service=service, message=message)
if url is not None:
my_data['url'] = url
if icon_url is not None:
my_data['icon_url'] = icon_url
data = urllib.urlencode(my_data)
response, info = fetch_url(module, my_url, data=data)
if info['status'] != 200:
module.fail_json(msg="failed to send notification: %s" % info['msg'])
# ==============================================================
# main
def main():
module = AnsibleModule(
argument_spec = dict(
channel_token = dict(type='str', required=True),
message = dict(type='str', required=True),
service = dict(type='str', default='ansible'),
url = dict(type='str', default=None),
icon_url = dict(type='str', default=None),
validate_certs = dict(default='yes', type='bool'),
)
)
channel_token = module.params['channel_token']
service = module.params['service']
message = module.params['message']
url = module.params['url']
icon_url = module.params['icon_url']
do_notify_grove(module, channel_token, service, message, url, icon_url)
# Mission complete
module.exit_json(msg="OK")
# import module snippets
from ansible.module_utils.basic import *
main()

View File

@@ -0,0 +1,149 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
---
module: hipchat
version_added: "1.2"
short_description: Send a message to hipchat
description:
- Send a message to hipchat
options:
token:
description:
- API token.
required: true
room:
description:
- ID or name of the room.
required: true
from:
description:
- Name the message will appear be sent from. max 15 characters.
Over 15, will be shorten.
required: false
default: Ansible
msg:
description:
- The message body.
required: true
default: null
color:
description:
- Background color for the message. Default is yellow.
required: false
default: yellow
choices: [ "yellow", "red", "green", "purple", "gray", "random" ]
msg_format:
description:
- message format. html or text. Default is text.
required: false
default: text
choices: [ "text", "html" ]
notify:
description:
- notify or not (change the tab color, play a sound, etc)
required: false
default: 'yes'
choices: [ "yes", "no" ]
validate_certs:
description:
- If C(no), SSL certificates will not be validated. This should only be used
on personally controlled sites using self-signed certificates.
required: false
default: 'yes'
choices: ['yes', 'no']
version_added: 1.5.1
api:
description:
- API url if using a self-hosted hipchat server
required: false
default: 'https://api.hipchat.com/v1/rooms/message'
version_added: 1.6.0
# informational: requirements for nodes
requirements: [ urllib, urllib2 ]
author: WAKAYAMA Shirou
'''
EXAMPLES = '''
- hipchat: token=AAAAAA room=notify msg="Ansible task finished"
'''
# ===========================================
# HipChat module specific support methods.
#
MSG_URI = "https://api.hipchat.com/v1/rooms/message"
def send_msg(module, token, room, msg_from, msg, msg_format='text',
color='yellow', notify=False, api=MSG_URI):
'''sending message to hipchat'''
params = {}
params['room_id'] = room
params['from'] = msg_from[:15] # max length is 15
params['message'] = msg
params['message_format'] = msg_format
params['color'] = color
params['api'] = api
if notify:
params['notify'] = 1
else:
params['notify'] = 0
url = api + "?auth_token=%s" % (token)
data = urllib.urlencode(params)
response, info = fetch_url(module, url, data=data)
if info['status'] == 200:
return response.read()
else:
module.fail_json(msg="failed to send message, return status=%s" % str(info['status']))
# ===========================================
# Module execution.
#
def main():
module = AnsibleModule(
argument_spec=dict(
token=dict(required=True),
room=dict(required=True),
msg=dict(required=True),
msg_from=dict(default="Ansible", aliases=['from']),
color=dict(default="yellow", choices=["yellow", "red", "green",
"purple", "gray", "random"]),
msg_format=dict(default="text", choices=["text", "html"]),
notify=dict(default=True, type='bool'),
validate_certs = dict(default='yes', type='bool'),
api = dict(default=MSG_URI),
),
supports_check_mode=True
)
token = module.params["token"]
room = module.params["room"]
msg = module.params["msg"]
msg_from = module.params["msg_from"]
color = module.params["color"]
msg_format = module.params["msg_format"]
notify = module.params["notify"]
api = module.params["api"]
try:
send_msg(module, token, room, msg_from, msg, msg_format, color, notify, api)
except Exception, e:
module.fail_json(msg="unable to sent msg: %s" % e)
changed = True
module.exit_json(changed=changed, room=room, msg_from=msg_from, msg=msg)
# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
main()

View File

@@ -0,0 +1,215 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013, Jan-Piet Mens <jpmens () gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
DOCUMENTATION = '''
---
module: irc
version_added: "1.2"
short_description: Send a message to an IRC channel
description:
- Send a message to an IRC channel. This is a very simplistic implementation.
options:
server:
description:
- IRC server name/address
required: false
default: localhost
port:
description:
- IRC server port number
required: false
default: 6667
nick:
description:
- Nickname. May be shortened, depending on server's NICKLEN setting.
required: false
default: ansible
msg:
description:
- The message body.
required: true
default: null
color:
description:
- Text color for the message. ("none" is a valid option in 1.6 or later, in 1.6 and prior, the default color is black, not "none").
required: false
default: "none"
choices: [ "none", "yellow", "red", "green", "blue", "black" ]
channel:
description:
- Channel name
required: true
key:
description:
- Channel key
required: false
version_added: 1.7
passwd:
description:
- Server password
required: false
timeout:
description:
- Timeout to use while waiting for successful registration and join
messages, this is to prevent an endless loop
default: 30
version_added: 1.5
use_ssl:
description:
- Designates whether TLS/SSL should be used when connecting to the IRC server
default: False
version_added: 1.8
# informational: requirements for nodes
requirements: [ socket ]
author: Jan-Piet Mens, Matt Martz
'''
EXAMPLES = '''
- irc: server=irc.example.net channel="#t1" msg="Hello world"
- local_action: irc port=6669
channel="#t1"
msg="All finished at {{ ansible_date_time.iso8601 }}"
color=red
nick=ansibleIRC
'''
# ===========================================
# IRC module support methods.
#
import re
import socket
import ssl
from time import sleep
def send_msg(channel, msg, server='localhost', port='6667', key=None,
nick="ansible", color='none', passwd=False, timeout=30, use_ssl=False):
'''send message to IRC'''
colornumbers = {
'black': "01",
'red': "04",
'green': "09",
'yellow': "08",
'blue': "12",
}
try:
colornumber = colornumbers[color]
colortext = "\x03" + colornumber
except:
colortext = ""
message = colortext + msg
irc = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if use_ssl:
irc = ssl.wrap_socket(irc)
irc.connect((server, int(port)))
if passwd:
irc.send('PASS %s\r\n' % passwd)
irc.send('NICK %s\r\n' % nick)
irc.send('USER %s %s %s :ansible IRC\r\n' % (nick, nick, nick))
motd = ''
start = time.time()
while 1:
motd += irc.recv(1024)
# The server might send back a shorter nick than we specified (due to NICKLEN),
# so grab that and use it from now on (assuming we find the 00[1-4] response).
match = re.search('^:\S+ 00[1-4] (?P<nick>\S+) :', motd, flags=re.M)
if match:
nick = match.group('nick')
break
elif time.time() - start > timeout:
raise Exception('Timeout waiting for IRC server welcome response')
sleep(0.5)
if key:
irc.send('JOIN %s %s\r\n' % (channel, key))
else:
irc.send('JOIN %s\r\n' % channel)
join = ''
start = time.time()
while 1:
join += irc.recv(1024)
if re.search('^:\S+ 366 %s %s :' % (nick, channel), join, flags=re.M):
break
elif time.time() - start > timeout:
raise Exception('Timeout waiting for IRC JOIN response')
sleep(0.5)
irc.send('PRIVMSG %s :%s\r\n' % (channel, message))
sleep(1)
irc.send('PART %s\r\n' % channel)
irc.send('QUIT\r\n')
sleep(1)
irc.close()
# ===========================================
# Main
#
def main():
module = AnsibleModule(
argument_spec=dict(
server=dict(default='localhost'),
port=dict(default=6667),
nick=dict(default='ansible'),
msg=dict(required=True),
color=dict(default="none", choices=["yellow", "red", "green",
"blue", "black", "none"]),
channel=dict(required=True),
key=dict(),
passwd=dict(),
timeout=dict(type='int', default=30),
use_ssl=dict(type='bool', default=False)
),
supports_check_mode=True
)
server = module.params["server"]
port = module.params["port"]
nick = module.params["nick"]
msg = module.params["msg"]
color = module.params["color"]
channel = module.params["channel"]
key = module.params["key"]
passwd = module.params["passwd"]
timeout = module.params["timeout"]
use_ssl = module.params["use_ssl"]
try:
send_msg(channel, msg, server, port, key, nick, color, passwd, timeout, use_ssl)
except Exception, e:
module.fail_json(msg="unable to send to IRC: %s" % e)
module.exit_json(changed=False, channel=channel, nick=nick,
msg=msg)
# import module snippets
from ansible.module_utils.basic import *
main()

View File

@@ -0,0 +1,146 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
---
version_added: "1.2"
module: jabber
short_description: Send a message to jabber user or chat room
description:
- Send a message to jabber
options:
user:
description:
User as which to connect
required: true
password:
description:
password for user to connect
required: true
to:
description:
user ID or name of the room, when using room use a slash to indicate your nick.
required: true
msg:
description:
- The message body.
required: true
default: null
host:
description:
host to connect, overrides user info
required: false
port:
description:
port to connect to, overrides default
required: false
default: 5222
encoding:
description:
message encoding
required: false
# informational: requirements for nodes
requirements: [ xmpp ]
author: Brian Coca
'''
EXAMPLES = '''
# send a message to a user
- jabber: user=mybot@example.net
password=secret
to=friend@example.net
msg="Ansible task finished"
# send a message to a room
- jabber: user=mybot@example.net
password=secret
to=mychaps@conference.example.net/ansiblebot
msg="Ansible task finished"
# send a message, specifying the host and port
- jabber user=mybot@example.net
host=talk.example.net
port=5223
password=secret
to=mychaps@example.net
msg="Ansible task finished"
'''
import os
import re
import time
HAS_XMPP = True
try:
import xmpp
except ImportError:
HAS_XMPP = False
def main():
module = AnsibleModule(
argument_spec=dict(
user=dict(required=True),
password=dict(required=True),
to=dict(required=True),
msg=dict(required=True),
host=dict(required=False),
port=dict(required=False,default=5222),
encoding=dict(required=False),
),
supports_check_mode=True
)
if not HAS_XMPP:
module.fail_json(msg="xmpp is not installed")
jid = xmpp.JID(module.params['user'])
user = jid.getNode()
server = jid.getDomain()
port = module.params['port']
password = module.params['password']
try:
to, nick = module.params['to'].split('/', 1)
except ValueError:
to, nick = module.params['to'], None
if module.params['host']:
host = module.params['host']
else:
host = server
if module.params['encoding']:
xmpp.simplexml.ENCODING = params['encoding']
msg = xmpp.protocol.Message(body=module.params['msg'])
try:
conn=xmpp.Client(server)
if not conn.connect(server=(host,port)):
module.fail_json(rc=1, msg='Failed to connect to server: %s' % (server))
if not conn.auth(user,password,'Ansible'):
module.fail_json(rc=1, msg='Failed to authorize %s on: %s' % (user,server))
# some old servers require this, also the sleep following send
conn.sendInitPresence(requestRoster=0)
if nick: # sending to room instead of user, need to join
msg.setType('groupchat')
msg.setTag('x', namespace='http://jabber.org/protocol/muc#user')
conn.send(xmpp.Presence(to=module.params['to']))
time.sleep(1)
else:
msg.setType('chat')
msg.setTo(to)
if not module.check_mode:
conn.send(msg)
time.sleep(1)
conn.disconnect()
except Exception, e:
module.fail_json(msg="unable to send msg: %s" % e)
module.exit_json(changed=False, to=to, user=user, msg=msg.getBody())
# import module snippets
from ansible.module_utils.basic import *
main()

View File

@@ -0,0 +1,252 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2012 Dag Wieers <dag@wieers.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = """
---
author: Dag Wieers
module: mail
short_description: Send an email
description:
- This module is useful for sending emails from playbooks.
- One may wonder why automate sending emails? In complex environments
there are from time to time processes that cannot be automated, either
because you lack the authority to make it so, or because not everyone
agrees to a common approach.
- If you cannot automate a specific step, but the step is non-blocking,
sending out an email to the responsible party to make him perform his
part of the bargain is an elegant way to put the responsibility in
someone else's lap.
- Of course sending out a mail can be equally useful as a way to notify
one or more people in a team that a specific action has been
(successfully) taken.
version_added: "0.8"
options:
from:
description:
- The email-address the mail is sent from. May contain address and phrase.
default: root
required: false
to:
description:
- The email-address(es) the mail is being sent to. This is
a comma-separated list, which may contain address and phrase portions.
default: root
required: false
cc:
description:
- The email-address(es) the mail is being copied to. This is
a comma-separated list, which may contain address and phrase portions.
required: false
bcc:
description:
- The email-address(es) the mail is being 'blind' copied to. This is
a comma-separated list, which may contain address and phrase portions.
required: false
subject:
description:
- The subject of the email being sent.
aliases: [ msg ]
required: true
body:
description:
- The body of the email being sent.
default: $subject
required: false
host:
description:
- The mail server
default: 'localhost'
required: false
port:
description:
- The mail server port
default: '25'
required: false
version_added: "1.0"
attach:
description:
- A space-separated list of pathnames of files to attach to the message.
Attached files will have their content-type set to C(application/octet-stream).
default: null
required: false
version_added: "1.0"
headers:
description:
- A vertical-bar-separated list of headers which should be added to the message.
Each individual header is specified as C(header=value) (see example below).
default: null
required: false
version_added: "1.0"
charset:
description:
- The character set of email being sent
default: 'us-ascii'
required: false
"""
EXAMPLES = '''
# Example playbook sending mail to root
- local_action: mail msg='System {{ ansible_hostname }} has been successfully provisioned.'
# Send e-mail to a bunch of users, attaching files
- local_action: mail
host='127.0.0.1'
port=2025
subject="Ansible-report"
body="Hello, this is an e-mail. I hope you like it ;-)"
from="jane@example.net (Jane Jolie)"
to="John Doe <j.d@example.org>, Suzie Something <sue@example.com>"
cc="Charlie Root <root@localhost>"
attach="/etc/group /tmp/pavatar2.png"
headers=Reply-To=john@example.com|X-Special="Something or other"
charset=utf8
'''
import os
import sys
import smtplib
try:
from email import encoders
import email.utils
from email.utils import parseaddr, formataddr
from email.mime.base import MIMEBase
from mail.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
except ImportError:
from email import Encoders as encoders
import email.Utils
from email.Utils import parseaddr, formataddr
from email.MIMEBase import MIMEBase
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
def main():
module = AnsibleModule(
argument_spec = dict(
host = dict(default='localhost'),
port = dict(default='25'),
sender = dict(default='root', aliases=['from']),
to = dict(default='root', aliases=['recipients']),
cc = dict(default=None),
bcc = dict(default=None),
subject = dict(required=True, aliases=['msg']),
body = dict(default=None),
attach = dict(default=None),
headers = dict(default=None),
charset = dict(default='us-ascii')
)
)
host = module.params.get('host')
port = module.params.get('port')
sender = module.params.get('sender')
recipients = module.params.get('to')
copies = module.params.get('cc')
blindcopies = module.params.get('bcc')
subject = module.params.get('subject')
body = module.params.get('body')
attach_files = module.params.get('attach')
headers = module.params.get('headers')
charset = module.params.get('charset')
sender_phrase, sender_addr = parseaddr(sender)
if not body:
body = subject
try:
smtp = smtplib.SMTP(host, port=int(port))
except Exception, e:
module.fail_json(rc=1, msg='Failed to send mail to server %s on port %s: %s' % (host, port, e))
msg = MIMEMultipart()
msg['Subject'] = subject
msg['From'] = formataddr((sender_phrase, sender_addr))
msg.preamble = "Multipart message"
if headers is not None:
for hdr in [x.strip() for x in headers.split('|')]:
try:
h_key, h_val = hdr.split('=')
msg.add_header(h_key, h_val)
except:
pass
if 'X-Mailer' not in msg:
msg.add_header('X-Mailer', "Ansible")
to_list = []
cc_list = []
addr_list = []
if recipients is not None:
for addr in [x.strip() for x in recipients.split(',')]:
to_list.append( formataddr( parseaddr(addr)) )
addr_list.append( parseaddr(addr)[1] ) # address only, w/o phrase
if copies is not None:
for addr in [x.strip() for x in copies.split(',')]:
cc_list.append( formataddr( parseaddr(addr)) )
addr_list.append( parseaddr(addr)[1] ) # address only, w/o phrase
if blindcopies is not None:
for addr in [x.strip() for x in blindcopies.split(',')]:
addr_list.append( parseaddr(addr)[1] )
if len(to_list) > 0:
msg['To'] = ", ".join(to_list)
if len(cc_list) > 0:
msg['Cc'] = ", ".join(cc_list)
part = MIMEText(body + "\n\n", _charset=charset)
msg.attach(part)
if attach_files is not None:
for file in attach_files.split():
try:
fp = open(file, 'rb')
part = MIMEBase('application', 'octet-stream')
part.set_payload(fp.read())
fp.close()
encoders.encode_base64(part)
part.add_header('Content-disposition', 'attachment', filename=os.path.basename(file))
msg.attach(part)
except Exception, e:
module.fail_json(rc=1, msg="Failed to send mail: can't attach file %s: %s" % (file, e))
sys.exit()
composed = msg.as_string()
try:
smtp.sendmail(sender_addr, set(addr_list), composed)
except Exception, e:
module.fail_json(rc=1, msg='Failed to send mail to %s: %s' % (", ".join(addr_list), e))
smtp.quit()
module.exit_json(changed=False)
# import module snippets
from ansible.module_utils.basic import *
main()

View File

@@ -0,0 +1,166 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013, 2014, Jan-Piet Mens <jpmens () gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#
DOCUMENTATION = '''
---
module: mqtt
short_description: Publish a message on an MQTT topic for the IoT
version_added: "1.2"
description:
- Publish a message on an MQTT topic.
options:
server:
description:
- MQTT broker address/name
required: false
default: localhost
port:
description:
- MQTT broker port number
required: false
default: 1883
username:
description:
- Username to authenticate against the broker.
required: false
password:
description:
- Password for C(username) to authenticate against the broker.
required: false
client_id:
description:
- MQTT client identifier
required: false
default: hostname + pid
topic:
description:
- MQTT topic name
required: true
default: null
payload:
description:
- Payload. The special string C("None") may be used to send a NULL
(i.e. empty) payload which is useful to simply notify with the I(topic)
or to clear previously retained messages.
required: true
default: null
qos:
description:
- QoS (Quality of Service)
required: false
default: 0
choices: [ "0", "1", "2" ]
retain:
description:
- Setting this flag causes the broker to retain (i.e. keep) the message so that
applications that subsequently subscribe to the topic can received the last
retained message immediately.
required: false
default: False
# informational: requirements for nodes
requirements: [ mosquitto ]
notes:
- This module requires a connection to an MQTT broker such as Mosquitto
U(http://mosquitto.org) and the I(Paho) C(mqtt) Python client (U(https://pypi.python.org/pypi/paho-mqtt)).
author: Jan-Piet Mens
'''
EXAMPLES = '''
- local_action: mqtt
topic=service/ansible/{{ ansible_hostname }}
payload="Hello at {{ ansible_date_time.iso8601 }}"
qos=0
retain=false
client_id=ans001
'''
# ===========================================
# MQTT module support methods.
#
HAS_PAHOMQTT = True
try:
import socket
import paho.mqtt.publish as mqtt
except ImportError:
HAS_PAHOMQTT = False
# ===========================================
# Main
#
def main():
module = AnsibleModule(
argument_spec=dict(
server = dict(default = 'localhost'),
port = dict(default = 1883),
topic = dict(required = True),
payload = dict(required = True),
client_id = dict(default = None),
qos = dict(default="0", choices=["0", "1", "2"]),
retain = dict(default=False, type='bool'),
username = dict(default = None),
password = dict(default = None),
),
supports_check_mode=True
)
if not HAS_PAHOMQTT:
module.fail_json(msg="Paho MQTT is not installed")
server = module.params.get("server", 'localhost')
port = module.params.get("port", 1883)
topic = module.params.get("topic")
payload = module.params.get("payload")
client_id = module.params.get("client_id", '')
qos = int(module.params.get("qos", 0))
retain = module.params.get("retain")
username = module.params.get("username", None)
password = module.params.get("password", None)
if client_id is None:
client_id = "%s_%s" % (socket.getfqdn(), os.getpid())
if payload and payload == 'None':
payload = None
auth=None
if username is not None:
auth = { 'username' : username, 'password' : password }
try:
rc = mqtt.single(topic, payload,
qos=qos,
retain=retain,
client_id=client_id,
hostname=server,
port=port,
auth=auth)
except Exception, e:
module.fail_json(msg="unable to publish to MQTT broker %s" % (e))
module.exit_json(changed=False, topic=topic)
# import module snippets
from ansible.module_utils.basic import *
main()

View File

@@ -0,0 +1,140 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2014, Matt Martz <matt@sivel.net>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = """
module: nexmo
short_description: Send a SMS via nexmo
description:
- Send a SMS message via nexmo
version_added: 1.6
author: Matt Martz
options:
api_key:
description:
- Nexmo API Key
required: true
api_secret:
description:
- Nexmo API Secret
required: true
src:
description:
- Nexmo Number to send from
required: true
dest:
description:
- Phone number(s) to send SMS message to
required: true
msg:
description:
- Message to text to send. Messages longer than 160 characters will be
split into multiple messages
required: true
validate_certs:
description:
- If C(no), SSL certificates will not be validated. This should only be used
on personally controlled sites using self-signed certificates.
required: false
default: 'yes'
choices:
- 'yes'
- 'no'
"""
EXAMPLES = """
- name: Send notification message via Nexmo
local_action:
module: nexmo
api_key: 640c8a53
api_secret: 0ce239a6
src: 12345678901
dest:
- 10987654321
- 16789012345
msg: "{{ inventory_hostname }} completed"
"""
NEXMO_API = 'https://rest.nexmo.com/sms/json'
def send_msg(module):
failed = list()
responses = dict()
msg = {
'api_key': module.params.get('api_key'),
'api_secret': module.params.get('api_secret'),
'from': module.params.get('src'),
'text': module.params.get('msg')
}
for number in module.params.get('dest'):
msg['to'] = number
url = "%s?%s" % (NEXMO_API, urllib.urlencode(msg))
headers = dict(Accept='application/json')
response, info = fetch_url(module, url, headers=headers)
if info['status'] != 200:
failed.append(number)
responses[number] = dict(failed=True)
try:
responses[number] = json.load(response)
except:
failed.append(number)
responses[number] = dict(failed=True)
else:
for message in responses[number]['messages']:
if int(message['status']) != 0:
failed.append(number)
responses[number] = dict(failed=True, **responses[number])
if failed:
msg = 'One or messages failed to send'
else:
msg = ''
module.exit_json(failed=bool(failed), msg=msg, changed=False,
responses=responses)
def main():
argument_spec = url_argument_spec()
argument_spec.update(
dict(
api_key=dict(required=True, no_log=True),
api_secret=dict(required=True, no_log=True),
src=dict(required=True, type='int'),
dest=dict(required=True, type='list'),
msg=dict(required=True),
),
)
module = AnsibleModule(
argument_spec=argument_spec
)
send_msg(module)
# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
main()

View File

@@ -0,0 +1,74 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2013, Michael DeHaan <michael@ansible.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
module: osx_say
version_added: "1.2"
short_description: Makes an OSX computer to speak.
description:
- makes an OS computer speak! Amuse your friends, annoy your coworkers!
notes:
- If you like this module, you may also be interested in the osx_say callback in the plugins/ directory of the source checkout.
options:
msg:
description:
What to say
required: true
voice:
description:
What voice to use
required: false
requirements: [ say ]
author: Michael DeHaan
'''
EXAMPLES = '''
- local_action: osx_say msg="{{inventory_hostname}} is all done" voice=Zarvox
'''
DEFAULT_VOICE='Trinoids'
def say(module, msg, voice):
module.run_command(["/usr/bin/say", msg, "--voice=%s" % (voice)], check_rc=True)
def main():
module = AnsibleModule(
argument_spec=dict(
msg=dict(required=True),
voice=dict(required=False, default=DEFAULT_VOICE),
),
supports_check_mode=False
)
if not os.path.exists("/usr/bin/say"):
module.fail_json(msg="/usr/bin/say is not installed")
msg = module.params['msg']
voice = module.params['voice']
say(module, msg, voice)
module.exit_json(msg=msg, changed=False)
# import module snippets
from ansible.module_utils.basic import *
main()

View File

@@ -0,0 +1,173 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2014, Ramon de la Fuente <ramon@delafuente.nl>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = """
module: slack
short_description: Send Slack notifications
description:
- The M(slack) module sends notifications to U(http://slack.com) via the Incoming WebHook integration
version_added: 1.6
author: Ramon de la Fuente <ramon@delafuente.nl>
options:
domain:
description:
- Slack (sub)domain for your environment without protocol.
(i.e. C(future500.slack.com))
required: true
token:
description:
- Slack integration token
required: true
msg:
description:
- Message to send.
required: true
channel:
description:
- Channel to send the message to. If absent, the message goes to the channel selected for the I(token).
required: false
username:
description:
- This is the sender of the message.
required: false
default: ansible
icon_url:
description:
- Url for the message sender's icon (default C(http://www.ansible.com/favicon.ico))
required: false
icon_emoji:
description:
- Emoji for the message sender. See Slack documentation for options.
(if I(icon_emoji) is set, I(icon_url) will not be used)
required: false
link_names:
description:
- Automatically create links for channels and usernames in I(msg).
required: false
default: 1
choices:
- 1
- 0
parse:
description:
- Setting for the message parser at Slack
required: false
choices:
- 'full'
- 'none'
validate_certs:
description:
- If C(no), SSL certificates will not be validated. This should only be used
on personally controlled sites using self-signed certificates.
required: false
default: 'yes'
choices:
- 'yes'
- 'no'
"""
EXAMPLES = """
- name: Send notification message via Slack
local_action:
module: slack
domain: future500.slack.com
token: thetokengeneratedbyslack
msg: "{{ inventory_hostname }} completed"
- name: Send notification message via Slack all options
local_action:
module: slack
domain: future500.slack.com
token: thetokengeneratedbyslack
msg: "{{ inventory_hostname }} completed"
channel: "#ansible"
username: "Ansible on {{ inventory_hostname }}"
icon_url: "http://www.example.com/some-image-file.png"
link_names: 0
parse: 'none'
"""
SLACK_INCOMING_WEBHOOK = 'https://%s/services/hooks/incoming-webhook?token=%s'
def build_payload_for_slack(module, text, channel, username, icon_url, icon_emoji, link_names, parse):
payload = dict(text=text)
if channel is not None:
payload['channel'] = channel if (channel[0] == '#') else '#'+channel
if username is not None:
payload['username'] = username
if icon_emoji is not None:
payload['icon_emoji'] = icon_emoji
else:
payload['icon_url'] = icon_url
if link_names is not None:
payload['link_names'] = link_names
if parse is not None:
payload['parse'] = parse
payload="payload=" + module.jsonify(payload)
return payload
def do_notify_slack(module, domain, token, payload):
slack_incoming_webhook = SLACK_INCOMING_WEBHOOK % (domain, token)
response, info = fetch_url(module, slack_incoming_webhook, data=payload)
if info['status'] != 200:
obscured_incoming_webhook = SLACK_INCOMING_WEBHOOK % (domain, '[obscured]')
module.fail_json(msg=" failed to send %s to %s: %s" % (payload, obscured_incoming_webhook, info['msg']))
def main():
module = AnsibleModule(
argument_spec = dict(
domain = dict(type='str', required=True),
token = dict(type='str', required=True),
msg = dict(type='str', required=True),
channel = dict(type='str', default=None),
username = dict(type='str', default='Ansible'),
icon_url = dict(type='str', default='http://www.ansible.com/favicon.ico'),
icon_emoji = dict(type='str', default=None),
link_names = dict(type='int', default=1, choices=[0,1]),
parse = dict(type='str', default=None, choices=['none', 'full']),
validate_certs = dict(default='yes', type='bool'),
)
)
domain = module.params['domain']
token = module.params['token']
text = module.params['msg']
channel = module.params['channel']
username = module.params['username']
icon_url = module.params['icon_url']
icon_emoji = module.params['icon_emoji']
link_names = module.params['link_names']
parse = module.params['parse']
payload = build_payload_for_slack(module, text, channel, username, icon_url, icon_emoji, link_names, parse)
do_notify_slack(module, domain, token, payload)
module.exit_json(msg="OK")
# import module snippets
from ansible.module_utils.basic import *
from ansible.module_utils.urls import *
main()

View File

@@ -0,0 +1,190 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2014, Michael J. Schultz <mjschultz@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = """
module: sns
short_description: Send Amazon Simple Notification Service (SNS) messages
description:
- The M(sns) module sends notifications to a topic on your Amazon SNS account
version_added: 1.6
author: Michael J. Schultz <mjschultz@gmail.com>
options:
msg:
description:
- Default message to send.
required: true
aliases: [ "default" ]
subject:
description:
- Subject line for email delivery.
required: false
topic:
description:
- The topic you want to publish to.
required: true
email:
description:
- Message to send to email-only subscription
required: false
sqs:
description:
- Message to send to SQS-only subscription
required: false
sms:
description:
- Message to send to SMS-only subscription
required: false
http:
description:
- Message to send to HTTP-only subscription
required: false
https:
description:
- Message to send to HTTPS-only subscription
required: false
aws_secret_key:
description:
- AWS secret key. If not set then the value of the AWS_SECRET_KEY environment variable is used.
required: false
default: None
aliases: ['ec2_secret_key', 'secret_key']
aws_access_key:
description:
- AWS access key. If not set then the value of the AWS_ACCESS_KEY environment variable is used.
required: false
default: None
aliases: ['ec2_access_key', 'access_key']
region:
description:
- The AWS region to use. If not specified then the value of the EC2_REGION environment variable, if any, is used.
required: false
aliases: ['aws_region', 'ec2_region']
requirements: [ "boto" ]
author: Michael J. Schultz
"""
EXAMPLES = """
- name: Send default notification message via SNS
local_action:
module: sns
msg: "{{ inventory_hostname }} has completed the play."
subject: "Deploy complete!"
topic: "deploy"
- name: Send notification messages via SNS with short message for SMS
local_action:
module: sns
msg: "{{ inventory_hostname }} has completed the play."
sms: "deployed!"
subject: "Deploy complete!"
topic: "deploy"
"""
import sys
from ansible.module_utils.basic import *
from ansible.module_utils.ec2 import *
try:
import boto
import boto.sns
except ImportError:
print "failed=True msg='boto required for this module'"
sys.exit(1)
def arn_topic_lookup(connection, short_topic):
response = connection.get_all_topics()
result = response[u'ListTopicsResponse'][u'ListTopicsResult']
# topic names cannot have colons, so this captures the full topic name
lookup_topic = ':{}'.format(short_topic)
for topic in result[u'Topics']:
if topic[u'TopicArn'].endswith(lookup_topic):
return topic[u'TopicArn']
return None
def main():
argument_spec = ec2_argument_spec()
argument_spec.update(
dict(
msg=dict(type='str', required=True, aliases=['default']),
subject=dict(type='str', default=None),
topic=dict(type='str', required=True),
email=dict(type='str', default=None),
sqs=dict(type='str', default=None),
sms=dict(type='str', default=None),
http=dict(type='str', default=None),
https=dict(type='str', default=None),
)
)
module = AnsibleModule(argument_spec=argument_spec)
msg = module.params['msg']
subject = module.params['subject']
topic = module.params['topic']
email = module.params['email']
sqs = module.params['sqs']
sms = module.params['sms']
http = module.params['http']
https = module.params['https']
region, ec2_url, aws_connect_params = get_aws_connection_info(module)
if not region:
module.fail_json(msg="region must be specified")
try:
connection = connect_to_aws(boto.sns, region, **aws_connect_params)
except boto.exception.NoAuthHandlerFound, e:
module.fail_json(msg=str(e))
# .publish() takes full ARN topic id, but I'm lazy and type shortnames
# so do a lookup (topics cannot contain ':', so thats the decider)
if ':' in topic:
arn_topic = topic
else:
arn_topic = arn_topic_lookup(connection, topic)
if not arn_topic:
module.fail_json(msg='Could not find topic: {}'.format(topic))
dict_msg = {'default': msg}
if email:
dict_msg.update(email=email)
if sqs:
dict_msg.update(sqs=sqs)
if sms:
dict_msg.update(sms=sms)
if http:
dict_msg.update(http=http)
if https:
dict_msg.update(https=https)
json_msg = json.dumps(dict_msg)
try:
connection.publish(topic=arn_topic, subject=subject,
message_structure='json', message=json_msg)
except boto.exception.BotoServerError, e:
module.fail_json(msg=str(e))
module.exit_json(msg="OK")
main()

View File

@@ -0,0 +1,135 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# (c) 2014, Matt Makai <matthew.makai@gmail.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
DOCUMENTATION = '''
---
version_added: "1.6"
module: twilio
short_description: Sends a text message to a mobile phone through Twilio.
description:
- Sends a text message to a phone number through an the Twilio SMS service.
notes:
- Like the other notification modules, this one requires an external
dependency to work. In this case, you'll need a Twilio account with
a purchased or verified phone number to send the text message.
options:
account_sid:
description:
user's account id for Twilio found on the account page
required: true
auth_token:
description: user's authentication token for Twilio found on the account page
required: true
msg:
description:
the body of the text message
required: true
to_number:
description:
what phone number to send the text message to, format +15551112222
required: true
from_number:
description:
what phone number to send the text message from, format +15551112222
required: true
requirements: [ urllib, urllib2 ]
author: Matt Makai
'''
EXAMPLES = '''
# send a text message from the local server about the build status to (555) 303 5681
# note: you have to have purchased the 'from_number' on your Twilio account
- local_action: text msg="All servers with webserver role are now configured."
account_sid={{ twilio_account_sid }}
auth_token={{ twilio_auth_token }}
from_number=+15552014545 to_number=+15553035681
# send a text message from a server to (555) 111 3232
# note: you have to have purchased the 'from_number' on your Twilio account
- text: msg="This server's configuration is now complete."
account_sid={{ twilio_account_sid }}
auth_token={{ twilio_auth_token }}
from_number=+15553258899 to_number=+15551113232
'''
# =======================================
# text module support methods
#
try:
import urllib, urllib2
except ImportError:
module.fail_json(msg="urllib and urllib2 are required")
import base64
def post_text(module, account_sid, auth_token, msg, from_number, to_number):
URI = "https://api.twilio.com/2010-04-01/Accounts/%s/Messages.json" \
% (account_sid,)
AGENT = "Ansible/1.5"
data = {'From':from_number, 'To':to_number, 'Body':msg}
encoded_data = urllib.urlencode(data)
request = urllib2.Request(URI)
base64string = base64.encodestring('%s:%s' % \
(account_sid, auth_token)).replace('\n', '')
request.add_header('User-Agent', AGENT)
request.add_header('Content-type', 'application/x-www-form-urlencoded')
request.add_header('Accept', 'application/ansible')
request.add_header('Authorization', 'Basic %s' % base64string)
return urllib2.urlopen(request, encoded_data)
# =======================================
# Main
#
def main():
module = AnsibleModule(
argument_spec=dict(
account_sid=dict(required=True),
auth_token=dict(required=True),
msg=dict(required=True),
from_number=dict(required=True),
to_number=dict(required=True),
),
supports_check_mode=True
)
account_sid = module.params['account_sid']
auth_token = module.params['auth_token']
msg = module.params['msg']
from_number = module.params['from_number']
to_number = module.params['to_number']
try:
response = post_text(module, account_sid, auth_token, msg,
from_number, to_number)
except Exception, e:
module.fail_json(msg="unable to send text message to %s" % to_number)
module.exit_json(msg=msg, changed=False)
# import module snippets
from ansible.module_utils.basic import *
main()

View File

@@ -0,0 +1,116 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
DOCUMENTATION = '''
---
module: typetalk
version_added: "1.6"
short_description: Send a message to typetalk
description:
- Send a message to typetalk using typetalk API ( http://developers.typetalk.in/ )
options:
client_id:
description:
- OAuth2 client ID
required: true
client_secret:
description:
- OAuth2 client secret
required: true
topic:
description:
- topic id to post message
required: true
msg:
description:
- message body
required: true
requirements: [ urllib, urllib2, json ]
author: Takashi Someda <someda@isenshi.com>
'''
EXAMPLES = '''
- typetalk: client_id=12345 client_secret=12345 topic=1 msg="install completed"
'''
try:
import urllib
except ImportError:
urllib = None
try:
import urllib2
except ImportError:
urllib2 = None
try:
import json
except ImportError:
json = None
def do_request(url, params, headers={}):
data = urllib.urlencode(params)
headers = dict(headers, **{
'User-Agent': 'Ansible/typetalk module',
})
return urllib2.urlopen(urllib2.Request(url, data, headers))
def get_access_token(client_id, client_secret):
params = {
'client_id': client_id,
'client_secret': client_secret,
'grant_type': 'client_credentials',
'scope': 'topic.post'
}
res = do_request('https://typetalk.in/oauth2/access_token', params)
return json.load(res)['access_token']
def send_message(client_id, client_secret, topic, msg):
"""
send message to typetalk
"""
try:
access_token = get_access_token(client_id, client_secret)
url = 'https://typetalk.in/api/v1/topics/%d' % topic
headers = {
'Authorization': 'Bearer %s' % access_token,
}
do_request(url, {'message': msg}, headers)
return True, {'access_token': access_token}
except urllib2.HTTPError, e:
return False, e
def main():
module = AnsibleModule(
argument_spec=dict(
client_id=dict(required=True),
client_secret=dict(required=True),
topic=dict(required=True, type='int'),
msg=dict(required=True),
),
supports_check_mode=False
)
if not (urllib and urllib2 and json):
module.fail_json(msg="urllib, urllib2 and json modules are required")
client_id = module.params["client_id"]
client_secret = module.params["client_secret"]
topic = module.params["topic"]
msg = module.params["msg"]
res, error = send_message(client_id, client_secret, topic, msg)
if not res:
module.fail_json(msg='fail to send message with response code %s' % error.code)
module.exit_json(changed=True, topic=topic, msg=msg)
# import module snippets
from ansible.module_utils.basic import *
main()