diff --git a/docs/data-sources/user.md b/docs/data-sources/user.md index 8dc5330a..4f362853 100644 --- a/docs/data-sources/user.md +++ b/docs/data-sources/user.md @@ -18,13 +18,13 @@ data "boundary_user" "global_scope_admin" { } # User from a org scope -data "boundary_user" "org_user" { - name = "username" - scope_id = data.boundary_scope.org.id -} - data "boundary_scope" "org" { name = "my-org" + scope_id = "global" +} + +data "boundary_user" "org_user" { + name = "username" scope_id = data.boundary_scope.org.id } ``` diff --git a/examples/data-sources/boundary_user/data-source.tf b/examples/data-sources/boundary_user/data-source.tf index bf2fe63b..14aca79b 100644 --- a/examples/data-sources/boundary_user/data-source.tf +++ b/examples/data-sources/boundary_user/data-source.tf @@ -4,12 +4,12 @@ data "boundary_user" "global_scope_admin" { } # User from a org scope -data "boundary_user" "org_user" { - name = "username" - scope_id = data.boundary_scope.org.id -} - data "boundary_scope" "org" { name = "my-org" + scope_id = "global" +} + +data "boundary_user" "org_user" { + name = "username" scope_id = data.boundary_scope.org.id } diff --git a/internal/provider/const.go b/internal/provider/const.go index 8945b944..04088bfc 100644 --- a/internal/provider/const.go +++ b/internal/provider/const.go @@ -56,4 +56,6 @@ const ( ParentScopeIdKey = "parent_scope_id" // GroupMemberIdsKey is used for common "member_ids" resource attribute GroupMemberIdsKey = "member_ids" + // UserAccountIdsKey is used for common "account_ids" resource attribute + UserAccountIdsKey = "account_ids" ) diff --git a/internal/provider/data_source_scope.go b/internal/provider/data_source_scope.go index 8b5eff3c..a940c218 100644 --- a/internal/provider/data_source_scope.go +++ b/internal/provider/data_source_scope.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/boundary/api/scopes" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" ) func dataSourceScope() *schema.Resource { @@ -19,71 +20,57 @@ func dataSourceScope() *schema.Resource { ReadContext: dataSourceScopeRead, Schema: map[string]*schema.Schema{ + NameKey: { + Description: "The name of the scope to retrieve.", + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, + ScopeIdKey: { + Description: "The parent scope ID that will be queried for the scope.", + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + }, IDKey: { Description: "The ID of the retrieved scope.", Type: schema.TypeString, Computed: true, }, - NameKey: { - Description: "The name of the scope to retrieve.", - Type: schema.TypeString, - Required: true, - }, DescriptionKey: { Description: "The description of the retrieved scope.", Type: schema.TypeString, Computed: true, }, - ScopeIdKey: { - Description: "The parent scope ID that will be queried for the scope.", - Type: schema.TypeString, - Required: true, - }, }, } } func dataSourceScopeRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics { md := meta.(*metaData) - opts := []scopes.Option{} - - var name string - if v, ok := d.GetOk(NameKey); ok { - name = v.(string) - } else { - return diag.Errorf("no name provided") - } - - var scopeId string - if scopeIdVal, ok := d.GetOk(ScopeIdKey); ok { - scopeId = scopeIdVal.(string) - } else { - return diag.Errorf("no parent scope ID provided") - } - scp := scopes.NewClient(md.client) + name := d.Get(NameKey).(string) + scopeId := d.Get(ScopeIdKey).(string) - scpls, err := scp.List(ctx, scopeId, opts...) + scl := scopes.NewClient(md.client) + scopesList, err := scl.List(ctx, scopeId, + scopes.WithFilter(FilterWithItemNameMatches(name)), + ) if err != nil { return diag.Errorf("error calling list scope: %v", err) } - if scpls == nil { + scopes := scopesList.GetItems() + if scopes == nil { return diag.Errorf("no scopes found") } - - var scopeIdRead string - for _, scopeItem := range scpls.GetItems() { - if scopeItem.Name == name { - scopeIdRead = scopeItem.Id - break - } + if len(scopes) == 0 { + return diag.Errorf("no matching scope found") } - - if scopeIdRead == "" { - return diag.Errorf("scope name %v not found in scope list", err) + if len(scopes) > 1 { + return diag.Errorf("error found more than 1 scope") } - srr, err := scp.Read(ctx, scopeIdRead) + srr, err := scl.Read(ctx, scopes[0].Id) if err != nil { if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { d.SetId("") @@ -95,21 +82,21 @@ func dataSourceScopeRead(ctx context.Context, d *schema.ResourceData, meta inter return diag.Errorf("scope nil after read") } - if err := setFromScopeReadResponseMap(d, srr.GetResponse().Map); err != nil { + if err := setFromScopeRead(d, *srr.Item); err != nil { return diag.FromErr(err) } return nil } -func setFromScopeReadResponseMap(d *schema.ResourceData, raw map[string]interface{}) error { - if err := d.Set(NameKey, raw["name"]); err != nil { +func setFromScopeRead(d *schema.ResourceData, scope scopes.Scope) error { + if err := d.Set(NameKey, scope.Name); err != nil { return err } - if err := d.Set(DescriptionKey, raw["description"]); err != nil { + if err := d.Set(DescriptionKey, scope.Description); err != nil { return err } - d.SetId(raw["id"].(string)) + d.SetId(scope.Id) return nil } diff --git a/internal/provider/data_source_user.go b/internal/provider/data_source_user.go index 0a6c49cc..ea2e8efb 100644 --- a/internal/provider/data_source_user.go +++ b/internal/provider/data_source_user.go @@ -5,7 +5,9 @@ package provider import ( "context" + "net/http" + "github.com/hashicorp/boundary/api" "github.com/hashicorp/boundary/api/users" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -18,22 +20,12 @@ func dataSourceUser() *schema.Resource { ReadContext: dataSourceUserRead, Schema: map[string]*schema.Schema{ - IDKey: { - Description: "The ID of the user.", - Type: schema.TypeString, - Computed: true, - }, NameKey: { Description: "The username to search for.", Type: schema.TypeString, Required: true, ValidateFunc: validation.StringIsNotEmpty, }, - DescriptionKey: { - Description: "The user description.", - Type: schema.TypeString, - Computed: true, - }, ScopeIdKey: { Description: "The scope ID in which the resource is created. Defaults `global` if unset.", Type: schema.TypeString, @@ -41,7 +33,17 @@ func dataSourceUser() *schema.Resource { Default: "global", ValidateFunc: validation.StringIsNotEmpty, }, - userAccountIDsKey: { + IDKey: { + Description: "The ID of the user.", + Type: schema.TypeString, + Computed: true, + }, + DescriptionKey: { + Description: "The user description.", + Type: schema.TypeString, + Computed: true, + }, + UserAccountIdsKey: { Description: "Account ID's to associate with this user resource.", Type: schema.TypeSet, Computed: true, @@ -99,39 +101,48 @@ func dataSourceUser() *schema.Resource { 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(NameKey).(string) scopeID := d.Get(ScopeIdKey).(string) - opts = append(opts, users.WithFilter(FilterWithItemNameMatches(name))) - - usersList, err := usrs.List(ctx, scopeID, opts...) + ucl := users.NewClient(md.client) + usersList, err := ucl.List(ctx, scopeID, + users.WithFilter(FilterWithItemNameMatches(name)), + ) 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 users == nil { + return diag.Errorf("no users found") + } if len(users) == 0 { - return diag.Errorf("no matching user found: %v", err) + return diag.Errorf("no matching user found") } - if len(users) > 1 { - return diag.Errorf("error found more than 1 user: %v", err) + return diag.Errorf("error found more than 1 user") + } + + urr, err := ucl.Read(ctx, users[0].Id) + if err != nil { + if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { + d.SetId("") + return nil + } + return diag.Errorf("error calling read scope: %v", err) + } + if urr == nil { + return diag.Errorf("scope nil after read") } - if err := setFromUserItem(d, *users[0]); err != nil { + if err := setFromUserRead(d, *urr.Item); err != nil { return diag.FromErr(err) } return nil } -func setFromUserItem(d *schema.ResourceData, user users.User) error { +func setFromUserRead(d *schema.ResourceData, user users.User) error { if err := d.Set(NameKey, user.Name); err != nil { return err } @@ -141,7 +152,7 @@ func setFromUserItem(d *schema.ResourceData, user users.User) error { if err := d.Set(ScopeIdKey, user.ScopeId); err != nil { return err } - if err := d.Set(userAccountIDsKey, user.AccountIds); err != nil { + if err := d.Set(UserAccountIdsKey, user.AccountIds); err != nil { return err } if err := d.Set(authorizedActions, user.AuthorizedActions); err != nil { diff --git a/internal/provider/resource_user.go b/internal/provider/resource_user.go index 2caf8349..99be84cd 100644 --- a/internal/provider/resource_user.go +++ b/internal/provider/resource_user.go @@ -13,8 +13,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -const userAccountIDsKey = "account_ids" - func resourceUser() *schema.Resource { return &schema.Resource{ Description: "The user resource allows you to configure a Boundary user.", @@ -49,7 +47,7 @@ func resourceUser() *schema.Resource { Required: true, ForceNew: true, }, - userAccountIDsKey: { + UserAccountIdsKey: { Description: "Account ID's to associate with this user resource.", Type: schema.TypeSet, Optional: true, @@ -69,7 +67,7 @@ func setFromUserResponseMap(d *schema.ResourceData, raw map[string]interface{}) if err := d.Set(ScopeIdKey, raw["scope_id"]); err != nil { return err } - if err := d.Set(userAccountIDsKey, raw["account_ids"]); err != nil { + if err := d.Set(UserAccountIdsKey, raw["account_ids"]); err != nil { return err } d.SetId(raw["id"].(string)) @@ -116,7 +114,7 @@ func resourceUserCreate(ctx context.Context, d *schema.ResourceData, meta interf } }() - if val, ok := d.GetOk(userAccountIDsKey); ok { + if val, ok := d.GetOk(UserAccountIdsKey); ok { list := val.(*schema.Set).List() acctIds := make([]string, 0, len(list)) for _, i := range list { @@ -205,9 +203,9 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf } } - if d.HasChange(userAccountIDsKey) { + if d.HasChange(UserAccountIdsKey) { var accountIds []string - if accountsVal, ok := d.GetOk(userAccountIDsKey); ok { + if accountsVal, ok := d.GetOk(UserAccountIdsKey); ok { accounts := accountsVal.(*schema.Set).List() for _, account := range accounts { accountIds = append(accountIds, account.(string)) @@ -218,7 +216,7 @@ func resourceUserUpdate(ctx context.Context, d *schema.ResourceData, meta interf if err != nil { return diag.Errorf("error updating accounts on user: %v", err) } - if err := d.Set(userAccountIDsKey, accountIds); err != nil { + if err := d.Set(UserAccountIdsKey, accountIds); err != nil { return diag.FromErr(err) } }