forked from hashicorp/terraform-provider-google
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for Google RuntimeConfig (hashicorp#315)
* Vendor runtimeconfig * Add support for RuntimeConfig config and variable resources This allows users to create/manage Google RuntimeConfig resources and variables. More information here: https://cloud.google.com/deployment-manager/runtime-configurator/ Closes hashicorp#236 * Remove typo * Use top-level declaration rather than init() * Cleanup testing-related code by using ConflictsWith Also adds better comments around how update works
- Loading branch information
Showing
12 changed files
with
6,555 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
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,146 @@ | ||
package google | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
|
||
"github.com/hashicorp/terraform/helper/schema" | ||
"google.golang.org/api/runtimeconfig/v1beta1" | ||
) | ||
|
||
var runtimeConfigFullName *regexp.Regexp = regexp.MustCompile("^projects/([^/]+)/configs/(.+)$") | ||
|
||
func resourceRuntimeconfigConfig() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceRuntimeconfigConfigCreate, | ||
Read: resourceRuntimeconfigConfigRead, | ||
Update: resourceRuntimeconfigConfigUpdate, | ||
Delete: resourceRuntimeconfigConfigDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
ValidateFunc: validateGCPName, | ||
}, | ||
|
||
"description": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"project": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceRuntimeconfigConfigCreate(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
project, err := getProject(d, config) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
name := d.Get("name").(string) | ||
fullName := resourceRuntimeconfigFullName(project, name) | ||
runtimeConfig := runtimeconfig.RuntimeConfig{ | ||
Name: fullName, | ||
} | ||
|
||
if val, ok := d.GetOk("description"); ok { | ||
runtimeConfig.Description = val.(string) | ||
} | ||
|
||
_, err = config.clientRuntimeconfig.Projects.Configs.Create("projects/"+project, &runtimeConfig).Do() | ||
|
||
if err != nil { | ||
return err | ||
} | ||
d.SetId(fullName) | ||
|
||
return nil | ||
} | ||
|
||
func resourceRuntimeconfigConfigRead(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
fullName := d.Id() | ||
runConfig, err := config.clientRuntimeconfig.Projects.Configs.Get(fullName).Do() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
project, name, err := resourceRuntimeconfigParseFullName(runConfig.Name) | ||
if err != nil { | ||
return err | ||
} | ||
// Check to see if project matches our current defined value - if it doesn't, we'll explicitly set it | ||
curProject, err := getProject(d, config) | ||
if err != nil { | ||
return err | ||
} | ||
if project != curProject { | ||
d.Set("project", project) | ||
} | ||
|
||
d.Set("name", name) | ||
d.Set("description", runConfig.Description) | ||
|
||
return nil | ||
} | ||
|
||
func resourceRuntimeconfigConfigUpdate(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
// Update works more like an 'overwrite' method - we build a new runtimeconfig.RuntimeConfig struct and it becomes | ||
// the new config. This means our Update logic looks an awful lot like Create (and hence, doesn't use | ||
// schema.ResourceData.hasChange()). | ||
fullName := d.Id() | ||
runtimeConfig := runtimeconfig.RuntimeConfig{ | ||
Name: fullName, | ||
} | ||
if v, ok := d.GetOk("description"); ok { | ||
runtimeConfig.Description = v.(string) | ||
} | ||
|
||
_, err := config.clientRuntimeconfig.Projects.Configs.Update(fullName, &runtimeConfig).Do() | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} | ||
|
||
func resourceRuntimeconfigConfigDelete(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(*Config) | ||
|
||
fullName := d.Id() | ||
|
||
_, err := config.clientRuntimeconfig.Projects.Configs.Delete(fullName).Do() | ||
if err != nil { | ||
return err | ||
} | ||
d.SetId("") | ||
return nil | ||
} | ||
|
||
// resourceRuntimeconfigFullName turns a given project and a 'short name' for a runtime config into a full name | ||
// (e.g. projects/my-project/configs/my-config). | ||
func resourceRuntimeconfigFullName(project, name string) string { | ||
return fmt.Sprintf("projects/%s/configs/%s", project, name) | ||
} | ||
|
||
// resourceRuntimeconfigParseFullName parses a full name (e.g. projects/my-project/configs/my-config) by parsing out the | ||
// project and the short name. Returns "", "", nil upon error. | ||
func resourceRuntimeconfigParseFullName(fullName string) (project, name string, err error) { | ||
matches := runtimeConfigFullName.FindStringSubmatch(fullName) | ||
if matches == nil { | ||
return "", "", fmt.Errorf("Given full name doesn't match expected regexp; fullname = '%s'", fullName) | ||
} | ||
return matches[1], matches[2], 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,159 @@ | ||
package google | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
"google.golang.org/api/runtimeconfig/v1beta1" | ||
) | ||
|
||
func TestAccRuntimeconfigConfig_basic(t *testing.T) { | ||
var runtimeConfig runtimeconfig.RuntimeConfig | ||
configName := fmt.Sprintf("runtimeconfig-test-%s", acctest.RandString(10)) | ||
description := "my test description" | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckRuntimeconfigConfigDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccRuntimeconfigConfig_basicDescription(configName, description), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckRuntimeConfigExists( | ||
"google_runtimeconfig_config.foobar", &runtimeConfig), | ||
testAccCheckRuntimeConfigDescription(&runtimeConfig, description), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccRuntimeconfig_update(t *testing.T) { | ||
var runtimeConfig runtimeconfig.RuntimeConfig | ||
configName := fmt.Sprintf("runtimeconfig-test-%s", acctest.RandString(10)) | ||
firstDescription := "my test description" | ||
secondDescription := "my updated test description" | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckRuntimeconfigConfigDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccRuntimeconfigConfig_basicDescription(configName, firstDescription), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckRuntimeConfigExists( | ||
"google_runtimeconfig_config.foobar", &runtimeConfig), | ||
testAccCheckRuntimeConfigDescription(&runtimeConfig, firstDescription), | ||
), | ||
}, { | ||
Config: testAccRuntimeconfigConfig_basicDescription(configName, secondDescription), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckRuntimeConfigExists( | ||
"google_runtimeconfig_config.foobar", &runtimeConfig), | ||
testAccCheckRuntimeConfigDescription(&runtimeConfig, secondDescription), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func TestAccRuntimeconfig_updateEmptyDescription(t *testing.T) { | ||
var runtimeConfig runtimeconfig.RuntimeConfig | ||
configName := fmt.Sprintf("runtimeconfig-test-%s", acctest.RandString(10)) | ||
description := "my test description" | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckRuntimeconfigConfigDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccRuntimeconfigConfig_basicDescription(configName, description), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckRuntimeConfigExists( | ||
"google_runtimeconfig_config.foobar", &runtimeConfig), | ||
testAccCheckRuntimeConfigDescription(&runtimeConfig, description), | ||
), | ||
}, { | ||
Config: testAccRuntimeconfigConfig_emptyDescription(configName), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckRuntimeConfigExists( | ||
"google_runtimeconfig_config.foobar", &runtimeConfig), | ||
testAccCheckRuntimeConfigDescription(&runtimeConfig, ""), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckRuntimeConfigDescription(runtimeConfig *runtimeconfig.RuntimeConfig, description string) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
if runtimeConfig.Description != description { | ||
return fmt.Errorf("On runtime config '%s', expected description '%s', but found '%s'", | ||
runtimeConfig.Name, description, runtimeConfig.Description) | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckRuntimeConfigExists(resourceName string, runtimeConfig *runtimeconfig.RuntimeConfig) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[resourceName] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", resourceName) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No ID is set") | ||
} | ||
|
||
config := testAccProvider.Meta().(*Config) | ||
|
||
found, err := config.clientRuntimeconfig.Projects.Configs.Get(rs.Primary.ID).Do() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
*runtimeConfig = *found | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckRuntimeconfigConfigDestroy(s *terraform.State) error { | ||
config := testAccProvider.Meta().(*Config) | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "google_runtimeconfig_config" { | ||
continue | ||
} | ||
|
||
_, err := config.clientRuntimeconfig.Projects.Configs.Get(rs.Primary.ID).Do() | ||
|
||
if err == nil { | ||
return fmt.Errorf("Runtimeconfig still exists") | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccRuntimeconfigConfig_basicDescription(name, description string) string { | ||
return fmt.Sprintf(` | ||
resource "google_runtimeconfig_config" "foobar" { | ||
name = "%s" | ||
description = "%s" | ||
}`, name, description) | ||
} | ||
|
||
func testAccRuntimeconfigConfig_emptyDescription(name string) string { | ||
return fmt.Sprintf(` | ||
resource "google_runtimeconfig_config" "foobar" { | ||
name = "%s" | ||
}`, name) | ||
} |
Oops, something went wrong.