Skip to content

Commit

Permalink
New Resource: github_user_ssh_key
Browse files Browse the repository at this point in the history
  • Loading branch information
radeksimko committed Aug 9, 2018
1 parent 83c7897 commit df60b9b
Show file tree
Hide file tree
Showing 6 changed files with 266 additions and 0 deletions.
1 change: 1 addition & 0 deletions github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ func Provider() terraform.ResourceProvider {
"github_team": resourceGithubTeam(),
"github_team_membership": resourceGithubTeamMembership(),
"github_team_repository": resourceGithubTeamRepository(),
"github_user_ssh_key": resourceGithubUserSshKey(),
},

DataSourcesMap: map[string]*schema.Resource{
Expand Down
2 changes: 2 additions & 0 deletions github/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
"github.com/terraform-providers/terraform-provider-tls/tls"
)

var testUser string = os.Getenv("GITHUB_TEST_USER")
Expand All @@ -24,6 +25,7 @@ func init() {
testAccProvider = Provider().(*schema.Provider)
testAccProviders = map[string]terraform.ResourceProvider{
"github": testAccProvider,
"tls": tls.Provider(),
}
}

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

import (
"context"
"strconv"
"strings"

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

func resourceGithubUserSshKey() *schema.Resource {
return &schema.Resource{
Create: resourceGithubUserSshKeyCreate,
Read: resourceGithubUserSshKeyRead,
Delete: resourceGithubUserSshKeyDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"title": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"key": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: func(k, oldV, newV string, d *schema.ResourceData) bool {
newTrimmed := strings.TrimSpace(newV)
return oldV == newTrimmed
},
},
"url": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

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

title := d.Get("title").(string)
key := d.Get("key").(string)

userKey, _, err := client.Users.CreateKey(context.TODO(), &github.Key{
Title: &title,
Key: &key,
})
if err != nil {
return err
}

d.SetId(strconv.FormatInt(*userKey.ID, 10))

return resourceGithubUserSshKeyRead(d, meta)
}

func resourceGithubUserSshKeyRead(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.GetKey(context.TODO(), id)
if err != nil {
d.SetId("")
return nil
}

d.Set("title", key.Title)
d.Set("key", key.Key)
d.Set("url", key.URL)

return nil
}

func resourceGithubUserSshKeyDelete(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.DeleteKey(context.TODO(), id)

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

import (
"context"
"fmt"
"regexp"
"strconv"
"testing"

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

func TestAccGithubUserSshKey_basic(t *testing.T) {
var key github.Key
randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
title := fmt.Sprintf("tf-acc-test-%s", randString)
keyRe := regexp.MustCompile("^ecdsa-sha2-nistp384 ")
urlRe := regexp.MustCompile("^https://api.github.com/[a-z0-9]+/keys/")

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGithubUserSshKeyDestroy,
Steps: []resource.TestStep{
{
Config: testAccGithubUserSshKeyConfig(title),
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubUserSshKeyExists("github_user_ssh_key.test", &key),
resource.TestCheckResourceAttr("github_user_ssh_key.test", "title", title),
resource.TestMatchResourceAttr("github_user_ssh_key.test", "key", keyRe),
resource.TestMatchResourceAttr("github_user_ssh_key.test", "url", urlRe),
),
},
},
})
}

func TestAccGithubUserSshKey_importBasic(t *testing.T) {
randString := acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum)
title := fmt.Sprintf("tf-acc-test-%s", randString)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGithubUserSshKeyDestroy,
Steps: []resource.TestStep{
{
Config: testAccGithubUserSshKeyConfig(title),
},
{
ResourceName: "github_user_ssh_key.test",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckGithubUserSshKeyExists(n string, key *github.Key) 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.GetKey(context.TODO(), id)
if err != nil {
return err
}
*key = *receivedKey
return nil
}
}

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

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

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

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

func testAccGithubUserSshKeyConfig(title string) string {
return fmt.Sprintf(`
resource "github_user_ssh_key" "test" {
title = "%s"
key = "${tls_private_key.test.public_key_openssh}"
}
resource "tls_private_key" "test" {
algorithm = "ECDSA"
ecdsa_curve = "P384"
}
`, title)
}
44 changes: 44 additions & 0 deletions website/docs/r/user_ssh_key.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
layout: "github"
page_title: "GitHub: github_user_ssh_key"
sidebar_current: "docs-github-resource-user-ssh-key"
description: |-
Provides a GitHub user's SSH key resource.
---

# github_user_ssh_key

Provides a GitHub user's SSH key resource.

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

## Example Usage

```hcl
resource "github_user_ssh_key" "example" {
title = "example title"
key = "${file("~/.ssh/id_rsa.pub")}"
}
```

## Argument Reference

The following arguments are supported:

* `title` - (Required) A descriptive name for the new key. e.g. `Personal MacBook Air`
* `key` - (Required) The public SSH key to add to your GitHub account.

## Attributes Reference

The following attributes are exported:

* `id` - The ID of the SSH key
* `url` - The URL of the SSH key

## Import

SSH keys can be imported using the their ID e.g.

```
$ terraform import github_user_ssh_key.example 1234567
```
3 changes: 3 additions & 0 deletions website/github.erb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@
<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-user-ssh-key") %>>
<a href="/docs/providers/github/r/user_ssh_key.html">github_user_ssh_key</a>
</li>
</ul>
</li>
</ul>
Expand Down

0 comments on commit df60b9b

Please sign in to comment.