{"action":"created","comment":{"url":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/comments/219646021","pull_request_review_id":157881518,"id":219646021,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIxOTY0NjAyMQ==","diff_hunk":"@@ -0,0 +1,365 @@\n+// Copyright 2016-2018, Pulumi Corporation.\n+//\n+// Licensed under the Apache License, Version 2.0 (the \"License\");\n+// you may not use this file except in compliance with the License.\n+// You may obtain a copy of the License at\n+//\n+//     http://www.apache.org/licenses/LICENSE-2.0\n+//\n+// Unless required by applicable law or agreed to in writing, software\n+// distributed under the License is distributed on an \"AS IS\" BASIS,\n+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n+// See the License for the specific language governing permissions and\n+// limitations under the License.\n+\n+import * as pulumi from \"@pulumi/pulumi\";\n+import * as crypto from \"crypto\";\n+\n+import * as arn from \"../arn\";\n+import * as iam from \"../iam\";\n+import * as utils from \"../utils\";\n+\n+import { Function as LambdaFunction, FunctionArgs } from \"./function\";\n+import * as permission from \"./permission\";\n+import * as runtime from \"./runtimes\";\n+\n+/**\n+ * Context is the shape of the context object passed to a Function callback.  For more information,\n+ * see: https://docs.aws.amazon.com/lambda/latest/dg/nodejs-prog-model-context.html\n+ */\n+export interface Context {\n+    /**\n+     * The default value is true. This property is useful only to modify the default behavior of the\n+     * callback. By default, the callback will wait until the event loop is empty before freezing\n+     * the process and returning the results to the caller. You can set this property to false to\n+     * request AWS Lambda to freeze the process soon after the callback is called, even if there are\n+     * events in the event loop. AWS Lambda will freeze the process, any state data and the events\n+     * in the event loop (any remaining events in the event loop processed when the Lambda function\n+     * is called next and if AWS Lambda chooses to use the frozen process).\n+     */\n+    callbackWaitsForEmptyEventLoop: boolean;\n+\n+    /**\n+     * Name of the Lambda function that is executing.\n+     */\n+    readonly functionName: string;\n+\n+    /**\n+     * The Lambda function version that is executing. If an alias is used to invoke the function,\n+     * then function_version will be the version the alias points to.\n+     */\n+    readonly functionVersion: string;\n+\n+    /**\n+     * The ARN used to invoke this function. It can be a function ARN or an alias ARN. An\n+     * unqualified ARN executes the $LATEST version and aliases execute the function version it is\n+     * pointing to.\n+     */\n+    readonly invokedFunctionArn: string;\n+\n+    /**\n+     * Memory limit, in MB, you configured for the Lambda function. You set the memory limit at the\n+     * time you create a Lambda function and you can change it later.\n+     */\n+    readonly memoryLimitInMB: string;\n+\n+    /**\n+     * AWS request ID associated with the request. This is the ID returned to the client that called\n+     * the invoke method.\n+     *\n+     * If AWS Lambda retries the invocation (for example, in a situation where the Lambda function\n+     * that is processing Kinesis records throws an exception), the request ID remains the same.\n+     */\n+    readonly awsRequestId: string;\n+\n+    /**\n+     * The name of the CloudWatch log group where you can find logs written by your Lambda function.\n+     */\n+    readonly logGroupName: string;\n+\n+    /**\n+     * The name of the CloudWatch log group where you can find logs written by your Lambda function.\n+     * The log stream may or may not change for each invocation of the Lambda function.\n+     *\n+     * The value is null if your Lambda function is unable to create a log stream, which can happen\n+     * if the execution role that grants necessary permissions to the Lambda function does not\n+     * include permissions for the CloudWatch actions.\n+     */\n+    readonly logStreamName: string;\n+\n+    /**\n+     * Information about the Amazon Cognito identity provider when invoked through the AWS Mobile\n+     * SDK. It can be null.\n+     */\n+    readonly identity: any;\n+\n+    /**\n+     * Information about the client application and device when invoked through the AWS Mobile SDK.\n+     * It can be null.\n+     */\n+    readonly clientContext: any;\n+\n+    /**\n+     * Returns the approximate remaining execution time (before timeout occurs) of the Lambda\n+     * function that is currently executing. The timeout is one of the Lambda function\n+     * configuration. When the timeout reaches, AWS Lambda terminates your Lambda function.\n+     *\n+     * You can use this method to check the remaining time during your function execution and take\n+     * appropriate corrective action at run time.\n+     */\n+    getRemainingTimeInMillis(): string;\n+}\n+\n+/**\n+ * EntryPoint is the signature for a serverless function that will be invoked each time the AWS\n+ * Lambda is invoked.\n+ *\n+ * This function can be synchronous or asynchronous function, though async is only supported with an\n+ * AWS Lambda runtime of 8.10 or higher.  On those runtimes a Promise can be returned, 'callback'\n+ * parameter can be ignored, and AWS will appropriately handle things. For AWS lambda pre-8.10, a\n+ * synchronous function must be provided.  The synchronous function should return nothing, and\n+ * should instead invoke 'callback' when complete.\n+ */\n+export type EntryPoint<E, R> = (event: E, context: Context, callback: (error: any, result: R) => void) => Promise<R> | void;\n+\n+/**\n+ * EntryPointFactory is the signature for a function that will be called once to produce the\n+ * serverless function that AWS Lambda will invoke.  It can be used to initialize expensive state\n+ * once that can then be used across all invocations of the Lambda (as long as the Lambda is using\n+ * the same warm node instance).\n+ */\n+export type EntryPointFactory<E, R> = () => EntryPoint<E, R>;\n+\n+/**\n+ * An EventHandler is either a JavaScript Function instance or an aws.lambda.Function that can be\n+ * used to handle an event triggered by some resource.  If just a JavaScript function is provided\n+ * the AWS Lambda will be created by calling [createFunction] on it.  If more control over the\n+ * resultant AWS Lambda is required, clients can call [createFunction] directly and pass the result\n+ * of that to any code that needs an EventHandler.\n+ */\n+export type EventHandler<E, R> = EntryPoint<E, R> | LambdaFunction;\n+\n+/**\n+ * FunctionOptions provides configuration options for the serverless Function.  It is effectively\n+ * equivalent to [aws.lambda.FunctionArgs] except with a few important differences documented at the\n+ * property level.  For example, [role] is an actual iam.Role instance, and not an ARN. Properties\n+ * like [runtime] are now optional.  And some properties (like [code]) are entirely disallowed.\n+ */\n+export type FunctionOptions<E, R> = utils.Overwrite<FunctionArgs, {\n+    /**\n+     * Not allowed when creating an aws.serverless.Function.  The [code] will be generated from the\n+     * passed in JavaScript callback.\n+     */\n+    code?: never;\n+\n+    /**\n+     * Not allowed when creating an aws.serverless.Function.  The [code] will be generated from the\n+     * passed in JavaScript callback.\n+     */\n+    handler?: never;\n+\n+    /**\n+     * The Javascript function instance to use as the entrypoint for the AWS Lambda out of.  Either\n+     * [entryPoint] or [entryPointFactory] must be provided.\n+     */\n+    entryPoint?: EntryPoint<E, R>;\n+\n+    /**\n+     * The Javascript function instance that will be called to produce the function that is the\n+     * entrypoint for the AWS Lambda. Either [entryPoint] or [entryPointFactory] must be provided.\n+     *\n+     * This form is useful when there is expensive initialization work that should only be executed\n+     * once.  The factory-function will be invoked once when the final AWS Lambda module is loaded.\n+     * It can run whatever code it needs, and will end by returning the actual function that Lambda\n+     * will call into each time the Lambda is invoked.\n+     */\n+    entryPointFactory?: EntryPointFactory<E, R>;\n+\n+    /**\n+     * A pre-created role to use for the Function. If not provided, [policies] will be used.\n+     */\n+    role?: iam.Role;\n+\n+    /**\n+     * A list of IAM policy ARNs to attach to the Function.  Will be used if [role] is not provide.\n+     * If neither [role] nor [policies] is provided, a default policy of [iam.AWSLambdaFullAccess]\n+     * will be used instead.\n+     */\n+    policies?: arn.ARN[];\n+\n+    /**\n+     * The Lambda runtime to use.  If not provided, will default to [NodeJS8d10Runtime]\n+     */\n+    runtime?: runtime.Runtime;\n+\n+    /**\n+     * Options to control which paths/packages should be included or excluded in the zip file containing\n+     * the code for the AWS lambda.\n+     */\n+    codePathOptions?: pulumi.runtime.CodePathOptions;\n+}>;\n+\n+/**\n+ * Base type for all subscription types.  An event subscription represents a connection between some\n+ * AWS resource an an AWS lambda that will be triggered when something happens to that resource.\n+ */\n+export class EventSubscription extends pulumi.ComponentResource {\n+    public permission: permission.Permission;\n+    public func: LambdaFunction;\n+\n+    public constructor(\n+        type: string, name: string, props: Record<string, any>, opts?: pulumi.ResourceOptions) {\n+\n+        super(type, name, props, opts);\n+    }\n+}\n+\n+/* @internal */ export function createFunctionFromEventHandler<E, R>(\n+    name: string, handler: EventHandler<E, R>, opts?: pulumi.ResourceOptions): LambdaFunction {\n+\n+    if (handler instanceof Function) {\n+        return createFunction(name, { entryPoint: handler } , opts);\n+    }\n+    else {\n+        return handler;\n+    }\n+}\n+\n+/**\n+ * Creates an AWS Lambda out of the provider options.func or options.factoryFunc.  Configuration of\n+ * this lambda can be provided through [options].\n+ */\n+export function createFunction<E, R>(\n+    name: string, options: FunctionOptions<E, R>, opts?: pulumi.ResourceOptions): LambdaFunction {\n+\n+    if (!name) {\n+        throw new Error(\"Missing required resource name\");\n+    }\n+\n+    if (options.entryPoint && options.entryPointFactory) {\n+        throw new pulumi.RunError(\"Cannot provide both [options.entryPoint] and [options.entryPointFactory]\");\n+    }\n+\n+    const func = options.entryPoint || options.entryPointFactory;\n+    if (!func) {\n+        throw new Error(\"One of [entryPoint] or [entryPointFactory] must be provided.\");\n+    }\n+\n+    let role: iam.Role;\n+    if (options.role) {\n+        role = options.role;\n+    } else {\n+        // Attach a role and then, if there are policies, attach those too.\n+        role = new iam.Role(name, {\n+            assumeRolePolicy: JSON.stringify(lambdaRolePolicy),\n+        }, opts);\n+\n+        if (!options.policies) {\n+            // Provides wide access to \"serverless\" services (Dynamo, S3, etc.)\n+            options.policies = [iam.AWSLambdaFullAccess];\n+        }\n+\n+        for (let policy of options.policies) {\n+            // RolePolicyAttachment objects don't have a physical identity, and create/deletes are processed\n+            // structurally based on the `role` and `policyArn`.  So we need to make sure our Pulumi name matches the\n+            // structural identity by using a name that includes the role name and policyArn.\n+            let attachment = new iam.RolePolicyAttachment(`${name}-${sha1hash(policy)}`, {\n+                role: role,\n+                policyArn: policy,\n+            }, opts);\n+        }\n+    }\n+\n+    // Now compile the function text into an asset we can use to create the lambda. Note: to\n+    // prevent a circularity/deadlock, we list this Function object as something that the\n+    // serialized closure cannot reference.\n+    const handlerName = \"handler\";\n+    const serializedFileNameNoExtension = \"__index\";\n+\n+    const closure = pulumi.runtime.serializeFunction(func, {\n+        serialize: _ => true,\n+        exportName: handlerName,\n+        isFactoryFunction: !!options.entryPointFactory,\n+    });\n+\n+    const codePaths = computeCodePaths(\n+        closure, serializedFileNameNoExtension, options.codePathOptions);\n+\n+    // Copy over all option values into the function args.  Then overwrite anything we care\n+    // about with our own values.  This ensures that clients can pass future supported\n+    // lambda options without us having to know about it.\n+    const copy = {\n+        ...options,\n+        code: new pulumi.asset.AssetArchive(codePaths),\n+        handler: serializedFileNameNoExtension + \".\" + handlerName,\n+        runtime: options.runtime || runtime.NodeJS8d10Runtime,\n+        role: role.arn,\n+        timeout: options.timeout === undefined ? 180 : options.timeout,\n+    };\n+\n+    // Create the Lambda Function.\n+    const lambda = new LambdaFunction(name, copy, opts);\n+    lambda.roleInstance = role;\n+    return lambda;\n+}\n+\n+// computeCodePaths calculates an AssetMap of files to include in the Lambda package.\n+async function computeCodePaths(\n+        closure: Promise<pulumi.runtime.SerializedFunction>,\n+        serializedFileNameNoExtension: string,\n+        codePathOptions: pulumi.runtime.CodePathOptions | undefined): Promise<pulumi.asset.AssetMap> {\n+\n+    const serializedFunction = await closure;\n+\n+    // Construct the set of paths to include in the archive for upload.\n+    let codePaths: pulumi.asset.AssetMap = {\n+        // Always include the serialized function.\n+        [serializedFileNameNoExtension + \".js\"]: new pulumi.asset.StringAsset(serializedFunction.text),\n+    };\n+\n+    // AWS Lambda always provides `aws-sdk`, so skip this.  Do this before processing user-provided\n+    // extraIncludePackages so that users can force aws-sdk to be included (if they need a specific\n+    // version).\n+    codePathOptions = codePathOptions || {};\n+    codePathOptions.extraExcludePackages = codePathOptions.extraExcludePackages || [];\n+    codePathOptions.extraExcludePackages.push(\"aws-sdk\");\n+\n+    const modulePaths = await pulumi.runtime.computeCodePaths(codePathOptions);\n+\n+    for (const [path, asset] of modulePaths) {\n+        codePaths[path] = asset;\n+    }\n+\n+    return codePaths;\n+}\n+\n+const lambdaRolePolicy = {\n+    \"Version\": \"2012-10-17\",\n+    \"Statement\": [\n+        {\n+            \"Action\": \"sts:AssumeRole\",\n+            \"Principal\": {\n+                \"Service\": \"lambda.amazonaws.com\",\n+            },\n+            \"Effect\": \"Allow\",\n+            \"Sid\": \"\",\n+        },\n+    ],\n+};\n+\n+// sha1hash returns a partial SHA1 hash of the input string.\n+function sha1hash(s: string): string {\n+    const shasum: crypto.Hash = crypto.createHash(\"sha1\");\n+    shasum.update(s);\n+    return shasum.digest(\"hex\").substring(0, 8);\n+}\n+\n+// Mixin the Role we potentially create into the Function instances we return.\n+\n+declare module \"./function\" {\n+    interface Function {\n+        // Actual Role instance value for this Function.  Will only be set if this function\n+        // was created from [createFunction]\n+        roleInstance?: iam.Role;\n+    }","path":"overlays/nodejs/lambda/lambdaMixins.ts","position":364,"original_position":364,"commit_id":"70b53d49613599b5946acb1c0ef5b98ed57b9bdb","original_commit_id":"70b53d49613599b5946acb1c0ef5b98ed57b9bdb","user":{"login":"CyrusNajmabadi","id":4564579,"node_id":"MDQ6VXNlcjQ1NjQ1Nzk=","avatar_url":"https://avatars3.githubusercontent.com/u/4564579?v=4","gravatar_id":"","url":"https://api.github.com/users/CyrusNajmabadi","html_url":"https://github.com/CyrusNajmabadi","followers_url":"https://api.github.com/users/CyrusNajmabadi/followers","following_url":"https://api.github.com/users/CyrusNajmabadi/following{/other_user}","gists_url":"https://api.github.com/users/CyrusNajmabadi/gists{/gist_id}","starred_url":"https://api.github.com/users/CyrusNajmabadi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CyrusNajmabadi/subscriptions","organizations_url":"https://api.github.com/users/CyrusNajmabadi/orgs","repos_url":"https://api.github.com/users/CyrusNajmabadi/repos","events_url":"https://api.github.com/users/CyrusNajmabadi/events{/privacy}","received_events_url":"https://api.github.com/users/CyrusNajmabadi/received_events","type":"User","site_admin":false},"body":"Sure.  That seems very doable.  ","created_at":"2018-09-21T22:55:06Z","updated_at":"2018-09-21T22:55:06Z","html_url":"https://github.com/pulumi/pulumi-aws/pull/327#discussion_r219646021","pull_request_url":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/327","author_association":"CONTRIBUTOR","_links":{"self":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/comments/219646021"},"html":{"href":"https://github.com/pulumi/pulumi-aws/pull/327#discussion_r219646021"},"pull_request":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/327"}},"in_reply_to_id":219640623},"pull_request":{"url":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/327","id":216798569,"node_id":"MDExOlB1bGxSZXF1ZXN0MjE2Nzk4NTY5","html_url":"https://github.com/pulumi/pulumi-aws/pull/327","diff_url":"https://github.com/pulumi/pulumi-aws/pull/327.diff","patch_url":"https://github.com/pulumi/pulumi-aws/pull/327.patch","issue_url":"https://api.github.com/repos/pulumi/pulumi-aws/issues/327","number":327,"state":"closed","locked":false,"title":"Move 'aws-serverless' components down into 'aws'","user":{"login":"CyrusNajmabadi","id":4564579,"node_id":"MDQ6VXNlcjQ1NjQ1Nzk=","avatar_url":"https://avatars3.githubusercontent.com/u/4564579?v=4","gravatar_id":"","url":"https://api.github.com/users/CyrusNajmabadi","html_url":"https://github.com/CyrusNajmabadi","followers_url":"https://api.github.com/users/CyrusNajmabadi/followers","following_url":"https://api.github.com/users/CyrusNajmabadi/following{/other_user}","gists_url":"https://api.github.com/users/CyrusNajmabadi/gists{/gist_id}","starred_url":"https://api.github.com/users/CyrusNajmabadi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/CyrusNajmabadi/subscriptions","organizations_url":"https://api.github.com/users/CyrusNajmabadi/orgs","repos_url":"https://api.github.com/users/CyrusNajmabadi/repos","events_url":"https://api.github.com/users/CyrusNajmabadi/events{/privacy}","received_events_url":"https://api.github.com/users/CyrusNajmabadi/received_events","type":"User","site_admin":false},"body":"Not ready for review.  Will ping when so.\r\n\r\nThere are many components to this change.  So it's worth outlining all of them:\r\n\r\n1. Moving 'EventSubscription' down to aws.lambda.EventSubscription.\r\n2. Move 'createLambdaFunction' down to aws.lambda.createFunction.  \r\n3. Deprecate aws.serverless.Function (and all corresponding types it exports), with documentation saying to use the corresponding functions and types in aws.lambda instead.\r\n4. Use mixins to take the small bit of functionality on aws.serverless.Function and expose it on aws.lambda.Function.\r\n5. Make the helpers/types surrounding creating aws.lambda.Functions strongly typed.  \r\n6. Move Bucket-Subscription code down from aws-serverless into aws.s3.  \r\n7. Use mixins to add that subscription functionality onto aws.Bucket itself.\r\n\r\nAll of the above has been done in a backward compatible fashion. i.e. we have deprecated, but kept around, all existing types/functions/classes.  Though, to ensure we don't have massive duplication, the old code sits on top of the new code now.\r\n\r\nI will also add a bunch of review comments to help explain what's going on.","created_at":"2018-09-19T22:46:56Z","updated_at":"2018-09-21T22:55:06Z","closed_at":"2018-09-21T21:23:59Z","merged_at":"2018-09-21T21:23:59Z","merge_commit_sha":"a4b57054d0b1eb3c692f6ebb302fa330f54b2719","assignee":null,"assignees":[],"requested_reviewers":[{"login":"jen20","id":548524,"node_id":"MDQ6VXNlcjU0ODUyNA==","avatar_url":"https://avatars2.githubusercontent.com/u/548524?v=4","gravatar_id":"","url":"https://api.github.com/users/jen20","html_url":"https://github.com/jen20","followers_url":"https://api.github.com/users/jen20/followers","following_url":"https://api.github.com/users/jen20/following{/other_user}","gists_url":"https://api.github.com/users/jen20/gists{/gist_id}","starred_url":"https://api.github.com/users/jen20/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jen20/subscriptions","organizations_url":"https://api.github.com/users/jen20/orgs","repos_url":"https://api.github.com/users/jen20/repos","events_url":"https://api.github.com/users/jen20/events{/privacy}","received_events_url":"https://api.github.com/users/jen20/received_events","type":"User","site_admin":false}],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/327/commits","review_comments_url":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/327/comments","review_comment_url":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/comments{/number}","comments_url":"https://api.github.com/repos/pulumi/pulumi-aws/issues/327/comments","statuses_url":"https://api.github.com/repos/pulumi/pulumi-aws/statuses/70b53d49613599b5946acb1c0ef5b98ed57b9bdb","head":{"label":"pulumi:mixins","ref":"mixins","sha":"70b53d49613599b5946acb1c0ef5b98ed57b9bdb","user":{"login":"pulumi","id":21992475,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIxOTkyNDc1","avatar_url":"https://avatars0.githubusercontent.com/u/21992475?v=4","gravatar_id":"","url":"https://api.github.com/users/pulumi","html_url":"https://github.com/pulumi","followers_url":"https://api.github.com/users/pulumi/followers","following_url":"https://api.github.com/users/pulumi/following{/other_user}","gists_url":"https://api.github.com/users/pulumi/gists{/gist_id}","starred_url":"https://api.github.com/users/pulumi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pulumi/subscriptions","organizations_url":"https://api.github.com/users/pulumi/orgs","repos_url":"https://api.github.com/users/pulumi/repos","events_url":"https://api.github.com/users/pulumi/events{/privacy}","received_events_url":"https://api.github.com/users/pulumi/received_events","type":"Organization","site_admin":false},"repo":{"id":97484940,"node_id":"MDEwOlJlcG9zaXRvcnk5NzQ4NDk0MA==","name":"pulumi-aws","full_name":"pulumi/pulumi-aws","private":false,"owner":{"login":"pulumi","id":21992475,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIxOTkyNDc1","avatar_url":"https://avatars0.githubusercontent.com/u/21992475?v=4","gravatar_id":"","url":"https://api.github.com/users/pulumi","html_url":"https://github.com/pulumi","followers_url":"https://api.github.com/users/pulumi/followers","following_url":"https://api.github.com/users/pulumi/following{/other_user}","gists_url":"https://api.github.com/users/pulumi/gists{/gist_id}","starred_url":"https://api.github.com/users/pulumi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pulumi/subscriptions","organizations_url":"https://api.github.com/users/pulumi/orgs","repos_url":"https://api.github.com/users/pulumi/repos","events_url":"https://api.github.com/users/pulumi/events{/privacy}","received_events_url":"https://api.github.com/users/pulumi/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/pulumi/pulumi-aws","description":"An Amazon Web Services (AWS) Pulumi resource package, providing multi-language access to AWS","fork":false,"url":"https://api.github.com/repos/pulumi/pulumi-aws","forks_url":"https://api.github.com/repos/pulumi/pulumi-aws/forks","keys_url":"https://api.github.com/repos/pulumi/pulumi-aws/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pulumi/pulumi-aws/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pulumi/pulumi-aws/teams","hooks_url":"https://api.github.com/repos/pulumi/pulumi-aws/hooks","issue_events_url":"https://api.github.com/repos/pulumi/pulumi-aws/issues/events{/number}","events_url":"https://api.github.com/repos/pulumi/pulumi-aws/events","assignees_url":"https://api.github.com/repos/pulumi/pulumi-aws/assignees{/user}","branches_url":"https://api.github.com/repos/pulumi/pulumi-aws/branches{/branch}","tags_url":"https://api.github.com/repos/pulumi/pulumi-aws/tags","blobs_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/refs{/sha}","trees_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pulumi/pulumi-aws/statuses/{sha}","languages_url":"https://api.github.com/repos/pulumi/pulumi-aws/languages","stargazers_url":"https://api.github.com/repos/pulumi/pulumi-aws/stargazers","contributors_url":"https://api.github.com/repos/pulumi/pulumi-aws/contributors","subscribers_url":"https://api.github.com/repos/pulumi/pulumi-aws/subscribers","subscription_url":"https://api.github.com/repos/pulumi/pulumi-aws/subscription","commits_url":"https://api.github.com/repos/pulumi/pulumi-aws/commits{/sha}","git_commits_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/commits{/sha}","comments_url":"https://api.github.com/repos/pulumi/pulumi-aws/comments{/number}","issue_comment_url":"https://api.github.com/repos/pulumi/pulumi-aws/issues/comments{/number}","contents_url":"https://api.github.com/repos/pulumi/pulumi-aws/contents/{+path}","compare_url":"https://api.github.com/repos/pulumi/pulumi-aws/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pulumi/pulumi-aws/merges","archive_url":"https://api.github.com/repos/pulumi/pulumi-aws/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pulumi/pulumi-aws/downloads","issues_url":"https://api.github.com/repos/pulumi/pulumi-aws/issues{/number}","pulls_url":"https://api.github.com/repos/pulumi/pulumi-aws/pulls{/number}","milestones_url":"https://api.github.com/repos/pulumi/pulumi-aws/milestones{/number}","notifications_url":"https://api.github.com/repos/pulumi/pulumi-aws/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pulumi/pulumi-aws/labels{/name}","releases_url":"https://api.github.com/repos/pulumi/pulumi-aws/releases{/id}","deployments_url":"https://api.github.com/repos/pulumi/pulumi-aws/deployments","created_at":"2017-07-17T14:20:33Z","updated_at":"2018-09-21T22:33:25Z","pushed_at":"2018-09-21T22:33:26Z","git_url":"git://github.com/pulumi/pulumi-aws.git","ssh_url":"git@github.com:pulumi/pulumi-aws.git","clone_url":"https://github.com/pulumi/pulumi-aws.git","svn_url":"https://github.com/pulumi/pulumi-aws","homepage":"","size":5947,"stargazers_count":23,"watchers_count":23,"language":"TypeScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"archived":false,"open_issues_count":23,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":5,"open_issues":23,"watchers":23,"default_branch":"master"}},"base":{"label":"pulumi:master","ref":"master","sha":"f3fdddb3b05e7e25414962d1a705026e1fd0b6a6","user":{"login":"pulumi","id":21992475,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIxOTkyNDc1","avatar_url":"https://avatars0.githubusercontent.com/u/21992475?v=4","gravatar_id":"","url":"https://api.github.com/users/pulumi","html_url":"https://github.com/pulumi","followers_url":"https://api.github.com/users/pulumi/followers","following_url":"https://api.github.com/users/pulumi/following{/other_user}","gists_url":"https://api.github.com/users/pulumi/gists{/gist_id}","starred_url":"https://api.github.com/users/pulumi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pulumi/subscriptions","organizations_url":"https://api.github.com/users/pulumi/orgs","repos_url":"https://api.github.com/users/pulumi/repos","events_url":"https://api.github.com/users/pulumi/events{/privacy}","received_events_url":"https://api.github.com/users/pulumi/received_events","type":"Organization","site_admin":false},"repo":{"id":97484940,"node_id":"MDEwOlJlcG9zaXRvcnk5NzQ4NDk0MA==","name":"pulumi-aws","full_name":"pulumi/pulumi-aws","private":false,"owner":{"login":"pulumi","id":21992475,"node_id":"MDEyOk9yZ2FuaXphdGlvbjIxOTkyNDc1","avatar_url":"https://avatars0.githubusercontent.com/u/21992475?v=4","gravatar_id":"","url":"https://api.github.com/users/pulumi","html_url":"https://github.com/pulumi","followers_url":"https://api.github.com/users/pulumi/followers","following_url":"https://api.github.com/users/pulumi/following{/other_user}","gists_url":"https://api.github.com/users/pulumi/gists{/gist_id}","starred_url":"https://api.github.com/users/pulumi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/pulumi/subscriptions","organizations_url":"https://api.github.com/users/pulumi/orgs","repos_url":"https://api.github.com/users/pulumi/repos","events_url":"https://api.github.com/users/pulumi/events{/privacy}","received_events_url":"https://api.github.com/users/pulumi/received_events","type":"Organization","site_admin":false},"html_url":"https://github.com/pulumi/pulumi-aws","description":"An Amazon Web Services (AWS) Pulumi resource package, providing multi-language access to AWS","fork":false,"url":"https://api.github.com/repos/pulumi/pulumi-aws","forks_url":"https://api.github.com/repos/pulumi/pulumi-aws/forks","keys_url":"https://api.github.com/repos/pulumi/pulumi-aws/keys{/key_id}","collaborators_url":"https://api.github.com/repos/pulumi/pulumi-aws/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/pulumi/pulumi-aws/teams","hooks_url":"https://api.github.com/repos/pulumi/pulumi-aws/hooks","issue_events_url":"https://api.github.com/repos/pulumi/pulumi-aws/issues/events{/number}","events_url":"https://api.github.com/repos/pulumi/pulumi-aws/events","assignees_url":"https://api.github.com/repos/pulumi/pulumi-aws/assignees{/user}","branches_url":"https://api.github.com/repos/pulumi/pulumi-aws/branches{/branch}","tags_url":"https://api.github.com/repos/pulumi/pulumi-aws/tags","blobs_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/refs{/sha}","trees_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/trees{/sha}","statuses_url":"https://api.github.com/repos/pulumi/pulumi-aws/statuses/{sha}","languages_url":"https://api.github.com/repos/pulumi/pulumi-aws/languages","stargazers_url":"https://api.github.com/repos/pulumi/pulumi-aws/stargazers","contributors_url":"https://api.github.com/repos/pulumi/pulumi-aws/contributors","subscribers_url":"https://api.github.com/repos/pulumi/pulumi-aws/subscribers","subscription_url":"https://api.github.com/repos/pulumi/pulumi-aws/subscription","commits_url":"https://api.github.com/repos/pulumi/pulumi-aws/commits{/sha}","git_commits_url":"https://api.github.com/repos/pulumi/pulumi-aws/git/commits{/sha}","comments_url":"https://api.github.com/repos/pulumi/pulumi-aws/comments{/number}","issue_comment_url":"https://api.github.com/repos/pulumi/pulumi-aws/issues/comments{/number}","contents_url":"https://api.github.com/repos/pulumi/pulumi-aws/contents/{+path}","compare_url":"https://api.github.com/repos/pulumi/pulumi-aws/compare/{base}...{head}","merges_url":"https://api.github.com/repos/pulumi/pulumi-aws/merges","archive_url":"https://api.github.com/repos/pulumi/pulumi-aws/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/pulumi/pulumi-aws/downloads","issues_url":"https://api.github.com/repos/pulumi/pulumi-aws/issues{/number}","pulls_url":"https://api.github.com/repos/pulumi/pulumi-aws/pulls{/number}","milestones_url":"https://api.github.com/repos/pulumi/pulumi-aws/milestones{/number}","notifications_url":"https://api.github.com/repos/pulumi/pulumi-aws/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/pulumi/pulumi-aws/labels{/name}","releases_url":"https://api.github.com/repos/pulumi/pulumi-aws/releases{/id}","deployments_url":"https://api.github.com/repos/pulumi/pulumi-aws/deployments","created_at":"2017-07-17T14:20:33Z","updated_at":"2018-09-21T22:33:25Z","pushed_at":"2018-09-21T22:33:26Z","git_url":"git://github.com/pulumi/pulumi-aws.git","ssh_url":"git@github.com:pulumi/pulumi-aws.git","clone_url":"https://github.com/pulumi/pulumi-aws.git","svn_url":"https://github.com/pulumi/pulumi-aws","homepage":"","size":5947,"stargazers_count":23,"watchers_count":23,"language":"TypeScript","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":5,"mirror_url":null,"archived":false,"open_issues_count":23,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":5,"open_issues":23,"watchers":23,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/327"},"html":{"href":"https://github.com/pulumi/pulumi-aws/pull/327"},"issue":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/issues/327"},"comments":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/issues/327/comments"},"review_comments":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/327/comments"},"review_comment":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/pulls/327/commits"},"statuses":{"href":"https://api.github.com/repos/pulumi/pulumi-aws/statuses/70b53d49613599b5946acb1c0ef5b98ed57b9bdb"}},"author_association":"CONTRIBUTOR"}}
{"actor":{"display_login":"CyrusNajmabadi"}}