diff --git a/.github/workflows/ensure-docs-compiled.yaml b/.github/workflows/ensure-docs-compiled.yaml new file mode 100644 index 00000000..8d10ac7b --- /dev/null +++ b/.github/workflows/ensure-docs-compiled.yaml @@ -0,0 +1,22 @@ +name: Ensure Docs are Compiled +on: + push: +jobs: + ensure-docs-compiled: + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎 + uses: actions/checkout@v2 + - uses: actions/setup-go@v4 + - shell: bash + run: make build-docs + - shell: bash + run: | + if [[ -z "$(git status -s)" ]]; then + echo "OK" + else + echo "Docs have been updated, but the compiled docs have not been committed." + echo "Run 'make build-docs', and commit the result to resolve this error." + exit 1 + fi + diff --git a/.github/workflows/notify-integration-release-via-manual.yaml b/.github/workflows/notify-integration-release-via-manual.yaml new file mode 100644 index 00000000..fa7073d6 --- /dev/null +++ b/.github/workflows/notify-integration-release-via-manual.yaml @@ -0,0 +1,50 @@ +# Manual release workflow is used for deploying documentation updates +# on the specified branch without making an official plugin release. +name: Notify Integration Release (Manual) +on: + workflow_dispatch: + inputs: + version: + description: "The release version (semver)" + default: 1.0.0 + required: false + branch: + description: "A branch or SHA" + default: 'main' + required: false +jobs: + notify-release: + runs-on: ubuntu-latest + steps: + - name: Checkout this repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + ref: ${{ github.event.inputs.branch }} + # Ensure that Docs are Compiled + - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + - shell: bash + run: make build-docs + - shell: bash + run: | + if [[ -z "$(git status -s)" ]]; then + echo "OK" + else + echo "Docs have been updated, but the compiled docs have not been committed." + echo "Run 'make build-docs', and commit the result to resolve this error." + exit 1 + fi + # Perform the Release + - name: Checkout integration-release-action + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + repository: hashicorp/integration-release-action + path: ./integration-release-action + - name: Notify Release + uses: ./integration-release-action + with: + # The integration identifier will be used by the Packer team to register the integration + # the expected format is packer// + integration_identifier: "packer/vultr/vultr" + release_version: ${{ github.event.inputs.version }} + release_sha: ${{ github.event.inputs.branch }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/notify-integration-release-via-tag.yaml b/.github/workflows/notify-integration-release-via-tag.yaml new file mode 100644 index 00000000..23106274 --- /dev/null +++ b/.github/workflows/notify-integration-release-via-tag.yaml @@ -0,0 +1,54 @@ +name: Notify Integration Release (Tag) +on: + push: + tags: + - '*.*.*' # Proper releases +jobs: + strip-version: + runs-on: ubuntu-latest + outputs: + packer-version: ${{ steps.strip.outputs.packer-version }} + steps: + - name: Strip leading v from version tag + id: strip + env: + REF: ${{ github.ref_name }} + run: | + echo "packer-version=$(echo "$REF" | sed -E 's/v?([0-9]+\.[0-9]+\.[0-9]+)/\1/')" >> "$GITHUB_OUTPUT" + notify-release: + needs: + - strip-version + runs-on: ubuntu-latest + steps: + - name: Checkout this repo + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + ref: ${{ github.ref }} + # Ensure that Docs are Compiled + - uses: actions/setup-go@93397bea11091df50f3d7e59dc26a7711a8bcfbe # v4.1.0 + - shell: bash + run: make build-docs + - shell: bash + run: | + if [[ -z "$(git status -s)" ]]; then + echo "OK" + else + echo "Docs have been updated, but the compiled docs have not been committed." + echo "Run 'make build-docs', and commit the result to resolve this error." + exit 1 + fi + # Perform the Release + - name: Checkout integration-release-action + uses: actions/checkout@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + with: + repository: hashicorp/integration-release-action + path: ./integration-release-action + - name: Notify Release + uses: ./integration-release-action + with: + # The integration identifier will be used by the Packer team to register the integration + # the expected format is packer// + integration_identifier: "packer/vultr/vultr" + release_version: ${{ needs.strip-version.outputs.packer-version }} + release_sha: ${{ github.ref }} + github_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.web-docs/README.md b/.web-docs/README.md new file mode 100644 index 00000000..48c9acb0 --- /dev/null +++ b/.web-docs/README.md @@ -0,0 +1,30 @@ +The [Vultr](https://www.Vultr.com/) Packer plugin provides a builder for building images in +Vultr. + +### Installation + +To install this plugin, copy and paste this code into your Packer configuration, then run [`packer init`](https://www.packer.io/docs/commands/init). + +```hcl +packer { + required_plugins { + vultr = { + version = ">= 2.5.0" + source = "github.com/vultr/vultr" + } + } +} +``` + +Alternatively, you can use `packer plugins install` to manage installation of this plugin. + +```sh +$ packer plugins install github.com/vultr/vultr +``` + + +### Components + +#### Builders + +- [vultr](/packer/integrations/vultr/vultr/latest/components/builder/vultr) - The builder takes a source image, runs any provisioning necessary on the image after launching it, then snapshots it into a reusable image. This reusable image can then be used as the foundation of new servers that are launched within Vultr. diff --git a/.web-docs/components/builder/vultr/README.md b/.web-docs/components/builder/vultr/README.md new file mode 100644 index 00000000..760100a4 --- /dev/null +++ b/.web-docs/components/builder/vultr/README.md @@ -0,0 +1,81 @@ +Type: `vultr` + +The `vultr` Packer builder is able to create new images for use with +[Vultr](https://www.vultr.com). The builder takes a source image, +runs any provisioning necessary on the image after launching it, then snapshots +it into a reusable image. This reusable image can be then used as the +foundation of new servers that are launched within Vultr. + +The builder does *not* manage images. Once it creates an image, it is up to you +to use it or delete it. + +**NOTE**: Packer-Builder-Vultr [v2+](https://github.com/vultr/packer-builder-vultr/blob/master/CHANGELOG.md#v200-2020-11-23) uses [API V2](https://www.vultr.com/api/) + + +## Required: + +- `api_key` (string) - The Vultr API Key to access your account. + +- `region_id` (string) - The id of the region to launch the instance in. See [List Regions](https://www.vultr.com/api/v2/#operation/list-regions). + +- `plan_id` (string) - The id of the plan you wish to use. See [List Plans](https://www.vultr.com/api/v2/#tag/plans). + +**NOTE**: that `os_id`, `app_id`, `snapshot_id`, or `iso_id` are not required and are optional. You **must** supply at least one for instance creation. +## Optional + +- `os_id` (int) - The id of the os to use. This will be the OS that will be used to launch a new instance and provision it. See [List Operating Systems](https://www.vultr.com/api/v2/#operation/list-os). + +- `snapshot_description` (string) - Description of the snapshot. + +- `snapshot_id` (string) - If you've selected the 'snapshot' operating system, this should be the ID of the snapshot. See [Snapshot](https://www.vultr.com/api/v2/#operation/list-snapshots). + +- `iso_id` (string) - If you've selected the 'custom' operating system, this is the ID of a specific ISO to mount during the deployment. See [ISO](https://www.vultr.com/api/v2/#operation/list-isos). + +- `iso_url` (string) - Upload a new ISO from this url that is publicly accessible. See [Create ISO](https://www.vultr.com/api/#operation/create-iso). This ISO will be deleted upon successful provisioning, or if the build is cancelled. + +- `app_id` (int) - If launching an application, this is the ID to launch. See [App](https://www.vultr.com/api/v2/#operation/list-applications). + +- `image_id` (string) If launching a marketplace application. See [App](https://www.vultr.com/api/v2/#operation/list-applications). Note marketplace applications are denoted by `type: marketplace` and you must use the `image_id` not the `id`. + +- `enable_ipv6` (bool) - IPv6 subnet will be assigned to the machine. Defaults to `false` + +- `enable_private_network` (bool) - Enables private networking support to the new server. Defaults to `false` + +- `script_id` (string) - If you've not selected a 'custom' (OS 159) operating system, this can be the `id` of a startup script to execute on boot. See [Startup Script](https://www.vultr.com/api/v2/#operation/list-startup-scripts). + +- `ssh_key_ids` (array of string) - List of SSH keys to apply to this server on install. Separate keys with commas. See [SSH Key](https://www.vultr.com/api/v2/#operation/list-ssh-keys). + +- `instance_label` (string) - This is a text label that will be shown in the control panel. + +- `userdata` (string) - Base64 encoded user-data. + +- `hostname` (string) - Hostname to assign to this server. + +- `tag` (string) - The tag to assign to this server. + +- `state_timeout` (string) - A duration to wait for the instance to boot, or a snapshot to be taken. Must be a string in [golang Duration-parsable format](https://golang.org/pkg/time/#ParseDuration), like "10m" or "30s". Defaults to `10m` + +You may also adjust the [SSH communicator settings](https://www.packer.io/docs/communicators/ssh) to configure how Packer will log into Vultr Instances. +## Example Usage + + +```hcl +variable "vultr_api_key" { + type = string + default = "${env("VULTR_API_KEY")}" +} + +source "vultr" "ubuntu-20" { + api_key = "${var.vultr_api_key}" + os_id = "413" + plan_id = "vhf-1c-1gb" + region_id = "atl" + snapshot_description = "testing" + state_timeout = "10m" + ssh_username = "root" +} + +build { + sources = ["source.vultr.ubuntu-20"] +} +``` diff --git a/.web-docs/metadata.hcl b/.web-docs/metadata.hcl new file mode 100644 index 00000000..60a2ef3f --- /dev/null +++ b/.web-docs/metadata.hcl @@ -0,0 +1,12 @@ +# For full specification on the configuration of this file visit: +# https://github.com/hashicorp/integration-template#metadata-configuration +integration { + name = "Vultr" + description = "A plugin for creating Vultr snapshots." + identifier = "packer/vultr/vultr" + component { + type = "builder" + name = "Vultr" + slug = "vultr" + } +} diff --git a/.web-docs/scripts/compile-to-webdocs.sh b/.web-docs/scripts/compile-to-webdocs.sh new file mode 100755 index 00000000..51a72383 --- /dev/null +++ b/.web-docs/scripts/compile-to-webdocs.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash + +# Converts the folder name that the component documentation file +# is stored in into the integration slug of the component. +componentTypeFromFolderName() { + if [[ "$1" = "builders" ]]; then + echo "builder" + elif [[ "$1" = "provisioners" ]]; then + echo "provisioner" + elif [[ "$1" = "post-processors" ]]; then + echo "post-processor" + elif [[ "$1" = "datasources" ]]; then + echo "data-source" + else + echo "" + fi +} + +# $1: The content to adjust links +# $2: The organization of the integration +rewriteLinks() { + local result="$1" + local organization="$2" + + urlSegment="([^/]+)" + urlAnchor="(#[^/]+)" + + # Rewrite Component Index Page links to the Integration root page. + # + # (\1) (\2) (\3) + # /packer/plugins/datasources/amazon#anchor-tag--> + # /packer/integrations/hashicorp/amazon#anchor-tag + local find="\(\/packer\/plugins\/$urlSegment\/$urlSegment$urlAnchor?\)" + local replace="\(\/packer\/integrations\/$organization\/\2\3\)" + result="$(echo "$result" | sed -E "s/$find/$replace/g")" + + + # Rewrite Component links to the Integration component page + # + # (\1) (\2) (\3) (\4) + # /packer/plugins/datasources/amazon/parameterstore#anchor-tag --> + # /packer/integrations/{organization}/amazon/latest/components/datasources/parameterstore + local find="\(\/packer\/plugins\/$urlSegment\/$urlSegment\/$urlSegment$urlAnchor?\)" + local replace="\(\/packer\/integrations\/$organization\/\2\/latest\/components\/\1\/\3\4\)" + result="$(echo "$result" | sed -E "s/$find/$replace/g")" + + # Rewrite the Component URL segment from the Packer Plugin format + # to the Integrations format + result="$(echo "$result" \ + | sed "s/\/datasources\//\/data-source\//g" \ + | sed "s/\/builders\//\/builder\//g" \ + | sed "s/\/post-processors\//\/post-processor\//g" \ + | sed "s/\/provisioners\//\/provisioner\//g" \ + )" + + echo "$result" +} + +# $1: Docs Dir +# $2: Web Docs Dir +# $3: Component File +# $4: The org of the integration +processComponentFile() { + local docsDir="$1" + local webDocsDir="$2" + local componentFile="$3" + + local escapedDocsDir="$(echo "$docsDir" | sed 's/\//\\\//g' | sed 's/\./\\\./g')" + local componentTypeAndSlug="$(echo "$componentFile" | sed "s/$escapedDocsDir\///g" | sed 's/\.mdx//g')" + + # Parse out the Component Slug & Component Type + local componentSlug="$(echo "$componentTypeAndSlug" | cut -d'/' -f 2)" + local componentType="$(componentTypeFromFolderName "$(echo "$componentTypeAndSlug" | cut -d'/' -f 1)")" + if [[ "$componentType" = "" ]]; then + echo "Failed to process '$componentFile', unexpected folder name." + echo "Documentation for components must be stored in one of:" + echo "builders, provisioners, post-processors, datasources" + exit 1 + fi + + + # Calculate the location of where this file will ultimately go + local webDocsFolder="$webDocsDir/components/$componentType/$componentSlug" + mkdir -p "$webDocsFolder" + local webDocsFile="$webDocsFolder/README.md" + local webDocsFileTmp="$webDocsFolder/README.md.tmp" + + # Copy over the file to its webDocsFile location + cp "$componentFile" "$webDocsFile" + + # Remove the Header + local lastMetadataLine="$(grep -n -m 2 '^\-\-\-' "$componentFile" | tail -n1 | cut -d':' -f1)" + cat "$webDocsFile" | tail -n +"$(($lastMetadataLine+2))" > "$webDocsFileTmp" + mv "$webDocsFileTmp" "$webDocsFile" + + # Remove the top H1, as this will be added automatically on the web + cat "$webDocsFile" | tail -n +3 > "$webDocsFileTmp" + mv "$webDocsFileTmp" "$webDocsFile" + + # Rewrite Links + rewriteLinks "$(cat "$webDocsFile")" "$4" > "$webDocsFileTmp" + mv "$webDocsFileTmp" "$webDocsFile" +} + +# Compiles the Packer SDC compiled docs folder down +# to a integrations-compliant folder (web docs) +# +# $1: The directory of the plugin +# $2: The directory of the SDC compiled docs files +# $3: The output directory to place the web-docs files +# $4: The org of the integration +compileWebDocs() { + local docsDir="$1/$2" + local webDocsDir="$1/$3" + + echo "Compiling MDX docs in '$2' to Markdown in '$3'..." + # Create the web-docs directory if it hasn't already been created + mkdir -p "$webDocsDir" + + # Copy the README over + cp "$docsDir/README.md" "$webDocsDir/README.md" + + # Process all MDX component files (exclude index files, which are unsupported) + for file in $(find "$docsDir" | grep "$docsDir/.*/.*\.mdx" | grep --invert-match "index.mdx"); do + processComponentFile "$docsDir" "$webDocsDir" "$file" "$4" + done +} + +compileWebDocs "$1" "$2" "$3" "$4" diff --git a/Makefile b/Makefile index 5f397c10..0c8bd608 100644 --- a/Makefile +++ b/Makefile @@ -37,9 +37,11 @@ build-binary: install-packer-sdc: ## Install packer sofware development command @go install github.com/hashicorp/packer-plugin-sdk/cmd/packer-sdc@${HASHICORP_PACKER_PLUGIN_SDK_VERSION} -ci-release-docs: install-packer-sdc - @packer-sdc renderdocs -src docs -partials docs-partials/ -dst docs/ - @/bin/sh -c "[ -d docs ] && zip -r docs.zip docs/" - plugin-check: install-packer-sdc build-binary - @packer-sdc plugin-check ${BINARY} \ No newline at end of file + @packer-sdc plugin-check ${BINARY} + +build-docs: install-packer-sdc + @if [ -d ".docs" ]; then rm -r ".docs"; fi + @packer-sdc renderdocs -src "docs" -partials docs-partials/ -dst ".docs/" + @./.web-docs/scripts/compile-to-webdocs.sh "." ".docs" ".web-docs" "vultr" + @rm -r ".docs" diff --git a/docs/README.md b/docs/README.md index ab245c0d..48c9acb0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,20 +1,9 @@ -# Vultr Plugins - The [Vultr](https://www.Vultr.com/) Packer plugin provides a builder for building images in Vultr. -## Installation - -### Using pre-built releases - -#### Using the `packer init` command +### Installation -Starting from version 1.7, Packer supports a new `packer init` command allowing -automatic installation of Packer plugins. Read the -[Packer documentation](https://www.packer.io/docs/commands/init) for more information. - -To install this plugin, copy and paste this code into your Packer configuration . -Then, run [`packer init`](https://www.packer.io/docs/commands/init). +To install this plugin, copy and paste this code into your Packer configuration, then run [`packer init`](https://www.packer.io/docs/commands/init). ```hcl packer { @@ -27,29 +16,15 @@ packer { } ``` -#### Manual installation - -You can find pre-built binary releases of the plugin [here](https://github.com/vultr/packer-plugin-vultr/releases). -Once you have downloaded the latest archive corresponding to your target OS, -uncompress it to retrieve the plugin binary file corresponding to your platform. -To install the plugin, please follow the Packer documentation on -[installing a plugin](https://www.packer.io/docs/extending/plugins/#installing-plugins). - - -#### From Source - -If you prefer to build the plugin from its source code, clone the GitHub -repository locally and run the command `go build` from the root -directory. Upon successful compilation, a `packer-plugin-vultr` plugin -binary file can be found in the root directory. -To install the compiled plugin, please follow the official Packer documentation -on [installing a plugin](https://www.packer.io/docs/extending/plugins/#installing-plugins). +Alternatively, you can use `packer plugins install` to manage installation of this plugin. +```sh +$ packer plugins install github.com/vultr/vultr +``` -## Plugin Contents -The Vultr plugin is intended as a starting point for creating Packer plugins, containing: +### Components -### Builders +#### Builders -- [builder](/docs/builders/vultr.mdx) - The builder takes a source image, runs any provisioning necessary on the image after launching it, then snapshots it into a reusable image. This reusable image can then be used as the foundation of new servers that are launched within Vultr. +- [vultr](/packer/integrations/vultr/vultr/latest/components/builder/vultr) - The builder takes a source image, runs any provisioning necessary on the image after launching it, then snapshots it into a reusable image. This reusable image can then be used as the foundation of new servers that are launched within Vultr. diff --git a/docs/builders/vultr.mdx b/docs/builders/vultr.mdx index 3c2c7697..dad7cd33 100644 --- a/docs/builders/vultr.mdx +++ b/docs/builders/vultr.mdx @@ -25,7 +25,7 @@ to use it or delete it. **NOTE**: Packer-Builder-Vultr [v2+](https://github.com/vultr/packer-builder-vultr/blob/master/CHANGELOG.md#v200-2020-11-23) uses [API V2](https://www.vultr.com/api/) -### Required: +## Required: - `api_key` (string) - The Vultr API Key to access your account. @@ -34,7 +34,7 @@ to use it or delete it. - `plan_id` (string) - The id of the plan you wish to use. See [List Plans](https://www.vultr.com/api/v2/#tag/plans). **NOTE**: that `os_id`, `app_id`, `snapshot_id`, or `iso_id` are not required and are optional. You **must** supply at least one for instance creation. -### Optional +## Optional - `os_id` (int) - The id of the os to use. This will be the OS that will be used to launch a new instance and provision it. See [List Operating Systems](https://www.vultr.com/api/v2/#operation/list-os). @@ -69,7 +69,7 @@ to use it or delete it. - `state_timeout` (string) - A duration to wait for the instance to boot, or a snapshot to be taken. Must be a string in [golang Duration-parsable format](https://golang.org/pkg/time/#ParseDuration), like "10m" or "30s". Defaults to `10m` You may also adjust the [SSH communicator settings](https://www.packer.io/docs/communicators/ssh) to configure how Packer will log into Vultr Instances. -### Example Usage +## Example Usage ```hcl