Skip to content

Commit

Permalink
feature: acquire configuration from instance definition
Browse files Browse the repository at this point in the history
  • Loading branch information
scottydawg committed Aug 11, 2022
1 parent 75063a1 commit d7885fc
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 29 deletions.
5 changes: 2 additions & 3 deletions packages/events-example/src/commands/reconcile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import Nile, { Instance, NileApi } from '@theniledev/js';

import { pulumiProgram } from '../../pulumiS3';
import PulumiAwsDeployment from '../../deployments/PulumiAwsDeployment';
import { ReconciliationPlan } from './ReconciliationPlan';
import { ReconciliationPlan } from '../../model/ReconciliationPlan';

export default class Reconcile extends Command {
static enableJsonFlag = true;
Expand All @@ -29,7 +29,6 @@ export default class Reconcile extends Command {
organization: Flags.string({ description: 'an organization in your Nile workspace' }),
entity: Flags.string({ description: 'an entity type in your Nile workspace' }),
status: Flags.boolean({ char: 's', description: 'check current status of your control and data planes', default: false }),
region: Flags.string({ description: 'AWS region', default: 'us-west-2'}),
};

deployment!: PulumiAwsDeployment;
Expand All @@ -42,7 +41,7 @@ export default class Reconcile extends Command {
await this.connectNile(flags);

// pulumi setup
this.deployment = await PulumiAwsDeployment.create("nile-examples", pulumiProgram, { region: flags.region });
this.deployment = await PulumiAwsDeployment.create("nile-examples", pulumiProgram);

// load our data
const stacks = await this.deployment.loadPulumiStacks();
Expand Down
3 changes: 0 additions & 3 deletions packages/events-example/src/deployments/AWSConfig.ts

This file was deleted.

65 changes: 46 additions & 19 deletions packages/events-example/src/deployments/PulumiAwsDeployment.ts
Original file line number Diff line number Diff line change
@@ -1,49 +1,44 @@
import { CliUx } from "@oclif/core";
import { DestroyResult, InlineProgramArgs, LocalWorkspace, PulumiFn, Stack, StackSummary, UpResult } from "@pulumi/pulumi/automation";
import { ConfigMap, DestroyResult, InlineProgramArgs, LocalWorkspace, PulumiFn, Stack, StackSummary, UpdateSummary, UpResult } from "@pulumi/pulumi/automation";
import { Instance } from "@theniledev/js";
import AWSConfig from "./AWSConfig";

export interface PulumiFnGen {
(staticContent: any): PulumiFn
(instance?: Instance): PulumiFn
}

export default class PulumiAwsDeployment {

projectName!: string;
private localWorkspace!: LocalWorkspace;
private pulumiProgram: PulumiFnGen;
private awsConfig: AWSConfig;

static async create(
projectName: string,
pulumiProgram: PulumiFnGen,
awsConfig: AWSConfig,
): Promise<PulumiAwsDeployment> {
const ws = await LocalWorkspace.create({
projectSettings: { name: projectName, runtime: 'nodejs' },
});
ws.installPlugin('aws', 'v4.0.0');
return new PulumiAwsDeployment(projectName, ws, pulumiProgram, awsConfig)
return new PulumiAwsDeployment(projectName, ws, pulumiProgram)
}

constructor(
projectName: string,
localWorkspace: LocalWorkspace,
pulumiProgram: PulumiFnGen,
awsConfig: AWSConfig,
) {
this.projectName = projectName;
this.localWorkspace = localWorkspace;
this.pulumiProgram = pulumiProgram;
this.awsConfig = awsConfig;
}

async loadPulumiStacks(): Promise<{ [key: string]: StackSummary }> {
const stacks = await (
await this.localWorkspace.listStacks()
).reduce(async (accP, stack) => {
const acc = await accP;
const fullStack = await this.getStack(stack.name, this.pulumiProgram({}));
const fullStack = await this.getStack(stack.name, this.pulumiProgram());
const info = await fullStack.info();
if (info?.kind != 'destroy') {
acc[stack.name] = stack;
Expand All @@ -52,39 +47,71 @@ export default class PulumiAwsDeployment {
}, Promise.resolve({} as { [key: string]: StackSummary }));
return stacks;
}

async waitOnStack(stack: Stack): Promise<void> {
let stackInfo;
do {
stackInfo = await stack.info();
} while (stackInfo != undefined && stackInfo?.result !== 'succeeded');
}

async getStack(stackName: string, program: PulumiFn): Promise<Stack> {
console.log(`PulumiAwsDeployments.getStack ${stackName}`);

const args: InlineProgramArgs = {
stackName,
projectName: 'tryhard',
projectName: this.projectName,
program,
};
console.log('\tcreateOrSelectStat', args);
const stack = await LocalWorkspace.createOrSelectStack(args);
await stack.setConfig('aws:region', { value: this.awsConfig.region });

console.log('\tstack retrieved');
//await stack.setConfig('aws:region', { value: 'us-east-2' });
return stack;
}

async createStack(instance: Instance): Promise<UpResult> {
console.log(`createStack ${ instance.id }`);
const stack = await this.getStack(instance.id, this.pulumiProgram(instance));
await this.configureStack(stack, instance);
await this.waitOnStack(stack);

try {
CliUx.ux.action.start(`Creating a stack id=${instance.id}`);
return await stack.up({ onOutput: console.log });
} finally {
CliUx.ux.action.stop();
}
}

private async configureStack(stack: Stack, instance: Instance) {
const instanceProps = instance.properties as {[key: string]: any} | undefined;
const stackConfig = instanceProps?.config as ConfigMap ? instanceProps!.config : { "aws:region": "us-east-2" };

console.log(`Config for instance ${ instance.id }`);
console.log(stackConfig);

for (const key of Object.keys(stackConfig)) {
console.log(`setting config ${key} = ${stackConfig[key]}`);
await stack.setConfig(key, { value: `${stackConfig[key]}` });
}
}

private async waitOnStack(stack: Stack): Promise<void> {
console.log('waitOnStack');
let stackInfo;
do {
stackInfo = await stack.info();
console.log(stackInfo);
} while (this.isUnresolved(stackInfo));
}

private isUnresolved(stackInfo: UpdateSummary | undefined): boolean {
return stackInfo != undefined && !(
stackInfo?.result == 'succeeded' ||
stackInfo?.result == 'failed'
)
}

async destroyStack(id: string): Promise<DestroyResult> {
const stack = await this.getStack(id, this.pulumiProgram({}));
console.log(`destroyStack ${id}`);
const stack = await this.getStack(id, this.pulumiProgram());
await this.waitOnStack(stack);
console.log('proceeding with destroy...');
try {
CliUx.ux.action.start(`Destroying a stack id=${id}`);
return await stack.destroy({ onOutput: console.log });
Expand Down
14 changes: 10 additions & 4 deletions packages/events-example/src/pulumiS3.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as aws from '@pulumi/aws';
import { PolicyDocument } from '@pulumi/aws/iam';
import { Instance } from "@theniledev/js";

export const pulumiProgram = (something: any) => {
export const pulumiProgram = (instance?: Instance) => {
return async () => {
// Create a bucket and expose a website index document.
const siteBucket = new aws.s3.Bucket('s3-website-bucket', {
Expand All @@ -10,12 +11,17 @@ export const pulumiProgram = (something: any) => {
},
});

const instanceProps = instance?.properties as {[key: string]: any};
const greeting = instanceProps?.greeting || "Hello, world!";
const indexContent = `<html><head>
<title>Hello S3</title><meta charset="UTF-8">
</head>
<body><p>Hello, world!</p><p>Made with ❤️ with <a href="https://pulumi.com">Pulumi</a></p>
<p>deployed with nile</p>
<p>${JSON.stringify(something)}</p>
<body>
<h1>${greeting}</h1>
<p>Made with ❤️ with <a href="https://pulumi.com">Pulumi</a></p>
<p>Deployed with nile</p>
<h2>Instance Details</h2>
<p>${JSON.stringify(instance, null, 2)}</p>
</body></html>
`;

Expand Down

0 comments on commit d7885fc

Please sign in to comment.