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

addition of team sync support #400

Merged
merged 24 commits into from
May 5, 2020
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
0602f1f
add data source w/tests
anGie44 Mar 27, 2020
8837974
update config params for github team sync groups test
anGie44 Mar 27, 2020
da5d694
Merge branch 'master' into ap_team_sync_support
anGie44 Mar 28, 2020
ec39885
updated groups attribute with computed key and add mapping resource
anGie44 Mar 30, 2020
806aaae
Merge branch 'master' into ap_team_sync_support
anGie44 Mar 30, 2020
3422321
fix renamed description attribute
anGie44 Mar 30, 2020
c8ef58d
update org-related attributes
anGie44 Mar 30, 2020
b1834b0
add website docs and update resource/test files
anGie44 Mar 31, 2020
de3efef
update tests and add helper methods to address CR
anGie44 Apr 2, 2020
121b3c9
fix field ref naming
anGie44 Apr 2, 2020
574ffc4
update resource checks
anGie44 Apr 2, 2020
6064065
merge master
anGie44 Apr 2, 2020
b99c869
update website link
anGie44 Apr 2, 2020
78d73f9
remove nomatch test for data source
anGie44 Apr 2, 2020
c0216ff
addressing code review comments
anGie44 Apr 3, 2020
7fe79e4
update test steps to using import steps as validation instead of indi…
anGie44 Apr 6, 2020
741512f
update expand method to return empty array and use team name to retri…
anGie44 Apr 9, 2020
6c0ea98
Merge branch 'master' into ap_team_sync_support
anGie44 Apr 16, 2020
7fa1d3f
update to v3 client
anGie44 Apr 17, 2020
5f34995
Merge branch 'master' into ap_team_sync_support
anGie44 May 5, 2020
6390652
update to use go-github v31.0.0 api and add additional error handling
anGie44 May 5, 2020
6222474
update for acceptance testing
anGie44 May 5, 2020
b0a28b8
update import docs
anGie44 May 5, 2020
579a206
fix indentation
anGie44 May 5, 2020
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
90 changes: 90 additions & 0 deletions github/data_source_github_organization_team_sync_groups.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package github

import (
"context"
"fmt"
"log"

"github.com/google/go-github/v29/github"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func dataSourceGithubOrganizationTeamSyncGroups() *schema.Resource {
return &schema.Resource{
Read: dataSourceGithubOrganizationTeamSyncGroupsRead,

Schema: map[string]*schema.Schema{
"groups": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"group_id": {
Type: schema.TypeString,
Computed: true,
},
"group_name": {
Type: schema.TypeString,
Computed: true,
},
"group_description": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}

func dataSourceGithubOrganizationTeamSyncGroupsRead(d *schema.ResourceData, meta interface{}) error {
log.Print("[INFO] Refreshing GitHub Organization Team-Sync Groups")

client := meta.(*Organization).client
ctx := context.Background()

orgName := meta.(*Organization).name
options := &github.ListCursorOptions{PerPage: maxPerPage}
megan07 marked this conversation as resolved.
Show resolved Hide resolved

groups := make([]interface{}, 0)
for {
idpGroupList, resp, err := client.Teams.ListIDPGroupsInOrganization(ctx, orgName, options)
if err != nil {
return err
}

result, err := flattenGithubIDPGroupList(idpGroupList)
if err != nil {
return fmt.Errorf("unable to flatten IdP Groups in Github Organization(Org: %q) : %+v", orgName, err)
}

groups = append(groups, result...)

if resp.NextPage == 0 {
break
}
options.Page = string(resp.NextPage)
}

d.SetId("github-org-team-sync-groups")
anGie44 marked this conversation as resolved.
Show resolved Hide resolved
d.Set("groups", groups)

return nil
}

func flattenGithubIDPGroupList(idpGroupList *github.IDPGroupList) ([]interface{}, error) {
anGie44 marked this conversation as resolved.
Show resolved Hide resolved
if idpGroupList == nil {
return make([]interface{}, 0), nil
}
results := make([]interface{}, 0)
for _, group := range idpGroupList.Groups {
result := make(map[string]interface{})
result["group_id"] = group.GetGroupID()
result["group_name"] = group.GetGroupName()
result["group_description"] = group.GetGroupDescription()
results = append(results, result)
}

return results, nil
}
52 changes: 52 additions & 0 deletions github/data_source_github_organization_team_sync_groups_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package github

import (
"regexp"
"testing"

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

func TestAccGithubOrganizationTeamSyncGroupsDataSource_noMatchReturnsError(t *testing.T) {
if isEnterprise != "true" {
t.Skip("Skipping because `ENTERPRISE_ACCOUNT` is not set or set to false")
}

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckGithubOrganizationTeamSyncGroupsDataSourceConfig(),
ExpectError: regexp.MustCompile(`This team is not externally managed.`),
},
},
})
}

