Skip to content

Commit adf9377

Browse files
Ravi Tandonkilokahn
authored andcommitted
Support for cloning of Autonomous Databases
1 parent 6646fa8 commit adf9377

9 files changed

+228
-57
lines changed

CHANGELOG.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
## 3.18.1 (Unreleased)
1+
## 3.19.0 (Unreleased)
2+
3+
### Added
4+
- Support for cloning of Autonomous Databases
5+
26
## 3.18.0 (March 13, 2019)
37

48
### Added
@@ -81,7 +85,7 @@
8185

8286
### Note
8387
- Examples and test updated to use VM.Standard2.1
84-
- Windows example image updated to Windows-Server-2012-R2-Standard-Edition-VM-Gen2-2018.12.12-0
88+
- Windows example image updated to Windows-Server-2012-R2-Standard-Edition-VM-Gen2-2018.12.12-0
8589

8690
## 3.11.2 (January 10, 2019)
8791

oci/database_autonomous_database_data_source.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ func DatabaseAutonomousDatabaseDataSource() *schema.Resource {
106106
Type: schema.TypeString,
107107
Computed: true,
108108
},
109+
"used_data_storage_size_in_tbs": {
110+
Type: schema.TypeInt,
111+
Computed: true,
112+
},
109113
},
110114
}
111115
}
@@ -208,5 +212,9 @@ func (s *DatabaseAutonomousDatabaseDataSourceCrud) SetData() error {
208212
s.D.Set("time_created", s.Res.TimeCreated.String())
209213
}
210214

215+
if s.Res.UsedDataStorageSizeInTBs != nil {
216+
s.D.Set("used_data_storage_size_in_tbs", *s.Res.UsedDataStorageSizeInTBs)
217+
}
218+
211219
return nil
212220
}

oci/database_autonomous_database_resource.go

Lines changed: 146 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ package provider
44

55
import (
66
"context"
7+
"fmt"
8+
"strings"
79

810
"github.com/hashicorp/terraform/helper/schema"
11+
"github.com/hashicorp/terraform/helper/validation"
912

1013
oci_database "github.com/oracle/oci-go-sdk/database"
1114
)
@@ -47,6 +50,12 @@ func DatabaseAutonomousDatabaseResource() *schema.Resource {
4750
},
4851

4952
// Optional
53+
"clone_type": {
54+
Type: schema.TypeString,
55+
Optional: true,
56+
Computed: true,
57+
ForceNew: true,
58+
},
5059
"db_workload": {
5160
Type: schema.TypeString,
5261
Optional: true,
@@ -77,6 +86,23 @@ func DatabaseAutonomousDatabaseResource() *schema.Resource {
7786
Computed: true,
7887
ForceNew: true,
7988
},
89+
"source": {
90+
Type: schema.TypeString,
91+
Optional: true,
92+
Computed: true,
93+
ForceNew: true,
94+
DiffSuppressFunc: EqualIgnoreCaseSuppressDiff,
95+
ValidateFunc: validation.StringInSlice([]string{
96+
"DATABASE",
97+
"NONE",
98+
}, true),
99+
},
100+
"source_id": {
101+
Type: schema.TypeString,
102+
Optional: true,
103+
Computed: true,
104+
ForceNew: true,
105+
},
80106

81107
// Computed
82108
"connection_strings": {
@@ -131,6 +157,10 @@ func DatabaseAutonomousDatabaseResource() *schema.Resource {
131157
Type: schema.TypeString,
132158
Computed: true,
133159
},
160+
"used_data_storage_size_in_tbs": {
161+
Type: schema.TypeInt,
162+
Computed: true,
163+
},
134164
},
135165
}
136166
}
@@ -221,55 +251,9 @@ func (s *DatabaseAutonomousDatabaseResourceCrud) UpdatedTarget() []string {
221251

222252
func (s *DatabaseAutonomousDatabaseResourceCrud) Create() error {
223253
request := oci_database.CreateAutonomousDatabaseRequest{}
224-
225-
if adminPassword, ok := s.D.GetOkExists("admin_password"); ok {
226-
tmp := adminPassword.(string)
227-
request.AdminPassword = &tmp
228-
}
229-
230-
if compartmentId, ok := s.D.GetOkExists("compartment_id"); ok {
231-
tmp := compartmentId.(string)
232-
request.CompartmentId = &tmp
233-
}
234-
235-
if cpuCoreCount, ok := s.D.GetOkExists("cpu_core_count"); ok {
236-
tmp := cpuCoreCount.(int)
237-
request.CpuCoreCount = &tmp
238-
}
239-
240-
if dataStorageSizeInTBs, ok := s.D.GetOkExists("data_storage_size_in_tbs"); ok {
241-
tmp := dataStorageSizeInTBs.(int)
242-
request.DataStorageSizeInTBs = &tmp
243-
}
244-
245-
if dbName, ok := s.D.GetOkExists("db_name"); ok {
246-
tmp := dbName.(string)
247-
request.DbName = &tmp
248-
}
249-
250-
if dbWorkload, ok := s.D.GetOkExists("db_workload"); ok {
251-
request.DbWorkload = oci_database.CreateAutonomousDatabaseDetailsDbWorkloadEnum(dbWorkload.(string))
252-
}
253-
254-
if definedTags, ok := s.D.GetOkExists("defined_tags"); ok {
255-
convertedDefinedTags, err := mapToDefinedTags(definedTags.(map[string]interface{}))
256-
if err != nil {
257-
return err
258-
}
259-
request.DefinedTags = convertedDefinedTags
260-
}
261-
262-
if displayName, ok := s.D.GetOkExists("display_name"); ok {
263-
tmp := displayName.(string)
264-
request.DisplayName = &tmp
265-
}
266-
267-
if freeformTags, ok := s.D.GetOkExists("freeform_tags"); ok {
268-
request.FreeformTags = objectMapToStringMap(freeformTags.(map[string]interface{}))
269-
}
270-
271-
if licenseModel, ok := s.D.GetOkExists("license_model"); ok {
272-
request.LicenseModel = oci_database.CreateAutonomousDatabaseDetailsLicenseModelEnum(licenseModel.(string))
254+
err := s.populateTopLevelPolymorphicCreateAutonomousDatabaseRequest(&request)
255+
if err != nil {
256+
return err
273257
}
274258

275259
request.RequestMetadata.RetryPolicy = getRetryPolicy(s.DisableNotFoundRetries, "database")
@@ -417,6 +401,10 @@ func (s *DatabaseAutonomousDatabaseResourceCrud) SetData() error {
417401
s.D.Set("time_created", s.Res.TimeCreated.String())
418402
}
419403

404+
if s.Res.UsedDataStorageSizeInTBs != nil {
405+
s.D.Set("used_data_storage_size_in_tbs", *s.Res.UsedDataStorageSizeInTBs)
406+
}
407+
420408
return nil
421409
}
422410

@@ -439,3 +427,112 @@ func AutonomousDatabaseConnectionStringsToMap(obj *oci_database.AutonomousDataba
439427

440428
return result
441429
}
430+
431+
func (s *DatabaseAutonomousDatabaseResourceCrud) populateTopLevelPolymorphicCreateAutonomousDatabaseRequest(request *oci_database.CreateAutonomousDatabaseRequest) error {
432+
//discriminator
433+
sourceRaw, ok := s.D.GetOkExists("source")
434+
var source string
435+
if ok {
436+
source = sourceRaw.(string)
437+
} else {
438+
source = "NONE" // default value
439+
}
440+
switch strings.ToLower(source) {
441+
case strings.ToLower("DATABASE"):
442+
details := oci_database.CreateAutonomousDatabaseCloneDetails{}
443+
if cloneType, ok := s.D.GetOkExists("clone_type"); ok {
444+
details.CloneType = oci_database.CreateAutonomousDatabaseCloneDetailsCloneTypeEnum(cloneType.(string))
445+
}
446+
if sourceId, ok := s.D.GetOkExists("source_id"); ok {
447+
tmp := sourceId.(string)
448+
details.SourceId = &tmp
449+
}
450+
if adminPassword, ok := s.D.GetOkExists("admin_password"); ok {
451+
tmp := adminPassword.(string)
452+
details.AdminPassword = &tmp
453+
}
454+
if compartmentId, ok := s.D.GetOkExists("compartment_id"); ok {
455+
tmp := compartmentId.(string)
456+
details.CompartmentId = &tmp
457+
}
458+
if cpuCoreCount, ok := s.D.GetOkExists("cpu_core_count"); ok {
459+
tmp := cpuCoreCount.(int)
460+
details.CpuCoreCount = &tmp
461+
}
462+
if dataStorageSizeInTBs, ok := s.D.GetOkExists("data_storage_size_in_tbs"); ok {
463+
tmp := dataStorageSizeInTBs.(int)
464+
details.DataStorageSizeInTBs = &tmp
465+
}
466+
if dbName, ok := s.D.GetOkExists("db_name"); ok {
467+
tmp := dbName.(string)
468+
details.DbName = &tmp
469+
}
470+
if dbWorkload, ok := s.D.GetOkExists("db_workload"); ok {
471+
details.DbWorkload = oci_database.CreateAutonomousDatabaseBaseDbWorkloadEnum(dbWorkload.(string))
472+
}
473+
if definedTags, ok := s.D.GetOkExists("defined_tags"); ok {
474+
convertedDefinedTags, err := mapToDefinedTags(definedTags.(map[string]interface{}))
475+
if err != nil {
476+
return err
477+
}
478+
details.DefinedTags = convertedDefinedTags
479+
}
480+
if displayName, ok := s.D.GetOkExists("display_name"); ok {
481+
tmp := displayName.(string)
482+
details.DisplayName = &tmp
483+
}
484+
if freeformTags, ok := s.D.GetOkExists("freeform_tags"); ok {
485+
details.FreeformTags = objectMapToStringMap(freeformTags.(map[string]interface{}))
486+
}
487+
if licenseModel, ok := s.D.GetOkExists("license_model"); ok {
488+
details.LicenseModel = oci_database.CreateAutonomousDatabaseBaseLicenseModelEnum(licenseModel.(string))
489+
}
490+
request.CreateAutonomousDatabaseDetails = details
491+
case strings.ToLower("NONE"):
492+
details := oci_database.CreateAutonomousDatabaseDetails{}
493+
if adminPassword, ok := s.D.GetOkExists("admin_password"); ok {
494+
tmp := adminPassword.(string)
495+
details.AdminPassword = &tmp
496+
}
497+
if compartmentId, ok := s.D.GetOkExists("compartment_id"); ok {
498+
tmp := compartmentId.(string)
499+
details.CompartmentId = &tmp
500+
}
501+
if cpuCoreCount, ok := s.D.GetOkExists("cpu_core_count"); ok {
502+
tmp := cpuCoreCount.(int)
503+
details.CpuCoreCount = &tmp
504+
}
505+
if dataStorageSizeInTBs, ok := s.D.GetOkExists("data_storage_size_in_tbs"); ok {
506+
tmp := dataStorageSizeInTBs.(int)
507+
details.DataStorageSizeInTBs = &tmp
508+
}
509+
if dbName, ok := s.D.GetOkExists("db_name"); ok {
510+
tmp := dbName.(string)
511+
details.DbName = &tmp
512+
}
513+
if dbWorkload, ok := s.D.GetOkExists("db_workload"); ok {
514+
details.DbWorkload = oci_database.CreateAutonomousDatabaseBaseDbWorkloadEnum(dbWorkload.(string))
515+
}
516+
if definedTags, ok := s.D.GetOkExists("defined_tags"); ok {
517+
convertedDefinedTags, err := mapToDefinedTags(definedTags.(map[string]interface{}))
518+
if err != nil {
519+
return err
520+
}
521+
details.DefinedTags = convertedDefinedTags
522+
}
523+
if displayName, ok := s.D.GetOkExists("display_name"); ok {
524+
tmp := displayName.(string)
525+
details.DisplayName = &tmp
526+
}
527+
if freeformTags, ok := s.D.GetOkExists("freeform_tags"); ok {
528+
details.FreeformTags = objectMapToStringMap(freeformTags.(map[string]interface{}))
529+
}
530+
if licenseModel, ok := s.D.GetOkExists("license_model"); ok {
531+
details.LicenseModel = oci_database.CreateAutonomousDatabaseBaseLicenseModelEnum(licenseModel.(string))
532+
}
533+
request.CreateAutonomousDatabaseDetails = details
534+
default:
535+
return fmt.Errorf("unknown source '%v' was specified", source)
536+
}
537+
return nil
538+
}

oci/database_autonomous_database_test.go

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@ var (
3737
"values": Representation{repType: Required, create: []string{`${oci_database_autonomous_database.test_autonomous_database.id}`}},
3838
}
3939

40-
adbName = randomString(1, charsetWithoutDigits) + randomString(13, charset)
40+
adbName = randomString(1, charsetWithoutDigits) + randomString(13, charset)
41+
adbCloneName = randomString(1, charsetWithoutDigits) + randomString(13, charset)
4142

4243
autonomousDatabaseRepresentation = map[string]interface{}{
4344
"admin_password": Representation{repType: Required, create: `BEstrO0ng_#11`, update: `BEstrO0ng_#12`},
@@ -52,6 +53,14 @@ var (
5253
"license_model": Representation{repType: Optional, create: `LICENSE_INCLUDED`},
5354
}
5455

56+
autonomousDatabaseRepresentationForClone = representationCopyWithNewProperties(
57+
getUpdatedRepresentationCopy("db_name", Representation{repType: Required, create: adbCloneName}, autonomousDatabaseRepresentation),
58+
map[string]interface{}{
59+
"clone_type": Representation{repType: Optional, create: `FULL`},
60+
"source": Representation{repType: Optional, create: `DATABASE`},
61+
"source_id": Representation{repType: Optional, create: `${oci_database_autonomous_database.test_autonomous_database_source.id}`},
62+
})
63+
5564
AutonomousDatabaseResourceDependencies = DefinedTagsDependencies
5665
)
5766

@@ -174,7 +183,6 @@ func TestDatabaseAutonomousDatabaseResource_basic(t *testing.T) {
174183
resource.TestCheckResourceAttr(datasourceName, "autonomous_databases.0.freeform_tags.%", "1"),
175184
resource.TestCheckResourceAttrSet(datasourceName, "autonomous_databases.0.id"),
176185
resource.TestCheckResourceAttr(datasourceName, "autonomous_databases.0.license_model", "LICENSE_INCLUDED"),
177-
resource.TestCheckResourceAttrSet(datasourceName, "autonomous_databases.0.state"),
178186
),
179187
},
180188
// verify singular datasource
@@ -216,6 +224,9 @@ func TestDatabaseAutonomousDatabaseResource_basic(t *testing.T) {
216224
ImportStateVerify: true,
217225
ImportStateVerifyIgnore: []string{
218226
"admin_password",
227+
"clone_type",
228+
"source",
229+
"source_id",
219230
"lifecycle_details",
220231
},
221232
ResourceName: resourceName,
@@ -279,6 +290,42 @@ func TestDatabaseAutonomousDatabaseResource_basic(t *testing.T) {
279290
},
280291
),
281292
},
293+
294+
// remove any previously created resources
295+
{
296+
Config: config + compartmentIdVariableStr + AutonomousDatabaseResourceDependencies,
297+
},
298+
// verify ADB clone from a source ADB
299+
{
300+
Config: config + compartmentIdVariableStr + AutonomousDatabaseResourceDependencies +
301+
generateResourceFromRepresentationMap("oci_database_autonomous_database", "test_autonomous_database_source", Optional, Create, autonomousDatabaseRepresentation) +
302+
generateResourceFromRepresentationMap("oci_database_autonomous_database", "test_autonomous_database", Optional, Create, autonomousDatabaseRepresentationForClone),
303+
Check: resource.ComposeAggregateTestCheckFunc(
304+
resource.TestCheckResourceAttr(resourceName, "admin_password", "BEstrO0ng_#11"),
305+
resource.TestCheckResourceAttr(resourceName, "clone_type", "FULL"),
306+
resource.TestCheckResourceAttr(resourceName, "compartment_id", compartmentId),
307+
resource.TestCheckResourceAttr(resourceName, "cpu_core_count", "1"),
308+
resource.TestCheckResourceAttr(resourceName, "data_storage_size_in_tbs", "1"),
309+
resource.TestCheckResourceAttr(resourceName, "db_name", adbCloneName),
310+
resource.TestCheckResourceAttr(resourceName, "db_workload", "OLTP"),
311+
resource.TestCheckResourceAttr(resourceName, "defined_tags.%", "1"),
312+
resource.TestCheckResourceAttr(resourceName, "display_name", "example_autonomous_database"),
313+
resource.TestCheckResourceAttr(resourceName, "freeform_tags.%", "1"),
314+
resource.TestCheckResourceAttrSet(resourceName, "id"),
315+
resource.TestCheckResourceAttr(resourceName, "license_model", "LICENSE_INCLUDED"),
316+
resource.TestCheckResourceAttr(resourceName, "source", "DATABASE"),
317+
resource.TestCheckResourceAttrSet(resourceName, "source_id"),
318+
resource.TestCheckResourceAttrSet(resourceName, "state"),
319+
320+
func(s *terraform.State) (err error) {
321+
resId, err = fromInstanceState(s, resourceName, "id")
322+
if resId == resId2 {
323+
return fmt.Errorf("Resource updated when it was supposed to be re-created.")
324+
}
325+
return err
326+
},
327+
),
328+
},
282329
},
283330
})
284331
}

