Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(terraform): add Terraform package #524

Merged
merged 2 commits into from
Oct 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions terraform/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
title: Terraform
homepage: https://www.terraform.io/
tagline: |
Provision, change, and version resources on any environment.
description: |
Terraform is an infrastructure as code (IaC) tool that allows you to build, change, and version infrastructure safely and efficiently.
---

To update or switch versions, run `webi terraform@stable` (or `@v1.6.1`,
`@beta`, etc).

### Files

These are the files / directories that are created and/or modified with this
install:

```text
~/.config/envman/PATH.env
~/.local/bin/terraform
<PROJECT-DIR>/main.tf
```

## Cheat Sheet

> With HashiCorp Terraform, provisioning and security can be automated based on
> infrastructure and policy as code. Infrastructure and policies are codified,
> shared, managed, and executed within a workflow that is consistent across all
> infrastructure.

### How to Define Infrastructure State

Create configurations that provide an outline for Terraform to provision your
target infrastructure. For example:

`main.tf`:

```tf
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "~> 2.13.0"
}
}
}

provider "docker" {
# provider-specific configuration goes here, e.g.,
# browse provider documentation here https://registry.terraform.io/browse/providers
}

# Define some resources!
resource "docker_image" "nginx" {
name = "nginx:latest"
keep_locally = false
}

resource "docker_container" "nginx" {
image = docker_image.nginx.latest
name = "web-server"
ports {
internal = 80
external = 8080
}
}
```

### How to Initialize Terraform

Terraform needs to install provider-specific plugins, generate lockfiles, etc.
before you can begin provisioning.

```sh
terraform init
```

You should only need to run this on new configurations, or other configurations
checked-out from version control.

### How to Lint / Check / Validate your Config

To check you have a valid configuration

```sh
terraform validate
```

To format your configuration files

```sh
terraform fmt
```

### How to Provision Resources

You can generate an execution plan before committing to provisioning real
resources. This command allows you to see exactly what Terraform will do when
running the next command.

```sh
terraform plan
```

Then, **to apply your configurations and provision infrastructure** resources:

```sh
terraform apply
```

Use `-auto-approve` to automatically accept all user prompts (non-interactive,
batch mode):

```sh
terraform apply -auto-approve
```

### How to Execute Plans

Execution plans generated by `terraform plan` also act as the _last working
state of your infrastructure_. You may wish to save the generated `.tfstate`
file so that you may re-provision these resources reliably.

You can pass in the execution plan to `terraform apply` (example):

```sh
terraform apply -auto-approve ./main.tf
```
57 changes: 57 additions & 0 deletions terraform/install.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/usr/bin/env pwsh

#################
# Install terraform #
#################

# Every package should define these variables
$pkg_cmd_name = "terraform"

$pkg_dst_cmd = "$Env:USERPROFILE\.local\bin\terraform.exe"
$pkg_dst_bin = "$Env:USERPROFILE\.local\bin"
$pkg_dst = "$pkg_dst_cmd"

$pkg_src_cmd = "$Env:USERPROFILE\.local\opt\terraform-v$Env:WEBI_VERSION\bin\terraform.exe"
$pkg_src_bin = "$Env:USERPROFILE\.local\opt\terraform-v$Env:WEBI_VERSION\bin"
$pkg_src_dir = "$Env:USERPROFILE\.local\opt\terraform-v$Env:WEBI_VERSION"
$pkg_src = "$pkg_src_cmd"

New-Item "$Env:USERPROFILE\Downloads\webi" -ItemType Directory -Force | out-null
$pkg_download = "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE"

# Fetch archive
IF (!(Test-Path -Path "$Env:USERPROFILE\Downloads\webi\$Env:WEBI_PKG_FILE")) {
echo "Downloading terraform from $Env:WEBI_PKG_URL to $pkg_download"
& curl.exe -A "$Env:WEBI_UA" -fsSL "$Env:WEBI_PKG_URL" -o "$pkg_download.part"
& move "$pkg_download.part" "$pkg_download"
}

