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

Add SQL Backup Run Datasource #2824

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
3 changes: 3 additions & 0 deletions .changelog/4352.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-datasource
`google_sql_backup_run`
```
75 changes: 75 additions & 0 deletions google-beta/bootstrap_utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"google.golang.org/api/cloudkms/v1"
cloudresourcemanager "google.golang.org/api/cloudresourcemanager/v1"
"google.golang.org/api/iam/v1"
sqladmin "google.golang.org/api/sqladmin/v1beta4"
)

var SharedKeyRing = "tftest-shared-keyring-1"
Expand Down Expand Up @@ -335,3 +336,77 @@ func BootstrapConfig(t *testing.T) *Config {
}
return config
}

// SQL Instance names are not reusable for a week after deletion
const SharedTestSQLInstanceName = "tf-bootstrap-do-not-delete"

// BootstrapSharedSQLInstanceBackupRun will return a shared SQL db instance that
// has a backup created for it.
func BootstrapSharedSQLInstanceBackupRun(t *testing.T) string {
project := getTestProjectFromEnv()

config := BootstrapConfig(t)
if config == nil {
return ""
}

log.Printf("[DEBUG] Getting shared test sql instance %s", SharedTestSQLInstanceName)

instance, err := config.NewSqlAdminClient(config.userAgent).Instances.Get(project, SharedTestSQLInstanceName).Do()
if err != nil {
if isGoogleApiErrorWithCode(err, 404) {
log.Printf("[DEBUG] SQL Instance %q not found, bootstrapping", SharedTestSQLInstanceName)
settings := &sqladmin.Settings{
Tier: "db-f1-micro",
}
instance = &sqladmin.DatabaseInstance{
Name: SharedTestSQLInstanceName,
Region: "us-central1",
Settings: settings,
DatabaseVersion: "POSTGRES_11",
}

var op *sqladmin.Operation
err = retryTimeDuration(func() (operr error) {
op, operr = config.NewSqlAdminClient(config.userAgent).Instances.Insert(project, instance).Do()
return operr
}, time.Duration(20)*time.Minute, isSqlOperationInProgressError)
if err != nil {
t.Fatalf("Error, failed to create instance %s: %s", instance.Name, err)
}
err = sqlAdminOperationWaitTime(config, op, project, "Create Instance", config.userAgent, time.Duration(20)*time.Minute)
if err != nil {
t.Fatalf("Error, failed to create instance %s: %s", instance.Name, err)
}
} else {
t.Fatalf("Unable to bootstrap SQL Instance. Cannot retrieve instance: %s", err)
}
}

res, err := config.NewSqlAdminClient(config.userAgent).BackupRuns.List(project, instance.Name).Do()
if err != nil {
t.Fatalf("Unable to bootstrap SQL Instance. Cannot retrieve backup list: %s", err)
}
backupsList := res.Items
if len(backupsList) == 0 {
log.Printf("[DEBUG] No backups found for %s, creating backup", SharedTestSQLInstanceName)
backupRun := &sqladmin.BackupRun{
Instance: instance.Name,
}

var op *sqladmin.Operation
err = retryTimeDuration(func() (operr error) {
op, operr = config.NewSqlAdminClient(config.userAgent).BackupRuns.Insert(project, instance.Name, backupRun).Do()
return operr
}, time.Duration(20)*time.Minute, isSqlOperationInProgressError)
if err != nil {
t.Fatalf("Error, failed to create instance backup: %s", err)
}
err = sqlAdminOperationWaitTime(config, op, project, "Backup Instance", config.userAgent, time.Duration(20)*time.Minute)
if err != nil {
t.Fatalf("Error, failed to create instance backup: %s", err)
}
}

return instance.Name
}
106 changes: 106 additions & 0 deletions google-beta/data_source_sql_backup_run.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package google

import (
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
sqladmin "google.golang.org/api/sqladmin/v1beta4"
)

func dataSourceSqlBackupRun() *schema.Resource {

return &schema.Resource{
Read: dataSourceSqlBackupRunRead,

Schema: map[string]*schema.Schema{
"backup_id": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: `The identifier for this backup run. Unique only for a specific Cloud SQL instance. If left empty and multiple backups exist for the instance, most_recent must be set to true.`,
},
"instance": {
Type: schema.TypeString,
Required: true,
Description: `Name of the database instance.`,
},
"location": {
Type: schema.TypeString,
Computed: true,
Description: `Location of the backups.`,
},
"start_time": {
Type: schema.TypeString,
Computed: true,
Description: `The time the backup operation actually started in UTC timezone in RFC 3339 format, for example 2012-11-15T16:19:00.094Z.`,
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: `The status of this run.`,
},
"most_recent": {
Type: schema.TypeBool,
Optional: true,
Description: `Toggles use of the most recent backup run if multiple backups exist for a Cloud SQL instance.`,
},
},
}
}

func dataSourceSqlBackupRunRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
}
project, err := getProject(d, config)
if err != nil {
return err
}

instance := d.Get("instance").(string)

var backup *sqladmin.BackupRun
if backupId, ok := d.GetOk("backup_id"); ok {
backup, err = config.NewSqlAdminClient(userAgent).BackupRuns.Get(project, instance, int64(backupId.(int))).Do()
if err != nil {
return err
}
} else {
res, err := config.NewSqlAdminClient(userAgent).BackupRuns.List(project, instance).Do()
if err != nil {
return err
}
backupsList := res.Items
if len(backupsList) == 0 {
return fmt.Errorf("No backups found for SQL Database Instance %s", instance)
} else if len(backupsList) > 1 {
mostRecent := d.Get("most_recent").(bool)
if !mostRecent {
return fmt.Errorf("Multiple SQL backup runs listed for Instance %s. Consider setting most_recent or specifying a backup_id", instance)
}
}
backup = backupsList[0]
}

if err := d.Set("backup_id", backup.Id); err != nil {
return fmt.Errorf("Error setting backup_id: %s", err)
}
if err := d.Set("location", backup.Location); err != nil {
return fmt.Errorf("Error setting location: %s", err)
}
if err := d.Set("start_time", backup.StartTime); err != nil {
return fmt.Errorf("Error setting start_time: %s", err)
}
if err := d.Set("status", backup.Status); err != nil {
return fmt.Errorf("Error setting status: %s", err)
}

id, err := replaceVars(d, config, "projects/{{project}}/instances/{{instance}}/backupRuns/{{backup_id}}")
if err != nil {
return fmt.Errorf("Error constructing id: %s", err)
}
d.SetId(id)
return nil
}
85 changes: 85 additions & 0 deletions google-beta/data_source_sql_backup_run_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package google

import (
"fmt"
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccDataSourceSqlBackupRun_basic(t *testing.T) {
// Sqladmin client
skipIfVcr(t)
t.Parallel()

instance := BootstrapSharedSQLInstanceBackupRun(t)

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccDataSourceSqlBackupRun_basic(instance),
Check: resource.TestMatchResourceAttr("data.google_sql_backup_run.backup", "status", regexp.MustCompile("SUCCESSFUL")),
},
},
})
}

func TestAccDataSourceSqlBackupRun_notFound(t *testing.T) {
// Sqladmin client
skipIfVcr(t)
t.Parallel()

context := map[string]interface{}{
"random_suffix": randString(t, 10),
}

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccSqlDatabaseInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccDataSourceSqlBackupRun_notFound(context),
ExpectError: regexp.MustCompile("No backups found for SQL Database Instance"),
},
},
})
}

func testAccDataSourceSqlBackupRun_basic(instance string) string {
return fmt.Sprintf(`
data "google_sql_backup_run" "backup" {
instance = "%s"
most_recent = true
}
`, instance)
}

func testAccDataSourceSqlBackupRun_notFound(context map[string]interface{}) string {
return Nprintf(`
resource "google_sql_database_instance" "instance" {
name = "tf-test-instance-%{random_suffix}"
database_version = "POSTGRES_11"
region = "us-central1"

settings {
tier = "db-f1-micro"
backup_configuration {
enabled = "false"
}
}

deletion_protection = false
}

