# Authoring desired state

This guide explains how to **author the desired state** in MechCloud Stateless IaC for GCP. You define your infrastructure using a clean, hierarchical YAML format that is inspired by Terraform but significantly simpler — no logical IDs, no state files, and no HCL. Instead, you use **nesting for relationships**, **`snake_case` for properties**, and **`ref:` syntax** for cross-resource references.

### Key Principles

| Principle                    | Description                                                                                                     |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------- |
| **Hierarchy = Relationship** | Nest resources to define parent-child relationships (e.g., subnetwork inside VPC network).                      |
| **Unique Relative Paths**    | Every resource must have a unique path (e.g., `vpc1/subnet1/vm1`). You are responsible for ensuring uniqueness. |
| **`snake_case` Properties**  | All keys use lowercase with underscores (e.g., `auto_create_subnetworks`, not `autoCreateSubnetworks`).         |
| **No Parent Links**          | Do **not** include `network` for subnetwork — MechCloud infers them from nesting.                               |
| **Sibling References**       | Use `ref:<name>` **only** if both resources are in the **same `resources:` block**.                             |
| **Non-Sibling References**   | Use `ref:<full_path>` to reference resources outside the current parent.                                        |

### Step-by-Step: Example to MechCloud Desired State

Here is a GCP desired state example using the `compute.v1.instance` resource. It assumes that the linked resources (Network, Subnetwork) already exist in the same environment.

#### MechCloud Desired State

```yaml
defaults:
  zone: us-central1-a

resources:
  - type: compute.v1.instance
    name: vm1
    props:
      machine_type: machineTypes/e2-micro
      disks:
        - boot: true
          auto_delete: true
          initialize_params:
            # Set to 30GB to maximize the Free Tier limit
            disk_size_gb: 30
            # Set to pd-standard (Standard Persistent Disk) for Free Tier eligibility
            disk_type: diskTypes/pd-standard
            source_image: projects/ubuntu-os-cloud/global/images/family/ubuntu-2404-lts
      network_interfaces:
        - subnetwork: subnetworks/subnet1
          access_configs:
            - type: ONE_TO_ONE_NAT
              name: External NAT
```

### Using `defaults` for Zonal Resources

In GCP, many resources are zonal or regional and require a `zone` or `location` property, as well as full paths that include the region or zone (e.g., `zones/us-central1-a/machineTypes/e2-micro`). To simplify authoring, you can use the `defaults:` block at the top of your YAML file for zones, while the region is automatically inferred from the Execution Context.

By setting a default `zone` in the YAML, MechCloud does two things automatically:

1. **Property Injection**: It injects the `zone` into the resource's `props` if it is missing. You don't need to repeatedly specify `zone: us-central1-a` on every disk or instance, or `location: us-central1-a` on a GKE cluster. (For regional resources, the region selected in the Execution Context dropdown is automatically injected).
2. **Path Expansion**: It expands short paths for you:
   * `machineTypes/e2-micro` becomes `zones/us-central1-a/machineTypes/e2-micro`
   * `diskTypes/pd-standard` becomes `zones/us-central1-a/diskTypes/pd-standard`

This makes your desired state much easier to read and maintain across different environments.

### Referencing Resources

In this template, the instance (`vm1`) needs to refer to the subnetwork in its network interfaces. There is no need to specify the `network` property for the instance, as specifying the subnetwork is sufficient.

Because the subnetwork reference points to a resource that is already existing and not defined in the same template, we provide a path relative to the project id (e.g. `subnetworks/subnet1`) instead of using `ref:`.

**Regional vs Global Paths**:

* If the target subnetwork exists in the **same region** selected in your Execution Context, you can use the short path: `subnetworks/subnet1`. MechCloud will automatically expand this to the full regional path (`regions/<selected-region>/subnetworks/subnet1`).
* If the target subnetwork is in a **different region**, you must specify the full relative path: `regions/europe-west1/subnetworks/subnet1`.
* For global resources (like VPC Networks), you must use the full path: `global/networks/vpc1`.

