"Fossies" - the Fresh Open Source Software Archive

Member "salt-3002.2/salt/modules/slack_notify.py" (18 Nov 2020, 7967 Bytes) of package /linux/misc/salt-3002.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. For more information about "slack_notify.py" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3002.1_vs_3002.2.

    1 """
    2 Module for sending messages to Slack
    3 
    4 .. versionadded:: 2015.5.0
    5 
    6 :configuration: This module can be used by either passing an api key and version
    7     directly or by specifying both in a configuration profile in the salt
    8     master/minion config.
    9 
   10     For example:
   11 
   12     .. code-block:: yaml
   13 
   14         slack:
   15           api_key: peWcBiMOS9HrZG15peWcBiMOS9HrZG15
   16 """
   17 
   18 
   19 import logging
   20 
   21 import salt.ext.six.moves.http_client
   22 import salt.utils.json
   23 import salt.utils.slack
   24 from salt.exceptions import SaltInvocationError
   25 from salt.ext.six.moves import range
   26 
   27 # pylint: disable=import-error,no-name-in-module,redefined-builtin
   28 from salt.ext.six.moves.urllib.parse import urlencode as _urlencode
   29 from salt.ext.six.moves.urllib.parse import urljoin as _urljoin
   30 
   31 # pylint: enable=import-error,no-name-in-module
   32 
   33 log = logging.getLogger(__name__)
   34 
   35 __virtualname__ = "slack"
   36 
   37 
   38 def __virtual__():
   39     """
   40     Return virtual name of the module.
   41 
   42     :return: The virtual name of the module.
   43     """
   44     return __virtualname__
   45 
   46 
   47 def _get_api_key():
   48     api_key = __salt__["config.get"]("slack.api_key") or __salt__["config.get"](
   49         "slack:api_key"
   50     )
   51 
   52     if not api_key:
   53         raise SaltInvocationError("No Slack API key found.")
   54 
   55     return api_key
   56 
   57 
   58 def _get_hook_id():
   59     url = __salt__["config.get"]("slack.hook") or __salt__["config.get"]("slack:hook")
   60     if not url:
   61         raise SaltInvocationError("No Slack WebHook url found")
   62 
   63     return url
   64 
   65 
   66 def list_rooms(api_key=None):
   67     """
   68     List all Slack rooms.
   69 
   70     :param api_key: The Slack admin api key.
   71     :return: The room list.
   72 
   73     CLI Example:
   74 
   75     .. code-block:: bash
   76 
   77         salt '*' slack.list_rooms
   78 
   79         salt '*' slack.list_rooms api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15
   80     """
   81     if not api_key:
   82         api_key = _get_api_key()
   83     return salt.utils.slack.query(function="rooms", api_key=api_key, opts=__opts__)
   84 
   85 
   86 def list_users(api_key=None):
   87     """
   88     List all Slack users.
   89 
   90     :param api_key: The Slack admin api key.
   91     :return: The user list.
   92 
   93     CLI Example:
   94 
   95     .. code-block:: bash
   96 
   97         salt '*' slack.list_users
   98 
   99         salt '*' slack.list_users api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15
  100     """
  101     if not api_key:
  102         api_key = _get_api_key()
  103     return salt.utils.slack.query(function="users", api_key=api_key, opts=__opts__)
  104 
  105 
  106 def find_room(name, api_key=None):
  107     """
  108     Find a room by name and return it.
  109 
  110     :param name:    The room name.
  111     :param api_key: The Slack admin api key.
  112     :return:        The room object.
  113 
  114     CLI Example:
  115 
  116     .. code-block:: bash
  117 
  118         salt '*' slack.find_room name="random"
  119 
  120         salt '*' slack.find_room name="random" api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15
  121     """
  122     if not api_key:
  123         api_key = _get_api_key()
  124 
  125     # search results don't include the name of the
  126     # channel with a hash, if the passed channel name
  127     # has a hash we remove it.
  128     if name.startswith("#"):
  129         name = name[1:]
  130     ret = list_rooms(api_key)
  131     if ret["res"]:
  132         rooms = ret["message"]
  133         if rooms:
  134             for room in range(0, len(rooms)):
  135                 if rooms[room]["name"] == name:
  136                     return rooms[room]
  137     return False
  138 
  139 
  140 def find_user(name, api_key=None):
  141     """
  142     Find a user by name and return it.
  143 
  144     :param name:        The user name.
  145     :param api_key:     The Slack admin api key.
  146     :return:            The user object.
  147 
  148     CLI Example:
  149 
  150     .. code-block:: bash
  151 
  152         salt '*' slack.find_user name="ThomasHatch"
  153 
  154         salt '*' slack.find_user name="ThomasHatch" api_key=peWcBiMOS9HrZG15peWcBiMOS9HrZG15
  155     """
  156     if not api_key:
  157         api_key = _get_api_key()
  158 
  159     ret = list_users(api_key)
  160     if ret["res"]:
  161         users = ret["message"]
  162         if users:
  163             for user in range(0, len(users)):
  164                 if users[user]["name"] == name:
  165                     return users[user]
  166     return False
  167 
  168 
  169 def post_message(channel, message, from_name, api_key=None, icon=None):
  170     """
  171     Send a message to a Slack channel.
  172 
  173     :param channel:     The channel name, either will work.
  174     :param message:     The message to send to the Slack channel.
  175     :param from_name:   Specify who the message is from.
  176     :param api_key:     The Slack api key, if not specified in the configuration.
  177     :param icon:        URL to an image to use as the icon for this message
  178     :return:            Boolean if message was sent successfully.
  179 
  180     CLI Example:
  181 
  182     .. code-block:: bash
  183 
  184         salt '*' slack.post_message channel="Development Room" message="Build is done" from_name="Build Server"
  185 
  186     """
  187     if not api_key:
  188         api_key = _get_api_key()
  189 
  190     if not channel:
  191         log.error("channel is a required option.")
  192 
  193     # channel must start with a hash or an @ (direct-message channels)
  194     if not channel.startswith("#") and not channel.startswith("@"):
  195         log.warning(
  196             "Channel name must start with a hash or @. "
  197             'Prepending a hash and using "#%s" as '
  198             "channel name instead of %s",
  199             channel,
  200             channel,
  201         )
  202         channel = "#{}".format(channel)
  203 
  204     if not from_name:
  205         log.error("from_name is a required option.")
  206 
  207     if not message:
  208         log.error("message is a required option.")
  209 
  210     if not from_name:
  211         log.error("from_name is a required option.")
  212 
  213     parameters = {"channel": channel, "username": from_name, "text": message}
  214 
  215     if icon is not None:
  216         parameters["icon_url"] = icon
  217 
  218     # Slack wants the body on POST to be urlencoded.
  219     result = salt.utils.slack.query(
  220         function="message",
  221         api_key=api_key,
  222         method="POST",
  223         header_dict={"Content-Type": "application/x-www-form-urlencoded"},
  224         data=_urlencode(parameters),
  225         opts=__opts__,
  226     )
  227 
  228     if result["res"]:
  229         return True
  230     else:
  231         return result
  232 
  233 
  234 def call_hook(
  235     message,
  236     attachment=None,
  237     color="good",
  238     short=False,
  239     identifier=None,
  240     channel=None,
  241     username=None,
  242     icon_emoji=None,
  243 ):
  244     """
  245     Send message to Slack incoming webhook.
  246 
  247     :param message:     The topic of message.
  248     :param attachment:  The message to send to the Slack WebHook.
  249     :param color:       The color of border of left side
  250     :param short:       An optional flag indicating whether the value is short
  251                         enough to be displayed side-by-side with other values.
  252     :param identifier:  The identifier of WebHook.
  253     :param channel:     The channel to use instead of the WebHook default.
  254     :param username:    Username to use instead of WebHook default.
  255     :param icon_emoji:  Icon to use instead of WebHook default.
  256     :return:            Boolean if message was sent successfully.
  257 
  258     CLI Example:
  259 
  260     .. code-block:: bash
  261 
  262         salt '*' slack.call_hook message='Hello, from SaltStack'
  263 
  264     """
  265     base_url = "https://hooks.slack.com/services/"
  266     if not identifier:
  267         identifier = _get_hook_id()
  268 
  269     url = _urljoin(base_url, identifier)
  270 
  271     if not message:
  272         log.error("message is required option")
  273 
  274     if attachment:
  275         payload = {
  276             "attachments": [
  277                 {
  278                     "fallback": message,
  279                     "color": color,
  280                     "pretext": message,
  281                     "fields": [{"value": attachment, "short": short}],
  282                 }
  283             ]
  284         }
  285     else:
  286         payload = {
  287             "text": message,
  288         }
  289 
  290     if channel:
  291         payload["channel"] = channel
  292 
  293     if username:
  294         payload["username"] = username
  295 
  296     if icon_emoji:
  297         payload["icon_emoji"] = icon_emoji
  298 
  299     data = _urlencode({"payload": salt.utils.json.dumps(payload)})
  300     result = salt.utils.http.query(url, method="POST", data=data, status=True)
  301 
  302     if result["status"] <= 201:
  303         return True
  304     else:
  305         return {"res": False, "message": result.get("body", result["status"])}