#JLL import json import requests import os import urllib3 import re ################################## ### Mission Control variables ################################## Cookie='' CSRF='' ################################## ### Environment Dynatrace ################################## Tenant="https://"+str(os.getenv('MyTenant')) Token=os.getenv('MyToken') ################################## ## API ################################## APIdashboard='/api/config/v1/dashboards' APIslo='/api/v2/slo' ################################## ## SLO ################################## SLO_source={'Optimization - CPU Usage':'d432ca69-7cb0-3dcf-a176-6225a6d5ff4c','Optimization - Disk Usage':'f73c599d-87ba-38e8-98ff-1dae02879969','Optimization - Memory Usage':'ef700817-f0c2-33f8-916d-8dfeb0f1ce3a','Smarter - Application Performance':'eb99760c-52f6-303b-94eb-4a67d5bf3b32','Smarter - Browser Monitor Availability':'2d23383a-8124-3799-916a-548d307ffbcd','Smarter - Database Performance':'91f1aaee-8e54-37cd-9771-cacd0bc977dc','Smarter - Database Success Rate':'c3b96795-e1db-3e55-806b-c4dbba302094','Smarter - Http Monitor Availability':'7dffcc5b-a736-32da-bf7e-a981205fc9fb','Smarter - Service Availability':'a0a88884-5d41-3425-8f02-37436794da80','Smarter - Service Performance':'811465a3-5b0b-3096-9279-02a3d499ba25'} SLO_target={'Optimization - CPU Usage':'','Optimization - Disk Usage':'','Optimization - Memory Usage':'','Smarter - Application Performance':'','Smarter - Browser Monitor Availability':'','Smarter - Database Performance':'','Smarter - Database Success Rate':'','Smarter - Http Monitor Availability':'','Smarter - Service Availability':'','Smarter - Service Performance':''} ################################## ## Dashboard ################################## Dashboard_source={'🏠 Dynatrace: simply smarter':'bbbbbbbb-a003-a017-0000-000000000133','✔ SLO Simply Smarter':'bbbbbbbb-a003-a017-0008-000000000133','✔ SLO Resource Optimization':'bbbbbbbb-a003-a017-0009-000000000133','✔ User experience (web applications)':'bbbbbbbb-a003-a017-0002-000000000133','✔ User experience (mobile apps)':'bbbbbbbb-a003-a017-0003-000000000133','✔ Synthetic (browser)':'bbbbbbbb-a003-a017-0004-000000000133','✔ Services':'bbbbbbbb-a003-a017-0001-000000000133','✔ Database services':'bbbbbbbb-a003-a017-0005-000000000133','✔ Synthetic (service)':'bbbbbbbb-a003-a017-0006-000000000133','✔ Infrastructure':'bbbbbbbb-a003-a017-0007-000000000133'} Dashboard_target={'🏠 Dynatrace: simply smarter':'','✔ SLO Simply Smarter':'','✔ SLO Resource Optimization':'','✔ User experience (web applications)':'','✔ User experience (mobile apps)':'','✔ Synthetic (browser)':'','✔ Services':'','✔ Database services':'','✔ Synthetic (service)':'','✔ Infrastructure':''} Dashboard_mapping_name={'🏠 Dynatrace: simply smarter':'Dynatrace_simply smarter.json','✔ SLO Simply Smarter':'SLO Simply Smarter.json','✔ SLO Resource Optimization':'SLO Resource Optimization.json','✔ User experience (web applications)':'User experience (web applications).json','✔ User experience (mobile apps)':'User experience (mobile apps).json','✔ Synthetic (browser)':'Synthetic (browser).json','✔ Services':'Services.json','✔ Database services':'Database services.json','✔ Synthetic (service)':'Synthetic (service).json','✔ Infrastructure':'Infrastructure.json'} ################################## ## Others ################################## deploy=os.getenv('Deploy') if deploy == None: deploy = 'ALL' owner=os.getenv('Owner') if owner == None: owner = 'smarter' owner_old='' #disable warning urllib3.disable_warnings() # variable changed if script is run on Windows or Linux. "\\" for Windows, "/" for Linux if Cookie == '': head = { 'Accept': 'application/json', 'Content-Type': 'application/json; charset=UTF-8', 'Authorization': 'Api-Token {}'.format(Token) } else: head = { 'Accept': 'application/json', 'Content-Type': 'application/json; charset=UTF-8', 'Authorization': 'Api-Token {}'.format(Token), 'X-CSRFToken': CSRF, 'Cookie': Cookie } ################################## ## Generic Dynatrace API ################################## # generic function GET to call API with a given uri def queryDynatraceAPI(uri): jsonContent = None #print(head) response = requests.get(uri,headers=head,verify=False) #print(response) # For successful API call, response code will be 200 (OK) if(response.ok): if(len(response.text) > 0): jsonContent = json.loads(response.text) else: jsonContent = json.loads(response.text) print(jsonContent) errorMessage = "" if(jsonContent["error"]): errorMessage = jsonContent["error"]["message"] print("Dynatrace API returned an error: " + errorMessage) jsonContent = None #raise Exception("Error", "Dynatrace API returned an error: " + errorMessage) return(jsonContent) #generic function POST to call API with a given uri def postDynatraceAPI(uri, payload): jsonContent = None response = requests.post(uri,headers=head,verify=False, json=payload) # For successful API call, response code will be 200 (OK) if(response.ok): if(len(response.text) > 0): jsonContent = json.loads(response.text) jsonContent="success" else: jsonContent = json.loads(response.text) print(jsonContent) errorMessage = "" if(jsonContent["error"]): errorMessage = jsonContent["error"]["message"] print("Dynatrace API returned an error: " + errorMessage) jsonContent = None #raise Exception("Error", "Dynatrace API returned an error: " + errorMessage) return(jsonContent) #generic function PUT to call API with a given uri def putDynatraceAPI(uri, payload): jsonContent = None #print(uri,head,payload) response = requests.put(uri,headers=head,verify=False, json=payload) # For successful API call, response code will be 200 (OK) if(response.ok): jsonContent="success" else: jsonContent = json.loads(response.text) #print(jsonContent) errorMessage = "" if (jsonContent["error"]): errorMessage = jsonContent["error"]["message"] #print("Dynatrace API returned an error: " + errorMessage) jsonContent = None #raise Exception("Error", "Dynatrace API returned an error: " + errorMessage) return(jsonContent) ################################## ## Get SLO Target ################################## def getSLO(TENANT, TOKEN): for slo_filter in ['smarter', 'optimization']: uri=TENANT+APIslo+'?pageSize=100&sloSelector=text("'+slo_filter+'")&sort=name&timeFrame=CURRENT&demo=false&evaluate=false&enabledSlos=true&showGlobalSlos=true' #print(uri) datastore = queryDynatraceAPI(uri) #print(datastore) slos = datastore['slo'] for slo in slos : if slo['name'] in SLO_target: if SLO_target[slo['name']] == '': #print(slo['name']) SLO_target[slo['name']]=slo['id'] return() def getDashboard(TENANT, TOKEN): global owner uri=TENANT+APIdashboard+'?tags=smarter' #print(uri+'&Api-Token='+Token) datastore = queryDynatraceAPI(uri) #print(datastore) dashboards = datastore['dashboards'] for dashboard in dashboards : if dashboard['name'] in Dashboard_target: if Dashboard_target[dashboard['name']] == '': #print(dashboard['name']) Dashboard_target[dashboard['name']]=dashboard['id'] owner_old=dashboard['owner'] if owner == '' : owner == owner_old return() def mappSloDashboard(TENANT, TOKEN): print('\nmapping slo') uri=TENANT+APIdashboard+'?tags=smarter' #print(uri) datastore = queryDynatraceAPI(uri) #print(datastore) dashboards = datastore['dashboards'] deploy_dash=False for dashboard in dashboards : if dashboard['name'] in ['✔ SLO Simply Smarter', '✔ SLO Resource Optimization'] : uri=TENANT+APIdashboard+'/'+dashboard['id'] datastore = queryDynatraceAPI(uri) #print(datastore) data=json.dumps(datastore) for i in SLO_source: if SLO_target[i] != '': data=re.sub(SLO_source[i], SLO_target[i], data) print(' mapping slo for ', dashboard['name'],dashboard['id']) putDynatraceAPI(uri,json.loads(data)) deploy_dash=True if not deploy_dash: print(' no dashbaords, import Dynatrace: Simply Smarter or run this script with Deploy=ALL') return() def updateSLO(TENANT, TOKEN): print('\nupdate slo') for slo in SLO_target: url='https://raw.githubusercontent.com/dynatrace-ace-services/slo-simply-smarter/main/project_monaco/smarter/slo/'+slo.replace(' ','')+'.json' req = requests.get(url) payload=req.json() payload['name']=slo payload['id']=SLO_target[slo] print(' update', slo, SLO_target[slo]) uri=TENANT+APIslo+'/'+SLO_target[slo] putDynatraceAPI(uri, payload) return() def generateSLO(TENANT, TOKEN): print('\ndeploy slo') for slo in SLO_target: if SLO_target[slo] == '': url='https://raw.githubusercontent.com/dynatrace-ace-services/slo-simply-smarter/main/project_monaco/smarter/slo/'+slo.replace(' ','')+'.json' req = requests.get(url) payload=req.json() payload['name']=slo print(' deploy', slo, SLO_target[slo]) uri=TENANT+APIslo result=postDynatraceAPI(uri, payload) return() def generateDashboard(TENANT, TOKEN): print('\ndeploy dashboards') global owner if owner == '' : owner = 'smarter' for dashboard in Dashboard_target: if Dashboard_target[dashboard] == '': url='https://raw.githubusercontent.com/JLLormeau/dynatrace_template_fr/master/'+Dashboard_mapping_name[dashboard] req = requests.get(url) payload=req.json() payload['dashboardMetadata']['owner']=owner del payload['id'] print(' deploy', dashboard, Dashboard_target[dashboard]) uri=TENANT+APIdashboard result=postDynatraceAPI(uri, payload) else: url='https://raw.githubusercontent.com/JLLormeau/dynatrace_template_fr/master/'+Dashboard_mapping_name[dashboard] req = requests.get(url) payload=req.json() payload['dashboardMetadata']['owner']=owner payload['id']=Dashboard_target[dashboard] print(' deploy', dashboard, Dashboard_target[dashboard]) uri=TENANT+APIdashboard+'/'+Dashboard_target[dashboard] result=putDynatraceAPI(uri, payload) return() def mappDashboard(TENANT, TOKEN): global owner print('\nupdate dashboards') for dashboard in Dashboard_target: uri=TENANT+APIdashboard+'/'+Dashboard_target[dashboard] datastore = queryDynatraceAPI(uri) #print(datastore) datastore['dashboardMetadata']['owner']=owner data=json.dumps(datastore) for i in Dashboard_source: if Dashboard_target[i] != '': data=re.sub(Dashboard_source[i], Dashboard_target[i], data) print(' update', dashboard, Dashboard_target[dashboard]) uri=TENANT+APIdashboard+'/'+Dashboard_target[dashboard] putDynatraceAPI(uri, json.loads(data)) print(' => with owner', owner) return() ################################## ## Main program ################################## print("######## SLO Simply Smarter automatic deployment ") print('\nvariables') print(' MyTenant', Tenant) if Tenant == None: print(' Error Tenant is empty') exit() if Token == None: print(' Error Token is empty') exit() if len(Token) > 15 : print(' MyToken', Token[0:15]+'*****') else : print('ERROR : MyToken', Token) exit() print(' Deploy', deploy) if Cookie != '' or CSRF != '' : print(' Temporary Cookie and CSRFToken from Mission Control') if len(Cookie) > 30 : print(' Cookie', Cookie[0:15]+'...'+Cookie[-15:-1]) else: print(' Cookie', Cookie) print(' X-CSRFToken', CSRF) if deploy != 'SLO' and deploy != 'slo' : print(' Owner', owner) if Tenant == None : print('ERROR : MyTenant is empty') exit() if Token == None : print('ERROR : MyToken is empty') exit() if Cookie != '' : if CSRF == '' : print('ERROR : CSRFToken is empty') exit() if CSRF != '' : if Cookie == '' : print('ERROR : Cookie is empty') exit() #info dashboard try: getDashboard(Tenant, Token) except: print('Connection ERROR with your tenant "'+Tenant+'" and your token "'+Token[0:15]+'*****"') exit() #update dashboards if deploy != 'SLO' and deploy != 'slo' : generateDashboard(Tenant, Token) getDashboard(Tenant, Token) mappDashboard(Tenant, Token) #validate slo getSLO(Tenant, Token) generateSLO(Tenant, Token) getSLO(Tenant, Token) #mapping slo dashboards mappSloDashboard(Tenant, Token) #update slo and owner if deploy != 'SLO' and deploy != 'slo' : updateSLO(Tenant, Token) print('\nsimply smarter') Home=Tenant+"/#dashboard;id="+Dashboard_target['🏠 Dynatrace: simply smarter'] print(' ',Home) #################################