Resource Imports
Relevant source files
The following files were used as context for generating this wiki page:
- CONTRIBUTING.md
- README.md
- developer-docs/architecture/import.md
- developer-docs/build.md
- developer-docs/index.md
- pkg/cmd/pulumi/operations/import.go
- pkg/cmd/pulumi/packagecmd/package_info.go
- pkg/cmd/pulumi/packagecmd/package_info_test.go
- pkg/codegen/go/gen.go
- pkg/codegen/python/gen.go
- pkg/codegen/testing/test/testdata/different-package-name-conflict/schema.json
- pkg/codegen/testing/test/testdata/external-go-import-aliases/schema.json
- pkg/codegen/testing/test/testdata/other-owned/schema.json
- sdk/nodejs/tests/automation/localWorkspace.spec.ts
- sdk/nodejs/tests/runtime/langhost/run.spec.ts
- tests/testdata/codegen/different-package-name-conflict/schema.json
- tests/testdata/codegen/external-go-import-aliases/schema.json
- tests/testdata/codegen/other-owned/schema.json
Resource importing is a critical feature in Pulumi that allows users to bring existing cloud resources, which were not previously managed by Pulumi, under its management. This is essential for migrating from manual resource management, other IaC tools, or even between different Pulumi stacks. The core principle is to add the resource's state to the destination stack's statefile and then generate the corresponding code definition to be added to the user's Pulumi program.
Pulumi provides two primary methods for importing resources: the pulumi import command for bulk and single resource imports, and the import resource option for an in-code approach. Both methods ensure that at the point of a successful import, the Pulumi program's definition for the resource accurately describes its current state, preventing accidental modifications or deletions.
Sources: developer-docs/architecture/import.md:3-13
pulumi import Command
The pulumi import command is the primary mechanism for bringing existing resources into a Pulumi stack. It can import a single resource specified via command-line arguments or multiple resources from a JSON file. After importing the resources into the state, it also generates the necessary code definitions in the project's language, which the user can then add to their program.
Sources: pkg/cmd/pulumi/operations/import.go:683-731, developer-docs/architecture/import.md:61-66
Command-Line Interface
The command is defined in NewImportCmd and supports a variety of flags to control its behavior. It can be used for a single resource or for bulk operations via a file.
Usage:
- Single Resource:
pulumi import [type] [name] [id] - Bulk from file:
pulumi import --file import.json - From converter:
pulumi import --from <converter-name>
Sources: pkg/cmd/pulumi/operations/import.go:683-731
The following table details the flags available for the pulumi import command.
| Flag | Shorthand | Type | Description |
|---|---|---|---|
--parent | string | The name and URN of the parent resource (name=urn). | |
--provider | string | The name and URN of the provider to use (name=urn). | |
--properties | string slice | Property names to use for the import. | |
--file | -f | string | Path to a JSON file containing resources to import. |
--out | -o | string | Path to a file to save the generated resource code. |
--generate-code | bool | If true (default), generates resource declaration code. | |
--protect | bool | If true (default), resources are imported with deletion protection. | |
--from | string | Invokes a converter to import resources from another source. | |
--generate-resources | string | When used with --from, writes a JSON import file to the specified path. | |
--stack | -s | string | The name of the stack to operate on. |
--preview-only | bool | Shows a preview of the import without performing it. | |
--skip-preview | bool | Skips the preview and performs the import directly. | |
--yes | -y | bool | Automatically approves the import after the preview. |
--diff | bool | Displays the operation as a rich diff. | |
--json | -j | bool | Serializes output as JSON. |
Sources: pkg/cmd/pulumi/operations/import.go:1071-1142
Import File Schema
For bulk imports, a JSON file is used. The structure of this file is defined by the importFile and importSpec Go structs.
// pkg/cmd/pulumi/operations/import.go:167-182
type importSpec struct {
Type tokens.Type `json:"type"`
Name string `json:"name"`
ID resource.ID `json:"id,omitempty"`
Parent string `json:"parent,omitempty"`
Provider string `json:"provider,omitempty"`
Version string `json:"version,omitempty"`
PluginDownloadURL string `json:"pluginDownloadUrl,omitempty"`
Properties []string `json:"properties,omitempty"`
Component bool `json:"component,omitempty"`
Remote bool `json:"remote,omitempty"`
LogicalName string `json:"logicalName,omitempty"`
}
type importFile struct {
NameTable map[string]resource.URN `json:"nameTable,omitempty"`
Resources []importSpec `json:"resources,omitempty"`
}
The importFile structure contains a nameTable for mapping logical names to URNs (for parents and providers) and a list of resources to import.
| Field | Type | Description |
|---|---|---|
type | string | The Pulumi type token of the resource (e.g., aws:s3/bucket:Bucket). |
name | string | The logical name for the resource in the Pulumi program. |
id | string | The physical ID of the resource in the cloud provider. |
parent | string | The logical name of the parent resource, as defined in nameTable. |
provider | string | The logical name of the provider, as defined in nameTable. |
version | string | The specific provider version to use for the import. |
component | bool | true if the resource is a Pulumi Component Resource. |
remote | bool | true if the resource is a remote Component Resource. |
logicalName | string | The Pulumi name of the resource (first argument to new Resource). Defaults to name. |
Sources: pkg/cmd/pulumi/operations/import.go:167-186
Execution Flow
The pulumi import command follows a series of steps to import resources and generate code.
This diagram illustrates the high-level flow of the pulumi import command.
- Input Parsing: The command first determines the source of the resources to import: inline arguments, a file (
--file), or a converter (--from). This information is consolidated into animportFilestruct. - Import File Validation: The
parseImportFilefunction validates theimportFiledata. It checks for uniqueness of resource names, resolves parent and provider references, and generates a URN for each resource. - Backend Import: The
backend.ImportStackfunction is called with the list ofdeploy.Importobjects. The engine communicates with the appropriate resource provider to read the existing resource's state using its ID. The resource's state is then saved into the stack's state file. - Code Generation: If
--generate-codeis true,generateImportedDefinitionsis called. It uses the newly updated deployment state to generate language-specific code. This involves usingimporter.GenerateLanguageDefinitions, which creates a PCL (Pulumi Control Language) program that is then passed to the project's language plugin (e.g.,goorpython) to generate the final code.
Sources: pkg/cmd/pulumi/operations/import.go:733-1068, developer-docs/architecture/import.md:61-86
Parsing and URN Generation
The parseImportFile function is responsible for translating the user-provided importFile into a list of deploy.Import objects that the engine can process.
This diagram shows the logic for parsing the import file and resolving dependencies.
- Uniqueness Checks: It first checks for duplicate resource names and ambiguous references.
- URN Generation: It iteratively resolves dependencies. A resource's URN depends on its parent's URN. The process loops until all parent URNs are resolved, allowing child URNs to be constructed. A URN is created using
resource.NewURN(stack, project, parentType, resourceType, logicalName). - Name Table: A
nameTableis constructed to map the generated URNs back to the logical names used in the import file, which is crucial for code generation to correctly reference parents and providers.
Sources: pkg/cmd/pulumi/operations/import.go:230-415
Code Generation
After a successful import into the state, Pulumi can generate the corresponding resource definitions for the user's program.
- The
generateImportedDefinitionsfunction orchestrates this process. - It retrieves the latest deployment snapshot to get the full state of the newly imported resources.
- It uses a
schema.Loaderto fetch schemas for the resource types. importer.GenerateLanguageDefinitionsconverts the resource states into a PCL (Pulumi Control Language) program.- This PCL program is then passed to the appropriate language plugin (e.g., Go, Python, TypeScript) via its
GenerateProgrammethod, which produces the final source code.
This process ensures that the generated code accurately reflects the imported resource's state, minimizing any diff on the next pulumi up.
Sources: pkg/cmd/pulumi/operations/import.go:520-580, pkg/codegen/go/gen.go:3013-3026, pkg/codegen/python/gen.go:1218-1231
import Resource Option
An alternative to the pulumi import command is the import resource option, which is specified directly in the Pulumi program code. When this option is set on a resource, Pulumi attempts to adopt an existing resource with the given ID instead of creating a new one.
// sdk/nodejs/tests/runtime/langhost/run.spec.ts:803-826
const myResource = new MyResource("testResource1", {}, { import: "testID" });
The behavior depends on the resource's state:
- Resource does not exist in state: The resource with the specified ID is imported.
- Resource exists with same ID: The resource is treated like any other managed resource.
- Resource exists with different ID: The existing resource in the state is deleted and replaced by importing the new one.
A key requirement for this method is the "no-diffs" principle. The state of the resource described in the program must exactly match the actual state of the resource being imported. If any differences are detected, the import will fail.
Sources: developer-docs/architecture/import.md:15-40, sdk/nodejs/tests/runtime/langhost/run.spec.ts:803-826
Import Operation Sequence (import option)
This sequence diagram shows the steps taken by the engine when using the import resource option.
Summary
Resource importing is a powerful capability for bringing existing infrastructure under Pulumi's management. The pulumi import command offers a flexible and robust solution for both single and bulk resource imports, complete with code generation to streamline the adoption process. For simpler, in-code scenarios, the import resource option provides a direct way to adopt a resource, though it requires the program to precisely match the resource's actual state. Both methods are designed to ensure a safe and predictable transition to managing infrastructure with Pulumi.
Sources: developer-docs/architecture/import.md, pkg/cmd/pulumi/operations/import.go