> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ubiquex.io/llms.txt
> Use this file to discover all available pages before exploring further.

# import — Bring Existing Resources Under Management

> Adopt existing cloud resources into ubx without recreating them.

Not every resource starts its life in ubx. A bucket created manually in the AWS console. An RDS instance provisioned before the team adopted IaC. A VPC that predates the current stack by years. These resources exist, they're in use, and recreating them from scratch is either impossible (stateful databases) or dangerous (anything currently serving traffic). The `import` block is how you bring them under management: you write a `unit` block describing the resource's desired configuration, add a matching `import` block with the resource's cloud provider ID, and on the next `ubx apply`, Pulumi reads the live resource's state, writes it into Pulumi's state file, and begins managing it going forward. No recreation. No downtime. No data loss.

## What you'll learn

* How `import` brings an existing cloud resource under ubx management
* How the `id` value maps to the cloud provider's resource identifier
* What happens at validate time vs apply time

***

## Why this matters

<Info>
  `ubx validate` only checks the `import` block's syntax — it does not contact AWS to verify the resource exists. The actual import (writing the resource into Pulumi state) happens on the first `ubx apply`, which requires AWS credentials and the resource to already exist in your account.
</Info>

***

## The source code

<CodeGroup>
  ```hcl main.iac theme={"theme":"css-variables"}
  # unit block describes the desired final state after import.
  # The attributes should match what the existing resource actually has.
  unit "aws_s3_bucket_v2" "assets" {
    bucket = "my-existing-bucket"
  }
  ```

  ```hcl imports.iac theme={"theme":"css-variables"}
  # import "type" "name" { id = "..." } adopts an existing resource.
  # type and name must exactly match the corresponding unit block.
  #
  # id is the cloud provider's resource identifier:
  #   S3 bucket:    the bucket name
  #   EC2 instance: "i-0123456789abcdef0"
  #   RDS instance: the DB instance identifier
  #   IAM role:     the role name
  #   VPC:          "vpc-0abc1234ef567890"
  import "aws_s3_bucket_v2" "assets" {
    id = "my-existing-bucket"
  }
  ```

  ```hcl outputs.iac theme={"theme":"css-variables"}
  output "bucket_name" {
    value = unit.aws_s3_bucket_v2.assets.bucket
  }
  ```

  ```hcl ubx.iac theme={"theme":"css-variables"}
  ubx {
    name    = "import-existing-resource"
    runtime = "typescript"
    stacks  = ["dev", "staging", "prod"]
  }

  backend "s3" {
    bucket = "my-ubx-state"
    region = "us-east-1"
    key    = "${stack}/import-existing-resource.tfstate"
  }
  ```
</CodeGroup>

***

## How it works

<Steps>
  <Step title="ubx validate checks syntax only">
    `ubx validate` confirms the `import` block's type and name match an existing `unit` block, and that the `id` field is present. It does not contact AWS or verify the resource exists. Validation passes even if the bucket doesn't exist yet.
  </Step>

  <Step title="ubx apply reads the live resource state">
    On the first apply after an `import` block is added, Pulumi calls the AWS API to read the resource's current configuration and writes it into the Pulumi state file. The resource is now tracked in state as if it had been created by Pulumi originally.
  </Step>

  <Step title="Subsequent applies manage the resource normally">
    After the first import apply, the `import` block can be removed — the resource is now in Pulumi state. Future `ubx apply` runs treat it like any other managed resource: diffs are computed, updates are applied if attributes change.
  </Step>
</Steps>

***

## What ubx generates

<CodeGroup>
  ```typescript index.ts theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  import * as pulumi from "@pulumi/pulumi";
  import * as aws from "@pulumi/aws";

  // The import option tells Pulumi to adopt the existing resource
  const assets = new aws.s3.BucketV2("assets", {
      bucket: "my-existing-bucket",
  }, {
      import: "my-existing-bucket",  // generated from the import block
  });

  export const bucketName = assets.bucket;
  ```

  ```python __main__.py theme={"theme":"css-variables"}
  # Generated by ubx — do not edit
  import pulumi
  import pulumi_aws as aws

  assets = aws.s3.BucketV2("assets",
      bucket="my-existing-bucket",
      opts=pulumi.ResourceOptions(import_="my-existing-bucket"),
  )

  pulumi.export("bucket_name", assets.bucket)
  ```

  ```go main.go theme={"theme":"css-variables"}
  // Generated by ubx — do not edit
  package main

  import (
      "github.com/pulumi/pulumi-aws/sdk/v6/go/aws/s3"
      "github.com/pulumi/pulumi/sdk/v3/go/pulumi"
  )

  func main() {
      pulumi.Run(func(ctx *pulumi.Context) error {
          assets, err := s3.NewBucketV2(ctx, "assets", &s3.BucketV2Args{
              Bucket: pulumi.String("my-existing-bucket"),
          }, pulumi.Import(pulumi.ID("my-existing-bucket")))
          if err != nil { return err }
          ctx.Export("bucketName", assets.Bucket)
          return nil
      })
  }
  ```
</CodeGroup>

***

## Common mistakes

<Warning>
  If the attributes in your `unit` block don't match the live resource's actual configuration, the first import apply will produce a diff and immediately try to update the resource to match your `.iac` declaration. Before importing, inspect the live resource's attributes and ensure your `unit` block reflects them accurately to avoid unintended updates on first apply.
</Warning>

<Tip>
  After the first `ubx apply` succeeds and the resource is in Pulumi state, remove the `import` block. Leaving it in place causes Pulumi to attempt re-import on every subsequent apply, which is a no-op but adds noise to the plan output.
</Tip>

***

## Run it

```bash theme={"theme":"css-variables"}
ubx validate              # syntax check only — does not contact AWS
ubx plan                  # requires AWS credentials; shows the import in the plan
ubx apply                 # performs the import — resource must exist in AWS
# After successful apply: remove the import block
```

***

## What you learned

<Check>`import` brings an existing cloud resource under ubx management without recreating it</Check>
<Check>`ubx validate` only checks syntax — the actual import requires AWS credentials and the resource to exist</Check>
<Check>Remove the `import` block after the first successful apply — the resource is now in Pulumi state</Check>

***

## Next steps

<CardGroup cols={2}>
  <Card title="moved block" href="/v1/tutorials/32-moved-block-resource-rename">
    Rename a resource in state without destroying it
  </Card>

  <Card title="import block reference" href="/v1/language/import">
    Full import block syntax and provider ID formats
  </Card>
</CardGroup>

***

<Info>
  Full runnable example: [github.com/ubiquex/ubx-examples/31-import-existing-resource](https://github.com/ubiquex/ubx-examples/tree/main/31-import-existing-resource)
</Info>