func TestAccGithubOrganizationTeamSyncGroupsDataSource_existing(t *testing.T) {
if isEnterprise != "true" {
t.Skip("Skipping because `ENTERPRISE_ACCOUNT` is not set or set to false")
}

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() {
testAccPreCheck(t)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccCheckGithubOrganizationTeamSyncGroupsDataSourceConfig(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.github_organization_team_sync_groups.test", "groups.#"),
),
},
},
})
}

func testAccCheckGithubOrganizationTeamSyncGroupsDataSourceConfig() string {
return `data "github_organization_team_sync_groups" "test" {}`
}
20 changes: 11 additions & 9 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,22 +62,24 @@ func Provider() terraform.ResourceProvider {
"github_repository": resourceGithubRepository(),
"github_team_membership": resourceGithubTeamMembership(),
"github_team_repository": resourceGithubTeamRepository(),
"github_team_sync_group_mapping": resourceGithubTeamSyncGroupMapping(),
"github_team": resourceGithubTeam(),
"github_user_gpg_key": resourceGithubUserGpgKey(),
"github_user_invitation_accepter": resourceGithubUserInvitationAccepter(),
"github_user_ssh_key": resourceGithubUserSshKey(),
},

DataSourcesMap: map[string]*schema.Resource{
"github_collaborators": dataSourceGithubCollaborators(),
"github_ip_ranges": dataSourceGithubIpRanges(),
"github_membership": dataSourceGithubMembership(),
"github_release": dataSourceGithubRelease(),
"github_repositories": dataSourceGithubRepositories(),
"github_repository": dataSourceGithubRepository(),
"github_team": dataSourceGithubTeam(),
"github_user": dataSourceGithubUser(),
"github_actions_public_key": dataSourceGithubActionsPublicKey(),
"github_collaborators": dataSourceGithubCollaborators(),
"github_ip_ranges": dataSourceGithubIpRanges(),
"github_membership": dataSourceGithubMembership(),
"github_release": dataSourceGithubRelease(),
"github_repositories": dataSourceGithubRepositories(),
"github_repository": dataSourceGithubRepository(),
"github_organization_team_sync_groups": dataSourceGithubOrganizationTeamSyncGroups(),
"github_team": dataSourceGithubTeam(),
"github_user": dataSourceGithubUser(),
"github_actions_public_key": dataSourceGithubActionsPublicKey(),
},
}

Expand Down
1 change: 1 addition & 0 deletions github/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
var testUser string = os.Getenv("GITHUB_TEST_USER")
var testCollaborator string = os.Getenv("GITHUB_TEST_COLLABORATOR")
var testOrganization string = os.Getenv("GITHUB_ORGANIZATION")
var isEnterprise string = os.Getenv("ENTERPRISE_ACCOUNT")

var testAccProviders map[string]terraform.ResourceProvider
var testAccProviderFactories func(providers *[]*schema.Provider) map[string]terraform.ResourceProviderFactory
Expand Down
194 changes: 194 additions & 0 deletions github/resource_github_team_sync_group_mapping.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
package github

import (
"context"
"log"

"github.com/google/go-github/v29/github"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)

