Skip to main content

VPC

This example demonstrates building a VPC with an internet gateway, route table, and public subnets. This is exposed through an AwsEnvironment abstraction. This example also shows how consistent metadata labels and AWS tags can be applied across resources. This uses ACK for provisioning AWS resources.

aws-environment Workflow

apiVersion: koreo.dev/v1beta1
kind: Workflow
metadata:
name: aws-environment
spec:
crdRef:
apiGroup: acme.example.com
version: v1beta1
kind: AwsEnvironment
steps:
- label: config
ref:
name: aws-environment-config
kind: ValueFunction
inputs:
metadata: =parent.metadata

- label: metadata
ref:
name: aws-environment-metadata
kind: ValueFunction
inputs:
config: =steps.config

- label: resource_tags
ref:
name: aws-environment-tags
kind: ValueFunction
inputs:
config: =steps.config

- label: vpc
ref:
name: aws-environment-vpc
kind: ResourceFunction
inputs:
metadata: =steps.metadata
resource_tags: =steps.resource_tags
condition:
type: VPC
name: Environment VPC

- label: internet_gateway
ref:
name: aws-environment-internet-gateway
kind: ResourceFunction
inputs:
metadata: =steps.metadata
resource_tags: =steps.resource_tags
vpc: =steps.vpc
condition:
type: InternetGateway
name: Environment Internet Gateway

- label: public_route_table
ref:
name: aws-environment-public-route-table
kind: ResourceFunction
inputs:
metadata: =steps.metadata
resource_tags: =steps.resource_tags
vpc: =steps.vpc
internet_gateway: =steps.internet_gateway
condition:
type: RouteTable
name: Environment Public Route Table

- label: public_subnets
ref:
name: aws-environment-public-subnet
kind: ResourceFunction
forEach:
itemIn: =parent.spec.vpc.publicSubnets
inputKey: subnet
inputs:
metadata: =steps.metadata
resource_tags: =steps.resource_tags
subnet: =parent.spec.vpc.publicSubnets
public_route_table: =steps.public_route_table
vpc: =steps.vpc
condition:
type: PublicSubnet
name: Environment Public Subnet

aws-environment-config ValueFunction

apiVersion: koreo.dev/v1beta1
kind: ValueFunction
metadata:
name: aws-environment-config
spec:
return:
environment: =inputs.metadata.name
environment_namespace: =inputs.metadata.namespace
business_unit: |
=has(inputs.metadata.labels['acme.example.com/business-unit']) ?
inputs.metadata.labels['acme.example.com/business-unit'] : ""
product_line: |
=has(inputs.metadata.labels['acme.example.com/product-line']) ?
inputs.metadata.labels['acme.example.com/product-line'] : ""
domain: |
=has(inputs.metadata.labels['acme.example.com/domain']) ?
inputs.metadata.labels['acme.example.com/domain'] : ""
---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-config-test
spec:
functionRef:
name: aws-environment-config
kind: ValueFunction
inputs:
metadata:
name: test-aws-environment
namespace: test-namespace
labels:
acme.example.com/domain: domain
acme.example.com/business-unit: acme-bu
acme.example.com/product-line: acme-widgets

testCases:
- expectReturn:
business_unit: acme-bu
product_line: acme-widgets
domain: 'domain'
environment_namespace: test-namespace
environment: test-aws-environment
---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-config-test-partial
spec:
functionRef:
name: aws-environment-config
kind: ValueFunction
inputs:
metadata:
name: test-aws-environment
namespace: test-namespace

testCases:
- expectReturn:
business_unit: ''
product_line: ''
domain: ''
environment_namespace: test-namespace
environment: test-aws-environment

aws-environment-metadata ValueFunction

apiVersion: koreo.dev/v1beta1
kind: ValueFunction
metadata:
name: aws-environment-metadata
spec:
return:
name: =inputs.config.environment
namespace: =inputs.config.environment_namespace
labels:
app.kubernetes.io/managed-by: koreo
acme.example.com/domain: =inputs.config.app_domain_name
acme.example.com/environment: =inputs.config.environment
---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-metadata-test
spec:
functionRef:
name: aws-environment-metadata
kind: ValueFunction
inputs:
config:
environment: acme-test
environment_namespace: acme-ns
app_domain_name: test-domain
testCases:
- expectReturn:
labels:
app.kubernetes.io/managed-by: koreo
acme.example.com/domain: test-domain
acme.example.com/environment: acme-test
name: acme-test
namespace: acme-ns

