Skip to content

Commit

Permalink
enhancement(snapshot): added support for cross region snapshot copy (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
ujjwal-ibm authored Jul 20, 2023
1 parent 201ffe7 commit 0690a06
Show file tree
Hide file tree
Showing 10 changed files with 956 additions and 67 deletions.
14 changes: 13 additions & 1 deletion examples/ibm-is-ng/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,18 @@ data "ibm_is_share" "is_share" {
data "ibm_is_shares" "is_shares" {
}

// snapshot cross region

provider "ibm" {
alias = "eu-de"
region = "eu-de"
}

resource "ibm_is_snapshot" "b_snapshot_copy" {
provider = ibm.eu-de
name = "my-snapshot-boot-copy"
source_snapshot_crn = ibm_is_snapshot.b_snapshot.crn
}

// image deprecate and obsolete

Expand All @@ -1282,4 +1294,4 @@ resource "ibm_is_image_deprecate" "example" {

resource "ibm_is_image_obsolete" "example" {
image = ibm_is_image.image1.id
}
}
11 changes: 9 additions & 2 deletions ibm/acctest/acctest.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ var VSIUnattachedBootVolumeID string
var VSIDataVolumeID string
var ISRouteDestination string
var ISRouteNextHop string
var ISSnapshotCRN string
var WorkspaceID string
var TemplateID string
var ActionID string
Expand Down Expand Up @@ -594,8 +595,8 @@ func init() {
IsImage = os.Getenv("IS_IMAGE")
if IsImage == "" {
//IsImage = "fc538f61-7dd6-4408-978c-c6b85b69fe76" // for classic infrastructure
IsImage = "r006-13938c0a-89e4-4370-b59b-55cd1402562d" // for next gen infrastructure
fmt.Println("[INFO] Set the environment variable IS_IMAGE for testing ibm_is_instance, ibm_is_floating_ip else it is set to default value 'r006-ed3f775f-ad7e-4e37-ae62-7199b4988b00'")
IsImage = "r006-907911a7-0ffe-467e-8821-3cc9a0d82a39" // for next gen infrastructure ibm-centos-7-9-minimal-amd64-10 image
fmt.Println("[INFO] Set the environment variable IS_IMAGE for testing ibm_is_instance, ibm_is_floating_ip else it is set to default value 'r006-907911a7-0ffe-467e-8821-3cc9a0d82a39'")
}

IsWinImage = os.Getenv("IS_WIN_IMAGE")
Expand Down Expand Up @@ -765,6 +766,12 @@ func init() {
fmt.Println("[INFO] Set the environment variable SL_ROUTE_NEXTHOP else it is set to default value '10.0.0.4'")
}

ISSnapshotCRN = os.Getenv("IS_SNAPSHOT_CRN")
if ISSnapshotCRN == "" {
ISSnapshotCRN = "crn:v1:bluemix:public:is:ca-tor:a/xxxxxxxx::snapshot:xxxx-xxxxc-xxx-xxxx-xxxx-xxxxxxxxxx"
fmt.Println("[INFO] Set the environment variable ISSnapshotCRN for ibm_is_snapshot resource else it is set to default value 'crn:v1:bluemix:public:is:ca-tor:a/xxxxxxxx::snapshot:xxxx-xxxxc-xxx-xxxx-xxxx-xxxxxxxxxx'")
}

IcdDbRegion = os.Getenv("ICD_DB_REGION")
if IcdDbRegion == "" {
IcdDbRegion = "eu-gb"
Expand Down
210 changes: 206 additions & 4 deletions ibm/service/vpc/data_source_ibm_is_snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,74 @@ func DataSourceSnapshot() *schema.Resource {
ValidateFunc: validate.InvokeDataSourceValidator("ibm_is_snapshot", "identifier"),
},

isSnapshotCopies: {
Type: schema.TypeList,
Computed: true,
Description: "The copies of this snapshot in other regions.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"crn": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The CRN for the copied snapshot.",
},
"deleted": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Description: "If present, this property indicates the referenced resource has been deleted, and provides some supplementary information.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"more_info": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "Link to documentation about deleted resources.",
},
},
},
},
"href": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The URL for the copied snapshot.",
},
"id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The unique identifier for the copied snapshot.",
},
"name": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The name for the copied snapshot. The name is unique across all snapshots in the copied snapshot's native region.",
},
"remote": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Description: "If present, this property indicates the referenced resource is remote to this region,and identifies the native region.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"href": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The URL for this region.",
},
"name": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The globally unique name for this region.",
},
},
},
},
"resource_type": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The resource type.",
},
},
},
},

isSnapshotName: {
Type: schema.TypeString,
Optional: true,
Expand All @@ -45,6 +113,75 @@ func DataSourceSnapshot() *schema.Resource {
Computed: true,
Description: "Snapshot source volume id",
},
isSnapshotSourceSnapshot: {
Type: schema.TypeList,
Optional: true,
Computed: true,
Description: "If present, the source snapshot this snapshot was created from.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"crn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
Computed: true,
Description: "The CRN of the source snapshot.",
},
"deleted": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Description: "If present, this property indicates the referenced resource has been deleted, and providessome supplementary information.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"more_info": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "Link to documentation about deleted resources.",
},
},
},
},
"href": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The URL for the source snapshot.",
},
"id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The unique identifier for the source snapshot.",
},
"name": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The name for the source snapshot. The name is unique across all snapshots in the source snapshot's native region.",
},
"remote": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Description: "If present, this property indicates the referenced resource is remote to this region,and identifies the native region.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"href": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The URL for this region.",
},
"name": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The globally unique name for this region.",
},
},
},
},
"resource_type": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The resource type.",
},
},
},
},
isSnapshotSourceImage: {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -250,9 +387,41 @@ func snapshotGetByNameOrID(d *schema.ResourceData, meta interface{}, name, id st
d.Set(isSnapshotLCState, *snapshot.LifecycleState)
d.Set(isSnapshotResourceType, *snapshot.ResourceType)
d.Set(isSnapshotBootable, *snapshot.Bootable)

// source snapshot
sourceSnapshotList := []map[string]interface{}{}
if snapshot.SourceSnapshot != nil {
sourceSnapshot := map[string]interface{}{}
sourceSnapshot["href"] = snapshot.SourceSnapshot.Href
if snapshot.SourceSnapshot.Deleted != nil {
snapshotSourceSnapshotDeletedMap := map[string]interface{}{}
snapshotSourceSnapshotDeletedMap["more_info"] = snapshot.SourceSnapshot.Deleted.MoreInfo
sourceSnapshot["deleted"] = []map[string]interface{}{snapshotSourceSnapshotDeletedMap}
}
sourceSnapshot["id"] = snapshot.SourceSnapshot.ID
sourceSnapshot["name"] = snapshot.SourceSnapshot.Name

sourceSnapshot["resource_type"] = snapshot.SourceSnapshot.ResourceType
sourceSnapshotList = append(sourceSnapshotList, sourceSnapshot)
}
d.Set(isSnapshotSourceSnapshot, sourceSnapshotList)

// snapshot copies
snapshotCopies := []map[string]interface{}{}
if snapshot.Copies != nil {
for _, copiesItem := range snapshot.Copies {
copiesMap, err := dataSourceIBMIsSnapshotsSnapshotCopiesItemToMap(&copiesItem)
if err != nil {
return fmt.Errorf("[ERROR] Error fetching snapshot copies: %s", err)
}
snapshotCopies = append(snapshotCopies, copiesMap)
}
}
d.Set(isSnapshotCopies, snapshotCopies)

if snapshot.UserTags != nil {
if err = d.Set(isSnapshotUserTags, snapshot.UserTags); err != nil {
return fmt.Errorf("Error setting user tags: %s", err)
return fmt.Errorf("[ERROR] Error setting user tags: %s", err)
}
}
if snapshot.ResourceGroup != nil && snapshot.ResourceGroup.ID != nil {
Expand Down Expand Up @@ -297,7 +466,7 @@ func snapshotGetByNameOrID(d *schema.ResourceData, meta interface{}, name, id st
accesstags, err := flex.GetGlobalTagsUsingCRN(meta, *snapshot.CRN, "", isAccessTagType)
if err != nil {
log.Printf(
"Error on get of resource snapshot (%s) access tags: %s", d.Id(), err)
"[ERROR] Error on get of resource snapshot (%s) access tags: %s", d.Id(), err)
}
d.Set(isSnapshotAccessTags, accesstags)
return nil
Expand Down Expand Up @@ -325,12 +494,45 @@ func snapshotGetByNameOrID(d *schema.ResourceData, meta interface{}, name, id st
d.Set(isSnapshotLCState, *snapshot.LifecycleState)
d.Set(isSnapshotResourceType, *snapshot.ResourceType)
d.Set(isSnapshotBootable, *snapshot.Bootable)

if snapshot.EncryptionKey != nil && snapshot.EncryptionKey.CRN != nil {
d.Set(isSnapshotEncryptionKey, *snapshot.EncryptionKey.CRN)
}
// source snapshot
sourceSnapshotList := []map[string]interface{}{}
if snapshot.SourceSnapshot != nil {
sourceSnapshot := map[string]interface{}{}
sourceSnapshot["href"] = snapshot.SourceSnapshot.Href
sourceSnapshot["crn"] = snapshot.SourceSnapshot.CRN
if snapshot.SourceSnapshot.Deleted != nil {
snapshotSourceSnapshotDeletedMap := map[string]interface{}{}
snapshotSourceSnapshotDeletedMap["more_info"] = snapshot.SourceSnapshot.Deleted.MoreInfo
sourceSnapshot["deleted"] = []map[string]interface{}{snapshotSourceSnapshotDeletedMap}
}
sourceSnapshot["id"] = snapshot.SourceSnapshot.ID
sourceSnapshot["name"] = snapshot.SourceSnapshot.Name
sourceSnapshot["resource_type"] = snapshot.SourceSnapshot.ResourceType
sourceSnapshotList = append(sourceSnapshotList, sourceSnapshot)
}
// snapshot copies
snapshotCopies := []map[string]interface{}{}
if snapshot.Copies != nil {
for _, copiesItem := range snapshot.Copies {
copiesMap, err := dataSourceIBMIsSnapshotsSnapshotCopiesItemToMap(&copiesItem)
if err != nil {
return fmt.Errorf("[ERROR] Error fetching snapshot copies: %s", err)
}
snapshotCopies = append(snapshotCopies, copiesMap)
}
}
d.Set(isSnapshotCopies, snapshotCopies)

if snapshot.CapturedAt != nil {
d.Set(isSnapshotCapturedAt, (*snapshot.CapturedAt).String())
}
if snapshot.UserTags != nil {
if err = d.Set(isSnapshotUserTags, snapshot.UserTags); err != nil {
return fmt.Errorf("Error setting user tags: %s", err)
return fmt.Errorf("[ERROR] Error setting user tags: %s", err)
}
}
if snapshot.ResourceGroup != nil && snapshot.ResourceGroup.ID != nil {
Expand Down Expand Up @@ -374,7 +576,7 @@ func snapshotGetByNameOrID(d *schema.ResourceData, meta interface{}, name, id st
accesstags, err := flex.GetGlobalTagsUsingCRN(meta, *snapshot.CRN, "", isAccessTagType)
if err != nil {
log.Printf(
"Error on get of resource snapshot (%s) access tags: %s", d.Id(), err)
"[ERROR] Error on get of resource snapshot (%s) access tags: %s", d.Id(), err)
}
d.Set(isSnapshotAccessTags, accesstags)
return nil
Expand Down
Loading

0 comments on commit 0690a06

Please sign in to comment.