crossplane / crossplane/cli

Plan layer: run provider plan servers, add provider planning to simulate

Open
#369 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Go
Stars
19
Forks
31
Avg merge
3d 4h
Merged PRs (30d)
52

Description

### What

Implement the provider layer from the accepted design ([crossplane/cli#181](https://github.com/crossplane/cli/pull/181),[design/one-pager-cli-simulate.md](https://github.com/crossplane/cli/blob/main/design/one-pager-cli-simulate.md)): run provider packages as local plan servers and route rendered/input MRs to them, upgrading both simulate commands from client-side diffs to provider-computed plans.

**Blocked on the crossplane/upjet PlanService design PR.** this issue follows whatever that review approves. https://github.com/crossplane/upjet/pull/694

Scope:

- **Image sources.** Project `dependsOn` for `project simulate`; providers installed on the current cluster context for `resource simulate`; `--provider-images` overrides either. The override only changes the image list, never routing.
- **Container orchestration.** Start each provider image with its `internal plan-server` entrypoint as a local Docker container, following render's runtime conventions (pull policy, cleanup on exit). Deterministic container names derived from the image digest. `--keep-plan-servers` leaves containers running for later runs to reuse; a changed image never matches a stale server.
- **Routing.** Call each server's `GetInfo`, build the routing table from declared API groups. A resource with no route is detected up front.
- **Matching.** Match rendered to live composed resources by the `crossplane.io/composition-resource-name` annotation, falling back to group/kind/name; merge the live MR's external-name annotation and status into the request. Live resources with no rendered counterpart enter the plan as deletes.
- **Rendering responses.** Field changes inline in CRD terms, sensitive values redacted, computed values as `(known after apply)`, replacement warnings inline, provider diagnostics under their resource. Replaces counted separately in the summary (`N requires replacement`) with the wedge warning from the design.
- **Fallback.** A resource with no plan server gets the client-side diff, marked `[?]`, with the closing approximate warning. `--skip-plan` skips the plan layer entirely (no containers start).
- **Provider upgrade preview.** `resource simulate --all --provider-images `: enumerate managed resources of the served groups from the cluster, plan each with its own spec as desired and itself as live; anything that is not a no-op is a finding.

### Acceptance criteria

- [ ] Both simulate commands produce provider-computed plans for resources whose provider serves the plan protocol, and `[?]` client-side diffs for the rest, in one run.
- [ ] Routing comes only from `GetInfo`; no image-name parsing, no registry queries.
- [ ] `--provider-images`, `--skip-plan`, `--keep-plan-servers` behave as documented; leftover containers follow the naming scheme and are reused only on digest match.
- [ ] `--all` previews a provider upgrade with zero cloud API calls and no cloud credentials.
- [ ] Replaces are counted separately and never presented as destroy-and-recreate; the unsynced-until-replaced warning prints.
- [ ] JSON/YAML output includes actions, field changes, replace information, and diagnostics, sufficient for a PR bot to gate on "any replace anywhere".

### Out of scope

- The PlanService protocol and server implementation https://github.com/crossplane/upjet/pull/694
- Non-upjet providers serving plans

### Dependencies

Depends on the `project simulate` https://github.com/crossplane/cli/issues/367 and `resource simulate` https://github.com/crossplane/cli/issues/368 issues, and on the approved upjet PlanService design.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.