diff --git a/docs/data-sources/client_config.md b/docs/data-sources/client_config.md new file mode 100644 index 0000000000..8a19002c5a --- /dev/null +++ b/docs/data-sources/client_config.md @@ -0,0 +1,46 @@ +--- +page_title: "github_client_config (Data Source) - GitHub" +description: |- + Get information about the configured GitHub provider client, including the resolved owner and authenticated user. +--- + +# github_client_config (Data Source) + +Use this data source to access information about the GitHub provider's client +configuration. This is useful when the `owner` argument is set via the +`GITHUB_OWNER` environment variable (and therefore not available in +configuration), or when you need to know which user the provider is +authenticating as. + +## Example Usage + +```terraform +data "github_client_config" "current" {} + +output "owner" { + value = data.github_client_config.current.owner +} + +output "username" { + value = data.github_client_config.current.username +} +``` + +## Argument Reference + +This data source has no arguments. + +## Attributes Reference + +- `id` - The resolved owner name, or the authenticated user's login when no + owner is configured. Falls back to the API base URL in anonymous mode. +- `owner` - The owner the provider is configured to manage. This reflects the + value of the `owner` provider argument or the `GITHUB_OWNER` environment + variable. When neither is set and the provider is authenticated, this is the + login of the authenticated user. +- `is_organization` - Whether the resolved `owner` is a GitHub organization + (`true`) or a user (`false`). +- `username` - The login of the user the provider is authenticated as. This + may differ from `owner` when `owner` is an organization or another user. + Empty when the provider is configured in anonymous mode. +- `base_url` - The GitHub API base URL the provider is configured to use. diff --git a/examples/data-sources/client_config/example_1.tf b/examples/data-sources/client_config/example_1.tf new file mode 100644 index 0000000000..77dd77a18f --- /dev/null +++ b/examples/data-sources/client_config/example_1.tf @@ -0,0 +1,9 @@ +data "github_client_config" "current" {} + +output "owner" { + value = data.github_client_config.current.owner +} + +output "username" { + value = data.github_client_config.current.username +} diff --git a/github/data_source_github_client_config.go b/github/data_source_github_client_config.go new file mode 100644 index 0000000000..2473891444 --- /dev/null +++ b/github/data_source_github_client_config.go @@ -0,0 +1,67 @@ +package github + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-sdk/v2/diag" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" +) + +func dataSourceGithubClientConfig() *schema.Resource { + return &schema.Resource{ + ReadContext: dataSourceGithubClientConfigRead, + + Schema: map[string]*schema.Schema{ + "owner": { + Type: schema.TypeString, + Computed: true, + }, + "is_organization": { + Type: schema.TypeBool, + Computed: true, + }, + "username": { + Type: schema.TypeString, + Computed: true, + }, + "base_url": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceGithubClientConfigRead(ctx context.Context, d *schema.ResourceData, meta any) diag.Diagnostics { + owner := meta.(*Owner) + client := owner.v3client + + if err := d.Set("owner", owner.name); err != nil { + return diag.FromErr(err) + } + if err := d.Set("is_organization", owner.IsOrganization); err != nil { + return diag.FromErr(err) + } + if err := d.Set("base_url", client.BaseURL.String()); err != nil { + return diag.FromErr(err) + } + + var username string + if user, _, err := client.Users.Get(ctx, ""); err == nil { + username = user.GetLogin() + } + if err := d.Set("username", username); err != nil { + return diag.FromErr(err) + } + + id := owner.name + if id == "" { + id = username + } + if id == "" { + id = client.BaseURL.String() + } + d.SetId(id) + + return nil +} diff --git a/github/data_source_github_client_config_test.go b/github/data_source_github_client_config_test.go new file mode 100644 index 0000000000..4da7b142b5 --- /dev/null +++ b/github/data_source_github_client_config_test.go @@ -0,0 +1,58 @@ +package github + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccGithubClientConfigDataSource(t *testing.T) { + t.Run("reads provider configuration without error", func(t *testing.T) { + config := `data "github_client_config" "test" {}` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.github_client_config.test", "owner", testAccConf.owner), + resource.TestCheckResourceAttr("data.github_client_config.test", "username", testAccConf.username), + resource.TestCheckResourceAttr("data.github_client_config.test", "base_url", testAccConf.baseURL.String()), + resource.TestCheckResourceAttrSet("data.github_client_config.test", "is_organization"), + resource.TestCheckResourceAttrSet("data.github_client_config.test", "id"), + ) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { skipUnauthenticated(t) }, + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + }) + }) + + t.Run("reads provider configuration in anonymous mode", func(t *testing.T) { + if testAccConf.authMode != anonymous { + t.Skip("Skipping as test mode is not anonymous") + } + + config := `data "github_client_config" "test" {}` + + check := resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.github_client_config.test", "owner", ""), + resource.TestCheckResourceAttr("data.github_client_config.test", "username", ""), + resource.TestCheckResourceAttr("data.github_client_config.test", "is_organization", "false"), + resource.TestCheckResourceAttrSet("data.github_client_config.test", "base_url"), + resource.TestCheckResourceAttrSet("data.github_client_config.test", "id"), + ) + + resource.Test(t, resource.TestCase{ + ProviderFactories: providerFactories, + Steps: []resource.TestStep{ + { + Config: config, + Check: check, + }, + }, + }) + }) +} diff --git a/github/provider.go b/github/provider.go index bfcfc66825..4c4dad3fd3 100644 --- a/github/provider.go +++ b/github/provider.go @@ -240,6 +240,7 @@ func Provider() *schema.Provider { "github_app_token": dataSourceGithubAppToken(), "github_branch": dataSourceGithubBranch(), "github_branch_protection_rules": dataSourceGithubBranchProtectionRules(), + "github_client_config": dataSourceGithubClientConfig(), "github_collaborators": dataSourceGithubCollaborators(), "github_codespaces_organization_public_key": dataSourceGithubCodespacesOrganizationPublicKey(), "github_codespaces_organization_secrets": dataSourceGithubCodespacesOrganizationSecrets(), diff --git a/templates/data-sources/client_config.md.tmpl b/templates/data-sources/client_config.md.tmpl new file mode 100644 index 0000000000..d6ba2eba18 --- /dev/null +++ b/templates/data-sources/client_config.md.tmpl @@ -0,0 +1,36 @@ +--- +page_title: "{{.Name}} ({{.Type}}) - {{.RenderedProviderName}}" +description: |- + Get information about the configured GitHub provider client, including the resolved owner and authenticated user. +--- + +# {{.Name}} ({{.Type}}) + +Use this data source to access information about the GitHub provider's client +configuration. This is useful when the `owner` argument is set via the +`GITHUB_OWNER` environment variable (and therefore not available in +configuration), or when you need to know which user the provider is +authenticating as. + +## Example Usage + +{{ tffile "examples/data-sources/client_config/example_1.tf" }} + +## Argument Reference + +This data source has no arguments. + +## Attributes Reference + +- `id` - The resolved owner name, or the authenticated user's login when no + owner is configured. Falls back to the API base URL in anonymous mode. +- `owner` - The owner the provider is configured to manage. This reflects the + value of the `owner` provider argument or the `GITHUB_OWNER` environment + variable. When neither is set and the provider is authenticated, this is the + login of the authenticated user. +- `is_organization` - Whether the resolved `owner` is a GitHub organization + (`true`) or a user (`false`). +- `username` - The login of the user the provider is authenticated as. This + may differ from `owner` when `owner` is an organization or another user. + Empty when the provider is configured in anonymous mode. +- `base_url` - The GitHub API base URL the provider is configured to use.