aws-environment-tags ValueFunction

apiVersion: koreo.dev/v1beta1
kind: ValueFunction
metadata:
name: aws-environment-tags
spec:
return:
tags:
- key: business-unit
value: =inputs.config.business_unit
- key: product-line
value: =inputs.config.product_line
- key: domain
value: =inputs.config.domain
- key: environment
value: =inputs.config.environment
---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-tags-test
spec:
functionRef:
name: aws-environment-tags
kind: ValueFunction
inputs:
config:
environment: acme-test
environment_namespace: acme-ns
business_unit: acme-bu
product_line: acme-widgets
domain: test-domain
testCases:
- expectReturn:
tags:
- key: business-unit
value: acme-bu
- key: product-line
value: acme-widgets
- key: domain
value: test-domain
- key: environment
value: acme-test

aws-environment-vpc ResourceFunction

apiVersion: koreo.dev/v1beta1
kind: ResourceFunction
metadata:
name: aws-environment-vpc
spec:
apiConfig:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: VPC
name: =inputs.metadata.name
namespace: =inputs.metadata.namespace

resource:
metadata: =inputs.metadata
spec:
enableDNSHostnames: true
enableDNSSupport: true
cidrBlocks:
- 10.0.0.0/16
tags: =inputs.resource_tags.tags

postconditions:
- assert: =has(resource.status.vpcID)
retry:
message: Waiting for vpc to become healthy
delay: 5

return:
name: =inputs.metadata.name
vpc_id: =resource.status.vpcID
vpc_account_id: =resource.status.ownerID
---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-vpc-test
spec:
functionRef:
kind: ResourceFunction
name: aws-environment-vpc

inputs:
metadata:
name: test
namespace: test-namespace
resource_tags:
tags:
- key: test
value: value

testCases:
- expectResource:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: VPC
metadata:
name: test
namespace: test-namespace
spec:
cidrBlocks:
- 10.0.0.0/16
enableDNSHostnames: true
enableDNSSupport: true
tags:
- key: test
value: value
- overlayResource:
status:
vpcID: 123213323
ownerID: 213412341
expectReturn:
name: test
vpc_account_id: 213412341
vpc_id: 123213323

aws-environment-internet-gateway ResourceFunction

apiVersion: koreo.dev/v1beta1
kind: ResourceFunction
metadata:
name: aws-environment-internet-gateway
spec:
apiConfig:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: InternetGateway
name: =inputs.metadata.name
namespace: =inputs.metadata.namespace

create:
delay: 1

resource:
metadata: =inputs.metadata
spec:
vpcRef:
from:
name: =inputs.vpc.name
tags: =inputs.resource_tags.tags

postconditions:
- assert: =has(resource.status.internetGatewayID)
retry:
message: Waiting for internet gateway to become healthy
delay: 5

return:
name: =inputs.metadata.name
gateway_id: =resource.status.internetGatewayID
---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-internet-gateway-test
spec:
functionRef:
kind: ResourceFunction
name: aws-environment-internet-gateway
inputs:
vpc:
name: test-vpc
metadata:
name: test
namespace: test-namespace
resource_tags:
tags:
- key: test
value: value

testCases:
- expectResource:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: InternetGateway
metadata:
name: test
namespace: test-namespace
spec:
tags:
- key: test
value: value
vpcRef:
from:
name: test-vpc

---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-internet-gateway-test-validation
spec:
functionRef:
kind: ResourceFunction
name: aws-environment-internet-gateway
inputs:
vpc:
name: test-vpc
metadata:
name: test
namespace: test-namespace
resource_tags:
tags:
- key: test
value: value

currentResource:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: InternetGateway
metadata:
name: test
namespace: test-namespace
spec:
tags:
- key: test
value: value
vpcRef:
from:
name: test-vpc
status:
internetGatewayID: ig-2453445123

testCases:
- expectReturn:
name: test
gateway_id: ig-2453445123

aws-environment-public-route-table ResourceFunction

apiVersion: koreo.dev/v1beta1
kind: ResourceFunction
metadata:
name: aws-environment-public-route-table
spec:
locals:
metadata: |
=inputs.metadata.overlay({"name": inputs.metadata.name + "-public"})
apiConfig:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: RouteTable
name: =locals.metadata.name
namespace: =locals.metadata.namespace

resource:
metadata: =locals.metadata
spec:
vpcRef:
from:
name: =inputs.vpc.name
tags: =inputs.resource_tags.tags
routes:
- destinationCIDRBlock: 0.0.0.0/0
gatewayRef:
from:
name: =inputs.internet_gateway.name

create:
delay: 1

postconditions:
- assert: =has(resource.status.routeTableID)
retry:
message: Waiting for route table to become healthy
delay: 5

return:
name: =locals.metadata.name
route_table_id: =resource.status.routeTableID
---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-public-route-table-test
spec:
functionRef:
kind: ResourceFunction
name: aws-environment-public-route-table

inputs:
internet_gateway:
name: internet_gateway
vpc:
name: vpc
metadata:
name: test
namespace: test-namespace
resource_tags:
tags:
- key: test
value: value

testCases:
- expectResource:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: RouteTable
metadata:
name: test-public
namespace: test-namespace
spec:
routes:
- destinationCIDRBlock: 0.0.0.0/0
gatewayRef:
from:
name: internet_gateway
tags:
- key: test
value: value
vpcRef:
from:
name: vpc
- overlayResource:
status:
routeTableID: rt-12341234
expectReturn:
route_table_id: rt-12341234
name: test-public

aws-environment-public-subnet ResourceFunction

apiVersion: koreo.dev/v1beta1
kind: ResourceFunction
metadata:
name: aws-environment-public-subnet
spec:
locals:
metadata: |
=inputs.metadata.overlay({"name": inputs.metadata.name + "-" + inputs.subnet.name + "-public"})

apiConfig:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: Subnet
name: =locals.metadata.name
namespace: =locals.metadata.namespace

resource:
metadata: =locals.metadata
spec:
availabilityZone: =inputs.subnet.availabilityZone
cidrBlock: =inputs.subnet.cidrBlock
tags: =inputs.resource_tags.tags
mapPublicIPOnLaunch: true
vpcRef:
from:
name: =inputs.vpc.name
routeTableRefs:
- from:
name: =inputs.public_route_table.name

create:
delay: 1

postconditions:
- assert: =has(resource.status.subnetID)
retry:
message: Waiting for subnet to become healthy
delay: 5

return:
name: =locals.metadata.name
subnet_id: =resource.status.subnetID
---
apiVersion: koreo.dev/v1beta1
kind: FunctionTest
metadata:
name: aws-environment-public-subnet-test
spec:
functionRef:
kind: ResourceFunction
name: aws-environment-public-subnet
inputs:
metadata:
name: test
namespace: test-namespace
public_route_table:
name: public_route_table
resource_tags:
tags:
- key: test
value: value
subnet:
availabilityZone: us-west-2a
cidrBlock: 10.0.0.0/20
name: a
vpc:
name: vpc

testCases:
- expectResource:
apiVersion: ec2.services.k8s.aws/v1alpha1
kind: Subnet
metadata:
name: test-a-public
namespace: test-namespace
spec:
availabilityZone: us-west-2a
cidrBlock: 10.0.0.0/20
mapPublicIPOnLaunch: true
routeTableRefs:
- from:
name: public_route_table
tags:
- key: test
value: value
vpcRef:
from:
name: vpc

Example Trigger AwsEnvironment

apiVersion: acme.example.com/v1beta1
kind: AwsEnvironment
metadata:
name: test-aws-environment
labels:
acme.example.com/business-unit: acme-bu
acme.example.com/product-line: acme-widgets
acme.example.com/domain: acme-domain
spec:
vpc:
publicSubnets:
- cidrBlock: 10.0.128.0/20
availabilityZone: us-east-1a
name: a-public