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 github_teams data source #725

Merged
merged 9 commits into from
Apr 9, 2021
134 changes: 134 additions & 0 deletions github/data_source_github_organization_teams.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
package github

import (
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/shurcooL/githubv4"
"log"
)

func dataSourceGithubOrganizationTeams() *schema.Resource {
return &schema.Resource{
Read: dataSourceGithubOrganizationTeamsRead,

Schema: map[string]*schema.Schema{
"root_teams_only": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},
"teams": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeInt,
Computed: true,
},
"node_id": {
Type: schema.TypeString,
Computed: true,
},
"slug": {
Type: schema.TypeString,
Required: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"privacy": {
Type: schema.TypeString,
Computed: true,
},
"members": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
},
}
}

func dataSourceGithubOrganizationTeamsRead(d *schema.ResourceData, meta interface{}) error {
err := checkOrganization(meta)
if err != nil {
return err
}

client := meta.(*Owner).v4client
orgName := meta.(*Owner).name
rootTeamsOnly := d.Get("root_teams_only").(bool)

log.Print("[INFO] Refreshing GitHub Teams for Organization: ", orgName)

var query TeamsQuery
variables := map[string]interface{}{
"first": githubv4.Int(100),
"login": githubv4.String(orgName),
"cursor": (*githubv4.String)(nil),
"rootTeamsOnly": githubv4.Boolean(rootTeamsOnly),
}

var teams []interface{}
for {
err = client.Query(meta.(*Owner).StopContext, &query, variables)
if err != nil {
return err
}

additionalTeams := flattenGitHubTeams(query)
teams = append(teams, additionalTeams...)

if !query.Organization.Teams.PageInfo.HasNextPage {
break
}
variables["cursor"] = githubv4.NewString(query.Organization.Teams.PageInfo.EndCursor)
}

d.SetId(string(query.Organization.ID))
d.Set("teams", teams)

return nil
}

func flattenGitHubTeams(tq TeamsQuery) []interface{} {
teams := tq.Organization.Teams.Nodes

if len(teams) == 0 {
return make([]interface{}, 0)
}

flatTeams := make([]interface{}, len(teams))

for i, team := range teams {
t := make(map[string]interface{})

t["id"] = team.DatabaseID
t["node_id"] = team.ID
t["slug"] = team.Slug
t["name"] = team.Name
t["description"] = team.Description
t["privacy"] = team.Privacy

members := team.Members.Nodes
flatMembers := make([]string, len(members))

for i, member := range members {
flatMembers[i] = string(member.Login)
}

t["members"] = flatMembers

flatTeams[i] = t
}

return flatTeams
}
90 changes: 90 additions & 0 deletions github/data_source_github_organization_teams_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package github

import (
"fmt"
"testing"

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

func TestAccGithubOrganizationTeamsDataSource(t *testing.T) {

t.Run("queries without error", func(t *testing.T) {

config := fmt.Sprintf(`
data "github_organization_teams" "all" {}
`)

check := resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("data.github_organization_teams.all", "teams.0.id"),
resource.TestCheckResourceAttrSet("data.github_organization_teams.all", "teams.0.node_id"),
)

testCase := func(t *testing.T, mode string) {
resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessMode(t, mode) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: check,
},
},
})
}

t.Run("with an anonymous account", func(t *testing.T) {
t.Skip("anonymous account not supported for this operation")
})

t.Run("with an individual account", func(t *testing.T) {
t.Skip("individual account not supported for this operation")
})

t.Run("with an organization account", func(t *testing.T) {
testCase(t, organization)
})

})

t.Run("queries root teams only without error", func(t *testing.T) {

config := fmt.Sprintf(`
data "github_organization_teams" "root_teams" {
root_teams_only = true
}
`)

check := resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttrSet("data.github_organization_teams.root_teams", "teams.0.id"),
resource.TestCheckResourceAttrSet("data.github_organization_teams.root_teams", "teams.0.node_id"),
)

testCase := func(t *testing.T, mode string) {
resource.Test(t, resource.TestCase{
PreCheck: func() { skipUnlessMode(t, mode) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: config,
Check: check,
},
},
})
}

t.Run("with an anonymous account", func(t *testing.T) {
t.Skip("anonymous account not supported for this operation")
})

t.Run("with an individual account", func(t *testing.T) {
t.Skip("individual account not supported for this operation")
})

t.Run("with an organization account", func(t *testing.T) {
testCase(t, organization)
})

})

}
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func Provider() terraform.ResourceProvider {
"github_membership": dataSourceGithubMembership(),
"github_organization": dataSourceGithubOrganization(),
"github_organization_team_sync_groups": dataSourceGithubOrganizationTeamSyncGroups(),
"github_organization_teams": dataSourceGithubOrganizationTeams(),
"github_release": dataSourceGithubRelease(),
"github_repositories": dataSourceGithubRepositories(),
"github_repository": dataSourceGithubRepository(),
Expand Down
25 changes: 25 additions & 0 deletions github/util_v4_teams.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package github

import "github.com/shurcooL/githubv4"

type TeamsQuery struct {
Organization struct {
ID githubv4.String
Teams struct {
Nodes []struct {
ID githubv4.String
DatabaseID githubv4.Int
Slug githubv4.String
Name githubv4.String
Description githubv4.String
Privacy githubv4.String
Members struct {
Nodes []struct {
Login githubv4.String
}
}
}
PageInfo PageInfo
} `graphql:"teams(first:$first, after:$cursor, rootTeamsOnly:$rootTeamsOnly)"`
} `graphql:"organization(login:$login)"`
}
42 changes: 42 additions & 0 deletions website/docs/d/organization_teams.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
---
layout: "github"
page_title: "GitHub: github_organization_teams"
description: |-
Get information on all GitHub teams of an organization.
---

# github\_organization\_teams

Use this data source to retrieve information about all GitHub teams in an organization.

## Example Usage

To retrieve *all* teams of the organization:

```hcl
data "github_organization_teams" "all" {}
```

To retrieve only the team's at the root of the organization:

```hcl
data "github_organization_teams" "root_teams" {
root_teams_only = true
}
```

## Attributes Reference

* `root_teams_only` - Only return teams that are at the organization's root, i.e. no nested teams. Defaults to `false`.
* `teams` - An Array of GitHub Teams. Each `team` block consists of the fields documented below.
___

The `team` block consists of:

* `id` - the ID of the team.
* `node_id` - the Node ID of the team.
* `slug` - the slug of the team.
* `name` - the team's full name.
* `description` - the team's description.
* `privacy` - the team's privacy type.
* `members` - List of team members.
3 changes: 3 additions & 0 deletions website/github.erb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
<li>
<a href="/docs/providers/github/d/organization_team_sync_groups.html">github_organization_team_sync_groups</a>
</li>
<li>
<a href="/docs/providers/github/d/organization_teams.html">github_organization_teams</a>
</li>
<li>
<a href="/docs/providers/github/d/release.html">github_release</a>
</li>
Expand Down