forked from aws/aws-cdk
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(servicediscovery): Add construct lib
Partially addresses aws#1554
- Loading branch information
Showing
15 changed files
with
1,622 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,11 @@ | ||
## The CDK Construct Library for AWS Service Discovery | ||
This module is part of the [AWS Cloud Development Kit](https://github.com/awslabs/aws-cdk) project. | ||
|
||
This package contains constructs for working with **AWS Cloud Map** | ||
|
||
AWS Cloud Map is a fully managed service that you can use to create and | ||
maintain a map of the backend services and resources that your applications | ||
depend on. | ||
|
||
For further information on AWS Cloud Map, | ||
see the [AWS Cloud Map documentation](https://docs.aws.amazon.com/cloud-map) |
41 changes: 41 additions & 0 deletions
41
packages/@aws-cdk/aws-servicediscovery/lib/http-namespace.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import cdk = require('@aws-cdk/cdk'); | ||
import { CfnHttpNamespace } from './servicediscovery.generated'; | ||
|
||
export interface HttpNamespaceProps { | ||
/** | ||
* A name for the HttpNamespace. | ||
*/ | ||
name: string; | ||
|
||
/** | ||
* A description of the namespace. | ||
*/ | ||
description?: string; | ||
} | ||
|
||
/** | ||
* Define a Service Discovery HTTP Namespace | ||
*/ | ||
export class HttpNamespace extends cdk.Construct { | ||
/** | ||
* A domain name | ||
*/ | ||
public readonly name: string; | ||
|
||
/** | ||
* Namespace Id for the HttpNamespace. | ||
*/ | ||
public readonly namespaceId: string; | ||
|
||
constructor(scope: cdk.Construct, id: string, props: HttpNamespaceProps) { | ||
super(scope, id); | ||
|
||
const ns = new CfnHttpNamespace(this, 'Resource', { | ||
name: props.name, | ||
description: props.description | ||
}); | ||
|
||
this.name = props.name; | ||
this.namespaceId = ns.httpNamespaceId; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
export * from './instance'; | ||
export * from './namespace'; | ||
export * from './service'; | ||
// AWS::ServiceDiscovery CloudFormation Resources: | ||
export * from './servicediscovery.generated'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
import cdk = require('@aws-cdk/cdk'); | ||
import { NamespaceType } from './namespace'; | ||
import { DnsRecordType, Service } from './service'; | ||
import { CfnInstance } from './servicediscovery.generated'; | ||
|
||
/** | ||
* Properties to define ServiceDiscovery Instance | ||
*/ | ||
export interface InstanceProps { | ||
/** | ||
* The instance attributes. | ||
* FIXME: add defaults/validations | ||
*/ | ||
instanceAttributes: InstanceAttributes | ||
|
||
/** | ||
* The id of the instance resource | ||
*/ | ||
instanceId: string; | ||
|
||
/** | ||
* The Cloudmap service this resource is registered to. | ||
*/ | ||
service: Service; | ||
} | ||
|
||
/** | ||
* Define a Service Discovery Instance | ||
*/ | ||
export class Instance extends cdk.Construct { | ||
/** | ||
* The Id of the instance | ||
*/ | ||
public readonly instanceId: string; | ||
/** | ||
* The Cloudmap service to which the instance is registered. | ||
*/ | ||
public readonly service: Service; | ||
|
||
constructor(scope: cdk.Construct, id: string, props: InstanceProps) { | ||
super(scope, id); | ||
|
||
const customAttributes = props.instanceAttributes.customAttributes || {}; | ||
|
||
const resource = new CfnInstance(this, 'Resource', { | ||
instanceAttributes: { ...customAttributes, ...getInstanceAttributes(props) }, | ||
instanceId: props.instanceId, | ||
serviceId: props.service.serviceId | ||
}); | ||
|
||
this.service = props.service; | ||
this.instanceId = resource.instanceId; | ||
} | ||
} | ||
|
||
// NOTE: These are the 5 that seem to be supported in cloudformation, but the API docs indicate that you can also | ||
// specify custom attributes. Not sure if CFN would support these? In the generated L1s instance attributes appears to | ||
// just be an object. | ||
export interface InstanceAttributes { | ||
/** | ||
* If you want AWS Cloud Map to create an Amazon Route 53 alias record that routes traffic to an Elastic Load | ||
* Balancing load balancer, specify the DNS name that is associated with the load balancer. | ||
*/ | ||
aliasDnsName?: string, | ||
|
||
/** | ||
* If the service configuration includes a CNAME record, the domain name that you want Route 53 to return in | ||
* response to DNS queries, for example, example.com. This value is required if the service specified by ServiceId | ||
* includes settings for an CNAME record. | ||
*/ | ||
instanceCname?: string, | ||
|
||
/** The port on the endpoint that you want AWS Cloud Map to perform health checks on. This value is also used for | ||
* the port value in an SRV record if the service that you specify includes an SRV record. You can also specify a | ||
* default port that is applied to all instances in the Service configuration. | ||
*/ | ||
port?: string, | ||
/** | ||
* If the service that you specify contains a template for an A record, the IPv4 address that you want AWS Cloud | ||
* Map to use for the value of the A record. | ||
*/ | ||
ipv4?: string, | ||
/** | ||
* If the service that you specify contains a template for an AAAA record, the IPv6 address that you want AWS Cloud | ||
* Map to use for the value of the AAAA record. | ||
*/ | ||
ipv6?: string, | ||
|
||
/** | ||
* Custom attributes of the instance. | ||
*/ | ||
customAttributes?: object; | ||
} | ||
|
||
/** | ||
* Validates instance attributes and returns standard attributes based on the namespace/service type. | ||
* | ||
* @param props instance props | ||
* @throws if the instance attributes are invalid | ||
*/ | ||
function getInstanceAttributes(props: InstanceProps): object { | ||
if (props.instanceAttributes.aliasDnsName && props.instanceAttributes.instanceCname) { | ||
throw new Error('Cannot specify both `aliasDnsName` and `instanceCname`.'); | ||
} | ||
|
||
if (props.service.namespace.type === NamespaceType.Http) { | ||
if (props.instanceAttributes.aliasDnsName || props.instanceAttributes.instanceCname) { | ||
throw new Error('Cannot specify `aliasDnsName` or `instanceCname` for an HTTP namespace.'); | ||
} | ||
|
||
return { | ||
AWS_INSTANCE_IPV4: props.instanceAttributes.ipv4, | ||
AWS_INSTANCE_IPV6: props.instanceAttributes.ipv6, | ||
AWS_INSTANCE_PORT: props.instanceAttributes.port | ||
}; | ||
} | ||
|
||
if (props.service.dnsRecordType === DnsRecordType.Cname) { | ||
if (!props.instanceAttributes.instanceCname) { | ||
throw new Error('A `instanceCname` must be specified for a service using a `CNAME` record.'); | ||
} | ||
|
||
return { | ||
AWS_INSTANCE_CNAME: props.instanceAttributes.instanceCname | ||
}; | ||
} | ||
|
||
if (props.service.dnsRecordType === DnsRecordType.Srv) { | ||
if (!props.instanceAttributes.port) { | ||
throw new Error('A `port` must be specified for a service using a `SRV` record.'); | ||
} | ||
|
||
if (!props.instanceAttributes.ipv4 && !props.instanceAttributes.ipv6) { | ||
throw new Error('At least `ipv4` or `ipv6` must be specified for a service using a `SRV` record.'); | ||
} | ||
|
||
return { | ||
AWS_INSTANCE_IPV4: props.instanceAttributes.ipv4, | ||
AWS_INSTANCE_IPV6: props.instanceAttributes.ipv6, | ||
AWS_INSTANCE_PORT: props.instanceAttributes.port | ||
}; | ||
} | ||
|
||
if (props.instanceAttributes.aliasDnsName) { | ||
if (props.instanceAttributes.ipv4 || props.instanceAttributes.ipv6 || props.instanceAttributes.port) { | ||
throw new Error('Cannot specify `ipv4`, `ipv6` or `port` when specifying `aliasDnsName`.'); | ||
} | ||
|
||
return { | ||
AWS_ALIAS_DNS_NAME: props.instanceAttributes.aliasDnsName | ||
}; | ||
} | ||
|
||
if (!props.instanceAttributes.ipv4 && (props.service.dnsRecordType === DnsRecordType.A || props.service.dnsRecordType === DnsRecordType.A_AAAA)) { | ||
throw new Error('An `ipv4` must be specified for a service using a `A` record.'); | ||
} | ||
|
||
if (!props.instanceAttributes.ipv6 && | ||
(props.service.dnsRecordType === DnsRecordType.AAAA || props.service.dnsRecordType === DnsRecordType.A_AAAA)) { | ||
throw new Error('An `ipv6` must be specified for a service using a `AAAA` record.'); | ||
} | ||
|
||
return { | ||
AWS_INSTANCE_IPV4: props.instanceAttributes.ipv4, | ||
AWS_INSTANCE_IPV6: props.instanceAttributes.ipv6, | ||
AWS_INSTANCE_PORT: props.instanceAttributes.port | ||
}; | ||
} |
156 changes: 156 additions & 0 deletions
156
packages/@aws-cdk/aws-servicediscovery/lib/namespace.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
import ec2 = require('@aws-cdk/aws-ec2'); | ||
import cdk = require('@aws-cdk/cdk'); | ||
// import { BaseServiceProps, Service } from './service'; | ||
import { CfnHttpNamespace, CfnPrivateDnsNamespace, CfnPublicDnsNamespace} from './servicediscovery.generated'; | ||
|
||
export interface INamespace extends cdk.IConstruct { | ||
/** | ||
* A name for the Namespace. | ||
*/ | ||
readonly namespaceName: string; | ||
|
||
/** | ||
* Namespace Id for the Namespace. | ||
*/ | ||
readonly namespaceId: string; | ||
|
||
/** | ||
* Namespace ARN for the Namespace. | ||
*/ | ||
readonly namespaceArn: string; | ||
|
||
/** | ||
* Type of Namespace. Valid values: HTTP, DNS_PUBLIC, or DNS_PRIVATE | ||
*/ | ||
readonly type: NamespaceType; | ||
} | ||
|
||
export interface NamespaceProps { | ||
/** | ||
* A name for the Namespace. | ||
*/ | ||
name: string; | ||
|
||
/** | ||
* A description of the Namespace. | ||
* | ||
* @default none | ||
*/ | ||
description?: string; | ||
|
||
/** | ||
* Type of Namespace. Valid values: HTTP, DNS_PUBLIC, or DNS_PRIVATE | ||
* | ||
* @default HTTP | ||
*/ | ||
type?: NamespaceType; | ||
|
||
/** | ||
* The Amazon VPC that you want to associate the namespace with. | ||
* Only applies for Private DNS Namespaces. | ||
* | ||
* @default none | ||
*/ | ||
vpc?: ec2.IVpcNetwork; | ||
|
||
} | ||
|
||
export interface NamespaceImportProps { | ||
/** | ||
* A name for the Namespace. | ||
*/ | ||
readonly namespaceName: string; | ||
|
||
/** | ||
* Namespace Id for the Namespace. | ||
*/ | ||
readonly namespaceId: string; | ||
|
||
/** | ||
* Namespace ARN for the Namespace. | ||
*/ | ||
readonly namespaceArn: string; | ||
|
||
/** | ||
* Type of Namespace. Valid values: HTTP, DNS_PUBLIC, or DNS_PRIVATE | ||
*/ | ||
readonly type: NamespaceType; | ||
} | ||
|
||
export enum NamespaceType { | ||
Http = "HTTP", | ||
DnsPublic = "DNS_PUBLIC", | ||
DnsPrivate = "DNS_PRIVATE" | ||
} | ||
|
||
export class Namespace extends cdk.Construct implements INamespace { | ||
public readonly namespaceName: string; | ||
public readonly namespaceId: string; | ||
public readonly namespaceArn: string; | ||
public readonly type: NamespaceType; | ||
|
||
constructor(scope: cdk.Construct, id: string, props: NamespaceProps) { | ||
super(scope, id); | ||
|
||
const namespaceName = props.name; | ||
const description = props.description; | ||
|
||
let namespaceType = props.type; | ||
if (namespaceType === undefined) { | ||
namespaceType = NamespaceType.Http; | ||
} | ||
|
||
this.namespaceName = namespaceName; | ||
this.type = namespaceType; | ||
|
||
switch (namespaceType) { | ||
case NamespaceType.Http: { | ||
const ns = new CfnHttpNamespace(this, 'Resource', { | ||
name: namespaceName, | ||
description | ||
}); | ||
|
||
this.namespaceId = ns.httpNamespaceId; | ||
this.namespaceArn = ns.httpNamespaceArn; | ||
break; | ||
} | ||
|
||
case NamespaceType.DnsPrivate: { | ||
if (props.vpc === undefined) { | ||
throw new Error(`VPC must be specified for PrivateDNSNamespaces`); | ||
} | ||
|
||
const ns = new CfnPrivateDnsNamespace(this, 'Resource', { | ||
name: namespaceName, | ||
description, | ||
vpc: props.vpc.vpcId | ||
}); | ||
|
||
this.namespaceId = ns.privateDnsNamespaceId; | ||
this.namespaceArn = ns.privateDnsNamespaceArn; | ||
break; | ||
} | ||
|
||
case NamespaceType.DnsPublic: { | ||
const ns = new CfnPublicDnsNamespace(this, 'Resource', { | ||
name: namespaceName, | ||
description | ||
}); | ||
|
||
this.namespaceId = ns.publicDnsNamespaceId; | ||
this.namespaceArn = ns.publicDnsNamespaceArn; | ||
break; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Creates a new service in this namespace FIXME -- not setting namespace correctly | ||
*/ | ||
// public createService(id: string, props?: BaseServiceProps): Service { | ||
// return new Service(this, id, { | ||
// namespace: this, | ||
// ...props, | ||
// }); | ||
// } | ||
} |
Oops, something went wrong.