diff --git a/github/provider.go b/github/provider.go index d96b919522..3a3b24863c 100644 --- a/github/provider.go +++ b/github/provider.go @@ -18,10 +18,11 @@ func Provider() *schema.Provider { p := &schema.Provider{ Schema: map[string]*schema.Schema{ "token": { - Type: schema.TypeString, - Optional: true, - DefaultFunc: schema.EnvDefaultFunc("GITHUB_TOKEN", nil), - Description: descriptions["token"], + Type: schema.TypeString, + Optional: true, + DefaultFunc: schema.EnvDefaultFunc("GITHUB_TOKEN", nil), + Description: descriptions["token"], + ExactlyOneOf: []string{"app_auth"}, }, "owner": { Type: schema.TypeString, @@ -93,10 +94,11 @@ func Provider() *schema.Provider { Description: descriptions["parallel_requests"], }, "app_auth": { - Type: schema.TypeList, - Optional: true, - MaxItems: 1, - Description: descriptions["app_auth"], + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Description: descriptions["app_auth"], + ExactlyOneOf: []string{"token"}, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "id": { @@ -414,6 +416,7 @@ func providerConfigure(p *schema.Provider) schema.ConfigureContextFunc { } if token == "" { + log.Printf("[INFO] No token found, using GitHub CLI to get token from hostname %s", baseURL.Host) token = tokenFromGHCLI(baseURL) } diff --git a/github/provider_test.go b/github/provider_test.go index 5a7915cab7..6d05f3fa15 100644 --- a/github/provider_test.go +++ b/github/provider_test.go @@ -2,6 +2,7 @@ package github import ( "fmt" + "regexp" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" @@ -53,7 +54,7 @@ func TestAccProviderConfigure(t *testing.T) { t.Run("can be configured to run anonymously", func(t *testing.T) { config := ` provider "github" { - token = "" + token = "" } data "github_ip_ranges" "test" {} ` @@ -77,7 +78,7 @@ func TestAccProviderConfigure(t *testing.T) { insecure = true } data "github_ip_ranges" "test" {} - ` + ` resource.Test(t, resource.TestCase{ ProviderFactories: providerFactories, @@ -116,39 +117,42 @@ func TestAccProviderConfigure(t *testing.T) { config := fmt.Sprintf(` provider "github" { token = "%s" - owner = "%s" - }`, testAccConf.token, testAccConf.owner) + owner = "%[2]s" + } + + data "github_organization" "test" { + name = "%[2]s" + } + `, testAccConf.token, testAccConf.owner) resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnlessHasOrgs(t) }, ProviderFactories: providerFactories, Steps: []resource.TestStep{ { - Config: config, - PlanOnly: true, - ExpectNonEmptyPlan: false, + Config: config, }, }, }) + }) - t.Run("can be configured with an organization account legacy", func(t *testing.T) { - config := fmt.Sprintf(` + t.Run("can be configured with an organization account legacy", func(t *testing.T) { + config := fmt.Sprintf(` provider "github" { token = "%s" organization = "%s" }`, testAccConf.token, testAccConf.owner) - resource.Test(t, resource.TestCase{ - PreCheck: func() { skipUnlessHasOrgs(t) }, - ProviderFactories: providerFactories, - Steps: []resource.TestStep{ - { - Config: config, - PlanOnly: true, - ExpectNonEmptyPlan: false, - }, + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnlessHasOrgs(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + PlanOnly: true, + ExpectNonEmptyPlan: false, }, - }) + }, }) }) @@ -172,11 +176,15 @@ func TestAccProviderConfigure(t *testing.T) { }) t.Run("can be configured with max retries", func(t *testing.T) { + testMaxRetries := -1 config := fmt.Sprintf(` provider "github" { owner = "%s" - max_retries = 3 - }`, testAccConf.owner) + max_retries = %d + } + + data "github_ip_ranges" "test" {} + `, testAccConf.owner, testMaxRetries) resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnauthenticated(t) }, @@ -185,17 +193,22 @@ func TestAccProviderConfigure(t *testing.T) { { Config: config, ExpectNonEmptyPlan: false, + ExpectError: regexp.MustCompile("max_retries must be greater than or equal to 0"), }, }, }) }) t.Run("can be configured with max per page", func(t *testing.T) { - config := ` + testMaxPerPage := 101 + config := fmt.Sprintf(` provider "github" { owner = "%s" - max_per_page = 100 - }` + max_per_page = %d + } + + data "github_ip_ranges" "test" {} + `, testAccConf.owner, testMaxPerPage) resource.Test(t, resource.TestCase{ PreCheck: func() { skipUnauthenticated(t) }, @@ -205,8 +218,8 @@ func TestAccProviderConfigure(t *testing.T) { Config: config, ExpectNonEmptyPlan: false, Check: func(_ *terraform.State) error { - if maxPerPage != 100 { - return fmt.Errorf("max_per_page should be set to 100, got %d", maxPerPage) + if maxPerPage != testMaxPerPage { + return fmt.Errorf("max_per_page should be set to %d, got %d", testMaxPerPage, maxPerPage) } return nil }, @@ -214,4 +227,55 @@ func TestAccProviderConfigure(t *testing.T) { }, }) }) + t.Run("should not allow both token and app_auth to be configured", func(t *testing.T) { + config := fmt.Sprintf(` + provider "github" { + owner = "%s" + token = "%s" + app_auth { + id = "1234567890" + installation_id = "1234567890" + pem_file = "1234567890" + } + } + + data "github_ip_ranges" "test" {} + `, testAccConf.owner, testAccConf.token) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnauthenticated(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + ExpectError: regexp.MustCompile("only one of `app_auth,token` can be specified"), + }, + }, + }) + }) + t.Run("should not allow app_auth and GITHUB_TOKEN to be configured", func(t *testing.T) { + config := fmt.Sprintf(` + provider "github" { + owner = "%s" + app_auth { + id = "1234567890" + installation_id = "1234567890" + pem_file = "1234567890" + } + } + + data "github_ip_ranges" "test" {} + `, testAccConf.owner) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnauthenticated(t); t.Setenv("GITHUB_TOKEN", "1234567890") }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + ExpectError: regexp.MustCompile("only one of `app_auth,token` can be specified"), + }, + }, + }) + }) }