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

Add tracking #18

Merged
merged 2 commits into from
Jun 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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 .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ jobs:
npm run rain
env:
CDK_RELEASE_VERSION: "${{ steps.release.outputs.major }}.${{ steps.release.outputs.minor }}.${{ steps.release.outputs.patch }}"
CDK_ENVIRONMENT: prod

- name: Archive release assets
if: ${{ steps.release.outputs.release_created }}
Expand Down
12 changes: 7 additions & 5 deletions cdk.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@
},
"context": {
"GardenDevClusterStackID": "garden-dev-cluster",

"EKSClusterName": "garden-dev-cluster",
"EKSNodeGroupMinSize": 1,
"EKSNodeGroupMaxSize": 10,

"ECRRepositories": "api,result,vote,worker",
"ECRPrefix": "garden-dev-cluster",

"IAMEKSFullAccessRole": "",
"IAMEKSFullAccessPrincipals": "",

"IngressSubdomain": "",
"IngressRoute53HostedZoneId": ""
"IngressRoute53HostedZoneId": "",
"dev": {
"SegmentAPIWriteKey": "7f9LMF7SUiOJHp1DKGGMTWAsMQVATmga"
},
"prod": {
"SegmentAPIWriteKey": "n28eGgbHFaNYAUe09O0j29hYOXhsCYj7"
}
}
}
3,217 changes: 2,831 additions & 386 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 10 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
"description": "Garden development cluster CDK and CFN quickstart, batteries included.",
"main": "src/index.ts",
"dependencies": {
"@aws-quickstart/eks-blueprints": "=1.6.0",
"@types/aws-lambda": "^8.10.114",
"aws-cdk-lib": "=2.66.1",
"@aws-quickstart/eks-blueprints": "=1.8.1",
"@segment/analytics-node": "^1.0.0-beta.26",
"@types/aws-lambda": "^8.10.115",
"aws-cdk-lib": "=2.81.0",
"aws-lambda": "^1.0.7",
"cdk": "^2.73.0-alpha.0",
"cdk-assets": "^2.73.0-alpha.0",
"constructs": "=10.1.252"
"cdk": "^2.81.0-alpha.0",
"cdk-assets": "^2.81.0",
"constructs": "=10.2.39",
"hasha": "^5.2.2",
"pjson": "^1.0.9"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
Expand All @@ -25,6 +28,7 @@
"license": "MPL-2.0",
"homepage": "https://github.com/garden-io/dev-cluster",
"devDependencies": {
"@types/analytics-node": "^3.1.11",
"ts-node": "^10.9.1"
}
}
14 changes: 14 additions & 0 deletions src/constructs/garden-addon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import * as iam from "aws-cdk-lib/aws-iam";
import * as cdk from "aws-cdk-lib";
import { ECRRepositories } from "./ecr-repositories";
import { EKSCleanupLB } from "./eks-cleanuplb";
import { TrackUsage } from "./tracking";
import { GardenEKSDevCluster } from "../stacks/garden-dev-cluster";
var pjson = require("pjson");

export interface GardenAddOnProps {
readonly accountId: string
Expand Down Expand Up @@ -45,6 +47,9 @@ export class GardenAddOn implements ClusterAddOn {

// fix cluster deletion
this.addCleanupLBHack(clusterInfo)

//track usage
this.trackUsage(clusterInfo)
}

private addCleanupLBHack(clusterInfo: ClusterInfo) {
Expand All @@ -64,6 +69,15 @@ export class GardenAddOn implements ClusterAddOn {
})
}

private trackUsage(clusterInfo: ClusterInfo) {
const cluster = clusterInfo.cluster
new TrackUsage(cluster, "TrackUsage", {
account: this.props.accountId,
stackVersion: pjson.version,
parameters: this.props.parameters
})
}

