This directory contains working examples demonstrating various use cases and configurations for the Packer Plugin for IBM Cloud Power Virtual Server.
These examples are designed to:
- Demonstrate plugin capabilities
- Provide starting templates for common scenarios
- Serve as integration tests for the plugin
- Help users understand best practices
Before running these examples, ensure you have:
- IBM Cloud Account: Active account with PowerVS service
- API Key: IBM Cloud API key with PowerVS permissions
- PowerVS Service Instance: Created in your target zone
- SSH Key: Public key uploaded to PowerVS
- Packer: Version 1.7.0 or higher installed
# Initialize Packer and download the plugin
packer init .Create a variables.pkrvars.hcl file (don't commit this file):
ibm_api_key = "your-ibm-cloud-api-key"
service_instance_id = "your-powervs-service-instance-id"
zone = "lon04"
ssh_key_name = "your-ssh-key-name"
ssh_private_key = "~/.ssh/id_rsa"packer validate -var-file="variables.pkrvars.hcl" .packer build -var-file="variables.pkrvars.hcl" .Main build configuration demonstrating:
- Plugin initialization
- Source configuration
- Build blocks
- Provisioner usage
- Post-processor integration
Key Features:
- Multiple source definitions
- Parallel builds
- Conditional provisioning
- Error handling
Data source usage examples:
- Querying PowerVS resources
- Using data in builds
- Dynamic configuration
Variable definitions and local values:
- Input variables
- Local computations
- Variable validation
- Sensitive data handling
Build a simple custom image from a stock image:
source "powervs" "basic" {
api_key = var.ibm_api_key
service_instance_id = var.service_instance_id
zone = var.zone
source {
stock_image {
name = "CentOS-Stream-8"
}
}
instance_name = "packer-basic-${timestamp()}"
key_pair_name = var.ssh_key_name
dhcp_network = true
ssh_username = "root"
ssh_private_key_file = var.ssh_private_key
capture {
name = "basic-image-${timestamp()}"
destination = "image-catalog"
}
}
build {
sources = ["source.powervs.basic"]
provisioner "shell" {
inline = [
"yum update -y",
"yum install -y vim wget curl"
]
}
}Build from an image stored in COS:
source "powervs" "cos_import" {
api_key = var.ibm_api_key
service_instance_id = var.service_instance_id
zone = var.zone
source {
name = "imported-base-image"
cos {
bucket = var.cos_bucket
object = "base-image.ova.gz"
region = var.cos_region
}
}
instance_name = "packer-cos-${timestamp()}"
key_pair_name = var.ssh_key_name
dhcp_network = true
ssh_username = "root"
ssh_private_key_file = var.ssh_private_key
capture {
name = "custom-image-${timestamp()}"
destination = "cloud-storage"
cos {
bucket = var.cos_bucket
region = var.cos_region
access_key = var.cos_access_key
secret_key = var.cos_secret_key
}
}
}Create a base image and then build application images from it:
# Stage 1: Base image with common tools
source "powervs" "base" {
# ... configuration ...
capture {
name = "base-${formatdate("YYYY-MM-DD", timestamp())}"
destination = "image-catalog"
}
}
build {
name = "base-image"
sources = ["source.powervs.base"]
provisioner "shell" {
inline = [
"yum update -y",
"yum install -y vim wget curl git",
"yum clean all"
]
}
}
# Stage 2: Application image
source "powervs" "app" {
# ... configuration ...
source {
name = "base-2024-03-14" # Reference base image
}
capture {
name = "app-${formatdate("YYYY-MM-DD", timestamp())}"
destination = "image-catalog"
}
}
build {
name = "app-image"
sources = ["source.powervs.app"]
provisioner "shell" {
inline = [
"yum install -y httpd",
"systemctl enable httpd"
]
}
}Build multiple images simultaneously:
source "powervs" "centos" {
# CentOS configuration
source {
stock_image {
name = "CentOS-Stream-8"
}
}
# ... rest of config ...
}
source "powervs" "rhel" {
# RHEL configuration
source {
stock_image {
name = "RHEL8-SP4"
}
}
# ... rest of config ...
}
build {
sources = [
"source.powervs.centos",
"source.powervs.rhel"
]
# Shared provisioning
provisioner "shell" {
inline = [
"yum update -y",
"yum install -y common-packages"
]
}
# OS-specific provisioning
provisioner "shell" {
only = ["powervs.centos"]
inline = ["echo 'CentOS-specific setup'"]
}
provisioner "shell" {
only = ["powervs.rhel"]
inline = ["echo 'RHEL-specific setup'"]
}
}Use existing subnets instead of DHCP:
source "powervs" "existing_network" {
# ... authentication config ...
subnet_ids = [
"subnet-id-1",
"subnet-id-2"
]
dhcp_network = false # Don't create DHCP network
# ... rest of config ...
}Provide cloud-init configuration:
source "powervs" "cloud_init" {
# ... configuration ...
user_data = file("${path.root}/cloud-init.yaml")
# ... rest of config ...
}cloud-init.yaml:
#cloud-config
packages:
- vim
- wget
- curl
runcmd:
- echo "Cloud-init setup complete"build {
sources = ["source.powervs.example"]
provisioner "ansible" {
playbook_file = "./playbook.yml"
user = "root"
extra_arguments = [
"--extra-vars",
"ansible_python_interpreter=/usr/bin/python3"
]
}
}build {
sources = ["source.powervs.example"]
provisioner "file" {
source = "files/config.conf"
destination = "/etc/myapp/config.conf"
}
provisioner "shell" {
inline = [
"chmod 644 /etc/myapp/config.conf",
"systemctl restart myapp"
]
}
}build {
sources = ["source.powervs.example"]
provisioner "shell" {
inline = [
"risky-command || true" # Continue on error
]
}
provisioner "shell" {
inline = ["critical-command"]
on_error = "abort" # Stop on error
valid_exit_codes = [0, 2] # Accept these exit codes
}
}# Validate syntax
packer validate .
# Format templates
packer fmt .
# Check with specific variables
packer validate -var-file="test-variables.pkrvars.hcl" .# See what would be built without actually building
packer inspect .# Enable debug logging
export PACKER_LOG=1
export PACKER_LOG_PATH=packer-debug.log
packer build -var-file="variables.pkrvars.hcl" .name: Build PowerVS Image
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Packer
uses: hashicorp/setup-packer@main
with:
version: latest
- name: Initialize Packer
run: packer init .
- name: Validate Template
run: packer validate .
- name: Build Image
run: packer build .
env:
PKR_VAR_ibm_api_key: ${{ secrets.IBM_API_KEY }}
PKR_VAR_service_instance_id: ${{ secrets.SERVICE_INSTANCE_ID }}variable "ibm_api_key" {
type = string
sensitive = true
}
variable "zone" {
type = string
default = "lon04"
}instance_name = "packer-${timestamp()}"cleanup_timeout = "15m" # Ensure cleanup completescapture {
name = "app-v1.2.3-${formatdate("YYYY-MM-DD", timestamp())}"
}# Never commit secrets
# Use variables and .pkrvars.hcl (add to .gitignore)
api_key = var.ibm_api_key-
Plugin Not Found
packer init . # Download plugin
-
Authentication Failed
# Verify API key ibmcloud login --apikey $IBM_API_KEY
-
SSH Timeout
ssh_timeout = "30m" # Increase timeout
-
Build Fails
PACKER_LOG=1 packer build . # Enable debug logging
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Note: Remember to clean up resources after testing to avoid unnecessary costs.