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 google_cloud_identity_group_lookup data source #9163

Merged
merged 11 commits into from
Oct 18, 2023
Merged
1 change: 1 addition & 0 deletions mmv1/third_party/terraform/provider/provider.go.erb
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@ func DatasourceMapWithErrors() (map[string]*schema.Resource, error) {
<% end -%>
"google_cloud_identity_groups": cloudidentity.DataSourceGoogleCloudIdentityGroups(),
"google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(),
"google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(),
"google_cloud_run_locations": cloudrun.DataSourceGoogleCloudRunLocations(),
"google_cloud_run_service": cloudrun.DataSourceGoogleCloudRunService(),
"google_composer_environment": composer.DataSourceGoogleComposerEnvironment(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<% autogen_exception -%>
package cloudidentity

import (
"fmt"
"time"

"github.com/hashicorp/terraform-provider-google/google/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"

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

func DataSourceGoogleCloudIdentityGroupLookup() *schema.Resource {

return &schema.Resource{
Read: dataSourceGoogleCloudIdentityGroupLookupRead,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
Description: `The [resource name](https://cloud.google.com/apis/design/resource_names) of the looked-up Group.`,
},
"group_key": {
Type: schema.TypeList,
MaxItems: 1,
Required: true,
Description: `The EntityKey of the Group to lookup. A unique identifier for an entity in the Cloud Identity Groups API.
An entity can represent either a group with an optional namespace or a user without a namespace.
The combination of id and namespace must be unique; however, the same id can be used with different namespaces.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Required: true,
Description: `The ID of the entity. For Google-managed entities, the id should be the email address of an existing group or user.
For external-identity-mapped entities, the id must be a string conforming to the Identity Source's requirements.
Must be unique within a namespace.`,
},
"namespace": {
Type: schema.TypeString,
Optional: true,
Description: `The namespace in which the entity exists. If not specified, the EntityKey represents a Google-managed entity such as a Google user or a Google Group.
If specified, the EntityKey represents an external-identity-mapped group. The namespace must correspond to an identity source created in Admin Console and must be in the form of identitysources/{identity_source}.`,
},
},
},
},
},
}
}

func dataSourceGoogleCloudIdentityGroupLookupRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*transport_tpg.Config)
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
if err != nil {
return err
}

gkId, ok := d.GetOk("group_key.0.id")
if !ok {
return fmt.Errorf("error getting group key id")
}
id := gkId.(string)

groupsLookupCall := config.NewCloudIdentityClient(userAgent).Groups.Lookup().GroupKeyId(id)

gkNamespace, ok := d.GetOk("group_key.0.namespace")
if ok {
// If optional namespace argument provided, add as param to API call
namespace := gkNamespace.(string)
groupsLookupCall = groupsLookupCall.GroupKeyNamespace(namespace)
}

if config.UserProjectOverride {
billingProject := ""
// err may be nil - project isn't required for this resource
if project, err := tpgresource.GetProject(d, config); err == nil {
billingProject = project
}

// err == nil indicates that the billing_project value was found
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
billingProject = bp
}

if billingProject != "" {
groupsLookupCall.Header().Set("X-Goog-User-Project", billingProject)
}
}
resp, err := groupsLookupCall.Do()
if err != nil {
return transport_tpg.HandleDataSourceNotFoundError(err, d, fmt.Sprintf("CloudIdentityGroups %q", d.Id()), "Groups")
}

if err := d.Set("name", resp.Name); err != nil {
return fmt.Errorf("error setting group lookup name: %s", err)
}
d.SetId(time.Now().UTC().String())
return nil
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package cloudidentity_test

import (
"regexp"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-provider-google/google/acctest"
"github.com/hashicorp/terraform-provider-google/google/envvar"
)

func testAccDataSourceCloudIdentityGroupLookup_basicTest(t *testing.T) {

context := map[string]interface{}{
"org_domain": envvar.GetTestOrgDomainFromEnv(t),
"cust_id": envvar.GetTestCustIdFromEnv(t),
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
// Create group and look it up via its group key, i.e. email we set
Config: testAccCloudIdentityGroupLookupConfig_groupKeyLookup(context),
Check: resource.ComposeTestCheckFunc(
resource.TestMatchResourceAttr("data.google_cloud_identity_group_lookup.email",
"name", regexp.MustCompile("^groups/.*$")),
resource.TestCheckResourceAttrPair("data.google_cloud_identity_group_lookup.email", "name",
"google_cloud_identity_group.cloud_identity_group_basic", "name"),
),
},
{
// Look up group via an API-generated 'additional group key'
Config: testAccCloudIdentityGroupLookupConfig_additionalGroupKeyLookup(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair("data.google_cloud_identity_group_lookup.additional-groupkey", "name",
"google_cloud_identity_group.cloud_identity_group_basic", "name"),
),
},
},
})
}

func testAccCloudIdentityGroupLookupConfig_groupKeyLookup(context map[string]interface{}) string {
return acctest.Nprintf(`
# config matching testAccCloudIdentityGroup_cloudIdentityGroupsBasicExample
resource "google_cloud_identity_group" "cloud_identity_group_basic" {
display_name = "tf-test-my-identity-group%{random_suffix}"
initial_group_config = "WITH_INITIAL_OWNER"

parent = "customers/%{cust_id}"

group_key {
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}"
}

labels = {
"cloudidentity.googleapis.com/groups.discussion_forum" = ""
}
}

data "google_cloud_identity_group_lookup" "email" {
group_key {
id = google_cloud_identity_group.cloud_identity_group_basic.group_key[0].id
}
}
`, context)
}

func testAccCloudIdentityGroupLookupConfig_additionalGroupKeyLookup(context map[string]interface{}) string {
return acctest.Nprintf(`
# config matching testAccCloudIdentityGroup_cloudIdentityGroupsBasicExample
resource "google_cloud_identity_group" "cloud_identity_group_basic" {
display_name = "tf-test-my-identity-group%{random_suffix}"
initial_group_config = "WITH_INITIAL_OWNER"

parent = "customers/%{cust_id}"

group_key {
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}"
}

labels = {
"cloudidentity.googleapis.com/groups.discussion_forum" = ""
}
}

data "google_cloud_identity_group_lookup" "additional-groupkey" {
group_key {
# This value is an automatically created 'additionalGroupKeys' value
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}.test-google-a.com"
}
depends_on = [
google_cloud_identity_group.cloud_identity_group_basic,
]
}
`, context)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package cloudidentity
import (
"fmt"
"time"

"github.com/hashicorp/terraform-provider-google/google/tpgresource"
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ resource "google_cloud_identity_group" "group" {
parent = "customers/%{cust_id}"

group_key {
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}"
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}"
}

labels = {
Expand All @@ -310,7 +310,7 @@ resource "google_cloud_identity_group" "child-group" {
parent = "customers/%{cust_id}"

group_key {
id = "tf-test-my-identity-group%{random_suffix}-child@%{org_domain}"
id = "tf-test-my-identity-group%{random_suffix}-child@%{org_domain}"
}

labels = {
Expand All @@ -326,7 +326,7 @@ resource "google_cloud_identity_group_membership" "cloud_identity_group_membersh
}

roles {
name = "MEMBER"
name = "MEMBER"
}
}
`, context)
Expand Down Expand Up @@ -425,7 +425,7 @@ resource "google_cloud_identity_group" "group" {
parent = "customers/%{cust_id}"

group_key {
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}"
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}"
}