private createFullAccessIAMRoleIfNeeded(clusterInfo: ClusterInfo) {
const cluster = clusterInfo.cluster
const parameters = this.props.parameters
Expand Down
69 changes: 69 additions & 0 deletions src/constructs/tracking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as path from 'path';
import { CustomResource, Stack } from 'aws-cdk-lib';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as lambdaNodejs from 'aws-cdk-lib/aws-lambda-nodejs';
import * as cr from 'aws-cdk-lib/custom-resources';
import { Construct } from 'constructs';
import * as cdk from "aws-cdk-lib";
import { PROP_ACCOUNT, PROP_SEGMENT_KEY, PROP_CF_STACK_ARN, PROP_VERSION, PROP_FULL_ACCESS_ROLE, PROP_FULL_ACCESS_PRINCIPALS, PROP_CLUSTER_NAME, PROP_ECR_PREFIX, PROP_ECR_REPO_NAMES, PROP_HOSTEDZONE_ID, PROP_MAX_NODEGROUP_SIZE, PROP_MIN_NODEGROUP_SIZE, PROP_SUBDOMAIN} from '../functions/tracking';
import { GardenEKSDevCluster} from '../stacks/garden-dev-cluster';


export const cdkEnvironment: string = process.env.CDK_ENVIRONMENT || 'dev';
interface TrackUsageProps {
stackVersion: string;
account: string;
parameters: typeof GardenEKSDevCluster.parameters;
}

export class TrackUsage extends Construct {
constructor(scope: Construct, id: string, props: TrackUsageProps) {
super(scope, id);

new CustomResource(this, 'Resource', {
serviceToken: TrackUsageProvider.getOrCreate(this),
resourceType: 'Custom::TrackUsage',
properties: {
[PROP_SEGMENT_KEY]: this.node.tryGetContext(cdkEnvironment).SegmentAPIWriteKey,
[PROP_VERSION]: props.stackVersion,
[PROP_ACCOUNT]: props.account,
[PROP_CF_STACK_ARN]: cdk.Stack.of(scope).stackId,
[PROP_FULL_ACCESS_ROLE]: props.parameters.fullAccessRole,
[PROP_FULL_ACCESS_PRINCIPALS]: props.parameters.fullAccessPrincipals,
[PROP_ECR_REPO_NAMES]: props.parameters.ecrRepoNames,
[PROP_ECR_PREFIX]: props.parameters.ecrPrefix,
[PROP_SUBDOMAIN]: props.parameters.subdomain,
[PROP_HOSTEDZONE_ID]: props.parameters.hostedZoneID,
[PROP_CLUSTER_NAME]: props.parameters.clusterName,
[PROP_MIN_NODEGROUP_SIZE]: props.parameters.minNodeGroupSize,
[PROP_MAX_NODEGROUP_SIZE]: props.parameters.maxNodeGroupSize
},
});
}
}

class TrackUsageProvider extends Construct {

/**
* Returns the singleton provider.
*/
public static getOrCreate(scope: Construct) {
const stack = Stack.of(scope);
const id = 'garden.custom-track-usage-provider';
const x = stack.node.tryFindChild(id) as TrackUsageProvider || new TrackUsageProvider(stack, id);
return x.provider.serviceToken;
}

private readonly provider: cr.Provider;

constructor(scope: Construct, id: string) {
super(scope, id);

this.provider = new cr.Provider(this, 'track-usage-provider', {
onEventHandler: new lambdaNodejs.NodejsFunction(this, 'tracking-on-event', {
runtime: lambda.Runtime.NODEJS_18_X ,
entry: path.join(__dirname, '..', 'functions', 'tracking.ts'),
}),
});
}
}
4 changes: 3 additions & 1 deletion src/functions/ecr-repositories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ export async function handler(event: AWSCDKAsyncCustomResource.OnEventRequest):

// get deleted repos
for (const repo of oldRepos.filter((r) => !newRepos.includes(r))) {
console.log(`deleting repo ${prefix}/${repo}`)
await deleteRepo(prefix, repo)
}

for (const repo of newRepos.filter((r) => !oldRepos.includes(r))) {
createRepo(prefix, repo)
console.log(`creating repo ${prefix}/${repo}`)
await createRepo(prefix, repo)
}
return {}

Expand Down
64 changes: 64 additions & 0 deletions src/functions/tracking.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import * as AWSCDKAsyncCustomResource from 'aws-cdk-lib/custom-resources/lib/provider-framework/types';
import Analytics from "@segment/analytics-node";
import hasha = require("hasha");

export const PROP_SEGMENT_KEY = "segmentApiKey"
export const PROP_VERSION = "gardenDevClusterVersion"
export const PROP_ACCOUNT = "awsAccount"
export const PROP_CF_STACK_ARN = "cloudformationStackArn"
export const PROP_FULL_ACCESS_ROLE = "iamFullAccessRole"
export const PROP_FULL_ACCESS_PRINCIPALS = "iamFullAccessPrincipals"
export const PROP_ECR_REPO_NAMES = "ecrRepoNames"
export const PROP_ECR_PREFIX = "ecrPrefix"
export const PROP_SUBDOMAIN = "subdomain"
export const PROP_HOSTEDZONE_ID = "hostedzoneID"
export const PROP_CLUSTER_NAME = "clusterName"
export const PROP_MIN_NODEGROUP_SIZE = "minNodegroupSize"
export const PROP_MAX_NODEGROUP_SIZE = "maxNodegroupSize"

export async function handler(event: AWSCDKAsyncCustomResource.OnEventRequest): Promise<AWSCDKAsyncCustomResource.OnEventResponse> {
const version: string = event.ResourceProperties[PROP_VERSION]
const accountHash: string = hasha(event.ResourceProperties[PROP_ACCOUNT],{algorithm: "sha512"})
const cfnStackArnHash: string = hasha(event.ResourceProperties[PROP_CF_STACK_ARN], {algorithm: 'sha512'}).slice(0,64)
const analytics = new Analytics({writeKey: event.ResourceProperties[PROP_SEGMENT_KEY]})
switch (event.RequestType) {
case 'Create':
analytics.track({
anonymousId: cfnStackArnHash,
event: "Installed dev-cluster",
properties: {
version: version,
accountHash: accountHash,
platform: "AWS"
},
})
await analytics.closeAndFlush()
return {}

case 'Update':
analytics.track({
anonymousId: cfnStackArnHash,
event: "Updated dev-cluster",
properties: {
version: version,
accountHash: accountHash,
platform: "AWS"
},
})
await analytics.closeAndFlush()
return {}

case 'Delete':
analytics.track({
anonymousId: cfnStackArnHash,
event: "Deleted dev-cluster",
properties: {
version: version,
accountHash: accountHash,
platform: "AWS"
},
})
await analytics.closeAndFlush()
return {}
}
}