diff --git a/createDash.py b/createDash.py index 9e1571c..fdc8e2a 100644 --- a/createDash.py +++ b/createDash.py @@ -7,17 +7,18 @@ from datetime import datetime from git import Repo import os #set STAGING global dashboard name -DASHBOARD_NAME = "[STAGING]Global Offboard Reliability - Touchpoint Mobile #" +DASHBOARD_NAME = "[STAGING]Global Offboard Reliability - Touchpoint " AUTHSTRING = config("BITBUCKET_USERNAME")+":"+config("BITBUCKET_TOKEN") -CONFIG_REPO_URL = "https://"+AUTHSTRING+"atc.bmwgroup.net/bitbucket/scm/opapm/shared_configuration.git" +CONFIG_REPO_URL = "https://"+AUTHSTRING+"@atc.bmwgroup.net/bitbucket/scm/opapm/shared_configuration.git" CONFIG_REPO_NAME = "shared_configuration" -ARCHIVE_REPO_URL = "https://"+AUTHSTRING+"atc.bmwgroup.net/bitbucket/scm/opapm/archive.git" +ARCHIVE_REPO_URL = "https://"+AUTHSTRING+"@atc.bmwgroup.net/bitbucket/scm/opapm/archive.git" ARCHIVE_REPO_NAME = "archive" parser = argparse.ArgumentParser(description="Generate and deploy the Dynatrace Global Dashboard as Code. Auto deployment works only for STAGING dashboard", formatter_class=argparse.ArgumentDefaultsHelpFormatter) parser.add_argument("-R", "--rows", type=int, help="Number of rows per dashboard. If not specified, all rows will be added to single dashboard") parser.add_argument('--auto-upload', default=False, action='store_true', help="Auto upload to STAGING dashboard") +parser.add_argument('-T', '--touchpoint', type=str, help="Define touchpoint for which the dashboard should be updated: 'Mobile' or 'Vehicle'") args = parser.parse_args() def clone_repo_if_notexist(repourl, reponame): @@ -66,9 +67,11 @@ def make_request(url, DTAPIToken,verify, method, jsondata): return "An Unknown Error occurred" + repr(err) return response + def get_all_dashboards_withname(DTAPIToken, DTENV,name): DTAPIURL= DTENV + "api/config/v1/dashboards" r = make_request(DTAPIURL,DTAPIToken,True,"get",None) + print(r) entityResponse = r.json() result = [] if("dashboards" in entityResponse): @@ -77,6 +80,7 @@ def get_all_dashboards_withname(DTAPIToken, DTENV,name): result.append(dashboard) result = sorted(result, key=lambda x : x['name'], reverse=False) return result + def backup_dashboards(DTAPIToken, DTENV, dashboards): for dashboard in dashboards: DTAPIURL = DTENV + "api/config/v1/dashboards/" + dashboard["id"] @@ -95,6 +99,7 @@ def remove_dashboards(DTAPIToken, DTENV, dashboards): print("Removing STAGING dashboard from Dynatrace: "+dashboard["name"]) DTAPIURL = DTENV + "api/config/v1/dashboards/" + dashboard["id"] print(make_request(DTAPIURL,DTAPIToken,True,"delete",None)) + def create_or_update_dashboard(DTAPIToken, DTENV, dashboards, files): if(files): for index, filename in enumerate(files,start=1): @@ -118,7 +123,7 @@ def create_or_update_dashboard(DTAPIToken, DTENV, dashboards, files): print("Dashboard for file: "+filename + " not found.") newdashboard = { "dashboardMetadata":{ - "name": DASHBOARD_NAME+str(index), + "name": DASHBOARD_NAME+ args.touchpoint + "#" + str(index), "owner": "PATRYK.GUDALEWICZ@partner.bmw.de" }, "tiles":[] @@ -129,8 +134,6 @@ def create_or_update_dashboard(DTAPIToken, DTENV, dashboards, files): print(make_request(DTAPIURL,DTAPIToken,True,"post",json.dumps(newdashboard))) remove_dashboards(DTAPIToken, DTENV, dashboards) - - def get_bounds (grid_row, grid_column, tile_columnwidth, tile_rowheight): grid_brick = 38 grid_top = 0 if grid_row == 0 else grid_row * grid_brick @@ -169,7 +172,7 @@ def get_DataExplorerTile_Markdown(name_short, department, bounds, detailDashboar "configured": "true", "bounds": bounds, "tileFilter": {}, - "markdown": "___________\n## " + name_short + "\n\n" + department + " \n [Documentation](" + docURL + ")" + "markdown": "___________\n## " + name_short + "\n\n" + department + " \n[Documentation](" + docURL + ")" } return dataExplorerTile_Markdown @@ -256,17 +259,17 @@ def create_default_tiles(): ) # EMEA HUB newDashboardTiles.append({ "name": "Header" ,"tileType": "MARKDOWN" , "configured": "true" , "bounds": get_bounds(0 , 7 , 20 , 2), "tileFilter": {}, "markdown": "# EMEA" }) - newDashboardTiles.append({ "name": "ACTUAL" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 7 , 4 , 1), "tileFilter": {} }) + newDashboardTiles.append({ "name": "CURRENT" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 7 , 4 , 1), "tileFilter": {} }) newDashboardTiles.append({ "name": "10 DAYS" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 11 , 12 , 1), "tileFilter": {} }) newDashboardTiles.append({ "name": "YTD" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 23 , 4 , 1), "tileFilter": {} }) # NORTH AMERICA HUB newDashboardTiles.append({ "name": "Header" ,"tileType": "MARKDOWN" , "configured": "true" , "bounds": get_bounds(0 , 27 , 20 , 2), "tileFilter": {}, "markdown": "# NORTH AMERICA" }) - newDashboardTiles.append({ "name": "ACTUAL" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 27 , 4 , 1), "tileFilter": {} }) + newDashboardTiles.append({ "name": "CURRENT" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 27 , 4 , 1), "tileFilter": {} }) newDashboardTiles.append({ "name": "10 DAYS" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 31 , 12 , 1), "tileFilter": {} }) newDashboardTiles.append({ "name": "YTD" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 43 , 4 , 1), "tileFilter": {} }) # CHINA HUB newDashboardTiles.append({ "name": "Header" ,"tileType": "MARKDOWN" , "configured": "true" , "bounds": get_bounds(0 , 47 , 20 , 2), "tileFilter": {}, "markdown": "# CHINA" }) - newDashboardTiles.append({ "name": "ACTUAL" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 47 , 4 , 1), "tileFilter": {} }) + newDashboardTiles.append({ "name": "CURRENT" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 47 , 4 , 1), "tileFilter": {} }) newDashboardTiles.append({ "name": "10 DAYS" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 51 , 12 , 1), "tileFilter": {} }) newDashboardTiles.append({ "name": "YTD" ,"tileType": "HEADER" , "configured": "true" , "bounds": get_bounds(2 , 63 , 4 , 1), "tileFilter": {} }) @@ -311,34 +314,37 @@ def main(slo_path): if(args.rows is not None): rowcount = args.rows for slo_name, configuration in slo_doc.items(): - slo_index = configuration["index"] - currindex = slo_index - if rowcount > 0 and slo_index > rowcount: - dashboard_json = create_default_tiles() - rowcount = rowcount+args.rows - dahboardcount = dahboardcount+1 - boundindex = 1 - slo_display = configuration["displayname"] - slo_department = configuration["department"] - timeframe_ytd = configuration["yearstart"] + " 00:00 to now" + if "TP_" + args.touchpoint in slo_name: + print (slo_name + " eq " + args.touchpoint) + if "TP_" + args.touchpoint in slo_name: + slo_index = configuration["index"] + currindex = slo_index + if rowcount > 0 and slo_index > rowcount: + dashboard_json = create_default_tiles() + rowcount = rowcount+args.rows + dahboardcount = dahboardcount+1 + boundindex = 1 + slo_display = configuration["displayname"] + slo_department = configuration["department"] + timeframe_ytd = configuration["yearstart"] + " 00:00 to now" - slo_graphThreshold_SingleValue = get_dataExplorerTileSloThreshold(configuration["thresholds"]["single_value"]) - slo_graphThreshold_Graph = get_dataExplorerTileSloThreshold(configuration["thresholds"]["graph_value"]) - - if len(configuration["hubs"]) > 0: - dashboard_json.append(get_DataExplorerTile_Markdown(slo_display, slo_department, get_bounds(((boundindex)*(3)) , 0 , 7 , 3), configuration["ops_dashboard"]["emea"], configuration["ops_dashboard"]["na"], configuration["ops_dashboard"]["cn"],configuration["doc_url"])) - for hub,tiles in configuration["hubs"].items(): - if 'actual' in tiles["tiles"]: - dashboard_json.append(get_DataExplorerTile_SingleValue(slo_name, configuration["metric"], hub_config[hub]["remote_url"], get_bounds(((boundindex)*(3)) , 7 + hub_config[hub]["offset"] , 4 , 3), timeframe_actual, slo_graphThreshold_SingleValue)) - if "graph" in tiles["tiles"]: - dashboard_json.append(get_DataExplorerTile_Graph(slo_name, configuration["metric"], hub_config[hub]["remote_url"], get_bounds(((boundindex)*(3)) , 11 + hub_config[hub]["offset"] , 12 , 3), timeframe_graph, "97", "102", slo_graphThreshold_Graph)) - if "ytd" in tiles["tiles"]: - dashboard_json.append(get_DataExplorerTile_SingleValue(slo_name, configuration["metric"], hub_config[hub]["remote_url"], get_bounds(((boundindex)*(3)) , 23 + hub_config[hub]["offset"] , 4 , 3), timeframe_ytd, slo_graphThreshold_SingleValue)) - boundindex = boundindex+1 - if rowcount > 0 and slo_index == rowcount: - with open("dashboard_tiles_"+str(dahboardcount)+".json", "w") as file: - json.dump(dashboard_json, file, indent=2) - generatedfiles.append("dashboard_tiles_"+str(dahboardcount)+".json") + slo_graphThreshold_SingleValue = get_dataExplorerTileSloThreshold(configuration["thresholds"]["single_value"]) + slo_graphThreshold_Graph = get_dataExplorerTileSloThreshold(configuration["thresholds"]["graph_value"]) + + if len(configuration["hubs"]) > 0: + dashboard_json.append(get_DataExplorerTile_Markdown(slo_display, slo_department, get_bounds(((boundindex)*(3)) , 0 , 7 , 3), configuration["ops_dashboard"]["emea"], configuration["ops_dashboard"]["na"], configuration["ops_dashboard"]["cn"],configuration["doc_url"])) + for hub,tiles in configuration["hubs"].items(): + if 'actual' in tiles["tiles"]: + dashboard_json.append(get_DataExplorerTile_SingleValue(slo_name, configuration["metric"], hub_config[hub]["remote_url"], get_bounds(((boundindex)*(3)) , 7 + hub_config[hub]["offset"] , 4 , 3), timeframe_actual, slo_graphThreshold_SingleValue)) + if "graph" in tiles["tiles"]: + dashboard_json.append(get_DataExplorerTile_Graph(slo_name, configuration["metric"], hub_config[hub]["remote_url"], get_bounds(((boundindex)*(3)) , 11 + hub_config[hub]["offset"] , 12 , 3), timeframe_graph, "97", "102", slo_graphThreshold_Graph)) + if "ytd" in tiles["tiles"]: + dashboard_json.append(get_DataExplorerTile_SingleValue(slo_name, configuration["metric"], hub_config[hub]["remote_url"], get_bounds(((boundindex)*(3)) , 23 + hub_config[hub]["offset"] , 4 , 3), timeframe_ytd, slo_graphThreshold_SingleValue)) + boundindex = boundindex+1 + if rowcount > 0 and slo_index == rowcount: + with open("dashboard_tiles_"+str(dahboardcount)+".json", "w") as file: + json.dump(dashboard_json, file, indent=2) + generatedfiles.append("dashboard_tiles_"+str(dahboardcount)+".json") if rowcount == 0 or (args.rows is not None and currindex%args.rows != 0): with open("dashboard_tiles_"+str(dahboardcount)+".json", "w") as file: @@ -358,7 +364,7 @@ def main(slo_path): DTTOKEN = config(token.get('env-token-name')) DTURL = url.get('env-url') - existingdashboards = get_all_dashboards_withname(DTTOKEN, DTURL,DASHBOARD_NAME) + existingdashboards = get_all_dashboards_withname(DTTOKEN, DTURL,DASHBOARD_NAME + args.touchpoint) print("Uploading STAGING dashboards to Dynatrace...") backup_dashboards(DTTOKEN, DTURL, existingdashboards) now=datetime.now() diff --git a/readme.md b/readme.md index 240568c..07a5083 100644 --- a/readme.md +++ b/readme.md @@ -3,14 +3,14 @@ This repository holds the code to generate the Dynatrace Global Dashboard as Cod The Global Dashboard splits in 2 different dashboards: - - STAGING (https://jyy23483.live.dynatrace.com/#dashboard;gtf=defaultTimeFrame;gf=defaultManagementZone;id=2f1be2c6-9109-4e6b-8ec1-895be69935e3) + - STAGING - PROD While the PROD dashboard is adapted manually, the Staging dashboard is auto updated when this script runs. # Dashboard Splitting To enable flexibility for different screensizes, the script takes an -R or --ROWS parameter to define how many SLOs should be on one dedicated dashboard. -If left empty, only one dashboard will be created, if entered a row the dashboard will be splitted to multiple dashboards and uploaded with the following name: [STAGING]Global Offboard Reliability - Touchpoint Mobile #1 ..#2..#3 +If left empty, only one dashboard will be created, if entered a row the dashboard will be splitted to multiple dashboards and uploaded with the following name: [STAGING]Global Offboard Reliability - Touchpoint Mobile|Vehicle #1 ..#2..#3 # shared configuration @@ -40,14 +40,16 @@ To provide authentication for API calls, create ".env" file in the script direct # Usage - python createDash.py [-h] [-R ROWS] [--auto-upload] + usage: createDash.py [-h] [-R ROWS] [--auto-upload] [-T TOUCHPOINT] - options: - -h, --help show help message and exit - -R ROWS, --rows ROWS Number of rows per dashboard. If not specified, all rows will be added to single dashboard - (default: None) + Generate and deploy the Dynatrace Global Dashboard as Code. Auto deployment works only for STAGING dashboard + + optional arguments: + -h, --help show this help message and exit + -R ROWS, --rows ROWS Number of rows per dashboard. If not specified, all rows will be added to single dashboard (default: None) --auto-upload Auto upload to STAGING dashboard (default: False) - + -T TOUCHPOINT, --touchpoint TOUCHPOINT + Define touchpoint for which the dashboard should be updated: 'Mobile' or 'Vehicle' (default: None) # Files ## slo_parameter.yaml @@ -104,7 +106,7 @@ Defintion Description: single_value: str #thresholds and coloring for single value tiles graph_value: str #thresholds and coloring for graph tiles -## createDash . py +## createDash.py This scripts generates the "tile" Section of a Dynatrace Dashboard and takes the slo_parameter.yaml as input parameter (no need to add it manually)