<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Volkan Paksoy</title>
    <description>The latest articles on DEV Community by Volkan Paksoy (@volkanpaksoy).</description>
    <link>https://dev.to/volkanpaksoy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F259551%2F052a4456-db2f-4fa6-96c1-7e9850fde468.png</url>
      <title>DEV Community: Volkan Paksoy</title>
      <link>https://dev.to/volkanpaksoy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/volkanpaksoy"/>
    <language>en</language>
    <item>
      <title>Migrating an EC2 Instance to a Different AWS Account</title>
      <dc:creator>Volkan Paksoy</dc:creator>
      <pubDate>Wed, 18 Mar 2020 06:00:00 +0000</pubDate>
      <link>https://dev.to/volkanpaksoy/migrating-an-ec2-instance-to-a-different-aws-account-35k7</link>
      <guid>https://dev.to/volkanpaksoy/migrating-an-ec2-instance-to-a-different-aws-account-35k7</guid>
      <description>&lt;p&gt;Recently I needed to migrate an EC2 instance to a different AWS account. There’s no built-in functionality to handle this. The solution is creating an AMI from the instance and sharing it with the target account. I scripted my solution with Powershell and AWS Tools for Powershell as below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Since the operation involves a source account and a target account, first create 2 profiles with EC2 access. credentials files should look like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[source_profile]
aws_access_key_id = xxxxxxxxx
aws_secret_access_key = xxxxxxxxx

[target_profile]
aws_access_key_id = xxxxxxxxx
aws_secret_access_key = xxxxxxxxx

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 00: Configuration
&lt;/h2&gt;

&lt;p&gt;I put all the variables in a Powershell script file which I include in the following steps. To use the scripts you need to provide the values first. Hopefully the variable names are self-explanatory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$sourceAccountAwsProfileName = ""
$sourceRegion = ""
$sourceAccountId = ""
$instanceId = ""
$amiName = ""
$amiDescription = ""
$targetAccountAwsProfileName = ""
$targetAccountId = ""
$targetRegion = ""

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 01: Create AMI
&lt;/h2&gt;

&lt;p&gt;First step to migrate EC2 instance is to create an AMi from the instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;. .\"00. configuration.ps1"

# Create AMI
$imageId = New-EC2Image -InstanceId $instanceId -Name $amiName -Description $amiDescription -ProfileName $sourceAccountAwsProfileName -Region $sourceRegion

Set-Variable -Scope global -Name AMI_ID -Value $imageId
Write-Host "AMI_ID: [" $AMI_ID "]"

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This operation takes a few minutes. The image has to become available before we can proceed to the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 02: Share AMI
&lt;/h2&gt;

&lt;p&gt;Now the image is ready we have to share it with the target account. The script below shares the AMI and allows new volumes created from this AMI.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;. .\"00. configuration.ps1"

$imageId = Get-Variable AMI_ID -valueOnly
Edit-EC2ImageAttribute -ImageId $imageId -Attribute launchPermission -OperationType add -UserId $targetAccountId -ProfileName $sourceAccountAwsProfileName -Region $sourceRegion

$imageSnapshots = Get-EC2Snapshot -OwnerId $sourceAccountId -ProfileName $sourceAccountAwsProfileName -Region $sourceRegion
                | Where-Object {$_.Description -like "*$imageId*" }

