diff --git a/github/data_source_github_organization_webhooks.go b/github/data_source_github_organization_webhooks.go new file mode 100644 index 0000000000..5cad9b072d --- /dev/null +++ b/github/data_source_github_organization_webhooks.go @@ -0,0 +1,76 @@ +package github + +import ( + "context" + + "github.com/google/go-github/v47/github" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceGithubOrganizationWebhooks() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGithubOrganizationWebhooksRead, + + Schema: map[string]*schema.Schema{ + "webhooks": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeInt, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "url": { + Type: schema.TypeString, + Computed: true, + }, + "active": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceGithubOrganizationWebhooksRead(d *schema.ResourceData, meta interface{}) error { + owner := meta.(*Owner).name + + client := meta.(*Owner).v3client + ctx := context.Background() + + options := &github.ListOptions{ + PerPage: 100, + } + + results := make([]map[string]interface{}, 0) + for { + hooks, resp, err := client.Organizations.ListHooks(ctx, owner, options) + if err != nil { + return err + } + + results = append(results, flattenGitHubWebhooks(hooks)...) + if resp.NextPage == 0 { + break + } + + options.Page = resp.NextPage + } + + d.SetId(owner) + d.Set("webhooks", results) + + return nil +} diff --git a/github/data_source_github_organization_webhooks_test.go b/github/data_source_github_organization_webhooks_test.go new file mode 100644 index 0000000000..41c2a663d8 --- /dev/null +++ b/github/data_source_github_organization_webhooks_test.go @@ -0,0 +1,65 @@ +package github + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccGithubOrganizationWebhooksDataSource(t *testing.T) { + t.Run("manages organization webhooks", func(t *testing.T) { + config := ` + resource "github_organization_webhook" "test" { + configuration { + url = "https://google.de/webhook" + content_type = "json" + insecure_ssl = true + } + + events = ["pull_request"] + } + ` + + config2 := config + ` + data "github_organization_webhooks" "test" {} + ` + + const resourceName = "data.github_organization_webhooks.test" + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "webhooks.#", "1"), + resource.TestCheckResourceAttr(resourceName, "webhooks.0.name", "web"), + resource.TestCheckResourceAttr(resourceName, "webhooks.0.url", "https://google.de/webhook"), + resource.TestCheckResourceAttr(resourceName, "webhooks.0.active", "true"), + resource.TestCheckResourceAttrSet(resourceName, "webhooks.0.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: resource.ComposeTestCheckFunc(), + }, + { + Config: config2, + 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) { + testCase(t, individual) + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) +} diff --git a/github/data_source_github_repository_webhooks.go b/github/data_source_github_repository_webhooks.go new file mode 100644 index 0000000000..3e0b15c469 --- /dev/null +++ b/github/data_source_github_repository_webhooks.go @@ -0,0 +1,106 @@ +package github + +import ( + "context" + "fmt" + + "github.com/google/go-github/v47/github" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func dataSourceGithubRepositoryWebhooks() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGithubRepositoryWebhooksRead, + + Schema: map[string]*schema.Schema{ + "repository": { + Type: schema.TypeString, + Required: true, + }, + "webhooks": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "id": { + Type: schema.TypeInt, + Computed: true, + }, + "type": { + Type: schema.TypeString, + Computed: true, + }, + "name": { + Type: schema.TypeString, + Computed: true, + }, + "url": { + Type: schema.TypeString, + Computed: true, + }, + "active": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceGithubRepositoryWebhooksRead(d *schema.ResourceData, meta interface{}) error { + repository := d.Get("repository").(string) + owner := meta.(*Owner).name + + client := meta.(*Owner).v3client + ctx := context.Background() + + options := &github.ListOptions{ + PerPage: 100, + } + + results := make([]map[string]interface{}, 0) + for { + hooks, resp, err := client.Repositories.ListHooks(ctx, owner, repository, options) + if err != nil { + return err + } + + results = append(results, flattenGitHubWebhooks(hooks)...) + + if resp.NextPage == 0 { + break + } + + options.Page = resp.NextPage + } + + d.SetId(fmt.Sprintf("%s/%s", owner, repository)) + d.Set("repository", repository) + d.Set("webhooks", results) + + return nil +} + +func flattenGitHubWebhooks(hooks []*github.Hook) []map[string]interface{} { + results := make([]map[string]interface{}, 0) + + if hooks == nil { + return results + } + + for _, hook := range hooks { + result := make(map[string]interface{}) + + result["id"] = hook.ID + result["type"] = hook.Type + result["name"] = hook.Name + result["url"] = hook.Config["url"] + result["active"] = hook.Active + + results = append(results, result) + } + + return results +} diff --git a/github/data_source_github_repository_webhooks_test.go b/github/data_source_github_repository_webhooks_test.go new file mode 100644 index 0000000000..e5015e722d --- /dev/null +++ b/github/data_source_github_repository_webhooks_test.go @@ -0,0 +1,78 @@ +package github + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/helper/acctest" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" +) + +func TestAccGithubRepositoryWebhooksDataSource(t *testing.T) { + t.Run("manages repository webhooks", func(t *testing.T) { + repoName := fmt.Sprintf("tf-acc-test-webhooks-%s", acctest.RandString(5)) + + config := fmt.Sprintf(` + resource "github_repository" "test" { + name = "%s" + auto_init = true + } + + resource "github_repository_webhook" "test" { + repository = github_repository.test.name + + configuration { + url = "https://google.de/webhook" + content_type = "json" + insecure_ssl = true + } + + events = ["pull_request"] + } + `, repoName) + + config2 := config + ` + data "github_repository_webhooks" "test" { + repository = github_repository.test.name + } + ` + + const resourceName = "data.github_repository_webhooks.test" + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "webhooks.#", "1"), + resource.TestCheckResourceAttr(resourceName, "webhooks.0.name", "web"), + resource.TestCheckResourceAttr(resourceName, "webhooks.0.url", "https://google.de/webhook"), + resource.TestCheckResourceAttr(resourceName, "webhooks.0.active", "true"), + resource.TestCheckResourceAttrSet(resourceName, "webhooks.0.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: resource.ComposeTestCheckFunc(), + }, + { + Config: config2, + 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) { + testCase(t, individual) + }) + + t.Run("with an organization account", func(t *testing.T) { + testCase(t, organization) + }) + }) +} diff --git a/github/provider.go b/github/provider.go index 7990b420c6..c05729796e 100644 --- a/github/provider.go +++ b/github/provider.go @@ -150,6 +150,7 @@ func Provider() terraform.ResourceProvider { "github_organization_ip_allow_list": dataSourceGithubOrganizationIpAllowList(), "github_organization_team_sync_groups": dataSourceGithubOrganizationTeamSyncGroups(), "github_organization_teams": dataSourceGithubOrganizationTeams(), + "github_organization_webhooks": dataSourceGithubOrganizationWebhooks(), "github_ref": dataSourceGithubRef(), "github_release": dataSourceGithubRelease(), "github_repositories": dataSourceGithubRepositories(), @@ -160,6 +161,7 @@ func Provider() terraform.ResourceProvider { "github_repository_pull_request": dataSourceGithubRepositoryPullRequest(), "github_repository_pull_requests": dataSourceGithubRepositoryPullRequests(), "github_repository_teams": dataSourceGithubRepositoryTeams(), + "github_repository_webhooks": dataSourceGithubRepositoryWebhooks(), "github_team": dataSourceGithubTeam(), "github_tree": dataSourceGithubTree(), "github_user": dataSourceGithubUser(), diff --git a/website/docs/d/organization_webhooks.html.markdown b/website/docs/d/organization_webhooks.html.markdown new file mode 100644 index 0000000000..aed6ae85f6 --- /dev/null +++ b/website/docs/d/organization_webhooks.html.markdown @@ -0,0 +1,31 @@ +--- +layout: "github" +page_title: "GitHub: github_organization_webhooks" +description: |- + Get information on all Github webhooks of the organization. +--- + +# github\_organization\_webhooks + +Use this data source to retrieve all webhooks of the organization. + +## Example Usage + +To retrieve *all* webhooks of the organization: + +```hcl +data "github_organization_webhooks" "all" {} +``` + +## Attributes Reference + +* `webhooks` - An Array of GitHub Webhooks. Each `webhook` block consists of the fields documented below. +___ + +The `webhook` block consists of: + + * `id` - the ID of the webhook. + * `type` - the type of the webhook. + * `name` - the name of the webhook. + * `url` - the url of the webhook. + * `active` - `true` if the webhook is active. diff --git a/website/docs/d/repository_webhooks.html.markdown b/website/docs/d/repository_webhooks.html.markdown new file mode 100644 index 0000000000..ba1ac6d99d --- /dev/null +++ b/website/docs/d/repository_webhooks.html.markdown @@ -0,0 +1,33 @@ +--- +layout: "github" +page_title: "GitHub: github_repository_webhooks" +description: |- + Get information on all Github webhooks of the organization. +--- + +# github\_repository\_webhooks + +Use this data source to retrieve webhooks for a given repository. + +## Example Usage + +To retrieve webhooks of a repository: + +```hcl +data "github_repository_webhooks" "repo" { + repository = "foo" +} +``` + +## Attributes Reference + +* `webhooks` - An Array of GitHub Webhooks. Each `webhook` block consists of the fields documented below. +___ + +The `webhook` block consists of: + + * `id` - the ID of the webhook. + * `type` - the type of the webhook. + * `name` - the name of the webhook. + * `url` - the url of the webhook. + * `active` - `true` if the webhook is active. diff --git a/website/github.erb b/website/github.erb index 3cd6e44a5f..0655ea0482 100644 --- a/website/github.erb +++ b/website/github.erb @@ -55,6 +55,9 @@
  • github_organization_teams
  • +
  • + github_organization_webhooks +
  • github_ref
  • @@ -79,6 +82,9 @@
  • github_repository_teams
  • +
  • + github_repository_webhooks +
  • github_team