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

provider/github Add repository deploy key resource to provider github #15215

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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 builtin/providers/github/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func Provider() terraform.ResourceProvider {
"github_team_repository": resourceGithubTeamRepository(),
"github_membership": resourceGithubMembership(),
"github_repository": resourceGithubRepository(),
"github_repository_deploy_key": resourceGithubRepositoryDeployKey(),
"github_repository_webhook": resourceGithubRepositoryWebhook(),
"github_organization_webhook": resourceGithubOrganizationWebhook(),
"github_repository_collaborator": resourceGithubRepositoryCollaborator(),
Expand Down
120 changes: 120 additions & 0 deletions builtin/providers/github/resource_github_repository_deploy_key.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package github

import (
"context"
"strconv"

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

func resourceGithubRepositoryDeployKey() *schema.Resource {
return &schema.Resource{
Create: resourceGithubRepositoryDeployKeyCreate,
Read: resourceGithubRepositoryDeployKeyRead,
// Deploy keys are defined immutable in the API. Updating results in force new.
Delete: resourceGithubRepositoryDeployKeyDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"key": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"read_only": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
ForceNew: true,
Default: true,
},
"repository": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"title": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}

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

repo := d.Get("repository").(string)

k := d.Get("key").(string)
t := d.Get("title").(string)
key := &github.Key{
Key: &k,
Title: &t,
}

if readOnly, ok := d.GetOk("read_only"); ok {
Copy link
Contributor

Choose a reason for hiding this comment

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

We have a default value - therefore, there is no need for the d.GetOk("") here - it will always be there

We can replace this and do it inline in the &github.Key like Key and Title

pReadOnly := readOnly.(bool)
key.ReadOnly = &pReadOnly
}

owner := meta.(*Organization).name
resultKey, _, err := client.Repositories.CreateKey(context.TODO(), owner, repo, key)

if err != nil {
return err
}

i := strconv.Itoa(*resultKey.ID)
id := buildTwoPartID(&repo, &i)

d.SetId(id)

return resourceGithubRepositoryDeployKeyRead(d, meta)
}

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

owner := meta.(*Organization).name
repo, id := parseTwoPartID(d.Id())

i, err := strconv.Atoi(id)
if err != nil {
return err
}

key, _, err := client.Repositories.GetKey(context.TODO(), owner, repo, i)
if err != nil {
return err
}

d.Set("key", *key.Key)
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's not dereference these - d.Set takes care of this safely

d.Set("read_only", *key.ReadOnly)
d.Set("repository", repo)
d.Set("title", *key.Title)

return nil
}

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

owner := meta.(*Organization).name
repo, id := parseTwoPartID(d.Id())

i, err := strconv.Atoi(id)
if err != nil {
return err
}

_, err = client.Repositories.DeleteKey(context.TODO(), owner, repo, i)
if err != nil {
return err
}

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

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

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

const testRepo string = "test-repo"

func TestAccGithubRepositoryDeployKey_basic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGithubRepositoryDeployKeyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGithubRepositoryDeployKeyConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubRepositoryDeployKeyExists("github_repository_deploy_key.test_repo_deploy_key"),
resource.TestCheckResourceAttr("github_repository_deploy_key.test_repo_deploy_key", "read_only", "false"),
resource.TestCheckResourceAttr("github_repository_deploy_key.test_repo_deploy_key", "repository", testRepo),
resource.TestCheckResourceAttr("github_repository_deploy_key.test_repo_deploy_key", "key", testAccGithubRepositoryDeployKeytestDeployKey),
resource.TestCheckResourceAttr("github_repository_deploy_key.test_repo_deploy_key", "title", "title"),
),
},
},
})
}

func TestAccGithubRepositoryDeployKey_importBasic(t *testing.T) {
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGithubRepositoryDeployKeyDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGithubRepositoryDeployKeyConfig,
},
resource.TestStep{
ResourceName: "github_repository_deploy_key.test_repo_deploy_key",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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

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

o := testAccProvider.Meta().(*Organization).name
r, i := parseTwoPartID(rs.Primary.ID)
id, err := strconv.Atoi(i)
if err != nil {
return err
}

_, resp, err := conn.Repositories.GetKey(context.TODO(), o, r, id)

if err != nil && resp.Response.StatusCode != 404 {
return err
}
return nil
}

return nil
}

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

if rs.Primary.ID == "" {
return fmt.Errorf("No membership ID is set")
}