foreach ($snapshot in $imageSnapshots) {
    Edit-EC2SnapshotAttribute -SnapshotId $snapshot.SnapshotId -Attribute createVolumePermission -OperationType add -UserId $targetAccountId -ProfileName $sourceAccountAwsProfileName -Region $sourceRegion
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 03: Copy AMI
&lt;/h2&gt;

&lt;p&gt;At this point, if you go to the target account you should be able to see the image when you choose “Private images” category. Make sure to choose the same region as the source account to be able to see the image.&lt;/p&gt;

&lt;p&gt;We have access to this image but we want to have our own copy which we accomplish with the script below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;. .\"00. configuration.ps1"

$imageId = Get-Variable AMI_ID -valueOnly
Copy-EC2Image -SourceImageId $imageId -SourceRegion $sourceRegion -Name $amiName -ProfileName $targetAccountAwsProfileName -Region $targetRegion

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In my experience the whole copying process took about 5 minutes.&lt;/p&gt;

&lt;p&gt;Now that we have our own copy of the AMI we can launch instances as we please. Job (almost) done!&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 04: Clean Up
&lt;/h2&gt;

&lt;p&gt;Final step is to clean up after ourselves. Since this AMI was created to migrate to the new account only I assume we won’t need it anymore in the source account. The following script deregisters the AMI and deletes all the associated snapshots.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;. .\"00. configuration.ps1"

# Create image script writes the AMI ID to a variable. If it doesn't exist get the image id from AWS Management Console
$imageId = Get-Variable AMI_ID -valueOnly

Write-Host "Unregistering image: [" $imageId "]"
Unregister-EC2Image -ImageId $imageId -ProfileName $sourceAccountAwsProfileName -Region $sourceRegion

$imageSnapshots = Get-EC2Snapshot -OwnerId $sourceAccountId -ProfileName $sourceAccountAwsProfileName -Region $sourceRegion
                | Where-Object {$_.Description -like "*$imageId*" }

foreach ($snapshot in $imageSnapshots) {
    Write-Host "Removing snapshot: [" $snapshot.SnapshotId "]"
    Remove-EC2Snapshot -SnapshotId $snapshot.SnapshotId -Force -ProfileName $sourceAccountAwsProfileName -Region $sourceRegion
}

# Delete variable
Remove-Variable AMI_ID -Scope global

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/volkanpaksoy/lab/tree/master/blog/migrate-ec2-instance-to-another-account"&gt;Source Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/account-transfer-ec2-instance/"&gt;How do I transfer an Amazon EC2 instance to a different AWS account?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://alestic.com/2014/02/ec2-create-image-reboot/"&gt;EC2 create-image Does Not Fully “Stop” The Instance&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
    </item>
    <item>
      <title>Infrastructure as Code with AWS CloudFormation and Cloud Development Kit (CDK)</title>
      <dc:creator>Volkan Paksoy</dc:creator>
      <pubDate>Sat, 26 Oct 2019 12:00:00 +0000</pubDate>
      <link>https://dev.to/volkanpaksoy/infrastructure-as-code-with-aws-cloudformation-and-cloud-development-kit-cdk-31gi</link>
      <guid>https://dev.to/volkanpaksoy/infrastructure-as-code-with-aws-cloudformation-and-cloud-development-kit-cdk-31gi</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Using AWS is great as it simplifies and improves infrastructure provisioning and maintenance quite a lot. As you depend more and more on AWS you quickly realize that managing everything through AWS Management Console is not an ideal way.&lt;/p&gt;

&lt;p&gt;Earlier this year, I published this &lt;a href="https://volkanpaksoy.com/archive/2019/01/15/Infrastructure-as-code-with-AWS-CloudFormation/"&gt;post&lt;/a&gt; about AWS CloudFormation. This post will also discuss using CloudFormation but by taking it a higher level by using AWS Cloud Development Kit (CDK).&lt;/p&gt;

&lt;h2&gt;
  
  
  Levels of infrastructure
&lt;/h2&gt;

&lt;p&gt;I liked the way the several approaches of infrastructure management is illustrated as levels here: &lt;a href="https://www.youtube.com/watch?v=184S7ki6fJA"&gt;Develop a Web App Using Amazon ECS and AWS Cloud Development Kit (CDK) - AWS Online Tech Talks (YouTube Video)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In a nutshell, those levels are:&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 0: By hand
&lt;/h3&gt;

&lt;p&gt;This approach is simply using AWS Management Console user interface to manage the infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple and easy&lt;/li&gt;
&lt;li&gt;Helps to get results faster for exploratory projects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hard to reproduce&lt;/li&gt;
&lt;li&gt;Possible inconsistencies based on people’s preferences&lt;/li&gt;
&lt;li&gt;Error-prone&lt;/li&gt;
&lt;li&gt;Slow for complex systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Level 1: Imperative Infrastructure as Code
&lt;/h3&gt;

&lt;p&gt;In this approach you write your own scripts using AWS SDK and manage the resources programmatically.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Repeatable and reusable&lt;/li&gt;
&lt;li&gt;Can be source-controlled&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lots of boilerplate code&lt;/li&gt;
&lt;li&gt;It needs to address all edge cases&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Level 2: Declarative Infrastructure as Code
&lt;/h3&gt;

&lt;p&gt;Describe the infrastructure as a script (in JSON or YAML) and use an resource provisioning engine such as AWS CloudFormation or HashiCorp Terraform which in turn use AWS SDK to manage the infrastructure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No boilerplate&lt;/li&gt;
&lt;li&gt;Creating and updating resources is handled automatically&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Templates can become verbose&lt;/li&gt;
&lt;li&gt;Implementing logic is limited to some built-in helper functions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Level 3: AWS Cloud Development Kit
&lt;/h3&gt;

&lt;p&gt;In this approach software is developed using AWS CDK which generates the input for AWS CloudFormation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--B2xznRjP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-overview.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--B2xznRjP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-overview.jpg" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The application can be developed in a number of languages. At the time of this writing the following languages are supported: TypeScript, JavaScript, Python, Java, C#.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Handles creation of underlying resources. For example, when creating a VPC it also automatically generates YAML for all other networking resources (routing tables, NAT gateways etc) that are required by VPC.&lt;/li&gt;
&lt;li&gt;Helps with local workflow&lt;/li&gt;
&lt;li&gt;CDK constructs are reusable. Can be developed by AWS or third parties and can be installed separately.&lt;/li&gt;
&lt;li&gt;Ability to use familiar programming languages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Extra installation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Basic Concepts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Construct:&lt;/strong&gt; Basic building block for an AWS CDK app. Represents a “cloud component” and encapsulates everything AWS CloudFormation needs to create the component. They can be developed or downloaded from &lt;a href="https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html"&gt;AWS Construct Library&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stack:&lt;/strong&gt; Constructs need to be created within the scope of a Stack. This corresponds to a CloudFormation template.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;App:&lt;/strong&gt; Stacks are created in the scope of an App. An App can contain multiple stacks.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  CDK Basics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;In order to create an application that uses CDK we need to install the CDK&lt;/li&gt;
&lt;li&gt;The application can have one of the 3 supported templates:

&lt;ul&gt;
&lt;li&gt;app: General purpose application. This is the default template&lt;/li&gt;
&lt;li&gt;lib: Used to develop a CDK construct&lt;/li&gt;
&lt;li&gt;sample-app: Creates an application already populated with a sample CDK application.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The following diagram illustrates the app lifecycle:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--o5_CjLF0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-app-lifecycle.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--o5_CjLF0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-app-lifecycle.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing CDK
&lt;/h2&gt;

&lt;p&gt;AWS CDK is developed using TypeScript. It’s available via npm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g aws-cdk

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Using CDK
&lt;/h2&gt;

&lt;p&gt;In my example, I will use C#. A new project can be created by using &lt;strong&gt;cdk init&lt;/strong&gt; command:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7MMfUB4n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-init.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7MMfUB4n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-init.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It expects 2 parameters: Language (Can be one of these: csharp, fsharp, java, javascript, python or typescript).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk init app --language csharp

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To test my first app, I followed the sample app provided and added an S3 construct to my code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CdkWorkoutStack : Stack
{
    public CdkWorkoutStack(Construct parent, string id, IStackProps props) : base(parent, id, props)
    {
        _ = new Bucket(this, "CdkBucket", new BucketProps
        {
            Versioned = true
        });
    }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Next step is to synnthesize a CloudFormation template by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk synth

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This generates a folder called cdk.out which contains a file named CdkWorkoutStack.template.json and with the following contents:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Resources": {
    "CdkBucket2FB0D10E": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "VersioningConfiguration": {
          "Status": "Enabled"
        }
      },
      "UpdateReplacePolicy": "Retain",
      "DeletionPolicy": "Retain",
      "Metadata": {
        "aws:cdk:path": "CdkWorkoutStack/CdkBucket/Resource"
      }
    }
  }
}  

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Final step is to create the resources by running&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk deploy

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This produces the following results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--5bHMnFWI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-deployment-results.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--5bHMnFWI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-deployment-results.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And not surprisingly a CloudFormation stack with the bucket is created in AWS.&lt;/p&gt;

