Skip to content

Commit

Permalink
MIGRATIONS-1014: Add unit test cases and minor fixes
Browse files Browse the repository at this point in the history
Signed-off-by: Tanner Lewis <[email protected]>
  • Loading branch information
lewijacn committed May 3, 2023
1 parent 7dfc6e5 commit 2de79f2
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 18 deletions.
4 changes: 2 additions & 2 deletions deployment/cdk/opensearch-service/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ Additional context on some of these options, can also be found in the Domain con
| vpcId | false | string | "vpc-123456789abcdefgh" | Specify an existing VPC to place the domain inside of |
| vpcSubnetIds | false | string array | ["subnet-123456789abcdefgh", "subnet-223456789abcdefgh"] | Specify the subnet IDs of an existing VPC to place the Domain in. Requires `vpcId` to be specified |
| vpcSecurityGroupIds | false | string array | ["sg-123456789abcdefgh", "sg-223456789abcdefgh"] | Specify the Security Groups that will be associated with the VPC endpoints for the Domain. Requires `vpcId` to be specified |
| availabilityZoneCount | false | number | 1 | The number of Availability Zones for the Domain to use |
| openAccessPolicyEnabled | false | boolean | false | Applies an open access policy to the Domain. **NOTE**: This setting is only available to Domains placed within a VPC, and is applicable to many use cases where access controlled by Security Groups on the VPC is sufficient. |
| availabilityZoneCount | false | number | 1 | The number of Availability Zones for the Domain to use. If not specified a single AZ is used. If specified the Domain CDK construct requires at least 2 AZs |
| openAccessPolicyEnabled | false | boolean | false | Applies an open access policy to the Domain. **NOTE**: This setting should only be used for Domains placed within a VPC, and is applicable to many use cases where access controlled by Security Groups on the VPC is sufficient. |
| domainRemovalPolicy | false | string | "RETAIN" | Policy to apply when the domain is removed from the CloudFormation stack |


Expand Down
2 changes: 2 additions & 0 deletions deployment/cdk/opensearch-service/lib/network-stack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ export class NetworkStack extends Stack {
});
}

// If specified, these subnets will be selected to place the Domain nodes in. Otherwise, this is not provided
// to the Domain as it has existing behavior to select private subnets from a given VPC
if (props.vpcSubnetIds) {
const selectSubnets = this.vpc.selectSubnets({
subnetFilters: [SubnetFilter.byIds(props.vpcSubnetIds)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"engineVersion": "OS_1.0",
"domainName": "default-test-domain"
"domainName": "sample-cdk-unit-test-domain"
}
99 changes: 91 additions & 8 deletions deployment/cdk/opensearch-service/test/domain-cdk-stack.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import {App} from 'aws-cdk-lib';
import {Template} from 'aws-cdk-lib/assertions';
import {StackComposer} from "../lib/stack-composer";
import * as testDefaultValues from "./default-values-test.json";
import {OpensearchServiceDomainCdkStack} from "../lib/opensearch-service-domain-cdk-stack";
import {NetworkStack} from "../lib/network-stack";

test('Test primary context options are mapped with standard data type', () => {
// The cdk.context.json and default-values.json files allow multiple data types
Expand Down Expand Up @@ -36,7 +38,11 @@ test('Test primary context options are mapped with standard data type', () => {
loggingAppLogEnabled: true,
loggingAppLogGroupARN: "arn:aws:logs:us-east-1:123456789123:log-group:test-log-group:*",
nodeToNodeEncryptionEnabled: true,
vpcEnabled: true,
vpcId: "vpc-123456789abcdefgh",
vpcSubnetIds: ["subnet-123456789abcdefgh", "subnet-223456789abcdefgh"],
vpcSecurityGroupIds: ["sg-123456789abcdefgh", "sg-223456789abcdefgh"],
availabilityZoneCount: 3,
domainRemovalPolicy: "DESTROY"
}
})
Expand All @@ -45,9 +51,14 @@ test('Test primary context options are mapped with standard data type', () => {
env: {account: "test-account", region: "us-east-1"}
})

const domainStack = openSearchStacks.stacks.filter((s) => s.stackName === "opensearchDomainStack")[0]
const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
const networkStack = openSearchStacks.stacks.filter((s) => s instanceof NetworkStack)[0]
const networkTemplate = Template.fromStack(networkStack)
assertPrimaryDomainStackTemplate(domainTemplate)
// When existing resources are provided the network stack creates no resources
const resources = networkTemplate.toJSON().Resources;
expect(resources === undefined)
})

test('Test primary context options are mapped with only string data type', () => {
Expand Down Expand Up @@ -75,7 +86,11 @@ test('Test primary context options are mapped with only string data type', () =>
loggingAppLogEnabled: "true",
loggingAppLogGroupARN: "arn:aws:logs:us-east-1:123456789123:log-group:test-log-group:*",
nodeToNodeEncryptionEnabled: "true",
vpcEnabled: "true",
vpcId: "vpc-123456789abcdefgh",
vpcSubnetIds: "[\"subnet-123456789abcdefgh\", \"subnet-223456789abcdefgh\"]",
vpcSecurityGroupIds: "[\"sg-123456789abcdefgh\", \"sg-223456789abcdefgh\"]",
availabilityZoneCount: "3",
domainRemovalPolicy: "DESTROY"
}
})
Expand All @@ -84,9 +99,14 @@ test('Test primary context options are mapped with only string data type', () =>
env: {account: "test-account", region: "us-east-1"}
})

const domainStack = openSearchStacks.stacks.filter((s) => s.stackName === "opensearchDomainStack")[0]
const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
const networkStack = openSearchStacks.stacks.filter((s) => s instanceof NetworkStack)[0]
const networkTemplate = Template.fromStack(networkStack)
assertPrimaryDomainStackTemplate(domainTemplate)
// When existing resources are provided the network stack creates no resources
const resources = networkTemplate.toJSON().Resources;
expect(resources === undefined)
})

