Skip to content

Commit fb32b5c

Browse files
alex-muiravinitp
authored andcommitted
Added - Support for Cancel a full or incremental automatic backup
1 parent 9f96171 commit fb32b5c

17 files changed

+380
-41
lines changed
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
// Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
2+
// Licensed under the Mozilla Public License v2.0
3+
4+
package integrationtest
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"testing"
10+
"time"
11+
12+
"github.com/oracle/terraform-provider-oci/internal/acctest"
13+
"github.com/oracle/terraform-provider-oci/internal/client"
14+
"github.com/oracle/terraform-provider-oci/internal/utils"
15+
16+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
17+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
18+
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
19+
"github.com/oracle/oci-go-sdk/v65/common"
20+
oci_database "github.com/oracle/oci-go-sdk/v65/database"
21+
22+
"github.com/oracle/terraform-provider-oci/httpreplay"
23+
)
24+
25+
var (
26+
DatabaseCancelExacsBackupDatabaseRepresentation = map[string]interface{}{
27+
"backup_id": acctest.Representation{RepType: acctest.Required, Create: `unknown`},
28+
"cancel_backup_trigger": acctest.Representation{RepType: acctest.Optional, Create: `1`},
29+
}
30+
31+
GetBackupIdDataSourceRepresentation = map[string]interface{}{
32+
"database_id": acctest.Representation{RepType: acctest.Optional, Create: `${oci_database_database.test_database.id}`},
33+
}
34+
35+
DatabaseCancelExacsBackupDatabaseResourceDependencies = DatabaseDatabaseResourceDependencies +
36+
acctest.GenerateResourceFromRepresentationMap("oci_database_database", "test_database", acctest.Optional, acctest.Create, DatabaseDatabaseRepresentation)
37+
)
38+
39+
// issue-routing-tag: database/default
40+
func TestDatabaseBackupCancelManagementResource_basic(t *testing.T) {
41+
httpreplay.SetScenario("TestDatabaseBackupCancelManagementResource_basic")
42+
defer httpreplay.SaveScenario()
43+
44+
provider := acctest.TestAccProvider
45+
config := acctest.ProviderTestConfig()
46+
47+
compartmentId := utils.GetEnvSettingWithBlankDefault("compartment_ocid")
48+
compartmentIdVariableStr := fmt.Sprintf("variable \"compartment_id\" { default = \"%s\" }\n", compartmentId)
49+
50+
kmsKeyId := utils.GetEnvSettingWithBlankDefault("kms_key_id")
51+
kmsKeyIdVariableStr := fmt.Sprintf("variable \"kms_key_id\" { default = \"%s\" }\n", kmsKeyId)
52+
53+
resourceName := "oci_database_backup_cancel_management.test_cancel_backup"
54+
databaseName := "oci_database_database.test_database"
55+
listBackupName := "data.oci_database_backups.test_backups"
56+
57+
var resId string
58+
// Save TF content to create resource with optional properties. This has to be exactly the same as the config part in the "create with optionals" step in the test.
59+
acctest.SaveConfigContent(config+compartmentIdVariableStr+DatabaseCancelExacsBackupDatabaseResourceDependencies+kmsKeyIdVariableStr+
60+
acctest.GenerateResourceFromRepresentationMap("oci_database_backup_cancel_management", "test_cancel_backup", acctest.Optional, acctest.Create, DatabaseCancelExacsBackupDatabaseRepresentation), "database", "backup", t)
61+
62+
resource.Test(t, resource.TestCase{
63+
PreCheck: func() { acctest.PreCheck(t) },
64+
Providers: map[string]*schema.Provider{
65+
"oci": provider,
66+
},
67+
Steps: []resource.TestStep{
68+
69+
// Creating dependencies and most importantly the database with autoBackups enabled
70+
{
71+
Config: config + compartmentIdVariableStr + DatabaseCancelExacsBackupDatabaseResourceDependencies + kmsKeyIdVariableStr,
72+
Check: acctest.ComposeAggregateTestCheckFuncWrapper(
73+
resource.TestCheckResourceAttr(databaseName, "db_backup_config.0.auto_backup_enabled", "true"),
74+
75+
func(s *terraform.State) (err error) {
76+
resId, err = acctest.FromInstanceState(s, databaseName, "id")
77+
return err
78+
},
79+
),
80+
},
81+
// Poll the database until it reaches a backup_in_progress state and then call list backup on the databaseId to get the backup_id
82+
{
83+
PreConfig: acctest.WaitTillCondition(acctest.TestAccProvider, &resId, databaseWaitTillBackupInProgressConditionExa, time.Duration(1*time.Minute),
84+
databaseResponseFetchOperationExa, "database", true),
85+
Config: config + compartmentIdVariableStr + DatabaseCancelExacsBackupDatabaseResourceDependencies + kmsKeyIdVariableStr + acctest.GenerateDataSourceFromRepresentationMap("oci_database_backups", "test_backups", acctest.Optional, acctest.Update, GetBackupIdDataSourceRepresentation),
86+
Check: acctest.ComposeAggregateTestCheckFuncWrapper(
87+
resource.TestCheckResourceAttr(listBackupName, "backups.#", "1"),
88+
),
89+
},
90+
91+
// populate the cancel_backup request with the backup id
92+
{
93+
Config: config + compartmentIdVariableStr + DatabaseCancelExacsBackupDatabaseResourceDependencies + kmsKeyIdVariableStr +
94+
acctest.GenerateDataSourceFromRepresentationMap("oci_database_backups", "test_backups", acctest.Optional, acctest.Update, GetBackupIdDataSourceRepresentation) +
95+
acctest.GenerateResourceFromRepresentationMap("oci_database_backup_cancel_management", "test_cancel_backup", acctest.Required, acctest.Create,
96+
acctest.RepresentationCopyWithNewProperties(acctest.RepresentationCopyWithRemovedProperties(DatabaseCancelExacsBackupDatabaseRepresentation, []string{"backup_id"}), map[string]interface{}{
97+
"backup_id": acctest.Representation{RepType: acctest.Required, Create: `${data.oci_database_backups.test_backups.backups.0.id}`},
98+
})),
99+
Check: acctest.ComposeAggregateTestCheckFuncWrapper(
100+
resource.TestCheckResourceAttrSet(resourceName, "backup_id"),
101+
),
102+
},
103+
104+
// test if retries of cancel_backup on a backup that has already completed or been canceled will fail
105+
{
106+
Config: config + compartmentIdVariableStr + DatabaseCancelExacsBackupDatabaseResourceDependencies + kmsKeyIdVariableStr +
107+
acctest.GenerateDataSourceFromRepresentationMap("oci_database_backups", "test_backups", acctest.Optional, acctest.Update, GetBackupIdDataSourceRepresentation) +
108+
acctest.GenerateResourceFromRepresentationMap("oci_database_backup_cancel_management", "test_cancel_backup", acctest.Optional, acctest.Create,
109+
acctest.RepresentationCopyWithNewProperties(acctest.RepresentationCopyWithRemovedProperties(DatabaseCancelExacsBackupDatabaseRepresentation, []string{"backup_id"}), map[string]interface{}{
110+
"backup_id": acctest.Representation{RepType: acctest.Required, Create: `${data.oci_database_backups.test_backups.backups.0.id}`},
111+
})),
112+
Check: acctest.ComposeAggregateTestCheckFuncWrapper(
113+
resource.TestCheckResourceAttrSet(resourceName, "backup_id"),
114+
resource.TestCheckResourceAttrSet(resourceName, "cancel_backup_trigger"),
115+
),
116+
},
117+
},
118+
})
119+
}
120+
121+
func databaseWaitTillBackupInProgressConditionExa(response common.OCIOperationResponse) bool {
122+
if databaseResponse, ok := response.Response.(oci_database.GetDatabaseResponse); ok {
123+
fmt.Print("Checking whether the state of resource is BACKUP_IN_PROGRESS: ", databaseResponse.LifecycleState == oci_database.DatabaseLifecycleStateBackupInProgress, "\n")
124+
return (databaseResponse.LifecycleState != oci_database.DatabaseLifecycleStateBackupInProgress)
125+
}
126+
return false
127+
}
128+
129+
func databaseResponseFetchOperationExa(client *client.OracleClients, resourceId *string, retryPolicy *common.RetryPolicy) error {
130+
_, err := client.DatabaseClient().GetDatabase(context.Background(), oci_database.GetDatabaseRequest{
131+
DatabaseId: resourceId,
132+
RequestMetadata: common.RequestMetadata{
133+
RetryPolicy: retryPolicy,
134+
},
135+
})
136+
return err
137+
}

internal/integrationtest/database_database_backup_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ var (
113113
acctest.GenerateResourceFromRepresentationMap("oci_database_database", "db", acctest.Optional, acctest.Create, DatabaseDatabaseRepresentation) +
114114
acctest.GenerateResourceFromRepresentationMap("oci_database_backup", "test_backup", acctest.Required, acctest.Create, backupDatabaseRepresentation)
115115

116-
DatabaseBackupResourceDbHomeDependencies = ExaBaseDependencies + DefinedTagsDependencies + AvailabilityDomainConfig + databaseKeyConfig +
116+
DatabaseBackupResourceDbHomeDependencies = ExaBaseDependencies + DefinedTagsDependencies + AvailabilityDomainConfig + KeyResourceDependencyConfig2 +
117117
acctest.GenerateResourceFromRepresentationMap("oci_database_db_home", "test_db_home", acctest.Required, acctest.Create, dbHomeRepresentationSourceBackup) +
118118
acctest.GenerateResourceFromRepresentationMap("oci_database_database", "db", acctest.Optional, acctest.Create, DatabaseDatabaseBackupRepresentation) +
119119
acctest.GenerateResourceFromRepresentationMap("oci_database_backup", "test_backup", acctest.Required, acctest.Create, backupDatabaseRepresentation)

internal/integrationtest/database_database_test.go

Lines changed: 4 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -225,38 +225,13 @@ var (
225225
"db_version": acctest.Representation{RepType: acctest.Required, Create: `19.16.0.0`},
226226
})
227227

