Extend DSA Reads to compute plan name and version from plan ID (#20)

* Extend Read to compute plan name and version from plan ID

* Lint

* Fix error handling; Pass client to loadPlanNameAndVersion

* Change error to warning

* Replicate to other DSA

* Update acc tests to test import of plan name and version
This commit is contained in:
João Palet 2023-09-20 11:00:08 +02:00 committed by GitHub
parent 7f35b5a1dc
commit 386ccac6b4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 240 additions and 42 deletions

View file

@ -174,6 +174,13 @@ func (r *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)

View file

@ -234,8 +234,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
ctx = tflog.SetField(ctx, "project_id", projectId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load LogMe service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -310,6 +309,13 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
core.LogAndAddError(ctx, &resp.Diagnostics, "Error mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
@ -330,8 +336,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = tflog.SetField(ctx, "instance_id", instanceId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load LogMe service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -641,3 +646,25 @@ func (r *instanceResource) loadPlanId(ctx context.Context, diags *diag.Diagnosti
}
diags.AddError("Invalid plan_name", fmt.Sprintf("Couldn't find plan_name '%s' for version %s, available names are:%s", planName, version, availablePlanNames))
}
func loadPlanNameAndVersion(ctx context.Context, client *logme.APIClient, diags *diag.Diagnostics, model *Model) {
projectId := model.ProjectId.ValueString()
planId := model.PlanId.ValueString()
res, err := client.GetOfferings(ctx, projectId).Execute()
if err != nil {
diags.AddError("Failed to list LogMe offerings", err.Error())
return
}
for _, offer := range *res.Offerings {
for _, plan := range *offer.Plans {
if strings.EqualFold(*plan.Id, planId) && plan.Id != nil {
model.PlanName = types.StringPointerValue(plan.Name)
model.Version = types.StringPointerValue(offer.Version)
return
}
}
}
diags.AddWarning("Failed to get plan_name and version", fmt.Sprintf("Couldn't find plan_name and version for plan_id = %s", planId))
}

View file

@ -136,9 +136,8 @@ func TestAccLogMeResource(t *testing.T) {
}
return fmt.Sprintf("%s,%s", testutil.ProjectId, instanceId), nil
},
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"plan_name", "version"},
ImportState: true,
ImportStateVerify: true,
},
{
ResourceName: "stackit_logme_credentials.credentials",

View file

@ -174,6 +174,13 @@ func (r *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)

View file

@ -216,8 +216,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
ctx = tflog.SetField(ctx, "project_id", projectId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load MariaDB service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -292,6 +291,13 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
core.LogAndAddError(ctx, &resp.Diagnostics, "Error mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
@ -312,8 +318,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = tflog.SetField(ctx, "instance_id", instanceId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load MariaDB service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -622,3 +627,25 @@ func (r *instanceResource) loadPlanId(ctx context.Context, diags *diag.Diagnosti
}
diags.AddError("Invalid plan_name", fmt.Sprintf("Couldn't find plan_name '%s' for version %s, available names are:%s", planName, version, availablePlanNames))
}
func loadPlanNameAndVersion(ctx context.Context, client *mariadb.APIClient, diags *diag.Diagnostics, model *Model) {
projectId := model.ProjectId.ValueString()
planId := model.PlanId.ValueString()
res, err := client.GetOfferings(ctx, projectId).Execute()
if err != nil {
diags.AddError("Failed to list MariaDB offerings", err.Error())
return
}
for _, offer := range *res.Offerings {
for _, plan := range *offer.Plans {
if strings.EqualFold(*plan.Id, planId) && plan.Id != nil {
model.PlanName = types.StringPointerValue(plan.Name)
model.Version = types.StringPointerValue(offer.Version)
return
}
}
}
diags.AddWarning("Failed to get plan_name and version", fmt.Sprintf("Couldn't find plan_name and version for plan_id = %s", planId))
}

View file

@ -135,9 +135,8 @@ func TestAccMariaDBResource(t *testing.T) {
}
return fmt.Sprintf("%s,%s", testutil.ProjectId, instanceId), nil
},
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"plan_name", "version"},
ImportState: true,
ImportStateVerify: true,
},
{
ResourceName: "stackit_mariadb_credentials.credentials",

View file

@ -174,6 +174,13 @@ func (r *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)

View file

@ -216,8 +216,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
ctx = tflog.SetField(ctx, "project_id", projectId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load OpenSearch service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -292,6 +291,13 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
core.LogAndAddError(ctx, &resp.Diagnostics, "Error mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
@ -312,8 +318,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = tflog.SetField(ctx, "instance_id", instanceId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load OpenSearch service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -621,3 +626,25 @@ func (r *instanceResource) loadPlanId(ctx context.Context, diags *diag.Diagnosti
}
diags.AddError("Invalid plan_name", fmt.Sprintf("Couldn't find plan_name '%s' for version %s, available names are:%s", planName, version, availablePlanNames))
}
func loadPlanNameAndVersion(ctx context.Context, client *opensearch.APIClient, diags *diag.Diagnostics, model *Model) {
projectId := model.ProjectId.ValueString()
planId := model.PlanId.ValueString()
res, err := client.GetOfferings(ctx, projectId).Execute()
if err != nil {
diags.AddError("Failed to list OpenSearch offerings", err.Error())
return
}
for _, offer := range *res.Offerings {
for _, plan := range *offer.Plans {
if strings.EqualFold(*plan.Id, planId) && plan.Id != nil {
model.PlanName = types.StringPointerValue(plan.Name)
model.Version = types.StringPointerValue(offer.Version)
return
}
}
}
diags.AddWarning("Failed to get plan_name and version", fmt.Sprintf("Couldn't find plan_name and version for plan_id = %s", planId))
}

View file

@ -160,9 +160,8 @@ func TestAccOpenSearchResource(t *testing.T) {
return fmt.Sprintf("%s,%s", testutil.ProjectId, instanceId), nil
},
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"plan_name", "version"},
ImportState: true,
ImportStateVerify: true,
},
{
ResourceName: "stackit_opensearch_credentials.credentials",

View file

@ -191,6 +191,13 @@ func (r *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)

View file

@ -261,8 +261,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
ctx = tflog.SetField(ctx, "project_id", projectId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load PostgreSQL service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -376,6 +375,13 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
core.LogAndAddError(ctx, &resp.Diagnostics, "Error mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
@ -396,8 +402,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = tflog.SetField(ctx, "instance_id", instanceId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load PostgreSQL service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -702,3 +707,25 @@ func (r *instanceResource) loadPlanId(ctx context.Context, diags *diag.Diagnosti
}
diags.AddError("Invalid plan_name", fmt.Sprintf("Couldn't find plan_name '%s' for version %s, available names are:%s", planName, version, availablePlanNames))
}
func loadPlanNameAndVersion(ctx context.Context, client *postgresql.APIClient, diags *diag.Diagnostics, model *Model) {
projectId := model.ProjectId.ValueString()
planId := model.PlanId.ValueString()
res, err := client.GetOfferings(ctx, projectId).Execute()
if err != nil {
diags.AddError("Failed to list PostgreSQL offerings", err.Error())
return
}
for _, offer := range *res.Offerings {
for _, plan := range *offer.Plans {
if strings.EqualFold(*plan.Id, planId) && plan.Id != nil {
model.PlanName = types.StringPointerValue(plan.Name)
model.Version = types.StringPointerValue(offer.Version)
return
}
}
}
diags.AddWarning("Failed to get plan_name and version", fmt.Sprintf("Couldn't find plan_name and version for plan_id = %s", planId))
}

View file

@ -144,9 +144,8 @@ func TestAccPostgreSQLResource(t *testing.T) {
}
return fmt.Sprintf("%s,%s", testutil.ProjectId, instanceId), nil
},
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"plan_name", "version"},
ImportState: true,
ImportStateVerify: true,
},
{
ResourceName: "stackit_postgresql_credentials.credentials",

View file

@ -174,6 +174,13 @@ func (r *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, &state)
resp.Diagnostics.Append(diags...)

View file

@ -229,8 +229,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
ctx = tflog.SetField(ctx, "project_id", projectId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load RabbitMQ service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -326,6 +325,13 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
core.LogAndAddError(ctx, &resp.Diagnostics, "Error mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
@ -346,8 +352,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = tflog.SetField(ctx, "instance_id", instanceId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load RabbitMQ service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -635,3 +640,25 @@ func (r *instanceResource) loadPlanId(ctx context.Context, diags *diag.Diagnosti
}
diags.AddError("Invalid plan_name", fmt.Sprintf("Couldn't find plan_name '%s' for version %s, available names are:%s", planName, version, availablePlanNames))
}
func loadPlanNameAndVersion(ctx context.Context, client *rabbitmq.APIClient, diags *diag.Diagnostics, model *Model) {
projectId := model.ProjectId.ValueString()
planId := model.PlanId.ValueString()
res, err := client.GetOfferings(ctx, projectId).Execute()
if err != nil {
diags.AddError("Failed to list RabbitMQ offerings", err.Error())
return
}
for _, offer := range *res.Offerings {
for _, plan := range *offer.Plans {
if strings.EqualFold(*plan.Id, planId) && plan.Id != nil {
model.PlanName = types.StringPointerValue(plan.Name)
model.Version = types.StringPointerValue(offer.Version)
return
}
}
}
diags.AddWarning("Failed to get plan_name and version", fmt.Sprintf("Couldn't find plan_name and version for plan_id = %s", planId))
}

View file

@ -181,9 +181,8 @@ func TestAccRabbitMQResource(t *testing.T) {
}
return fmt.Sprintf("%s,%s", testutil.ProjectId, instanceId), nil
},
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"plan_name", "version"},
ImportState: true,
ImportStateVerify: true,
},
{
ResourceName: "stackit_rabbitmq_credentials.credentials",

View file

@ -174,6 +174,13 @@ func (r *instanceDataSource) Read(ctx context.Context, req datasource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)

View file

@ -226,8 +226,7 @@ func (r *instanceResource) Create(ctx context.Context, req resource.CreateReques
ctx = tflog.SetField(ctx, "project_id", projectId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load Redis service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -323,6 +322,13 @@ func (r *instanceResource) Read(ctx context.Context, req resource.ReadRequest, r
core.LogAndAddError(ctx, &resp.Diagnostics, "Error mapping fields", err.Error())
return
}
// Compute and store values not present in the API response
loadPlanNameAndVersion(ctx, r.client, &resp.Diagnostics, &state)
if resp.Diagnostics.HasError() {
return
}
// Set refreshed state
diags = resp.State.Set(ctx, state)
resp.Diagnostics.Append(diags...)
@ -343,8 +349,7 @@ func (r *instanceResource) Update(ctx context.Context, req resource.UpdateReques
ctx = tflog.SetField(ctx, "instance_id", instanceId)
r.loadPlanId(ctx, &resp.Diagnostics, &model)
if diags.HasError() {
core.LogAndAddError(ctx, &diags, "Failed to load Redis service plan", "plan "+model.PlanName.ValueString())
if resp.Diagnostics.HasError() {
return
}
@ -632,3 +637,25 @@ func (r *instanceResource) loadPlanId(ctx context.Context, diags *diag.Diagnosti
}
diags.AddError("Invalid plan_name", fmt.Sprintf("Couldn't find plan_name '%s' for version %s, available names are:%s", planName, version, availablePlanNames))
}
func loadPlanNameAndVersion(ctx context.Context, client *redis.APIClient, diags *diag.Diagnostics, model *Model) {
projectId := model.ProjectId.ValueString()
planId := model.PlanId.ValueString()
res, err := client.GetOfferings(ctx, projectId).Execute()
if err != nil {
diags.AddError("Failed to list Redis offerings", err.Error())
return
}
for _, offer := range *res.Offerings {
for _, plan := range *offer.Plans {
if strings.EqualFold(*plan.Id, planId) && plan.Id != nil {
model.PlanName = types.StringPointerValue(plan.Name)
model.Version = types.StringPointerValue(offer.Version)
return
}
}
}
diags.AddWarning("Failed to get plan_name and version", fmt.Sprintf("Couldn't find plan_name and version for plan_id = %s", planId))
}

View file

@ -181,9 +181,8 @@ func TestAccRedisResource(t *testing.T) {
}
return fmt.Sprintf("%s,%s", testutil.ProjectId, instanceId), nil
},
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"plan_name", "version"},
ImportState: true,
ImportStateVerify: true,
},
{
ResourceName: "stackit_redis_credentials.credentials",