## Description
<!-- **Please link some issue here describing what you are trying to achieve.**
In case there is no issue present for your PR, please consider creating one.
At least please give us some description what you are trying to achieve and why your change is needed. -->
relates to #1234
## Checklist
- [ ] Issue was linked above
- [ ] Code format was applied: `make fmt`
- [ ] Examples were added / adjusted (see `examples/` directory)
- [x] Docs are up-to-date: `make generate-docs` (will be checked by CI)
- [ ] Unit tests got implemented or updated
- [ ] Acceptance tests got implemented or updated (see e.g. [here](f5f99d1709/stackit/internal/services/dns/dns_acc_test.go))
- [x] Unit tests are passing: `make test` (will be checked by CI)
- [x] No linter issues: `make lint` (will be checked by CI)
Reviewed-on: #58
Co-authored-by: Marcel S. Henselin <marcel.henselin@stackit.cloud>
Co-committed-by: Marcel S. Henselin <marcel.henselin@stackit.cloud>
355 lines
13 KiB
Go
355 lines
13 KiB
Go
package sqlserverFlexBetaFlavor
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform-plugin-framework/attr"
|
|
"github.com/hashicorp/terraform-plugin-framework/datasource"
|
|
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
|
|
"github.com/hashicorp/terraform-plugin-framework/types"
|
|
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
|
|
"github.com/hashicorp/terraform-plugin-log/tflog"
|
|
"github.com/stackitcloud/stackit-sdk-go/core/config"
|
|
|
|
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/conversion"
|
|
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/core"
|
|
"tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/utils"
|
|
|
|
sqlserverflexbetaPkg "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/pkg_gen/sqlserverflexbeta"
|
|
sqlserverflexbetaGen "tf-provider.git.onstackit.cloud/stackit-dev-tools/terraform-provider-stackitprivatepreview/stackit/internal/services/sqlserverflexbeta/flavor/datasources_gen"
|
|
)
|
|
|
|
// Ensure the implementation satisfies the expected interfaces.
|
|
var (
|
|
_ datasource.DataSource = &flavorDataSource{}
|
|
_ datasource.DataSourceWithConfigure = &flavorDataSource{}
|
|
)
|
|
|
|
type FlavorModel struct {
|
|
ProjectId types.String `tfsdk:"project_id"`
|
|
Region types.String `tfsdk:"region"`
|
|
StorageClass types.String `tfsdk:"storage_class"`
|
|
Cpu types.Int64 `tfsdk:"cpu"`
|
|
Description types.String `tfsdk:"description"`
|
|
Id types.String `tfsdk:"id"`
|
|
FlavorId types.String `tfsdk:"flavor_id"`
|
|
MaxGb types.Int64 `tfsdk:"max_gb"`
|
|
Memory types.Int64 `tfsdk:"ram"`
|
|
MinGb types.Int64 `tfsdk:"min_gb"`
|
|
NodeType types.String `tfsdk:"node_type"`
|
|
StorageClasses types.List `tfsdk:"storage_classes"`
|
|
}
|
|
|
|
// NewFlavorDataSource is a helper function to simplify the provider implementation.
|
|
func NewFlavorDataSource() datasource.DataSource {
|
|
return &flavorDataSource{}
|
|
}
|
|
|
|
// flavorDataSource is the data source implementation.
|
|
type flavorDataSource struct {
|
|
client *sqlserverflexbetaPkg.APIClient
|
|
providerData core.ProviderData
|
|
}
|
|
|
|
// Metadata returns the data source type name.
|
|
func (r *flavorDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
|
|
resp.TypeName = req.ProviderTypeName + "_sqlserverflexbeta_flavor"
|
|
}
|
|
|
|
// Configure adds the provider configured client to the data source.
|
|
func (r *flavorDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
|
|
var ok bool
|
|
r.providerData, ok = conversion.ParseProviderData(ctx, req.ProviderData, &resp.Diagnostics)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
apiClientConfigOptions := []config.ConfigurationOption{
|
|
config.WithCustomAuth(r.providerData.RoundTripper),
|
|
utils.UserAgentConfigOption(r.providerData.Version),
|
|
}
|
|
if r.providerData.SQLServerFlexCustomEndpoint != "" {
|
|
apiClientConfigOptions = append(
|
|
apiClientConfigOptions,
|
|
config.WithEndpoint(r.providerData.SQLServerFlexCustomEndpoint),
|
|
)
|
|
} else {
|
|
apiClientConfigOptions = append(
|
|
apiClientConfigOptions,
|
|
config.WithRegion(r.providerData.GetRegion()),
|
|
)
|
|
}
|
|
apiClient, err := sqlserverflexbetaPkg.NewAPIClient(apiClientConfigOptions...)
|
|
if err != nil {
|
|
resp.Diagnostics.AddError(
|
|
"Error configuring API client",
|
|
fmt.Sprintf(
|
|
"Configuring client: %v. This is an error related to the provider configuration, not to the resource configuration",
|
|
err,
|
|
),
|
|
)
|
|
return
|
|
}
|
|
r.client = apiClient
|
|
tflog.Info(ctx, "SQL Server Flex instance client configured")
|
|
}
|
|
|
|
func (r *flavorDataSource) Schema(ctx context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
|
|
resp.Schema = schema.Schema{
|
|
Attributes: map[string]schema.Attribute{
|
|
"project_id": schema.StringAttribute{
|
|
Required: true,
|
|
Description: "The project ID of the flavor.",
|
|
MarkdownDescription: "The project ID of the flavor.",
|
|
},
|
|
"region": schema.StringAttribute{
|
|
Required: true,
|
|
Description: "The region of the flavor.",
|
|
MarkdownDescription: "The region of the flavor.",
|
|
},
|
|
"cpu": schema.Int64Attribute{
|
|
Required: true,
|
|
Description: "The cpu count of the instance.",
|
|
MarkdownDescription: "The cpu count of the instance.",
|
|
},
|
|
"ram": schema.Int64Attribute{
|
|
Required: true,
|
|
Description: "The memory of the instance in Gibibyte.",
|
|
MarkdownDescription: "The memory of the instance in Gibibyte.",
|
|
},
|
|
"storage_class": schema.StringAttribute{
|
|
Required: true,
|
|
Description: "The memory of the instance in Gibibyte.",
|
|
MarkdownDescription: "The memory of the instance in Gibibyte.",
|
|
},
|
|
"node_type": schema.StringAttribute{
|
|
Required: true,
|
|
Description: "defines the nodeType it can be either single or HA",
|
|
MarkdownDescription: "defines the nodeType it can be either single or HA",
|
|
},
|
|
"flavor_id": schema.StringAttribute{
|
|
Computed: true,
|
|
Description: "The id of the instance flavor.",
|
|
MarkdownDescription: "The id of the instance flavor.",
|
|
},
|
|
"description": schema.StringAttribute{
|
|
Computed: true,
|
|
Description: "The flavor description.",
|
|
MarkdownDescription: "The flavor description.",
|
|
},
|
|
"id": schema.StringAttribute{
|
|
Computed: true,
|
|
Description: "The id of the instance flavor.",
|
|
MarkdownDescription: "The id of the instance flavor.",
|
|
},
|
|
"max_gb": schema.Int64Attribute{
|
|
Computed: true,
|
|
Description: "maximum storage which can be ordered for the flavor in Gigabyte.",
|
|
MarkdownDescription: "maximum storage which can be ordered for the flavor in Gigabyte.",
|
|
},
|
|
"min_gb": schema.Int64Attribute{
|
|
Computed: true,
|
|
Description: "minimum storage which is required to order in Gigabyte.",
|
|
MarkdownDescription: "minimum storage which is required to order in Gigabyte.",
|
|
},
|
|
"storage_classes": schema.ListNestedAttribute{
|
|
NestedObject: schema.NestedAttributeObject{
|
|
Attributes: map[string]schema.Attribute{
|
|
"class": schema.StringAttribute{
|
|
Computed: true,
|
|
},
|
|
"max_io_per_sec": schema.Int64Attribute{
|
|
Computed: true,
|
|
},
|
|
"max_through_in_mb": schema.Int64Attribute{
|
|
Computed: true,
|
|
},
|
|
},
|
|
CustomType: sqlserverflexbetaGen.StorageClassesType{
|
|
ObjectType: types.ObjectType{
|
|
AttrTypes: sqlserverflexbetaGen.StorageClassesValue{}.AttributeTypes(ctx),
|
|
},
|
|
},
|
|
},
|
|
Computed: true,
|
|
Description: "maximum storage which can be ordered for the flavor in Gigabyte.",
|
|
MarkdownDescription: "maximum storage which can be ordered for the flavor in Gigabyte.",
|
|
},
|
|
},
|
|
//Attributes: map[string]schema.Attribute{
|
|
// "project_id": schema.StringAttribute{
|
|
// Required: true,
|
|
// Description: "The cpu count of the instance.",
|
|
// MarkdownDescription: "The cpu count of the instance.",
|
|
// },
|
|
// "region": schema.StringAttribute{
|
|
// Required: true,
|
|
// Description: "The flavor description.",
|
|
// MarkdownDescription: "The flavor description.",
|
|
// },
|
|
// "cpu": schema.Int64Attribute{
|
|
// Required: true,
|
|
// Description: "The cpu count of the instance.",
|
|
// MarkdownDescription: "The cpu count of the instance.",
|
|
// },
|
|
// "ram": schema.Int64Attribute{
|
|
// Required: true,
|
|
// Description: "The memory of the instance in Gibibyte.",
|
|
// MarkdownDescription: "The memory of the instance in Gibibyte.",
|
|
// },
|
|
// "storage_class": schema.StringAttribute{
|
|
// Required: true,
|
|
// Description: "The memory of the instance in Gibibyte.",
|
|
// MarkdownDescription: "The memory of the instance in Gibibyte.",
|
|
// },
|
|
// "description": schema.StringAttribute{
|
|
// Computed: true,
|
|
// Description: "The flavor description.",
|
|
// MarkdownDescription: "The flavor description.",
|
|
// },
|
|
// "id": schema.StringAttribute{
|
|
// Computed: true,
|
|
// Description: "The terraform id of the instance flavor.",
|
|
// MarkdownDescription: "The terraform id of the instance flavor.",
|
|
// },
|
|
// "flavor_id": schema.StringAttribute{
|
|
// Computed: true,
|
|
// Description: "The flavor id of the instance flavor.",
|
|
// MarkdownDescription: "The flavor id of the instance flavor.",
|
|
// },
|
|
// "max_gb": schema.Int64Attribute{
|
|
// Computed: true,
|
|
// Description: "maximum storage which can be ordered for the flavor in Gigabyte.",
|
|
// MarkdownDescription: "maximum storage which can be ordered for the flavor in Gigabyte.",
|
|
// },
|
|
// "min_gb": schema.Int64Attribute{
|
|
// Computed: true,
|
|
// Description: "minimum storage which is required to order in Gigabyte.",
|
|
// MarkdownDescription: "minimum storage which is required to order in Gigabyte.",
|
|
// },
|
|
// "node_type": schema.StringAttribute{
|
|
// Required: true,
|
|
// Description: "defines the nodeType it can be either single or replica",
|
|
// MarkdownDescription: "defines the nodeType it can be either single or replica",
|
|
// },
|
|
// "storage_classes": schema.ListNestedAttribute{
|
|
// Computed: true,
|
|
// NestedObject: schema.NestedAttributeObject{
|
|
// Attributes: map[string]schema.Attribute{
|
|
// "class": schema.StringAttribute{
|
|
// Computed: true,
|
|
// },
|
|
// "max_io_per_sec": schema.Int64Attribute{
|
|
// Computed: true,
|
|
// },
|
|
// "max_through_in_mb": schema.Int64Attribute{
|
|
// Computed: true,
|
|
// },
|
|
// },
|
|
// CustomType: sqlserverflexalphaGen.StorageClassesType{
|
|
// ObjectType: types.ObjectType{
|
|
// AttrTypes: sqlserverflexalphaGen.StorageClassesValue{}.AttributeTypes(ctx),
|
|
// },
|
|
// },
|
|
// },
|
|
// },
|
|
// },
|
|
}
|
|
}
|
|
|
|
func (r *flavorDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
|
|
var model FlavorModel
|
|
diags := req.Config.Get(ctx, &model)
|
|
resp.Diagnostics.Append(diags...)
|
|
if resp.Diagnostics.HasError() {
|
|
return
|
|
}
|
|
|
|
ctx = core.InitProviderContext(ctx)
|
|
|
|
projectId := model.ProjectId.ValueString()
|
|
region := r.providerData.GetRegionWithOverride(model.Region)
|
|
ctx = tflog.SetField(ctx, "project_id", projectId)
|
|
ctx = tflog.SetField(ctx, "region", region)
|
|
|
|
flavors, err := getAllFlavors(ctx, r.client, projectId, region)
|
|
if err != nil {
|
|
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading flavors", fmt.Sprintf("getAllFlavors: %v", err))
|
|
return
|
|
}
|
|
|
|
var foundFlavors []sqlserverflexbetaPkg.ListFlavors
|
|
for _, flavor := range flavors {
|
|
if model.Cpu.ValueInt64() != *flavor.Cpu {
|
|
continue
|
|
}
|
|
if model.Memory.ValueInt64() != *flavor.Memory {
|
|
continue
|
|
}
|
|
if model.NodeType.ValueString() != *flavor.NodeType {
|
|
continue
|
|
}
|
|
for _, sc := range *flavor.StorageClasses {
|
|
if model.StorageClass.ValueString() != *sc.Class {
|
|
continue
|
|
}
|
|
foundFlavors = append(foundFlavors, flavor)
|
|
}
|
|
}
|
|
if len(foundFlavors) == 0 {
|
|
resp.Diagnostics.AddError("get flavor", "could not find requested flavor")
|
|
return
|
|
}
|
|
if len(foundFlavors) > 1 {
|
|
resp.Diagnostics.AddError("get flavor", "found too many matching flavors")
|
|
return
|
|
}
|
|
|
|
f := foundFlavors[0]
|
|
model.Description = types.StringValue(*f.Description)
|
|
model.Id = utils.BuildInternalTerraformId(model.ProjectId.ValueString(), region, *f.Id)
|
|
model.FlavorId = types.StringValue(*f.Id)
|
|
model.MaxGb = types.Int64Value(*f.MaxGB)
|
|
model.MinGb = types.Int64Value(*f.MinGB)
|
|
|
|
if f.StorageClasses == nil {
|
|
model.StorageClasses = types.ListNull(sqlserverflexbetaGen.StorageClassesType{
|
|
ObjectType: basetypes.ObjectType{
|
|
AttrTypes: sqlserverflexbetaGen.StorageClassesValue{}.AttributeTypes(ctx),
|
|
},
|
|
})
|
|
} else {
|
|
var scList []attr.Value
|
|
for _, sc := range *f.StorageClasses {
|
|
scList = append(
|
|
scList,
|
|
sqlserverflexbetaGen.NewStorageClassesValueMust(
|
|
sqlserverflexbetaGen.StorageClassesValue{}.AttributeTypes(ctx),
|
|
map[string]attr.Value{
|
|
"class": types.StringValue(*sc.Class),
|
|
"max_io_per_sec": types.Int64Value(*sc.MaxIoPerSec),
|
|
"max_through_in_mb": types.Int64Value(*sc.MaxThroughInMb),
|
|
},
|
|
),
|
|
)
|
|
}
|
|
storageClassesList := types.ListValueMust(
|
|
sqlserverflexbetaGen.StorageClassesType{
|
|
ObjectType: basetypes.ObjectType{
|
|
AttrTypes: sqlserverflexbetaGen.StorageClassesValue{}.AttributeTypes(ctx),
|
|
},
|
|
},
|
|
scList,
|
|
)
|
|
model.StorageClasses = storageClassesList
|
|
}
|
|
|
|
// Set refreshed state
|
|
diags = resp.State.Set(ctx, model)
|
|
resp.Diagnostics.Append(diags...)
|
|
if resp.Diagnostics.HasError() {
|
|
return
|
|
}
|
|
tflog.Info(ctx, "SQL Server Flex flavors read")
|
|
}
|