Skip to content

Commit

Permalink
Merge branch 'master' into epolon/jest-upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
iliapolo committed Nov 5, 2021
2 parents 050a10f + 7bbd10d commit 9cb31fc
Show file tree
Hide file tree
Showing 17 changed files with 259 additions and 96 deletions.
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-codepipeline-actions/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export * from './s3/source-action';
export * from './stepfunctions/invoke-action';
export * from './servicecatalog/deploy-action-beta1';
export * from './action';

Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import * as cdk from '@aws-cdk/core';
import { Construct } from 'constructs';
import { CustomActionRegistration } from '../custom-action-registration';

// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
Expand Down Expand Up @@ -190,7 +189,7 @@ export class JenkinsProvider extends BaseJenkinsProvider {
}

private registerJenkinsCustomAction(id: string, category: codepipeline.ActionCategory) {
new CustomActionRegistration(this, id, {
new codepipeline.CustomActionRegistration(this, id, {
category,
artifactBounds: jenkinsArtifactsBounds,
provider: this.providerName,
Expand Down
34 changes: 34 additions & 0 deletions packages/@aws-cdk/aws-codepipeline/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,40 @@ or you can use the `IStage.addAction()` method to mutate an existing Stage:
sourceStage.addAction(someAction);
```

## Custom Action Registration

To make your own custom CodePipeline Action requires registering the action provider. Look to the `JenkinsProvider` in `@aws-cdk/aws-codepipeline-actions` for an implementation example.

```ts
new codepipeline.CustomActionRegistration(this, 'GenericGitSourceProviderResource', {
category: codepipeline.ActionCategory.SOURCE,
artifactBounds: { minInputs: 0, maxInputs: 0, minOutputs: 1, maxOutputs: 1 },
provider: 'GenericGitSource',
version: '1',
entityUrl: 'https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-create-custom-action.html',
executionUrl: 'https://docs.aws.amazon.com/codepipeline/latest/userguide/actions-create-custom-action.html',
actionProperties: [
{
name: 'Branch',
required: true,
key: false,
secret: false,
queryable: false,
description: 'Git branch to pull',
type: 'String',
},
{
name: 'GitUrl',
required: true,
key: false,
secret: false,
queryable: false,
description: 'SSH git clone URL',
type: 'String',
},
]
```
## Cross-account CodePipelines
> Cross-account Pipeline actions require that the Pipeline has *not* been
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as codepipeline from '@aws-cdk/aws-codepipeline';
import { Construct } from 'constructs';
import { ActionCategory, ActionArtifactBounds } from './action';
import { CfnCustomActionType } from './codepipeline.generated';

// keep this import separate from other imports to reduce chance for merge conflicts with v2-main
// eslint-disable-next-line no-duplicate-imports, import/order
import { Construct } from '@aws-cdk/core';
import { Construct as CoreConstruct } from '@aws-cdk/core';

/**
* The creation attributes used for defining a configuration property
Expand All @@ -13,22 +15,22 @@ export interface CustomActionProperty {
* The name of the property.
* You use this name in the `configuration` attribute when defining your custom Action class.
*/
name: string;
readonly name: string;

/**
* The description of the property.
*
* @default the description will be empty
*/
description?: string;
readonly description?: string;

/**
* Whether this property is a key.
*
* @default false
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codepipeline-customactiontype-configurationproperties.html#cfn-codepipeline-customactiontype-configurationproperties-key
*/
key?: boolean;
readonly key?: boolean;

/**
* Whether this property is queryable.
Expand All @@ -37,28 +39,28 @@ export interface CustomActionProperty {
* @default false
* @see https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-codepipeline-customactiontype-configurationproperties.html#cfn-codepipeline-customactiontype-configurationproperties-queryable
*/
queryable?: boolean;
readonly queryable?: boolean;

/**
* Whether this property is required.
*/
required: boolean;
readonly required: boolean;

/**
* Whether this property is secret,
* like a password, or access key.
*
* @default false
*/
secret?: boolean;
readonly secret?: boolean;

/**
* The type of the property,
* like 'String', 'Number', or 'Boolean'.
*
* @default 'String'
*/
type?: string;
readonly type?: string;
}

/**
Expand All @@ -68,41 +70,44 @@ export interface CustomActionRegistrationProps {
/**
* The category of the Action.
*/
category: codepipeline.ActionCategory;
readonly category: ActionCategory;

/**
* The artifact bounds of the Action.
*/
artifactBounds: codepipeline.ActionArtifactBounds;
readonly artifactBounds: ActionArtifactBounds;

/**
* The provider of the Action.
* @example 'MyCustomActionProvider'
*/
provider: string;
readonly provider: string;

/**
* The version of your Action.
*
* @default '1'
*/
version?: string;
readonly version?: string;

/**
* The URL shown for the entire Action in the Pipeline UI.
* @default none
*/
entityUrl?: string;
readonly entityUrl?: string;

/**
* The URL shown for a particular execution of an Action in the Pipeline UI.
* @default none
*/
executionUrl?: string;
readonly executionUrl?: string;

/**
* The properties used for customizing the instance of your Action.
*
* @default []
*/
actionProperties?: CustomActionProperty[];
readonly actionProperties?: CustomActionProperty[];
}

/**
Expand All @@ -112,11 +117,11 @@ export interface CustomActionRegistrationProps {
* representing your custom Action, extending the Action class,
* and taking the `actionProperties` as properly typed, construction properties.
*/
export class CustomActionRegistration extends Construct {
constructor(parent: Construct, id: string, props: CustomActionRegistrationProps) {
super(parent, id);
export class CustomActionRegistration extends CoreConstruct {
constructor(scope: Construct, id: string, props: CustomActionRegistrationProps) {
super(scope, id);

new codepipeline.CfnCustomActionType(this, 'Resource', {
new CfnCustomActionType(this, 'Resource', {
category: props.category,
inputArtifactDetails: {
minimumCount: props.artifactBounds.minInputs,
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-codepipeline/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export * from './action';
export * from './artifact';
export * from './pipeline';
export * from './custom-action-registration';

// AWS::CodePipeline CloudFormation Resources:
export * from './codepipeline.generated';
17 changes: 11 additions & 6 deletions packages/@aws-cdk/aws-eks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ The following is a qualitative diagram of the various possible components involv

```text
+-----------------------------------------------+ +-----------------+
| EKS Cluster | kubectl | |
|-----------------------------------------------|<-------------+| Kubectl Handler |
| EKS Cluster | kubectl | |
| ----------- |<-------------+| Kubectl Handler |
| | | |
| | +-----------------+
| +--------------------+ +-----------------+ |
Expand Down Expand Up @@ -539,16 +539,21 @@ If the endpoint does not expose private access (via `EndpointAccess.PUBLIC`) **o

#### Cluster Handler

The `ClusterHandler` is a Lambda function responsible to interact with the EKS API in order to control the cluster lifecycle. To provision this function inside the VPC, set the `placeClusterHandlerInVpc` property to `true`. This will place the function inside the private subnets of the VPC based on the selection strategy specified in the [`vpcSubnets`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-eks.Cluster.html#vpcsubnetsspan-classapi-icon-api-icon-experimental-titlethis-api-element-is-experimental-it-may-change-without-noticespan) property.
The `ClusterHandler` is a set of Lambda functions (`onEventHandler`, `isCompleteHandler`) responsible for interacting with the EKS API in order to control the cluster lifecycle. To provision these functions inside the VPC, set the `placeClusterHandlerInVpc` property to `true`. This will place the functions inside the private subnets of the VPC based on the selection strategy specified in the [`vpcSubnets`](https://docs.aws.amazon.com/cdk/api/latest/docs/@aws-cdk_aws-eks.Cluster.html#vpcsubnetsspan-classapi-icon-api-icon-experimental-titlethis-api-element-is-experimental-it-may-change-without-noticespan) property.

You can configure the environment of this function by specifying it at cluster instantiation. For example, this can be useful in order to configure an http proxy:
You can configure the environment of the Cluster Handler functions by specifying it at cluster instantiation. For example, this can be useful in order to configure an http proxy:

```ts
const cluster = new eks.Cluster(this, 'hello-eks', {
version: eks.KubernetesVersion.V1_21,
clusterHandlerEnvironment: {
'http_proxy': 'http://proxy.myproxy.com'
}
https_proxy: 'http://proxy.myproxy.com'
},
/**
* If the proxy is not open publicly, you can pass a security group to the
* Cluster Handler Lambdas so that it can reach the proxy.
*/
clusterHandlerSecurityGroup: proxyInstanceSecurityGroup
});
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,6 @@ export abstract class ResourceHandler {
}

public onEvent() {
// eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-extraneous-dependencies
const ProxyAgent: any = require('proxy-agent');
aws.config.update({
httpOptions: { agent: new ProxyAgent() },
});

switch (this.requestType) {
case 'Create': return this.onCreate();
case 'Update': return this.onUpdate();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import { EksClient } from './common';
import * as consts from './consts';
import { FargateProfileResourceHandler } from './fargate';

// eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-extraneous-dependencies
const ProxyAgent = require('proxy-agent');

aws.config.logger = console;
aws.config.update({
httpOptions: { agent: new ProxyAgent() },
});

let eks: aws.EKS | undefined;

Expand Down
33 changes: 21 additions & 12 deletions packages/@aws-cdk/aws-eks/lib/cluster-resource-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,18 @@ export interface ClusterResourceProviderProps {
readonly environment?: { [key: string]: string };

/**
* An AWS Lambda layer that includes the NPM dependency `proxy-agent`.
*
* If not defined, a default layer will be used.
*/
* An AWS Lambda layer that includes the NPM dependency `proxy-agent`.
*
* If not defined, a default layer will be used.
*/
readonly onEventLayer?: lambda.ILayerVersion;

/**
* The security group to associate with the functions.
*
* @default - No security group.
*/
readonly securityGroup?: ec2.ISecurityGroup;
}

/**
Expand All @@ -66,6 +73,9 @@ export class ClusterResourceProvider extends NestedStack {
private constructor(scope: Construct, id: string, props: ClusterResourceProviderProps) {
super(scope as CoreConstruct, id);

// The NPM dependency proxy-agent is required in order to support proxy routing with the AWS JS SDK.
const nodeProxyAgentLayer = new NodeProxyAgentLayer(this, 'NodeProxyAgentLayer');

const onEvent = new lambda.Function(this, 'OnEventHandler', {
code: lambda.Code.fromAsset(HANDLER_DIR),
description: 'onEvent handler for EKS cluster resource provider',
Expand All @@ -75,24 +85,22 @@ export class ClusterResourceProvider extends NestedStack {
timeout: Duration.minutes(1),
vpc: props.subnets ? props.vpc : undefined,
vpcSubnets: props.subnets ? { subnets: props.subnets } : undefined,
securityGroups: props.securityGroup ? [props.securityGroup] : undefined,
// Allow user to override the layer.
layers: props.onEventLayer ? [props.onEventLayer] : [nodeProxyAgentLayer],
});

// Allow user to customize the layer
if (!props.onEventLayer) {
// `NodeProxyAgentLayer` provides `proxy-agent` which is needed to configure `aws-sdk-js` with a user provided proxy.
onEvent.addLayers(new NodeProxyAgentLayer(this, 'NodeProxyAgentLayer'));
} else {
onEvent.addLayers(props.onEventLayer);
}

const isComplete = new lambda.Function(this, 'IsCompleteHandler', {
code: lambda.Code.fromAsset(HANDLER_DIR),
description: 'isComplete handler for EKS cluster resource provider',
runtime: HANDLER_RUNTIME,
environment: props.environment,
handler: 'index.isComplete',
timeout: Duration.minutes(1),
vpc: props.subnets ? props.vpc : undefined,
vpcSubnets: props.subnets ? { subnets: props.subnets } : undefined,
securityGroups: props.securityGroup ? [props.securityGroup] : undefined,
layers: [nodeProxyAgentLayer],
});

this.provider = new cr.Provider(this, 'Provider', {
Expand All @@ -102,6 +110,7 @@ export class ClusterResourceProvider extends NestedStack {
queryInterval: Duration.minutes(1),
vpc: props.subnets ? props.vpc : undefined,
vpcSubnets: props.subnets ? { subnets: props.subnets } : undefined,
securityGroups: props.securityGroup ? [props.securityGroup] : undefined,
});

props.adminRole.grant(onEvent.role!, 'sts:AssumeRole');
Expand Down
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-eks/lib/cluster-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface ClusterResourceProps {
readonly subnets?: ec2.ISubnet[];
readonly secretsEncryptionKey?: kms.IKey;
readonly onEventLayer?: lambda.ILayerVersion;
readonly clusterHandlerSecurityGroup?: ec2.ISecurityGroup;
}

/**
Expand Down Expand Up @@ -66,6 +67,7 @@ export class ClusterResource extends CoreConstruct {
vpc: props.vpc,
environment: props.environment,
onEventLayer: props.onEventLayer,
securityGroup: props.clusterHandlerSecurityGroup,
});

const resource = new CustomResource(this, 'Resource', {
Expand Down

0 comments on commit 9cb31fc

Please sign in to comment.