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 support for setting labels to google_project #383

Merged
merged 1 commit into from
Sep 14, 2017
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
22 changes: 22 additions & 0 deletions google/resource_google_project.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ func resourceGoogleProject() *schema.Resource {
Type: schema.TypeString,
Optional: true,
},
"labels": &schema.Schema{
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
},
}
}
Expand All @@ -95,6 +101,10 @@ func resourceGoogleProjectCreate(d *schema.ResourceData, meta interface{}) error
},
}

if _, ok := d.GetOk("labels"); ok {
project.Labels = expandLabels(d)
}

op, err := config.clientResourceManager.Projects.Create(project).Do()
if err != nil {
return fmt.Errorf("Error creating project %s (%s): %s.", project.ProjectId, project.Name, err)
Expand Down Expand Up @@ -142,6 +152,7 @@ func resourceGoogleProjectRead(d *schema.ResourceData, meta interface{}) error {
d.Set("project_id", pid)
d.Set("number", strconv.FormatInt(int64(p.ProjectNumber), 10))
d.Set("name", p.Name)
d.Set("labels", p.Labels)

if p.Parent != nil {
d.Set("org_id", p.Parent.Id)
Expand Down Expand Up @@ -213,6 +224,17 @@ func resourceGoogleProjectUpdate(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("Error updating billing account %q for project %q: %v", name, prefixedProject(pid), err)
}
}

// Project Labels have changed
if ok := d.HasChange("labels"); ok {
p.Labels = expandLabels(d)

// Do Update on project
p, err = config.clientResourceManager.Projects.Update(p.ProjectId, p).Do()
if err != nil {
return fmt.Errorf("Error updating project %q: %s", p.Name, err)
}
}
return nil
}

Expand Down
162 changes: 162 additions & 0 deletions google/resource_google_project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package google
import (
"fmt"
"os"
"reflect"
"strconv"
"strings"
"testing"

"github.com/davecgh/go-spew/spew"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
Expand Down Expand Up @@ -76,6 +79,23 @@ func TestAccGoogleProject_createBilling(t *testing.T) {
})
}

// Test that a Project resource can be created with labels
func TestAccGoogleProject_createLabels(t *testing.T) {
pid := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccGoogleProject_createLabels(pid, pname, org, "test", "that"),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleProjectHasLabels("google_project.acceptance", pid, map[string]string{"test": "that"}),
),
},
},
})
}

// Test that a Project resource can be created and updated
// with billing account information
func TestAccGoogleProject_updateBilling(t *testing.T) {
Expand Down Expand Up @@ -154,6 +174,48 @@ func TestAccGoogleProject_merge(t *testing.T) {
})
}

// Test that a Project resource can be updated with labels
func TestAccGoogleProject_updateLabels(t *testing.T) {
pid := "terraform-" + acctest.RandString(10)
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
// create project without labels
{
Config: testAccGoogleProject_create(pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleProjectExists("google_project.acceptance", pid),
),
},
// update project with labels
{
Config: testAccGoogleProject_updateLabels(pid, pname, org, map[string]string{"label": "label-value"}),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleProjectExists("google_project.acceptance", pid),
testAccCheckGoogleProjectHasLabels("google_project.acceptance", pid, map[string]string{"label": "label-value"}),
),
},
// update project with other labels
{
Config: testAccGoogleProject_updateLabels(pid, pname, org, map[string]string{"empty-label": ""}),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleProjectExists("google_project.acceptance", pid),
testAccCheckGoogleProjectHasLabels("google_project.acceptance", pid, map[string]string{"empty-label": ""}),
),
},
// update project delete labels
{
Config: testAccGoogleProject_create(pid, pname, org),
Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleProjectExists("google_project.acceptance", pid),
testAccCheckGoogleProjectHasNoLabels("google_project.acceptance", pid),
),
},
},
})
}

func testAccCheckGoogleProjectExists(r, pid string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[r]
Expand Down Expand Up @@ -212,6 +274,77 @@ func testAccCheckGoogleProjectHasMoreBindingsThan(pid string, count int) resourc
}
}

func testAccCheckGoogleProjectHasLabels(r, pid string, expected map[string]string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[r]
if !ok {
return fmt.Errorf("Not found: %s", r)
}

// State should have the same number of labels
if rs.Primary.Attributes["labels.%"] != strconv.Itoa(len(expected)) {
return fmt.Errorf("Expected %d labels, got %s", len(expected), rs.Primary.Attributes["labels.%"])
}

// Actual value in API should match state and expected
config := testAccProvider.Meta().(*Config)

found, err := config.clientResourceManager.Projects.Get(pid).Do()
if err != nil {
return err
}

actual := found.Labels
if !reflect.DeepEqual(actual, expected) {
// Determine only the different attributes
for k, v := range expected {
if av, ok := actual[k]; ok && v == av {
delete(expected, k)
delete(actual, k)
}
}

spewConf := spew.NewDefaultConfig()
spewConf.SortKeys = true
return fmt.Errorf(
"Labels not equivalent. Difference is shown below. Top is actual, bottom is expected."+
"\n\n%s\n\n%s",
spewConf.Sdump(actual), spewConf.Sdump(expected),
)
}
return nil
}
}

func testAccCheckGoogleProjectHasNoLabels(r, pid string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[r]
if !ok {
return fmt.Errorf("Not found: %s", r)
}

// State should have zero labels
if rs.Primary.Attributes["labels.%"] != "0" {
return fmt.Errorf("Expected 0 labels, got %s", rs.Primary.Attributes["labels.%"])
}

// Actual value in API should match state and expected
config := testAccProvider.Meta().(*Config)

found, err := config.clientResourceManager.Projects.Get(pid).Do()
if err != nil {
return err
}

spewConf := spew.NewDefaultConfig()
spewConf.SortKeys = true
if found.Labels != nil {
return fmt.Errorf("Labels should be empty. Actual \n%s", spewConf.Sdump(found.Labels))
}
return nil
}
}

func testAccGoogleProject_toMerge(pid, name, org string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
Expand Down Expand Up @@ -244,6 +377,35 @@ resource "google_project" "acceptance" {
}`, pid, name, org)
}

func testAccGoogleProject_createLabels(pid, name, org, key, value string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
project_id = "%s"
name = "%s"
org_id = "%s"
labels {
"%s" = "%s"
}
}`, pid, name, org, key, value)
}

func testAccGoogleProject_updateLabels(pid, name, org string, labels map[string]string) string {
r := fmt.Sprintf(`
resource "google_project" "acceptance" {
project_id = "%s"
name = "%s"
org_id = "%s"
labels {`, pid, name, org)

l := ""
for key, value := range labels {
l += fmt.Sprintf("%q = %q\n", key, value)
}

l += fmt.Sprintf("}\n}")
return r + l
}

func skipIfEnvNotSet(t *testing.T, envs ...string) {
for _, k := range envs {
if os.Getenv(k) == "" {
Expand Down
2 changes: 2 additions & 0 deletions website/docs/r/google_project.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ The following arguments are supported:
This argument is no longer supported, and will be removed in a future version
of Terraform. It should be replaced with a `google_project_iam_policy` resource.

* `labels` - (Optional) A set of key/value label pairs to assign to the project.

## Attributes Reference

In addition to the arguments listed above, the following computed attributes are
Expand Down