&lt;p&gt;In the next version I’m going to change some properties of the bucket such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CdkWorkoutStack : Stack
{
    public CdkWorkoutStack(Construct parent, string id, IStackProps props) : base(parent, id, props)
    {
        _ = new Bucket(this, "CdkBucket", new BucketProps
        {
            Versioned = true,
            BlockPublicAccess = new BlockPublicAccess(new BlockPublicAccessOptions()
            {
                BlockPublicAcls = true,
                BlockPublicPolicy = true
            })
        });
    }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After this change in the code we can review what’s going to be updated by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk diff

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and it produces the following result outlining the changes between the current code and the deployed version:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--daXJCUra--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-diff-results.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--daXJCUra--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/10/aws_cdk/aws-cdk-diff-results.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the stack can be deleted by running the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cdk destroy

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the CDK version I’m using the default deletion policy is to retain. That’s why when I deleted the stack via CDK it didn’t delete the bucket. In order to change that behaviour I had to change the value to delete as such:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class CdkWorkoutStack : Stack
{
    public CdkWorkoutStack(Construct parent, string id, IStackProps props) : base(parent, id, props)
    {
        var bucket = new Bucket(this, "CdkBucket", new BucketProps
        {
            Versioned = true,
            BlockPublicAccess = new BlockPublicAccess(new BlockPublicAccessOptions()
            {
                BlockPublicAcls = true,
                BlockPublicPolicy = true
            })
        });

        var resource = bucket.Node.FindChild("Resource") as Amazon.CDK.CfnResource;
        resource.ApplyRemovalPolicy(RemovalPolicy.DESTROY);
    }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This time it produces a CloudFormation template with a different policy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Resources": {
    "CdkBucket2FB0D10E": {
      "Type": "AWS::S3::Bucket",
      "Properties": {
        "PublicAccessBlockConfiguration": {
          "BlockPublicAcls": true,
          "BlockPublicPolicy": true
        },
        "VersioningConfiguration": {
          "Status": "Enabled"
        }
      },
      "UpdateReplacePolicy": "Delete",
      "DeletionPolicy": "Delete",
      "Metadata": {
        "aws:cdk:path": "CdkWorkoutStack/CdkBucket/Resource"
      }
    }
  }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This time after destroy command it did delete the bucket as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I think infrastructure as code is definitely the way to manage cloud resources and CDK provides a great way to simplify the process. It’s at early stages for the time being as the NuGet packages are in devpreview mode but it’s good enough to rely on and start developing with CDK.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=Lh-kVC2r2AU"&gt;AWS re:Invent 2018: Infrastructure Is Code with the AWS Cloud Development Kit (DEV372) (YouTube Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.youtube.com/watch?v=184S7ki6fJA"&gt;Develop a Web App Using Amazon ECS and AWS Cloud Development Kit (CDK) - AWS Online Tech Talks (YouTube Video)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/en_pv/cdk/latest/guide/getting_started.html"&gt;AWS Documentation: Getting Started With the AWS CDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cdk/api/latest/docs/aws-construct-library.html"&gt;AWS CDK Construct Library&lt;/a&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sNgYoied--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/PlaygroundForTheMind/%257E4/vwij0F6WILU" alt=""&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>cdk</category>
    </item>
    <item>
      <title>Generating Test Data with Bogus</title>
      <dc:creator>Volkan Paksoy</dc:creator>
      <pubDate>Thu, 27 Jun 2019 06:00:00 +0000</pubDate>
      <link>https://dev.to/volkanpaksoy/generating-test-data-with-bogus-12me</link>
      <guid>https://dev.to/volkanpaksoy/generating-test-data-with-bogus-12me</guid>
      <description>&lt;p&gt;Generating high-quality test data can have an impact on the accuracy of the tests overall. In this post I’ll show using a helpful C# library called &lt;a href="https://github.com/bchavez/Bogus"&gt;Bogus&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Showcase project: Bank Statement Generator
&lt;/h2&gt;

&lt;p&gt;In this example I’ll generate fake bank statements. Normally they come in CSV files and have the following model:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public class BankStatementLine
{
    public DateTime TransactionDate { get; set; }
    public string TransactionType { get; set; }
    public string SortCode { get; set; }
    public string AccountNumber { get; set; }
    public string TransactionDescription { get; set; }
    public decimal? DebitAmount { get; set; }
    public decimal? CreditAmount { get; set; }
    public decimal Balance { get; set; }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’ll use Bogus to generate realistic fake statement lines and finally save it as a CSV and see if it looks real.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rules and restrictions
&lt;/h2&gt;

&lt;p&gt;I want the fields in the model above conform to certain set of rules to be realistic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Transaction Date must be within a certain range I provide as bank statements are generated for a date range.&lt;/li&gt;
&lt;li&gt;Dates should be incremental and not random&lt;/li&gt;
&lt;li&gt;Sort Code must be in the following format: NN-NN-NN and must be the same for the entire statement.&lt;/li&gt;
&lt;li&gt;Account number must be an 8-digit number and same for the entire statement.&lt;/li&gt;
&lt;li&gt;Transaction Description must be free text&lt;/li&gt;
&lt;li&gt;Debit Amount and Credit Amount must be decimal numbers but only one of them can be present at any given line&lt;/li&gt;
&lt;li&gt;Transaction Type must be one of the pre-defined values and also some types can be for credit and some for debit only.&lt;/li&gt;
&lt;li&gt;Balance should be sum of all debit and credit amounts plus the first balance in the statement. So this value is dependent on the values that come before it.&lt;/li&gt;
&lt;li&gt;The number of lines in a statement should be random.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Rule implementations
&lt;/h2&gt;

&lt;p&gt;Some rules stated above are very straightforward and easy to implement. These are some samples of what Bogus is capable of. For the full documentation check out the GitHub repository.&lt;/p&gt;

&lt;h3&gt;
  
  
  Date range support
&lt;/h3&gt;

&lt;p&gt;Generating a date between a range is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.TransactionDate, f =&amp;gt; f.Date.Between(startDate, endDate))

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Enum and array support
&lt;/h3&gt;

&lt;p&gt;For Transaction Type I want to select a random value from a list of set values. This can be done in 2 ways: By using an enum or an IEnumerable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var transactionTypes = new[] { "FPO", "DEB", "DB", "FPI" };

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and in the rule description it can be used as&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.TransactionType, f =&amp;gt; f.PickRandom(transactionTypes) )

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Another way is using enums such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public enum TransactionType
{
    FPO,
    DEB,
    DB,
    FPI
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;and the rule becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; .RuleFor(x =&amp;gt; x.TransactionType, f =&amp;gt; f.PickRandom&amp;lt;TransactionType&amp;gt;().ToString())

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In my final implementation I used selecting from a list of objects. You can check out the &lt;a href="https://github.com/volkanpaksoy/lab/tree/master/blog/GeneratingTestDataWithBogus"&gt;sample code&lt;/a&gt; to see that version.&lt;/p&gt;

&lt;h3&gt;
  
  
  Number range
&lt;/h3&gt;

&lt;p&gt;For the account number I need an 8-digit number which can be achieved with something like this rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.AccountNumber, f =&amp;gt; f.Random.Long(100000000, 99999999).ToString())

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Bogus API also has builtin support for account number so the following is a more elegant and expressive way of achieving the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.AccountNumber, f =&amp;gt; f.Finance.Account())

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Formatting string
&lt;/h3&gt;

