Hi, Hello, I am trying to create a dashboard with ...
# general
d
Hi, Hello, I am trying to create a dashboard with grafana using pulumi, but when I deploy the following code I get an error:
Copy code
return new grafana.DataSource(dataSourceName, {
			type: 'cloudwatch',
			orgId: workspace.id.apply(id => id),
			jsonDataEncoded:  dataEncoded,
			secureJsonDataEncoded: JSON.stringify(secureData),
		}, {
			provider: this.provider
		});
this is the error: "error: Resource type 'grafanaindex/dataSourceDataSource' not found" Please consider that I am using the library that the official Pulumi website says it's: import * as grafana from '@lbrlabs/pulumi-grafana'; Help me please 🙏
r
@many-telephone-49025 can you help here?
e
Is
this.provider
a grafana provider object?
m
@dazzling-greece-45968 can you show the
Provider
resource code too? What Grafana version do you use?
d
Hi, i use AWS Grafana v9.4, and this is mi complete code:
Copy code
import * as grafana from '@lbrlabs/pulumi-grafana';
import { Provider, iam, grafana as grafanaPL } from '@pulumi/aws';
import { interpolate } from '@pulumi/pulumi';

export class GrafanaCreator {
	private role: iam.Role;
	private provider: Provider;
	private providerGrafana: grafana.Provider;

	constructor(role: iam.Role, provider: Provider){
		this.role = role;
		this.provider = provider;
	}

	createWorkSpace(workSpaceName: string, roleAssociationName: string): grafanaPL.Workspace{
		const workspace = new grafanaPL.Workspace(workSpaceName, {
			name: workSpaceName,
			accountAccessType: 'CURRENT_ACCOUNT',
			authenticationProviders: ['AWS_SSO'],
			permissionType: 'SERVICE_MANAGED',
			roleArn: this.role.arn.apply((arn) => arn),
			dataSources: ['CLOUDWATCH'],
			notificationDestinations: ['SNS']
		}, {
			provider: this.provider,
			dependsOn: [this.role]
		});

		new grafanaPL.RoleAssociation(roleAssociationName, {
			role: 'ADMIN',
			userIds: [
				'8458d478-1031-70ca-e65c-383077b38f9d', // Gabriel
				'04d8b408-1081-70f2-277c-9b2809365393', // Moises
				'44f8b4b8-2061-7086-7b9f-877f0144da72', // Alvaro
				'b4088498-80a1-703c-f5a2-3350856367e5'  // Manuel
			],
			workspaceId: workspace.id.apply(id => id),
		}, {
			provider: this.provider,
			dependsOn: [workspace]
		});

		return workspace;
	}

	createProvider(providerName: string, workspace: grafanaPL.Workspace){

		this.providerGrafana = new grafana.Provider(providerName, {
			auth: interpolate`ec2_iam_role`,
			url: interpolate`https://${workspace.endpoint}`,

		});
	}

	createDashboard(dashBoardName: string, dataSource:  grafana.DataSource){
		const report = {
			'title': 'GaboGTH Dashboard',
			'timezone': 'browser',
			'schemaVersion': 16,
			'panels': [
				{
					'type': 'graph',
					'title': 'Panel Title 1',
					'targets': [
						{
							'refId': 'A',
							'region': 'us-east-1', // Specify the region
							'namespace': 'AWS/EC2',
							'metricName': 'CPUUtilization',
							'statistics': ['Average'],
							'period': '300',
							'datasource': `${dataSource.name.apply(name => name)}`
						}
					],
					// Add more panel settings here as needed
				},
			],
		};
		return new grafana.Dashboard(dashBoardName, {
			configJson: JSON.stringify(report),
		}, {
			provider: this.provider,
			dependsOn: [dataSource]
		});
	}

	createDataSourceCloudWatch(dataSourceName: string, workspace: grafanaPL.Workspace): grafana.DataSource{
		const dataEncoded = JSON.stringify({
			authType: 'ec2_iam_role',
			customMetricsNamespaces: 'MonitoringDMS',
			defaultRegion: 'us-east-1',
			assumeRoleArn: ''
		});

		console.log('dataEncoded: ', dataEncoded);

		return new grafana.DataSource(dataSourceName, {
			type: 'cloudwatch',
			orgId: workspace.id.apply(id => id),
			jsonDataEncoded:  dataEncoded,
			secureJsonDataEncoded: JSON.stringify({
				accessKey: '',
				secretKey: ''
			}),
			url: interpolate`https://${workspace.endpoint}/datasources`
		}, {
			provider: this.providerGrafana
		});
	}
}
thanks a lot
e
That still doesn't show what
this.provider
is. What provider are you passing to the
GrafanaCreator(role, provider)
constructor?
d
a oks, srry, i create the role:
Copy code
const roleGrafana = this.createRoleGrafana(roleGrafanaName);
and the this.createRoleGrafana call this function
Copy code
private createRoleGrafana(rolName: string): Role {
		const roleName = rolName;
		const roleCreator = new RoleCreator(this.provider);
		return roleCreator.createRoleGrafana(roleName);
	}
and RoleCreator object:
Copy code
import { Provider, iam } from '@pulumi/aws';

import { Role } from '@pulumi/aws/iam';
import { getProject } from '@pulumi/pulumi';
import { getTags } from './tags';

export class RoleCreator {
	private provider: Provider;

	constructor(provider: Provider) {
		this.provider = provider;
	}

	private attachPolicyToRole(role: Role, policyKey: string, policy: string, description: string): void {
		const policyName = `${policyKey}-policy`;
		const iamPolicy = new iam.Policy(policyName, {
			path: '/',
			description,
			policy,
			name: policyName,
			tags: getTags()
		},
		{
			provider: this.provider,
			dependsOn: [role]
		});

		new iam.RolePolicyAttachment(`${policyName}-attachment`, {
			role: role.name,
			policyArn: iamPolicy.arn,
		},
		{
			provider: this.provider,
			dependsOn: [role]
		});
	}