conn := testAccProvider.Meta().(*Organization).client
o := testAccProvider.Meta().(*Organization).name
r, i := parseTwoPartID(rs.Primary.ID)
id, err := strconv.Atoi(i)
if err != nil {
return err
}

_, _, err = conn.Repositories.GetKey(context.TODO(), o, r, id)
if err != nil {
return err
}

return nil
}
}

const testAccGithubRepositoryDeployKeytestDeployKey = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDnDk1liOxXwE27fjOVVHl6RNVgQznGqGIfhsoa5QNfLOcoWJR3EIv44dSUx1GSvxQ7uR9qBY/i/SEdAbKdupo3Ru5sykc0GqaMRVys+Cin/Lgnl6+ntmTZOudNjIbz10Vfu/dKmexSzqlD3XWzPGXRI5WyKWzvc2XKjRdfnOOzogJpqJ5kh/CN0ZhCzBPTu/b4mJl2ionTEzEeLK2g4Re4IuU/dGoyf0LGLidjmqhSY7dQtL+mfte9m3x/BQTrDf0+AW3kGWXR8EL0EyIJ2HRtHW67YnoOcTAFK0hDCuKgvt78rqdUQ2bVjcsIhNqnvQMPf3ZeZ5bP2JqB9zKaFl8uaRJv+TdxEeFTkgnbYb85M+aBggBYr6xxeb24g7WlU0iPxJ8GmjvCizxe2I1DOJDRDozn1sinKjapNRdJy00iuo46TJC5Wgmid0vnMJ7SMZtubz+btxhoFLt4F4U2JnILaYG4/buJg4H/GkqmkE8G3hr4b4mgsFXBtBFgK6uCTFQSvvV7TyyWkZxHL6DRCxL/Dp0bSj+EM8Tw1K304EvkBEO3rMyvPs4nXL7pepyKWalmUI8U4Qp2xMXSq7fmfZY55osb03MUAtKl0wJ/ykyKOwYWeLbubSVcc6VPx5bXZmnM5bTcZdYW9+vNt86X2F2b0h/sIkGNEPpqQQBzElY+fQ=="

var testAccGithubRepositoryDeployKeyConfig = fmt.Sprintf(`
resource "github_repository_deploy_key" "test_repo_deploy_key" {
key = "%s"
read_only = "false"
repository = "%s"
title = "title"
}
`, testAccGithubRepositoryDeployKeytestDeployKey, testRepo)
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
layout: "github"
page_title: "GitHub: github_repository_deploy_key"
sidebar_current: "docs-github-resource-repository-deploy-key"
description: |-
Provides a GitHub repository deploy key resource.
---

# github_repository_deploy_key

Provides a GitHub repository deploy key resource.

A deploy key is an SSH key that is stored on your server and grants
access to a single GitHub repository. This key is attached directly to the repository instead of to a personal user
account.

This resource allows you to add/remove repository deploy keys.

Further documentation on GitHub repository deploy keys:
- [About deploy keys](https://developer.github.com/guides/managing-deploy-keys/#deploy-keys)

## Example Usage

```hcl
# Add a deploy key
resource "github_repository_deploy_key" "example_repository_deploy_key" {
title = "Repository test key"
repository = "test-repo"
key = "ssh-rsa AAA..."
read_only = "false"
}
```


## Argument Reference

The following arguments are supported:

* `key` - (Required) A ssh key.
* `read_only` - (Required) A boolean qualifying the key to be either read only or read/write.
* `repository` - (Required) Name of the Github repository.
* `title` - (Required) A title.

Changing any of the fields forces re-creating the resource.
Copy link
Contributor

Choose a reason for hiding this comment

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

Please can you add the import section to the bottom of the docs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@stack72 Thanks a ton!

3 changes: 3 additions & 0 deletions website/source/layouts/github.erb
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
<li<%= sidebar_current("docs-github-resource-repository-collaborator") %>>
<a href="/docs/providers/github/r/repository_collaborator.html">github_repository_collaborator</a>
</li>
<li<%= sidebar_current("docs-github-resource-repository-deploy-key") %>>
<a href="/docs/providers/github/r/repository_deploy_key.html">github_repository_deploy_key</a>
</li>
<li<%= sidebar_current("docs-github-resource-repository-webhook") %>>
<a href="/docs/providers/github/r/repository_webhook.html">github_repository_webhook</a>
</li>
Expand Down