Skip to content

Built for people who want to own their automations. Join the waitlist for an invite.

Package listing

@kody/datadog

src/core.test.ts

117 lines · 4.3 KB · TypeScript
import assert from 'node:assert/strict'
import { test } from 'node:test'
import {
	mutationPreview,
	requireConfirm,
	resolveApiHost,
	resolveApiKeySecretName,
	resolveApplicationKeySecretName,
	resolveSite,
	secretSetupUrl,
} from './core.ts'
import { createDashboard, deleteDashboard } from './dashboards.ts'
import { createIncident, deleteIncident } from './incidents.ts'
import { createMonitor, deleteMonitor, muteMonitor } from './monitors.ts'

test('secret names use datadogApiKey and datadogApplicationKey plus account labels', () => {
	assert.equal(resolveApiKeySecretName({}), 'datadogApiKey')
	assert.equal(resolveApplicationKeySecretName({}), 'datadogApplicationKey')
	assert.equal(resolveApiKeySecretName({ account: 'work' }), 'datadogApiKey-work')
	assert.equal(
		resolveApplicationKeySecretName({ account: 'work' }),
		'datadogApplicationKey-work',
	)
	assert.equal(
		resolveApiKeySecretName({ apiKeySecretName: 'datadogApiKey-staging' }),
		'datadogApiKey-staging',
	)
	assert.throws(() => resolveApiKeySecretName({ apiKeySecretName: 'otherKey' }), /datadogApiKey/)
	assert.throws(
		() => resolveApplicationKeySecretName({ applicationKeySecretName: 'otherKey' }),
		/datadogApplicationKey/,
	)
})

test('secretSetupUrl stays on the hosted secrets page with Datadog API hosts', () => {
	assert.match(secretSetupUrl('datadogApiKey'), /https:\/\/kody\.codes\/account\/secrets\/new\?name=datadogApiKey/)
	assert.match(
		secretSetupUrl('datadogApplicationKey'),
		/name=datadogApplicationKey/,
	)
	assert.match(secretSetupUrl('datadogApiKey'), /allowedHosts=api\.datadoghq\.com/)
	assert.match(secretSetupUrl('datadogApiKey-work'), /name=datadogApiKey-work/)
})

test('resolveSite maps aliases and rejects unknown orgs', () => {
	assert.equal(resolveSite({}), 'datadoghq.com')
	assert.equal(resolveSite({ site: 'eu' }), 'datadoghq.eu')
	assert.equal(resolveSite({ site: 'us3' }), 'us3.datadoghq.com')
	assert.equal(resolveApiHost({ site: 'eu' }), 'api.datadoghq.eu')
	assert.equal(resolveApiHost({ site: 'api.datadoghq.eu' }), 'api.datadoghq.eu')
	assert.throws(() => resolveSite({ site: 'kentcdodds' }), /site must be a Datadog site/)
})

test('requireConfirm blocks live mutations', () => {
	assert.throws(() => requireConfirm({}, 'delete monitor 1'), /confirm: true/)
	requireConfirm({ confirm: true }, 'delete monitor 1')
})

test('mutationPreview dryRun skips confirm', () => {
	const preview = mutationPreview(
		{ dryRun: true },
		{
			action: 'delete monitor 1',
			method: 'DELETE',
			path: '/api/v1/monitor/1',
		},
	)
	assert.equal(preview?.dryRun, true)
	assert.equal(preview?.method, 'DELETE')
	assert.equal(preview?.path, '/api/v1/monitor/1')
	assert.equal(preview?.host, 'api.datadoghq.com')
})

test('monitor/incident/dashboard dryRun does not require confirm or a network call', async () => {
	const create = await createMonitor({
		type: 'query alert',
		query: 'avg(last_5m):avg:system.cpu.user{*} > 95',
		name: 'preview',
		dryRun: true,
	})
	const mute = await muteMonitor({ monitorId: 9, dryRun: true })
	const del = await deleteMonitor({ monitorId: 9, dryRun: true })
	const incident = await createIncident({ title: 'preview', dryRun: true })
	const incidentDelete = await deleteIncident({ incidentId: 'abc', dryRun: true })
	const dashboard = await createDashboard({
		title: 'preview',
		layoutType: 'ordered',
		dryRun: true,
	})
	const dashboardDelete = await deleteDashboard({ dashboardId: 'abc-def', dryRun: true })
	assert.equal(create.dryRun, true)
	assert.equal(create.method, 'POST')
	assert.equal(create.path, '/api/v1/monitor')
	assert.equal(mute.path, '/api/v1/monitor/9/mute')
	assert.equal(del.method, 'DELETE')
	assert.equal(incident.path, '/api/v2/incidents')
	assert.equal(incidentDelete.path, '/api/v2/incidents/abc')
	assert.equal(dashboard.path, '/api/v1/dashboard')
	assert.equal(dashboardDelete.path, '/api/v1/dashboard/abc-def')
})

test('live mutations without confirm or dryRun throw', async () => {
	await assert.rejects(
		createMonitor({
			type: 'query alert',
			query: 'avg(last_5m):avg:system.cpu.user{*} > 95',
			name: 'live',
		}),
		/confirm: true/,
	)
	await assert.rejects(deleteMonitor({ monitorId: 1 }), /confirm: true/)
	await assert.rejects(createIncident({ title: 'live' }), /confirm: true/)
	await assert.rejects(
		createDashboard({ title: 'live', layoutType: 'ordered' }),
		/confirm: true/,
	)
})