Skip to content
Open
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
2 changes: 1 addition & 1 deletion RESOURCES.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ The overall status of each resource or data source is captured in this document
| `github_dependabot_public_key` | ⚠️ | ✅ | ❓ | ❓ | ❓ | ❓ |
| `github_dependabot_secrets` | ⚠️ | ✅ | ❓ | ❓ | ❓ | ❓ |
| `github_enterprise` | ⚠️ | ✅ | ❓ | ❓ | ❓ | ❓ |
| `github_external_groups` | ⚠️ | ✅ | | | | |
| `github_external_groups` | | ✅ | | | | |
| `github_ip_ranges` | ⚠️ | ✅ | ❓ | ❓ | ❓ | ❓ |
| `github_issue_labels` | ⚠️ | ✅ | ❓ | ❓ | ❓ | ❓ |
| `github_membership` | ⚠️ | ✅ | ❓ | ❓ | ❓ | ❓ |
Expand Down
57 changes: 39 additions & 18 deletions docs/data-sources/external_groups.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,58 @@
---
page_title: "github_external_groups (Data Source) - GitHub"
subcategory: ""
description: |-
Retrieve external groups belonging to an organization.
Data source to list all external groups in an organization.
---

# github_external_groups (Data Source)

Use this data source to retrieve external groups belonging to an organization.
Data source to list all external groups in an organization.

## Example Usage

```terraform
data "github_external_groups" "example_external_groups" {}
data "github_external_groups" "example" {}
```

locals {
local_groups = data.github_external_groups.example_external_groups
}
<!--
## Schema