&lt;p&gt;Formatting Sort Code can be achieved by Field.Random.Replace method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.SortCode, f =&amp;gt; f.Random.Replace("##-##-##"))

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Similar to account number, it also has built-in support for sort code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.SortCode, f =&amp;gt; f.Finance.SortCode())

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Null values
&lt;/h3&gt;

&lt;p&gt;In my case in some fields I’d like to have null values too. This can be achieved by &lt;em&gt;OrNull&lt;/em&gt; extension method. For example, in the code below it generates %20 of DebitAmount values null.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.DebitAmount, f =&amp;gt; f.Random.Decimal(0.00m, 9999.00m).OrNull(f, 0.2f))

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Common fields
&lt;/h3&gt;

&lt;p&gt;In my case some values in each statement line repeat throughout the entire statement such as account number and sort code. To achieve that I created a “base” statement line and every fake statement line used these shared fields instead of generating new ones.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var commonFields = new Faker&amp;lt;BankStatementLine&amp;gt;()
    .RuleFor(x =&amp;gt; x.AccountNumber, f =&amp;gt; f.Finance.Account())
    .RuleFor(x =&amp;gt; x.SortCode, f =&amp;gt; f.Finance.SortCode())
    .Generate();

var fakeTransactions = new Faker&amp;lt;BankStatementLine&amp;gt;()
    .StrictMode(true)
    .RuleFor(x =&amp;gt; x.AccountNumber, commonFields.AccountNumber)
    .RuleFor(x =&amp;gt; x.SortCode, f =&amp;gt; commonFields.SortCode)
    ...
    ...

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Random number of objects
&lt;/h3&gt;