test('Test alternate context options are mapped with standard data type', () => {
Expand All @@ -107,13 +127,13 @@ test('Test alternate context options are mapped with standard data type', () =>
env: {account: "test-account", region: "us-east-1"}
})

const domainStack = openSearchStacks.stacks.filter((s) => s.stackName === "opensearchDomainStack")[0]
const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
assertAlternateDomainStackTemplate(domainTemplate)
})

test('Test alternate context options are mapped with only string data type', () => {
// The cdk.context.json and default-values.json files allow multiple data types
// CDK CLI commands pass all context values as strings
const app = new App({
context: {
useUnsignedBasicAuth: "true",
Expand All @@ -130,11 +150,65 @@ test('Test alternate context options are mapped with only string data type', ()
env: {account: "test-account", region: "us-east-1"}
})

const domainStack = openSearchStacks.stacks.filter((s) => s.stackName === "opensearchDomainStack")[0]
const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
assertAlternateDomainStackTemplate(domainTemplate)
})

test('Test openAccessPolicy setting creates access policy when enabled', () => {
const app = new App({
context: {
openAccessPolicyEnabled: true
}
})

const openSearchStacks = new StackComposer(app, {
env: {account: "test-account", region: "us-east-1"}
})

const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
// Check that openAccessPolicy is created
domainTemplate.resourceCountIs("Custom::OpenSearchAccessPolicy", 1)

})

test('Test openAccessPolicy setting does not create access policy when disabled', () => {
const app = new App({
context: {
openAccessPolicyEnabled: false
}
})

const openSearchStacks = new StackComposer(app, {
env: {account: "test-account", region: "us-east-1"}
})

const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
// Check that openAccessPolicy is not created
domainTemplate.resourceCountIs("Custom::OpenSearchAccessPolicy", 0)

})

test('Test openAccessPolicy setting is mapped with string data type', () => {
const app = new App({
context: {
openAccessPolicyEnabled: "true"
}
})

const openSearchStacks = new StackComposer(app, {
env: {account: "test-account", region: "us-east-1"}
})

const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
// Check that openAccessPolicy is created
domainTemplate.resourceCountIs("Custom::OpenSearchAccessPolicy", 1)

})

test( 'Test default stack is created with default values when no context options are provided', () => {
const app = new App({
context: {}
Expand All @@ -145,7 +219,7 @@ test( 'Test default stack is created with default values when no context options
})

const defaultValues: { [x: string]: (string); } = testDefaultValues
const domainStack = openSearchStacks.stacks.filter((s) => s.stackName === "opensearchDomainStack")[0]
const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
domainTemplate.resourceCountIs("AWS::OpenSearchService::Domain", 1)
domainTemplate.hasResourceProperties("AWS::OpenSearchService::Domain", {
Expand Down Expand Up @@ -178,7 +252,12 @@ test( 'Test default stack is created when empty context options are provided for
loggingAppLogEnabled: "",
loggingAppLogGroupARN: "",
nodeToNodeEncryptionEnabled: "",
vpcEnabled: "",
vpcId: "",
vpcSubnetIds: "",
vpcSecurityGroupIds: "",
availabilityZoneCount: "",
openAccessPolicyEnabled: "",
domainRemovalPolicy: ""
}
})
Expand All @@ -187,7 +266,7 @@ test( 'Test default stack is created when empty context options are provided for
env: {account: "test-account", region: "us-east-1"}
})

const domainStack = openSearchStacks.stacks.filter((s) => s.stackName === "opensearchDomainStack")[0]
const domainStack = openSearchStacks.stacks.filter((s) => s instanceof OpensearchServiceDomainCdkStack)[0]
const domainTemplate = Template.fromStack(domainStack)
domainTemplate.resourceCountIs("AWS::OpenSearchService::Domain", 1)
})
Expand Down Expand Up @@ -217,7 +296,11 @@ function assertPrimaryDomainStackTemplate(template: Template) {
InstanceCount: 5,
InstanceType: "r6.large.search",
WarmCount: 2,
WarmType: "ultrawarm1.medium.search"
WarmType: "ultrawarm1.medium.search",
ZoneAwarenessConfig: {
AvailabilityZoneCount: 3
},
ZoneAwarenessEnabled: true
},
DomainEndpointOptions: {
EnforceHTTPS: true,
Expand Down
51 changes: 51 additions & 0 deletions deployment/cdk/opensearch-service/test/network-stack.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import {App} from "aws-cdk-lib";
import {StackComposer} from "../lib/stack-composer";
import {NetworkStack} from "../lib/network-stack";
import {Template} from "aws-cdk-lib/assertions";

test('Test vpcEnabled setting that is disabled does not create stack', () => {
const app = new App({
context: {
vpcEnabled: false
}
})

const openSearchStacks = new StackComposer(app, {
env: {account: "test-account", region: "us-east-1"}
})

openSearchStacks.stacks.forEach(function(stack) {
expect(!(stack instanceof NetworkStack))
})

})

test('Test vpcEnabled setting that is enabled without existing resources creates default VPC resources', () => {
const app = new App({
context: {
vpcEnabled: true,
// This setting could be left out, but provides clarity into the subnets for this test case
availabilityZoneCount: 2
}
})

const openSearchStacks = new StackComposer(app, {
env: {account: "test-account", region: "us-east-1"}
})

const networkStack: NetworkStack = (openSearchStacks.stacks.filter((s) => s instanceof NetworkStack)[0]) as NetworkStack
const networkTemplate = Template.fromStack(networkStack)

networkTemplate.resourceCountIs("AWS::EC2::VPC", 1)
networkTemplate.resourceCountIs("AWS::EC2::SecurityGroup", 1)
// For each AZ, a private and public subnet is created
networkTemplate.resourceCountIs("AWS::EC2::Subnet", 4)

const securityGroups = networkStack.domainSecurityGroups
expect(securityGroups.length).toBe(1)
const subnets = networkStack.domainSubnets
expect(subnets).toBe(undefined)
const vpc = networkStack.vpc
expect(vpc.publicSubnets.length).toBe(2)
expect(vpc.privateSubnets.length).toBe(2)
})
Loading

0 comments on commit 2de79f2

Please sign in to comment.