diff --git a/google/data_source_google_organization.go b/google/data_source_google_organization.go new file mode 100644 index 00000000000..4ea15e97553 --- /dev/null +++ b/google/data_source_google_organization.go @@ -0,0 +1,103 @@ +package google + +import ( + "fmt" + "net/http" + "strings" + + "github.com/hashicorp/terraform/helper/schema" + + "google.golang.org/api/cloudresourcemanager/v1" + "google.golang.org/api/googleapi" +) + +func dataSourceGoogleOrganization() *schema.Resource { + return &schema.Resource{ + Read: dataSourceOrganizationRead, + Schema: map[string]*schema.Schema{ + "domain": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ConflictsWith: []string{"organization"}, + }, + "organization": { + Type: schema.TypeString, + Optional: true, + ConflictsWith: []string{"domain"}, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "directory_customer_id": { + Type: schema.TypeString, + Computed: true, + }, + "create_time": { + Type: schema.TypeString, + Computed: true, + }, + "lifecycle_state": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceOrganizationRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + var organization *cloudresourcemanager.Organization + if v, ok := d.GetOk("domain"); ok { + filter := fmt.Sprintf("domain=%s", v.(string)) + resp, err := config.clientResourceManager.Organizations.Search(&cloudresourcemanager.SearchOrganizationsRequest{ + Filter: filter, + }).Do() + if err != nil { + return fmt.Errorf("Error reading organization: %s", err) + } + + if len(resp.Organizations) == 0 { + return fmt.Errorf("Organization not found: %s", v) + } + if len(resp.Organizations) > 1 { + return fmt.Errorf("More than one matching organization found") + } + + organization = resp.Organizations[0] + } else if v, ok := d.GetOk("organization"); ok { + resp, err := config.clientResourceManager.Organizations.Get(canonicalOrganizationName(v.(string))).Do() + if err != nil { + if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == http.StatusNotFound { + return fmt.Errorf("Organization not found: %s", v) + } + + return fmt.Errorf("Error reading organization: %s", err) + } + + organization = resp + } else { + return fmt.Errorf("one of domain or organization must be set") + } + + d.SetId(GetResourceNameFromSelfLink(organization.Name)) + d.Set("name", organization.Name) + d.Set("domain", organization.DisplayName) + d.Set("create_time", organization.CreationTime) + d.Set("lifecycle_state", organization.LifecycleState) + if organization.Owner != nil { + d.Set("directory_customer_id", organization.Owner.DirectoryCustomerId) + } + + return nil +} + +func canonicalOrganizationName(ba string) string { + if strings.HasPrefix(ba, "organizations/") { + return ba + } + + return "organizations/" + ba +} diff --git a/google/data_source_google_organization_test.go b/google/data_source_google_organization_test.go new file mode 100644 index 00000000000..6c422794d8d --- /dev/null +++ b/google/data_source_google_organization_test.go @@ -0,0 +1,77 @@ +package google + +import ( + "fmt" + "regexp" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccDataSourceGoogleOrganization_byFullName(t *testing.T) { + orgId := getTestOrgFromEnv(t) + name := "organizations/" + orgId + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckGoogleOrganization_byName(name), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.google_organization.org", "id", orgId), + resource.TestCheckResourceAttr("data.google_organization.org", "name", name), + ), + }, + }, + }) +} + +func TestAccDataSourceGoogleOrganization_byShortName(t *testing.T) { + orgId := getTestOrgFromEnv(t) + name := "organizations/" + orgId + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckGoogleOrganization_byName(orgId), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.google_organization.org", "id", orgId), + resource.TestCheckResourceAttr("data.google_organization.org", "name", name), + ), + }, + }, + }) +} + +func TestAccDataSourceGoogleOrganization_byDomain(t *testing.T) { + name := acctest.RandString(16) + ".com" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckGoogleOrganization_byDomain(name), + ExpectError: regexp.MustCompile("Organization not found: " + name), + }, + }, + }) +} + +func testAccCheckGoogleOrganization_byName(name string) string { + return fmt.Sprintf(` +data "google_organization" "org" { + organization = "%s" +}`, name) +} + +func testAccCheckGoogleOrganization_byDomain(name string) string { + return fmt.Sprintf(` +data "google_organization" "org" { + domain = "%s" +}`, name) +} diff --git a/google/provider.go b/google/provider.go index 78adb957d87..1c22e4bd20f 100644 --- a/google/provider.go +++ b/google/provider.go @@ -77,6 +77,7 @@ func Provider() terraform.ResourceProvider { "google_active_folder": dataSourceGoogleActiveFolder(), "google_iam_policy": dataSourceGoogleIamPolicy(), "google_kms_secret": dataSourceGoogleKmsSecret(), + "google_organization": dataSourceGoogleOrganization(), "google_storage_object_signed_url": dataSourceGoogleSignedUrl(), }, diff --git a/website/docs/d/google_organization.html.markdown b/website/docs/d/google_organization.html.markdown new file mode 100644 index 00000000000..3f9d63721b7 --- /dev/null +++ b/website/docs/d/google_organization.html.markdown @@ -0,0 +1,43 @@ +--- +layout: "google" +page_title: "Google: google_organization" +sidebar_current: "docs-google-datasource-organization" +description: |- + Get information about a Google Cloud Organization. +--- + +# google\_organization + +Use this data source to get information about a Google Cloud Organization. + +```hcl +data "google_organization" "org" { + domain = "example.com" +} + +resource "google_folder" "sales" { + display_name = "Sales" + parent = "${data.google_organization.org.name}" +} +``` + +## Argument Reference + +The arguments of this data source act as filters for querying the available Organizations. +The given filters must match exactly one Organizations whose data will be exported as attributes. +The following arguments are supported: + +* `organization` (Optional) - The name of the Organization in the form `{organization_id}` or `organizations/{organization_id}`. +* `domain` (Optional) - The domain name of the Organization. + +~> **NOTE:** One of `organization` or `domain` must be specified. + +## Attributes Reference + +The following additional attributes are exported: + +* `id` - The Organization ID. +* `name` - The resource name of the Organization in the form `organizations/{organization_id}`. +* `directory_customer_id` - The Google for Work customer ID of the Organization. +* `create_time` - Timestamp when the Organization was created. A timestamp in RFC3339 UTC "Zulu" format, accurate to nanoseconds. Example: "2014-10-02T15:01:23.045123456Z". +* `lifecycle_state` - The Organization's current lifecycle state. diff --git a/website/google.erb b/website/google.erb index 8effbbd4046..1e2009321dc 100644 --- a/website/google.erb +++ b/website/google.erb @@ -64,6 +64,9 @@ > google_kms_secret + > + google_organization + > google_storage_object_signed_url