@studion/infra-code-blocks
Version:
Studion common infra components
154 lines (153 loc) • 6.27 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Grafana = void 0;
const pulumi = require("@pulumi/pulumi");
const grafana = require("@pulumiverse/grafana");
const merge_with_defaults_1 = require("../../shared/merge-with-defaults");
const plugin_ready_1 = require("./plugin-ready");
const REQUIRED_ACCESS_POLICY_SCOPES = [
'accesspolicies:read',
'accesspolicies:write',
'accesspolicies:delete',
'datasources:read',
'datasources:write',
'datasources:delete',
'stacks:read',
'stack-dashboards:read',
'stack-dashboards:write',
'stack-dashboards:delete',
'stack-plugins:read',
'stack-plugins:write',
'stack-plugins:delete',
];
const defaults = {
serviceAccountTokenRotation: {
secondsToLive: 7_776_000, // 90 days
earlyRotationWindowSeconds: 604_800, // 7 days
},
accessPolicyTokenRotation: {
expireAfter: '2160h', // 90 days
earlyRotationWindow: '168h', // 7 days
},
};
/**
* This component requires a grafana cloud access policy token to be created and set
* as `GRAFANA_CLOUD_ACCESS_POLICY_TOKEN` with the following scopes:
* accesspolicies:read, accesspolicies:write, accesspolicies:delete, stacks:read, stack-service-accounts:write
*/
class Grafana extends pulumi.ComponentResource {
name;
stack;
accessPolicy;
accessPolicyToken;
serviceAccount;
serviceAccountToken;
provider;
plugins;
connections;
folder;
dashboards;
constructor(name, args, opts = {}) {
super('studion:grafana:Grafana', name, {}, opts);
const argsWithDefaults = (0, merge_with_defaults_1.mergeWithDefaults)(defaults, args);
this.name = name;
this.stack = grafana.cloud.getStackOutput({
slug: argsWithDefaults.stackSlug,
});
this.accessPolicy = this.createAccessPolicy(argsWithDefaults.scopes);
this.accessPolicyToken = this.createAccessPolicyToken(argsWithDefaults.accessPolicyTokenRotation);
this.serviceAccount = this.createServiceAccount();
this.serviceAccountToken = this.createServiceAccountToken(argsWithDefaults.serviceAccountTokenRotation);
this.provider = this.createProvider();
const pluginsReadiness = [];
if (argsWithDefaults.plugins?.length) {
this.plugins = [];
let previous;
for (const pluginArgs of argsWithDefaults.plugins) {
const { plugin, readiness } = this.createPlugin(pluginArgs, {
dependsOn: previous ? [previous] : [],
});
this.plugins.push(plugin);
pluginsReadiness.push(readiness);
previous = this.plugins.at(-1);
}
}
this.connections = argsWithDefaults.connectionBuilders.map(build => {
return build({ stack: this.stack }, { parent: this, provider: this.provider, dependsOn: pluginsReadiness });
});
this.folder = this.createFolder(argsWithDefaults.folderName, this.provider);
this.dashboards = argsWithDefaults.dashboardBuilders.map(build => {
return build(this.folder, {
parent: this.folder,
provider: this.provider,
});
});
this.registerOutputs();
}
static getStackSlug(grafanaUrl) {
return new URL(grafanaUrl).hostname.split('.')[0];
}
createAccessPolicy(scopes) {
return new grafana.cloud.AccessPolicy(`${this.name}-access-policy`, {
region: this.stack.regionSlug,
name: `${this.name}-ap-icb-observability-rwd-${pulumi.getStack()}`,
scopes: [
...new Set([...REQUIRED_ACCESS_POLICY_SCOPES, ...(scopes ?? [])]),
],
realms: [{ type: 'stack', identifier: this.stack.id }],
}, { parent: this });
}
createAccessPolicyToken(rotation) {
return new grafana.cloud.AccessPolicyRotatingToken(`${this.name}-access-policy-token`, {
region: this.stack.regionSlug,
accessPolicyId: this.accessPolicy.policyId,
namePrefix: `${this.name}-apt-icb-${pulumi.getStack()}`,
expireAfter: rotation.expireAfter,
earlyRotationWindow: rotation.earlyRotationWindow,
deleteOnDestroy: true,
}, { parent: this });
}
createServiceAccount() {
return new grafana.cloud.StackServiceAccount(`${this.name}-service-account`, {
stackSlug: this.stack.slug,
name: `${this.name}-sa-icb-provisioner-${pulumi.getStack()}`,
role: 'Admin',
}, { parent: this });
}
createServiceAccountToken(rotation) {
return new grafana.cloud.StackServiceAccountRotatingToken(`${this.name}-service-account-token`, {
stackSlug: this.stack.slug,
serviceAccountId: this.serviceAccount.id,
namePrefix: `${this.name}-sat-icb-${pulumi.getStack()}`,
secondsToLive: rotation.secondsToLive,
earlyRotationWindowSeconds: rotation.earlyRotationWindowSeconds,
deleteOnDestroy: true,
}, { parent: this });
}
createFolder(folderName, provider) {
return new grafana.oss.Folder(`${this.name}-folder`, { title: folderName ?? `${this.name}-ICB-GENERATED` }, { parent: this, provider });
}
createPlugin({ name, slug, version = 'latest' }, opts) {
const plugin = new grafana.cloud.PluginInstallation(`${this.name}-${name}-plugin`, {
stackSlug: this.stack.slug,
slug,
version,
}, { ...opts, parent: this, provider: this.provider });
const readiness = new plugin_ready_1.PluginReady(`${this.name}-${name}-plugin-ready`, {
grafanaToken: this.serviceAccountToken.key,
grafanaUrl: this.stack.url,
slug,
}, {
dependsOn: [plugin],
});
return { plugin, readiness };
}
createProvider() {
return new grafana.Provider(`${this.name}-provider`, {
cloudAccessPolicyToken: this.accessPolicyToken.token,
url: this.stack.url,
auth: this.serviceAccountToken.key,
}, { parent: this });
}
}
exports.Grafana = Grafana;