Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ below.
| `account` | | AWS account the resources deploy to. |
| `region` | | AWS region. |
| `project` | | GCP project. |
| `domain` | | T Cloud Public domain: the 32-hex id or the account name. Must match your connector's spelling exactly — see below. |
| `stack-export` | | `pulumi stack export` document, to recover the account/region a preview cannot carry. A scope hint — its resources are **not** simulated. |
| `allow-mock-account` | `false` | Submit with no resolved account. Identities are then derived from a placeholder, so nothing matches your real inventory. Not for a gate. |

Expand Down Expand Up @@ -133,8 +134,53 @@ quietly turn off the gate you added it for.

A Terraform plan carries its provider configuration, so `account` and `region`
are often recoverable from the plan alone. A **Pulumi preview carries none** —
if you simulate a preview, pass `account`/`region` (and `project` for GCP), or
the resources are identified against the wrong scope.
if you simulate a preview, pass `account`/`region` (and `project` for GCP, or
`domain` for T Cloud Public), or the resources are identified against the wrong
scope.

The split is plan vs preview, not provider. What differs per provider is how
many ways a *plan* can state the value:

| Value | Where it can come from, in order |
|---|---|
| AWS region | the plan's provider config, a per-resource hint, then `region` |
| AWS account | an `assume_role` role ARN in the provider config, `stack-export`, then `account` |
| GCP project | a constant `project` in the `google` provider block, then `project` |
| T Cloud Public domain | a constant `domain_id`/`domain_name` in the `opentelekomcloud` provider block, then `domain`. **That is all.** |

And only a value **written in the provider block** reaches the plan. A provider
configured from the environment — `AWS_REGION`, `OS_DOMAIN_NAME`, both commonly
repo secrets in CI — carries nothing into `terraform show -json`. AWS has two
other paths to fall back on; OTC has none, so an OTC plan in CI needs its input
more often than an AWS plan needs `account`.

### `domain` must match your connector, byte for byte

A T Cloud Public connector's `domain` scope holds **whatever you typed when you
created it** — the 32-hex domain id *or* the account name
(`OTC00000000001000000000`). Linro never rewrites one form into the other, and
every resource's identity is derived from the spelling it holds.

So a simulation passing the other spelling composes rows that shadow nothing:
every simulated resource lands *beside* its live twin instead of over it, the
diff shows everything as new, and **nothing errors**. The run succeeds and
describes a world that does not exist.

Read the value off the connector — do not retype what you think you configured:

```yaml
- uses: linro-io/simulation-github-action@v1
with:
plan: infra/plan.json
server: ${{ vars.LINRO_SERVER }}
token: ${{ secrets.LINRO_TOKEN }}
# Exactly as the connector shows it. `OS_DOMAIN_NAME` in the job's
# environment configures the provider; it does NOT reach the plan.
domain: ${{ vars.LINRO_OTC_DOMAIN }}
```

The CLI compares the value literally: it does not fold case and it does not
resolve a name to an id, because doing either would mean calling OTC.

## Several sources, one simulation

Expand Down
20 changes: 20 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ inputs:
# A Terraform plan carries its provider config, so account/region are often
# recoverable from the plan itself. A Pulumi preview carries none, so these
# are how a preview gets scoped at all.
#
# The split is plan vs preview, not provider — but how many ways a PLAN can
# state a value does differ. AWS region has three (plan-wide, per-resource,
# the flag) and AWS account has three (an assume_role ARN, stack-export, the
# flag); an OTC domain has exactly one before the flag, a constant
# domain_id/domain_name in the provider block. Both AWS and OTC lose the
# provider-block value when it comes from the environment, which in CI it
# usually does; AWS has somewhere else to look and OTC has not.
account:
description: AWS account id the resources deploy to.
required: false
Expand All @@ -100,6 +108,16 @@ inputs:
description: GCP project id the resources deploy to.
required: false
default: ""
domain:
description: >-
T Cloud Public domain the resources deploy to: the 32-hex domain id or
the account name (e.g. OTC00000000001000000000). It must be spelt exactly
as your connector's domain scope is — the value is never rewritten from
one form to the other, so read it off the connector rather than retyping
it. An OTC provider block configured from OS_DOMAIN_NAME carries nothing
into the plan, which is why this is needed more often than `account` is.
required: false
default: ""
stack-export:
description: >-
Path to a `pulumi stack export` document, used to recover the AWS account
Expand Down Expand Up @@ -310,6 +328,7 @@ runs:
INPUT_ACCOUNT: ${{ inputs.account }}
INPUT_REGION: ${{ inputs.region }}
INPUT_PROJECT: ${{ inputs.project }}
INPUT_DOMAIN: ${{ inputs.domain }}
INPUT_STACK_EXPORT: ${{ inputs.stack-export }}
INPUT_ALLOW_MOCK_ACCOUNT: ${{ inputs.allow-mock-account }}
INPUT_LABEL: ${{ inputs.label }}
Expand Down Expand Up @@ -407,6 +426,7 @@ runs:
if [ -n "$INPUT_ACCOUNT" ]; then args+=(--account "$INPUT_ACCOUNT"); fi
if [ -n "$INPUT_REGION" ]; then args+=(--region "$INPUT_REGION"); fi
if [ -n "$INPUT_PROJECT" ]; then args+=(--project "$INPUT_PROJECT"); fi
if [ -n "$INPUT_DOMAIN" ]; then args+=(--domain "$INPUT_DOMAIN"); fi
if [ -n "$INPUT_STACK_EXPORT" ]; then args+=(--stack-export "$INPUT_STACK_EXPORT"); fi
if [ -n "$INPUT_PROJECT_DIR" ]; then args+=(--project-dir "$INPUT_PROJECT_DIR"); fi
if [ -n "$INPUT_LABEL" ]; then args+=(--label "$INPUT_LABEL"); fi
Expand Down
Loading