Skip to content
Merged
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
15 changes: 15 additions & 0 deletions .github/docs/contribution-guide/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ 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 @@ -203,6 +206,8 @@ func (r *barResource) Create(ctx context.Context, req resource.CreateRequest, re
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):
// Write id attributes to state before polling via the wait handler - just in case anything goes wrong during the wait handler
Expand Down Expand Up @@ -244,6 +249,9 @@ 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 @@ -257,6 +265,8 @@ func (r *barResource) Read(ctx context.Context, req resource.ReadRequest, resp *
return
}

ctx = core.LogResponse(ctx)

// Map response body to schema
err = mapFields(barResp, &model)
if err != nil {
Expand Down Expand Up @@ -285,6 +295,9 @@ 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 @@ -298,6 +311,8 @@ func (r *barResource) Delete(ctx context.Context, req resource.DeleteRequest, re
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)
if err != nil {
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
28 changes: 28 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,20 @@ 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 +134,22 @@ func LogAndAddErrorBeta(ctx context.Context, diags *diag.Diagnostics, name strin
tflog.Error(ctx, fmt.Sprintf("%s | %s", errTitle, errContent))
diags.AddError(errTitle, errContent)
}

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

// LogResponse logs the trace-id of the last request
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,8 @@ 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 @@ -171,6 +173,8 @@ func (r *roleAssignmentResource) Create(ctx context.Context, req resource.Create
return
}

ctx = core.LogResponse(ctx)

// Map response body to schema
err = mapMembersResponse(createResp, &model)
if err != nil {
Expand All @@ -194,6 +198,8 @@ 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()
Expand All @@ -202,6 +208,8 @@ func (r *roleAssignmentResource) Read(ctx context.Context, req resource.ReadRequ
return
}

ctx = core.LogResponse(ctx)

// Map response body to schema
err = mapListMembersResponse(listResp, &model)
if err != nil {
Expand Down Expand Up @@ -232,6 +240,8 @@ 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 @@ -247,6 +257,8 @@ func (r *roleAssignmentResource) Delete(ctx context.Context, req resource.Delete
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
4 changes: 4 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,8 @@ 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 @@ -146,6 +148,8 @@ func (r *customDomainDataSource) Read(ctx context.Context, req datasource.ReadRe
return
}

ctx = core.LogResponse(ctx)

// Call the new data source mapping function
err = mapCustomDomainDataSourceFields(customDomainResp, &model, projectId, distributionId)
if err != nil {
Expand Down
21 changes: 20 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,9 @@ 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 +210,9 @@ 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 +246,8 @@ 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 +256,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 +268,9 @@ 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 +293,8 @@ 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 @@ -306,6 +318,8 @@ func (r *customDomainResource) Update(ctx context.Context, req resource.UpdateRe
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 updating CDN custom domain certificate", fmt.Sprintf("Waiting for update: %v", err))
Expand Down Expand Up @@ -338,6 +352,8 @@ 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 +365,9 @@ 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
5 changes: 5 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,8 @@ 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 +201,9 @@ 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
21 changes: 21 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,9 @@ 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 +351,9 @@ 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 +382,8 @@ 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 +402,9 @@ 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 +427,8 @@ 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 @@ -516,6 +529,8 @@ func (r *distributionResource) Update(ctx context.Context, req resource.UpdateRe
return
}

ctx = core.LogResponse(ctx)

waitResp, err := wait.UpdateDistributionWaitHandler(ctx, r.client, projectId, distributionId).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Update CDN distribution", fmt.Sprintf("Waiting for update: %v", err))
Expand Down Expand Up @@ -543,6 +558,9 @@ 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 +570,9 @@ 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
Loading
Loading