Skip to content

Commit

Permalink
Merge of #4197
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Sep 25, 2023
2 parents f8ec82d + af792d7 commit c0651e1
Show file tree
Hide file tree
Showing 10 changed files with 939 additions and 43 deletions.
25 changes: 13 additions & 12 deletions libs/wingsdk/src/target-tf-gcp/app.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Construct } from "constructs";
import { Bucket } from "./bucket";
import { Function } from "./function";
import { GoogleProvider } from "../.gen/providers/google/provider";
import { RandomProvider } from "../.gen/providers/random/provider";
import { BUCKET_FQN } from "../cloud";
import { BUCKET_FQN, FUNCTION_FQN } from "../cloud";
import { AppProps as CdktfAppProps } from "../core";
import { CdktfApp } from "../shared-tf/app";

Expand All @@ -16,10 +17,10 @@ export interface AppProps extends CdktfAppProps {
readonly projectId: string;

/**
* The Google Cloud storage location, used for all storage resources.
* @see https://cloud.google.com/storage/docs/locations
* The Google Cloud region, used for all resources.
* @see https://cloud.google.com/functions/docs/locations
*/
readonly storageLocation: string;
readonly region: string;
}

/**
Expand All @@ -33,9 +34,9 @@ export class App extends CdktfApp {
public readonly projectId: string;

/**
* The Google Cloud storage location, used for all storage resources.
* The Google Cloud region, used for all resources.
*/
public readonly storageLocation: string;
public readonly region: string;

public readonly _target = "tf-gcp";

Expand All @@ -51,18 +52,16 @@ export class App extends CdktfApp {
);
}