&lt;p&gt;It’s more realistic to have varying number of lines in statements. With Generate method you can specify the exact number of items you want to generate which is good for unit tests. For my purposes I just wanted to create random of rows in each statement as I only needed the data to be imported. This can be achieved by GenerateBetween:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var statementLines = fakeTransactions.GenerateBetween(10, 20);

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Dependent values
&lt;/h3&gt;

&lt;p&gt;The tricky part in this scenario was the dependent values. Normally when you use RuleFor extension method it generates the value for that field alone in isolation. In my case, one restriction was Debit Amount and Credit Amount could not both have values in the same line. Also Balance depends on these values and needs to be calculated in each line.&lt;/p&gt;

&lt;p&gt;As far as I can tell there’s no built-in support to define these dependencies. Based on my tests I was able to achieve this in 2 ways&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update the values accordingly in &lt;strong&gt;FinishWith&lt;/strong&gt; extension method&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Rules&lt;/strong&gt; extension method to define multiple rules at once and implement the restrictions inside it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think the latter is a better solution as FinishWith sounds more like clean up, logging or similar extra activity where Rules sound more like actual business logic implementation.&lt;/p&gt;

&lt;p&gt;So with that in mind my rules for Debit Amount, Credit Amount and Balance fields looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.Rules((f, x) =&amp;gt;
{
    var debitAmount = (decimal?)f.Random.Decimal(1, 100).OrNull(f, 1.0f - statementconfig.DebitTransactionRatio);
    if (debitAmount.HasValue) // Is it a debit transaction?
    {
        x.CreditAmount = null;
        x.DebitAmount = debitAmount.Value;
        balance -= x.DebitAmount.Value;

        x.TransactionType = f.PickRandom(TransactionType.AllTransactionTypes
            .Where(tt =&amp;gt; tt.Direction == TransactionDirection.Debit || tt.Direction == TransactionDirection.DebitOrCredit)
            .Select(tt =&amp;gt; tt.Code));
    }
    else
    {
        var creditAmount = f.Random.Decimal(1, 100);
        x.DebitAmount = null;
        x.CreditAmount = creditAmount;

        balance += x.CreditAmount.Value;

        x.TransactionType = f.PickRandom(TransactionType.AllTransactionTypes
            .Where(tt =&amp;gt; tt.Direction == TransactionDirection.Credit || tt.Direction == TransactionDirection.DebitOrCredit)
            .Select(tt =&amp;gt; tt.Code));
    }

    x.Balance = balance;
});

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;A caveat with this approach is that I cannot use &lt;strong&gt;StrictMode&lt;/strong&gt; anymore as it complains about those 3 fields having null values. It specifically mentions that in the exception. If you use Rules you’re on your own to ensure that all fields are populated properly.&lt;/p&gt;

