provider/github: github_repository resource

Allows creation of repositories within the organization configured on the
provider.
This commit is contained in:
Martin Atkins 2016-10-11 10:05:38 -07:00
parent 7fddaf04bd
commit f4ecf72125
3 changed files with 374 additions and 0 deletions

View File

@ -36,6 +36,7 @@ func Provider() terraform.ResourceProvider {
"github_team_membership": resourceGithubTeamMembership(),
"github_team_repository": resourceGithubTeamRepository(),
"github_membership": resourceGithubMembership(),
"github_repository": resourceGithubRepository(),
"github_repository_collaborator": resourceGithubRepositoryCollaborator(),
},

View File

@ -0,0 +1,170 @@
package github
import (
"log"
"github.com/google/go-github/github"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceGithubRepository() *schema.Resource {
return &schema.Resource{
Create: resourceGithubRepositoryCreate,
Read: resourceGithubRepositoryRead,
Update: resourceGithubRepositoryUpdate,
Delete: resourceGithubRepositoryDelete,
Schema: map[string]*schema.Schema{
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"description": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"homepage_url": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"private": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
"has_issues": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
"has_wiki": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
"has_downloads": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
"auto_init": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
"full_name": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"default_branch": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"ssh_clone_url": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"svn_url": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"git_clone_url": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
"http_clone_url": &schema.Schema{
Type: schema.TypeString,
Computed: true,
},
},
}
}
func resourceGithubRepositoryObject(d *schema.ResourceData) *github.Repository {
name := d.Get("name").(string)
description := d.Get("description").(string)
homepageUrl := d.Get("homepage_url").(string)
private := d.Get("private").(bool)
hasIssues := d.Get("has_issues").(bool)
hasWiki := d.Get("has_wiki").(bool)
hasDownloads := d.Get("has_downloads").(bool)
autoInit := d.Get("auto_init").(bool)
repo := &github.Repository{
Name: &name,
Description: &description,
Homepage: &homepageUrl,
Private: &private,
HasIssues: &hasIssues,
HasWiki: &hasWiki,
HasDownloads: &hasDownloads,
AutoInit: &autoInit,
}
return repo
}
func resourceGithubRepositoryCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
repoReq := resourceGithubRepositoryObject(d)
log.Printf("[DEBUG] create github repository %s/%s", meta.(*Organization).name, *repoReq.Name)
repo, _, err := client.Repositories.Create(meta.(*Organization).name, repoReq)
if err != nil {
return err
}
d.SetId(*repo.Name)
return resourceGithubRepositoryRead(d, meta)
}
func resourceGithubRepositoryRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
repoName := d.Id()
log.Printf("[DEBUG] read github repository %s/%s", meta.(*Organization).name, repoName)
repo, resp, err := client.Repositories.Get(meta.(*Organization).name, repoName)
if err != nil {
if resp.StatusCode == 404 {
log.Printf(
"[WARN] removing %s/%s from state because it no longer exists in github",
meta.(*Organization).name,
repoName,
)
d.SetId("")
return nil
}
return err
}
d.Set("description", repo.Description)
d.Set("homepage_url", repo.Homepage)
d.Set("private", repo.Private)
d.Set("has_issues", repo.HasIssues)
d.Set("has_wiki", repo.HasWiki)
d.Set("has_downloads", repo.HasDownloads)
d.Set("full_name", repo.FullName)
d.Set("default_branch", repo.DefaultBranch)
d.Set("ssh_clone_url", repo.SSHURL)
d.Set("svn_url", repo.SVNURL)
d.Set("git_clone_url", repo.GitURL)
d.Set("http_clone_url", repo.CloneURL)
return nil
}
func resourceGithubRepositoryUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
repoReq := resourceGithubRepositoryObject(d)
repoName := d.Id()
log.Printf("[DEBUG] update github repository %s/%s", meta.(*Organization).name, repoName)
_, _, err := client.Repositories.Edit(meta.(*Organization).name, repoName, repoReq)
if err != nil {
return err
}
return resourceGithubRepositoryRead(d, meta)
}
func resourceGithubRepositoryDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
repoName := d.Id()
log.Printf("[DEBUG] delete github repository %s/%s", meta.(*Organization).name, repoName)
_, err := client.Repositories.Delete(meta.(*Organization).name, repoName)
return err
}

View File

