Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .github/docs/contribution-guide/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ func (r *barResource) Create(ctx context.Context, req resource.CreateRequest, re
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
region := model.Region.ValueString() // not needed for global APIs
ctx = tflog.SetField(ctx, "project_id", projectId)
Expand All @@ -202,6 +203,7 @@ func (r *barResource) Create(ctx context.Context, req resource.CreateRequest, re
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating bar", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

// only in case the create bar API call is asynchronous (Make sure to include *ALL* fields which are part of the
// internal terraform resource id! And please include the comment below in your code):
Expand Down Expand Up @@ -244,6 +246,7 @@ func (r *barResource) Read(ctx context.Context, req resource.ReadRequest, resp *
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
region := r.providerData.GetRegionWithOverride(model.Region)
barId := model.BarId.ValueString()
Expand All @@ -256,6 +259,7 @@ func (r *barResource) Read(ctx context.Context, req resource.ReadRequest, resp *
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading bar", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

// Map response body to schema
err = mapFields(barResp, &model)
Expand Down Expand Up @@ -285,6 +289,7 @@ func (r *barResource) Delete(ctx context.Context, req resource.DeleteRequest, re
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
region := model.Region.ValueString()
barId := model.BarId.ValueString()
Expand All @@ -297,6 +302,7 @@ func (r *barResource) Delete(ctx context.Context, req resource.DeleteRequest, re
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting bar", fmt.Sprintf("Calling API: %v", err))
}
ctx = core.LogResponse(ctx)

// only in case the bar delete API endpoint is asynchronous: use a wait handler to wait for the delete operation to complete
_, err = wait.DeleteBarWaitHandler(ctx, r.client, projectId, region, barId).WaitWithContext(ctx)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ require (
github.com/hashicorp/terraform-plugin-go v0.29.0
github.com/hashicorp/terraform-plugin-log v0.10.0
github.com/hashicorp/terraform-plugin-testing v1.13.3
github.com/stackitcloud/stackit-sdk-go/core v0.19.0
github.com/stackitcloud/stackit-sdk-go/core v0.20.0
github.com/stackitcloud/stackit-sdk-go/services/cdn v1.6.0
github.com/stackitcloud/stackit-sdk-go/services/dns v0.17.1
github.com/stackitcloud/stackit-sdk-go/services/git v0.8.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8=
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
github.com/stackitcloud/stackit-sdk-go/core v0.19.0 h1:dtJcs6/TTCzzb2RKI7HJugDrbCkaFEDmn1pOeFe8qnI=
github.com/stackitcloud/stackit-sdk-go/core v0.19.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ=
github.com/stackitcloud/stackit-sdk-go/core v0.20.0 h1:4rrUk6uT1g4nOn5/g1uXukP07Tux/o5xbMz/f/qE1rY=
github.com/stackitcloud/stackit-sdk-go/core v0.20.0/go.mod h1:fqto7M82ynGhEnpZU6VkQKYWYoFG5goC076JWXTUPRQ=
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0 h1:7ZKd3b+E/R4TEVShLTXxx5FrsuDuJBOyuVOuKTMa4mo=
github.com/stackitcloud/stackit-sdk-go/services/authorization v0.9.0/go.mod h1:/FoXa6hF77Gv8brrvLBCKa5ie1Xy9xn39yfHwaln9Tw=
github.com/stackitcloud/stackit-sdk-go/services/cdn v1.6.0 h1:Q+qIdejeMsYMkbtVoI9BpGlKGdSVFRBhH/zj44SP8TM=
Expand Down
25 changes: 25 additions & 0 deletions stackit/internal/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"strings"

"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/runtime"

"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-log/tflog"
Expand Down Expand Up @@ -102,12 +103,18 @@ func DiagsToError(diags diag.Diagnostics) error {

// LogAndAddError Logs the error and adds it to the diags
func LogAndAddError(ctx context.Context, diags *diag.Diagnostics, summary, detail string) {
if traceId := runtime.GetTraceId(ctx); traceId != "" {
detail = fmt.Sprintf("%s\nTrace ID: %q", detail, traceId)
}
tflog.Error(ctx, fmt.Sprintf("%s | %s", summary, detail))
diags.AddError(summary, detail)
}

// LogAndAddWarning Logs the warning and adds it to the diags
func LogAndAddWarning(ctx context.Context, diags *diag.Diagnostics, summary, detail string) {
if traceId := runtime.GetTraceId(ctx); traceId != "" {
detail = fmt.Sprintf("%s\nTrace ID: %q", detail, traceId)
}
tflog.Warn(ctx, fmt.Sprintf("%s | %s", summary, detail))
diags.AddWarning(summary, detail)
}
Expand All @@ -125,3 +132,21 @@ func LogAndAddErrorBeta(ctx context.Context, diags *diag.Diagnostics, name strin
tflog.Error(ctx, fmt.Sprintf("%s | %s", errTitle, errContent))
diags.AddError(errTitle, errContent)
}

func InitProviderContext(ctx context.Context) context.Context {
// Capture http response to get trace-id
var httpResp *http.Response
ctx = runtime.WithCaptureHTTPResponse(ctx, &httpResp)

return ctx
}

func LogResponse(ctx context.Context) context.Context {
// Logs the trace-id of the request
traceId := runtime.GetTraceId(ctx)
ctx = tflog.SetField(ctx, "x-trace-id", traceId)
tflog.Info(ctx, "response data", map[string]interface{}{
"x-trace-id": traceId,
})
return ctx
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,7 @@ func (r *roleAssignmentResource) Create(ctx context.Context, req resource.Create
return
}

ctx = core.InitProviderContext(ctx)
ctx = r.annotateLogger(ctx, &model)

if err := r.checkDuplicate(ctx, model); err != nil {
Expand All @@ -170,6 +171,7 @@ func (r *roleAssignmentResource) Create(ctx context.Context, req resource.Create
core.LogAndAddError(ctx, &resp.Diagnostics, fmt.Sprintf("Error creating %s role assignment", r.apiName), fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

// Map response body to schema
err = mapMembersResponse(createResp, &model)
Expand All @@ -194,13 +196,15 @@ func (r *roleAssignmentResource) Read(ctx context.Context, req resource.ReadRequ
return
}

ctx = core.InitProviderContext(ctx)
ctx = r.annotateLogger(ctx, &model)

listResp, err := r.authorizationClient.ListMembers(ctx, r.apiName, model.ResourceId.ValueString()).Subject(model.Subject.ValueString()).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading authorizations", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

// Map response body to schema
err = mapListMembersResponse(listResp, &model)
Expand Down Expand Up @@ -232,6 +236,7 @@ func (r *roleAssignmentResource) Delete(ctx context.Context, req resource.Delete
return
}

ctx = core.InitProviderContext(ctx)
ctx = r.annotateLogger(ctx, &model)

payload := authorization.RemoveMembersPayload{
Expand All @@ -246,6 +251,7 @@ func (r *roleAssignmentResource) Delete(ctx context.Context, req resource.Delete
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, fmt.Sprintf("Error deleting %s role assignment", r.apiName), fmt.Sprintf("Calling API: %v", err))
}
ctx = core.LogResponse(ctx)

tflog.Info(ctx, fmt.Sprintf("%s role assignment deleted", r.apiName))
}
Expand Down
2 changes: 2 additions & 0 deletions stackit/internal/services/cdn/customdomain/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ func (r *customDomainDataSource) Read(ctx context.Context, req datasource.ReadRe
return
}

ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
distributionId := model.DistributionId.ValueString()
Expand All @@ -145,6 +146,7 @@ func (r *customDomainDataSource) Read(ctx context.Context, req datasource.ReadRe
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN custom domain", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

// Call the new data source mapping function
err = mapCustomDomainDataSourceFields(customDomainResp, &model, projectId, distributionId)
Expand Down
11 changes: 10 additions & 1 deletion stackit/internal/services/cdn/customdomain/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func (r *customDomainResource) Create(ctx context.Context, req resource.CreateRe
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
distributionId := model.DistributionId.ValueString()
Expand All @@ -207,6 +208,8 @@ func (r *customDomainResource) Create(ctx context.Context, req resource.CreateRe
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN custom domain", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

_, err = wait.CreateCDNCustomDomainWaitHandler(ctx, r.client, projectId, distributionId, name).SetTimeout(5 * time.Minute).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN custom domain", fmt.Sprintf("Waiting for create: %v", err))
Expand Down Expand Up @@ -240,6 +243,7 @@ func (r *customDomainResource) Read(ctx context.Context, req resource.ReadReques
return
}

ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
distributionId := model.DistributionId.ValueString()
Expand All @@ -248,7 +252,6 @@ func (r *customDomainResource) Read(ctx context.Context, req resource.ReadReques
ctx = tflog.SetField(ctx, "name", name)

customDomainResp, err := r.client.GetCustomDomain(ctx, projectId, distributionId, name).Execute()

if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
// n.b. err is caught here if of type *oapierror.GenericOpenAPIError, which the stackit SDK client returns
Expand All @@ -261,6 +264,8 @@ func (r *customDomainResource) Read(ctx context.Context, req resource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN custom domain", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

err = mapCustomDomainResourceFields(customDomainResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN custom domain", fmt.Sprintf("Processing API payload: %v", err))
Expand All @@ -283,6 +288,7 @@ func (r *customDomainResource) Update(ctx context.Context, req resource.UpdateRe
return
}

ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
distributionId := model.DistributionId.ValueString()
Expand All @@ -305,6 +311,7 @@ func (r *customDomainResource) Update(ctx context.Context, req resource.UpdateRe
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating CDN custom domain certificate", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)

_, err = wait.CreateCDNCustomDomainWaitHandler(ctx, r.client, projectId, distributionId, name).SetTimeout(5 * time.Minute).WaitWithContext(ctx)
if err != nil {
Expand Down Expand Up @@ -338,6 +345,7 @@ func (r *customDomainResource) Delete(ctx context.Context, req resource.DeleteRe
return
}

ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
distributionId := model.DistributionId.ValueString()
Expand All @@ -349,6 +357,7 @@ func (r *customDomainResource) Delete(ctx context.Context, req resource.DeleteRe
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Delete CDN custom domain", fmt.Sprintf("Delete custom domain: %v", err))
}
ctx = core.LogResponse(ctx)
_, err = wait.DeleteCDNCustomDomainWaitHandler(ctx, r.client, projectId, distributionId, name).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Delete CDN custom domain", fmt.Sprintf("Waiting for deletion: %v", err))
Expand Down
2 changes: 2 additions & 0 deletions stackit/internal/services/cdn/distribution/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ func (r *distributionDataSource) Read(ctx context.Context, req datasource.ReadRe
return
}

ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
distributionId := model.DistributionId.ValueString()
distributionResp, err := r.client.GetDistributionExecute(ctx, projectId, distributionId)
Expand All @@ -199,6 +200,7 @@ func (r *distributionDataSource) Read(ctx context.Context, req datasource.ReadRe
resp.State.RemoveResource(ctx)
return
}
ctx = core.LogResponse(ctx)
err = mapFields(ctx, distributionResp.Distribution, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN distribution", fmt.Sprintf("Error processing API response: %v", err))
Expand Down
8 changes: 8 additions & 0 deletions stackit/internal/services/cdn/distribution/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ func (r *distributionResource) Create(ctx context.Context, req resource.CreateRe
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)

Expand All @@ -348,6 +349,7 @@ func (r *distributionResource) Create(ctx context.Context, req resource.CreateRe
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN distribution", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)
waitResp, err := wait.CreateDistributionPoolWaitHandler(ctx, r.client, projectId, *createResp.Distribution.Id).SetTimeout(5 * time.Minute).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating CDN distribution", fmt.Sprintf("Waiting for create: %v", err))
Expand Down Expand Up @@ -376,6 +378,7 @@ func (r *distributionResource) Read(ctx context.Context, req resource.ReadReques
return
}

ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
distributionId := model.DistributionId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
Expand All @@ -394,6 +397,7 @@ func (r *distributionResource) Read(ctx context.Context, req resource.ReadReques
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN distribution", fmt.Sprintf("Calling API: %v", err))
return
}
ctx = core.LogResponse(ctx)
err = mapFields(ctx, cdnResp.Distribution, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading CDN ditribution", fmt.Sprintf("Processing API payload: %v", err))
Expand All @@ -416,6 +420,7 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe
return
}

ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
distributionId := model.DistributionId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
Expand Down Expand Up @@ -515,6 +520,7 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", fmt.Sprintf("Patch distribution: %v", err))
return
}
ctx = core.LogResponse(ctx)

waitResp, err := wait.UpdateDistributionWaitHandler(ctx, r.client, projectId, distributionId).WaitWithContext(ctx)
if err != nil {
Expand Down Expand Up @@ -543,6 +549,7 @@ func (r *distributionResource) Delete(ctx context.Context, req resource.DeleteRe
if resp.Diagnostics.HasError() {
return
}
ctx = core.LogResponse(ctx)
projectId := model.ProjectId.ValueString()
distributionId := model.DistributionId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
Expand All @@ -552,6 +559,7 @@ func (r *distributionResource) Delete(ctx context.Context, req resource.DeleteRe
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Delete CDN distribution", fmt.Sprintf("Delete distribution: %v", err))
}
ctx = core.LogResponse(ctx)
_, err = wait.DeleteDistributionWaitHandler(ctx, r.client, projectId, distributionId).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Delete CDN distribution", fmt.Sprintf("Waiting for deletion: %v", err))
Expand Down
2 changes: 2 additions & 0 deletions stackit/internal/services/dns/recordset/datasource.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ func (d *recordSetDataSource) Read(ctx context.Context, req datasource.ReadReque
if resp.Diagnostics.HasError() {
return
}
ctx = core.InitProviderContext(ctx)
projectId := model.ProjectId.ValueString()
zoneId := model.ZoneId.ValueString()
recordSetId := model.RecordSetId.ValueString()
Expand All @@ -157,6 +158,7 @@ func (d *recordSetDataSource) Read(ctx context.Context, req datasource.ReadReque
resp.State.RemoveResource(ctx)
return
}
ctx = core.LogResponse(ctx)
if recordSetResp != nil && recordSetResp.Rrset.State != nil && *recordSetResp.Rrset.State == dns.RECORDSETSTATE_DELETE_SUCCEEDED {
resp.State.RemoveResource(ctx)
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading record set", "Record set was deleted successfully")
Expand Down
Loading
Loading