Skip to content

Commit

Permalink
Add google_cloud_identity_group_lookup data source (#9163) (#16296)
Browse files Browse the repository at this point in the history
* Add initial version of `google_cloud_identity_group_lookup` data source and acceptance test

* Add `google_cloud_identity_group_lookup` to provider

* Add dependency

* Update `google_cloud_identity_group_lookup` test to check that the group name matches between resource and datasource

* Add documentation for `google_cloud_identity_group_lookup` data source

* Fix docs description, add link to EntityKey description

* Add second test case testing `google_cloud_identity_group_lookup` for lookup via alias

* Format imports

* Fix mixture of tabs/spaces in config strings for cloud identity group tests

* Remove unneeded data source from acc test step

* Remove inter-datasource comparison check
[upstream:91231a153e48efbc72d28a58447cafc0ba56042d]

Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
modular-magician authored Oct 18, 2023
1 parent c5a83a0 commit 9a0fec7
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .changelog/9163.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-datasource
`google_cloud_identity_group_lookup`
```
1 change: 1 addition & 0 deletions google/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -801,6 +801,7 @@ func DatasourceMapWithErrors() (map[string]*schema.Resource, error) {
"google_cloudfunctions2_function": cloudfunctions2.DataSourceGoogleCloudFunctions2Function(),
"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_cloud_run_v2_job": cloudrunv2.DataSourceGoogleCloudRunV2Job(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
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,102 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
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,9 +4,10 @@ package cloudidentity

import (
"fmt"
"time"

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

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"google.golang.org/api/cloudidentity/v1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,7 +297,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 @@ -311,7 +311,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 @@ -327,7 +327,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 @@ -31,6 +31,7 @@ func TestAccCloudIdentityGroup(t *testing.T) {
"membership_user": testAccCloudIdentityGroupMembership_cloudIdentityGroupMembershipUserExampleTest,
"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 @@ -125,7 +126,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
51 changes: 51 additions & 0 deletions website/docs/d/cloud_identity_group_lookup.html.markdown
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.

0 comments on commit 9a0fec7

Please sign in to comment.