this.storageLocation =
props.storageLocation ?? process.env.GOOGLE_STORAGE_LOCATION;
// Using env variable for location is work around until we are
// able to implement https://github.com/winglang/wing/issues/493 (policy as infrastructure)
if (this.storageLocation === undefined) {
this.region = props.region ?? process.env.GOOGLE_REGION;
if (this.region === undefined) {
throw new Error(
"A Google Cloud storage location must be specified through the GOOGLE_STORAGE_LOCATION environment variable."
"A Google Cloud region must be specified through the GOOGLE_REGION environment variable."
);
}

new GoogleProvider(this, "google", {
project: this.projectId,
region: this.region,
});
new RandomProvider(this, "random");

Expand All @@ -85,6 +84,8 @@ export class App extends CdktfApp {
switch (fqn) {
case BUCKET_FQN:
return new Bucket(scope, id, args[0]);
case FUNCTION_FQN:
return new Function(scope, id, args[0], args[1]);
}

return undefined;
Expand Down
4 changes: 2 additions & 2 deletions libs/wingsdk/src/target-tf-gcp/bucket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ const BUCKET_NAME_OPTS: NameOptions = {
* @inflight `@winglang/sdk.cloud.IBucketClient`
*/
export class Bucket extends cloud.Bucket {
private readonly bucket: StorageBucket;
public readonly bucket: StorageBucket;

constructor(scope: Construct, id: string, props: cloud.BucketProps = {}) {
super(scope, id, props);
Expand All @@ -57,7 +57,7 @@ export class Bucket extends cloud.Bucket {

this.bucket = new StorageBucket(this, "Default", {
name: bucketName + "-" + randomId.hex,
location: (App.of(this) as App).storageLocation,
location: (App.of(this) as App).region,
// recommended by GCP: https://cloud.google.com/storage/docs/uniform-bucket-level-access#should-you-use
uniformBucketLevelAccess: true,
publicAccessPrevention: props.public ? "inherited" : "enforced",
Expand Down
114 changes: 114 additions & 0 deletions libs/wingsdk/src/target-tf-gcp/function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { resolve } from "path";
import { AssetType, TerraformAsset } from "cdktf";
import { Construct } from "constructs";
import { App } from "./app";
import { Bucket } from "./bucket";
import { CloudfunctionsFunction } from "../.gen/providers/google/cloudfunctions-function";
import { StorageBucketObject } from "../.gen/providers/google/storage-bucket-object";
import * as cloud from "../cloud";
import { createBundle } from "../shared/bundling";
import {
CaseConventions,
NameOptions,
ResourceNames,
} from "../shared/resource-names";
import { IInflightHost } from "../std";

const FUNCTION_NAME_OPTS: NameOptions = {
maxLen: 32,
disallowedRegex: /[^a-z0-9]+/g,
case: CaseConventions.LOWERCASE,
};

/**
* GCP implementation of `cloud.Function`.
*
* @inflight `@winglang/wingsdk.cloud.IFunctionClient`
*/

export class Function extends cloud.Function {
private readonly function: CloudfunctionsFunction;

constructor(
scope: Construct,
id: string,
inflight: cloud.IFunctionHandler,
props: cloud.FunctionProps = {}
) {
super(scope, id, inflight, props);

// app is a property of the `cloud.Function` class
const app = App.of(this) as App;

// bundled code is guaranteed to be in a fresh directory
const bundle = createBundle(this.entrypoint);

// Create Cloud Function executable
const asset = new TerraformAsset(this, "Asset", {
path: resolve(bundle.directory),
type: AssetType.ARCHIVE,
});

// memory limits must be between 128 and 8192 MB
if (props?.memory && (props.memory < 128 || props.memory > 8192)) {
throw new Error(
"Memory must be between 128 and 8192 MB for GCP Cloud Functions"
);
}

// timeout must be between 1 and 540 seconds
if (
props?.timeout &&
(props.timeout.seconds < 1 || props.timeout.seconds > 540)
) {
throw new Error(
"Timeout must be between 1 and 540 seconds for GCP Cloud Functions"
);
}

// create a bucket to store the function executable
const FunctionBucket = new Bucket(this, "FunctionBucket");

// put the executable in the bucket as an object
const FunctionObjectBucket = new StorageBucketObject(
this,
"FunctionObjectBucket",
{
name: "objects",
bucket: FunctionBucket.bucket.name,
source: asset.path,
}
);

// create the cloud function
this.function = new CloudfunctionsFunction(this, "DefaultFunction", {
name: ResourceNames.generateName(this, FUNCTION_NAME_OPTS),
description: "This function was created by Wing",
project: app.projectId,
region: app.region,
runtime: "nodejs16",
availableMemoryMb: props.memory ?? 128,
sourceArchiveBucket: FunctionBucket.bucket.name,
sourceArchiveObject: FunctionObjectBucket.name,
entryPoint: "handler",
triggerHttp: true,
timeout: props.timeout?.seconds ?? 60,
environmentVariables: props.env ?? {},
});
}

public get functionName(): string {
return this.function.name;
}

// TODO: implement with https://github.com/winglang/wing/issues/1282
public _toInflight(): string {
throw new Error(
"cloud.Function cannot be used as an Inflight resource on GCP yet"
);
}

public bind(_host: IInflightHost, _ops: string[]): void {
throw new Error("Method not implemented.");
}
}
1 change: 1 addition & 0 deletions libs/wingsdk/src/target-tf-gcp/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from "./app";
export * from "./bucket";
export * from "./function";
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ exports[`bucket is public 1`] = `
"resource": {
"google_storage_bucket": {
"my_bucket": {
"location": "US",
"location": "us-central1",
"name": "my_bucket-\${random_id.my_bucket_Id_50F73A6B.hex}",
"public_access_prevention": "inherited",
"uniform_bucket_level_access": true,
Expand Down Expand Up @@ -130,7 +130,7 @@ exports[`bucket with two preflight files 1`] = `
"resource": {
"google_storage_bucket": {
"my_bucket": {
"location": "US",
"location": "us-central1",
"name": "my_bucket-\${random_id.my_bucket_Id_50F73A6B.hex}",
"public_access_prevention": "enforced",
"uniform_bucket_level_access": true,
Expand Down Expand Up @@ -268,7 +268,7 @@ exports[`bucket with two preflight objects 1`] = `
"resource": {
"google_storage_bucket": {
"my_bucket": {
"location": "US",
"location": "us-central1",
"name": "my_bucket-\${random_id.my_bucket_Id_50F73A6B.hex}",
"public_access_prevention": "enforced",
"uniform_bucket_level_access": true,
Expand Down Expand Up @@ -406,7 +406,7 @@ exports[`create a bucket 1`] = `
"resource": {
"google_storage_bucket": {
"my_bucket": {
"location": "US",
"location": "us-central1",
"name": "my_bucket-\${random_id.my_bucket_Id_50F73A6B.hex}",
"public_access_prevention": "enforced",
"uniform_bucket_level_access": true,
Expand Down Expand Up @@ -516,13 +516,13 @@ exports[`two buckets 1`] = `
"resource": {
"google_storage_bucket": {
"my_bucket1": {
"location": "US",
"location": "us-central1",
"name": "my_bucket1-\${random_id.my_bucket1_Id_D79FE240.hex}",
"public_access_prevention": "enforced",
"uniform_bucket_level_access": true,
},
"my_bucket2": {
"location": "US",
"location": "us-central1",
"name": "my_bucket2-\${random_id.my_bucket2_Id_0AB96F49.hex}",
"public_access_prevention": "enforced",
"uniform_bucket_level_access": true,
Expand Down
Loading

0 comments on commit c0651e1

Please sign in to comment.