oci/database_autonomous_databases_data_source.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ func (s *DatabaseAutonomousDatabasesDataSourceCrud) SetData() error {
168168
autonomousDatabase["time_created"] = r.TimeCreated.String()
169169
}
170170

171+
if r.UsedDataStorageSizeInTBs != nil {
172+
autonomousDatabase["used_data_storage_size_in_tbs"] = *r.UsedDataStorageSizeInTBs
173+
}
174+
171175
resources = append(resources, autonomousDatabase)
172176
}
173177

website/docs/d/database_autonomous_database.html.markdown

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,5 @@ The following attributes are exported:
5252
* `service_console_url` - The URL of the Service Console for the Autonomous Database.
5353
* `state` - The current state of the database.
5454
* `time_created` - The date and time the database was created.
55+
* `used_data_storage_size_in_tbs` - The amount of storage that has been used, in terabytes.
5556

website/docs/d/database_autonomous_databases.html.markdown

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,5 @@ The following attributes are exported:
6666
* `service_console_url` - The URL of the Service Console for the Autonomous Database.
6767
* `state` - The current state of the database.
6868
* `time_created` - The date and time the database was created.
69+
* `used_data_storage_size_in_tbs` - The amount of storage that has been used, in terabytes.
6970

0 commit comments

Comments
 (0)