228-
databaseKeyConfig = KmsKeyResourceDependencies + `
229-
data "oci_kms_keys" "test_keys_dependency" {
230-
#Required
231-
compartment_id = "${var.compartment_id}"
232-
management_endpoint = "${data.oci_kms_vault.test_vault.management_endpoint}"
233-
algorithm = "AES"
234-
235-
filter {
236-
name = "state"
237-
values = ["ENABLED", "UPDATING"]
238-
}
239-
}
240-
data "oci_kms_keys" "test_keys_dependency_RSA" {
241-
#Required
242-
compartment_id = "${var.compartment_id}"
243-
management_endpoint = "${data.oci_kms_vault.test_vault.management_endpoint}"
244-
algorithm = "RSA"
245-
246-
filter {
247-
name = "state"
248-
values = ["ENABLED", "UPDATING"]
249-
}
250-
}
251-
`
252-
253-
DatabaseDatabaseResourceDependencies = ExaBaseDependencies + DefinedTagsDependencies + AvailabilityDomainConfig + databaseKeyConfig +
228+
DatabaseDatabaseResourceDependencies = ExaBaseDependencies + DefinedTagsDependencies + AvailabilityDomainConfig + KeyResourceDependencyConfig2 +
254229
acctest.GenerateResourceFromRepresentationMap("oci_database_db_home", "test_db_home", acctest.Required, acctest.Create, dbHomeRepresentationSourceNone)
255230

256231
DatabaseExacsDatabaseResourceDependencies = DbHomeResourceVmClusterDependencies +
257232
acctest.GenerateResourceFromRepresentationMap("oci_database_db_home", "test_db_home_vm_cluster_no_db", acctest.Required, acctest.Create, dbHomeRepresentationSourceVmCluster)
258233

259-
DatabaseDatabaseResourceDbrsDependencies = ExaBaseDependencies + DefinedTagsDependencies + AvailabilityDomainConfig + databaseKeyConfig +
234+
DatabaseDatabaseResourceDbrsDependencies = ExaBaseDependencies + DefinedTagsDependencies + AvailabilityDomainConfig + KeyResourceDependencyConfig2 +
260235
acctest.GenerateResourceFromRepresentationMap("oci_database_db_home", "test_db_home_dbrs", acctest.Required, acctest.Create, dbHomeDbrsRepresentation)
261236
)
262237