	private getNetworkPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [
				{
					Effect: 'Allow',
					Action: [
						'ec2:DescribeNetworkInterfaces',
						'ec2:CreateNetworkInterface',
						'ec2:DeleteNetworkInterface',
						'ec2:DescribeInstances',
						'ec2:AttachNetworkInterface'
					],
					Resource: ['*']
				}
			]
		});
	}

	private getSecretPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [
				{
					Effect: 'Allow',
					Action: [
						'secretsmanager:GetSecretValue',
						'secretsmanager:DescribeSecret',
						'secretsmanager:ListSecrets',
						'secretsmanager:ListSecretVersionIds',
						'secretsmanager:PutSecretValue',
						'secretsmanager:CreateSecret',
						'secretsmanager:UpdateSecret',
						'secretsmanager:DeleteSecret'
					],
					Resource: ['*']
				}
			]
		});
	}

	private getLoggingPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [
				{
					Effect: 'Allow',
					Action: [
						'logs:CreateLogGroup',
						'logs:CreateLogStream',
						'logs:PutLogEvents',
					],
					Resource: ['arn:aws:logs:*:*:*']
				}
			]
		});
	}

	private getDmsPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [
				{
					Effect: 'Allow',
					Action: [
						'dms:DescribeTableStatistics',
						'sts:AssumeRole'
					],
					Resource: ['*']
				}
			]
		});
	}

	private getDynamoDBPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [
				{
					Effect: 'Allow',
					Action: [
						'dynamodb:*'
					],
					Resource: ['*']
				}
			]
		});
	}

	private getMetricPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [
				{
					Effect: 'Allow',
					Action: [
						'cloudwatch:PutMetricData'
					],
					Resource: ['*']
				}
			]
		});
	}

	private getSnsPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [
				{
					Effect: 'Allow',
					Action: [
						'sns:Publish'
					],
					Resource: ['*']
				}
			]
		});
	}

	private getOmopPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [
				{
					Effect: 'Allow',
					Principal: {
						AWS: ['arn:aws:iam::448645697317:role/dms_role_omnichannel'],
						Service: 'lambda.amazonaws.com'
					},
					Action: 'sts:AssumeRole'
				}
			]
		});
	}

	private getGrafanaPolicy(): string {
		return JSON.stringify({
			Version: '2012-10-17',
			Statement: [{
				Effect: 'Allow',
				Principal: {
					Service: 'grafana.amazonaws.com',
				},
				Action: 'sts:AssumeRole'
			}]
		});
	}

	private addPoliciesToRole(role: Role): void {
		const policyForLogging = this.getLoggingPolicy();
		const policyForDms = this.getDmsPolicy();
		const policyForMetrics = this.getMetricPolicy();
		const policyForSecret = this.getSecretPolicy();
		const policyForDynamoDB = this.getDynamoDBPolicy();
		const policyForNetwork = this.getNetworkPolicy();
		this.attachPolicyToRole(role, `${getProject()}-logging`, policyForLogging, 'Logging policy for the monitorDMS');
		this.attachPolicyToRole(role, `${getProject()}-metrics`, policyForMetrics, 'Metrics policy for the monitorDMS');
		this.attachPolicyToRole(role, `${getProject()}-secret`, policyForSecret, 'Secrets policy for the monitorDMS');
		this.attachPolicyToRole(role, `${getProject()}-dms`, policyForDms, 'DMS policy for the monitorDMS');
		this.attachPolicyToRole(role, `${getProject()}-dynamodb`, policyForDynamoDB, 'DynamoDB policy for the monitorDMS');
		this.attachPolicyToRole(role, `${getProject()}-network`, policyForNetwork, 'Network policy for the monitorDMS');
	}

	private addPoliciesToRoleGrafana(role: Role): void {
		const policyForSns = this.getSnsPolicy();
		new iam.RolePolicyAttachment('policyAmazonGrafanaCloudWatchAccess', {
			policyArn: 'arn:aws:iam::aws:policy/service-role/AmazonGrafanaCloudWatchAccess',
			role: role.name,
		},
		{
			provider: this.provider,
			dependsOn: [role]
		});
		new iam.RolePolicyAttachment('policyCloudWatchReadOnlyAccess', {
			policyArn: 'arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess',
			role: role.name,
		},
		{
			provider: this.provider,
			dependsOn: [role]
		});
		this.attachPolicyToRole(role, `${getProject()}-sns`, policyForSns, 'SNS policy for the monitorDMS');
	}

	public createRole(roleName: string): iam.Role {
		const role = new iam.Role(
			roleName,
			{
				name: roleName,
				assumeRolePolicy: this.getOmopPolicy(),
				tags: getTags(),
			},
			{
				provider: this.provider
			}
		);

		this.addPoliciesToRole(role);

		return role;
	}

	public createRoleGrafana(roleName: string): iam.Role {
		const role = new iam.Role(roleName, {
			name: roleName,
			assumeRolePolicy: this.getGrafanaPolicy(),
			tags: getTags(),
		}, {
			provider: this.provider
		});
		this.addPoliciesToRoleGrafana(role);
		return role;
	}
}
Thanksss!!!!
e
Ok that still doesn't show what the provider object is but I strongly suspect given all of that that it's an aws provider. You can't pass an aws provider as the provider to use for a grafana resource. This is probably just a simple fix up of using
this.providerGrafana
instead of
this.provider
for all the resources inside
GrafanaCreator
though.