output "groups" {
value = local.local_groups
}
```
### Optional

## Argument Reference
- `display_name_filter` (String) Filter external groups by display name.

N/A. This resource will retrieve all the external groups belonging to an organization.
### Read-Only

## Attributes Reference
- `external_groups` (List of Object) List of external groups in the organization. (see [below for nested schema](#nestedatt--external_groups))
- `id` (String) The ID of this resource.

- `external_groups` - an array of external groups belonging to the organization. Each group consists of the fields documented below.
<a id="nestedatt--external_groups"></a>
### Nested Schema for `external_groups`

---
Read-Only:

- `group_id` (Number)
- `group_name` (String)
- `updated_at` (String)
-->

## Schema

### Optional

- `display_name_filter` (String) Filter external groups by display name.

### Read-Only

- `external_groups` (List of Object) List of external groups in the organization. (see [below for nested schema](#nestedatt--external_groups))
- `id` (String) The ID of this resource.

<a id="nestedatt--external_groups"></a>
### Nested Schema for `external_groups`

Read-Only:

- `group_id` - the ID of the group.
- `group_name` - the name of the group.
- `updated_at` - the date the group was last updated.
- `group_id` (Number) ID of the external group.
- `group_name` (String) Name of the external group.
- `updated_at` (String) Timestamp of the last update to the external group.
9 changes: 0 additions & 9 deletions examples/data-sources/external_groups/example_1.tf

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data "github_external_groups" "example" {}
5 changes: 4 additions & 1 deletion github/acc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,10 @@ type testAccConfig struct {
testExternalUser2 string

// Enterprise test configuration
testEnterpriseEMUGroupId int
testEnterpriseEMUGroupId int
testExternalGroup1ID int
testExternalGroup1DisplayName string
testExternalGroup2ID int

// Test options
testAdvancedSecurity bool
Expand Down
84 changes: 47 additions & 37 deletions github/data_source_github_external_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package github

import (
"context"
"encoding/json"
"fmt"

"github.com/google/go-github/v89/github"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
Expand All @@ -13,23 +11,33 @@ import (
func dataSourceGithubExternalGroups() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceGithubExternalGroupsRead,
Description: "Data source to list all external groups in an organization.",
Schema: map[string]*schema.Schema{
"display_name_filter": {
Description: "Filter external groups by display name.",
Type: schema.TypeString,
Optional: true,
},
"external_groups": {
Type: schema.TypeList,
Computed: true,
Description: "List of external groups in the organization.",
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"group_id": {
Type: schema.TypeInt,
Computed: true,
Description: "ID of the external group.",
Type: schema.TypeInt,
Computed: true,
},
"group_name": {
Type: schema.TypeString,
Computed: true,
Description: "Name of the external group.",
Type: schema.TypeString,
Computed: true,
},
"updated_at": {
Type: schema.TypeString,
Computed: true,
Description: "Timestamp of the last update to the external group.",
Type: schema.TypeString,
Computed: true,
},
},
},
Expand All @@ -38,48 +46,50 @@ func dataSourceGithubExternalGroups() *schema.Resource {
}
}

func dataSourceGithubExternalGroupsRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics {
err := checkOrganization(meta)
if err != nil {
func dataSourceGithubExternalGroupsRead(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnostics {
meta, _ := m.(*Owner)

if err := checkOrganization(meta); err != nil {
return diag.FromErr(err)
}
client := meta.(*Owner).v3client
orgName := meta.(*Owner).name

opts := &github.ListExternalGroupsOptions{}

externalGroups := new(github.ExternalGroupList)
var filter *string
if v, ok := d.GetOk("display_name_filter"); ok {
s, _ := v.(string)
filter = &s
}

for {
groups, resp, err := client.Teams.ListExternalGroups(ctx, orgName, opts)
groups := make([]map[string]any, 0)
for group, err := range meta.v3client.Teams.ListExternalGroupsIter(ctx, meta.name, &github.ListExternalGroupsOptions{DisplayName: filter, ListOptions: github.ListOptions{PerPage: maxPerPage}}) {
if err != nil {
return diag.FromErr(err)
}

externalGroups.Groups = append(externalGroups.Groups, groups.Groups...)

if resp.NextPage == 0 {
break
g := map[string]any{
"group_id": group.GetGroupID(),
"group_name": group.GetGroupName(),
"updated_at": group.GetUpdatedAt().String(),
}
opts.Page = resp.NextPage
}

// convert to JSON in order to martial to format we can return
jsonGroups, err := json.Marshal(externalGroups.Groups)
if err != nil {
return diag.FromErr(err)
groups = append(groups, g)
}

groupsState := make([]map[string]any, 0)
err = json.Unmarshal(jsonGroups, &groupsState)
if err != nil {
return diag.FromErr(err)
var id string
if filter != nil {
s, err := buildID(meta.name, *filter)
if err != nil {
return diag.FromErr(err)
}
id = s
} else {
id = meta.name
}

if err := d.Set("external_groups", groupsState); err != nil {
return diag.FromErr(err)
d.SetId(id)

if err := d.Set("external_groups", groups); err != nil {
return diag.Errorf("error setting external_groups: %v", err)
}

d.SetId(fmt.Sprintf("/orgs/%v/external-groups", orgName))
return nil
}
82 changes: 82 additions & 0 deletions github/data_source_github_external_groups_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package github

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/knownvalue"
"github.com/hashicorp/terraform-plugin-testing/statecheck"
"github.com/hashicorp/terraform-plugin-testing/tfjsonpath"
)

func TestAccDataSourceGithubExternalGroups(t *testing.T) {
t.Parallel()

if testAccConf.authMode != enterprise && !testAccConf.enterpriseIsEMU {
t.Skip("Skipping as test mode is not enterprise using EMU")
}

t.Run("queries_all_external_groups", func(t *testing.T) {
t.Parallel()

if testAccConf.testExternalGroup1ID == 0 {
t.Skip("Skipping as no external groups are configured for the test organization")
}

groupID := int32(testAccConf.testExternalGroup1ID)

config := `
data "github_external_groups" "example" {}
`

resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: config,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue("data.github_external_groups.example", tfjsonpath.New("groups"), knownvalue.SetPartial([]knownvalue.Check{
knownvalue.MapPartial(map[string]knownvalue.Check{
"group_id": knownvalue.Int32Exact(groupID),
}),
})),
},
},
},
})
})

t.Run("queries_external_groups_with_filter", func(t *testing.T) {
t.Parallel()

if testAccConf.testExternalGroup1ID == 0 || testAccConf.testExternalGroup1DisplayName == "" || testAccConf.testExternalGroup2ID == 0 {
t.Skip("Skipping as no external groups are configured for the test organization")
}

groupID := int32(testAccConf.testExternalGroup1ID)

config := fmt.Sprintf(`
data "github_external_groups" "example" {
display_name_filter = "%s"
}
`, testAccConf.testExternalGroup1DisplayName)

// TODO: Use new not in set matcher when available from #3537
resource.Test(t, resource.TestCase{
ProviderFactories: providerFactories,
Steps: []resource.TestStep{
{
Config: config,
ConfigStateChecks: []statecheck.StateCheck{
statecheck.ExpectKnownValue("data.github_external_groups.example", tfjsonpath.New("groups"), knownvalue.ListExact([]knownvalue.Check{
knownvalue.MapPartial(map[string]knownvalue.Check{
"group_id": knownvalue.Int32Exact(groupID),
}),
})),
},
},
},
})
})
}
43 changes: 32 additions & 11 deletions templates/data-sources/external_groups.md.tmpl
Original file line number Diff line number Diff line change
@@ -1,27 +1,48 @@
---
page_title: "{{.Name}} ({{.Type}}) - {{.RenderedProviderName}}"
subcategory: ""
description: |-
Retrieve external groups belonging to an organization.
{{ .Description | plainmarkdown | trimspace | prefixlines " " }}
---

# {{.Name}} ({{.Type}})

Use this data source to retrieve external groups belonging to an organization.
{{ .Description | trimspace }}

{{ if .HasExamples -}}
## Example Usage

{{ tffile "examples/data-sources/external_groups/example_1.tf" }}
{{- range .ExampleFiles }}

## Argument Reference
{{ tffile . }}
{{- end }}
{{- end }}

N/A. This resource will retrieve all the external groups belonging to an organization.
<!--
{{- $schema := .SchemaMarkdown | trimspace -}}
{{- range $line := split $schema "\n" }}
{{- if ne (trimspace $line) "<!-- schema generated by tfplugindocs -->" }}
{{ $line }}
{{- end }}
{{- end }}
-->

## Attributes Reference
## Schema

- `external_groups` - an array of external groups belonging to the organization. Each group consists of the fields documented below.
### Optional

---
- `display_name_filter` (String) Filter external groups by display name.

### Read-Only

- `external_groups` (List of Object) List of external groups in the organization. (see [below for nested schema](#nestedatt--external_groups))
- `id` (String) The ID of this resource.

<a id="nestedatt--external_groups"></a>
### Nested Schema for `external_groups`

Read-Only:

- `group_id` - the ID of the group.
- `group_name` - the name of the group.
- `updated_at` - the date the group was last updated.
- `group_id` (Number) ID of the external group.
- `group_name` (String) Name of the external group.
- `updated_at` (String) Timestamp of the last update to the external group.
Loading