@ -0,0 +1,203 @@
package github
import (
"fmt"
"strings"
"testing"
"github.com/google/go-github/github"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestAccGithubRepository_basic(t *testing.T) {
var repo github.Repository
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGithubRepositoryDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGithubRepositoryConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubRepositoryExists("github_repository.foo", &repo),
testAccCheckGithubRepositoryAttributes(&repo, &testAccGithubRepositoryExpectedAttributes{
Name: "foo",
Description: "Terraform acceptance tests",
Homepage: "http://example.com/",
HasIssues: true,
HasWiki: true,
HasDownloads: true,
DefaultBranch: "master",
}),
),
},
resource.TestStep{
Config: testAccGithubRepositoryUpdateConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubRepositoryExists("github_repository.foo", &repo),
testAccCheckGithubRepositoryAttributes(&repo, &testAccGithubRepositoryExpectedAttributes{
Name: "foo",
Description: "Terraform acceptance tests!",
Homepage: "http://example.com/",
DefaultBranch: "master",
}),
),
},
},
})
}
func testAccCheckGithubRepositoryExists(n string, repo *github.Repository) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[n]
if !ok {
return fmt.Errorf("Not Found: %s", n)
}
repoName := rs.Primary.ID
if repoName == "" {
return fmt.Errorf("No repository name is set")
}
org := testAccProvider.Meta().(*Organization)
conn := org.client
gotRepo, _, err := conn.Repositories.Get(org.name, repoName)
if err != nil {
return err
}
*repo = *gotRepo
return nil
}
}
type testAccGithubRepositoryExpectedAttributes struct {
Name string
Description string
Homepage string
Private bool
HasIssues bool
HasWiki bool
HasDownloads bool
DefaultBranch string
}
func testAccCheckGithubRepositoryAttributes(repo *github.Repository, want *testAccGithubRepositoryExpectedAttributes) resource.TestCheckFunc {
return func(s *terraform.State) error {
if *repo.Name != want.Name {
return fmt.Errorf("got repo %q; want %q", *repo.Name, want.Name)
}
if *repo.Description != want.Description {
return fmt.Errorf("got description %q; want %q", *repo.Description, want.Description)
}
if *repo.Homepage != want.Homepage {
return fmt.Errorf("got homepage URL %q; want %q", *repo.Homepage, want.Homepage)
}
if *repo.Private != want.Private {
return fmt.Errorf("got private %#v; want %#v", *repo.Private, want.Private)
}
if *repo.HasIssues != want.HasIssues {
return fmt.Errorf("got has issues %#v; want %#v", *repo.HasIssues, want.HasIssues)
}
if *repo.HasWiki != want.HasWiki {
return fmt.Errorf("got has wiki %#v; want %#v", *repo.HasWiki, want.HasWiki)
}
if *repo.HasDownloads != want.HasDownloads {
return fmt.Errorf("got has downloads %#v; want %#v", *repo.HasDownloads, want.HasDownloads)
}
if *repo.DefaultBranch != want.DefaultBranch {
return fmt.Errorf("got default branch %q; want %q", *repo.DefaultBranch, want.DefaultBranch)
}
// For the rest of these, we just want to make sure they've been
// populated with something that seems somewhat reasonable.
if !strings.HasSuffix(*repo.FullName, "/"+want.Name) {
return fmt.Errorf("got full name %q; want to end with '/%s'", *repo.FullName, want.Name)
}
if !strings.HasSuffix(*repo.CloneURL, "/"+want.Name+".git") {
return fmt.Errorf("got Clone URL %q; want to end with '/%s.git'", *repo.CloneURL, want.Name)
}
if !strings.HasPrefix(*repo.CloneURL, "https://") {
return fmt.Errorf("got Clone URL %q; want to start with 'https://'", *repo.CloneURL)
}
if !strings.HasSuffix(*repo.SSHURL, "/"+want.Name+".git") {
return fmt.Errorf("got SSH URL %q; want to end with '/%s.git'", *repo.SSHURL, want.Name)
}
if !strings.HasPrefix(*repo.SSHURL, "git@github.com:") {
return fmt.Errorf("got SSH URL %q; want to start with 'git@github.com:'", *repo.SSHURL)
}
if !strings.HasSuffix(*repo.GitURL, "/"+want.Name+".git") {
return fmt.Errorf("got git URL %q; want to end with '/%s.git'", *repo.GitURL, want.Name)
}
if !strings.HasPrefix(*repo.GitURL, "git://") {
return fmt.Errorf("got git URL %q; want to start with 'git://'", *repo.GitURL)
}
if !strings.HasSuffix(*repo.SVNURL, "/"+want.Name) {
return fmt.Errorf("got svn URL %q; want to end with '/%s'", *repo.SVNURL, want.Name)
}
if !strings.HasPrefix(*repo.SVNURL, "https://") {
return fmt.Errorf("got svn URL %q; want to start with 'https://'", *repo.SVNURL)
}
return nil
}
}
func testAccCheckGithubRepositoryDestroy(s *terraform.State) error {
conn := testAccProvider.Meta().(*Organization).client
orgName := testAccProvider.Meta().(*Organization).name
for _, rs := range s.RootModule().Resources {
if rs.Type != "github_repository" {
continue
}
gotRepo, resp, err := conn.Repositories.Get(orgName, rs.Primary.ID)
if err == nil {
if gotRepo != nil && *gotRepo.Name == rs.Primary.ID {
return fmt.Errorf("Repository still exists")
}
}
if resp.StatusCode != 404 {
return err
}
return nil
}
return nil
}
const testAccGithubRepositoryConfig = `
resource "github_repository" "foo" {
name = "foo"
description = "Terraform acceptance tests"
homepage_url = "http://example.com/"
# So that acceptance tests can be run in a github organization
# with no billing
private = false
has_issues = true
has_wiki = true
has_downloads = true
}
`
const testAccGithubRepositoryUpdateConfig = `
resource "github_repository" "foo" {
name = "foo"
description = "Terraform acceptance tests!"
homepage_url = "http://example.com/"
# So that acceptance tests can be run in a github organization
# with no billing
private = false
has_issues = false
has_wiki = false
has_downloads = false
}
`