def parse(self, objdata): user_id_map = {} ################################################################### # TEAM CREATION ################################################################### obj_name = objdata['metadata']['name'] team_members = objdata['metadata']['annotations'].get('sysdigTeamMembers', '').split(',') trecipients = objdata['metadata']['annotations'].get('sysdigAlertEmails', '').split(',') tdashboards = objdata['metadata']['annotations'].get('sysdigDashboards', '').split(',') alertsj = objdata['metadata']['annotations'].get('sysdigAlerts', json.dumps([])) if self._type == 'deployment' or self._type == 'service': ns_name = objdata['metadata']['namespace'] team_name = "%s%s_%s_%s" % (self._team_prefix, self._type, ns_name, obj_name) elif self._type == 'namespace': ns_name = objdata['metadata']['name'] team_name = "%s%s_%s" % (self._team_prefix, self._type, ns_name) else: Logger.log('unrecognized type argument', 'error') return False # # Resolve the user emails. # Add the users that are not part of sysdig cloud yet. # for o in team_members: uname = o.strip() res = self._customer_admin_sdclient.get_user(uname) if res[0] == False: if res[1] == USER_NOT_FOUND_ERR: Logger.log("adding user " + uname) res = self._customer_admin_sdclient.create_user_invite(uname) res = self._customer_admin_sdclient.get_user(uname) Logger.log("User added") if res[0] == False: Logger.log('cannot get user %s: %s' % (uname, res[1]), 'error') continue else: Logger.log('cannot get user %s: %s' % (uname, res[1]), 'error') continue user_id_map[uname] = res[1]['id'] if len(user_id_map) == 0: Logger.log('No users specified for this team. Skipping.', 'error') return False # # Normalize alert recipients # recipients = [] for r in trecipients: recipients.append(r.strip()) # # Normalize the dashboards list # dashboards = [] for d in tdashboards: dashboards.append(d.strip()) # # Parse the alerts json # alerts = [] try: alerts = json.loads(alertsj) except ValueError: Logger.log('Invalid JSON in the "alerts" field', 'error') return False # XXX This is here for testing purposes only # res = self._customer_admin_sdclient.delete_team(team_name) # # Check the existence of the team and create it if it doesn't exist # team_exists = True res = self._customer_admin_sdclient.get_team(team_name) if res[0] == False: if res[1] == TEAM_NOT_EXISTING_ERR: team_exists = False new_memberships = dict(map(lambda u: (u, 'ROLE_TEAM_EDIT'), user_id_map.keys())) else: teaminfo = res[1] teamid = teaminfo['id'] old_memberships = dict(map(lambda m: (m['userId'], m['role']), teaminfo['userRoles'])) new_memberships = dict(map(lambda u: (u, 'ROLE_TEAM_EDIT') if user_id_map[u] not in old_memberships else (u, old_memberships[user_id_map[u]]), user_id_map.keys())) if team_exists: # Team exists. Detect if there are users to add and edit the team users list. newusers = [] team_uids = set(old_memberships.keys()) if team_uids != set(user_id_map.values()): Logger.log("Detected modified %s %s, editing team %s" % (self._type, obj_name, team_name)) newusers.append([u for u in user_id_map.keys() if user_id_map[u] not in team_uids]) res = self._customer_admin_sdclient.edit_team(team_name, memberships=new_memberships) if res[0] == False: Logger.log('Team editing failed: ' + res[1], 'error') return False else: Logger.log("Detected new %s %s, adding team %s" % (self._type, obj_name, team_name)) # Team doesn't exist. Try to create it. if self._type == 'deployment': flt = 'kubernetes.namespace.name = "%s" and kubernetes.deployment.name = "%s"' % (ns_name, obj_name) elif self._type == 'service': flt = 'kubernetes.namespace.name = "%s" and kubernetes.service.name = "%s"' % (ns_name, obj_name) elif self._type == 'namespace': flt = 'kubernetes.namespace.name = "%s"' % ns_name desc = 'automatically generated team based on deployment annotations' res = self._customer_admin_sdclient.create_team(team_name, filter=flt, description=desc, show='container', memberships=new_memberships) if res[0] == False: Logger.log('Team creation failed: ' + res[1], 'error') return False teamid = res[1]['team']['id'] newusers = user_id_map.keys() ################################################################### # TEAM CONFIGURATION ################################################################### # # If we have alerts, create a notification channel and point the # alerts at it. # if alerts: Logger.log('adding notification recipients') # # These steps can be done as the admin user since notification # channels have global scope and alerts has team scope, and admin # users are members of all teams. # res = self._customer_admin_sdclient.get_user_api_token(self._customer_id, team_name) if res[0] == False: Logger.log('Can\'t fetch token for user ' + user, 'error') return False else: utoken_t = res[1] teamclient = SdcClient(utoken_t, self._sdc_url) # # Add the email notification channel. This will silently fail # if it has already been created. # res = teamclient.create_email_notification_channel(team_name, recipients) if not res[0]: if res[1][:20] != EXISTING_CHANNEL_ERR: Logger.log('Error setting email recipient: ' + res[1], 'error') return False # # Get the notification channel ID to use for the alerts. # notify_channels = [{'type': 'EMAIL', 'name': team_name}] res = teamclient.get_notification_ids(notify_channels) if not res[0]: Logger.log("cannot create the email notification channel: " + res[1], 'error') return False notification_channel_ids = res[1] # # Make sure the members of the email notification channel are current. # Since we searched for the channel by name, there should only be one. But # since get_notification_ids() returns a list, treat it as such. # for channel_id in notification_channel_ids: res = teamclient.get_notification_channel(channel_id) if not res[0]: Logger.log("cannot find the email notification channel: " + res[1], 'error') return False c = res[1] current_recip = c['options']['emailRecipients'] if set(current_recip) == set(recipients): Logger.log('email recipients have not changed since last update', 'info') else: Logger.log('email recipients have changed - updating', 'info') c['options']['emailRecipients'] = copy.deepcopy(recipients) teamclient.update_notification_channel(c) # # Add the Alerts # res = teamclient.get_alerts() if not res[0]: Logger.log("cannot get user alerts: " + res[1], 'error') return False cur_alerts = res[1]['alerts'] for a in alerts: aname = a.get('name', '') # # Check if this alert already exists # skip = False for ca in cur_alerts: if ca['name'] == aname and 'annotations' in ca: skip = True break if skip: # # Alert already exists, skip the creation # continue Logger.log('adding alert %s' % aname) res = teamclient.create_alert(aname, # Alert name. a.get('description', ''), # Alert description. a.get('severity', 6), # Syslog-encoded severity. 6 means 'info'. a.get('timespan', 60000000), # The alert will fire if the condition is met for at least 60 seconds. a.get('condition', ''), # The condition. a.get('segmentBy', []), # Segmentation. We want to check this metric for every process on every machine. a.get('segmentCondition', 'ANY'), # in case there is more than one tomcat process, this alert will fire when a single one of them crosses the 80% threshold. a.get('filter', ''), # Filter. We want to receive a notification only if the name of the process meeting the condition is 'tomcat'. notification_channel_ids, a.get('enabled', True), {'engineTeam': team_name + aname}) if not res[0]: Logger.log('Error creating alert: ' + res[1], 'error') # # Go through the list of new users and set them up for this team # for user in user_id_map.keys(): # # First of all, we need to impersonate the users in this team # so that we can configure their workplace. This is # currently a little bit tricky because it involves: # - finding the user token using the admin API # - logging in with the new user token # Logger.log('impersonating user ' + user) res = self._customer_admin_sdclient.get_user_api_token(user, team_name) if res[0] == False: Logger.log('Can\'t fetch token for user ' + user, 'error') return False else: utoken_t = res[1] teamclient = SdcClient(utoken_t, self._sdc_url) Logger.log('waiting for activation of user ' + user) while True: res = teamclient.get_user_token() if res[0] == True: break else: time.sleep(3) # # Now that we are in the right user context, we can start to apply the # configurations. First of all we set a default kube-friendly grouping hierarchy. # We do this only is the user is new to the group, because we don't want to # pollute the grouping of existing users. # if user in newusers: Logger.log('setting grouping') if self._type == 'service': res = teamclient.set_explore_grouping_hierarchy(['kubernetes.namespace.name', 'kubernetes.service.name', 'kubernetes.pod.name', 'container.id']) else: res = teamclient.set_explore_grouping_hierarchy(['kubernetes.namespace.name', 'kubernetes.deployment.name', 'kubernetes.pod.name', 'container.id']) if res[0] == False: Logger.log('Failed setting team grouping: ' + res[1], 'error') return False # # Add the dashboards # res = teamclient.get_dashboards() if not res[0]: Logger.log('Error getting the dasboards list: ' + res[1], 'error') break existing_dasboards = res[1]['dashboards'] for d in dashboards: skip = False for ex in existing_dasboards: if ex['name'] == d: if ex['isShared'] and 'annotations' in ex and ex['annotations'].get('engineTeam') == team_name + d: # dashboard already exists. Skip adding it skip = True break if skip: continue Logger.log('adding dasboard ' + d) res = teamclient.create_dashboard_from_view(d, d, None, True, {'engineTeam': team_name + d, 'ownerUser': user}) if not res[0]: Logger.log('Error creating dasboard: ' + res[1], 'error')
if len(args) != 1: usage() sdc_token = args[0] # # Instantiate the SDC client # sdclient = SdcClient(sdc_token) # # Create an email notification channel # ok, res = sdclient.create_email_notification_channel( channel_name, ['*****@*****.**', '*****@*****.**', '*****@*****.**']) if not ok: print(res) sys.exit(1) # # The notification channel will contain the id, that can be used when creating alerts # channel = res['notificationChannel'] print(channel) # # Notification channels can also be programmatically deleted # ok, res = sdclient.delete_notification_channel(channel)
if len(sys.argv) != 2: print 'usage: %s <sysdig-token>' % sys.argv[0] print 'You can find your token at https://app.sysdigcloud.com/#/settings/user' sys.exit(1) sdc_token = sys.argv[1] # # Instantiate the SDC client # sdclient = SdcClient(sdc_token) # # Create an email notification channel # res = sdclient.create_email_notification_channel('Api Channel', ['*****@*****.**', '*****@*****.**', '*****@*****.**']) if not res[0]: print res[1] sys.exit(1) # # The notification channel will contain the id, that can be used when creating alerts # channel = res[1]['notificationChannel'] print channel # # Notification channels can also be programmatically deleted # res = sdclient.delete_notification_channel(channel) if not res[0]: