-
Notifications
You must be signed in to change notification settings - Fork 154
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #154 from terraform-providers/leetrout/use-org-mem…
…berships-for-teams Use org memberships for teams
- Loading branch information
Showing
21 changed files
with
864 additions
and
44 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
package tfe | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
|
||
tfe "github.com/hashicorp/go-tfe" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
) | ||
|
||
func resourceTFEOrganizationMembership() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceTFEOrganizationMembershipCreate, | ||
Read: resourceTFEOrganizationMembershipRead, | ||
Delete: resourceTFEOrganizationMembershipDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"email": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"organization": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceTFEOrganizationMembershipCreate(d *schema.ResourceData, meta interface{}) error { | ||
tfeClient := meta.(*tfe.Client) | ||
|
||
// Get the email and organization. | ||
email := d.Get("email").(string) | ||
organization := d.Get("organization").(string) | ||
|
||
// Create a new options struct. | ||
options := tfe.OrganizationMembershipCreateOptions{ | ||
Email: tfe.String(email), | ||
} | ||
|
||
log.Printf("[DEBUG] Create membership %s for organization: %s", email, organization) | ||
membership, err := tfeClient.OrganizationMemberships.Create(ctx, organization, options) | ||
if err != nil { | ||
return fmt.Errorf( | ||
"Error creating membership %s for organization %s: %v", email, organization, err) | ||
} | ||
|
||
d.SetId(membership.ID) | ||
|
||
return resourceTFEOrganizationMembershipRead(d, meta) | ||
} | ||
|
||
func resourceTFEOrganizationMembershipRead(d *schema.ResourceData, meta interface{}) error { | ||
tfeClient := meta.(*tfe.Client) | ||
|
||
log.Printf("[DEBUG] Read configuration of membership: %s", d.Id()) | ||
membership, err := tfeClient.OrganizationMemberships.Read(ctx, d.Id()) | ||
|
||
if err != nil { | ||
if err == tfe.ErrResourceNotFound { | ||
log.Printf("[DEBUG] Membership %s does no longer exist", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
return fmt.Errorf("Error reading configuration of membership %s: %v", d.Id(), err) | ||
} | ||
|
||
// Update the config. | ||
log.Printf("[INFO] User = %#v", membership.User) | ||
d.Set("email", membership.Email) | ||
|
||
return nil | ||
} | ||
|
||
func resourceTFEOrganizationMembershipDelete(d *schema.ResourceData, meta interface{}) error { | ||
tfeClient := meta.(*tfe.Client) | ||
|
||
log.Printf("[DEBUG] Delete membership: %s", d.Id()) | ||
err := tfeClient.OrganizationMemberships.Delete(ctx, d.Id()) | ||
if err != nil { | ||
if err == tfe.ErrResourceNotFound { | ||
return nil | ||
} | ||
return fmt.Errorf("Error deleting membership %s: %v", d.Id(), err) | ||
} | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
package tfe | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
tfe "github.com/hashicorp/go-tfe" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/terraform" | ||
) | ||
|
||
func TestAccTFEOrganizationMembership_basic(t *testing.T) { | ||
mem := &tfe.OrganizationMembership{} | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckTFEOrganizationMembershipDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccTFEOrganizationMembership_basic, | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckTFEOrganizationMembershipExists( | ||
"tfe_organization_membership.foobar", mem), | ||
testAccCheckTFEOrganizationMembershipAttributes(mem), | ||
resource.TestCheckResourceAttr( | ||
"tfe_organization_membership.foobar", "email", "example@hashicorp.com"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckTFEOrganizationMembershipExists( | ||
n string, membership *tfe.OrganizationMembership) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
tfeClient := testAccProvider.Meta().(*tfe.Client) | ||
|
||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", n) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No instance ID is set") | ||
} | ||
|
||
options := tfe.OrganizationMembershipReadOptions{ | ||
Include: "user", | ||
} | ||
|
||
m, err := tfeClient.OrganizationMemberships.ReadWithOptions(ctx, rs.Primary.ID, options) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if m == nil { | ||
return fmt.Errorf("Membership not found") | ||
} | ||
|
||
*membership = *m | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckTFEOrganizationMembershipAttributes( | ||
membership *tfe.OrganizationMembership) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
if membership.User.Email != "example@hashicorp.com" { | ||
return fmt.Errorf("Bad email: %s", membership.User.Email) | ||
} | ||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckTFEOrganizationMembershipDestroy(s *terraform.State) error { | ||
tfeClient := testAccProvider.Meta().(*tfe.Client) | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "tfe_organization_membership" { | ||
continue | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No instance ID is set") | ||
} | ||
|
||
_, err := tfeClient.OrganizationMemberships.Read(ctx, rs.Primary.ID) | ||
if err == nil { | ||
return fmt.Errorf("Membership %s still exists", rs.Primary.ID) | ||
} | ||
} | ||
|
||
return nil | ||
} | ||
|
||
const testAccTFEOrganizationMembership_basic = ` | ||
resource "tfe_organization" "foobar" { | ||
name = "tst-terraform" | ||
email = "admin@company.com" | ||
} | ||
resource "tfe_organization_membership" "foobar" { | ||
email = "example@hashicorp.com" | ||
organization = "${tfe_organization.foobar.id}" | ||
}` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
package tfe | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"strings" | ||
|
||
tfe "github.com/hashicorp/go-tfe" | ||
"github.com/hashicorp/terraform-plugin-sdk/helper/schema" | ||
) | ||
|
||
func resourceTFETeamOrganizationMember() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceTFETeamOrganizationMemberCreate, | ||
Read: resourceTFETeamOrganizationMemberRead, | ||
Delete: resourceTFETeamOrganizationMemberDelete, | ||
Importer: &schema.ResourceImporter{ | ||
State: schema.ImportStatePassthrough, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"team_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"organization_membership_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceTFETeamOrganizationMemberCreate(d *schema.ResourceData, meta interface{}) error { | ||
tfeClient := meta.(*tfe.Client) | ||
|
||
// Get the team ID and username.. | ||
teamID := d.Get("team_id").(string) | ||
organizationMembershipID := d.Get("organization_membership_id").(string) | ||
|
||
// Create a new options struct. | ||
options := tfe.TeamMemberAddOptions{ | ||
OrganizationMembershipIDs: []string{organizationMembershipID}, | ||
} | ||
|
||
log.Printf("[DEBUG] Add organization membership %q to team: %s", organizationMembershipID, teamID) | ||
err := tfeClient.TeamMembers.Add(ctx, teamID, options) | ||
if err != nil { | ||
return fmt.Errorf("Error adding organization membership %q to team %s: %v", organizationMembershipID, teamID, err) | ||
} | ||
|
||
d.SetId(packTeamOrganizationMemberID(teamID, organizationMembershipID)) | ||
|
||
return nil | ||
} | ||
|
||
func resourceTFETeamOrganizationMemberRead(d *schema.ResourceData, meta interface{}) error { | ||
tfeClient := meta.(*tfe.Client) | ||
|
||
// Get the team ID and organization membership id. | ||
teamID, organizationMembershipID, err := unpackTeamOrganizationMemberID(d.Id()) | ||
if err != nil { | ||
return fmt.Errorf("Error unpacking team member ID: %v", err) | ||
} | ||
|
||
log.Printf("[DEBUG] Read organization membership from team: %s", teamID) | ||
organizationMemberships, err := tfeClient.TeamMembers.ListOrganizationMemberships(ctx, teamID) | ||
if err != nil { | ||
if err == tfe.ErrResourceNotFound { | ||
log.Printf("[DEBUG] Organization membership %q does no longer exist", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
return fmt.Errorf("Error reading organization memberships from team %s: %v", teamID, err) | ||
} | ||
|
||
found := false | ||
for _, organizationMembership := range organizationMemberships { | ||
if organizationMembership.ID == organizationMembershipID { | ||
d.Set("team_id", teamID) | ||
d.Set("organization_membership_id", organizationMembershipID) | ||
|
||
found = true | ||
break | ||
} | ||
} | ||
|
||
if !found { | ||
log.Printf("[DEBUG] Organization membership %q no longer exists", d.Id()) | ||
d.SetId("") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceTFETeamOrganizationMemberDelete(d *schema.ResourceData, meta interface{}) error { | ||
tfeClient := meta.(*tfe.Client) | ||
|
||
// Get the team ID and organization membership id. | ||
teamID, organizationMembershipID, err := unpackTeamOrganizationMemberID(d.Id()) | ||
if err != nil { | ||
return fmt.Errorf("Error unpacking team member ID: %v", err) | ||
} | ||
|
||
// Create a new options struct. | ||
options := tfe.TeamMemberRemoveOptions{ | ||
OrganizationMembershipIDs: []string{organizationMembershipID}, | ||
} | ||
|
||
log.Printf("[DEBUG] Remove organization membership %q from team: %s", organizationMembershipID, teamID) | ||
err = tfeClient.TeamMembers.Remove(ctx, teamID, options) | ||
if err != nil { | ||
return fmt.Errorf("Error removing organization membership %q to team %s: %v", organizationMembershipID, teamID, err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func packTeamOrganizationMemberID(teamID, organizationMembershipID string) string { | ||
return teamID + "/" + organizationMembershipID | ||
} | ||
|
||
func unpackTeamOrganizationMemberID(id string) (teamID, organizationMembershipID string, err error) { | ||
s := strings.SplitN(id, "/", 2) | ||
if len(s) != 2 { | ||
return "", "", fmt.Errorf( | ||
"invalid team organization member ID format: %s (expected <TEAM ID>/<ORGANIZATION MEMBERSHIP ID>)", id) | ||
} | ||
|
||
return s[0], s[1], nil | ||
} |
Oops, something went wrong.