data "google_sql_backup_run" "backup" {
instance = google_sql_database_instance.instance.name
most_recent = true
depends_on = [google_sql_database_instance.instance]
}
`, context)
}
1 change: 1 addition & 0 deletions google-beta/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -759,6 +759,7 @@ func Provider() *schema.Provider {
"google_service_account_key": dataSourceGoogleServiceAccountKey(),
"google_spanner_instance": dataSourceSpannerInstance(),
"google_sql_ca_certs": dataSourceGoogleSQLCaCerts(),
"google_sql_backup_run": dataSourceSqlBackupRun(),
"google_sql_database_instance": dataSourceSqlDatabaseInstance(),
"google_storage_bucket_object": dataSourceGoogleStorageBucketObject(),
"google_storage_bucket_object_content": dataSourceGoogleStorageBucketObjectContent(),
Expand Down
2 changes: 1 addition & 1 deletion google-beta/resource_dataflow_flex_template_job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
"google.golang.org/api/compute/v1"
compute "google.golang.org/api/compute/v1"
)

func TestAccDataflowFlexTemplateJob_basic(t *testing.T) {
Expand Down
44 changes: 44 additions & 0 deletions website/docs/d/sql_backup_run.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
subcategory: "Cloud SQL"
layout: "google"
page_title: "Google: google_sql_backup_run"
sidebar_current: "docs-google-datasource-sql-backup-run"
description: |-
Get a SQL backup run in Google Cloud SQL.
---

# google\_sql\_backup\_run

Use this data source to get information about a Cloud SQL instance backup run.

## Example Usage

```hcl
data "google_sql_backup_run" "backup" {
instance = google_sql_database_instance.master.name
most_recent = true
}
```

## Argument Reference

The following arguments are supported:

* `instance` - (required) The name of the instance the backup is taken from.

* `backup_id` - (optional) The identifier for this backup run. Unique only for a specific Cloud SQL instance.
If left empty and multiple backups exist for the instance, `most_recent` must be set to `true`.

* `most_recent` - (optional) Toggles use of the most recent backup run if multiple backups exist for a
Cloud SQL instance.

## Attributes Reference

In addition to the arguments listed above, the following attributes are exported:

* `location` - Location of the backups.

* `start_time` - The time the backup operation actually started in UTC timezone in RFC 3339 format, for
example 2012-11-15T16:19:00.094Z.

* `status` - The status of this run. Refer to [API reference](https://cloud.google.com/sql/docs/mysql/admin-api/rest/v1beta4/backupRuns#SqlBackupRunStatus) for possible status values.
4 changes: 4 additions & 0 deletions website/google.erb
Original file line number Diff line number Diff line change
Expand Up @@ -1196,6 +1196,10 @@
<a href="#">Data Sources</a>
<ul class="nav nav-auto-expand">

<li>
<a href="/docs/providers/google/d/sql_backup_run.html">google_sql_backup_run</a>
</li>

<li>
<a href="/docs/providers/google/d/sql_ca_certs.html">google_sql_ca_certs</a>
</li>
Expand Down