From 2dc34a980ddac0f8cb17f2edb201b12e24fdee15 Mon Sep 17 00:00:00 2001 From: megan07 Date: Mon, 10 Jun 2019 15:38:15 -0500 Subject: [PATCH] New Datasource: `github_collaborators` (#239) --- github/data_source_github_collaborators.go | 193 ++++++++++++++++++ .../data_source_github_collaborators_test.go | 42 ++++ github/provider.go | 11 +- website/docs/d/collaborators.html.markdown | 68 ++++++ website/github.erb | 3 + 5 files changed, 312 insertions(+), 5 deletions(-) create mode 100644 github/data_source_github_collaborators.go create mode 100644 github/data_source_github_collaborators_test.go create mode 100644 website/docs/d/collaborators.html.markdown diff --git a/github/data_source_github_collaborators.go b/github/data_source_github_collaborators.go new file mode 100644 index 0000000000..5ab57c3331 --- /dev/null +++ b/github/data_source_github_collaborators.go @@ -0,0 +1,193 @@ +package github + +import ( + "context" + "fmt" + + "github.com/google/go-github/v25/github" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" +) + +func dataSourceGithubCollaborators() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGithubCollaboratorsRead, + + Schema: map[string]*schema.Schema{ + "owner": { + Type: schema.TypeString, + Required: true, + }, + "repository": { + Type: schema.TypeString, + Required: true, + }, + "affiliation": { + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + "all", + "direct", + "outside", + }, false), + Optional: true, + Default: "all", + }, + "collaborator": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "login": { + Type: schema.TypeString, + Computed: true, + }, + "id": { + Type: schema.TypeInt, + Computed: true, + }, + "url": { + Type: schema.TypeString, + Computed: true, + }, + "html_url": { + Type: schema.TypeString, + Computed: true, + }, + "followers_url": { + Type: schema.TypeString, + Computed: true, + }, + "following_url": { + Type: schema.TypeString, + Computed: true, + }, + "gists_url": { + Type: schema.TypeString, + Computed: true, + }, + "starred_url": { + Type: schema.TypeString, + Computed: true, + }, + "subscriptions_url": { + Type: schema.TypeString, + Computed: true, + }, + "organizations_url": { + Type: schema.TypeString, + Computed: true, + }, + "repos_url": { + Type: schema.TypeString, + Computed: true, + }, + "events_url": { + Type: schema.TypeString, + Computed: true, + }, + "received_events_url": { + Type: schema.TypeString, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "site_admin": { + Type: schema.TypeBool, + Computed: true, + }, + "permission": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceGithubCollaboratorsRead(d *schema.ResourceData, meta interface{}) error { + + client := meta.(*Organization).client + ctx := context.Background() + + owner := d.Get("owner").(string) + repo := d.Get("repository").(string) + affiliation := d.Get("affiliation").(string) + + options := &github.ListCollaboratorsOptions{ + Affiliation: affiliation, + ListOptions: github.ListOptions{ + PerPage: maxPerPage, + }, + } + + d.SetId(fmt.Sprintf("%s/%s/%s", owner, repo, affiliation)) + d.Set("owner", owner) + d.Set("repository", repo) + d.Set("affiliation", affiliation) + + totalCollaborators := make([]interface{}, 0) + for { + collaborators, resp, err := client.Repositories.ListCollaborators(ctx, owner, repo, options) + if err != nil { + return err + } + + result, err := flattenGitHubCollaborators(collaborators) + if err != nil { + return fmt.Errorf("unable to flatten GitHub Collaborators (Owner: %q/Repository: %q) : %+v", owner, repo, err) + } + + totalCollaborators = append(totalCollaborators, result...) + + if resp.NextPage == 0 { + break + } + options.Page = resp.NextPage + } + + d.Set("collaborator", totalCollaborators) + + return nil +} + +func flattenGitHubCollaborators(collaborators []*github.User) ([]interface{}, error) { + if collaborators == nil { + return make([]interface{}, 0), nil + } + + results := make([]interface{}, 0) + + for _, c := range collaborators { + result := make(map[string]interface{}) + + result["login"] = c.Login + result["id"] = c.ID + result["url"] = c.URL + result["html_url"] = c.HTMLURL + result["following_url"] = c.FollowingURL + result["followers_url"] = c.FollowersURL + result["gists_url"] = c.GistsURL + result["starred_url"] = c.StarredURL + result["subscriptions_url"] = c.SubscriptionsURL + result["organizations_url"] = c.OrganizationsURL + result["repos_url"] = c.ReposURL + result["events_url"] = c.EventsURL + result["received_events_url"] = c.ReceivedEventsURL + result["type"] = c.Type + result["site_admin"] = c.SiteAdmin + + permissionName, err := getRepoPermission(c.Permissions) + if err != nil { + return nil, err + } + + result["permission"] = permissionName + results = append(results, result) + } + + return results, nil +} diff --git a/github/data_source_github_collaborators_test.go b/github/data_source_github_collaborators_test.go new file mode 100644 index 0000000000..90cf04c7c9 --- /dev/null +++ b/github/data_source_github_collaborators_test.go @@ -0,0 +1,42 @@ +package github + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccGithubCollaboratorsDataSource_basic(t *testing.T) { + repoName := fmt.Sprintf("tf-acc-test-collab-%s", acctest.RandString(5)) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheck(t) + }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccCheckGithubCollaboratorsDataSourceConfig(repoName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("data.github_collaborators.test", "collaborator.#"), + resource.TestCheckResourceAttr("data.github_collaborators.test", "affiliation", "all"), + ), + }, + }, + }) +} + +func testAccCheckGithubCollaboratorsDataSourceConfig(repo string) string { + return fmt.Sprintf(` +resource "github_repository" "test" { + name = "%s" +} + +data "github_collaborators" "test" { + owner = "%s" + repository = "${github_repository.test.name}" +} +`, repo, testOrganization) +} diff --git a/github/provider.go b/github/provider.go index 19c65f7092..29ce952766 100644 --- a/github/provider.go +++ b/github/provider.go @@ -57,11 +57,12 @@ func Provider() terraform.ResourceProvider { }, DataSourcesMap: map[string]*schema.Resource{ - "github_ip_ranges": dataSourceGithubIpRanges(), - "github_repositories": dataSourceGithubRepositories(), - "github_repository": dataSourceGithubRepository(), - "github_team": dataSourceGithubTeam(), - "github_user": dataSourceGithubUser(), + "github_collaborators": dataSourceGithubCollaborators(), + "github_ip_ranges": dataSourceGithubIpRanges(), + "github_repositories": dataSourceGithubRepositories(), + "github_repository": dataSourceGithubRepository(), + "github_team": dataSourceGithubTeam(), + "github_user": dataSourceGithubUser(), }, } diff --git a/website/docs/d/collaborators.html.markdown b/website/docs/d/collaborators.html.markdown new file mode 100644 index 0000000000..4c687b5ad1 --- /dev/null +++ b/website/docs/d/collaborators.html.markdown @@ -0,0 +1,68 @@ +--- +layout: "github" +page_title: "GitHub: github_collaborators" +sidebar_current: "docs-github-datasource-collaborators" +description: |- + Get the collaborators for a given repository. +--- + +# github_collaborators + +Use this data source to retrieve the collaborators for a given repository. + +## Example Usage + +```hcl +data "github_collaborators" "test" { + owner = "example_owner" + repository = "example_repository" +} +``` + +## Arguments Reference + + * `owner` - (Required) The organization that owns the repository. + + * `repository` - (Required) The name of the repository. + + * `affiliation` - (Optional) Filter collaborators returned by their affiliation. Can be one of: `outside`, `direct`, `all`. Defaults to `all`. + +## Attributes Reference + + * `collaborator` - An Array of GitHub collaborators. Each `collaborator` block consists of the fields documented below. + +___ + +The `collaborator` block consists of: + +* `login` - The collaborator's login. + +* `id` - The id of the collaborator. + +* `url` - The github api url for the collaborator. + +* `html_url` - The github html url for the collaborator. + +* `followers_url` - The github api url for the collaborator's followers. + +* `following_url` - The github api url for those following the collaborator. + +* `gists_url` - The github api url for the collaborator's gists. + +* `starred_url` - The github api url for the collaborator's starred repositories. + +* `subscriptions_url` - The github api url for the collaborator's subscribed repositories. + +* `organizations_url` - The github api url for the collaborator's organizations. + +* `repos_url` - The github api url for the collaborator's repositories. + +* `events_url` - The github api url for the collaborator's events. + +* `received_events_url` - The github api url for the collaborator's received events. + +* `type` - The type of the collaborator (ex. `User`). + +* `site_admin` - Whether the user is a GitHub admin. + +* `permission` - The permission of the collaborator. \ No newline at end of file diff --git a/website/github.erb b/website/github.erb index 29104add5b..7421b267b7 100644 --- a/website/github.erb +++ b/website/github.erb @@ -13,6 +13,9 @@ > Data Sources