Skip to content

Instantly share code, notes, and snippets.

@skorfmann
Last active July 8, 2021 13:54
Show Gist options
  • Save skorfmann/f1b9a972eadac072cc4dd84959cd96fa to your computer and use it in GitHub Desktop.
Save skorfmann/f1b9a972eadac072cc4dd84959cd96fa to your computer and use it in GitHub Desktop.
A custom data source for cdktf without generics
import { Construct, Node, } from "constructs";
import { Resource, TerraformResource, TerraformAsset, AssetType } from 'cdktf';
import * as fs from "fs";
import * as path from 'path'
import { DataExternal } from "@cdktf/provider-external"
export interface CustomDataSourceConfig {
code(input: any): Promise<any>
inputs: any;
dependsOn?: TerraformResource[];
}
export abstract class CustomDataSource extends Resource {
public readonly data: DataExternal;
constructor(scope: Construct, name: string, config: CustomDataSourceConfig) {
super(scope, name);
const { code, inputs, dependsOn } = config;
const filePath = this.writeHandler(code);
const asset = new TerraformAsset(this, 'data-source-asset', {
path: filePath,
type: AssetType.FILE,
});
this.data = new DataExternal(this, 'external', {
program: ['node', asset.path],
query: inputs,
workingDir: asset.path,
dependsOn
})
}
private writeHandler(code: (input: any) => Promise<any>) {
const name = Node.of(this).addr
const tmpWorkDir = path.join(process.cwd(), 'tmp', 'build', 'data-soruces')
fs.mkdirSync(tmpWorkDir, { recursive: true })
const filePath = path.join(tmpWorkDir, `${name}-data-source.js`)
fs.writeFileSync(filePath, `
const handler = ${code.toString()}
const stdin = process.stdin,
stdout = process.stdout,
inputChunks = [];
stdin.setEncoding('utf8');
stdin.on('data', function (chunk) {
inputChunks.push(chunk)
});
stdin.on('end', async function () {
const input = JSON.parse(inputChunks.join(''))
try {
const output = await handler(input)
stdout.write(JSON.stringify(output));
stdout.write('\\n');
} catch(e) {
console.error("error", e)
}
})
`)
return filePath;
}
}
import { Construct, } from "constructs";
import { TerraformResource } from 'cdktf';
import { CustomDataSource } from '../custom-data-source'
import { AwsEcrRepository } from "./aws-ecr-repository";
export interface CustomDockerImageConfig {
repository: AwsEcrRepository,
dependsOn?: TerraformResource[];
}
export class CustomDockerImage extends CustomDataSource {
public readonly digest: string;
public readonly url: string;
constructor(scope: Construct, name: string, config: CustomDockerImageConfig) {
const { repository } = config;
super(scope, name, {
inputs: {
repositoryUrl: repository.url,
username: repository.authorizationUser,
password: repository.authorizationPassword
},
code: async (args: any) => {
const drc = require('docker-registry-client')
return new Promise((resolve, reject) => {
var rar = drc.parseRepoAndRef(args.repositoryUrl);
var client = drc.createClientV2({
repo: rar,
insecure: false,
username: args.username,
password: args.password,
maxSchemaVersion: 2
});
var tagOrDigest = rar.tag || rar.digest;
client.getManifest({ref: tagOrDigest}, function (err:any, _manifest:any, _res:any, manifestStr:any) {
client.close();
if (err) {
reject(err)
}
resolve({sha256Digest: drc.digestFromManifestStr(manifestStr)});
});
});
},
dependsOn: config.dependsOn
});
this.digest = this.data.result('sha256Digest');
this.url = `${repository.url}@${this.digest}`
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment