Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: move pulumi interactions out of top-level example #407

Merged
merged 5 commits into from
Aug 11, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.DS_Store
node_modules
.eslintcache
.idea

.yarn/*
!.yarn/patches
Expand Down
3 changes: 2 additions & 1 deletion packages/events-example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"@pulumi/awsx": "^0.40.0",
"@pulumi/pulumi": "^3.36.0",
"@theniledev/js": "^0.13.1",
"@theniledev/react": "^0.13.1",
"@types/node-fetch": "^2.6.2",
"node-fetch": "^3.2.10"
},
Expand All @@ -24,7 +25,7 @@
"eslint": "^8.21.0",
"eslint-config-oclif": "^4",
"eslint-config-oclif-typescript": "^1.0.2",
"globby": "^13",
"globby": "^11",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was weird. I was getting an error with the ES6 import styles between oclif and globby. Had to downgrade to fix. Known issue with globby.

Error:

(node:84782) [ERR_REQUIRE_ESM] Error Plugin: @theniledev/events-example [ERR_REQUIRE_ESM]: require() of ES Module /Users/sdelamater/work/nile-js/packages/events-example/node_modules/globby/index.js from /Users/sdelamater/work/nile-js/node_modules/@oclif/core/lib/config/plugin.js not supported.
Instead change the require of index.js in /Users/sdelamater/work/nile-js/node_modules/@oclif/core/lib/config/plugin.js to a dynamic import() which is available in all CommonJS modules.
module: @oclif/core@1.13.0

"oclif": "^3",
"shx": "^0.3.3",
"ts-node": "^10.2.1",
Expand Down
25 changes: 18 additions & 7 deletions packages/events-example/src/commands/reconcile/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
PulumiFn,
} from '@pulumi/pulumi/automation';

import { pulumiProgram } from '../../pulumiS3';
import { pulumiProgramGenerator } from '../../pulumiS3';
import PulumiAwsDeployment from '../../deployments/pulumi';

export default class Reconcile extends Command {
static enableJsonFlag = true;
Expand Down Expand Up @@ -38,9 +39,11 @@ export default class Reconcile extends Command {
status: Flags.boolean({ char: 's', description: 'status', default: false }),
};

localWorkspace!: LocalWorkspace;
//localWorkspace!: LocalWorkspace;
nile!: NileApi;
deployment!: PulumiAwsDeployment;

/*
async waitOnStack(stack: Stack): Promise<void> {
let stackInfo;
do {
Expand Down Expand Up @@ -98,6 +101,7 @@ export default class Reconcile extends Command {
this.debug(stacks);
return stacks;
}
*/

async loadInstances(
organization: string,
Expand All @@ -123,10 +127,17 @@ export default class Reconcile extends Command {
const { flags } = await this.parse(Reconcile);

// pulumi setup
/*
this.localWorkspace = await LocalWorkspace.create({
projectSettings: { name: flags.workspace, runtime: 'nodejs' },
});
this.localWorkspace.installPlugin('aws', 'v4.0.0');
*/
this.deployment = await PulumiAwsDeployment.create(
"tryhard",
{ projectSettings: { name: flags.workspace, runtime: 'nodejs' } },
pulumiProgramGenerator
)

// nile setup
this.nile = Nile({ basePath: flags.basePath, workspace: flags.workspace });
Expand All @@ -144,7 +155,7 @@ export default class Reconcile extends Command {
this.nile.authToken = token?.token;

// load our data
const stacks = await this.loadPulumiStacks();
const stacks = await this.deployment.loadStacks();
const instances = await this.loadInstances(
flags.organization,
flags.entity
Expand All @@ -163,14 +174,14 @@ export default class Reconcile extends Command {
// destroy any stacks that shouldnt exist
for (const id of Object.keys(stacks)) {
if (!instances[id]) {
this.destroyStack(id);
this.deployment.destroyStack(id);
}
}

// create any stacks that should exist
for (const id of Object.keys(instances)) {
if (!stacks[id]) {
this.createStack(instances[id]);
this.deployment.createStack(instances[id]);
}
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@norwood - I'm seeing some inconsistencies with instances that get created then deleted before running this script. Still debugging synchronization issues.


Expand All @@ -179,8 +190,8 @@ export default class Reconcile extends Command {
this.log(JSON.stringify(e, null, 2));
if (e.after) {
const out = await (e.after.deleted
? this.destroyStack(e.after.id)
: this.createStack(e.after));
? this.deployment.destroyStack(e.after.id)
: this.deployment.createStack(e.after));

this.debug(out);
}
Expand Down
94 changes: 94 additions & 0 deletions packages/events-example/src/deployments/pulumi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@

import { CliUx } from "@oclif/core";
import {
DestroyResult,
InlineProgramArgs,
LocalWorkspace,
LocalWorkspaceOptions,
PulumiFn,
Stack,
StackSummary,
UpResult
} from "@pulumi/pulumi/automation";
import { Instance } from "@theniledev/js";

export interface PulumiFnGen {
(something: any): PulumiFn
}

export default class PulumiAwsDeployment {

projectName!: string;
private workspace!: LocalWorkspace;
private programGen!: PulumiFnGen;

static async create(projectName: string, opts: LocalWorkspaceOptions, program: PulumiFnGen): Promise<PulumiAwsDeployment> {
const ws = await LocalWorkspace.create(opts);
ws.installPlugin('aws', 'v4.0.0');
return new PulumiAwsDeployment(projectName, ws, program);
};

constructor(projectName: string, workspace: LocalWorkspace, programGenerator: PulumiFnGen) {
this.projectName = projectName;
this.workspace = workspace;
this.programGen = programGenerator;
}

async loadStacks(): Promise<{[key: string]: StackSummary}> {
const stacks = await (
await this.workspace.listStacks()
).reduce(async (accP, stack) => {
const acc = await accP;
const fullStack = await this.getStack(stack.name, this.programGen({}));
const info = await fullStack.info();
if (info?.kind != 'destroy') {
acc[stack.name] = stack;
console.debug('adding stack', stack);
}
return acc;
}, Promise.resolve({} as { [key: string]: StackSummary }));
console.debug(stacks);
return stacks;
}

private async getStack(stackName: string, program: PulumiFn): Promise<Stack> {
const args: InlineProgramArgs = {
stackName,
projectName: this.projectName,
program,
};
const stack = await LocalWorkspace.createOrSelectStack(args);
await stack.setConfig('aws:region', { value: 'us-west-2' }); // TODO: generalize AWS config.
return stack;
}

async createStack(instance: Instance): Promise<UpResult> {
const stack = await this.getStack(instance.id, this.programGen(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 waitOnStack(stack: Stack): Promise<void> {
let stackInfo;
do {
stackInfo = await stack.info();
console.debug(stackInfo);
} while (stackInfo != undefined && stackInfo?.result !== 'succeeded');
}

async destroyStack(id: string): Promise<DestroyResult> {
const stack = await this.getStack(id, this.programGen({}));
await this.waitOnStack(stack);
try {
CliUx.ux.action.start(`Destroying a stack id=${id}`);
return await stack.destroy({ onOutput: console.log });
} finally {
CliUx.ux.action.stop();
}
}
}
5 changes: 4 additions & 1 deletion packages/events-example/src/pulumiS3.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import * as aws from '@pulumi/aws';
import { PolicyDocument } from '@pulumi/aws/iam';
import { PulumiFn } from '@pulumi/pulumi/automation';
import { PulumiFnGen } from './deployments/pulumi';

export const pulumiProgram = (something: any) => {

export const pulumiProgramGenerator: PulumiFnGen = (something: any): PulumiFn => {
return async () => {
// Create a bucket and expose a website index document.
const siteBucket = new aws.s3.Bucket('s3-website-bucket', {
Expand Down
20 changes: 2 additions & 18 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -9746,7 +9746,7 @@ fast-glob@^2.2.6:
merge2 "^1.2.3"
micromatch "^3.1.10"

fast-glob@^3.0.3, fast-glob@^3.2.11, fast-glob@^3.2.9:
fast-glob@^3.0.3, fast-glob@^3.2.9:
version "3.2.11"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.11.tgz#a1172ad95ceb8a16e20caa5c5e56480e5129c1d9"
integrity sha512-xrO3+1bxSo3ZVHAnqzyuewYT6aMFHRAd4Kcs92MAonjwQZLsK9d0SF1IyQ3k5PoirxTW0Oe/RqFgMQ6TcNE5Ew==
Expand Down Expand Up @@ -10629,7 +10629,7 @@ globby@^10.0.1:
merge2 "^1.2.3"
slash "^3.0.0"

globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.1.0:
globby@^11, globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
Expand All @@ -10641,17 +10641,6 @@ globby@^11.0.1, globby@^11.0.2, globby@^11.0.3, globby@^11.1.0:
merge2 "^1.4.1"
slash "^3.0.0"

globby@^13:
version "13.1.2"
resolved "https://registry.npmjs.org/globby/-/globby-13.1.2.tgz"
integrity sha512-LKSDZXToac40u8Q1PQtZihbNdTYSNMuWe+K5l+oa6KgDzSvVrHXlJy40hUP522RjAIoNLJYBJi7ow+rbFpIhHQ==
dependencies:
dir-glob "^3.0.1"
fast-glob "^3.2.11"
ignore "^5.2.0"
merge2 "^1.4.1"
slash "^4.0.0"

globby@^9.2.0:
version "9.2.0"
resolved "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz"
Expand Down Expand Up @@ -16943,11 +16932,6 @@ slash@^3.0.0:
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==

slash@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz"
integrity sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==

slice-ansi@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz"
Expand Down