@@ -307,7 +282,7 @@ func TestDatabaseDatabaseResource_basic(t *testing.T) {
307282
//},
308283
// delete dbrs db
309284
//{
310-
// Config: config + compartmentIdVariableStr + ExaBaseDependencies + DefinedTagsDependencies + AvailabilityDomainConfig + databaseKeyConfig,
285+
// Config: config + compartmentIdVariableStr + ExaBaseDependencies + DefinedTagsDependencies + AvailabilityDomainConfig + KeyResourceDependencyConfig2,
311286
//},
312287

313288
// verify create
@@ -370,6 +345,7 @@ func TestDatabaseDatabaseResource_basic(t *testing.T) {
370345

371346
func(s *terraform.State) (err error) {
372347
resId, err = acctest.FromInstanceState(s, resourceName, "id")
348+
// commenting out because ListCompartment policies not re-added to tf user
373349
//if isEnableExportCompartment, _ := strconv.ParseBool(utils.GetEnvSettingWithDefault("enable_export_compartment", "true")); isEnableExportCompartment {
374350
// if errExport := resourcediscovery.TestExportCompartmentWithResourceName(&resId, &compartmentId, resourceName); errExport != nil {
375351
// return errExport
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
// Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
2+
// Licensed under the Mozilla Public License v2.0
3+
4+
package database
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"log"
10+
"strings"
11+
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
13+
14+
oci_database "github.com/oracle/oci-go-sdk/v65/database"
15+
16+
"github.com/oracle/terraform-provider-oci/internal/client"
17+
"github.com/oracle/terraform-provider-oci/internal/tfresource"
18+
)
19+
20+
func DatabaseBackupCancelManagementResource() *schema.Resource {
21+
return &schema.Resource{
22+
Timeouts: tfresource.DefaultTimeout,
23+
Create: createDatabaseBackupCancelManagement,
24+
Read: readDatabaseBackupCancelManagement,
25+
Delete: deleteDatabaseBackupCancelManagement,
26+
Schema: map[string]*schema.Schema{
27+
// Required
28+
"backup_id": {
29+
Type: schema.TypeString,
30+
Required: true,
31+
ForceNew: true,
32+
},
33+
34+
"cancel_backup_trigger": {
35+
Type: schema.TypeInt,
36+
Optional: true,
37+
ForceNew: true,
38+
},
39+
40+
// Optional
41+
42+
// Computed
43+
},
44+
}
45+
}
46+
47+
func createDatabaseBackupCancelManagement(d *schema.ResourceData, m interface{}) error {
48+
sync := &DatabaseBackupCancelManagementResourceCrud{}
49+
sync.D = d
50+
sync.Client = m.(*client.OracleClients).DatabaseClient()
51+
52+
return tfresource.CreateResource(d, sync)
53+
}
54+
55+
func readDatabaseBackupCancelManagement(d *schema.ResourceData, m interface{}) error {
56+
return nil
57+
}
58+
59+
func deleteDatabaseBackupCancelManagement(d *schema.ResourceData, m interface{}) error {
60+
return nil
61+
}
62+
63+
type DatabaseBackupCancelManagementResourceCrud struct {
64+
tfresource.BaseCrud
65+
Client *oci_database.DatabaseClient
66+
Res *oci_database.Backup
67+
DisableNotFoundRetries bool
68+
}
69+
70+
func (s *DatabaseBackupCancelManagementResourceCrud) ID() string {
71+
return tfresource.GenerateDataSourceHashID("DatabaseBackupCancelManagementResource-", DatabaseBackupCancelManagementResource(), s.D)
72+
}
73+
74+
func (s *DatabaseBackupCancelManagementResourceCrud) Create() error {
75+
request := oci_database.CancelBackupRequest{}
76+
77+
if backupId, ok := s.D.GetOkExists("backup_id"); ok {
78+
err := s.getBackupInfo(backupId.(string))
79+
if err != nil {
80+
return fmt.Errorf("[ERROR] Could not get Backup for the : %v", err)
81+
}
82+
83+
backupType := string(s.Res.Type)
84+
85+
if !s.IsAutomaticBackup(backupType) {
86+
return fmt.Errorf("[ERROR] Cancel backup only supported on automatic backups")
87+
}
88+
89+
tmp := backupId.(string)
90+
request.BackupId = &tmp
91+
}
92+
93+
request.RequestMetadata.RetryPolicy = tfresource.GetRetryPolicy(s.DisableNotFoundRetries, "database")
94+
_, err := s.Client.CancelBackup(context.Background(), request)
95+
96+
if err != nil {
97+
log.Printf("Error occurred during cancel backup: %s", err)
98+
}
99+
trigger := s.D.Get("cancel_backup_trigger")
100+
s.D.Set("cancel_backup_trigger", trigger)
101+
val := s.D.Get("backup_id")
102+
s.D.Set("backup_id", val)
103+
104+
return nil
105+
}
106+
107+
func (s *DatabaseBackupCancelManagementResourceCrud) SetData() error {
108+
return nil
109+
}
110+
111+
func (s *DatabaseBackupCancelManagementResourceCrud) getBackupInfo(backupId string) error {
112+
request := oci_database.GetBackupRequest{}
113+
114+
request.BackupId = &backupId
115+
116+
response, err := s.Client.GetBackup(context.Background(), request)
117+
if err != nil {
118+
return err
119+
}
120+
121+
s.Res = &response.Backup
122+
123+
return nil
124+
}
125+
126+
func (s *DatabaseBackupCancelManagementResourceCrud) IsAutomaticBackup(backupType string) bool {
127+
// Only allowing cancelation of automatic backups
128+
return strings.EqualFold(backupType, "INCREMENTAL")
129+
}

internal/service/database/register_resource.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ func RegisterResource() {
1717
tfresource.RegisterResource("oci_database_autonomous_exadata_infrastructure", DatabaseAutonomousExadataInfrastructureResource())
1818
tfresource.RegisterResource("oci_database_autonomous_vm_cluster", DatabaseAutonomousVmClusterResource())
1919
tfresource.RegisterResource("oci_database_backup", DatabaseBackupResource())
20+
tfresource.RegisterResource("oci_database_backup_cancel_management", DatabaseBackupCancelManagementResource())
2021
tfresource.RegisterResource("oci_database_backup_destination", DatabaseBackupDestinationResource())
2122
tfresource.RegisterResource("oci_database_cloud_autonomous_vm_cluster", DatabaseCloudAutonomousVmClusterResource())
2223
tfresource.RegisterResource("oci_database_cloud_database_management", DatabaseCloudDatabaseManagementResource())

website/docs/d/database_autonomous_database.html.markdown

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,14 @@ The following attributes are exported:
108108
* `is_dedicated` - True if the database uses [dedicated Exadata infrastructure](https://docs.oracle.com/en/cloud/paas/autonomous-database/index.html).
109109
* `is_free_tier` - Indicates if this is an Always Free resource. The default value is false. Note that Always Free Autonomous Databases have 1 CPU and 20GB of memory. For Always Free databases, memory and CPU cannot be scaled.
110110
* `is_local_data_guard_enabled` - Indicates whether the Autonomous Database has local (in-region) Data Guard enabled. Not applicable to cross-region Autonomous Data Guard associations, or to Autonomous Databases using dedicated Exadata infrastructure or Exadata Cloud@Customer infrastructure.
111-
* `is_mtls_connection_required` - Indicates whether the Autonomous Database requires mTLS connections.
111+
* `is_mtls_connection_required` - Specifies if the Autonomous Database requires mTLS connections.
112+
113+
This may not be updated in parallel with any of the following: licenseModel, databaseEdition, cpuCoreCount, computeCount, maxCpuCoreCount, dataStorageSizeInTBs, whitelistedIps, openMode, permissionLevel, db-workload, privateEndpointLabel, nsgIds, customerContacts, dbVersion, scheduledOperations, dbToolsDetails, isLocalDataGuardEnabled, or isFreeTier.
114+
115+
Service Change: The default value of the isMTLSConnectionRequired attribute will change from true to false on July 1, 2023 in the following APIs:
116+
* CreateAutonomousDatabase
117+
* GetAutonomousDatabase
118+
* UpdateAutonomousDatabase Details: Prior to the July 1, 2023 change, the isMTLSConnectionRequired attribute default value was true. This applies to Autonomous Databases on shared Exadata infrastructure. Does this impact me? If you use or maintain custom scripts or Terraform scripts referencing the CreateAutonomousDatabase, GetAutonomousDatabase, or UpdateAutonomousDatabase APIs, you want to check, and possibly modify, the scripts for the changed default value of the attribute. Should you choose not to leave your scripts unchanged, the API calls containing this attribute will continue to work, but the default value will switch from true to false. How do I make this change? Using either Oracle Cloud Infrastructure SDKs or command line tools, update your custom scripts to explicitly set the isMTLSConnectionRequired attribute to true.
112119
* `is_preview` - Indicates if the Autonomous Database version is a preview version.
113120
* `is_reconnect_clone_enabled` - Indicates if the refreshable clone can be reconnected to its source database.
114121
* `is_refreshable_clone` - Indicates whether the Autonomous Database is a refreshable clone.

0 commit comments

Comments
 (0)