From f20c6a84c5f1ded1e9e8207116a28ffe49f2c095 Mon Sep 17 00:00:00 2001 From: BrandonRomano Date: Wed, 14 Jun 2023 16:04:28 -0700 Subject: [PATCH] docs: Upgrade plugin to integrations framework --- .github/workflows/ensure-docs-compiled.yaml | 22 +++ ...notify-integration-release-via-manual.yaml | 46 ++++++ .../notify-integration-release-via-tag.yaml | 40 +++++ .web-docs/README.md | 31 ++++ .../builder/hetzner-cloud/README.md | 142 ++++++++++++++++++ .web-docs/metadata.hcl | 12 ++ .web-docs/scripts/compile-to-webdocs.sh | 129 ++++++++++++++++ GNUmakefile | 6 + docs/README.md | 79 ++-------- 9 files changed, 444 insertions(+), 63 deletions(-) create mode 100644 .github/workflows/ensure-docs-compiled.yaml create mode 100644 .github/workflows/notify-integration-release-via-manual.yaml create mode 100644 .github/workflows/notify-integration-release-via-tag.yaml create mode 100644 .web-docs/README.md create mode 100644 .web-docs/components/builder/hetzner-cloud/README.md create mode 100644 .web-docs/metadata.hcl create mode 100755 .web-docs/scripts/compile-to-webdocs.sh diff --git a/.github/workflows/ensure-docs-compiled.yaml b/.github/workflows/ensure-docs-compiled.yaml new file mode 100644 index 00000000..74a174d3 --- /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@8e5e7e5ab8b370d6c329ec480221332ada57f0ab # v3.5.2 + - uses: actions/setup-go@fac708d6674e30b6ba41289acaab6d4b75aa0753 # v4.0.1 + - 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..7f839c2f --- /dev/null +++ b/.github/workflows/notify-integration-release-via-manual.yaml @@ -0,0 +1,46 @@ +name: Notify Integration Release (Manual) +on: + workflow_dispatch: + inputs: + version: + description: "The release version (semver)" + default: 0.0.1 + 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@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + with: + ref: ${{ github.event.inputs.branch }} + # Ensure that Docs are Compiled + - 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 + # Perform the Release + - name: Checkout integration-release-action + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + with: + repository: hashicorp/integration-release-action + path: ./integration-release-action + - name: Notify Release + uses: ./integration-release-action + with: + integration_identifier: 'packer/hashicorp/hcloud' + 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..4dbe10a9 --- /dev/null +++ b/.github/workflows/notify-integration-release-via-tag.yaml @@ -0,0 +1,40 @@ +name: Notify Integration Release (Tag) +on: + push: + tags: + - '*.*.*' # Proper releases + - '*.*.*-*' # Pre releases +jobs: + notify-release: + runs-on: ubuntu-latest + steps: + - name: Checkout this repo + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + with: + ref: ${{ github.ref }} + # Ensure that Docs are Compiled + - 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 + # Perform the Release + - name: Checkout integration-release-action + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + with: + repository: hashicorp/integration-release-action + path: ./integration-release-action + - name: Notify Release + uses: ./integration-release-action + with: + integration_identifier: 'packer/hashicorp/hcloud' + release_version: ${{ github.ref_name }} + 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..de75b190 --- /dev/null +++ b/.web-docs/README.md @@ -0,0 +1,31 @@ +The `hcloud` Packer plugin is able to create new images for use with [Hetzner +Cloud](https://www.hetzner.cloud). + +### 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 { + hcloud = { + source = "github.com/hashicorp/hcloud" + version = "~> 1" + } + } +} +``` + +Alternatively, you can use `packer plugins install` to manage installation of this plugin. + +```sh +$ packer plugins install github.com/hashicorp/hcloud +``` + +### Components + +#### Builders + +- [hcloud](/packer/integrations/hashicorp/hcloud/latest/components/builder/hetzner-cloud) - The hcloud builder + lets you create custom images on Hetzner Cloud by launching an instance, provisioning it, then + export it as an image for later reuse. diff --git a/.web-docs/components/builder/hetzner-cloud/README.md b/.web-docs/components/builder/hetzner-cloud/README.md new file mode 100644 index 00000000..3f9280f3 --- /dev/null +++ b/.web-docs/components/builder/hetzner-cloud/README.md @@ -0,0 +1,142 @@ +Type: `hcloud` +Artifact BuilderId: `hcloud.builder` + +The `hcloud` Packer builder is able to create new images for use with [Hetzner +Cloud](https://www.hetzner.cloud). 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 the Hetzner Cloud. + +The builder does _not_ manage images. Once it creates an image, it is up to you +to use it or delete it. + +## Configuration Reference + +There are many configuration options available for the builder. They are +segmented below into two categories: required and optional parameters. Within +each category, the available configuration keys are alphabetized. + +In addition to the options listed here, a +[communicator](/packer/docs/templates/legacy_json_templates/communicator) can be configured for this +builder. + +### Required Builder Configuration options: + +- `token` (string) - The client TOKEN to use to access your account. It can + also be specified via environment variable `HCLOUD_TOKEN`, if set. + +- `image` (string) - ID or name of image to launch server from. Alternatively + you can use `image_filter`. + +- `location` (string) - The name of the location to launch the server in. + +- `server_type` (string) - ID or name of the server type this server should + be created with. + +### Optional: + +- `endpoint` (string) - Non standard api endpoint URL. Set this if you are + using a Hetzner Cloud API compatible service. It can also be specified via + environment variable `HCLOUD_ENDPOINT`. + +- `image_filter` (object) - Filters used to populate the `filter` + field. Example: + + ```hcl + image_filter { + most_recent = true + with_selector = ["name==my-image"] + } + ``` + + This selects the most recent image with the label `name==my-image`. NOTE: + This will fail unless _exactly_ one AMI is returned. In the above example, + `most_recent` will cause this to succeed by selecting the newest image. + + - `with_selector` (list of strings) - label selectors used to select an + `image`. NOTE: This will fail unless _exactly_ one image is returned. + Check the official hcloud docs on + [Label Selectors](https://docs.hetzner.cloud/#overview-label-selector) + for more info. + + - `most_recent` (boolean) - Selects the newest created image when true. + This is most useful if you base your image on another Packer build image. + + You may set this in place of `image`, but not both. + +- `server_name` (string) - The name assigned to the server. The Hetzner Cloud + sets the hostname of the machine to this value. + +- `snapshot_name` (string) - The name of the resulting snapshot that will + appear in your account as image description. Defaults to `packer-{{timestamp}}` (see + [configuration templates](/packer/docs/templates/legacy_json_templates/engine) for more info). + The snapshot_name must be unique per architecture. + If you want to reference the image as a sample in your terraform configuration please use the image id or the `snapshot_labels`. + +- `snapshot_labels` (map of key/value strings) - Key/value pair labels to + apply to the created image. + +- `poll_interval` (string) - Configures the interval in which actions are + polled by the client. Default `500ms`. Increase this interval if you run + into rate limiting errors. + +- `user_data` (string) - User data to launch with the server. Packer will not + automatically wait for a user script to finish before shutting down the + instance this must be handled in a provisioner. + +- `user_data_file` (string) - Path to a file that will be used for the user + data when launching the server. + +- `ssh_keys` (array of strings) - List of SSH keys by name or id to be added + to image on launch. + + + +- `temporary_key_pair_type` (string) - `dsa` | `ecdsa` | `ed25519` | `rsa` ( the default ) + + Specifies the type of key to create. The possible values are 'dsa', + 'ecdsa', 'ed25519', or 'rsa'. + + NOTE: DSA is deprecated and no longer recognized as secure, please + consider other alternatives like RSA or ED25519. + +- `temporary_key_pair_bits` (int) - Specifies the number of bits in the key to create. For RSA keys, the + minimum size is 1024 bits and the default is 4096 bits. Generally, 3072 + bits is considered sufficient. DSA keys must be exactly 1024 bits as + specified by FIPS 186-2. For ECDSA keys, bits determines the key length + by selecting from one of three elliptic curve sizes: 256, 384 or 521 + bits. Attempting to use bit lengths other than these three values for + ECDSA keys will fail. Ed25519 keys have a fixed length and bits will be + ignored. + + NOTE: DSA is deprecated and no longer recognized as secure as specified + by FIPS 186-5, please consider other alternatives like RSA or ED25519. + + + + +- `rescue` (string) - Enable and boot in to the specified rescue system. This + enables simple installation of custom operating systems. `linux64` or `linux32` + +- `upgrade_server_type` (string) - ID or name of the server type this server should + be upgraded to, without changing the disk size. Improves building performance. + The resulting snapshot is compatible with smaller server types and disk sizes. + +## Basic Example + +Here is a basic example. It is completely valid as soon as you enter your own +access tokens: + +```hcl +source "hcloud" "basic_example" { + token = "YOUR API TOKEN" + image = "ubuntu-22.04" + location = "nbg1" + server_type = "cx11" + ssh_username = "root" +} + +build { + sources = ["source.hcloud.basic_example"] +} +``` diff --git a/.web-docs/metadata.hcl b/.web-docs/metadata.hcl new file mode 100644 index 00000000..55e26c97 --- /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 = "Hetzner Cloud" + description = "The hcloud plugin can be used with HashiCorp Packer to create custom images on Hetzner Cloud." + identifier = "packer/hashicorp/hcloud" + component { + type = "builder" + name = "Hetzner Cloud" + slug = "hcloud" + } +} 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/GNUmakefile b/GNUmakefile index c4781f93..ff630fdd 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -34,3 +34,9 @@ generate: install-packer-sdc @go generate ./... packer-sdc renderdocs -src ./docs -dst ./.docs -partials ./docs-partials # checkout the .docs folder for a preview of the docs + +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" "hashicorp" + @rm -r ".docs" diff --git a/docs/README.md b/docs/README.md index cb92f62a..de75b190 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,78 +1,31 @@ -# Scaffolding Plugins +The `hcloud` Packer plugin is able to create new images for use with [Hetzner +Cloud](https://www.hetzner.cloud). - - -## Installation - -### Using pre-built releases - -#### Using the `packer init` command - -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 { required_plugins { - name = { - version = ">= 1.0.0" - source = "github.com/hashicorp/name" + hcloud = { + source = "github.com/hashicorp/hcloud" + version = "~> 1" } } } ``` -#### Manual installation - -You can find pre-built binary releases of the plugin [here](https://github.com/hashicorp/packer-plugin-name/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-name` 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/hashicorp/hcloud +``` -## Plugin Contents - -The Scaffolding plugin is intended as a starting point for creating Packer plugins, containing: - -### Builders - -- [builder](/docs/builders/builder-name.mdx) - The scaffolding builder is used to create endless Packer - plugins using a consistent plugin structure. - -### Provisioners - -- [provisioner](/docs/provisioners/provisioner-name.mdx) - The scaffolding provisioner is used to provisioner - Packer builds. - -### Post-processors - -- [post-processor](/docs/post-processors/postprocessor-name.mdx) - The scaffolding post-processor is used to - export scaffolding builds. - -### Data Sources +### Components -- [data source](/docs/datasources/datasource-name.mdx) - The scaffolding data source is used to - export scaffolding data. +#### Builders +- [hcloud](/packer/integrations/hashicorp/hcloud/latest/components/builder/hetzner-cloud) - The hcloud builder + lets you create custom images on Hetzner Cloud by launching an instance, provisioning it, then + export it as an image for later reuse.