&lt;p&gt;Another drawback of setting multiple rules at once is that it can easily make the code harder to read. Fortunately for me, the author of the library &lt;a href="https://bchavez.bitarmory.com/"&gt;Brian Chavez&lt;/a&gt; kindly reviewed the code and suggested some refactorings one of which proved it was still possible to use &lt;strong&gt;RuleFor&lt;/strong&gt; method and strict mode. I’ve updated the final source code with these refactorings. So with individual rules the implementation looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.DebitAmount, f =&amp;gt;
{
    return (decimal?)f.Random.Decimal(1, 100).OrNull(f, 1.0f - statementconfig.DebitTransactionRatio);
})
.RuleFor(x =&amp;gt; x.CreditAmount, (f, x) =&amp;gt;
{
    return x.IsCredit() ? (decimal?)f.Random.Decimal(1, 100) : null;
})
.RuleFor(x =&amp;gt; x.TransactionType, (f, x) =&amp;gt;
{
    if (x.IsCredit())
    {
        return RandomTxCode(TransactionDirection.Credit); ;
    }
    else
    {
        return RandomTxCode(TransactionDirection.Debit);
    }

    string RandomTxCode(TransactionDirection direction)
    {
        return f.PickRandom(TransactionType.AllTransactionTypes
            .Where(tt =&amp;gt; tt.Direction == direction || tt.Direction == TransactionDirection.DebitOrCredit)
            .Select(tt =&amp;gt; tt.Code));
    }
})
.RuleFor(x =&amp;gt; x.Balance, (f, x) =&amp;gt;
{
    if (x.IsCredit())
        balance += x.CreditAmount.Value;
    else
        balance -= x.DebitAmount.Value;

    return balance;
});

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;IsDebit and IsCredit methods referred to above are extension methods defined like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public static class Extensions
{
   public static bool IsCredit(this BankStatementLine bsl)
   {
      return bsl.DebitAmount is null;
   }
   public static bool IsDebit(this BankStatementLine bsl)
   {
      return !IsCredit(bsl);
   }
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Random text
&lt;/h3&gt;

&lt;p&gt;For the transaction description for now I’ll go with random Lorem Ipsum texts. Bogus has support for this too&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.TransactionDescription, f =&amp;gt; f.Lorem.Sentence(3))

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I probably will need to use a fixed list of descriptions soon but for the time being it’s fine. Also as shown below it’s very easy to switch to that too.&lt;/p&gt;

