-
Notifications
You must be signed in to change notification settings - Fork 263
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #134 from modular-magician/codegen-pr-912
Add the sql ssl (client) cert resource, sibling of TPG #2290.
- Loading branch information
1 parent
16e0766
commit a6a5a80
Showing
5 changed files
with
381 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
package google | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
"google.golang.org/api/sqladmin/v1beta4" | ||
) | ||
|
||
func resourceSqlSslCert() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceSqlSslCertCreate, | ||
Read: resourceSqlSslCertRead, | ||
Delete: resourceSqlSslCertDelete, | ||
|
||
SchemaVersion: 1, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"common_name": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"instance": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"cert": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"cert_serial_number": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"create_time": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"expiration_time": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"private_key": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
Sensitive: true, | ||
}, | ||
|
||
"server_ca_cert": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
|
||
"sha1_fingerprint": &schema.Schema{ | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceSqlSslCertCreate(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
project, err := getProject(d, config) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
instance := d.Get("instance").(string) | ||
commonName := d.Get("common_name").(string) | ||
|
||
sslCertsInsertRequest := &sqladmin.SslCertsInsertRequest{ | ||
CommonName: commonName, | ||
} | ||
|
||
mutexKV.Lock(instanceMutexKey(project, instance)) | ||
defer mutexKV.Unlock(instanceMutexKey(project, instance)) | ||
resp, err := config.clientSqlAdmin.SslCerts.Insert(project, instance, sslCertsInsertRequest).Do() | ||
if err != nil { | ||
return fmt.Errorf("Error, failed to insert "+ | ||
"ssl cert %s into instance %s: %s", commonName, instance, err) | ||
} | ||
|
||
err = sqladminOperationWait(config, resp.Operation, project, "Create Ssl Cert") | ||
if err != nil { | ||
return fmt.Errorf("Error, failure waiting for creation of %q "+ | ||
"in %q: %s", commonName, instance, err) | ||
} | ||
|
||
fingerprint := resp.ClientCert.CertInfo.Sha1Fingerprint | ||
d.SetId(fmt.Sprintf("%s/%s", instance, fingerprint)) | ||
d.Set("sha1_fingerprint", fingerprint) | ||
|
||
// The private key is only returned on the initial insert so set it here. | ||
d.Set("private_key", resp.ClientCert.CertPrivateKey) | ||
d.Set("server_ca_cert", resp.ServerCaCert.Cert) | ||
|
||
return resourceSqlSslCertRead(d, meta) | ||
} | ||
|
||
func resourceSqlSslCertRead(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
project, err := getProject(d, config) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
instance := d.Get("instance").(string) | ||
commonName := d.Get("common_name").(string) | ||
fingerprint := d.Get("sha1_fingerprint").(string) | ||
|
||
sslCerts, err := config.clientSqlAdmin.SslCerts.Get(project, instance, fingerprint).Do() | ||
if err != nil { | ||
return handleNotFoundError(err, d, fmt.Sprintf("SQL Ssl Cert %q in instance %q", commonName, instance)) | ||
} | ||
|
||
if sslCerts == nil { | ||
log.Printf("[WARN] Removing SQL Ssl Cert %q because it's gone", commonName) | ||
d.SetId("") | ||
|
||
return nil | ||
} | ||
|
||
d.Set("instance", sslCerts.Instance) | ||
d.Set("sha1_fingerprint", sslCerts.Sha1Fingerprint) | ||
d.Set("common_name", sslCerts.CommonName) | ||
d.Set("cert", sslCerts.Cert) | ||
d.Set("cert_serial_number", sslCerts.CertSerialNumber) | ||
d.Set("create_time", sslCerts.CreateTime) | ||
d.Set("expiration_time", sslCerts.ExpirationTime) | ||
|
||
d.SetId(fmt.Sprintf("%s/%s", instance, fingerprint)) | ||
return nil | ||
} | ||
|
||
func resourceSqlSslCertDelete(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
project, err := getProject(d, config) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
instance := d.Get("instance").(string) | ||
commonName := d.Get("common_name").(string) | ||
fingerprint := d.Get("sha1_fingerprint").(string) | ||
|
||
mutexKV.Lock(instanceMutexKey(project, instance)) | ||
defer mutexKV.Unlock(instanceMutexKey(project, instance)) | ||
op, err := config.clientSqlAdmin.SslCerts.Delete(project, instance, fingerprint).Do() | ||
|
||
if err != nil { | ||
return fmt.Errorf("Error, failed to delete "+ | ||
"ssl cert %q in instance %q: %s", commonName, | ||
instance, err) | ||
} | ||
|
||
err = sqladminOperationWait(config, op, project, "Delete Ssl Cert") | ||
|
||
if err != nil { | ||
return fmt.Errorf("Error, failure waiting for deletion of ssl cert %q "+ | ||
"in %q: %s", commonName, instance, err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package google | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccSqlClientCert_mysql(t *testing.T) { | ||
t.Parallel() | ||
|
||
instance := acctest.RandomWithPrefix("i") | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccSqlClientCertDestroy, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testGoogleSqlClientCert_mysql(instance), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckGoogleSqlClientCertExists("google_sql_ssl_cert.cert1"), | ||
testAccCheckGoogleSqlClientCertExists("google_sql_ssl_cert.cert2"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccSqlClientCert_postgres(t *testing.T) { | ||
t.Parallel() | ||
|
||
instance := acctest.RandomWithPrefix("i") | ||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccSqlClientCertDestroy, | ||
Steps: []resource.TestStep{ | ||
resource.TestStep{ | ||
Config: testGoogleSqlClientCert_postgres(instance), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckGoogleSqlClientCertExists("google_sql_ssl_cert.cert"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckGoogleSqlClientCertExists(n string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
config := testAccProvider.Meta().(*Config) | ||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Resource not found: %s", n) | ||
} | ||
|
||
instance := rs.Primary.Attributes["instance"] | ||
fingerprint := rs.Primary.Attributes["sha1_fingerprint"] | ||
sslClientCert, err := config.clientSqlAdmin.SslCerts.Get(config.Project, instance, fingerprint).Do() | ||
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
if sslClientCert.Instance == instance && sslClientCert.Sha1Fingerprint == fingerprint { | ||
return nil | ||
} | ||
|
||
return fmt.Errorf("Not found: %s: %s", n, err) | ||
} | ||
} | ||
|
||
func testAccSqlClientCertDestroy(s *terraform.State) error { | ||
for _, rs := range s.RootModule().Resources { | ||
config := testAccProvider.Meta().(*Config) | ||
if rs.Type != "google_sql_ssl_cert" { | ||
continue | ||
} | ||
|
||
fingerprint := rs.Primary.Attributes["sha1_fingerprint"] | ||
instance := rs.Primary.Attributes["instance"] | ||
sslCert, _ := config.clientSqlAdmin.SslCerts.Get(config.Project, instance, fingerprint).Do() | ||
|
||
commonName := rs.Primary.Attributes["common_name"] | ||
if sslCert != nil { | ||
return fmt.Errorf("Client cert %q still exists, should have been destroyed", commonName) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testGoogleSqlClientCert_mysql(instance string) string { | ||
return fmt.Sprintf(` | ||
resource "google_sql_database_instance" "instance" { | ||
name = "%s" | ||
region = "us-central" | ||
settings { | ||
tier = "D0" | ||
} | ||
} | ||
resource "google_sql_ssl_cert" "cert1" { | ||
common_name = "cert1" | ||
instance = "${google_sql_database_instance.instance.name}" | ||
} | ||
resource "google_sql_ssl_cert" "cert2" { | ||
common_name = "cert2" | ||
instance = "${google_sql_database_instance.instance.name}" | ||
} | ||
`, instance) | ||
} | ||
|
||
func testGoogleSqlClientCert_postgres(instance string) string { | ||
return fmt.Sprintf(` | ||
resource "google_sql_database_instance" "instance" { | ||
name = "%s" | ||
region = "us-central1" | ||
database_version = "POSTGRES_9_6" | ||
settings { | ||
tier = "db-f1-micro" | ||
} | ||
} | ||
resource "google_sql_ssl_cert" "cert" { | ||
common_name = "cert" | ||
instance = "${google_sql_database_instance.instance.name}" | ||
} | ||
`, instance) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--- | ||
layout: "google" | ||
page_title: "Google: google_sql_ssl_cert" | ||
sidebar_current: "docs-google-sql-ssl-cert" | ||
description: |- | ||
Creates a new SQL Ssl Cert in Google Cloud SQL. | ||
--- | ||
|
||
# google\_client\_cert | ||
|
||
Creates a new Google SQL SSL Cert on a Google SQL Instance. For more information, see the [official documentation](https://cloud.google.com/sql/), or the [JSON API](https://cloud.google.com/sql/docs/mysql/admin-api/v1beta4/sslCerts). | ||
|
||
~> **Note:** All arguments including the private key will be stored in the raw state as plain-text. | ||
[Read more about sensitive data in state](/docs/state/sensitive-data.html). | ||
|
||
## Example Usage | ||
|
||
Example creating a SQL Client Certificate. | ||
|
||
```hcl | ||
resource "google_sql_database_instance" "master" { | ||
name = "master-instance" | ||
settings { | ||
tier = "D0" | ||
} | ||
} | ||
resource "google_sql_ssl_cert" "client_cert" { | ||
common_name = "client-name" | ||
instance = "${google_sql_database_instance.master.name}" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `instance` - (Required) The name of the Cloud SQL instance. Changing this | ||
forces a new resource to be created. | ||
|
||
* `common_name` - (Required) The common name to be used in the certificate to identify the | ||
client. Constrained to [a-zA-Z.-_ ]+. Changing this forces a new resource to be created. | ||
|
||
|
||
## Attributes Reference | ||
|
||
In addition to the arguments listed above, the following computed attributes are | ||
exported: | ||
|
||
* `sha1_fingerprint` - The SHA1 Fingerprint of the certificate. | ||
* `private_key` - The private key associated with the client certificate. | ||
* `server_ca_cert` - The CA cert of the server this client cert was generated from. | ||
* `cert` - The actual certificate data for this client certificate. | ||
* `cert_serial_number` - The serial number extracted from the certificate data. | ||
* `create_time` - The time when the certificate was created in RFC 3339 format, | ||
for example 2012-11-15T16:19:00.094Z. | ||
* `expiration_time` - The time when the certificate expires in RFC 3339 format, | ||
for example 2012-11-15T16:19:00.094Z. | ||
|
||
## Import | ||
|
||
Since the contents of the certificate cannot be accessed after its creation, this resource cannot be imported. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters