terraform-provider-stackitp.../stackit/internal/core/core.go
Andre Harms 4a2819787d
fix: linting (#77)
## 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: #77
Co-authored-by: Andre Harms <andre.harms@stackit.cloud>
Co-committed-by: Andre Harms <andre.harms@stackit.cloud>
2026-02-19 08:54:34 +00:00

180 lines
6 KiB
Go

// Copyright (c) STACKIT
package core
import (
"context"
"fmt"
"net/http"
"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"
)
type ResourceType string
const (
Resource ResourceType = "resource"
Datasource ResourceType = "datasource"
EphemeralResource ResourceType = "ephemeral-resource"
// Separator used for concatenation of TF-internal resource ID
Separator = ","
ResourceRegionFallbackDocstring = "Uses the `default_region` specified in the provider configuration as a fallback in case no `region` is defined on resource level."
DatasourceRegionFallbackDocstring = "Uses the `default_region` specified in the provider configuration as a fallback in case no `region` is defined on datasource level."
)
type EphemeralProviderData struct {
ProviderData
PrivateKey string //nolint:gosec //this is a placeholder and not used in this code
PrivateKeyPath string
ServiceAccountKey string
ServiceAccountKeyPath string
TokenCustomEndpoint string
}
type ProviderData struct {
RoundTripper http.RoundTripper
ServiceAccountEmail string // Deprecated: ServiceAccountEmail is not required and will be removed after 12th June 2025.
// Deprecated: Use DefaultRegion instead
Region string
DefaultRegion string
AuthorizationCustomEndpoint string
CdnCustomEndpoint string
DnsCustomEndpoint string
GitCustomEndpoint string
IaaSCustomEndpoint string
KMSCustomEndpoint string
LoadBalancerCustomEndpoint string
LogMeCustomEndpoint string
MariaDBCustomEndpoint string
MongoDBFlexCustomEndpoint string
ModelServingCustomEndpoint string
ObjectStorageCustomEndpoint string
ObservabilityCustomEndpoint string
OpenSearchCustomEndpoint string
PostgresFlexCustomEndpoint string
RabbitMQCustomEndpoint string
RedisCustomEndpoint string
ResourceManagerCustomEndpoint string
ScfCustomEndpoint string
SecretsManagerCustomEndpoint string
SQLServerFlexCustomEndpoint string
ServerBackupCustomEndpoint string
ServerUpdateCustomEndpoint string
SKECustomEndpoint string
ServiceEnablementCustomEndpoint string
ServiceAccountCustomEndpoint string
EnableBetaResources bool
Experiments []string
Version string // version of the STACKIT Terraform provider
}
// GetRegion returns the effective region for the provider, falling back to the deprecated _region_ attribute
func (pd *ProviderData) GetRegion() string {
if pd.DefaultRegion != "" {
return pd.DefaultRegion
} else if pd.Region != "" {
return pd.Region
}
// final fallback
return "eu01"
}
func (pd *ProviderData) GetRegionWithOverride(overrideRegion types.String) string {
if overrideRegion.IsUnknown() || overrideRegion.IsNull() {
return pd.GetRegion()
}
return overrideRegion.ValueString()
}
// DiagsToError Converts TF diagnostics' errors into an error with a human-readable description.
// If there are no errors, the output is nil
func DiagsToError(diags diag.Diagnostics) error {
if !diags.HasError() {
return nil
}
diagsError := diags.Errors()
diagsStrings := make([]string, 0)
for _, diagnostic := range diagsError {
diagsStrings = append(
diagsStrings, fmt.Sprintf(
"(%s) %s",
diagnostic.Summary(),
diagnostic.Detail(),
),
)
}
return fmt.Errorf("%s", strings.Join(diagsStrings, ";"))
}
// 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)
}
func LogAndAddWarningBeta(ctx context.Context, diags *diag.Diagnostics, name string, resourceType ResourceType) {
warnTitle := fmt.Sprintf("The %s %q is in beta", resourceType, name)
warnContent := fmt.Sprintf(
"The %s %q is in beta and may be subject to breaking changes in the future. Use with caution.",
resourceType,
name,
)
tflog.Warn(ctx, fmt.Sprintf("%s | %s", warnTitle, warnContent))
diags.AddWarning(warnTitle, warnContent)
}
func LogAndAddErrorBeta(ctx context.Context, diags *diag.Diagnostics, name string, resourceType ResourceType) {
errTitle := fmt.Sprintf("The %s %q is in beta and beta is not enabled", resourceType, name)
errContent := fmt.Sprintf(
`The %s %q is in beta and the beta functionality is currently not enabled. To enable it, set the environment variable STACKIT_TF_ENABLE_BETA_RESOURCES to "true" or set the "enable_beta_resources" provider field to true.`,
resourceType,
name,
)
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
}