IF (!(Test-Path -Path "$pkg_src_cmd")) {
echo "Installing terraform"

# TODO: create package-specific temp directory
# Enter tmp
pushd .local\tmp

# Remove any leftover tmp cruft
Remove-Item -Path ".\terraform-v*" -Recurse -ErrorAction Ignore
Remove-Item -Path ".\terraform.exe" -Recurse -ErrorAction Ignore

# Unpack archive file into this temporary directory
# Windows BSD-tar handles zip. Imagine that.
echo "Unpacking $pkg_download"
& tar xf "$pkg_download"

# Settle unpacked archive into place
echo "Install Location: $pkg_src_cmd"
New-Item "$pkg_src_bin" -ItemType Directory -Force | out-null
Move-Item -Path ".\terraform.exe" -Destination "$pkg_src_bin"

# Exit tmp
popd
}

echo "Copying into '$pkg_dst_cmd' from '$pkg_src_cmd'"
Remove-Item -Path "$pkg_dst_cmd" -Recurse -ErrorAction Ignore | out-null
New-Item "$pkg_dst_bin" -ItemType Directory -Force | out-null
Copy-Item -Path "$pkg_src" -Destination "$pkg_dst" -Recurse
38 changes: 38 additions & 0 deletions terraform/install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#!/bin/sh
set -e
set -u

pkg_cmd_name="terraform"

WEBI_SINGLE=true

pkg_get_current_version() {
# 'terraform -v' has output in this format:
# Terraform v1.6.1
# on linux_amd64
# This trims it down to just the version number:
# 1.6.1
terraform -v 2> /dev/null |
head -n 1 |
cut -d' ' -f2 |
cut -c2-
}

pkg_install() {
# $HOME/.local/bin/opt/terraform-v1.6.1/bin
mkdir -p "$pkg_src_bin"

# mv ./terraform* "$HOME/.local/opt/terraform-v1.6.1/bin/terraform"
mv ./"$pkg_cmd_name"* "$pkg_src_cmd"

# chmod a+x "$HOME/.local/opt/terraform-v1.6.1/bin/terraform"
chmod a+x "$pkg_src_cmd"
}

pkg_link() {
# rm -f "$HOME/.local/bin/terraform"
rm -f "$pkg_dst_cmd"

# ln -s "$HOME/.local/opt/terraform-v1.6.1/bin/terraform" "$HOME/.local/bin/terraform"
ln -s "$pkg_src_cmd" "$pkg_dst_cmd"
}
55 changes: 55 additions & 0 deletions terraform/releases.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';

let convert = {
freebsd: 'freebsd',
macos: 'darwin',
linux: 'linux',
windows: 'windows',
amd64: 'amd64',
arm: 'arm64',
386: 'x86',
};

function getAllReleases(request) {
return request({
url: 'https://releases.hashicorp.com/terraform/index.json',
json: true,
}).then(function (resp) {
let releases = resp.body;
let all = {
releases: [],
download: '', // Full URI provided in response body
};

function getBuildsForVersion(version) {
releases.versions[version].builds.forEach(function (build) {
let r = {
version: build.version,
download: build.url,
os: convert[build.os],
arch: convert[build.arch],
channel: 'stable', // No other channels
};
all.releases.push(r);
});
}

// Releases are listed chronologically, we want the latest first.
const allVersions = Object.keys(releases.versions).reverse();

allVersions.forEach(function (version) {
getBuildsForVersion(version);
});

return all;
});
}

module.exports = getAllReleases;

if (module === require.main) {
getAllReleases(require('@root/request')).then(function (all) {
all = require('../_webi/normalize.js')(all);
console.info(JSON.stringify(all));
});
}
3 changes: 3 additions & 0 deletions test/install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ __rmrf_local() {
ssh-pubkey \
ssh-utils \
syncthing \
terraform \
vim-ale \
vim-essentials \
vim-lastplace \
Expand Down Expand Up @@ -171,6 +172,7 @@ __rmrf_local() {
ssh-pubkey \
ssh-utils \
syncthing \
terraform \
vim-ale \
vim-essentials \
vim-go \
Expand Down Expand Up @@ -271,6 +273,7 @@ __test() {
ssh-pubkey \
ssh-utils \
syncthing \
terraform \
vim-ale \
vim-essentials \
vim-lastplace \
Expand Down