Skip to content

Commit

Permalink
ci: upload KIB release template to cloud director organization (#855)
Browse files Browse the repository at this point in the history
* ci: terraform script to upload KIB vsphere template to VCD

* ci: github actions workflow to upload template to vcd org

* ci: fix path to the terraform state

* ci: upload template to VCD when vsphere release is finished
  • Loading branch information
Shalin Patel authored Jul 18, 2023
1 parent 54b1758 commit b0e3190
Show file tree
Hide file tree
Showing 10 changed files with 365 additions and 27 deletions.
15 changes: 15 additions & 0 deletions .github/composite/vcd-e2e/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Builds vSphere image template when a release tag is created
name: Upload VCD templates for Konvoy E2E tests
description: "Common workflow to upload template to VCD"

runs:
using: "composite"
steps:
- name: upload VCD template
shell: bash
run: make infra.vcd.create

- name: Run make destroy to clean up failed tests
shell: bash
if: ${{ always() }}
run: make infra.vcd.destroy || true
55 changes: 55 additions & 0 deletions .github/workflows/release-vcd-template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Builds vSphere image template when a release tag is created
name: Upload VCD templates for Konvoy E2E tests
on:
workflow_dispatch:
inputs:
template_name:
description: "Name of the template in vCenter to upload to Cloud Director"
type: string
required: true
env:
VCD_SERVER: ${{ secrets.VCD_SERVER }}
VCD_ORG_USERNAME: ${{ secrets.VCD_ORG_USERNAME }}
VCD_ORG_PASSWORD: ${{ secrets.VCD_ORG_PASSWORD }}
SSH_BASTION_KEY_CONTENTS: ${{ secrets.SSH_BASTION_KEY_CONTENTS }}
SSH_BASTION_PUBLIC_KEY_CONTENTS: ${{ secrets.SSH_BASTION_PUBLIC_KEY_CONTENTS }}
VSPHERE_USERNAME: ${{ secrets.VSPHERE_USERNAME }}
VSPHERE_USER: ${{ secrets.VSPHERE_USERNAME }} # required for terraform
VSPHERE_PASSWORD: ${{ secrets.VSPHERE_PASSWORD }}
GITHUB_TOKEN: ${{ secrets.MESOSPHERECI_USER_TOKEN }}
VSPHERE_SERVER: ${{ secrets.VSPHERE_SERVER }}
VSPHERE_DATASTORE: ${{ secrets.VSPHERE_DATASTORE }}
TEMPLATE_NAME_TO_UPLOAD: ${{ inputs.template_name }}

jobs:
build-e2e:
runs-on:
- self-hosted
- small
continue-on-error: false
steps:
- name: Checkout konvoy-image-builder repository
uses: actions/checkout@v3
with:
fetch-depth: 0
ref: ${{ github.ref }}

- name: Set up Go
uses: actions/setup-go@v4
with:
go-version-file: 'go.mod'
cache: true

- name: Setup SSH agent with private key to connect with pre-configured bastion host
uses: webfactory/ssh-agent@v0.8.0
with:
ssh-private-key: ${{ secrets.SSH_BASTION_KEY_CONTENTS }}

# configure git to access private repo hosting vsphere module mesosphere/vcenter-tools
- name: Configure git to clone private registry from mesosphere org
run: |
git config --global url."https://git:${{ secrets.MESOSPHERECI_USER_TOKEN }}@github.com/mesosphere".insteadOf "https://github.com/mesosphere"
git config --global url."https://${{ secrets.MESOSPHERECI_USER_TOKEN }}:x-oauth-basic@github.com/mesosphere".insteadOf ssh://git@github.com/mesosphere
- name: Upload template to VCD
uses: ./.github/composite/vcd-e2e/
25 changes: 25 additions & 0 deletions .github/workflows/release-vsphere-template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,28 @@ jobs:
VSPHERE_SERVER: ${{ secrets.VSPHERE_SERVER }}
VSPHERE_DATASTORE: ${{ secrets.VSPHERE_DATASTORE }}
VSPHERE_DATACENTER: ${{ secrets.VSPHERE_DATACENTER }}

- name: Extract vsphere template name
id: extract-template
shell: bash
run: |
export RELEASE_TEMPLATE=$(jq -r '.last_run_uuid as $runid | .builds[] | select(.packer_run_uuid==$runid).artifact_id' manifest.json)
echo "release_template=${RELEASE_TEMPLATE}" >> "$GITHUB_OUTPUT"
echo "Release template = $RELEASE_TEMPLATE"
echo "$GITHUB_OUTPUT"
- name: Upload template to VCD
uses: ./.github/composite/vcd-e2e/
env:
VCD_SERVER: ${{ secrets.VCD_SERVER }}
VCD_ORG_USERNAME: ${{ secrets.VCD_ORG_USERNAME }}
VCD_ORG_PASSWORD: ${{ secrets.VCD_ORG_PASSWORD }}
SSH_BASTION_KEY_CONTENTS: ${{ secrets.SSH_BASTION_KEY_CONTENTS }}
SSH_BASTION_PUBLIC_KEY_CONTENTS: ${{ secrets.SSH_BASTION_PUBLIC_KEY_CONTENTS }}
VSPHERE_USERNAME: ${{ secrets.VSPHERE_USERNAME }}
VSPHERE_USER: ${{ secrets.VSPHERE_USERNAME }} # required for terraform
VSPHERE_PASSWORD: ${{ secrets.VSPHERE_PASSWORD }}
GITHUB_TOKEN: ${{ secrets.MESOSPHERECI_USER_TOKEN }}
VSPHERE_SERVER: ${{ secrets.VSPHERE_SERVER }}
VSPHERE_DATASTORE: ${{ secrets.VSPHERE_DATASTORE }}
TEMPLATE_NAME_TO_UPLOAD: ${{ steps.extract-template.outputs.release_template }}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,7 @@ github-token.txt
.local
/overrides/release.yaml
ansible-runs

.terraform
*.tfstate*
.terraform.*
61 changes: 42 additions & 19 deletions test/infra/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
# ---------------------------------------------------------------------
export GOOS ?= $(shell go env GOOS 2>/dev/null)
export GOARCH ?= $(shell go env GOARCH 2>/dev/null)
export TERRAFORM_VERSION ?= 0.15.3
export TERRAFORM_VERSION ?= 1.5.2
export TERRAFORM_ASSETS ?= $(CURDIR)/.local/terraform/$(TERRAFORM_VERSION)/bin/
export TERRAFORM_URL ?= https://releases.hashicorp.com/terraform/$(TERRAFORM_VERSION)/terraform_$(TERRAFORM_VERSION)_$(GOOS)_$(GOARCH).zip
export SCRIPT_DIR ?= $(CURDIR)/hack
export TERRAFORM_BIN = $(TERRAFORM_ASSETS)/terraform

TEST_MODULES_DIR = $(CURDIR)/test/infra
TEST_INFRA_STATE_DIR ?= $(CURDIR)/.local/infra
INFRA_MODULES_DIR = $(CURDIR)/test/infra

# export for local testing
SSH_BASTION_PUBLIC_KEY_FILE ?= ""
Expand All @@ -20,6 +19,18 @@ ifeq ($(CI),true)
SSH_BASTION_PUBLIC_KEY_FILE = $(CURDIR)/vsphere-bastion.pub
endif

# VCD terraform inputs
VCD_TF_FLAGS ?= \
-var='vsphere_url=$(VSPHERE_SERVER)' \
-var='vsphere_username=$(VSPHERE_USERNAME)' \
-var='vsphere_password=$(VSPHERE_PASSWORD)' \
-var='datastore_name=$(VSPHERE_DATASTORE)' \
-var='ssh_public_key=$(SSH_BASTION_PUBLIC_KEY_FILE)' \
-var='vcd_url=$(VCD_SERVER)' \
-var='vcd_org_username=$(VCD_ORG_USERNAME)' \
-var='vcd_org_password=$(VCD_ORG_PASSWORD)' \
-var='vm_template_name_to_upload=$(TEMPLATE_NAME_TO_UPLOAD)'

.PHONY: install-terraform
install-terraform: ## Download and unpack terraform binary
install-terraform: $(TERRAFORM_BIN)
Expand All @@ -35,52 +46,64 @@ $(TERRAFORM_BIN):
infra.aws.init: ## Initialize infrastructure metadata
infra.aws.init: install-terraform
$(call print-target)
mkdir -p $(TEST_INFRA_STATE_DIR)/aws
$(TERRAFORM_BIN) -chdir=$(TEST_INFRA_STATE_DIR)/aws init -from-module=$(TEST_MODULES_DIR)/aws -force-copy || true
cd $(TEST_INFRA_STATE_DIR)/aws && $(TEST_INFRA_STATE_DIR)/aws/init.sh
$(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/aws init
cd $(INFRA_MODULES_DIR)/aws && $(INFRA_MODULES_DIR)/aws/init.sh

.PHONY: infra.vsphere.init
infra.vsphere.init: ## Initialize infrastructure metadata
infra.vsphere.init: install-terraform
$(call print-target)
mkdir -p $(TEST_INFRA_STATE_DIR)/vsphere
$(TERRAFORM_BIN) -chdir=$(TEST_INFRA_STATE_DIR)/vsphere init -from-module=$(TEST_MODULES_DIR)/vsphere -force-copy || true
$(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/vsphere init

.PHONY: infra.aws.create
infra.aws.create: ## Create infrastructure
infra.aws.create: infra.aws.init
$(call print-target)
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(TEST_INFRA_STATE_DIR)/aws plan
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(TEST_INFRA_STATE_DIR)/aws apply -auto-approve
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/aws plan
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/aws apply -auto-approve

PHONY: infra.vsphere.create
infra.vsphere.create: ## Create infrastructure
infra.vsphere.create: TF_VAR_ssh_public_key=$(SSH_BASTION_PUBLIC_KEY_FILE)
infra.vsphere.create: TF_VAR_datastore_name=$(VSPHERE_DATASTORE)
infra.vsphere.create: infra.vsphere.init
$(call print-target)
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(TEST_INFRA_STATE_DIR)/vsphere plan
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(TEST_INFRA_STATE_DIR)/vsphere apply -auto-approve
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/vsphere plan
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/vsphere apply -auto-approve

packer-aws-offline-override.yaml: infra.aws.create install-envsubst
@$(TEST_INFRA_STATE_DIR)/aws/export.sh $@
@$(INFRA_MODULES_DIR)/aws/export.sh $@

packer-ova-offline-override.yaml: infra.vsphere.create install-envsubst
@$(TEST_INFRA_STATE_DIR)/vsphere/export.sh $@
@$(INFRA_MODULES_DIR)/vsphere/export.sh $@

.PHONY: infra.aws.destroy
infra.aws.destroy: ## Destroy infrastructure
infra.aws.destroy: install-terraform infra.aws.init
$(call print-target)
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(TEST_INFRA_STATE_DIR)/aws destroy -auto-approve
rm -r $(TEST_INFRA_STATE_DIR)/aws

TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/aws destroy -auto-approve

.PHONY: infra.vsphere.destroy
infra.vsphere.destroy: ## Destroy infrastructure
infra.vsphere.destroy: TF_VAR_ssh_public_key=$(SSH_BASTION_PUBLIC_KEY_FILE)
infra.vsphere.destroy: TF_VAR_datastore_name=$(VSPHERE_DATASTORE)
infra.vsphere.destroy: infra.vsphere.init
$(call print-target)
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(TEST_INFRA_STATE_DIR)/vsphere destroy -auto-approve
rm -r $(TEST_INFRA_STATE_DIR)/vsphere
TF_LOG=INFO $(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/vsphere destroy -auto-approve

.PHONY: infra.vcd.init
infra.vcd.init: ## Initialize VCD infrastructure
infra.vcd.init: install-terraform
$(call print-target)
$(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/vcd init

PHONY: infra.vcd.create
infra.vcd.create: ## Create VCD infrastructure
infra.vcd.create: infra.vcd.init
$(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/vcd plan $(VCD_TF_FLAGS)
$(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/vcd apply -auto-approve $(VCD_TF_FLAGS)

PHONY: infra.vcd.destroy
infra.vcd.destroy: ## Destroy VCD infrastructure
infra.vcd.destroy: infra.vcd.init
$(TERRAFORM_BIN) -chdir=$(INFRA_MODULES_DIR)/vcd destroy -auto-approve $(VCD_TF_FLAGS)
8 changes: 4 additions & 4 deletions test/infra/aws/export.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ set -o pipefail
set -o nounset

# shellcheck disable=SC2155
export AWS_VPC_ID="$("${TERRAFORM_BIN}" -chdir=.local/infra/aws output -raw vpc_id)"
export AWS_VPC_ID="$("${TERRAFORM_BIN}" -chdir="${INFRA_MODULES_DIR}/aws" output -raw vpc_id)"
# shellcheck disable=SC2155
export AWS_SECURITY_GROUP_ID="$("${TERRAFORM_BIN}" -chdir=.local/infra/aws output -raw security_group_id)"
export AWS_SECURITY_GROUP_ID="$("${TERRAFORM_BIN}" -chdir="${INFRA_MODULES_DIR}/aws" output -raw security_group_id)"
# shellcheck disable=SC2155
export AWS_SUBNET_ID="$("${TERRAFORM_BIN}" -chdir=.local/infra/aws output -raw public_subnets)"
"${ENVSUBST_ASSETS}"/envsubst < .local/infra/aws/packer-aws-offline-override.yaml.tmpl >> "$1"
export AWS_SUBNET_ID="$("${TERRAFORM_BIN}" -chdir="${INFRA_MODULES_DIR}/aws" output -raw public_subnets)"
"${ENVSUBST_ASSETS}"/envsubst < "${INFRA_MODULES_DIR}"/aws/packer-aws-offline-override.yaml.tmpl >> "$1"
74 changes: 74 additions & 0 deletions test/infra/vcd/bastion.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
resource "random_id" "build_id" {
byte_length = 8
}
module "bastion_node" {
source = "github.com/mesosphere/vcenter-tools/modules/vmclone"

node_name = "kib-vcd-bastion-${random_id.build_id.hex}"
ssh_public_key = file(var.ssh_public_key)

datastore_name = var.datastore_name
datastore_is_cluster = false
vm_template_name = var.bastion_base_template
resource_pool_name = var.vcd_bastion_resource_pool_name
root_volume_size = var.root_volume_size #80
vsphere_folder = var.vcd_bastion_vsphere_folder
ssh_user = var.ssh_user
custom_attribute_owner = var.bastion_owner
custom_attribute_expiration = "2h"
}

resource "null_resource" "copy_upload_template_script" {
provisioner "file" {
source = "${path.module}/upload-template.sh"
destination = "/home/${var.ssh_user}/upload-template.sh"
}
connection {
host = module.bastion_node.nat_address
port = module.bastion_node.nat_ssh_port
user = var.ssh_user
agent = true
}
}

resource "null_resource" "execute_upload_template_script" {
provisioner "remote-exec" {
inline = [
"export PROD_VSPHERE_URL=${var.vsphere_url}",
"export PROD_VSPHERE_USERNAME=${var.vsphere_username}",
"export PROD_VSPHERE_PASSWORD=${var.vsphere_password}",
"export VCD_URL=${var.vcd_url}",
"export VCD_USERNAME=${var.vcd_org_username}",
"export VCD_PASSWORD=${var.vcd_org_password}",
"export PROD_TEMPLATE_NAME=${var.vm_template_name_to_upload}",
"export VCD_ORG=${var.vcd_org}",
"export VCD_ORG_CATALOG=${var.vcd_org_catalog}",
"set -o errexit",
"chmod +x /home/${var.ssh_user}/upload-template.sh",
"/home/${var.ssh_user}/upload-template.sh | tee /home/${var.ssh_user}/upload-template.log"
]
}
provisioner "remote-exec" {
inline = [
"cat /home/${var.ssh_user}/upload-template.log"
]
}
connection {
host = module.bastion_node.nat_address
port = module.bastion_node.nat_ssh_port
user = var.ssh_user
agent = true
}
depends_on = [
null_resource.copy_upload_template_script
]
}


output "bastion_node_default_ip_address" {
value = module.bastion_node.default_ip_address
}

output "bastion_node_ssh_nat_address" {
value = "${module.bastion_node.nat_address}:${module.bastion_node.nat_ssh_port}"
}
48 changes: 48 additions & 0 deletions test/infra/vcd/upload-template.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/bin/bash
set -euo pipefail

SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )"

PROD_VSPHERE_URL=${PROD_VSPHERE_URL:=""}
PROD_VSPHERE_USERNAME=${PROD_VSPHERE_USERNAME:=""}
PROD_VSPHERE_PASSWORD=${PROD_VSPHERE_PASSWORD:=""}
PROD_VSPHERE_DATACENTER=${PROD_VSPHERE_DATACENTER:="dc1"}
PROD_TEMPLATE_NAME=${PROD_TEMPLATE_NAME:=""}


VCD_URL=${VCD_URL:=""}
VCD_USERNAME=${VCD_USERNAME:=""}
VCD_PASSWORD=${VCD_PASSWORD:=""}
VCD_ORG=${VCD_ORG:=""}
VCD_ORG_CATALOG=${VCD_ORG_CATALOG:=""}




GOVC_VERSION=${GOVC_VERSION:="v0.30.5"}
TMPDIR=${TMPDIR:=$SCRIPT_DIR}
# extract govc binary to /usr/local/bin
# note: the "tar" command must run with root permissions
GOVC_INSTALL_DIR="${TMPDIR}/govc-${GOVC_VERSION}"
mkdir -p "${GOVC_INSTALL_DIR}"
curl -L -o "${GOVC_INSTALL_DIR}"/govc.tar.gz "https://github.com/vmware/govmomi/releases/download/${GOVC_VERSION}/govc_$(uname -s)_$(uname -m).tar.gz"
tar -xvzf "${GOVC_INSTALL_DIR}"/govc.tar.gz -C "${GOVC_INSTALL_DIR}"


echo "Exporting template ""${PROD_TEMPLATE_NAME}"" from production"
GOVC_URL=${PROD_VSPHERE_URL} GOVC_USERNAME=${PROD_VSPHERE_USERNAME} GOVC_PASSWORD=${PROD_VSPHERE_PASSWORD} "${GOVC_INSTALL_DIR}"/govc export.ovf -f=true -sha 256 -dc="${PROD_VSPHERE_DATACENTER}" -vm "${PROD_TEMPLATE_NAME}" "${SCRIPT_DIR}"

echo "fix the file size in the file descriptor"
# shellcheck disable=SC2012
VMDK_SIZE=$(ls -l "${SCRIPT_DIR}/${PROD_TEMPLATE_NAME}/${PROD_TEMPLATE_NAME}-disk-0.vmdk" | awk '{print $5}')
sed -i -E "s/(ovf:size=\")[0-9].+(\"\/>)/\1${VMDK_SIZE}\2/g" "${SCRIPT_DIR}/${PROD_TEMPLATE_NAME}/${PROD_TEMPLATE_NAME}.ovf"

sudo dnf update -y
sudo dnf install python3 python3-pip -y
pip3 install vcd-cli
VCD_CLI="${HOME}/.local/bin/vcd"
${VCD_CLI} login "${VCD_URL}" "${VCD_ORG}" "${VCD_USERNAME}" --password "${VCD_PASSWORD}" --disable-warnings --no-verify-ssl-certs -V 37.1

echo "upload template to VCD organization's catalog"
cd "${SCRIPT_DIR}/${PROD_TEMPLATE_NAME}" && tar -cvf "${SCRIPT_DIR}/${PROD_TEMPLATE_NAME}.ova" "${PROD_TEMPLATE_NAME}".mf "${PROD_TEMPLATE_NAME}".ovf "${PROD_TEMPLATE_NAME}"-disk-0.vmdk
${VCD_CLI} catalog upload "${VCD_ORG_CATALOG}" -i "${PROD_TEMPLATE_NAME}" "${SCRIPT_DIR}/${PROD_TEMPLATE_NAME}.ova"
Loading

0 comments on commit b0e3190

Please sign in to comment.