diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index e4c1ace..e369882 100755 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -4,6 +4,9 @@ "features": { "ghcr.io/devcontainers/features/docker-in-docker:2.0.1": {}, }, + "containerEnv": { + "TF_PLUGIN_CACHE_DIR": "/workspaces/terraform-docker-artifact-packager/tmp/.terraform.d/" + }, "customizations": { "vscode": { "settings": { diff --git a/README.md b/README.md index a83f830..952bf21 100755 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ for more details on these variables. | `docker_build_args` | Additional arguments to pass to Docker during the build process. | `map(string)` | `{}` | no | | `artifact_dst_directory` | The destination directory on the host machine to which the artifact will be copied. | `string` | "" | no | | `artifact_src_path` | The path in the Docker container from which to copy the artifact. | `string` | n/a | yes | +| `artifact_src_type` | "The type of artifact to copy. Accepts 'zip' or 'directory'." | `string` | `zip` | no | | `force_rebuild_id` | A unique identifier that, when changed, will force the Docker image to be rebuilt. | `string` | "" | no | | `os_compatibility` | The operating system of Terrafrom environment. Accepts 'unix' or 'windows'. | `string` | `unix` | no | diff --git a/example/aws-lambda-fn/provider.tf b/example/aws-lambda-fn/provider.tf deleted file mode 100755 index c125940..0000000 --- a/example/aws-lambda-fn/provider.tf +++ /dev/null @@ -1,3 +0,0 @@ -provider "aws" { - region = "us-east-1" -} diff --git a/example/aws-lambda-fn/README.md b/examples/aws-lambda-fn/README.md similarity index 85% rename from example/aws-lambda-fn/README.md rename to examples/aws-lambda-fn/README.md index 347e8f5..e640f5f 100644 --- a/example/aws-lambda-fn/README.md +++ b/examples/aws-lambda-fn/README.md @@ -1,10 +1,12 @@ -# Terraform Docker Artifact Packager - AWS Lambda Example +# Terraform Module Example + +## AWS Lambda Function This is an example of using the Terraform Docker Artifact Package module to package a TypeScript app into a Docker image, extract the compiled JavaScript file, and use it as the source code for an AWS Lambda function. -## Prerequisites +### Prerequisites - Terraform installed on your local machine - Docker installed on your local machine diff --git a/example/aws-lambda-fn/fixtures/echo-app/Dockerfile b/examples/aws-lambda-fn/fixtures/echo-app/Dockerfile similarity index 100% rename from example/aws-lambda-fn/fixtures/echo-app/Dockerfile rename to examples/aws-lambda-fn/fixtures/echo-app/Dockerfile diff --git a/example/aws-lambda-fn/fixtures/echo-app/package-lock.json b/examples/aws-lambda-fn/fixtures/echo-app/package-lock.json similarity index 100% rename from example/aws-lambda-fn/fixtures/echo-app/package-lock.json rename to examples/aws-lambda-fn/fixtures/echo-app/package-lock.json diff --git a/example/aws-lambda-fn/fixtures/echo-app/package.json b/examples/aws-lambda-fn/fixtures/echo-app/package.json similarity index 100% rename from example/aws-lambda-fn/fixtures/echo-app/package.json rename to examples/aws-lambda-fn/fixtures/echo-app/package.json diff --git a/example/aws-lambda-fn/fixtures/echo-app/src/index.ts b/examples/aws-lambda-fn/fixtures/echo-app/src/index.ts similarity index 100% rename from example/aws-lambda-fn/fixtures/echo-app/src/index.ts rename to examples/aws-lambda-fn/fixtures/echo-app/src/index.ts diff --git a/example/aws-lambda-fn/fixtures/echo-app/tsconfig.json b/examples/aws-lambda-fn/fixtures/echo-app/tsconfig.json similarity index 100% rename from example/aws-lambda-fn/fixtures/echo-app/tsconfig.json rename to examples/aws-lambda-fn/fixtures/echo-app/tsconfig.json diff --git a/example/aws-lambda-fn/main.tf b/examples/aws-lambda-fn/main.tf similarity index 97% rename from example/aws-lambda-fn/main.tf rename to examples/aws-lambda-fn/main.tf index 5999f4e..689f0af 100755 --- a/example/aws-lambda-fn/main.tf +++ b/examples/aws-lambda-fn/main.tf @@ -1,5 +1,5 @@ module "packager" { - source = "../" + source = "../../" artifact_src_path = "/tmp/package.zip" docker_build_context = "${path.module}/fixures/echo-app" diff --git a/examples/aws-lambda-fn/provider.tf b/examples/aws-lambda-fn/provider.tf new file mode 100755 index 0000000..09e8b04 --- /dev/null +++ b/examples/aws-lambda-fn/provider.tf @@ -0,0 +1,7 @@ +provider "aws" { + region = "us-east-1" +} + +provider "docker" { + host = "unix:///var/run/docker.sock" +} diff --git a/examples/aws-lambda-fn/version.tf b/examples/aws-lambda-fn/version.tf new file mode 100755 index 0000000..758f8f6 --- /dev/null +++ b/examples/aws-lambda-fn/version.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + } + docker = { + source = "kreuzwerker/docker" + } + } +} diff --git a/examples/aws-s3-bucket/README.md b/examples/aws-s3-bucket/README.md new file mode 100644 index 0000000..35c587f --- /dev/null +++ b/examples/aws-s3-bucket/README.md @@ -0,0 +1,24 @@ +# Terraform Module Example + +## AWS S3 Bucket + +This example demonstrates how to use the Artifact Builder Terraform module to +build and deploy a simple static website to AWS S3. + +In this example, we have a simple static website composed of HTML files. We use +the Artifact Builder module with `artifact_src_type` set to "directory" to +package the entire website directory as the artifact. This artifact is then +deployed to an AWS S3 bucket, which is configured to host a static website. + +This example is intended to show the flexibility of the Artifact Builder module +in handling different artifact types, including whole directories. It also shows +how to integrate the module with other Terraform resources to create a complete +deployment workflow. + +### Prerequisites + +- Terraform installed on your local machine +- Docker installed on your local machine +- AWS account with the necessary permissions to create Lambda functions and + IAM roles +- AWS CLI installed and configured with your AWS account diff --git a/examples/aws-s3-bucket/fixtures/website/Dockerfile b/examples/aws-s3-bucket/fixtures/website/Dockerfile new file mode 100644 index 0000000..7bd71f2 --- /dev/null +++ b/examples/aws-s3-bucket/fixtures/website/Dockerfile @@ -0,0 +1,16 @@ +FROM node:18 as build + +WORKDIR /opt/app + +COPY . . + +# additional build steps here (e.g. npm install) + +# ------------------------------------------------------------------ package --- + +FROM alpine:latest as package + +COPY --from=build /opt/app/assets/ /opt/app/dist/ + +RUN apk add zip \ + && cd /opt/app/dist diff --git a/examples/aws-s3-bucket/fixtures/website/assets/index.html b/examples/aws-s3-bucket/fixtures/website/assets/index.html new file mode 100644 index 0000000..42db73e --- /dev/null +++ b/examples/aws-s3-bucket/fixtures/website/assets/index.html @@ -0,0 +1,13 @@ + + + + + My Static Website + + + +

Welcome to my static website!

+

This is a simple static website hosted on AWS S3 and deployed using a Terraform module.

+ + + diff --git a/examples/aws-s3-bucket/main.tf b/examples/aws-s3-bucket/main.tf new file mode 100755 index 0000000..fbfdc88 --- /dev/null +++ b/examples/aws-s3-bucket/main.tf @@ -0,0 +1,47 @@ +locals { + mime_types = { + ".html" = "text/html" + ".css" = "text/css" + ".js" = "application/javascript" + ".json" = "application/json" + ".png" = "image/png" + ".jpg" = "image/jpeg" + ".gif" = "image/gif" + ".svg" = "image/svg+xml" + } +} + +module "artifact_builder" { + source = "../../" + + docker_build_context = "${path.module}/fixtures/website" + docker_build_target = "package" + artifact_src_type = "directory" + artifact_src_path = "/opt/app/dist/" + artifact_dst_directory = "${path.module}/dist" +} + +resource "random_string" "website_bucket_random_suffix" { + length = 6 + special = false + upper = false +} + +resource "aws_s3_bucket" "website_bucket" { + bucket = "example-tf-docker-artifact-packager-${random_string.website_bucket_random_suffix.result}" + acl = "public-read" + + website { + index_document = "index.html" + } +} + +resource "aws_s3_bucket_object" "website_files" { + for_each = fileset(module.artifact_builder.artifact_dst_directory, "**/*") + + bucket = aws_s3_bucket.website_bucket.bucket + key = each.value + source = "${module.artifact_builder.artifact_dst_directory}/${each.value}" + content_type = lookup(local.mime_types, regex("\\.[^.]+$", each.value), "binary/octet-stream") + acl = "public-read" +} diff --git a/examples/aws-s3-bucket/provider.tf b/examples/aws-s3-bucket/provider.tf new file mode 100755 index 0000000..d8b940e --- /dev/null +++ b/examples/aws-s3-bucket/provider.tf @@ -0,0 +1,8 @@ +# provider "aws" { +# region = "us-east-1" +# } + +provider "docker" { + + host = "unix:///var/run/docker.sock" +} diff --git a/examples/aws-s3-bucket/version.tf b/examples/aws-s3-bucket/version.tf new file mode 100755 index 0000000..758f8f6 --- /dev/null +++ b/examples/aws-s3-bucket/version.tf @@ -0,0 +1,10 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + } + docker = { + source = "kreuzwerker/docker" + } + } +} diff --git a/main.tf b/main.tf index f1d1374..b7ec493 100755 --- a/main.tf +++ b/main.tf @@ -6,9 +6,14 @@ locals { artifact_id = try(random_string.this[0].id, "unknown") artifact_dst_dir = var.artifact_dst_directory == "" ? "${path.module}/dist" : var.artifact_dst_directory - artifact_dst_path = abspath("${local.artifact_dst_dir}/${module.artifact_label.id}-${local.artifact_id}.zip") + artifact_dst_path = abspath("${local.artifact_dst_dir}/${module.artifact_label.id}-${local.artifact_id}${local.artifact_type_dst_suffix_map[var.artifact_src_type]}") artifact_src_path = var.artifact_src_path + artifact_type_dst_suffix_map = { + zip = ".zip" + directory = "/" + } + os_script_map = { windows = <<-EOT $ARTIFACT_DST_DIR=[System.IO.Path]::GetDirectoryName('$ARTIFACT_DST_PATH') @@ -31,7 +36,7 @@ module "artifact_label" { source = "cloudposse/label/null" version = "0.25.0" - name = var.name == "" ? "artifact" : var.name + name = coalesce(module.this.name, var.name, "artifact") label_order = ["name", "attributes"] context = module.this.context } diff --git a/variables.tf b/variables.tf index ce56000..243b985 100755 --- a/variables.tf +++ b/variables.tf @@ -3,6 +3,17 @@ variable "artifact_src_path" { description = "The path in the Docker container from which to copy the artifact." } +variable "artifact_src_type" { + type = string + description = "The type of artifact to copy. Accepts 'zip' or 'directory'." + default = "zip" + + validation { + condition = var.artifact_src_type == "zip" || var.artifact_src_type == "directory" + error_message = "The `artifact_src_type` variable must be set to either 'zip' or 'directory'." + } +} + variable "artifact_dst_directory" { type = string description = "The destination directory on the host machine to which the artifact will be copied."