func resourceGithubTeamSyncGroupMapping() *schema.Resource {
return &schema.Resource{
Create: resourceGithubTeamSyncGroupMappingCreate,
Read: resourceGithubTeamSyncGroupMappingRead,
Update: resourceGithubTeamSyncGroupMappingUpdate,
Delete: resourceGithubTeamSyncGroupMappingDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"team_slug": {
Type: schema.TypeString,
Required: true,
},
"group": {
anGie44 marked this conversation as resolved.
Show resolved Hide resolved
Type: schema.TypeList,
Required: true,
ForceNew: true,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anGie44 I know this has been long part of the provider, but what was the reasoning for this? At first sight, it doesn't seem like an update to the groups should require a new resource. Why wasn't in-place updating possible?

Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"group_id": {
Type: schema.TypeString,
Required: true,
},
"group_name": {
Type: schema.TypeString,
Required: true,
},
"group_description": {
Type: schema.TypeString,
Required: true,
},
},
},
},
"etag": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

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

client := meta.(*Organization).client
ctx := context.Background()
orgName := meta.(*Organization).name
slug := d.Get("team_slug").(string)

team, err := getGithubTeamBySlug(ctx, client, orgName, slug)
if err != nil {
return err
}

idpGroupList, err := expandTeamSyncGroups(d)
if err != nil {
return err
}
log.Printf("[DEBUG] Creating team-sync group mapping (Team: %s)", team.GetName())
_, resp, err := client.Teams.CreateOrUpdateIDPGroupConnections(ctx, string(team.GetID()), *idpGroupList)
if err != nil {
return err
}

d.Set("etag", resp.Header.Get("ETag"))
d.SetId("github-team-sync-group-mappings")
anGie44 marked this conversation as resolved.
Show resolved Hide resolved

return resourceGithubTeamRead(d, meta)
}

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

client := meta.(*Organization).client
orgName := meta.(*Organization).name
slug := d.Get("team_slug").(string)

ctx := context.WithValue(context.Background(), ctxId, d.Id())
if !d.IsNewResource() {
ctx = context.WithValue(ctx, ctxEtag, d.Get("etag").(string))
}

team, err := getGithubTeamBySlug(ctx, client, orgName, slug)
if err != nil {
return err
}

log.Printf("[DEBUG] Reading team-sync group mapping (Team: %s)", team.GetName())
idpGroupList, _, err := client.Teams.ListIDPGroupsForTeam(ctx, string(team.GetID()))
if err != nil {
return err
}

groups, err := flattenGithubIDPGroupList(idpGroupList)
if err != nil {
return err
}

d.Set("group", groups)

return nil
}

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

client := meta.(*Organization).client
orgName := meta.(*Organization).name
ctx := context.WithValue(context.Background(), ctxId, d.Id())
slug := d.Get("team_slug").(string)

team, err := getGithubTeamBySlug(ctx, client, orgName, slug)
if err != nil {
return err
}

idpGroupList, err := expandTeamSyncGroups(d)
if err != nil {
return err
}
log.Printf("[DEBUG] Updating team-sync group mapping (Team: %s)", team.GetName())
_, _, err = client.Teams.CreateOrUpdateIDPGroupConnections(ctx, string(team.GetID()), *idpGroupList)
if err != nil {
return err
}

return resourceGithubTeamRead(d, meta)
}

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

client := meta.(*Organization).client
orgName := meta.(*Organization).name
ctx := context.WithValue(context.Background(), ctxId, d.Id())
slug := d.Get("team_slug").(string)

team, err := getGithubTeamBySlug(ctx, client, orgName, slug)
if err != nil {
return err
}

groups := make([]*github.IDPGroup, 0)
emptyGroupList := github.IDPGroupList{Groups: groups}

log.Printf("[DEBUG] Deleting team-sync group mapping (Team: %s)", team.GetName())
_, _, err = client.Teams.CreateOrUpdateIDPGroupConnections(ctx, string(team.GetID()), emptyGroupList)

return err
}

func expandTeamSyncGroups(d *schema.ResourceData) (*github.IDPGroupList, error) {
if v, ok := d.GetOk("group"); ok {
vL := v.([]interface{})
idpGroupList := new(github.IDPGroupList)
groups := make([]*github.IDPGroup, 0)
for _, v := range vL {
m := v.(map[string]interface{})
group := new(github.IDPGroup)
group.GroupID = m["group_id"].(*string)
group.GroupName = m["group_name"].(*string)
group.GroupDescription = m["group_description"].(*string)
groups = append(groups, group)
}
idpGroupList.Groups = groups
return idpGroupList, nil
}
return nil, nil
}
Loading