Skip to content

Commit 7644e85

Browse files
Isabella Macedavarmax2511
authored andcommitted
support for file system clones
1 parent 7b3a246 commit 7644e85

22 files changed

+430
-83
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 4.16.0 (Unreleased)
2+
3+
### Added
4+
- Support for File storage file system clones
5+
16
## 4.15.0 (February 24, 2021)
27

38
### Added
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
resource "oci_file_storage_file_system" "my_fs_clone" {
2+
#Required
3+
availability_domain = data.oci_identity_availability_domain.ad.name
4+
compartment_id = var.compartment_ocid
5+
6+
#Optional
7+
display_name = var.file_system_clone_display_name
8+
source_snapshot_id = oci_file_storage_snapshot.my_snapshot_clone.id
9+
}
10+
resource "oci_file_storage_file_system" "my_fs_simple" {
11+
#Required
12+
availability_domain = data.oci_identity_availability_domain.ad.name
13+
compartment_id = var.compartment_ocid
14+
15+
#Optional
16+
display_name = var.file_system_simple_display_name
17+
}
18+
resource "oci_file_storage_snapshot" "my_snapshot_clone" {
19+
#Required
20+
file_system_id = oci_file_storage_file_system.my_fs_simple.id
21+
name = var.snapshot_name_clone
22+
}

examples/storage/fss/variables.tf

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ variable "file_system_2_display_name" {
4242
default = "my_fs_2"
4343
}
4444

45+
variable "file_system_clone_display_name" {
46+
default= "my_fs_clone"
47+
}
48+
49+
variable "file_system_simple_display_name" {
50+
default= "my_fs_simple"
51+
}
52+
4553
variable "mount_target_1_display_name" {
4654
default = "my_mount_target_1"
4755
}
@@ -66,6 +74,10 @@ variable "snapshot_name" {
6674
default = "20180320_daily"
6775
}
6876

77+
variable "snapshot_name_clone" {
78+
default = "snapshot_clone"
79+
}
80+
6981
variable "export_set_name_1" {
7082
default = "export set for mount target 1"
7183
}

oci/file_storage_file_system_resource.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,53 @@ func FileStorageFileSystemResource() *schema.Resource {
6262
Type: schema.TypeString,
6363
Optional: true,
6464
},
65+
"source_snapshot_id": {
66+
Type: schema.TypeString,
67+
Optional: true,
68+
Computed: true,
69+
ForceNew: true,
70+
},
6571

6672
// Computed
73+
"is_clone_parent": {
74+
Type: schema.TypeBool,
75+
Computed: true,
76+
},
77+
"is_hydrated": {
78+
Type: schema.TypeBool,
79+
Computed: true,
80+
},
81+
"lifecycle_details": {
82+
Type: schema.TypeString,
83+
Computed: true,
84+
},
6785
"metered_bytes": {
6886
Type: schema.TypeString,
6987
Computed: true,
7088
},
89+
"source_details": {
90+
Type: schema.TypeList,
91+
Computed: true,
92+
MaxItems: 1,
93+
MinItems: 1,
94+
Elem: &schema.Resource{
95+
Schema: map[string]*schema.Schema{
96+
// Required
97+
98+
// Optional
99+
100+
// Computed
101+
"parent_file_system_id": {
102+
Type: schema.TypeString,
103+
Computed: true,
104+
},
105+
"source_snapshot_id": {
106+
Type: schema.TypeString,
107+
Computed: true,
108+
},
109+
},
110+
},
111+
},
71112
"state": {
72113
Type: schema.TypeString,
73114
Computed: true,
@@ -183,6 +224,11 @@ func (s *FileStorageFileSystemResourceCrud) Create() error {
183224
request.KmsKeyId = &tmp
184225
}
185226

227+
if sourceSnapshotId, ok := s.D.GetOkExists("source_snapshot_id"); ok {
228+
tmp := sourceSnapshotId.(string)
229+
request.SourceSnapshotId = &tmp
230+
}
231+
186232
request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "file_storage")
187233

