js-statusio-selector/statusio-selector.js

345 lines
17 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// ==UserScript==
// @name MS AKS Tool Launcher
// @namespace https://microsoft.com
// @description Effort to simplify launching AKS support-related tools
// @require http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js
// @require http://ajax.googleapis.com/ajax/libs/jqueryui/1.11.1/jquery-ui.min.js
// @require https://gist.github.com/raw/2625891/waitForKeyElements.js
// @grant GM_addStyle
// @grant GM_setClipboard
// @include /^https?://servicedesk\.microsoft\.com/.*$/
// @include /^https?://servicedesk/.*$/
// @version 0.0.1
// ==/UserScript==
const urlRegex = /^http?s:\/\/servicedesk(\.microsoft\.com)?\/\#\/customer\/commercial\?caseNumber=\d+$/
if (urlRegex.test($("ul").context.URL)) {
try {
waitForKeyElements("#mc-case-section", storeAndPrint);
function storeAndPrint () {
var region = "";
var d = new Date();
var endDate = d.toISOString().valueOf()
d.setDate(d.getDate() - 1)
var startDate = d.toISOString().valueOf()
const caseText = $("#mc-case-section")[0].innerText;
const caseID = $("#content")[0].innerText.split('\n')[1]
const resourceURIRegex = /\/subscriptions\/[\d\w]{8}-[\d\w]{4}-[\d\w]{4}-[\d\w]{4}-[\d\w]{12}\/resourceGroups\/.*\/providers\/Microsoft\.ContainerService\/managedClusters\/.*/g;
const resourceURI = caseText.match(resourceURIRegex)[0];
const ascResourceURI = resourceURI.replace(/\//gi, "~2F");
const subscription = resourceURI.split('/')[2];
const resourceGroup = resourceURI.split('/')[4];
const cluster = resourceURI.split('/')[8];
var template = `
// Heres are ALL the errors/messages for the AKS clusters in the resource group in the past 90 days -
union cluster("Aks").database("AKSprod").FrontEndContextActivity, cluster("Aks").database("AKSprod").AsyncContextActivity
| where subscriptionID contains "${subscription}"
| where resourceName contains "${cluster}"
| where level != "info"
| where PreciseTimeStamp > ago(90d)
| project PreciseTimeStamp, operationID, correlationID, level, suboperationName, msg
// Heres are the recent scale/upgrade operations
union cluster("Aks").database("AKSprod").FrontEndContextActivity, cluster("Aks").database("AKSprod").AsyncContextActivity
| where subscriptionID contains "${subscription}"
| where resourceName contains "${cluster}"
| where msg contains "intent" or msg contains "Upgrading" or msg contains "Successfully upgraded cluster" or msg contains "Operation succeeded" or msg contains "validateAndUpdateOrchestratorProfile" // or msg contains "unique pods in running state"
| where PreciseTimeStamp > ago(90d)
| project PreciseTimeStamp, operationID, correlationID, level, suboperationName, msg
// Shows the scale errors/messages for an AKS cluster using the operationID from the previous query
union cluster("Aks").database("AKSprod").FrontEndContextActivity, cluster("Aks").database("AKSprod").AsyncContextActivity
| where operationID == ""
| where level != "info"
| project PreciseTimeStamp, level, msg
//Black box monitoring FIND fqdn by customer"s subscriptionID
cluster("aks").database("AKSprod").BlackboxMonitoringActivity
| where subscriptionID == "${subscription}" and resourceGroupName contains "${resourceGroup}"
| where PreciseTimeStamp > ago(9d)
| summarize by fqdn, resourceGroupName, resourceName, underlayName
//Black box monitoring using fqdn to find where cluster is not healthy
cluster("aks").database("AKSprod").BlackboxMonitoringActivity
| where fqdn == "replacefqdn"
// | where (["state"] != "Healthy" or podsState != "Healthy" or resourceState != "Healthy" or addonPodsState != "Healthy")
| where PreciseTimeStamp > ago(20d)
| project fqdn, PreciseTimeStamp, agentNodeName, state, reason, podsState, resourceState, addonPodsState, agentNodeCount, provisioningState, msg, resourceGroupName, resourceName, underlayName
// | order by PreciseTimeStamp asc
// | render timepivot by fqdn, reason, agentNodeName, addonPodsState
| render timepivot by fqdn, agentNodeName, addonPodsState, reason
// | summarize count() by reason
// | sort by reason
//Black box monitoring for cluster
cluster("aks").database("AKSprod").BlackboxMonitoringActivity
| where PreciseTimeStamp > ago(12h) and underlayName == ""
| where reason != ""
| summarize count() by reason | top 10 by count_ desc
// Find Errors reported by ARM Failed - Deleted - Created
cluster("ARMProd").database("ARMProd").EventServiceEntries
| where subscriptionId == "${subscription}"
| where resourceUri contains "${cluster}"
| where TIMESTAMP > ago(3d)
| where status == "Failed"
| project PreciseTimeStamp, correlationId , operationId, operationName, properties
// Get serviceRequestId of processes sent to cluster
cluster("ARMProd").database("ARMProd").HttpOutgoingRequests
| where httpMethod != "GET"
| where TIMESTAMP > ago(1d)
| where targetUri contains "${cluster}"// and targetUri contains "${subscription}"
| project TIMESTAMP, ActivityId, serviceRequestId , clientRequestId, failureCause, httpMethod , operationName, targetUri
// Use the activityID from the previous query.
cluster("Azcrp").database("crp_allprod").ContextActivity
| where TIMESTAMP between (datetime(2018-08-17T07:57Z)..datetime(2018-08-17T09:28Z))
| where subscriptionId == "${subscription}"
// | where activityId == "3817a3d4-7045-4db5-bc7f-45dbffe2166a"
// | where message contains "${cluster}"
// | where PreciseTimeStamp > ago(3d) // datetime(2018-07-31)
| project PreciseTimeStamp, activityId, traceLevel, message
// claims name shows WHO requested or performed the action
cluster("ARMProd").database("ARMProd").EventServiceEntries
| where subscriptionId == "${subscription}"
| where resourceUri contains "${cluster}"
// | where claims contains "1d78a85d-813d-46f0-b496-dd72f50a3ec0"
// | where ActivityId == "3817a3d4-7045-4db5-bc7f-45dbffe2166a"
// | where operationName contains "delete"
| where TIMESTAMP between (datetime(2018-08-17T07:57Z)..datetime(2018-08-17T09:28Z))
// | where claims contains "baead28c-2ce7-4550-83a5-5e6a2deb02b8"
// | where status == "Failed"
| project PreciseTimeStamp, claims, authorization, properties, resourceUri, operationName //, httpRequest, correlationId, operationId, Deployment, operationName
// | project PreciseTimeStamp, resourceUri , issuer, issuedAt
// Get the PUT operation. This query also shows the command used (aks get-credentials, browse, scale, show, create)
cluster("Armprod").database("ARMProd").HttpIncomingRequests
| where subscriptionId == "${subscription}"
| where targetUri contains "${cluster}"
// | where authorizationAction contains "write" or authorizationAction contains "delete"
| where commandName contains "aks" and httpMethod == "PUT"
| where PreciseTimeStamp > ago(3d)
| project TIMESTAMP,httpMethod,commandName,failureCause,serviceRequestId,authorizationAction,errorCode,errorMessage,subscriptionId,correlationId,targetUri
// Get the PUT operation
cluster("Armprod").database("ARMProd").HttpIncomingRequests
| where subscriptionId == "${subscription}"
| where targetUri contains "${cluster}" and authorizationAction contains "Clusters"
| where httpMethod == "PUT"
| where PreciseTimeStamp > ago(3d) // between (datetime(2018-07-16) .. datetime(2018-07-20))
| project TIMESTAMP, commandName , serviceRequestId , httpMethod , authorizationAction , operationName
//
cluster("Aks").database("AKSprod").FrontEndQoSEvents
| where subscriptionID contains "${subscription}"
| where resourceName contains "${cluster}"
// | where operationName !contains "delete"
| where PreciseTimeStamp > ago(3d)
// feature-gates will be broken when upgrading to 1.11.0+ Please code all cases against - 2835281 - for this issue (also added in the wiki)
// Chase has created doc for scenario where upgrade failing to 1.11 and nodes getting disappear. Here is the doc: https://www.csssupportwiki.com/index.php/curated:Azure/Virtual_Machine/Products/Azure_Kubernetes_Service/TSG/upgrade_to_1.11_NodesNotReady
// Customer can run this script on nodes which are missing
// az vm run-command invoke -g $MC_RG_NAME -n $NODE_NAME --command-id RunShellScript --scripts "sed -i "s/--feature-gates=Accelerators=true //" /etc/default/kubelet && systemctl daemon-reload && systemctl restart kubelet"
// But a roll is being fixed out , once fix has been rolled out they can retry the upgrade
cluster("Aks").database("AKSprod").AsyncQoSEvents
| where subscriptionID == "${subscription}"
| where TIMESTAMP > ago(3d)
| where suboperationName == "Upgrading" and propertiesBag contains "1.11"
| extend bag = parse_json(propertiesBag)
| extend from_version = tostring(bag.k8sCurrentVersion)
| extend to_version = tostring(bag.k8sGoalVersion)
| where from_version !contains "1.11" and to_version contains "1.11" and resultCode == "NodesNotReady"
//Black box monitoring for cluster
cluster("aks").database("AKSprod").BlackboxMonitoringActivity
| where PreciseTimeStamp > ago(1d)
| where fqdn contains "replacefqdn"
// | where ["state"] == "Unhealthy"
| summarize count(state) by bin(PreciseTimeStamp, 5min), state
| render timeline
//Black box monitoring for cluster
cluster("aks").database("AKSprod").BlackboxMonitoringActivity
| where PreciseTimeStamp > ago(1d)
| where fqdn contains "replacefqdn"
| where state != "Healthy"
| project PreciseTimeStamp, state, provisioningState, reason, agentNodeCount, msg, resourceGroupName, resourceName, underlayName
| order by PreciseTimeStamp asc
// | render timeline
cluster("Aks").database("AKSprod").AsyncQoSEvents | sample 10
`;
const regionRegex = /- Location:.*/g;
const regionlower = caseText.match(regionRegex)[0].split(' ')[2];
switch (regionlower) {
case 'australiaeast':
region = "AustraliaEast";
break;
case 'brazilsouth':
region = "BrazilSouth";
break;
case 'canadacentral':
region = "CanadaCentral";
break;
case 'canadaeast':
region = "CanadaEast";
break;
case 'centralindia':
region = "CentralIndia";
break;
case 'centralus':
region = "CentralUS";
break;
case 'eastasia':
region = "EastAsia";
break;
case 'eastus':
region = "EastUS";
break;
case 'eastus2':
region = "EastUs2";
break;
case 'eastus2euap':
region = "EastUS2EUAP";
break;
case 'francecentral':
region = "FranceCentral";
break;
case 'japaneast':
region = "JapanEast";
break;
case 'japanwest':
region = "JapanWest";
break;
case 'northcentralus':
region = "NorthCentralUS";
break;
case 'northeurope':
region = "NorthEurope";
break;
case 'southafricanorth':
region = "SouthAfricaNorth";
break;
case 'southcentralus':
region = "SouthCentralUS";
break;
case 'southeastasia':
region = "SouthEastAsia";
break;
case 'southindia':
region = "SouthIndia";
break;
case 'uksouth':
region = "UkSouth";
break;
case 'ukwest':
region = "UKWest";
break;
case 'westcentralus':
region = "WestCentlraUS";
break;
case 'westeurope':
region = "WestEurope";
break;
case 'westus':
region = "WestUs";
break;
case 'westus2':
region = "WestUs2";
break;
default:
console.log(`Sorry, looks like ${regionlower} isn't stored as a valid region. Please reach out to tybean@.`);
}
const tenantIDRegex = /- Tenant Id:.*/g;
const tenantID = caseText.match(tenantIDRegex)[0].split(' ')[3];
const objectIDRegex = /- Object Id:.*/g;
const objectID = caseText.match(objectIDRegex)[0].split(' ')[3];
const appLensURL = `https://applens.azurewebsites.net${resourceURI}/home/category?startTime=${startDate}&endTime=${endDate}`;
const jarvisURL = `https://jarvis-west.dc.ad.msft.net/?page=actions&acisEndpoint=Public&selectedNodeType=3&extension=AzureContainerService%20AKS&group=Resource%20Operations&operationId=GetManagedCluster&operationName=Get%20Managed%20Cluster&inputMode=single&params={"wellknownsubscriptionid":"${subscription}","smeaksresourcegroup":"${resourceGroup}","smeaksresource":"${cluster}","smeaksapiversions":"2019-04-01"}&actionEndpoint=${region}`;
const ascURL = `https://azuresupportcenter.msftcloudes.com/resourceExplorer/resource/${ascResourceURI}?srId=${caseID}`
var zNode = document.createElement ('div');
zNode.innerHTML = '<button id="appLensButton" type="button">'
+ 'AppLens</button><button id = jarvisButton>Jarvis</button><button id=ascButton>ASC</button><button id = kustoButton>Kusto</button> <button id = oneClickButton>1 - Click</button>'
;
zNode.setAttribute ('id', 'myContainer');
document.body.appendChild (zNode);
//--- Activate the newly added button.
document.getElementById ("appLensButton").addEventListener (
"click", appLensButtonClickAction, false
);
document.getElementById ("jarvisButton").addEventListener (
"click", jarvisButtonClickAction, false
);
document.getElementById ("ascButton").addEventListener (
"click", ascButtonClickAction, false
);
document.getElementById ("kustoButton").addEventListener (
"click", kustoButtonClickAction, false
);
document.getElementById ("oneClickButton").addEventListener (
"click", oneClickButtonClickAction, false
);
function appLensButtonClickAction (zEvent) {
window.open(appLensURL, "_blank");
}
function jarvisButtonClickAction (zEvent) {
window.open(jarvisURL, "_blank");
}
function ascButtonClickAction (zEvent) {
window.open(ascURL, "_blank");
}
function kustoButtonClickAction (zEvent) {
GM_setClipboard(template, "kusto queries");
alert(`Kusto queries for ${cluster} have been copied to clipboard!`);
}
function oneClickButtonClickAction (zEvent) {
appLensButtonClickAction(zEvent);
jarvisButtonClickAction(zEvent);
ascButtonClickAction(zEvent);
kustoButtonClickAction(zEvent);
}
//--- Style our newly added elements using CSS.
GM_addStyle ( multilineStr ( function () {/*!
#myContainer {
position: absolute;
bottom: 0;
left: 0;
font-size: 14px;
background: orange;
border: 3px outset black;
margin: 3px;
opacity: 0.7;
z-index: 222;
padding: 5px 5px;
}
#myButton {
cursor: pointer;
}
#myContainer p {
color: red;
background: white;
}
*/} ) );
function multilineStr (dummyFunc) {
var str = dummyFunc.toString ();
str = str.replace (/^[^\/]+\/\*!?/, '') // Strip function () { /*!
.replace (/\s*\*\/\s*\}\s*$/, '') // Strip */ }
.replace (/\/\/.+$/gm, '') // Double-slash comments wreck CSS. Strip them.
;
return str;
}
}
} catch (err) {
// If an error was thrown, go ahead and present it as an alert to help
// with debugging any problems
alert(err.toString());
}
}