hops-cli is a Rust CLI for Crossplane development and XR lifecycle workflows.
This tool supports three related workflows:
- Local cluster setup on colima or kind
- Configuration package install/uninstall against the connected cluster
- XR observe/manage/adopt/orphan workflows for existing infrastructure
For local development, it can also:
- Install and manage a local cluster backend (colima or kind)
- Start a local k8s cluster with Crossplane installed via Helm
- Install the Kubernetes and Helm Crossplane providers
- Deploy an in-cluster OCI registry (
crossplane-system/registry) - Build and publish Crossplane configuration packages from an XRD project
- Install ubi:
Ensure you have ubi installed by running:curl --silent --location \ https://raw.githubusercontent.com/houseabsolute/ubi/master/bootstrap/bootstrap-ubi.sh | sh mkdir -p ~/.ubi/bin echo 'export PATH="$HOME/.ubi/bin:$PATH"' >> ~/.zshrc # or your preferred shell profile
- Install vnext with ubi:
ubi --project hops-ops/hops-cli --in /usr/local/bin --rename-exe hops
Install a specific version:
ubi --project hops-ops/hops-cli --tag vx.x.x --in /usr/local/bin/ --rename-exe hopsSee "Releases" for available versions and changenotes.
- macOS
- Rust/Cargo
- Homebrew
dockerCLIkubectlhelmup(Upbound CLI, used byup project build)awsCLI v2 (used bylocal awsto export profile credentials)
Note: hops-cli local install installs the selected backend (colima or kind) through Homebrew.
cargo buildIf you want static OpenSSL vendoring:
cargo build --features vendoredhops --help
hops local --help
hops config --help
hops secrets --help
hops validate --help
hops xr --helphops-cli is organized into a few command groups:
local- Manage a local control plane (colima, kind, or dory backend), install providers, and bootstrap AWS or GitHub provider auth.
config- Build, install, reload, and uninstall Crossplane configuration packages against the connected cluster.
secrets- Initialize secrets config, encrypt and decrypt local secrets, and sync repo-managed secrets to AWS Secrets Manager or GitHub repository secrets.
validate- Generate configuration manifests from Upbound-format XRD projects for validation workflows.
xr- Observe existing XR-backed infrastructure and render adoption, management, or orphaning manifests.
Microservice scaffolding previously available as hops service now lives in the standalone distributed CLI (distributed / distributed_cli).
hops secrets init sets up local secrets directories, .sops.yaml, and .hops.yaml so plaintext secrets can be encrypted locally and synced to AWS Secrets Manager or GitHub repository secrets.
Typical layout:
secrets/
aws/
github/
_shared/
secrets-encrypted/
aws/
github/
Typical config:
secrets:
plaintext_dir: secrets
encrypted_dir: secrets-encrypted
aws:
path: aws
region: us-east-2
tags:
hops.ops.com.ai/secret: "true"
github:
owner: hops-ops
path: github
shared_secrets:
path: _shared
repos:
- repo-a
- repo-bEncrypt and decrypt operate from the configured roots:
hops secrets encrypt
hops secrets decryptAWS sync reads from <plaintext_dir>/<aws.path>:
hops secrets sync awsAWS rules:
- A
.jsonfile becomes one AWS Secrets Manager secret with the JSON object stored as-is. - A directory containing plain files rolls up into one AWS secret. Each filename becomes a key in the JSON object.
- A
.envfile is parsed into key/value pairs and stored as one JSON secret. - A directory containing a
.envfile merges those parsed key/value pairs into that directory's rolled-up JSON secret. - Secret names are derived from the path relative to the AWS root.
--cleanuponly works when syncing the full configured AWS root.hops.ops.com.ai/secret=trueis always applied to repo-managed AWS secrets.
Examples:
secrets/aws/app.json-> AWS secretappsecrets/aws/github/tokenandsecrets/aws/github/owner-> AWS secretgithubsecrets/aws/slack/.envwithWEBHOOK_URL=...-> AWS secretslack
GitHub sync reads from <plaintext_dir>/<github.path>:
hops secrets sync githubGitHub rules:
- Each GitHub secret remains a separate GitHub secret. There is no AWS-style roll-up into a single JSON secret.
- A raw file becomes one GitHub secret.
- A
.jsonfile becomes multiple GitHub secrets, one per top-level key. - A
.envfile becomes multiple GitHub secrets, one perKEY=valueentry. - Repo-specific secrets come from repo-named paths like
secrets/github/repo-a/...orsecrets/github/repo-a.json. - Shared GitHub secrets come from
secrets/github/_shared/...and fan out to the repos listed insecrets.github.shared_secrets.reposor passed with--repo. - If a shared secret and a repo-specific secret have the same final name, the repo-specific value wins for that repo.
- GitHub secret names are normalized by the CLI to a stable format before syncing.
Examples:
secrets/github/repo-a/NPM_TOKEN-> GitHub secretNPM_TOKENinrepo-asecrets/github/repo-a/actions.jsonwith{"SLACK_WEBHOOK":"..."}-> GitHub secretSLACK_WEBHOOKinrepo-asecrets/github/repo-a/.envwithNPM_TOKEN=...-> GitHub secretNPM_TOKENinrepo-asecrets/github/_shared/ORG_TOKEN-> synced to every configured shared target repo
# 1) Install the backend (via Homebrew). Defaults to colima on macOS;
# pass --backend kind to use kind on any docker daemon.
hops local install
# 2) Start local k8s + Crossplane + providers + local registry
hops local start
# 3) Configure AWS provider-family + ProviderConfig from your AWS profile
hops local aws --profile <aws-profile>
# 4) Configure GitHub provider + ProviderConfig from your gh auth login
hops local github --owner <org-or-user>
# 5) Configure Zitadel provider + ProviderConfig from the AuthStack PAT Secret
hops local zitadel --source-context pat-local --domain auth.ops.com.ai
# 6) Install a Crossplane configuration package from an Upbound-format XRD project
hops config install --repo hops-ops/aws-auto-eks-cluster --version v0.11.0hops local supports three backends behind the same commands:
- colima — a VM running dockerd + k3s. macOS/Linux; supports
--cpus,--memory,--disk, andhops local resize. - kind — cluster nodes as docker containers on any reachable docker daemon: Docker Desktop, colima's dockerd, or CI runners. No VM of its own, so sizing flags don't apply (size the docker daemon instead); requires kind >= v0.27.
- dory — dory stock app: shared Apple
Silicon engine + product k3s. Enable Kubernetes in the Dory app (hops
does not fork Dory or call
dory k8s enable). Package installs use the same in-clusterregistry:2as other backends (Crossplane pullsregistry.crossplane-system.svc.cluster.local:5000). Docker push uses the k3s NodePort on the engine docker bridge ({dory-k8s-ip}:30500) because dockerd runs inside the engine — Maclocalhostis the wrong plane. The VM is sized in the Dory app, so hops sizing flags don't apply.
Select with the global --backend flag:
hops local start --backend kindThe chosen backend is persisted to ~/.hops/local/backend on a successful
start, so later commands (stop, destroy, doctor, package installs)
target the same cluster without the flag. Resolution order: --backend flag >
persisted choice > existing cluster detection (colima wins) > platform
default (macOS: colima, otherwise kind).
Unless --context is given, kubectl commands automatically use the backend's
kubeconfig context (colima, kind-hops, or hops-dory), regardless of your
current-context.
Stock Dory only (brew cask / Dory.app). No hops fork of Dory required.
# 1. Open Dory.app — engine healthy (not "needs attention")
# 2. Enable Kubernetes in the app; wait until the cluster is running
# (product container is usually named dory-k8s)
# 3. Bootstrap Crossplane + local package registry
hops local start --backend doryOn start/activate, hops:
- merges stock
~/.kube/dory-configinto~/.kube/configas contexthops-dory(override with--name <name>orHOPS_DORY_NAME; persisted in~/.hops/local/dory-name) - runs
kubectl config use-context hops-dory - creates/uses a docker context of the same name →
unix://$HOME/.dory/dory.sock
So you should not need:
export KUBECONFIG=$HOME/.kube/dory-config
export DOCKER_HOST=unix://$HOME/.dory/dory.sockhops local start --backend dory # name defaults to hops-dory
hops local start --backend dory --name mine # custom kube+docker context name
kubectl get nodes # context hops-dory
docker info # context hops-dory
hops local doctor
hops local github -o hops-ops
hops config install --path … --backend doryAlternatively, use kind on Dory's docker socket (no product k3s):
docker context use dory # product context from Dory.app
hops local start --backend kindCI: .github/workflows/on-pr-dory-smoke.yaml runs on a self-hosted
Apple Silicon Mac labeled hops-dory (opt-in with PR label test-dory or
workflow_dispatch). Stock Dory only — no fork build, no Colima sock.
Offline runner → job waits. The session is env-only so your desktop
defaults never change: DOCKER_HOST=unix://$HOME/.dory/dory.sock, a
job-private KUBECONFIG, and HOPS_DORY_DESKTOP=0 (hops skips
use-context / docker context switching). No destroy/stop of
dory-k8s. After start/doctor/registry, it path-installs the in-repo
fixture tests/fixtures/config-smoke (hops config install --path …) and
applies a namespaced ConfigMap XR under hops-ci. See the workflow header
for runner setup.
Two network planes matter. Mixing them up is the usual failure mode.
| Plane | Who | Where | Role |
|---|---|---|---|
| Engine Docker | docker CLI via ~/.dory/dory.sock |
Linux VM (dockerd) | build/push images |
| Cluster | kubectl / Crossplane pods | k3s inside dory-k8s |
run control plane + pull packages |
Package registry model (same idea as colima/kind, adapted to Dory):
- Pull (Crossplane): in-cluster Service
registry.crossplane-system.svc.cluster.local:5000over HTTPS - Push (docker on the engine): k3s NodePort on the docker bridge
{dory-k8s-ip}:30500(not Maclocalhost:30500) - TLS: hops generates a self-signed CA/server cert (
Secret hops-local-registry-tls) and patches Crossplane to trust that CA. Plain HTTP fails package unpack (http: server gave HTTP response to HTTPS client).
Do not put host.dory.internal in Crossplane package refs. That name exists
on the node /etc/hosts, not in pod CoreDNS, and is the wrong plane for
Crossplane's package manager.
Engine won't start / thrash / HV_BAD_ARGUMENT (big Macs)
The failure we hit in practice: on a large laptop (e.g. 128 GB host
RAM), Dory's UI Recommended / host-scaled default for guest engine memory
was ~half of host RAM → 64 GB (DORYD_MEMORY_MB=65536). That is not
"you need 64 GB of containers" — it is an aggressive ceiling. On Apple Silicon,
Hypervisor.framework often rejects creating a VM that large
(HV_BAD_ARGUMENT), so the engine never stays healthy and the UI looks broken
even though a 4 GB engine works fine.
# Pin sane resources (4 GiB / 4 CPUs is enough for hops local)
defaults write com.pythonxi.Dory dory.engineMemoryMB -int 4096
defaults write com.pythonxi.Dory dory.engineCPUCount -int 4
# Confirm the LaunchAgent is not still on 65536:
launchctl print "gui/$(id -u)/dev.dory.doryd" 2>/dev/null | grep DORYD_MEMORY
# Live engine cmdline should show --mem-mb 4096, not 65536:
ps aux | grep 'dory-hv engine' | grep -v grepIn the Dory app Resources panel: set memory to ~4 GB (8 GB is usually fine too). Do not apply Recommended if it offers tens of GB on a high-RAM Mac.
Then fully restart the engine (quit Dory, ensure no thrashing doryd/dory-hv,
reopen or dory engine wake). Once guest RAM is modest, the rest of hops local
is ordinary.
Docker socket path
Stock Docker API socket is:
unix://$HOME/.dory/dory.sock
There is no ~/.dory/engine.sock for the host Docker API. hops uses dory.sock
only. Prefer the docker context hops creates (hops-dory) over manual
DOCKER_HOST.
Kubernetes missing / no dory-k8s container
k3s is product-owned. hops does not run dory k8s enable.
- Install the Kubernetes component if needed:
dory component install kubernetes - Enable Kubernetes in the Dory app UI
- Wait until a
dory-k8scontainer is running:docker ps(with context hops-dory) - Re-run
hops local start --backend dory
k ctx has no dory / hops-dory entry
Stock Dory writes ~/.kube/dory-config (context often named default). hops
merges that into ~/.kube/config as hops-dory on activate/start. If the
merge is missing:
hops local doctor --backend dory
kubectl config get-contexts # expect hops-dory
kubectl config use-context hops-doryConfiguration Installed=False / HTTPS error
http: server gave HTTP response to HTTPS client
Crossplane always pulls packages with HTTPS. The local registry must be TLS (hops sets this up). If you have an old HTTP-only registry Deployment:
kubectl -n crossplane-system delete deploy registry
kubectl -n crossplane-system delete secret hops-local-registry-tls
hops local start --backend dory # recreates TLS secret + registry + CA patchdocker push to localhost:30500 fails (connection refused / HTTPS to HTTP)
With the docker context pointed at Dory, localhost is the engine VM, not
the Mac. hops pushes to {dory-k8s container IP}:30500 and marks the engine
docker bridge as an insecure registry for that self-signed TLS endpoint.
Check:
docker context show # hops-dory
hops local doctor # "package push registry reachable (…:30500)"Do not rely on Mac kubectl port-forward for engine-side docker push.
Engine docker broken after daemon.json / dockerd kill
Prefer Dory's own recovery:
dory repair dockerd --apply
dory engine wake
dory readinessAvoid raw kill of dockerd inside the guest unless you are prepared to wait for
dory repair / LaunchAgent recovery (live-restore helps but is not magic).
Useful diagnostics
dory doctor
dory readiness
hops local doctor --backend dory
docker context show
kubectl config current-context
kubectl get configuration,provider -A
kubectl -n crossplane-system get deploy,svc,secret | grep -E 'registry|crossplane|hops-local'hops local aws, hops local github, and hops local zitadel install the provider package and bootstrap auth into a local control plane. The exception is --refresh, which updates credentials only.
hops local aws installs the AWS provider package and uses your AWS CLI configuration to generate credentials for it.
# Use an explicit AWS profile
hops local aws --profile hops
# Refresh only the Secret credentials without re-applying the Provider or ProviderConfig
hops local aws --profile hops --refreshHow it works:
- Resolves the profile in this order:
--profile,AWS_PROFILE,AWS_DEFAULT_PROFILE, then interactive prompt. - Runs
aws configure export-credentials --format process. - If the selected profile needs AWS SSO login, it runs
aws sso login --profile <profile>and retries once. - Applies the AWS provider package unless
--refreshis used. - Writes the generated credentials into a Kubernetes Secret, defaulting to
default/aws-creds. - Applies an AWS
ProviderConfignameddefaultunless--refreshis used. - Supports overrides for namespace, Secret name, ProviderConfig name, provider name, and provider package.
hops local github installs the GitHub provider package and uses your GitHub CLI login to generate credentials for it.
# Use an explicit owner
hops local github --owner hops-ops
# Refresh only the Secret credentials without re-applying the Provider or ProviderConfig
hops local github --owner hops-ops --refreshHow it works:
- Resolves the owner in this order:
--owner,GH_OWNER,GITHUB_OWNER, then interactive prompt. - Uses your current
gh auth token. - If
ghis not authenticated, it runsgh auth loginand retries once. - Applies the GitHub provider package unless
--refreshis used. - Writes the generated credentials into a Kubernetes Secret, defaulting to
default/github-creds. - Applies a GitHub
ProviderConfignameddefaultunless--refreshis used. - Supports overrides for namespace, Secret name, ProviderConfig name, provider name, and provider package.
hops local zitadel installs the Zitadel provider package and creates a Zitadel ProviderConfig for consumer stacks that need to author Zitadel resources from the local control plane.
# Read the AuthStack iam-admin PAT from a target cluster and create default/zitadel-credentials + ProviderConfig/default
hops local zitadel --source-context pat-local --domain auth.ops.com.ai
# Use an explicit token instead of reading the target cluster Secret
ZITADEL_ACCESS_TOKEN=<pat> hops local zitadel --domain auth.ops.com.ai
# Refresh only the Secret credentials without re-applying the Provider or ProviderConfig
hops local zitadel --source-context pat-local --domain auth.ops.com.ai --refreshHow it works:
- Resolves the access token in this order:
--access-token,ZITADEL_ACCESS_TOKEN, then the source cluster Secret. - Defaults the source Secret to
pat-local/zitadel/iam-admin-patkeypat. - Writes the generated credentials JSON into a Kubernetes Secret, defaulting to
default/zitadel-credentials. - Applies a Zitadel
ProviderConfignameddefaultunless--refreshis used. - Supports overrides for namespace, Secret name, ProviderConfig name, provider name, provider package, source context, source namespace, source Secret, source key, domain, port, and
insecure.
config install and config uninstall operate on the currently connected Kubernetes cluster.
There are two different config install modes:
- Source-build mode via
--pathor--repobuilds an Upbound-format XRD project locally, pushes the package through the local registry flow, and is intended for a local control plane started withhops local start. - Remote-package mode via
--repo ... --version ...skips the build and applies a pinned package reference directly, so it can work against non-local connected clusters too.
Common install flows:
# Build from the current directory when it is an Upbound-format XRD project
hops config install
# Build from an explicit local Upbound-format XRD project path
hops config install --path /path/to/project
# Install from a GitHub repo; interactive TTY runs ask whether to build from source
# or use a published version
hops config install --repo hops-ops/aws-auto-eks-cluster
# Force a source reload before re-applying
hops config install --repo hops-ops/aws-auto-eks-cluster --reload
# Set spec.skipDependencyResolution=true on the generated Configuration
hops config install --path /path/to/project --skip-dependency-resolution
# Apply a pinned remote package directly from ghcr.io
hops config install --repo hops-ops/aws-auto-eks-cluster --version v0.11.0Common uninstall flows:
# Remove by explicit configuration name
hops config uninstall --name hops-ops-aws-auto-eks-cluster
# Remove by repo slug
hops config uninstall --repo hops-ops/aws-auto-eks-cluster
# Remove configurations derived from local build artifacts
hops config uninstall --path /path/to/projectNotes:
--reloadonly applies to source installs:--pathor--repowithout--version.--skip-dependency-resolutionsetsspec.skipDependencyResolution=trueon the generatedConfiguration.config install --repo ...now prompts in interactive terminals to choose between cloning/building from source or applying a published package version. Published-version prompts suggest the latest discovered tag by default and still accept arbitrary tags such aspr-<gitsha>.- Non-interactive
config install --repo ...keeps the previous default behavior and builds from source. config install --repo ... --version ...skips clone/build and applies the remote package directly.config uninstall --repo ...derives the configuration name as<org>-<repo>.
local install- Runs
brew install colima.
- Runs
local reset- Runs
colima kubernetes reset.
- Runs
local start [--bootstrap]- Brings up the selected backend cluster (colima / kind / dory)
- If Crossplane, k8s+helm providers, and the package registry are already
Healthy/Available, skips helm repo update/upgrade and bootstrap reapply
(fast resume). Pass
--bootstrapto force a full helm upgrade + reapply. - Cold path: installs Crossplane, applies
bootstrap/DRCs/providers/PCs, deploys the local HTTPS package registry, wires node/engine registry trust
local stop- Runs
colima stop.
- Runs
local destroy- Runs
colima delete --force.
- Runs
local uninstall- Prompts for confirmation, then runs
brew uninstall colima.
- Prompts for confirmation, then runs
config install [--path <PATH>] [--reload]- Targets the currently connected Kubernetes cluster
- Source-build mode intended for a local control plane because it depends on the local registry flow
- Runs
up project buildinPATH(defaults to current directory) - Loads generated
.uppkgartifacts from<PATH>/_output - Pushes package images to the registry exposed at
localhost:30500 - Applies Crossplane
Configurationresources pointing atregistry.crossplane-system.svc.cluster.local:5000/... - Supports
--skip-dependency-resolution
config install --repo <org/repo> [--reload]- Interactive terminals prompt for install mode: source build or published version
- Published-version installs suggest the latest discovered tag by default and accept custom tags such as
pr-<gitsha> - Non-interactive runs and
--reloadcontinue to use the source-build flow - Source-build mode is intended for a local control plane because it depends on the local registry flow
- Source builds use local repo cache at
~/.hops/local/repo-cache/<org>/<repo> - Source builds clone on first use, then fetch/pull on subsequent runs
- Source builds run the same build/load/push/apply flow as
--path
--reload- Forces source-based config install (
--pathor--repowithout--version) to delete existingConfigurationRevisionresources and matchingFunction/FunctionRevisionpackage resources from the same sources, then re-apply theConfiguration - Useful when re-running a config and you want Crossplane to re-create the current revision from source
- Forces source-based config install (
config install --repo <org/repo> --version <tag>- Remote-package mode that can target any connected cluster
- Skips clone/build and applies
Configurationwith packageghcr.io/<org>/<repo>:<tag> - Uses configuration name
<org>-<repo>(for examplehops-ops-aws-auto-eks-cluster) - Does not support
--reload - Supports
--skip-dependency-resolution
config uninstall --name <configuration-name>- Deletes the target
Configuration - Waits for package lock reconciliation
- Prunes orphaned
Configuration/Function/Providerpackages and revisions no longer present in lock - Prunes orphaned
ImageConfigrewrites for removed render functions
- Deletes the target
config uninstall --repo <org/repo>- Targets configuration name
<org>-<repo> - If cached repo exists at
~/.hops/local/repo-cache/<org>/<repo>, derives source hints from it for additional package pruning
- Targets configuration name
config uninstall --path <PATH>- Derives target configuration names from
<PATH>/_output/*.uppkgimage tags - Also derives package sources from those artifacts and prunes matching package resources (including Functions) if they remain
- Derives target configuration names from
local aws [--profile <AWS_PROFILE>]- Exports temporary AWS credentials with
aws configure export-credentials --format process - Uses profile resolution order:
--profile->AWS_PROFILE->AWS_DEFAULT_PROFILE-> interactive prompt - If AWS SSO token is missing/expired, runs
aws sso login --profile <profile>and retries once - Applies
xpkg.crossplane.io/crossplane-contrib/provider-family-aws:v2.4.0 - Waits for
providerconfigs.aws.m.upbound.ioCRD to exist - Applies a Secret (
aws-creds) and AWSProviderConfig(default) in namespacedefault --refreshupdates only the Secret credentials and skips Provider/ProviderConfig apply- Supports overrides via
--namespace,--secret-name,--provider-config-name,--provider-name, and--provider-package
- Exports temporary AWS credentials with
local github [--owner <ORG_OR_USER>]- Exports your current GitHub CLI token with
gh auth token - Uses owner resolution order:
--owner->GH_OWNER->GITHUB_OWNER-> interactive prompt with your authenticatedghlogin as the default - If GitHub CLI is not authenticated, runs
gh auth loginand retries once - Applies
xpkg.crossplane.io/crossplane-contrib/provider-upjet-github:v0.19.0 - Waits for
providerconfigs.github.m.upbound.ioCRD to exist - Applies a Secret (
github-creds) and GitHubProviderConfig(default) in namespacedefault --refreshupdates only the Secret credentials and skips Provider/ProviderConfig apply- Supports overrides via
--namespace,--secret-name,--provider-config-name,--provider-name, and--provider-package
- Exports your current GitHub CLI token with
validate generate-configuration [--path <PATH>] [--api-path <APIS_PATH>]- Reads
<PATH>/upbound.yamland writes<APIS_PATH>/configuration.yaml - Auto-detects
--api-pathviaapis/*/definition.yamlwhen omitted - Ensures
apis/**/configuration.yamlis present in<PATH>/.gitignore(unless--no-gitignore-update)
- Reads
xr observe --kind <KIND> --name <NAME> --namespace <NAMESPACE> --aws-region <REGION>- Generates an observe-only XR manifest for an existing resource
- Loads the live XR from the cluster when present
- Enriches the manifest with live AWS discovery for supported XR kinds such as
AutoEKSClusterandNetwork - Supports
--outputand--apply
xr adopt --kind <KIND> --name <NAME> --namespace <NAMESPACE>- Lists managed resources that belong to the XR and renders metadata patches needed for adoption
- For
AutoEKSCluster, uses the composite-specific labelhops.ops.com.ai/autoekscluster=<name> - Only emits patches for resources whose external name is missing or blank and can be resolved for that kind
- Supports
--apply,--output, and--recursive
xr manage --kind <KIND> --name <NAME> --namespace <NAMESPACE>- Generates the final managed XR manifest from an observed or adopted XR already in the cluster
- Supports
--outputand--apply
xr orphan --kind <KIND> --name <NAME> --namespace <NAMESPACE>- Renders managed-resource patches that remove
Deletefrom management policies - Supports
--applyand--output
- Renders managed-resource patches that remove
Typical reclaim flow:
# 1) Observe the existing resource into an XR manifest
hops xr observe --kind AutoEKSCluster --name pat-local --namespace default --aws-region us-east-2 --output observed.yaml
# 2) Apply the observe XR if desired
kubectl apply -f observed.yaml
# 3) Render and apply adoption patches for the next set of managed resources
hops xr adopt --kind AutoEKSCluster --name pat-local --namespace default --apply
# 4) Repeat adopt until no more patches are needed, or use --recursive
hops xr adopt --kind AutoEKSCluster --name pat-local --namespace default --recursive --apply
# 5) Convert the XR into a managed manifest
hops xr manage --kind AutoEKSCluster --name pat-local --namespace default --output managed.yamlNotes:
xr adoptonly patches resources it can identify for the selected XR kind.- A blank
crossplane.io/external-nameis treated as missing. AutoEKSClusteradoption currently resolves identities for supported managed kinds such as IAM attachments and KMS keys.
Set LOG_LEVEL to control output (default: info):
LOG_LEVEL=debug hops local startcargo test