188234
response, err := s.Client.CreateFileSystem(context.Background(), request)
@@ -290,14 +336,32 @@ func (s *FileStorageFileSystemResourceCrud) SetData() error {
290336

291337
s.D.Set("freeform_tags", s.Res.FreeformTags)
292338

339+
if s.Res.IsCloneParent != nil {
340+
s.D.Set("is_clone_parent", *s.Res.IsCloneParent)
341+
}
342+
343+
if s.Res.IsHydrated != nil {
344+
s.D.Set("is_hydrated", *s.Res.IsHydrated)
345+
}
346+
293347
if s.Res.KmsKeyId != nil {
294348
s.D.Set("kms_key_id", *s.Res.KmsKeyId)
295349
}
296350

351+
if s.Res.LifecycleDetails != nil {
352+
s.D.Set("lifecycle_details", *s.Res.LifecycleDetails)
353+
}
354+
297355
if s.Res.MeteredBytes != nil {
298356
s.D.Set("metered_bytes", strconv.FormatInt(*s.Res.MeteredBytes, 10))
299357
}
300358

359+
if s.Res.SourceDetails != nil {
360+
s.D.Set("source_details", []interface{}{FileSystemSourceDetailsToMap(s.Res.SourceDetails)})
361+
} else {
362+
s.D.Set("source_details", nil)
363+
}
364+
301365
s.D.Set("state", s.Res.LifecycleState)
302366

303367
if s.Res.TimeCreated != nil {
@@ -307,6 +371,20 @@ func (s *FileStorageFileSystemResourceCrud) SetData() error {
307371
return nil
308372
}
309373

374+
func FileSystemSourceDetailsToMap(obj *oci_file_storage.SourceDetails) map[string]interface{} {
375+
result := map[string]interface{}{}
376+
377+
if obj.ParentFileSystemId != nil {
378+
result["parent_file_system_id"] = string(*obj.ParentFileSystemId)
379+
}
380+
381+
if obj.SourceSnapshotId != nil {
382+
result["source_snapshot_id"] = string(*obj.SourceSnapshotId)
383+
}
384+
385+
return result
386+
}
387+
310388
func (s *FileStorageFileSystemResourceCrud) updateCompartment(compartment interface{}) error {
311389
changeCompartmentRequest := oci_file_storage.ChangeFileSystemCompartmentRequest{}
312390

oci/file_storage_file_system_resource_test.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package oci
55

66
import (
77
"fmt"
8+
"strconv"
89
"testing"
910

1011
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
@@ -22,6 +23,33 @@ var (
2223
"freeform_tags": Representation{repType: Optional, create: map[string]string{"Department": "Finance"}},
2324
"kms_key_id": Representation{repType: Optional, create: `${var.kms_key_id_for_create}`, update: ``},
2425
}
26+
snapshotRepresentationNoTags = map[string]interface{}{
27+
"file_system_id": Representation{repType: Required, create: `${oci_file_storage_file_system.test_file_system.id}`},
28+
"name": Representation{repType: Required, create: `snapshot-1`},
29+
"freeform_tags": Representation{repType: Optional, create: map[string]string{"Department": "Finance"}, update: map[string]string{"Department": "Accounting"}},
30+
}
31+
fileSystemRepresentationNoTags = map[string]interface{}{
32+
"availability_domain": Representation{repType: Required, create: `${data.oci_identity_availability_domains.test_availability_domains.availability_domains.0.name}`},
33+
"compartment_id": Representation{repType: Required, create: `${var.compartment_id}`},
34+
"display_name": Representation{repType: Optional, create: `media-files-1`, update: `displayName2`},
35+
"freeform_tags": Representation{repType: Optional, create: map[string]string{"Department": "Finance"}, update: map[string]string{"Department": "Accounting"}},
36+
"source_snapshot_id": Representation{repType: Optional, create: `${oci_file_storage_snapshot.test_snapshot.id}`},
37+
}
38+
39+
SnapshotResourceDependenciesNoTags = generateResourceFromRepresentationMap("oci_file_storage_file_system", "test_file_system", Required, Create, fileSystemRepresentationNoTags) +
40+
AvailabilityDomainConfig
41+
42+
fileSystemRepresentationClone = map[string]interface{}{
43+
"availability_domain": Representation{repType: Required, create: `${data.oci_identity_availability_domains.test_availability_domains.availability_domains.0.name}`},
44+
"compartment_id": Representation{repType: Required, create: `${var.compartment_id}`},
45+
"display_name": Representation{repType: Optional, create: `media-files-1`, update: `displayName2`},
46+
"freeform_tags": Representation{repType: Optional, create: map[string]string{"Department": "Finance"}, update: map[string]string{"Department": "Accounting"}},
47+
"source_snapshot_id": Representation{repType: Optional, create: `${oci_file_storage_snapshot.test_snapshot.id}`},
48+
}
49+
50+
FileSystemResourceDependenciesNoTags = generateResourceFromRepresentationMap("oci_file_storage_file_system", "test_file_system", Required, Create, fileSystemRepresentationNoTags) +
51+
generateResourceFromRepresentationMap("oci_file_storage_snapshot", "test_snapshot", Required, Create, snapshotRepresentationNoTags) +
52+
AvailabilityDomainConfig
2553
)
2654

2755
func TestFileStorageFileSystemResource_removeKMSKey(t *testing.T) {
@@ -123,3 +151,76 @@ func TestFileStorageFileSystemResource_removeKMSKey(t *testing.T) {
123151
},
124152
})
125153
}
154+
155+
func TestFileStorageFileSystemResource_cloneFromSnapshot(t *testing.T) {
156+
httpreplay.SetScenario("TestFileStorageFileSystemResource_cloneFromSnapshot")
157+
defer httpreplay.SaveScenario()
158+
159+
provider := testAccProvider
160+
config := testProviderConfig()
161+
162+
compartmentId := getEnvSettingWithBlankDefault("compartment_ocid")
163+
compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)
164+
165+
resourceName := "oci_file_storage_snapshot.test_snapshot"
166+
resourceName2 := "oci_file_storage_file_system.test_file_system_clone"
167+
168+
var resId string
169+
170+
resource.Test(t, resource.TestCase{
171+
PreCheck: func() { testAccPreCheck(t) },
172+
Providers: map[string]terraform.ResourceProvider{
173+
"oci": provider,
174+
},
175+
CheckDestroy: testAccCheckFileStorageFileSystemDestroy,
176+
Steps: []resource.TestStep{
177+
// verify create with optionals
178+
{
179+
Config: config + compartmentIdVariableStr + SnapshotResourceDependenciesNoTags +
180+
generateResourceFromRepresentationMap("oci_file_storage_snapshot", "test_snapshot", Optional, Create, snapshotRepresentationNoTags),
181+
Check: resource.ComposeAggregateTestCheckFunc(
182+
resource.TestCheckResourceAttrSet(resourceName, "file_system_id"),
183+
resource.TestCheckResourceAttr(resourceName, "freeform_tags.%", "1"),
184+
resource.TestCheckResourceAttrSet(resourceName, "id"),
185+
resource.TestCheckResourceAttr(resourceName, "name", "snapshot-1"),
186+
resource.TestCheckResourceAttrSet(resourceName, "state"),
187+
resource.TestCheckResourceAttrSet(resourceName, "time_created"),
188+
func(s *terraform.State) (err error) {
189+
resId, err = fromInstanceState(s, resourceName, "id")
190+
if isEnableExportCompartment, _ := strconv.ParseBool(getEnvSettingWithDefault("enable_export_compartment", "false")); isEnableExportCompartment {
191+
if errExport := testExportCompartmentWithResourceName(&resId, &compartmentId, resourceName); errExport != nil {
192+
return errExport
193+
}
194+
}
195+
return err
196+
},
197+
),
198+
},
199+
// verify create FileSystem via cloning Snapshot
200+
{
201+
Config: config + compartmentIdVariableStr + FileSystemResourceDependenciesNoTags +
202+
generateResourceFromRepresentationMap("oci_file_storage_file_system", "test_file_system_clone", Optional, Create, fileSystemRepresentationClone),
203+
Check: resource.ComposeAggregateTestCheckFunc(
204+
resource.TestCheckResourceAttrSet(resourceName2, "availability_domain"),
205+
resource.TestCheckResourceAttr(resourceName2, "compartment_id", compartmentId),
206+
resource.TestCheckResourceAttr(resourceName2, "display_name", "media-files-1"),
207+
resource.TestCheckResourceAttr(resourceName2, "freeform_tags.%", "1"),
208+
resource.TestCheckResourceAttrSet(resourceName2, "id"),
209+
resource.TestCheckResourceAttrSet(resourceName2, "metered_bytes"),
210+
resource.TestCheckResourceAttrSet(resourceName2, "source_snapshot_id"),
211+
resource.TestCheckResourceAttrSet(resourceName2, "state"),
212+
resource.TestCheckResourceAttrSet(resourceName2, "time_created"),
213+
//verify ids match
214+
func(s *terraform.State) (err error) {
215+
snapshotId, err := fromInstanceState(s, resourceName2, "source_snapshot_id")
216+
if resId != snapshotId {
217+
return fmt.Errorf("Resource source snapshot id [%v] was different from expected [%v].", snapshotId, resId)
218+
}
219+
220+
return err
221+
},
222+
),
223+
},
224+
},
225+
})
226+
}

0 commit comments

Comments
 (0)