From 37c3b2f5e47cd3d2b7766f0b820b869c39b72dac Mon Sep 17 00:00:00 2001 From: guillermo Date: Tue, 19 Dec 2023 14:57:25 +0100 Subject: [PATCH] feat: refs #6164 Now search in alerts --- main copy.js | 277 ------------------------------ main.js | 465 +++++++++++++++++++++++++++------------------------ package.json | 2 +- 3 files changed, 249 insertions(+), 495 deletions(-) delete mode 100644 main copy.js diff --git a/main copy.js b/main copy.js deleted file mode 100644 index 111367c..0000000 --- a/main copy.js +++ /dev/null @@ -1,277 +0,0 @@ -#!/usr/bin/env node - -const packageJson = require('./package.json'); -const fetch = require('node-fetch'); -const colors = require('colors'); -const os = require('os'); -const fs = require('fs'); -const getopts = require('getopts'); - -const error = `[ERROR]: `.bold; - -console.log( - `Grafana-Find (${packageJson.description})`.yellow.bold, - `v${packageJson.version}`.cyan.bold -); - -const usage = { - description: 'Utility to find strings in dashboards', - params: { - user: 'Grafana username', - version: 'Display the version number and exit', - help: 'Display this help message' - } -}; - -const opts = getopts(process.argv.slice(2), { - alias: { - version: 'v', - help: 'h' - }, - boolean: [ - 'version', - 'help' - ] -}); - -if (opts.version) { - process.exit(); -} -if (opts.help) { - console.log(`Usage:`.gray, `grafana-find`, ``.magenta); - process.exit(); -} - -if (!opts._[0]) { - console.error(`${error}The string to search for is missing`.red); - process.exit(1); -} -if (opts._.length > 1) { - console.error(`${error}This command doesn't allow more parameters`.red); - process.exit(1); -} - -let config; -const configPaths = [ - os.homedir(), - `${__dirname}` -]; -for (const configPath of configPaths) { - const configFile = `${configPath}/.grafana-find.json`; - if (fs.existsSync(configFile)) { - config = require(configFile); - break; - } -} -if (!config) { - console.error(`${error}Configuration file not found, search paths: .grafana-find.json: ${configPaths.join(':')}\n`.red); - process.exit(1); -} - -const findAll = opts._[0]; -const grafanaUrl = config.grafanaUrl; -let user = config.user; -let passw = config.password; - -const grafanaApi = `${grafanaUrl}/api`; -const urlOrganizations = `${grafanaUrl}/api/orgs`; -const urlDashboards = `${grafanaApi}/search?orgId=`; -const urlUID = `${grafanaApi}/dashboards/uid/`; -let numberOfDashboards = 0; -let totalDashboards = 0; -let numberOfPanels = 0; -let numberOfVariables = 0; -let numberOfObjects = 0; -let titlePanels = new Array; -let nameVariables = new Array; - -const regexRawSQL = new RegExp(findAll, 'i'); - -async function main(){ - if (!user) { - const readline = require('readline'); - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }); - - const answer = await new Promise(resolve => { - rl.question(colors.green('Enter your user: '), resolve); - }); - user = `${answer}`; - if (!answer) { - console.error(`\n${error}You need to put a user\n`.red); - process.exit(0); - } - rl.close(); - } - - if (!passw) { - const readline = require('readline'); - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }); - - rl.stdoutMuted = true; - - const answer = await new Promise(resolve => { - rl.question(colors.green('Enter your password: '), resolve); - rl._writeToOutput = function _writeToOutput(stringToWrite) { - if (rl.stdoutMuted) - rl.output.write("*"); - else - rl.output.write(stringToWrite); - }; - }); - passw = `${answer}`; - if (!answer) { - console.error(`\n${error}You need to put a password\n`.red); - process.exit(0); - } - rl.close(); - } - - const credentials = `Basic ` + Buffer.from(`${user}:${passw}`).toString('base64'); - - try { - var response = await fetch(urlOrganizations, { - method: "GET", - headers: { - Authorization: credentials - } - }); - } catch (notfound) { - console.error(`${error}Server '${config.grafanaUrl}' not found`.red); - process.exit(1); - }; - let AllOrganizations = await response.json(); - - if (AllOrganizations.message==='invalid username or password') { - console.error(`\n${error}Invalid username or password\n`.red); - process.exit(1); - } - - console.clear(); - console.log( - `--------- Grafana-Find (${packageJson.description})`.yellow.bold, - `v${packageJson.version}`.cyan.bold, - `--------`.yellow.bold, - ); - console.log(colors.green.bold(`-------------------- Starting process --------------------\n`)); - - for (let x in AllOrganizations) { - - console.log(colors.gray.bold(`(Organization: ${AllOrganizations[x].name})\n`)); - response = await fetch(`${urlDashboards}${AllOrganizations[x].id}`, { - method: "GET", - headers: { - Authorization: credentials - }, - redirect: 'manual' - }); - - if (response.status === 302) { - response = await fetch(`${urlDashboards}${AllOrganizations[x].id}`, { - method: 'GET', - headers: { - Accept: 'application/json' - }, - redirect: 'manual' - }); - } - - let allUID = await response.json(); - - for (let i in allUID) { - let url = `${urlUID}${allUID[i].uid}`; - response = await fetch(url, { - method: "GET", - headers: { - Authorization: credentials, - }, - redirect: 'manual' - }); - - if (response.status === 404) { - response = await fetch(url, { - method: 'GET', - headers: { - Accept: 'application/json' - }, - redirect: 'manual' - }); - } - - let data = await response.json(); - - let isFound = false; - let isFoundSomething = false; - - const dashboard = data.dashboard; - if (dashboard) { - if (dashboard.panels) - for (const panel of dashboard.panels) { - if (panel.targets) - for (const target of panel.targets) { - isFound = regexRawSQL.test(target.rawSql); - if (isFound) { - if (panel.title) - titlePanels.push(panel.title); - else - titlePanels.push(`null`); - numberOfPanels++; - isFoundSomething=true; - } - } - } - - if (dashboard.templating) - for (const list of dashboard.templating.list) { - isFound = regexRawSQL.test(list.query); - if (isFound) { - nameVariables.push(list.name) - numberOfVariables++; - isFoundSomething=true; - } - } - } - - if (isFoundSomething) { - const linkUrl = `${grafanaUrl}/d/${allUID[i].uid}?orgId=${AllOrganizations[x].id}`; - console.log((linkUrl).yellow.underline, dashboard.title); - if (numberOfPanels) { - console.log(colors.cyan.bold(`> ${numberOfPanels} panels`)); - console.log(colors.cyan(titlePanels.toString().split(","))); - } - if (numberOfVariables) { - console.log(colors.magenta.bold(`> ${numberOfVariables} variables`)); - console.log(colors.magenta(nameVariables.toString().split(","))); - } - console.log('') - numberOfDashboards++; - } - - titlePanels = []; - nameVariables= []; - numberOfObjects = numberOfPanels + numberOfVariables + numberOfObjects; - numberOfPanels = 0; - numberOfVariables = 0; - } - totalDashboards = numberOfDashboards + totalDashboards; - if (!numberOfDashboards) - console.log(`No results found\n`.green); - numberOfDashboards = 0; - }; - - console.log(colors.green.bold(`-------- Have been found ${numberOfObjects} results in ${totalDashboards} dashboards -------\n`)); - - if (!response) { - console.log(`${error}The server don't exists`); - process.exit(1); - } - - process.exit(); - -} -main(); \ No newline at end of file diff --git a/main.js b/main.js index a2467bb..bda43a0 100644 --- a/main.js +++ b/main.js @@ -10,281 +10,312 @@ const getopts = require('getopts'); const error = `[ERROR]: `.bold; console.log( - `Grafana-Find (${packageJson.description})`.yellow.bold, - `v${packageJson.version}`.cyan.bold + `Grafana-Find (${packageJson.description})`.yellow.bold, + `v${packageJson.version}`.cyan.bold ); -const usage = { - description: 'Utility to find strings in dashboards', - params: { - user: 'Grafana username', - version: 'Display the version number and exit', - help: 'Display this help message' - } -}; - const opts = getopts(process.argv.slice(2), { - alias: { - version: 'v', - help: 'h' - }, - boolean: [ - 'version', - 'help' - ] + alias: { + version: 'v', + help: 'h' + }, + boolean: [ + 'version', + 'help' + ] }); if (opts.version) { - process.exit(); + process.exit(); } if (opts.help) { - console.log(`Usage:`.gray, `grafana-find`, ``.magenta); - process.exit(); + console.log(`Usage:`.gray, `grafana-find`, ``.magenta); + process.exit(); } if (!opts._[0]) { - console.error(`${error}The string to search for is missing`.red); - process.exit(1); + console.error(`${error}The string to search for is missing`.red); + process.exit(1); } if (opts._.length > 1) { - console.error(`${error}This command doesn't allow more parameters`.red); - process.exit(1); + console.error(`${error}This command doesn't allow more parameters`.red); + process.exit(1); } let config; const configPaths = [ - os.homedir(), - `${__dirname}` + os.homedir(), + `${__dirname}` ]; for (const configPath of configPaths) { - const configFile = `${configPath}/.grafana-find.json`; - if (fs.existsSync(configFile)) { - config = require(configFile); - break; - } + const configFile = `${configPath}/.grafana-find.json`; + if (fs.existsSync(configFile)) { + config = require(configFile); + break; + } } if (!config) { - console.error(`${error}Configuration file not found, search paths: .grafana-find.json: ${configPaths.join(':')}\n`.red); - process.exit(1); + console.error(`${error}Configuration file not found, search paths: .grafana-find.json: ${configPaths.join(':')}\n`.red); + process.exit(1); } const findAll = opts._[0]; +const regexRawSQL = new RegExp(findAll, 'i'); const grafanaUrl = config.grafanaUrl; let user = config.user; let passw = config.password; - -const grafanaApi = `${grafanaUrl}/api`; -const urlOrganizations = `${grafanaUrl}/api/orgs`; -const urlDashboards = `${grafanaApi}/search?orgId=`; -const urlUID = `${grafanaApi}/dashboards/uid/`; let numberOfDashboards = 0; -let totalDashboards = 0; +let totalObjects = 0; let numberOfPanels = 0; let numberOfVariables = 0; let numberOfObjects = 0; let titlePanels = new Array; +let titleAlerts = new Array; let nameVariables = new Array; -const regexRawSQL = new RegExp(findAll, 'i'); +// URIs +const grafanaApi = `${grafanaUrl}/api`; +const urlOrganizations = `${grafanaUrl}/api/orgs`; +const urlDashboards = `${grafanaApi}/search?orgId=`; +const urlUID = `${grafanaApi}/dashboards/uid/`; +const urlAlerts = `${grafanaApi}/v1/provisioning/alert-rules?orgId=`; async function main(){ - if (!user) { - const readline = require('readline'); - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }); + if (!user) { + const readline = require('readline'); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); - const answer = await new Promise(resolve => { - rl.question(colors.green('Enter your user: '), resolve); - }); - user = `${answer}`; - if (!answer) { - console.error(`\n${error}You need to put a user\n`.red); - process.exit(0); - } - rl.close(); - } + const answer = await new Promise(resolve => { + rl.question(colors.green('Enter your user: '), resolve); + }); + user = `${answer}`; + if (!answer) { + console.error(`\n${error}You need to put a user\n`.red); + process.exit(0); + } + rl.close(); + } - if (!passw) { - const readline = require('readline'); - const rl = readline.createInterface({ - input: process.stdin, - output: process.stdout - }); + if (!passw) { + const readline = require('readline'); + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout + }); - rl.stdoutMuted = true; + rl.stdoutMuted = true; - const answer = await new Promise(resolve => { - rl.question(colors.green('Enter your password: '), resolve); - rl._writeToOutput = function _writeToOutput(stringToWrite) { - if (rl.stdoutMuted) - rl.output.write("*"); - else - rl.output.write(stringToWrite); - }; - }); - passw = `${answer}`; - if (!answer) { - console.error(`\n${error}You need to put a password\n`.red); - process.exit(0); - } - rl.close(); - } + const answer = await new Promise(resolve => { + rl.question(colors.green('Enter your password: '), resolve); + rl._writeToOutput = function _writeToOutput(stringToWrite) { + if (rl.stdoutMuted) + rl.output.write("*"); + else + rl.output.write(stringToWrite); + }; + }); + passw = `${answer}`; + if (!answer) { + console.error(`\n${error}You need to put a password\n`.red); + process.exit(0); + } + rl.close(); + } - const credentials = `Basic ` + Buffer.from(`${user}:${passw}`).toString('base64'); + const credentials = `Basic ` + Buffer.from(`${user}:${passw}`).toString('base64'); - try { - var response = await fetch(urlOrganizations, { - method: "GET", - headers: { - Authorization: credentials - } - }); - } catch (notfound) { - console.error(`${error}Server '${config.grafanaUrl}' not found`.red); - process.exit(1); - }; - let AllOrganizations = await response.json(); + try { + var response = await fetch(urlOrganizations, { + method: "GET", + headers: { + Authorization: credentials + } + }); + } catch (notfound) { + console.error(`${error}Server '${config.grafanaUrl}' not found`.red); + process.exit(1); + }; + let AllOrganizations = await response.json(); - if (AllOrganizations.message==='invalid username or password') { - console.error(`\n${error}Invalid username or password\n`.red); - process.exit(1); - } + if (AllOrganizations.message === 'invalid username or password') { + console.error(`\n${error}Invalid username or password\n`.red); + process.exit(1); + } - console.clear(); - console.log( - `───────── Grafana-Find (${packageJson.description}) v${packageJson.version} ────────`.yellow.bold - ); - console.log(colors.green.bold(`──────────────────── Starting process ────────────────────\n`)); + console.clear(); + console.log( + `───────── Grafana-Find (${packageJson.description}) v${packageJson.version} ────────`.bold.bgYellow.bgBrightWhite + ); + console.log(colors.green.bold(`──────────────────── Starting process ────────────────────\n`)); - for (let x in AllOrganizations) { + for (let x in AllOrganizations) { + console.log(colors.red.bold(`🏢 Organization: ${AllOrganizations[x].name} 🏢\n`.underline)); + response = await fetch(`${urlDashboards}${AllOrganizations[x].id}`, { + method: "GET", + headers: { + Authorization: credentials + }, + }); - console.log(colors.gray.bold(`-{Organization: ${AllOrganizations[x].name}}-\n`)); - response = await fetch(`${urlDashboards}${AllOrganizations[x].id}`, { - method: "GET", - headers: { - Authorization: credentials - }, - redirect: 'manual' - }); + console.log(colors.white.bold(`🔎 Searching in dashboards...\n`)); + if (response.status === 302) { + response = await fetch(`${urlDashboards}${AllOrganizations[x].id}`, { + method: 'GET', + headers: { + Accept: 'application/json' + }, + }); + } - if (response.status === 302) { - response = await fetch(`${urlDashboards}${AllOrganizations[x].id}`, { - method: 'GET', - headers: { - Accept: 'application/json' - }, - redirect: 'manual' - }); - } + let allUID = await response.json(); - let allUID = await response.json(); + if (allUID.message === 'Unauthorized') { + console.log(colors.red.bold(allUID.message)) + process.exit(); + } - for (let i in allUID) { - let url = `${urlUID}${allUID[i].uid}`; - response = await fetch(url, { - method: "GET", - headers: { - Authorization: credentials, - }, - redirect: 'manual' - }); + for (let i in allUID) { + let url = `${urlUID}${allUID[i].uid}`; + response = await fetch(url, { + method: "GET", + headers: { + Authorization: credentials, + }, + redirect: 'manual' + }); - if (response.status === 404) { - response = await fetch(url, { - method: 'GET', - headers: { - Accept: 'application/json' - }, - redirect: 'manual' - }); - } + if (response.status === 404) { + response = await fetch(url, { + method: 'GET', + headers: { + Accept: 'application/json' + }, + redirect: 'manual' + }); + } - let data = await response.json(); + let data = await response.json(); + let isFound = false; + let isFoundSomething = false; + const dashboard = data.dashboard; + if (dashboard) { + if (dashboard.panels) + for (const panel of dashboard.panels) { + if (panel.targets) + for (const target of panel.targets) { + isFound = regexRawSQL.test(target.rawSql); + if (isFound) { + if (panel.title) + if (panel.title==' ') + titlePanels.push(`(null)`.italic); + else + titlePanels.push(panel.title); + else + titlePanels.push(`(undefined)`.italic); + numberOfPanels++; + isFoundSomething=true; + } + } + } - let isFound = false; - let isFoundSomething = false; + if (dashboard.templating) + for (const list of dashboard.templating.list) { + isFound = regexRawSQL.test(list.query); + if (isFound) { + nameVariables.push(list.name) + numberOfVariables++; + isFoundSomething=true; + } + } + } - const dashboard = data.dashboard; - if (dashboard) { - if (dashboard.panels) - for (const panel of dashboard.panels) { - if (panel.targets) - for (const target of panel.targets) { - isFound = regexRawSQL.test(target.rawSql); - if (isFound) { - if (panel.title) - if (panel.title==' ') - titlePanels.push(`(null)`.italic); - else - titlePanels.push(panel.title); - else - titlePanels.push(`(undefined)`.italic); - numberOfPanels++; - isFoundSomething=true; - } - } - } + if (isFoundSomething) { + const linkUrl = `${grafanaUrl}/d/${allUID[i].uid}?orgId=${AllOrganizations[x].id}`; + console.log((linkUrl).yellow.underline, dashboard.title); + if (numberOfPanels) { + console.log(colors.cyan.bold(`[${numberOfPanels}] panels`)); + for (let q in titlePanels) { + if (q==(titlePanels.length-1)) { + console.log(` └─${titlePanels[q]}`.cyan) + break + } + console.log(` ├─${titlePanels[q]}`.cyan) + } + } + if (numberOfVariables) { + console.log(colors.magenta.bold(`[${numberOfVariables}] variables`)); + for (let q in nameVariables) { + if (q==(nameVariables.length-1)) { + console.log(` └─${nameVariables[q]}`.magenta) + break + } + console.log(` ├─${nameVariables[q]}`.magenta) + } + } + console.log('') + numberOfDashboards++; + } - if (dashboard.templating) - for (const list of dashboard.templating.list) { - isFound = regexRawSQL.test(list.query); - if (isFound) { - nameVariables.push(list.name) - numberOfVariables++; - isFoundSomething=true; - } - } - } - - if (isFoundSomething) { - const linkUrl = `${grafanaUrl}/d/${allUID[i].uid}?orgId=${AllOrganizations[x].id}`; - console.log((linkUrl).yellow.underline, dashboard.title); - if (numberOfPanels) { - console.log(colors.cyan.bold(`[${numberOfPanels}] panels`)); - for (let q in titlePanels) { - if (q==(titlePanels.length-1)) { - console.log(` └─${titlePanels[q]}`.cyan) - break - } - console.log(` ├─${titlePanels[q]}`.cyan) - } - } - if (numberOfVariables) { - console.log(colors.magenta.bold(`[${numberOfVariables}] variables`)); - for (let q in nameVariables) { - if (q==(nameVariables.length-1)) { - console.log(` └─${nameVariables[q]}`.magenta) - break - } - console.log(` ├─${nameVariables[q]}`.magenta) - } - } - console.log('') - numberOfDashboards++; - } - - titlePanels = []; - nameVariables= []; - numberOfObjects = numberOfPanels + numberOfVariables + numberOfObjects; - numberOfPanels = 0; + titlePanels = []; + nameVariables= []; + numberOfObjects = numberOfPanels + numberOfVariables + numberOfObjects; + numberOfPanels = 0; numberOfVariables = 0; - } - totalDashboards = numberOfDashboards + totalDashboards; - if (!numberOfDashboards) - console.log(`No results found\n`.green); - numberOfDashboards = 0; - }; + } + totalObjects = numberOfDashboards + totalObjects; - console.log(colors.green.bold(`──────── Have been found ${numberOfObjects} results in ${totalDashboards} dashboards ────────\n`)); + if (!numberOfDashboards) + console.log(`No results found\n`.gray); - if (!response) { - console.log(`${error}The server don't exists`); - process.exit(1); - } + console.log(colors.white.bold(`🔎 Searching in alerts...\n`)); - process.exit(); + response = await fetch(`${urlAlerts}${AllOrganizations[x].id}`, { + method: 'GET', + headers: { + Accept: 'application/json', + Authorization: credentials + }, + redirect: 'manual' + }); + let allAlerts = await response.json(); + + isFound = isFoundSomething = false; + + for (const alert of allAlerts) + for (const data of alert.data) + if (data?.model?.rawSql) { + isFound = regexRawSQL.test(data.model.rawSql); + if (isFound) { + if (alert?.title) + if (alert.title == ' ') + titleAlerts.push(`(null)`.italic); + else { + const linkUrl = `${grafanaUrl}/alerting/${alert.uid}/edit?orgId=${AllOrganizations[x].id}`; + console.log((linkUrl).yellow.underline, alert.title, '\n'); + numberOfObjects++; + totalObjects++; + } + else + titleAlerts.push(`(undefined)`.italic); + isFoundSomething = true; + } + } + + if (!isFoundSomething) + console.log(`No results found\n`.gray); + }; + + console.log(colors.green.bold(`──────── Have been found ${numberOfObjects} similarities in ${totalObjects} objects ────────\n`)); + + if (!response) { + console.log(`${error}The server don't exists`); + process.exit(1); + } + + process.exit(); } main(); \ No newline at end of file diff --git a/package.json b/package.json index 3bce800..aa47483 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grafana-find", - "version": "1.0.3", + "version": "1.0.4", "author": "Verdnatura Levante SL", "description": "Grafana Find Tool", "license": "GPL-3.0",