labels = {
Expand All @@ -439,7 +439,7 @@ resource "google_cloud_identity_group" "child-group" {
parent = "customers/%{cust_id}"

group_key {
id = "tf-test-my-identity-group%{random_suffix}-child@%{org_domain}"
id = "tf-test-my-identity-group%{random_suffix}-child@%{org_domain}"
}

labels = {
Expand All @@ -455,7 +455,7 @@ resource "google_cloud_identity_group_membership" "cloud_identity_group_membersh
}

roles {
name = "MEMBER"
name = "MEMBER"
}
}
`, context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ func TestAccCloudIdentityGroup(t *testing.T) {
<% end -%>
"data_source_basic": testAccDataSourceCloudIdentityGroups_basicTest,
"data_source_membership_basic": testAccDataSourceCloudIdentityGroupMemberships_basicTest,
"data_source_group_lookup": testAccDataSourceCloudIdentityGroupLookup_basicTest,
}

for name, tc := range testCases {
Expand Down Expand Up @@ -124,7 +125,7 @@ resource "google_cloud_identity_group" "cloud_identity_group_basic" {
parent = "customers/%{cust_id}"

group_key {
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}"
id = "tf-test-my-identity-group%{random_suffix}@%{org_domain}"
}

labels = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
subcategory: "Cloud Identity"
description: |-
Look up a Cloud Identity Group using its email and namespace.
---

# google_cloud_identity_group_lookup

Use this data source to look up the resource name of a Cloud Identity Group by its [EntityKey](https://cloud.google.com/identity/docs/reference/rest/v1/EntityKey), i.e. the group's email.

https://cloud.google.com/identity/docs/concepts/overview#groups

## Example Usage

```tf
data "google_cloud_identity_group_lookup" "group" {
group_key {
id = "my-group@example.com"
}
}
```

## Argument Reference

* `group_key` - (Required) The EntityKey of the Group to lookup. A unique identifier for an entity in the Cloud Identity Groups API.
An entity can represent either a group with an optional namespace or a user without a namespace.
The combination of id and namespace must be unique; however, the same id can be used with different namespaces. Structure is [documented below](#nested_group_key).

<a name="nested_group_key"></a>The `group_key` block supports:

* `id` -
(Required) The ID of the entity.
For Google-managed entities, the id is the email address of an existing group or user.
For external-identity-mapped entities, the id is a string conforming
to the Identity Source's requirements.

* `namespace` -
(Optional) The namespace in which the entity exists.
If not populated, the EntityKey represents a Google-managed entity
such as a Google user or a Google Group.
If populated, the EntityKey represents an external-identity-mapped group.
The namespace must correspond to an identity source created in Admin Console
and must be in the form of `identitysources/{identity_source_id}`.


## Attributes Reference

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

* `name` -
Resource name of the Group in the format: groups/{group_id}, where `group_id` is the unique ID assigned to the Group.