utils.slack
slack
Common code useful for sending slack messages.
Example Usage: from utils import slack from utilss.slack import send
1#!/usr/bin/env python3 2""" 3slack 4 5Common code useful for sending slack messages. 6 7Example Usage: 8 from utils import slack 9 from utilss.slack import send 10""" 11 12import json 13import logging 14import os 15from urllib.request import Request, urlopen 16from urllib.error import URLError, HTTPError 17 18SLACK_WEBHOOK_URL = os.environ.get('SLACK_WEBHOOK_URL', 'None') 19 20GO_SERVER_URL = os.environ.get('GO_SERVER_URL', 'None') 21GO_PIPELINE_NAME = os.environ.get('GO_PIPELINE_NAME', 'None') 22GO_PIPELINE_GROUP_NAME = os.environ.get('GO_PIPELINE_GROUP_NAME', 'None') 23GO_PIPELINE_LABEL = os.environ.get('GO_PIPELINE_LABEL', 'None') 24GO_PIPELINE_COUNTER = os.environ.get('GO_PIPELINE_COUNTER', 'None') 25GO_TRIGGER_USER = os.environ.get('GO_TRIGGER_USER', 'None') 26GO_STAGE_NAME = os.environ.get('GO_STAGE_NAME', 'None') 27GO_STAGE_COUNTER = os.environ.get('GO_STAGE_COUNTER', 'None') 28GO_JOB_NAME = os.environ.get('GO_JOB_NAME', 'None') 29GO_ENVIRONMENT_NAME = os.environ.get('GO_ENVIRONMENT_NAME', 'None') 30 31# 32# Need to iterate on this. Name is not always MYGITY 33# 34GO_REVISION_MYGITY = os.environ.get('GO_REVISION_MYGITY', 'None') 35GO_MATERIAL_BRANCH_MYGITY = os.environ.get('GO_MATERIAL_BRANCH_MYGITY', 'None') 36 37# 38# For testing 39# 40# export SLACK_WEBHOOK_URL=https://fake123454321.com/ 41# export GO_SERVER_URL=https://gocd.cloudops.rekor.io/go 42# export GO_ENVIRONMENT_NAME=build-prod 43# export GO_PIPELINE_GROUP_NAME=build-prod 44# export GO_TO_REVISION_MYGITY=40c9a6ea1716e1a3f12db4314644f5f1829f995d 45# export GO_FROM_REVISION_MYGITY=40c9a6ea1716e1a3f12db4314644f5f1829f995d 46# export GO_TRIGGER_USER=changes 47# export GO_REVISION_MYGITY=40c9a6ea1716e1a3f12db4314644f5f1829f995d 48# export GO_PIPELINE_NAME=cdk 49# export GO_MATERIAL_BRANCH_MYGITY=master 50 51# export GO_MATERIAL_URL_MYGITY=git@bitbucket.org:openalpr/rekor-ops-gocd.git 52# export GO_JAVA_HOME=/gocd-jre 53# export GO_PIPELINE_LABEL=37 54# export GO_EA_MODE=prod 55# export GO_STAGE_NAME=buildStg 56# export GO_STAGE_COUNTER=1 57# export GO_PIPELINE_COUNTER=37 58# export GO_JOB_NAME=buildJob 59 60# ${GO_SERVER_URL}/tab/build/detail/${GO_PIPELINE_NAME}/${GO_PIPELINE_LABEL}/${GO_STAGE_NAME}/${GO_STAGE_COUNTER}/${GO_JOB_NAME}#tab-console 61 62 63logger = logging.getLogger() 64logger.setLevel(logging.INFO) 65 66message_parsed = False 67 68pretty_alarm_name = "" 69alarm_name = "" 70old_state = "" 71new_state = "" 72reason = "" 73alarm_description = "" 74 75channel = "gocd" 76msg = None 77 78 79def parser(msg, basic_msg=None, json_block=None) -> dict: 80 """ 81 parser takes a message and creates a formatted / prettified slack message 82 83 msg: String with message 84 basic_msg: True/False, if True, will craft a small/basic message 85 json_block: True/Falswe, if True, will use whatever you have in msg as the block formatting 86 """ 87 88 if json_block: 89 message = json.loads(msg) 90 else: 91 if basic_msg: 92 message = { 93 "text": msg, 94 "channel": channel, 95 "username": "gocd-slack-bot", 96 "icon_emoji": ":gocd:" 97 } 98 else: 99 message = { 100 "username": "gocd-slack-bot", 101 "icon_emoji": ":gocd:", 102 "channel": channel, 103 "blocks": [ 104 { 105 "type": "section", 106 "text": { 107 "type": "mrkdwn", 108 "text": "*"+msg+"*" 109 } 110 }, 111 { 112 "type": "section", 113 "fields": [ 114 { 115 "type": "mrkdwn", 116 "text": "*Environment*\n"+GO_ENVIRONMENT_NAME 117 }, 118 { 119 "type": "mrkdwn", 120 "text": "*Pipeline Group*\n"+GO_PIPELINE_GROUP_NAME 121 }, 122 { 123 "type": "mrkdwn", 124 "text": "*Pipeline*\n"+GO_PIPELINE_NAME 125 }, 126 { 127 "type": "mrkdwn", 128 "text": "*Pipeline Build #*\n"+GO_PIPELINE_LABEL 129 }, 130 { 131 "type": "mrkdwn", 132 "text": "*Stage Name*\n"+GO_STAGE_NAME 133 }, 134 { 135 "type": "mrkdwn", 136 "text": "*Stage Counter*\n"+GO_STAGE_COUNTER 137 }, 138 { 139 "type": "mrkdwn", 140 "text": "*Job Name*\n"+GO_JOB_NAME 141 }, 142 { 143 "type": "mrkdwn", 144 "text": "*Trigger User*\n"+GO_TRIGGER_USER 145 }, 146 { 147 "type": "mrkdwn", 148 "text": "*Material Branch*\n"+GO_MATERIAL_BRANCH_MYGITY 149 }, 150 { 151 "type": "mrkdwn", 152 "text": "*Material Revision*\n"+GO_REVISION_MYGITY 153 } 154 ] 155 }, 156 { 157 "type": "section", 158 "text": { 159 "type": "mrkdwn", 160 "text": "*Console Logs:*\n<"+GO_SERVER_URL+"/pipelines/"+GO_PIPELINE_NAME+"/"+GO_PIPELINE_LABEL+"/"+GO_STAGE_NAME+"/"+GO_STAGE_COUNTER+"|GoCD Logs>" 161 } 162 } 163 ] 164 } 165 return message 166 167 168def send(message, basic_msg=None, json_block=None) -> bool: 169 """ 170 Slack.send() 171 172 Sends a formatted message. If message is a String, will use Slack.parser() before sending. 173 174 message: String or Dict (assumes it's processed through Slack.parser()) 175 basic_msg: True/False, if True, will craft a small/basic message when calling Slack.parser() 176 json_block: True/Falswe, if True, will use whatever you have in msg as the block formatting when calling Slack.parser() 177 """ 178 if type(message) == str: 179 message = parser(msg=message, basic_msg=basic_msg, json_block=json_block) 180 181 req = Request(SLACK_WEBHOOK_URL, json.dumps(message).encode('utf-8')) 182 try: 183 response = urlopen(req) 184 body = response.read() 185 print(body) 186 logger.info("Message posted") 187 except HTTPError as e: 188 logger.error("Request failed: %d %s", e.code, e.reason) 189 return False 190 except URLError as e: 191 logger.error("Server connection failed: %s", e.reason) 192 return False 193 194 return True
80def parser(msg, basic_msg=None, json_block=None) -> dict: 81 """ 82 parser takes a message and creates a formatted / prettified slack message 83 84 msg: String with message 85 basic_msg: True/False, if True, will craft a small/basic message 86 json_block: True/Falswe, if True, will use whatever you have in msg as the block formatting 87 """ 88 89 if json_block: 90 message = json.loads(msg) 91 else: 92 if basic_msg: 93 message = { 94 "text": msg, 95 "channel": channel, 96 "username": "gocd-slack-bot", 97 "icon_emoji": ":gocd:" 98 } 99 else: 100 message = { 101 "username": "gocd-slack-bot", 102 "icon_emoji": ":gocd:", 103 "channel": channel, 104 "blocks": [ 105 { 106 "type": "section", 107 "text": { 108 "type": "mrkdwn", 109 "text": "*"+msg+"*" 110 } 111 }, 112 { 113 "type": "section", 114 "fields": [ 115 { 116 "type": "mrkdwn", 117 "text": "*Environment*\n"+GO_ENVIRONMENT_NAME 118 }, 119 { 120 "type": "mrkdwn", 121 "text": "*Pipeline Group*\n"+GO_PIPELINE_GROUP_NAME 122 }, 123 { 124 "type": "mrkdwn", 125 "text": "*Pipeline*\n"+GO_PIPELINE_NAME 126 }, 127 { 128 "type": "mrkdwn", 129 "text": "*Pipeline Build #*\n"+GO_PIPELINE_LABEL 130 }, 131 { 132 "type": "mrkdwn", 133 "text": "*Stage Name*\n"+GO_STAGE_NAME 134 }, 135 { 136 "type": "mrkdwn", 137 "text": "*Stage Counter*\n"+GO_STAGE_COUNTER 138 }, 139 { 140 "type": "mrkdwn", 141 "text": "*Job Name*\n"+GO_JOB_NAME 142 }, 143 { 144 "type": "mrkdwn", 145 "text": "*Trigger User*\n"+GO_TRIGGER_USER 146 }, 147 { 148 "type": "mrkdwn", 149 "text": "*Material Branch*\n"+GO_MATERIAL_BRANCH_MYGITY 150 }, 151 { 152 "type": "mrkdwn", 153 "text": "*Material Revision*\n"+GO_REVISION_MYGITY 154 } 155 ] 156 }, 157 { 158 "type": "section", 159 "text": { 160 "type": "mrkdwn", 161 "text": "*Console Logs:*\n<"+GO_SERVER_URL+"/pipelines/"+GO_PIPELINE_NAME+"/"+GO_PIPELINE_LABEL+"/"+GO_STAGE_NAME+"/"+GO_STAGE_COUNTER+"|GoCD Logs>" 162 } 163 } 164 ] 165 } 166 return message
parser takes a message and creates a formatted / prettified slack message
msg: String with message basic_msg: True/False, if True, will craft a small/basic message json_block: True/Falswe, if True, will use whatever you have in msg as the block formatting
169def send(message, basic_msg=None, json_block=None) -> bool: 170 """ 171 Slack.send() 172 173 Sends a formatted message. If message is a String, will use Slack.parser() before sending. 174 175 message: String or Dict (assumes it's processed through Slack.parser()) 176 basic_msg: True/False, if True, will craft a small/basic message when calling Slack.parser() 177 json_block: True/Falswe, if True, will use whatever you have in msg as the block formatting when calling Slack.parser() 178 """ 179 if type(message) == str: 180 message = parser(msg=message, basic_msg=basic_msg, json_block=json_block) 181 182 req = Request(SLACK_WEBHOOK_URL, json.dumps(message).encode('utf-8')) 183 try: 184 response = urlopen(req) 185 body = response.read() 186 print(body) 187 logger.info("Message posted") 188 except HTTPError as e: 189 logger.error("Request failed: %d %s", e.code, e.reason) 190 return False 191 except URLError as e: 192 logger.error("Server connection failed: %s", e.reason) 193 return False 194 195 return True
Slack.send()
Sends a formatted message. If message is a String, will use Slack.parser() before sending.
message: String or Dict (assumes it's processed through Slack.parser()) basic_msg: True/False, if True, will craft a small/basic message when calling Slack.parser() json_block: True/Falswe, if True, will use whatever you have in msg as the block formatting when calling Slack.parser()