If the linked resources were being created in the *same* template, you would use the `ref:<name>` or `ref:<full_path>` syntax so MechCloud could resolve their IDs dynamically during plan and apply:

* **Short name (sibling) form:** `ref:<name>` — used when one resource needs the link of another resource that is declared **together under the same parent**.
* **Full-path (non-sibling) form:** `ref:<relative_path>` — used when the referencing resource is in a different part of the hierarchy (different parent).

### Conversion Rules

> **Tip**: Use hyphens in names for readability (e.g., `my-vpc`), but avoid spaces or special characters.

| Terraform / API Property                   | → | MechCloud                    |
| ------------------------------------------ | - | ---------------------------- |
| `type: google_compute_network`             | → | `type: compute.v1.network`   |
| `autoCreateSubnetworks`                    | → | `auto_create_subnetworks`    |
| `network` (for Subnetwork)                 | → | **Remove** — use nesting     |
| `subnetwork: google_compute_subnetwork.id` | → | `subnetwork: ref:vpc/subnet` |

Notes and clarifications:

* `snake_case` is mandatory in MechCloud YAML. MechCloud translates these property names to the GCP API property names when making provider calls (for example `auto_create_subnetworks` → `autoCreateSubnetworks`).
* There are two kinds of `ref:` forms:
  * **Short name (sibling) form:** `ref:<name>` — used when one resource needs the link of another resource that is declared **together under the same parent**.
  * **Full-path (non-sibling) form:** `ref:<relative_path>` — used when the referencing resource is in a different part of the hierarchy (different parent).

### **Resource Paths (Must Be Unique)**

Each resource gets a **unique relative path** based on its nesting within the hierarchy. This path allows MechCloud to resolve references (`ref:`) precisely at plan and apply time.

| Resource   | Path             |
| ---------- | ---------------- |
| Network    | `vpc1`           |
| Subnetwork | `vpc1/subnet1`   |
| Firewall   | `vpc1/allow-ssh` |
| Instance   | `vm1`            |

Each resource’s path must be unique across the entire desired state file.

### Next Steps

1. **Select Execution Context** At the top of the MechCloud console, select the execution context for your operation:
   * **Team** — e.g., `Academy (User 2)`
   * **Cloud Provider** — e.g., `GCP`
   * **Cloud Account** — e.g., `My GCP Project`
   * **Region** — e.g., `us-central1`
   * **Context** — e.g., `app1-dev1`
2. **Generate the Plan** Click **Plan** to generate an execution plan. MechCloud compares the desired state (defined in YAML) with the actual GCP infrastructure and determines which resources require changes.
3. **Review Plan Actions** Each resource in the plan shows an `action` indicating how MechCloud will reconcile it:
   * `create` — the resource does not exist and will be created.
   * `update` — the resource exists but properties differ and will be updated.
   * `delete` — the resource exists but is no longer in the desired state and will be removed.
   * `recreate` — the resource will be deleted and then created again (for non-updatable property changes).
   * `none` — the resource is already in the desired state; no action required.
4. **Apply the Plan (When Changes Exist)**
   * The **Apply** button becomes visible **only when** the plan includes at least one resource whose `action` is not `none`.
   * Click **Apply** to provision or update resources as per the plan.
   * MechCloud will execute the required operations and bring your GCP environment to match the desired state.
5. **Verify Post-Apply State**
   * Once the apply completes, click **Plan** again to re-run the comparison.
   * If all resources now display `action: none`, the desired and actual states are in sync.
   * In this case, the **Apply** button will not be visible because no further changes are required.
6. **Handle Errors (If Any)**
   * If any errors occur during the apply step, re-run **Plan** to refresh dependencies and reconcile state.
   * Then click **Apply** again to retry provisioning with the updated plan.
