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

GitHub Organization Provider #5194

Merged
merged 2 commits into from
Mar 17, 2016
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,6 @@ website/node_modules
*~
.*.swp
.idea
*.iml
*.test
*.iml
4 changes: 4 additions & 0 deletions Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions builtin/bins/provider-github/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"github.com/hashicorp/terraform/builtin/providers/github"
"github.com/hashicorp/terraform/plugin"
)

func main() {
plugin.Serve(&plugin.ServeOpts{
ProviderFunc: github.Provider,
})
}
1 change: 1 addition & 0 deletions builtin/bins/provider-github/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package main
29 changes: 29 additions & 0 deletions builtin/providers/github/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package github

import (
"github.com/google/go-github/github"
"golang.org/x/oauth2"
)

type Config struct {
Token string
Organization string
}

type Organization struct {
name string
client *github.Client
}

// Client configures and returns a fully initialized GithubClient
func (c *Config) Client() (interface{}, error) {
var org Organization
org.name = c.Organization
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: c.Token},
)
tc := oauth2.NewClient(oauth2.NoContext, ts)

org.client = github.NewClient(tc)
return &org, nil
}
56 changes: 56 additions & 0 deletions builtin/providers/github/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
package github

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

// Provider returns a terraform.ResourceProvider.
func Provider() terraform.ResourceProvider {

// The actual provider
return &schema.Provider{
Schema: map[string]*schema.Schema{
"token": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("GITHUB_TOKEN", nil),
Description: descriptions["token"],
},
"organization": &schema.Schema{
Type: schema.TypeString,
Required: true,
DefaultFunc: schema.EnvDefaultFunc("GITHUB_ORGANIZATION", nil),
Description: descriptions["organization"],
},
},

ResourcesMap: map[string]*schema.Resource{
"github_team": resourceGithubTeam(),
"github_team_membership": resourceGithubTeamMembership(),
"github_team_repository": resourceGithubTeamRepository(),
"github_membership": resourceGithubMembership(),
},

ConfigureFunc: providerConfigure,
}
}

var descriptions map[string]string

func init() {
descriptions = map[string]string{
"token": "The OAuth token used to connect to GitHub.",

"organization": "The GitHub organization name to manage.",
}
}

func providerConfigure(d *schema.ResourceData) (interface{}, error) {
config := Config{
Token: d.Get("token").(string),
Organization: d.Get("organization").(string),
}

return config.Client()
}
38 changes: 38 additions & 0 deletions builtin/providers/github/provider_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package github

import (
"os"
"testing"

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

var testAccProviders map[string]terraform.ResourceProvider
var testAccProvider *schema.Provider

func init() {
testAccProvider = Provider().(*schema.Provider)
testAccProviders = map[string]terraform.ResourceProvider{
"github": testAccProvider,
}
}

func TestProvider(t *testing.T) {
if err := Provider().(*schema.Provider).InternalValidate(); err != nil {
t.Fatalf("err: %s", err)
}
}

func TestProvider_impl(t *testing.T) {
var _ terraform.ResourceProvider = Provider()
}

func testAccPreCheck(t *testing.T) {
if v := os.Getenv("GITHUB_TOKEN"); v == "" {
t.Fatal("GITHUB_TOKEN must be set for acceptance tests")
}
if v := os.Getenv("GITHUB_ORGANIZATION"); v == "" {
t.Fatal("GITHUB_ORGANIZATION must be set for acceptance tests")
}
}
85 changes: 85 additions & 0 deletions builtin/providers/github/resource_github_membership.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package github

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

func resourceGithubMembership() *schema.Resource {

return &schema.Resource{
Create: resourceGithubMembershipCreate,
Read: resourceGithubMembershipRead,
Update: resourceGithubMembershipUpdate,
Delete: resourceGithubMembershipDelete,

Schema: map[string]*schema.Schema{
"username": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"role": &schema.Schema{
Type: schema.TypeString,
Optional: true,
ValidateFunc: validateRoleValueFunc([]string{"member", "admin"}),
Default: "member",
},
},
}
}

func resourceGithubMembershipCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
n := d.Get("username").(string)
r := d.Get("role").(string)

membership, _, err := client.Organizations.EditOrgMembership(n, meta.(*Organization).name,
&github.Membership{Role: &r})
if err != nil {
return err
}

d.SetId(buildTwoPartID(membership.Organization.Login, membership.User.Login))

return resourceGithubMembershipRead(d, meta)
}

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

membership, _, err := client.Organizations.GetOrgMembership(d.Get("username").(string), meta.(*Organization).name)
if err != nil {
d.SetId("")
return nil
}
username := membership.User.Login
roleName := membership.Role

d.Set("username", *username)
d.Set("role", *roleName)
return nil
}

func resourceGithubMembershipUpdate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
n := d.Get("username").(string)
r := d.Get("role").(string)

_, _, err := client.Organizations.EditOrgMembership(n, meta.(*Organization).name, &github.Membership{
Role: &r,
})
if err != nil {
return err
}
return nil
}

func resourceGithubMembershipDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Organization).client
n := d.Get("username").(string)

_, err := client.Organizations.RemoveOrgMembership(n, meta.(*Organization).name)

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

import (
"fmt"
"testing"

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

func TestAccGithubMembership_basic(t *testing.T) {
var membership github.Membership

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckGithubMembershipDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccGithubMembershipConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckGithubMembershipExists("github_membership.test_org_membership", &membership),
testAccCheckGithubMembershipRoleState("github_membership.test_org_membership", &membership),
),
},
},
})
}

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

for _, rs := range s.RootModule().Resources {
if rs.Type != "github_membership" {
continue
}
o, u := parseTwoPartID(rs.Primary.ID)

membership, resp, err := conn.Organizations.GetOrgMembership(u, o)

if err == nil {
if membership != nil &&
buildTwoPartID(membership.Organization.Login, membership.User.Login) == rs.Primary.ID {
return fmt.Errorf("Organization membership still exists")
}
}
if resp.StatusCode != 404 {
return err
}
return nil
}
return nil
}

func testAccCheckGithubMembershipExists(n string, membership *github.Membership) 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, u := parseTwoPartID(rs.Primary.ID)

githubMembership, _, err := conn.Organizations.GetOrgMembership(u, o)
if err != nil {
return err
}
*membership = *githubMembership
return nil
}
}

func testAccCheckGithubMembershipRoleState(n string, membership *github.Membership) 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, u := parseTwoPartID(rs.Primary.ID)

githubMembership, _, err := conn.Organizations.GetOrgMembership(u, o)
if err != nil {
return err
}

resourceRole := membership.Role
actualRole := githubMembership.Role

if *resourceRole != *actualRole {
return fmt.Errorf("Membership role %v in resource does match actual state of %v", *resourceRole, *actualRole)
}
return nil
}
}

const testAccGithubMembershipConfig = `
resource "github_membership" "test_org_membership" {
username = "TerraformDummyUser"
role = "member"
}
`
Loading