Skip to content

Commit

Permalink
feature : add s3 backend config
Browse files Browse the repository at this point in the history
  • Loading branch information
mvillafuertem committed Oct 19, 2023
1 parent f07934e commit 35bf788
Show file tree
Hide file tree
Showing 15 changed files with 706 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/modules/vpc/src/main/resources/stacks/
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,91 @@ AWS is a project with many proof of concept modules...

## Initial Configuration

### S3Backend

> **Note**
>
> if you change scala code, you need to rerun main
> ```shell
>
> sbt vpc/runMain io.github.mvillafuertem.Main2
>
> ```
1. Comment S3Backend resource which is inside Terraform.scala
```scala
// private val _: S3Backend = S3Backend.Builder
// .create(self)
// .bucket(configuration.bucket)
// .key("backend/terraform.tfstate")
// .region("eu-west-2")
// .dynamodbTable(configuration.dynamodbTable)
// .encrypt(true)
// .profile("gbgdev")
// .build()
```
2. Create backend stack

```shell

cd modules/vpc/src/main/resources/stacks/mvillafuertem-backend

terraform apply

...
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
....

```

3. Uncomment S3Backend resource which is inside Terraform.scala

```shell

terraform apply

│ Error: Backend initialization required: please run "terraform init"
│ Reason: Backend type changed from "local" to "s3"
...

```
4. Run terraform init again

```shell

terraform init -migrate-state

Initializing the backend...
Terraform detected that the backend type changed from "local" to "s3".

Do you want to copy existing state to the new backend?
...

Enter a value: yes

```

5. Check everything is ok

```shell

terraform plan

No changes. Your infrastructure matches the configuration.

```

## Using AWS profile

```shell

terraform init -var="profile=myprofile"

terraform init -backend-config="profile=myprofile"

```

Expand Down
8 changes: 8 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,14 @@ lazy val iam = (project in file("modules/iam"))
.settings(libraryDependencies += "com.dimafeng" %% "testcontainers-scala-core" % "0.40.12" % IntegrationTest)
.dependsOn(cdktf)

lazy val vpc = (project in file("modules/vpc"))
.configs(IntegrationTest)
.settings(Defaults.itSettings)
.settings(scalaVersion := scala213)
.settings(libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.15" % Test)
.settings(libraryDependencies += "com.dimafeng" %% "testcontainers-scala-core" % "0.40.12" % IntegrationTest)
.dependsOn(cdktf)

def welcomeMessage: Def.Setting[String] = onLoadMessage := {
def header(text: String): String = s"${csl.BOLD}${csl.MAGENTA}$text${csl.RESET}"
def cmd(text: String, description: String = "") = f"${csl.GREEN}> ${csl.CYAN}$text%10s $description${csl.RESET}"
Expand Down
19 changes: 19 additions & 0 deletions modules/vpc/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "iam",
"version": "0.1.0",
"description": "",
"license": "MIT",
"scripts": {
"initial": "cd ./src/main/resources/stacks/asdfadjkfaskdf && terraform init",
"applyInitial": "cd ./src/main/resources/stacks/mvillafuertem-cdktf-state && terraform apply",
"applyInitial": "cd ./src/main/resources/stacks/mvillafuertem-cdktf-state && terraform apply",
"destroyInitial": "cd ./src/main/resources/stacks/mvillafuertem-cdktf-state && terraform destroy",
"outputInitial": "cd ./src/main/resources/stacks/mvillafuertem-cdktf-state && terraform output -json",
"applyVpc": "cd ./src/main/resources/stacks/mvillafuertem-cdktf-vpc && terraform apply",
"destroyVpc": "cd ./src/main/resources/stacks/mvillafuertem-cdktf-vpc && terraform destroy",
"planVpc": "cd ./src/main/resources/stacks/mvillafuertem-cdktf-vpc && terraform init -migrate-state && terraform plan"
},
"dependencies": {},
"devDependencies": {},
"private": true
}
21 changes: 21 additions & 0 deletions modules/vpc/src/main/resources/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"version": "0.19.0",
"stacks": {
"mvillafuertem-backend": {
"name": "mvillafuertem-backend",
"constructPath": "mvillafuertem-backend",
"workingDirectory": "stacks/mvillafuertem-backend",
"synthesizedStackPath": "stacks/mvillafuertem-backend/cdk.tf.json",
"annotations": [],
"dependencies": []
},
"mvillafuertem-dev": {
"name": "mvillafuertem-dev",
"constructPath": "mvillafuertem-dev",
"workingDirectory": "stacks/mvillafuertem-dev",
"synthesizedStackPath": "stacks/mvillafuertem-dev/cdk.tf.json",
"annotations": [],
"dependencies": []
}
}
}
37 changes: 37 additions & 0 deletions modules/vpc/src/main/scala/io/github/mvillafuertem/Main.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.github.mvillafuertem

import com.hashicorp.cdktf.AppConfig

import scala.jdk.CollectionConverters._

