fix: include recent api changes Reviewed-on: #65 Co-authored-by: Marcel S. Henselin <marcel.henselin@stackit.cloud> Co-committed-by: Marcel S. Henselin <marcel.henselin@stackit.cloud>
This commit is contained in:
parent
452f73877f
commit
43223f5d1f
13 changed files with 202 additions and 63 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -46,3 +46,5 @@ dist
|
||||||
|
|
||||||
pkg_gen
|
pkg_gen
|
||||||
/release/
|
/release/
|
||||||
|
.env
|
||||||
|
**/.env
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ description: |-
|
||||||
|
|
||||||
- `collation_name` (String) The collation of the database. This database collation should match the *collation_name* of one of the collations given by the **Get database collation list** endpoint.
|
- `collation_name` (String) The collation of the database. This database collation should match the *collation_name* of one of the collations given by the **Get database collation list** endpoint.
|
||||||
- `compatibility_level` (Number) CompatibilityLevel of the Database.
|
- `compatibility_level` (Number) CompatibilityLevel of the Database.
|
||||||
- `id` (String) Terraform's internal resource ID. It is structured as \"`project_id`,`region`,`instance_id`,`database_id`\".",
|
- `id` (String) The terraform internal identifier.
|
||||||
- `name` (String) The name of the database.
|
- `name` (String) The name of the database.
|
||||||
- `owner` (String) The owner of the database.
|
- `owner` (String) The owner of the database.
|
||||||
- `tf_original_api_id` (Number) The id of the database.
|
- `tf_original_api_id` (Number) The id of the database.
|
||||||
|
|
|
||||||
|
|
@ -29,20 +29,20 @@ data "stackitprivatepreview_sqlserverflexalpha_flavor" "flavor" {
|
||||||
### Required
|
### Required
|
||||||
|
|
||||||
- `cpu` (Number) The cpu count of the instance.
|
- `cpu` (Number) The cpu count of the instance.
|
||||||
- `node_type` (String) defines the nodeType it can be either single or replica
|
- `node_type` (String) defines the nodeType it can be either single or HA
|
||||||
- `project_id` (String) The cpu count of the instance.
|
- `project_id` (String) The project ID of the flavor.
|
||||||
- `ram` (Number) The memory of the instance in Gibibyte.
|
- `ram` (Number) The memory of the instance in Gibibyte.
|
||||||
- `region` (String) The flavor description.
|
- `region` (String) The region of the flavor.
|
||||||
- `storage_class` (String) The memory of the instance in Gibibyte.
|
- `storage_class` (String) The memory of the instance in Gibibyte.
|
||||||
|
|
||||||
### Read-Only
|
### Read-Only
|
||||||
|
|
||||||
- `description` (String) The flavor description.
|
- `description` (String) The flavor description.
|
||||||
- `flavor_id` (String) The flavor id of the instance flavor.
|
- `flavor_id` (String) The id of the instance flavor.
|
||||||
- `id` (String) The terraform id of the instance flavor.
|
- `id` (String) The id of the instance flavor.
|
||||||
- `max_gb` (Number) maximum storage which can be ordered for the flavor in Gigabyte.
|
- `max_gb` (Number) maximum storage which can be ordered for the flavor in Gigabyte.
|
||||||
- `min_gb` (Number) minimum storage which is required to order in Gigabyte.
|
- `min_gb` (Number) minimum storage which is required to order in Gigabyte.
|
||||||
- `storage_classes` (Attributes List) (see [below for nested schema](#nestedatt--storage_classes))
|
- `storage_classes` (Attributes List) maximum storage which can be ordered for the flavor in Gigabyte. (see [below for nested schema](#nestedatt--storage_classes))
|
||||||
|
|
||||||
<a id="nestedatt--storage_classes"></a>
|
<a id="nestedatt--storage_classes"></a>
|
||||||
### Nested Schema for `storage_classes`
|
### Nested Schema for `storage_classes`
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ data "stackitprivatepreview_sqlserverflexalpha_instance" "example" {
|
||||||
- `edition` (String) Edition of the MSSQL server instance
|
- `edition` (String) Edition of the MSSQL server instance
|
||||||
- `encryption` (Attributes) this defines which key to use for storage encryption (see [below for nested schema](#nestedatt--encryption))
|
- `encryption` (Attributes) this defines which key to use for storage encryption (see [below for nested schema](#nestedatt--encryption))
|
||||||
- `flavor_id` (String) The id of the instance flavor.
|
- `flavor_id` (String) The id of the instance flavor.
|
||||||
- `id` (String) Terraform's internal resource ID. It is structured as \"`project_id`,`region`,`instance_id`\".
|
|
||||||
- `is_deletable` (Boolean) Whether the instance can be deleted or not.
|
- `is_deletable` (Boolean) Whether the instance can be deleted or not.
|
||||||
- `name` (String) The name of the instance.
|
- `name` (String) The name of the instance.
|
||||||
- `network` (Attributes) The access configuration of the instance (see [below for nested schema](#nestedatt--network))
|
- `network` (Attributes) The access configuration of the instance (see [below for nested schema](#nestedatt--network))
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
page_title: "stackitprivatepreview_sqlserverflexalpha_user Data Source - stackitprivatepreview"
|
page_title: "stackitprivatepreview_sqlserverflexalpha_user Data Source - stackitprivatepreview"
|
||||||
subcategory: ""
|
subcategory: ""
|
||||||
description: |-
|
description: |-
|
||||||
SQLServer Flex user data source schema. Must have a region specified in the provider configuration.
|
|
||||||
---
|
---
|
||||||
|
|
||||||
# stackitprivatepreview_sqlserverflexalpha_user (Data Source)
|
# stackitprivatepreview_sqlserverflexalpha_user (Data Source)
|
||||||
|
|
||||||
SQLServer Flex user data source schema. Must have a `region` specified in the provider configuration.
|
|
||||||
|
|
||||||
## Example Usage
|
## Example Usage
|
||||||
|
|
||||||
|
|
@ -25,20 +25,38 @@ data "stackitprivatepreview_sqlserverflexalpha_user" "example" {
|
||||||
|
|
||||||
### Required
|
### Required
|
||||||
|
|
||||||
- `instance_id` (String) ID of the SQLServer Flex instance.
|
- `instance_id` (String) The ID of the instance.
|
||||||
- `project_id` (String) STACKIT project ID to which the instance is associated.
|
- `project_id` (String) The STACKIT project ID.
|
||||||
- `user_id` (Number) User ID.
|
- `region` (String) The region which should be addressed
|
||||||
|
|
||||||
### Optional
|
### Optional
|
||||||
|
|
||||||
- `region` (String) The resource region. If not defined, the provider region is used.
|
- `page` (Number) Number of the page of items list to be returned.
|
||||||
|
- `size` (Number) Number of items to be returned on each page.
|
||||||
|
- `sort` (String) Sorting of the users to be returned on each page.
|
||||||
|
|
||||||
### Read-Only
|
### Read-Only
|
||||||
|
|
||||||
- `default_database` (String)
|
- `pagination` (Attributes) (see [below for nested schema](#nestedatt--pagination))
|
||||||
- `host` (String)
|
- `users` (Attributes List) List of all users inside an instance (see [below for nested schema](#nestedatt--users))
|
||||||
- `id` (String) Terraform's internal data source. ID. It is structured as "`project_id`,`region`,`instance_id`,`user_id`".
|
|
||||||
- `port` (Number)
|
<a id="nestedatt--pagination"></a>
|
||||||
- `roles` (Set of String) Database access levels for the user.
|
### Nested Schema for `pagination`
|
||||||
- `status` (String)
|
|
||||||
- `username` (String) Username of the SQLServer Flex instance.
|
Read-Only:
|
||||||
|
|
||||||
|
- `page` (Number)
|
||||||
|
- `size` (Number)
|
||||||
|
- `sort` (String)
|
||||||
|
- `total_pages` (Number)
|
||||||
|
- `total_rows` (Number)
|
||||||
|
|
||||||
|
|
||||||
|
<a id="nestedatt--users"></a>
|
||||||
|
### Nested Schema for `users`
|
||||||
|
|
||||||
|
Read-Only:
|
||||||
|
|
||||||
|
- `status` (String) The current status of the user.
|
||||||
|
- `tf_original_api_id` (Number) The ID of the user.
|
||||||
|
- `username` (String) The name of the user.
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ import {
|
||||||
|
|
||||||
### Read-Only
|
### Read-Only
|
||||||
|
|
||||||
- `connection_string` (String) The connection string for the user to the instance.
|
|
||||||
- `id` (Number) The ID of the user.
|
- `id` (Number) The ID of the user.
|
||||||
- `password` (String) The password for the user.
|
- `password` (String) The password for the user.
|
||||||
- `status` (String) The current status of the user.
|
- `status` (String) The current status of the user.
|
||||||
|
|
|
||||||
|
|
@ -65,15 +65,15 @@ resource "stackitprivatepreview_postgresflexalpha_instance" "msh-sna-pe-example2
|
||||||
resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbadminuser" {
|
resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbadminuser" {
|
||||||
project_id = var.project_id
|
project_id = var.project_id
|
||||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example.instance_id
|
instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example.instance_id
|
||||||
username = var.db_admin_username
|
name = var.db_admin_username
|
||||||
roles = ["createdb", "login"]
|
roles = ["createdb", "login", "login"]
|
||||||
# roles = ["createdb", "login", "createrole"]
|
# roles = ["createdb", "login", "createrole"]
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbadminuser2" {
|
resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbadminuser2" {
|
||||||
project_id = var.project_id
|
project_id = var.project_id
|
||||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example2.instance_id
|
instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example2.instance_id
|
||||||
username = var.db_admin_username
|
name = var.db_admin_username
|
||||||
roles = ["createdb", "login"]
|
roles = ["createdb", "login"]
|
||||||
# roles = ["createdb", "login", "createrole"]
|
# roles = ["createdb", "login", "createrole"]
|
||||||
}
|
}
|
||||||
|
|
@ -81,7 +81,7 @@ resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbadminuser2" {
|
||||||
resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbuser" {
|
resource "stackitprivatepreview_postgresflexalpha_user" "ptlsdbuser" {
|
||||||
project_id = var.project_id
|
project_id = var.project_id
|
||||||
instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example.instance_id
|
instance_id = stackitprivatepreview_postgresflexalpha_instance.msh-sna-pe-example.instance_id
|
||||||
username = var.db_username
|
name = var.db_name
|
||||||
roles = ["login"]
|
roles = ["login"]
|
||||||
# roles = ["createdb", "login", "createrole"]
|
# roles = ["createdb", "login", "createrole"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -29,11 +30,12 @@ import (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Ensure the implementation satisfies the expected interfaces.
|
// Ensure the implementation satisfies the expected interfaces.
|
||||||
_ resource.Resource = &userResource{}
|
_ resource.Resource = &userResource{}
|
||||||
_ resource.ResourceWithConfigure = &userResource{}
|
_ resource.ResourceWithConfigure = &userResource{}
|
||||||
_ resource.ResourceWithImportState = &userResource{}
|
_ resource.ResourceWithImportState = &userResource{}
|
||||||
_ resource.ResourceWithModifyPlan = &userResource{}
|
_ resource.ResourceWithModifyPlan = &userResource{}
|
||||||
_ resource.ResourceWithIdentity = &userResource{}
|
_ resource.ResourceWithIdentity = &userResource{}
|
||||||
|
_ resource.ResourceWithValidateConfig = &userResource{}
|
||||||
|
|
||||||
// Error message constants
|
// Error message constants
|
||||||
extractErrorSummary = "extracting failed"
|
extractErrorSummary = "extracting failed"
|
||||||
|
|
@ -138,6 +140,39 @@ func (r *userResource) Schema(ctx context.Context, _ resource.SchemaRequest, res
|
||||||
resp.Schema = s
|
resp.Schema = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *userResource) ValidateConfig(
|
||||||
|
ctx context.Context,
|
||||||
|
req resource.ValidateConfigRequest,
|
||||||
|
resp *resource.ValidateConfigResponse,
|
||||||
|
) {
|
||||||
|
var data resourceModel
|
||||||
|
|
||||||
|
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var roles []string
|
||||||
|
diags := data.Roles.ElementsAs(ctx, &roles, false)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if diags.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var resRoles []string
|
||||||
|
for _, role := range roles {
|
||||||
|
if slices.Contains(resRoles, role) {
|
||||||
|
resp.Diagnostics.AddAttributeError(
|
||||||
|
path.Root("roles"),
|
||||||
|
"Attribute Configuration Error",
|
||||||
|
"defined roles MUST NOT contain duplicates",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resRoles = append(resRoles, role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create creates the resource and sets the initial Terraform state.
|
// Create creates the resource and sets the initial Terraform state.
|
||||||
func (r *userResource) Create(
|
func (r *userResource) Create(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
|
@ -217,7 +252,7 @@ func (r *userResource) Create(
|
||||||
model.UserId = types.Int64Value(id)
|
model.UserId = types.Int64Value(id)
|
||||||
model.Password = types.StringValue(userResp.GetPassword())
|
model.Password = types.StringValue(userResp.GetPassword())
|
||||||
model.Status = types.StringValue(userResp.GetStatus())
|
model.Status = types.StringValue(userResp.GetStatus())
|
||||||
model.ConnectionString = types.StringValue(userResp.GetConnectionString())
|
//model.ConnectionString = types.StringValue(userResp.GetConnectionString())
|
||||||
|
|
||||||
waitResp, err := postgresflexalphaWait.GetUserByIdWaitHandler(
|
waitResp, err := postgresflexalphaWait.GetUserByIdWaitHandler(
|
||||||
ctx,
|
ctx,
|
||||||
|
|
@ -712,5 +747,6 @@ func (r *userResource) expandRoles(ctx context.Context, rolesSet types.List, dia
|
||||||
}
|
}
|
||||||
var roles []string
|
var roles []string
|
||||||
diags.Append(rolesSet.ElementsAs(ctx, &roles, false)...)
|
diags.Append(rolesSet.ElementsAs(ctx, &roles, false)...)
|
||||||
|
slices.Sort(roles)
|
||||||
return roles
|
return roles
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,6 @@ import (
|
||||||
func UserResourceSchema(ctx context.Context) schema.Schema {
|
func UserResourceSchema(ctx context.Context) schema.Schema {
|
||||||
return schema.Schema{
|
return schema.Schema{
|
||||||
Attributes: map[string]schema.Attribute{
|
Attributes: map[string]schema.Attribute{
|
||||||
"connection_string": schema.StringAttribute{
|
|
||||||
Computed: true,
|
|
||||||
Description: "The connection string for the user to the instance.",
|
|
||||||
MarkdownDescription: "The connection string for the user to the instance.",
|
|
||||||
},
|
|
||||||
"id": schema.Int64Attribute{
|
"id": schema.Int64Attribute{
|
||||||
Computed: true,
|
Computed: true,
|
||||||
Description: "The ID of the user.",
|
Description: "The ID of the user.",
|
||||||
|
|
@ -80,14 +75,13 @@ func UserResourceSchema(ctx context.Context) schema.Schema {
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserModel struct {
|
type UserModel struct {
|
||||||
ConnectionString types.String `tfsdk:"connection_string"`
|
Id types.Int64 `tfsdk:"id"`
|
||||||
Id types.Int64 `tfsdk:"id"`
|
InstanceId types.String `tfsdk:"instance_id"`
|
||||||
InstanceId types.String `tfsdk:"instance_id"`
|
Name types.String `tfsdk:"name"`
|
||||||
Name types.String `tfsdk:"name"`
|
Password types.String `tfsdk:"password"`
|
||||||
Password types.String `tfsdk:"password"`
|
ProjectId types.String `tfsdk:"project_id"`
|
||||||
ProjectId types.String `tfsdk:"project_id"`
|
Region types.String `tfsdk:"region"`
|
||||||
Region types.String `tfsdk:"region"`
|
Roles types.List `tfsdk:"roles"`
|
||||||
Roles types.List `tfsdk:"roles"`
|
Status types.String `tfsdk:"status"`
|
||||||
Status types.String `tfsdk:"status"`
|
UserId types.Int64 `tfsdk:"user_id"`
|
||||||
UserId types.Int64 `tfsdk:"user_id"`
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package sqlserverflexalpha
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||||
|
|
@ -44,8 +45,11 @@ func mapDataSourceFields(userResp *sqlserverflexalpha.GetUserResponse, model *da
|
||||||
if user.Roles == nil {
|
if user.Roles == nil {
|
||||||
model.Roles = types.List(types.SetNull(types.StringType))
|
model.Roles = types.List(types.SetNull(types.StringType))
|
||||||
} else {
|
} else {
|
||||||
|
resRoles := *user.Roles
|
||||||
|
slices.Sort(resRoles)
|
||||||
|
|
||||||
var roles []attr.Value
|
var roles []attr.Value
|
||||||
for _, role := range *user.Roles {
|
for _, role := range resRoles {
|
||||||
roles = append(roles, types.StringValue(string(role)))
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
}
|
}
|
||||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
|
@ -92,8 +96,11 @@ func mapFields(userResp *sqlserverflexalpha.GetUserResponse, model *resourceMode
|
||||||
|
|
||||||
// Map roles
|
// Map roles
|
||||||
if user.Roles != nil {
|
if user.Roles != nil {
|
||||||
|
resRoles := *user.Roles
|
||||||
|
slices.Sort(resRoles)
|
||||||
|
|
||||||
var roles []attr.Value
|
var roles []attr.Value
|
||||||
for _, role := range *user.Roles {
|
for _, role := range resRoles {
|
||||||
roles = append(roles, types.StringValue(string(role)))
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
}
|
}
|
||||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
|
@ -139,8 +146,11 @@ func mapFieldsCreate(userResp *sqlserverflexalpha.CreateUserResponse, model *res
|
||||||
model.Password = types.StringValue(*user.Password)
|
model.Password = types.StringValue(*user.Password)
|
||||||
|
|
||||||
if user.Roles != nil {
|
if user.Roles != nil {
|
||||||
|
resRoles := *user.Roles
|
||||||
|
slices.Sort(resRoles)
|
||||||
|
|
||||||
var roles []attr.Value
|
var roles []attr.Value
|
||||||
for _, role := range *user.Roles {
|
for _, role := range resRoles {
|
||||||
roles = append(roles, types.StringValue(string(role)))
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
}
|
}
|
||||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -30,11 +31,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ resource.Resource = &userResource{}
|
_ resource.Resource = &userResource{}
|
||||||
_ resource.ResourceWithConfigure = &userResource{}
|
_ resource.ResourceWithConfigure = &userResource{}
|
||||||
_ resource.ResourceWithImportState = &userResource{}
|
_ resource.ResourceWithImportState = &userResource{}
|
||||||
_ resource.ResourceWithModifyPlan = &userResource{}
|
_ resource.ResourceWithModifyPlan = &userResource{}
|
||||||
_ resource.ResourceWithIdentity = &userResource{}
|
_ resource.ResourceWithIdentity = &userResource{}
|
||||||
|
_ resource.ResourceWithValidateConfig = &userResource{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewUserResource() resource.Resource {
|
func NewUserResource() resource.Resource {
|
||||||
|
|
@ -156,6 +158,39 @@ func (r *userResource) IdentitySchema(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *userResource) ValidateConfig(
|
||||||
|
ctx context.Context,
|
||||||
|
req resource.ValidateConfigRequest,
|
||||||
|
resp *resource.ValidateConfigResponse,
|
||||||
|
) {
|
||||||
|
var data resourceModel
|
||||||
|
|
||||||
|
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var roles []string
|
||||||
|
diags := data.Roles.ElementsAs(ctx, &roles, false)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if diags.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var resRoles []string
|
||||||
|
for _, role := range roles {
|
||||||
|
if slices.Contains(resRoles, role) {
|
||||||
|
resp.Diagnostics.AddAttributeError(
|
||||||
|
path.Root("roles"),
|
||||||
|
"Attribute Configuration Error",
|
||||||
|
"defined roles MUST NOT contain duplicates",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resRoles = append(resRoles, role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create creates the resource and sets the initial Terraform state.
|
// Create creates the resource and sets the initial Terraform state.
|
||||||
func (r *userResource) Create(
|
func (r *userResource) Create(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
|
@ -186,6 +221,8 @@ func (r *userResource) Create(
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slices.Sort(roles)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate API request body from model
|
// Generate API request body from model
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package sqlserverflexbeta
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform-plugin-framework/attr"
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
||||||
|
|
@ -92,10 +93,14 @@ func mapFields(userResp *sqlserverflexbeta.GetUserResponse, model *resourceModel
|
||||||
|
|
||||||
// Map roles
|
// Map roles
|
||||||
if user.Roles != nil {
|
if user.Roles != nil {
|
||||||
|
resRoles := *user.Roles
|
||||||
|
slices.Sort(resRoles)
|
||||||
|
|
||||||
var roles []attr.Value
|
var roles []attr.Value
|
||||||
for _, role := range *user.Roles {
|
for _, role := range resRoles {
|
||||||
roles = append(roles, types.StringValue(string(role)))
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
}
|
}
|
||||||
|
|
||||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
if diags.HasError() {
|
if diags.HasError() {
|
||||||
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
return fmt.Errorf("failed to map roles: %w", core.DiagsToError(diags))
|
||||||
|
|
@ -139,8 +144,11 @@ func mapFieldsCreate(userResp *sqlserverflexbeta.CreateUserResponse, model *reso
|
||||||
model.Password = types.StringValue(*user.Password)
|
model.Password = types.StringValue(*user.Password)
|
||||||
|
|
||||||
if user.Roles != nil {
|
if user.Roles != nil {
|
||||||
|
resRoles := *user.Roles
|
||||||
|
slices.Sort(resRoles)
|
||||||
|
|
||||||
var roles []attr.Value
|
var roles []attr.Value
|
||||||
for _, role := range *user.Roles {
|
for _, role := range resRoles {
|
||||||
roles = append(roles, types.StringValue(string(role)))
|
roles = append(roles, types.StringValue(string(role)))
|
||||||
}
|
}
|
||||||
rolesSet, diags := types.SetValue(types.StringType, roles)
|
rolesSet, diags := types.SetValue(types.StringType, roles)
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -30,11 +31,12 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
_ resource.Resource = &userResource{}
|
_ resource.Resource = &userResource{}
|
||||||
_ resource.ResourceWithConfigure = &userResource{}
|
_ resource.ResourceWithConfigure = &userResource{}
|
||||||
_ resource.ResourceWithImportState = &userResource{}
|
_ resource.ResourceWithImportState = &userResource{}
|
||||||
_ resource.ResourceWithModifyPlan = &userResource{}
|
_ resource.ResourceWithModifyPlan = &userResource{}
|
||||||
_ resource.ResourceWithIdentity = &userResource{}
|
_ resource.ResourceWithIdentity = &userResource{}
|
||||||
|
_ resource.ResourceWithValidateConfig = &userResource{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewUserResource() resource.Resource {
|
func NewUserResource() resource.Resource {
|
||||||
|
|
@ -156,6 +158,39 @@ func (r *userResource) IdentitySchema(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *userResource) ValidateConfig(
|
||||||
|
ctx context.Context,
|
||||||
|
req resource.ValidateConfigRequest,
|
||||||
|
resp *resource.ValidateConfigResponse,
|
||||||
|
) {
|
||||||
|
var data resourceModel
|
||||||
|
|
||||||
|
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
|
||||||
|
if resp.Diagnostics.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var roles []string
|
||||||
|
diags := data.Roles.ElementsAs(ctx, &roles, false)
|
||||||
|
resp.Diagnostics.Append(diags...)
|
||||||
|
if diags.HasError() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var resRoles []string
|
||||||
|
for _, role := range roles {
|
||||||
|
if slices.Contains(resRoles, role) {
|
||||||
|
resp.Diagnostics.AddAttributeError(
|
||||||
|
path.Root("roles"),
|
||||||
|
"Attribute Configuration Error",
|
||||||
|
"defined roles MUST NOT contain duplicates",
|
||||||
|
)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resRoles = append(resRoles, role)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create creates the resource and sets the initial Terraform state.
|
// Create creates the resource and sets the initial Terraform state.
|
||||||
func (r *userResource) Create(
|
func (r *userResource) Create(
|
||||||
ctx context.Context,
|
ctx context.Context,
|
||||||
|
|
@ -186,6 +221,7 @@ func (r *userResource) Create(
|
||||||
if resp.Diagnostics.HasError() {
|
if resp.Diagnostics.HasError() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
slices.Sort(roles)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate API request body from model
|
// Generate API request body from model
|
||||||
|
|
@ -379,7 +415,7 @@ func (r *userResource) Update(
|
||||||
resp *resource.UpdateResponse,
|
resp *resource.UpdateResponse,
|
||||||
) { // nolint:gocritic // function signature required by Terraform
|
) { // nolint:gocritic // function signature required by Terraform
|
||||||
// Update shouldn't be called
|
// Update shouldn't be called
|
||||||
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating user", "User can't be updated")
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating user", "an SQL server user can not be updated, only created")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete deletes the resource and removes the Terraform state on success.
|
// Delete deletes the resource and removes the Terraform state on success.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue