Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature(share-crr): Share cross region replication #4995

Merged
merged 18 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion examples/ibm-is-ng/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -1408,7 +1408,14 @@ resource "ibm_is_image_obsolete" "example" {
image = ibm_is_image.image1.id
}


resource "ibm_is_share" "share" {
zone = "us-east-1"
source_share_crn = "crn:v1:staging:public:is:us-south-1:a/efe5afc483594adaa8325e2b4d1290df::share:r134-d8c8821c-a227-451d-a9ed-0c0cd2358829"
encryption_key = "crn:v1:staging:public:kms:us-south:a/efe5afc483594adaa8325e2b4d1290df:1be45161-6dae-44ca-b248-837f98004057:key:3dd21cc5-cc20-4f7c-bc62-8ec9a8a3d1bd"
replication_cron_spec = "5 * * * *"
name = "tfp-temp-crr"
profile = "dp2"
}
//snapshot consistency group

resource "ibm_is_snapshot_consistency_group" "is_snapshot_consistency_group_instance" {
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ require (
github.com/IBM/schematics-go-sdk v0.2.2
github.com/IBM/secrets-manager-go-sdk/v2 v2.0.2
github.com/IBM/vpc-beta-go-sdk v0.6.0
github.com/IBM/vpc-go-sdk v0.45.0
github.com/IBM/vpc-go-sdk v0.46.0
github.com/ScaleFT/sshkeys v0.0.0-20200327173127-6142f742bca5
github.com/akamai/AkamaiOPEN-edgegrid-golang v1.2.2
github.com/akamai/AkamaiOPEN-edgegrid-golang/v5 v5.0.0
Expand Down Expand Up @@ -241,4 +241,4 @@ exclude (
github.com/kubernetes-incubator/external-storage v0.20.4-openstorage-rc2
k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
k8s.io/client-go v12.0.0+incompatible
)
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ github.com/IBM/vpc-go-sdk v0.43.0 h1:uy/qWIqETCXraUG2cq5sjScr6pZ79ZteY1v5iLUVQ3Q
github.com/IBM/vpc-go-sdk v0.43.0/go.mod h1:kRz9tqPvpHoA/qGrC/qVjTbi4ICuTChpG76L89liGL4=
github.com/IBM/vpc-go-sdk v0.45.0 h1:RFbUZH5vBRGAEW5+jRzbDlxB+a+GvG9EBhyYO52Tvrs=
github.com/IBM/vpc-go-sdk v0.45.0/go.mod h1:4Hs5d/aClmsxAzwDQkwG+ri0vW2ykPJdpM6hDLRwKcA=
github.com/IBM/vpc-go-sdk v0.46.0 h1:OwXH3oaYgYmzt559n77AteSpNsW4H1PoeHcR4EOolzk=
github.com/IBM/vpc-go-sdk v0.46.0/go.mod h1:4Hs5d/aClmsxAzwDQkwG+ri0vW2ykPJdpM6hDLRwKcA=
github.com/Jeffail/gabs v1.1.1 h1:V0uzR08Hj22EX8+8QMhyI9sX2hwRu+/RJhJUmnwda/E=
github.com/Jeffail/gabs v1.1.1/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
github.com/Logicalis/asn1 v0.0.0-20190312173541-d60463189a56 h1:vuquMR410psHNax14XKNWa0Ae/kYgWJcXi0IFuX60N0=
Expand Down
14 changes: 14 additions & 0 deletions ibm/acctest/acctest.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ var (
DedicatedHostGroupFamily string
DedicatedHostGroupClass string
ShareProfileName string
SourceShareCRN string
ShareEncryptionKey string
VNIId string
VolumeProfileName string
VSIUnattachedBootVolumeID string
Expand Down Expand Up @@ -848,6 +850,18 @@ func init() {
fmt.Println("[INFO] Set the environment variable IS_SHARE_PROFILE for testing ibm_is_instance resource else it is set to default value 'tier-3iops'")
}

SourceShareCRN = os.Getenv("IS_SOURCE_SHARE_CRN")
if SourceShareCRN == "" {
SourceShareCRN = "crn:v1:staging:public:is:us-east-1:a/efe5afc483594adaa8325e2b4d1290df::share:r142-a106f162-86e4-4d7f-be75-193cc55a93e9" // for next gen infrastructure
fmt.Println("[INFO] Set the environment variable IS_SHARE_PROFILE for testing ibm_is_instance resource else it is set to default value")
}

ShareEncryptionKey = os.Getenv("IS_SHARE_ENCRYPTION_KEY")
if ShareEncryptionKey == "" {
ShareEncryptionKey = "crn:v1:staging:public:kms:us-south:a/efe5afc483594adaa8325e2b4d1290df:1be45161-6dae-44ca-b248-837f98004057:key:3dd21cc5-cc20-4f7c-bc62-8ec9a8a3d1bd" // for next gen infrastructure
fmt.Println("[INFO] Set the environment variable IS_SHARE_PROFILE for testing ibm_is_instance resource else it is set to default value")
}

VolumeProfileName = os.Getenv("IS_VOLUME_PROFILE")
if VolumeProfileName == "" {
VolumeProfileName = "general-purpose"
Expand Down
36 changes: 35 additions & 1 deletion ibm/service/vpc/data_source_ibm_is_share.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,30 @@ func DataSourceIbmIsShare() *schema.Resource {
Computed: true,
Description: "The maximum input/output operation performance bandwidth per second for the file share.",
},
"latest_sync": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Description: "Information about the latest synchronization for this file share.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"completed_at": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The completed date and time of last synchronization between the replica share and its source.",
},
"data_transferred": &schema.Schema{
Type: schema.TypeInt,
Computed: true,
Description: "The data transferred (in bytes) in the last synchronization between the replica and its source.",
},
"started_at": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The start date and time of last synchronization between the replica share and its source.",
},
},
},
},
"latest_job": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -410,7 +434,17 @@ func dataSourceIbmIsShareRead(context context.Context, d *schema.ResourceData, m
if err = d.Set("iops", share.Iops); err != nil {
return diag.FromErr(fmt.Errorf("Error setting iops: %s", err))
}

latest_syncs := []map[string]interface{}{}
if share.LatestSync != nil {
latest_sync := make(map[string]interface{})
latest_sync["completed_at"] = flex.DateTimeToString(share.LatestSync.CompletedAt)
if share.LatestSync.DataTransferred != nil {
latest_sync["data_transferred"] = *share.LatestSync.DataTransferred
}
latest_sync["started_at"] = flex.DateTimeToString(share.LatestSync.CompletedAt)
latest_syncs = append(latest_syncs, latest_sync)
}
d.Set("latest_sync", latest_syncs)
if share.LatestJob != nil {
err = d.Set("latest_job", dataSourceShareFlattenLatestJob(*share.LatestJob))
if err != nil {
Expand Down
35 changes: 35 additions & 0 deletions ibm/service/vpc/data_source_ibm_is_shares.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,30 @@ func DataSourceIbmIsShares() *schema.Resource {
Computed: true,
Description: "The maximum input/output operation performance bandwidth per second for the file share.",
},
"latest_sync": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Description: "Information about the latest synchronization for this file share.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"completed_at": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The completed date and time of last synchronization between the replica share and its source.",
},
"data_transferred": &schema.Schema{
Type: schema.TypeInt,
Computed: true,
Description: "The data transferred (in bytes) in the last synchronization between the replica and its source.",
},
"started_at": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The start date and time of last synchronization between the replica share and its source.",
},
},
},
},
"latest_job": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -455,6 +479,17 @@ func dataSourceShareCollectionSharesToMap(meta interface{}, sharesItem vpcv1.Sha
if sharesItem.Iops != nil {
sharesMap["iops"] = sharesItem.Iops
}
latest_syncs := []map[string]interface{}{}
if sharesItem.LatestSync != nil {
latest_sync := make(map[string]interface{})
latest_sync["completed_at"] = flex.DateTimeToString(sharesItem.LatestSync.CompletedAt)
if sharesItem.LatestSync.DataTransferred != nil {
latest_sync["data_transferred"] = *sharesItem.LatestSync.DataTransferred
}
latest_sync["started_at"] = flex.DateTimeToString(sharesItem.LatestSync.CompletedAt)
latest_syncs = append(latest_syncs, latest_sync)
}
sharesMap["latest_sync"] = latest_syncs
if sharesItem.LifecycleState != nil {
sharesMap["lifecycle_state"] = sharesItem.LifecycleState
}
Expand Down
89 changes: 69 additions & 20 deletions ibm/service/vpc/resource_ibm_is_share.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,11 @@ func ResourceIbmIsShare() *schema.Resource {

Schema: map[string]*schema.Schema{
"encryption_key": {
Type: schema.TypeString,
Optional: true,
RequiredWith: []string{"size"},
ForceNew: true,
Computed: true,
Description: "The CRN of the key to use for encrypting this file share.If no encryption key is provided, the share will not be encrypted.",
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
Description: "The CRN of the key to use for encrypting this file share.If no encryption key is provided, the share will not be encrypted.",
},
"initial_owner": {
Type: schema.TypeList,
Expand Down Expand Up @@ -105,8 +104,8 @@ func ResourceIbmIsShare() *schema.Resource {
Type: schema.TypeInt,
Optional: true,
Computed: true,
ExactlyOneOf: []string{"size", "source_share"},
ConflictsWith: []string{"replication_cron_spec", "source_share"},
ExactlyOneOf: []string{"size", "source_share", "source_share_crn"},
ConflictsWith: []string{"replication_cron_spec", "source_share", "source_share_crn"},
ValidateFunc: validate.InvokeValidator("ibm_is_share", "size"),
Description: "The size of the file share rounded up to the next gigabyte.",
},
Expand Down Expand Up @@ -511,16 +510,25 @@ func ResourceIbmIsShare() *schema.Resource {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ConflictsWith: []string{"replica_share", "size"},
Computed: true,
ConflictsWith: []string{"replica_share", "size", "source_share_crn"},
RequiredWith: []string{"replication_cron_spec"},
Description: "The ID of the source file share for this replica file share. The specified file share must not already have a replica, and must not be a replica.",
},
"source_share_crn": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ConflictsWith: []string{"replica_share", "size", "source_share"},
RequiredWith: []string{"replication_cron_spec"},
Description: "The CRN of the source file share for this replica file share. The specified file share must not already have a replica, and must not be a replica.",
},
"replication_cron_spec": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DiffSuppressFunc: suppressCronSpecDiff,
Computed: true,
RequiredWith: []string{"source_share"},
ConflictsWith: []string{"replica_share", "size"},
Description: "The cron specification for the file share replication schedule.Replication of a share can be scheduled to occur at most once per hour.",
},
Expand Down Expand Up @@ -563,6 +571,30 @@ func ResourceIbmIsShare() *schema.Resource {
Computed: true,
Description: "The date and time that the file share was last synchronized to its replica.This property will be present when the `replication_role` is `source`.",
},
"latest_sync": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Description: "Information about the latest synchronization for this file share.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"completed_at": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The completed date and time of last synchronization between the replica share and its source.",
},
"data_transferred": &schema.Schema{
Type: schema.TypeInt,
Computed: true,
Description: "The data transferred (in bytes) in the last synchronization between the replica and its source.",
},
"started_at": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The start date and time of last synchronization between the replica share and its source.",
},
},
},
},
"latest_job": &schema.Schema{
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -727,17 +759,18 @@ func resourceIbmIsShareCreate(context context.Context, d *schema.ResourceData, m
accessControlMode := accessControlModeIntf.(string)
sharePrototype.AccessControlMode = &accessControlMode
}
if encryptionKeyIntf, ok := d.GetOk("encryption_key"); ok {
encryptionKey := encryptionKeyIntf.(string)
encryptionKeyIdentity := &vpcv1.EncryptionKeyIdentity{
CRN: &encryptionKey,
}
sharePrototype.EncryptionKey = encryptionKeyIdentity
}
if sizeIntf, ok := d.GetOk("size"); ok {

size := int64(sizeIntf.(int))
sharePrototype.Size = &size
if encryptionKeyIntf, ok := d.GetOk("encryption_key"); ok {
encryptionKey := encryptionKeyIntf.(string)
encryptionKeyIdentity := &vpcv1.EncryptionKeyIdentity{
CRN: &encryptionKey,
}
sharePrototype.EncryptionKey = encryptionKeyIdentity
}

initial_owner := &vpcv1.ShareInitialOwner{}
if initialOwnerIntf, ok := d.GetOk("initial_owner"); ok {
initialOwnerMap := initialOwnerIntf.([]interface{})[0].(map[string]interface{})
Expand Down Expand Up @@ -823,7 +856,15 @@ func resourceIbmIsShareCreate(context context.Context, d *schema.ResourceData, m
sharePrototype.SourceShare = &vpcv1.ShareIdentity{
ID: &sourceShare,
}
} else {
sourceShareCRN := d.Get("source_share_crn").(string)
if sourceShareCRN != "" {
sharePrototype.SourceShare = &vpcv1.ShareIdentity{
CRN: &sourceShareCRN,
}
}
}

replicationCronSpec := d.Get("replication_cron_spec").(string)
sharePrototype.ReplicationCronSpec = &replicationCronSpec
}
Expand Down Expand Up @@ -1075,9 +1116,17 @@ func resourceIbmIsShareRead(context context.Context, d *schema.ResourceData, met
return diag.FromErr(fmt.Errorf("Error setting resource_type: %s", err))
}

// if share.LastSyncAt != nil {
// d.Set("last_sync_at", share.LastSyncAt.String())
// }
latest_syncs := []map[string]interface{}{}
if share.LatestSync != nil {
latest_sync := make(map[string]interface{})
latest_sync["completed_at"] = flex.DateTimeToString(share.LatestSync.CompletedAt)
if share.LatestSync.DataTransferred != nil {
latest_sync["data_transferred"] = *share.LatestSync.DataTransferred
}
latest_sync["started_at"] = flex.DateTimeToString(share.LatestSync.CompletedAt)
latest_syncs = append(latest_syncs, latest_sync)
}
d.Set("latest_sync", latest_syncs)
latest_jobs := []map[string]interface{}{}
if share.LatestJob != nil {
latest_job := make(map[string]interface{})
Expand Down
35 changes: 34 additions & 1 deletion ibm/service/vpc/resource_ibm_is_share_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ func TestAccIbmIsShareBasic(t *testing.T) {
})
}

func TestAccIbmIsShareCrossRegionReplication(t *testing.T) {
var conf vpcv1.Share
name := fmt.Sprintf("tf-fs-name-%d", acctest.RandIntRange(10, 100))
resource.Test(t, resource.TestCase{
PreCheck: func() { acc.TestAccPreCheck(t) },
Providers: acc.TestAccProviders,
CheckDestroy: testAccCheckIbmIsShareDestroy,
Steps: []resource.TestStep{
{
Config: testAccCheckIbmIsShareCrossRegionReplicaConfig(name),
Check: resource.ComposeAggregateTestCheckFunc(
testAccCheckIbmIsShareExists("ibm_is_share.is_share", conf),
resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "source_share_crn"),
resource.TestCheckResourceAttrSet("ibm_is_share.is_share", "encryption_key"),
resource.TestCheckResourceAttr("ibm_is_share.is_share", "name", name),
resource.TestCheckResourceAttr("ibm_is_share.is_share", "encryption", "user_managed"),
),
},
},
})
}

func TestAccIbmIsShareAllArgs(t *testing.T) {
var conf vpcv1.Share

Expand Down Expand Up @@ -157,7 +179,18 @@ func testAccCheckIbmIsShareConfigBasic(name string) string {
}
`, name, acc.ShareProfileName)
}

func testAccCheckIbmIsShareCrossRegionReplicaConfig(name string) string {
return fmt.Sprintf(`
resource "ibm_is_share" "is_share" {
zone = "us-south-2"
encryption_key = "%s"
source_share_crn = "%s"
replication_cron_spec = "0 */5 * * *"
name = "%s"
profile = "%s"
}
`, acc.ShareEncryptionKey, acc.SourceShareCRN, name, acc.ShareProfileName)
}
func testAccCheckIbmIsShareConfig(vpcName, name string, size int, shareTergetName string) string {
return fmt.Sprintf(`
Expand Down
7 changes: 6 additions & 1 deletion website/docs/d/is_share.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,14 @@ The following attributes are exported:
- `created_at` - The date and time that the file share is created.
- `crn` - The CRN for this share.
- `encryption` - The type of encryption used for this file share.
- `encryption_key` - The CRN of the key used to encrypt this file share. Nested `encryption_key` blocks have the following structure:
- `encryption_key` - The CRN of the key used to encrypt this file share.
- `href` - The URL for this share.
- `iops` - The maximum input/output operation performance bandwidth per second for the file share.
- `latest_sync` - (List) Information about the latest synchronization for this file share.
Nested `latest_sync` blocks have the following structure:
- `completed_at` - (String) The completed date and time of last synchronization between the replica share and its source.
- `data_transferred` - (Integer) The data transferred (in bytes) in the last synchronization between the replica and its source.
- `started_at` - (String) The start date and time of last synchronization between the replica share and its source.
- `latest_job` - The latest job associated with this file share.This property will be absent if no jobs have been created for this file share. Nested `latest_job` blocks have the following structure:
- `status` - The status of the file share job
- `status_reasons` - The reasons for the file share job status (if any). Nested `status_reasons` blocks have the following structure:
Expand Down
Loading
Loading