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

New Resource: github_user_gpg_key #120

Merged
merged 1 commit into from
Aug 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func Provider() terraform.ResourceProvider {
"github_team": resourceGithubTeam(),
"github_team_membership": resourceGithubTeamMembership(),
"github_team_repository": resourceGithubTeamRepository(),
"github_user_gpg_key": resourceGithubUserGpgKey(),
"github_user_ssh_key": resourceGithubUserSshKey(),
},

Expand Down
77 changes: 77 additions & 0 deletions github/resource_github_user_gpg_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package github

import (
"context"
"log"
"strconv"

"github.com/hashicorp/terraform/helper/schema"
)

func resourceGithubUserGpgKey() *schema.Resource {
return &schema.Resource{
Create: resourceGithubUserGpgKeyCreate,
Read: resourceGithubUserGpgKeyRead,
Delete: resourceGithubUserGpgKeyDelete,

Schema: map[string]*schema.Schema{
"armored_public_key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"key_id": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func resourceGithubUserGpgKeyCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client

pubKey := d.Get("armored_public_key").(string)

key, _, err := client.Users.CreateGPGKey(context.TODO(), pubKey)
if err != nil {
return err
}

d.SetId(strconv.FormatInt(*key.ID, 10))
Copy link

Choose a reason for hiding this comment

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

Should we use key.KeyID here instead? Looking at GitHub docs it looks like key.ID is a database index-like sequential key, where as KeyID appears to be a unique id.

It also saves us the trouble of using FormatInt and error checking

Copy link

Choose a reason for hiding this comment

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

I guess that depends on what GetGPGKey uses... the docs make it look like it uses key_id but I can't imagine your tests passed if that's what they expected and you weren't doing that 🤔

Copy link

Choose a reason for hiding this comment

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

I've answered my own question. How bizarre 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The documentation is indeed a bit confusing on this one. I actually first tried to use the KeyID, before realizing it's the numeric ID and that the interface expects *int. 😄


return resourceGithubUserGpgKeyRead(d, meta)
}

func resourceGithubUserGpgKeyRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client

id, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
return unconvertibleIdErr(d.Id(), err)
}

key, _, err := client.Users.GetGPGKey(context.TODO(), id)
if err != nil {
log.Printf("[WARN] GitHub User GPG Key (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

d.Set("key_id", key.KeyID)

return nil
}

func resourceGithubUserGpgKeyDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client

id, err := strconv.ParseInt(d.Id(), 10, 64)
if err != nil {
return unconvertibleIdErr(d.Id(), err)
}

_, err = client.Users.DeleteGPGKey(context.TODO(), id)

return err
}
91 changes: 91 additions & 0 deletions github/resource_github_user_gpg_key_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package github

import (
"context"
"fmt"
"path/filepath"
"regexp"
"strconv"
"testing"

"github.com/google/go-github/github"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)

func TestAccGithubUserGpgKey_basic(t *testing.T) {
var key github.GPGKey
keyRe := regexp.MustCompile("^-----BEGIN PGP PUBLIC KEY BLOCK-----")
pubKeyPath := filepath.Join("test-fixtures", "gpg-pubkey.asc")

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGithubUserGpgKeyDestroy,
Steps: []resource.TestStep{
{
Config: testAccGithubUserGpgKeyConfig(pubKeyPath),
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubUserGpgKeyExists("github_user_gpg_key.test", &key),
resource.TestMatchResourceAttr("github_user_gpg_key.test", "armored_public_key", keyRe),
resource.TestCheckResourceAttr("github_user_gpg_key.test", "key_id", "AC541D2D1709CD33"),
),
},
},
})
}

func testAccCheckGithubUserGpgKeyExists(n string, key *github.GPGKey) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not Found: %s", n)
}

id, err := strconv.ParseInt(rs.Primary.ID, 10, 64)
if err != nil {
return unconvertibleIdErr(rs.Primary.ID, err)
}

org := testAccProvider.Meta().(*Organization)
receivedKey, _, err := org.client.Users.GetGPGKey(context.TODO(), id)
if err != nil {
return err
}
*key = *receivedKey
return nil
}
}

func testAccCheckGithubUserGpgKeyDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*Organization).client

for _, rs := range s.RootModule().Resources {
if rs.Type != "github_user_gpg_key" {
continue
}

id, err := strconv.ParseInt(rs.Primary.ID, 10, 64)
if err != nil {
return unconvertibleIdErr(rs.Primary.ID, err)
}

_, resp, err := conn.Users.GetGPGKey(context.TODO(), id)
if err == nil {
return fmt.Errorf("GPG key %s still exists", rs.Primary.ID)
}
if resp.StatusCode != 404 {
return err
}
return nil
}
return nil
}

func testAccGithubUserGpgKeyConfig(pubKeyPath string) string {
return fmt.Sprintf(`
resource "github_user_gpg_key" "test" {
armored_public_key = "${file("%s")}"
}
`, pubKeyPath)
}
53 changes: 53 additions & 0 deletions github/test-fixtures/gpg-pubkey.asc
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----

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
=FSt9
-----END PGP PUBLIC KEY BLOCK-----
40 changes: 40 additions & 0 deletions website/docs/r/user_gpg_key.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
layout: "github"
page_title: "GitHub: github_user_gpg_key"
sidebar_current: "docs-github-resource-user-gpg-key"
description: |-
Provides a GitHub user's GPG key resource.
---

# github_user_gpg_key

Provides a GitHub user's GPG key resource.

This resource allows you to add/remove GPG keys from your user account.

## Example Usage

```hcl
resource "github_user_gpg_key" "example" {
armored_public_key = "-----BEGIN PGP PUBLIC KEY BLOCK-----\n...\n-----END PGP PUBLIC KEY BLOCK-----"
}
```

## Argument Reference

The following arguments are supported:

* `armored_public_key` - (Required) Your pulic GPG key, generated in ASCII-armored format.
See [Generating a new GPG key](https://help.github.com/articles/generating-a-new-gpg-key/) for help on creating a GPG key.

## Attributes Reference

The following attributes are exported:

* `id` - The GitHub ID of the GPG key, e.g. `401586`
* `key_id` - The key ID of the GPG key, e.g. `3262EFF25BA0D270`

## Import

GPG keys are not importable due to the fact that [API](https://developer.github.com/v3/users/gpg_keys/#gpg-keys)
does not return previously uploaded GPG key.
13 changes: 8 additions & 5 deletions website/github.erb
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,15 @@
<li<%= sidebar_current("docs-github-resource-branch-protection") %>>
<a href="/docs/providers/github/r/branch_protection.html">github_branch_protection</a>
</li>
<li<%= sidebar_current("docs-github-resource-issue-label") %>>
<a href="/docs/providers/github/r/issue_label.html">github_issue_label</a>
</li>
<li<%= sidebar_current("docs-github-resource-membership") %>>
<a href="/docs/providers/github/r/membership.html">github_membership</a>
</li>
<li<%= sidebar_current("docs-github-resource-organization-project") %>>
<a href="/docs/providers/github/r/organization_project.html">github_organization_project</a>
</li>
<li<%= sidebar_current("docs-github-resource-organization-webhook") %>>
<a href="/docs/providers/github/r/organization_webhook.html">github_organization_webhook</a>
</li>
Expand Down Expand Up @@ -64,11 +70,8 @@
<li<%= sidebar_current("docs-github-resource-team-repository") %>>
<a href="/docs/providers/github/r/team_repository.html">github_team_repository</a>
</li>
<li<%= sidebar_current("docs-github-resource-issue-label") %>>
<a href="/docs/providers/github/r/issue_label.html">github_issue_label</a>
</li>
<li<%= sidebar_current("docs-github-resource-organization-project") %>>
<a href="/docs/providers/github/r/organization_project.html">github_organization_project</a>
<li<%= sidebar_current("docs-github-resource-user-gpg-key") %>>
<a href="/docs/providers/github/r/user_gpg_key.html">github_user_gpg_key</a>
</li>
<li<%= sidebar_current("docs-github-resource-user-ssh-key") %>>
<a href="/docs/providers/github/r/user_ssh_key.html">github_user_ssh_key</a>
Expand Down