content/v1.20/guides/import-existing-resources.md
If you have resources that are already provisioned in a Provider,
you can import them as managed resources and let Crossplane manage them.
A managed resource's [managementPolicies]({{<ref "../concepts/managed-resources#managementpolicies">}})
field enables importing external resources into Crossplane.
Crossplane can import resources either [manually]({{<ref "#import-resources-manually">}}) or [automatically]({{<ref "#import-resources-automatically">}}).
Crossplane can discover and import existing Provider resources by matching the
crossplane.io/external-name annotation in a managed resource.
To import an existing external resource in a Provider, create a new managed
resource with the crossplane.io/external-name annotation. Set the annotation
value to the name of the resource in the Provider.
For example, to import an existing GCP Network named {{<hover label="annotation" line="5">}}my-existing-network{{</hover>}}, create a new managed resource and use the {{<hover label="annotation" line="5">}}my-existing-network{{</hover>}} in the annotation.
apiVersion: compute.gcp.crossplane.io/v1beta1
kind: Network
metadata:
annotations:
crossplane.io/external-name: my-existing-network
The {{<hover label="name" line="5">}}metadata.name{{</hover>}} field can be anything you want. For example, {{<hover label="name" line="5">}}imported-network{{</hover>}}.
{{< hint "note" >}} This name is the name of the Kubernetes object. It's not related to the resource name inside the Provider. {{< /hint >}}
apiVersion: compute.gcp.crossplane.io/v1beta1
kind: Network
metadata:
name: imported-network
annotations:
crossplane.io/external-name: my-existing-network
Leave the {{<hover label="fp" line="8">}}spec.forProvider{{</hover>}} field empty. Crossplane imports the settings and automatically applies them to the managed resource.
{{< hint "important" >}}
If the managed resource has required fields in the
{{<hover label="fp" line="8">}}spec.forProvider{{</hover>}} you must add it to
the forProvider field.
The values of those fields must match what's inside the Provider or Crossplane overwrites the existing values. {{< /hint >}}
apiVersion: compute.gcp.crossplane.io/v1beta1
kind: Network
metadata:
name: imported-network
annotations:
crossplane.io/external-name: my-existing-network
spec:
forProvider: {}
Crossplane now controls and manages this imported resource. Any changes to the
managed resource spec changes the external resource.
Automatically import external resources with an Observe [management policy]({{<ref "../concepts/managed-resources#managementpolicies">}}).
Crossplane imports observe only resources but never changes or deletes the resources.
{{<hint "important" >}}
The managed resource managementPolicies option is a beta feature.
The Provider determines support for management policies. Refer to the Provider's documentation to see if the Provider supports management policies. {{< /hint >}}
<!-- vale off -->Create a new managed resource matching the {{<hover label="oo-policy" line="1">}}apiVersion{{</hover>}} and {{<hover label="oo-policy" line="2">}}kind{{</hover>}} of the resource to import and add {{<hover label="oo-policy" line="4">}}managementPolicies: ["Observe"]{{</hover>}} to the {{<hover label="oo-policy" line="3">}}spec{{</hover>}}
For example, to import a GCP SQL DatabaseInstance, create a new resource with the {{<hover label="oo-policy" line="4">}}managementPolicies: ["Observe"]{{</hover>}} set.
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
spec:
managementPolicies: ["Observe"]
Add the {{<hover label="oo-ex-name" line="5">}}crossplane.io/external-name{{</hover>}} annotation for the resource. This name must match the name inside the Provider.
For example, for a GCP database named {{<hover label="oo-ex-name" line="5">}}my-external-database{{</hover>}}, apply the {{<hover label="oo-ex-name" line="5">}}crossplane.io/external-name{{</hover>}} annotation with the value {{<hover label="oo-ex-name" line="5">}}my-external-database{{</hover>}}.
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["Observe"]
Create a {{<hover label="oo-name" line="4">}}name{{</hover>}} to use for the Kubernetes object.
For example, name the Kubernetes object {{<hover label="oo-name" line="4">}}my-imported-database{{</hover>}}.
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
name: my-imported-database
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["Observe"]
If more than one resource inside the Provider shares the same name, identify the specific resource with a unique {{<hover line="9" label="oo-region">}}spec.forProvider{{</hover>}} field.
For example, only import the GCP SQL database in the {{<hover line="10" label="oo-region">}}us-central1{{</hover>}} region.
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
name: my-imported-database
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["Observe"]
forProvider:
region: "us-central1"
Apply the new managed resource. Crossplane syncs the status of the external resource in the cloud with the newly created managed resource.
Crossplane discovers the managed resource and populates the {{<hover label="ooPopulated" line="12">}}status.atProvider{{</hover>}} fields with the values from the external resource.
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
name: my-imported-database
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["Observe"]
forProvider:
region: us-central1
status:
atProvider:
connectionName: crossplane-playground:us-central1:my-external-database
databaseVersion: POSTGRES_14
deletionProtection: true
firstIpAddress: 35.184.74.79
id: my-external-database
publicIpAddress: 35.184.74.79
region: us-central1
# Removed for brevity
settings:
- activationPolicy: ALWAYS
availabilityType: REGIONAL
diskSize: 100
# Removed for brevity
pricingPlan: PER_USE
tier: db-custom-4-26624
version: 4
conditions:
- lastTransitionTime: "2023-02-22T07:16:51Z"
reason: Available
status: "True"
type: Ready
- lastTransitionTime: "2023-02-22T07:16:51Z"
reason: ReconcileSuccess
status: "True"
type: Synced
Crossplane can take active control of observe only imported resources by
changing the managementPolicies after import.
Change the {{<hover label="fc" line="8">}}managementPolicies{{</hover>}} field of the managed resource to {{<hover label="fc" line="8">}}["*"]{{</hover>}}.
Copy any required parameter values from {{<hover label="fc" line="16">}}status.atProvider{{</hover>}} and provide them in {{<hover label="fc" line="9">}}spec.forProvider{{</hover>}}.
{{< hint "tip" >}}
Manually copy the important status.atProvider values to spec.forProvider.
{{< /hint >}}
apiVersion: sql.gcp.upbound.io/v1beta1
kind: DatabaseInstance
metadata:
name: my-imported-database
annotations:
crossplane.io/external-name: my-external-database
spec:
managementPolicies: ["*"]
forProvider:
databaseVersion: POSTGRES_14
region: us-central1
settings:
- diskSize: 100
tier: db-custom-4-26624
status:
atProvider:
databaseVersion: POSTGRES_14
region: us-central1
# Removed for brevity
settings:
- diskSize: 100
tier: db-custom-4-26624
# Removed for brevity
conditions:
- lastTransitionTime: "2023-02-22T07:16:51Z"
reason: Available
status: "True"
type: Ready
- lastTransitionTime: "2023-02-22T11:16:45Z"
reason: ReconcileSuccess
status: "True"
type: Synced
Crossplane now fully manages the imported resource. Crossplane applies any changes to the managed resource in the Provider's external resource.