&lt;h3&gt;
  
  
  Incremental values
&lt;/h3&gt;

&lt;p&gt;Similar to balance being dependent on the previous values, transaction date is also dependent as it needs to go in an incremental fashion. I couldn’t find built-in support for this so implemented it using my own shared variable like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.RuleFor(x =&amp;gt; x.TransactionDate, f =&amp;gt;
{
    lastDate = lastDate.AddDays(f.Random.Double(0, statementconfig.TransactionDateInterval));
    if (lastDate.Date &amp;gt; statementconfig.EndDate)
    {
        lastDate = statementconfig.EndDate;
    }
    return lastDate;
})

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Putting It All Together
&lt;/h2&gt;

&lt;p&gt;So let’s see the output with the help of another nice library called &lt;a href="https://github.com/khalidabuhakmeh/ConsoleTables"&gt;Console Tables&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---JDjTQI6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/06/generating-test-data-with-bogus-output.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---JDjTQI6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://volkanpaksoy.com/images/vpblogimg/2019/06/generating-test-data-with-bogus-output.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Source Code
&lt;/h2&gt;

&lt;p&gt;Sample application can be found under blog/GeneratingTestDataWithBogus folder in the repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/bchavez/Bogus"&gt;Bogus GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/khalidabuhakmeh/ConsoleTables"&gt;Console Tables repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/volkanpaksoy/lab/tree/master/blog/GeneratingTestDataWithBogus"&gt;Sample source code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://bchavez.bitarmory.com/"&gt;Author Brian Chavez’s website&lt;/a&gt;
&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--enxFOrtF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/http://feeds.feedburner.com/%257Er/PlaygroundForTheMind/%257E4/9LiZ000ToT0" alt=""&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
