Chapter 15Lesson 05~110 minutes

Wrapping Cloud and Infrastructure CLIs

Cloud and infrastructure CLIs already implement complex remote APIs and state models. Bash adds value when it verifies targeting, standardizes preflight and output, and sequences well-defined operations without hiding provider semantics.

IntermediateDevOps CLI integrationHands-on lab

Learning objectives

By the end of this lesson

  • Make account/project/region/workspace targeting explicit.
  • Validate dependencies and supported versions.
  • Use structured output and safe credential providers.
  • Separate preview/plan from mutation.
  • Keep wrappers thin and provider-aware.

1. Cloud CLIs are API clients with local defaults

AWS, Azure, Google Cloud, Terraform, Pulumi, and vendor-specific CLIs often read profiles, regions, projects, subscriptions, credentials, output formats, and environment variables. Scripts should make critical targeting parameters explicit rather than inheriting a developer's workstation defaults.

CLI wrapper boundary
flowchart TD
  B["Bash wrapper"] --> C["cloud / infra CLI"]
  C --> A["remote API / state backend"]
  A --> R["structured response"]
  R --> V["validate + act"]

2. Check the exact executable and version contract

require_command() {
  command -v "$1" >/dev/null 2>&1 || {
    printf 'required command missing: %s\n' "$1" >&2
    return 69
  }
}

require_command terraform || exit $?
terraform version

If your wrapper depends on specific flags or output shapes, define and validate a supported version range instead of assuming every installed version behaves identically.

3. Make account, project, subscription, region, and workspace explicit

printf 'account=%s region=%s environment=%s\n' \
  "$account" "$region" "$environment" >&2

[[ $environment != prod || $ALLOW_PROD == true ]] || {
  printf 'production access not authorized\n' >&2
  exit 65
}
Target verification

The most dangerous automation bug is often not a bad command but a correct command against the wrong account, subscription, project, region, or workspace.

4. Request machine-readable output

# Example pattern:
cloud_cli resource list --output json |
jq -r '.items[] | [.name, .id] | @tsv'

Avoid parsing tables meant for humans. Most mature cloud CLIs offer JSON or other structured output.

5. Prefer CLI-native query filters when they are stable

Many cloud CLIs support built-in query languages. These can reduce transfer size and parsing complexity, but scripts should still validate the returned shape and avoid depending on undocumented human formatting.

6. Let supported credential providers handle secrets

Use workload identity, instance roles, service principals, managed identities, federated credentials, credential helpers, or CI secret integration according to the platform. Avoid placing long-lived credentials directly into shell source or command arguments.

Tracing risk

Disable or carefully scope set -x around authentication commands and secret-bearing environment variables.

7. Infrastructure plan and apply should be separate phases

terraform init -input=false

terraform plan \
  -input=false \
  -out=tfplan

terraform apply \
  -input=false \
  tfplan

Saving and applying the reviewed plan narrows the gap between what was evaluated and what is executed.

8. Disable prompts in automation

terraform plan -input=false

# Generic cloud CLI pattern:
cloud_cli operation \
  --no-interactive \
  --output json

Exact flags differ by tool, but the principle is universal: unattended automation must fail rather than wait for human input.

9. Do not add blind retries around infrastructure mutation

Cloud APIs often have eventual consistency and transient errors, but mutations can also have ambiguous outcomes. Prefer the CLI/provider's built-in retry semantics or reconcile remote state before repeating a side-effecting operation.

10. Use plan, what-if, preview, or dry-run capabilities

Tool patternCapabilityPurpose
TerraformplanPreview proposed infrastructure changes
Cloud deployment systemswhat-if / previewReview resource deltas
Imperative CLIdry-run when supportedValidate request without mutation

Preview is especially valuable for deletion, replacement, IAM, networking, and production changes.

11. Keep wrappers thin

main() {
  preflight || return $?
  verify_target || return $?
  plan_change || return $?
  apply_change || return $?
  verify_result || return $?
}

The wrapper should coordinate stable CLI operations, not reimplement the provider's entire state model, dependency graph, or authentication system.

12. Hands-on lab: generic infrastructure wrapper skeleton

mkdir -p "$HOME/devops-academy/bash/chapter15/lesson05"
cd "$HOME/devops-academy/bash/chapter15/lesson05"

cat > infra-wrapper.sh <<'EOF'
#!/usr/bin/env bash
set -u
set -o pipefail

tool=${1:-}
target=${2:-}

[[ -n $tool && -n $target ]] || {
  printf 'usage: %s TOOL TARGET\n' "$0" >&2
  exit 64
}

command -v "$tool" >/dev/null 2>&1 || {
  printf 'missing tool: %s\n' "$tool" >&2
  exit 69
}

printf 'tool=%s target=%s phase=preflight\n' \
  "$tool" "$target" >&2

if [[ $target == prod && ${ALLOW_PROD:-false} != true ]]; then
  printf 'production target requires ALLOW_PROD=true\n' >&2
  exit 65
fi

printf 'preflight=ok\n'
printf 'Next step: call a tool-specific read-only or plan command here.\n'
EOF

chmod u+x infra-wrapper.sh
./infra-wrapper.sh git staging

Verification checklist

13. Knowledge check

Question 1. What defaults should cloud automation avoid inheriting invisibly?

Question 2. Why prefer structured CLI output?

Question 3. Why separate infrastructure plan from apply?

Question 4. Why should wrappers stay thin?

14. Summary

Cloud and infrastructure CLI wrappers should make target identity explicit, validate versions and dependencies, use supported credential providers, request structured output, disable prompts, preview changes, and keep Bash focused on orchestration rather than reimplementing provider logic.

15. Further reading

  • Terraform CLI documentation — init, plan, apply, non-interactive workflows.
  • AWS CLI, Azure CLI, and Google Cloud CLI documentation for structured output and authentication.
  • Cloud provider workload-identity documentation.
  • Infrastructure-as-code guidance on plans, previews, and production safeguards.
Next lesson

Non-Interactive Shell Behavior in CI Runners

Chapter 16 will move these tool-integration patterns into CI/CD runners, environment variables, secrets, artifacts, failure policy, and portable pipeline helper scripts.

Keep the academy open

Support free, practical DevOps education.

Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.