object Main extends App {

private implicit val app: com.hashicorp.cdktf.App = new com.hashicorp.cdktf.App(
AppConfig
.builder()
.stackTraces(false)
.outdir("modules/vpc/src/main/resources/")
.context(
Map(
"excludeStackIdFromLogicalIds" -> true,
"allowSepCharsInLogicalIds" -> true
).asJava
)
.build()
)

private implicit val id: String = getClass.getPackage.getName
.split("\\.")
.last

private val commonTags = Map(
"CreatedBy" -> "scala-cdktf"
)

// dev
backend.BackendStack(commonTags)(app, id)
dev.DevStack(commonTags)(app, id)

app.synth()

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package io.github.mvillafuertem.backend

import com.hashicorp.cdktf.TerraformOutput
import io.github.mvillafuertem.aws.dynamodb_table.{ DynamodbTable, DynamodbTableAttribute }
import io.github.mvillafuertem.aws.s3_bucket._
import io.github.mvillafuertem.aws.s3_bucket_server_side_encryption_configuration.{
S3BucketServerSideEncryptionConfigurationA,
S3BucketServerSideEncryptionConfigurationRuleA,
S3BucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefaultA
}
import io.github.mvillafuertem.aws.s3_bucket_versioning.{ S3BucketVersioningA, S3BucketVersioningVersioningConfiguration }
import io.github.mvillafuertem.backend.Backend.BackendConfiguration
import software.constructs.Construct

import scala.jdk.CollectionConverters._

final case class Backend(configuration: BackendConfiguration)(implicit scope: Construct, id: String) extends Construct(scope, id) {
self: Construct =>

private val s3Bucket: S3Bucket = S3Bucket.Builder
.create(self, "s3")
.bucket(configuration.bucket)
.forceDestroy(true)
.tags(configuration.commonTags.asJava)
.build()

S3BucketServerSideEncryptionConfigurationA.Builder
.create(self, "s3_server_side_encryption")
.bucket(s3Bucket.getBucket)
.rule(
Seq(
S3BucketServerSideEncryptionConfigurationRuleA
.builder()
.applyServerSideEncryptionByDefault(
S3BucketServerSideEncryptionConfigurationRuleApplyServerSideEncryptionByDefaultA
.builder()
.sseAlgorithm("AES256")
.build()
)
.build()
).asJava
)
.build()

S3BucketVersioningA.Builder
.create(self, "s3_versioning")
.bucket(s3Bucket.getBucket)
.versioningConfiguration(
S3BucketVersioningVersioningConfiguration
.builder()
.status("Enabled")
.build()
)
.build()

private val dynamodbTable: DynamodbTable = DynamodbTable.Builder
.create(self, "dynamodb")
.name(configuration.dynamodbTable)
.billingMode("PAY_PER_REQUEST")
.hashKey("LockID")
.attribute(List(DynamodbTableAttribute.builder().name("LockID").`type`("S").build()).asJava)
.tags(configuration.commonTags.asJava)
.build()

private val _: TerraformOutput = TerraformOutput.Builder
.create(self, "tfstate_output")
.value(s"${s3Bucket.getArn}")
.build()

}

object Backend {

final case class BackendConfiguration(
bucket: String,
dynamodbTable: String,
commonTags: Map[String, String]
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package io.github.mvillafuertem.backend

import io.github.mvillafuertem.backend.Backend.BackendConfiguration
import io.github.mvillafuertem.backend.Terraform.TerraformConfiguration
import software.constructs.Construct

object BackendStack {

def apply(commonTags: Map[String, String])(scope: Construct, id: String): Backend = {
val terraformConfiguration =
TerraformConfiguration(
bucket = "scala-cdktf-dev-terraform-state",
dynamodbTable = "scala_cdktf_dev_terraform_state_locks"
)

val backendConfiguration = BackendConfiguration(
bucket = "scala-cdktf-dev-terraform-state",
dynamodbTable = "scala_cdktf_dev_terraform_state_locks",
commonTags = commonTags
)

val terraform = Terraform(terraformConfiguration)(scope, s"${id}-backend")
Backend(backendConfiguration)(terraform, s"${id}_backend_stack")
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package io.github.mvillafuertem.backend

import com.hashicorp.cdktf.{ S3Backend, TerraformStack }
import io.github.mvillafuertem.aws.provider.AwsProvider
import io.github.mvillafuertem.backend.Terraform.TerraformConfiguration
import software.constructs.Construct

import scala.jdk.CollectionConverters._

final case class Terraform(configuration: TerraformConfiguration)(implicit scope: Construct, id: String) extends TerraformStack(scope, id) {
self: Construct =>

private val accountId = "000000000000"
private val region = "eu-west-2"

// export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" \
// $(aws sts assume-role \
// --role-arn arn:aws:iam::123456789012:role/MyAssumedRole \
// --role-session-name MySessionName \
// --query "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" \
// --output text))
private val _: AwsProvider = AwsProvider.Builder
.create(self, s"${id}_aws_provider")
.allowedAccountIds(List(accountId).asJava)
.region(region)
.profile("gbgdev")
.build()

private val _: S3Backend = S3Backend.Builder
.create(self)
.bucket(configuration.bucket)
.key("backend/terraform.tfstate")
.region("eu-west-2")
.dynamodbTable(configuration.dynamodbTable)
.encrypt(true)
.profile("gbgdev")
.build()

}

object Terraform {
final case class TerraformConfiguration(
bucket: String,
dynamodbTable: String
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.github.mvillafuertem.dev

import io.github.mvillafuertem.dev.Iam.IamConfiguration
import io.github.mvillafuertem.dev.Terraform.TerraformConfiguration
import software.constructs.Construct

object DevStack {

def apply(commonTags: Map[String, String])(scope: Construct, id: String) = {
val terraformConfiguration =
TerraformConfiguration(
bucket = "scala-cdktf-dev-terraform-state",
dynamodbTable = "scala_cdktf_dev_terraform_state_locks"
)

val iamConfiguration = IamConfiguration(
commonTags = commonTags
)

val terraform = Terraform(terraformConfiguration)(scope, s"${id}-dev")
Iam(iamConfiguration)(terraform, s"${id}_iam")
}

}
Loading

0 comments on commit 35bf788

Please sign in to comment.