generated from hashicorp/terraform-provider-scaffolding
-
Notifications
You must be signed in to change notification settings - Fork 55
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
260abbb
commit a2282dd
Showing
5 changed files
with
351 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
// Use IntelliSense to learn about possible attributes. | ||
// Hover to view descriptions of existing attributes. | ||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 | ||
"version": "0.2.0", | ||
"configurations": [ | ||
{ | ||
"name": "Launch a test function", | ||
"type": "go", | ||
"request": "launch", | ||
"mode": "auto", | ||
"program": "${fileDirname}", | ||
"env": {"PKG_NAME": "${relativeFileDirname}"}, | ||
"args": [ | ||
"-test.v", | ||
"-test.run", | ||
"^${selectedText}$" | ||
], | ||
"showLog": true, | ||
"envFile": "${workspaceFolder}/.vscode/private.env" | ||
} | ||
] | ||
} |
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,3 @@ | ||
TF_ACC=1 | ||
TF_LOG=INFO | ||
GOFLAGS='-mod=readonly' |
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,127 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package provider | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/hashicorp/boundary/api/users" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
// const ( | ||
// loginNameKey = "login_name" | ||
// primaryAccountID = "primary_account_id" | ||
// ) | ||
|
||
func dataSourceUser() *schema.Resource { | ||
return &schema.Resource{ | ||
Description: "The user data source allows you to find a Boundary user.", | ||
ReadContext: resourceUserRead, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
IDKey: { | ||
Description: "The ID of the user.", | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
NameKey: { | ||
Description: "The username.", | ||
Type: schema.TypeString, | ||
Required: true, | ||
}, | ||
DescriptionKey: { | ||
Description: "The user description.", | ||
Type: schema.TypeString, | ||
Computed: true, | ||
}, | ||
ScopeIdKey: { | ||
Description: "The scope ID in which the resource is created. Defaults to the provider's `default_scope` if unset.", | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
Default: "global", | ||
}, | ||
userAccountIDsKey: { | ||
Description: "Account ID's to associate with this user resource.", | ||
Type: schema.TypeSet, | ||
Computed: true, | ||
Elem: &schema.Schema{Type: schema.TypeString}, | ||
}, | ||
// TODO: add after basic functionality works | ||
|
||
// authorizedActions: { | ||
// Description: "A list of actions that the worker is entitled to perform.", | ||
// Type: schema.TypeList, | ||
// Elem: &schema.Schema{ | ||
// Type: schema.TypeString, | ||
// }, | ||
// Computed: true, | ||
// }, | ||
// loginNameKey: { | ||
// Description: "Login name for user.", | ||
// Type: schema.TypeString, | ||
// Computed: true, | ||
// }, | ||
// primaryAccountID: { | ||
// Description: "Primary account ID.", | ||
// Type: schema.TypeString, | ||
// Computed: true, | ||
// }, | ||
}, | ||
} | ||
} | ||
|
||
func dataSourceUserRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { | ||
md := meta.(*metaData) | ||
usrs := users.NewClient(md.client) | ||
|
||
opts := []users.Option{} | ||
|
||
// Get user ID using name | ||
name := d.Get("name").(string) | ||
scopeID := d.Get("scope_id").(string) | ||
|
||
opts = append(opts, users.WithName(name)) | ||
|
||
usersList, err := usrs.List(ctx, scopeID, opts...) | ||
|
||
if err != nil { | ||
return diag.Errorf("error calling list user: %v", err) | ||
} | ||
users := usersList.GetItems() | ||
|
||
// check length, 0 means no user, > 1 means too many | ||
if len(users) == 0 || users[0] == nil { | ||
return diag.Errorf("no matching user found: %v", err) | ||
} | ||
|
||
if len(users) > 1 { | ||
return diag.Errorf("error found more than 1 user: %v", err) | ||
} | ||
|
||
if err := setFromUserItem(d, *users[0]); err != nil { | ||
return diag.FromErr(err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func setFromUserItem(d *schema.ResourceData, user users.User) error { | ||
if err := d.Set(NameKey, user.Name); err != nil { | ||
return err | ||
} | ||
if err := d.Set(DescriptionKey, user.Description); err != nil { | ||
return err | ||
} | ||
if err := d.Set(ScopeIdKey, user.ScopeId); err != nil { | ||
return err | ||
} | ||
if err := d.Set(userAccountIDsKey, user.AccountIds); err != nil { | ||
return err | ||
} | ||
d.SetId(user.Id) | ||
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,195 @@ | ||
// Copyright (c) HashiCorp, Inc. | ||
// SPDX-License-Identifier: MPL-2.0 | ||
|
||
package provider | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/hashicorp/boundary/testing/controller" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
var ( | ||
orgUserDataSource = fmt.Sprintf(` | ||
resource "boundary_user" "org1" { | ||
name = "test" | ||
description = "%s" | ||
scope_id = boundary_scope.org1.id | ||
depends_on = [boundary_role.org1_admin] | ||
} | ||
data "boundary_user" "org1" { | ||
name = "test" | ||
scope_id = boundary_scope.org1.id | ||
depends_on = [boundary_user.org1] | ||
}`, fooDescription) | ||
|
||
// orgUserUpdate = fmt.Sprintf(` | ||
// resource "boundary_user" "org1" { | ||
// name = "test" | ||
// description = "%s" | ||
// scope_id = boundary_scope.org1.id | ||
// depends_on = [boundary_role.org1_admin] | ||
// }`, fooDescriptionUpdate) | ||
|
||
// orgUserWithAccts = ` | ||
// resource "boundary_user" "org1" { | ||
// name = "test" | ||
// description = "with accts" | ||
// scope_id = boundary_scope.org1.id | ||
// account_ids = [ | ||
// boundary_account.foo.id | ||
// ] | ||
// depends_on = [boundary_role.org1_admin] | ||
// }` | ||
|
||
// orgUserWithAcctsUpdate = ` | ||
// | ||
// resource "boundary_user" "org1" { | ||
// name = "test" | ||
// description = "with accts" | ||
// scope_id = boundary_scope.org1.id | ||
// depends_on = [boundary_role.org1_admin] | ||
// }` | ||
) | ||
|
||
// NOTE: this test also tests out the direct token auth mechanism. | ||
|
||
func TestAccUserDataSource(t *testing.T) { | ||
tc := controller.NewTestController(t, tcConfig...) | ||
defer tc.Shutdown() | ||
url := tc.ApiAddrs()[0] | ||
token := tc.Token().Token | ||
|
||
resourceName := "boundary_user.org1" | ||
dataSourceName := "data.boundary_user.org1" | ||
|
||
var provider *schema.Provider | ||
resource.Test(t, resource.TestCase{ | ||
ProviderFactories: providerFactories(&provider), | ||
CheckDestroy: testAccCheckUserResourceDestroy(t, provider), | ||
Steps: []resource.TestStep{ | ||
{ | ||
// test create | ||
Config: testConfigWithToken(url, token, fooOrg, orgUserDataSource), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckUserResourceExists(provider, resourceName), | ||
resource.TestCheckResourceAttr(dataSourceName, DescriptionKey, fooDescription), | ||
resource.TestCheckResourceAttr(dataSourceName, NameKey, "test"), | ||
), | ||
}, | ||
// importStep("boundary_user.org1"), | ||
// { | ||
// // test update description | ||
// Config: testConfigWithToken(url, token, fooOrg, orgUserUpdate), | ||
// Check: resource.ComposeTestCheckFunc( | ||
// testAccCheckUserResourceExists(provider, "boundary_user.org1"), | ||
// resource.TestCheckResourceAttr("boundary_user.org1", DescriptionKey, fooDescriptionUpdate), | ||
// resource.TestCheckResourceAttr("boundary_user.org1", NameKey, "test"), | ||
// ), | ||
// }, | ||
// importStep("boundary_user.org1"), | ||
}, | ||
}) | ||
} | ||
|
||
// func TestAccUserWithAccounts(t *testing.T) { | ||
// tc := controller.NewTestController(t, tcConfig...) | ||
// defer tc.Shutdown() | ||
// url := tc.ApiAddrs()[0] | ||
// token := tc.Token().Token | ||
|
||
// var provider *schema.Provider | ||
// resource.Test(t, resource.TestCase{ | ||
// ProviderFactories: providerFactories(&provider), | ||
// CheckDestroy: testAccCheckUserResourceDestroy(t, provider), | ||
// Steps: []resource.TestStep{ | ||
// { | ||
// // test create | ||
// Config: testConfigWithToken(url, token, fooOrg, fooAccount, orgUserWithAccts), | ||
// Check: resource.ComposeTestCheckFunc( | ||
// testAccCheckUserResourceExists(provider, "boundary_user.org1"), | ||
// testAccCheckAccountResourceExists(provider, "boundary_account.foo"), | ||
// resource.TestCheckResourceAttr("boundary_user.org1", DescriptionKey, "with accts"), | ||
// resource.TestCheckResourceAttr("boundary_user.org1", NameKey, "test"), | ||
// testAccCheckUserResourceAccountsSet(provider, "boundary_user.org1", []string{"boundary_account.foo"}), | ||
// ), | ||
// }, | ||
// importStep("boundary_user.org1"), | ||
// importStep("boundary_account.foo", "password"), | ||
// { | ||
// // test update description | ||
// Config: testConfigWithToken(url, token, fooOrg, fooAccount, orgUserWithAcctsUpdate), | ||
// Check: resource.ComposeTestCheckFunc( | ||
// testAccCheckUserResourceExists(provider, "boundary_user.org1"), | ||
// testAccCheckAccountResourceExists(provider, "boundary_account.foo"), | ||
// resource.TestCheckResourceAttr("boundary_user.org1", DescriptionKey, "with accts"), | ||
// resource.TestCheckResourceAttr("boundary_user.org1", NameKey, "test"), | ||
// ), | ||
// }, | ||
// importStep("boundary_user.org1"), | ||
// importStep("boundary_account.foo", "password"), | ||
// }, | ||
// }) | ||
// } | ||
|
||
// func testAccCheckUserResourceAccountsSet(testProvider *schema.Provider, name string, accounts []string) resource.TestCheckFunc { | ||
// return func(s *terraform.State) error { | ||
// rs, ok := s.RootModule().Resources[name] | ||
// if !ok { | ||
// return fmt.Errorf("user resource not found: %s", name) | ||
// } | ||
|
||
// id := rs.Primary.ID | ||
// if id == "" { | ||
// return fmt.Errorf("user resource ID is not set") | ||
// } | ||
|
||
// // ensure accts are declared in state | ||
// acctIDs := []string{} | ||
// for _, acctResourceName := range acctIDs { | ||
// ur, ok := s.RootModule().Resources[acctResourceName] | ||
// if !ok { | ||
// return fmt.Errorf("account resource not found: %s", acctResourceName) | ||
// } | ||
|
||
// acctID := ur.Primary.ID | ||
// if id == "" { | ||
// return fmt.Errorf("account resource ID not set") | ||
// } | ||
|
||
// acctIDs = append(acctIDs, acctID) | ||
// } | ||
|
||
// // check boundary to ensure it matches | ||
// md := testProvider.Meta().(*metaData) | ||
// usrClient := users.NewClient(md.client) | ||
|
||
// u, err := usrClient.Read(context.Background(), id) | ||
// if err != nil { | ||
// return fmt.Errorf("Got an error when reading user %q: %v", id, err) | ||
// } | ||
|
||
// // for every account set on the user in the state, ensure | ||
// // each group in boundary has the same setings | ||
// if len(u.Item.AccountIds) == 0 { | ||
// return fmt.Errorf("no account found on user") | ||
// } | ||
|
||
// for _, stateAccount := range acctIDs { | ||
// ok := false | ||
// for _, gotAccount := range u.Item.AccountIds { | ||
// if gotAccount == stateAccount { | ||
// ok = true | ||
// } | ||
// } | ||
// if !ok { | ||
// return fmt.Errorf("account in state not set in boundary:\n in state: %+v\n in boundary: %+v", acctIDs, u.Item.AccountIds) | ||
// } | ||
// } | ||
|
||
// 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