feat: implement stackit git instances (#791)

* feat: implement stackit git instances

* review changes
This commit is contained in:
Mauritz Uphoff 2025-05-09 08:50:23 +02:00 committed by GitHub
parent c7c64a5806
commit cf7a7d154e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 937 additions and 96 deletions

38
docs/data-sources/git.md Normal file
View file

@ -0,0 +1,38 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackit_git Data Source - stackit"
subcategory: ""
description: |-
Git Instance datasource schema.
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources.
---
# stackit_git (Data Source)
Git Instance datasource schema.
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources.
## Example Usage
```terraform
data "stackit_git" "git" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
instance_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
```
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `instance_id` (String) ID linked to the git instance.
- `project_id` (String) STACKIT project ID to which the git instance is associated.
### Read-Only
- `id` (String) Terraform's internal resource ID, structured as "`project_id`,`instance_id`".
- `name` (String) Unique name linked to the git instance.
- `url` (String) Url linked to the git instance.
- `version` (String) Version linked to the git instance.

View file

@ -159,6 +159,7 @@ Note: AWS specific checks must be skipped as they do not work on STACKIT. For de
- `dns_custom_endpoint` (String) Custom endpoint for the DNS service
- `enable_beta_resources` (Boolean) Enable beta resources. Default is false.
- `experiments` (List of String) Enables experiments. These are unstable features without official support. More information can be found in the README. Available Experiments: [iam]
- `git_custom_endpoint` (String) Custom endpoint for the Git service
- `iaas_custom_endpoint` (String) Custom endpoint for the IaaS service
- `loadbalancer_custom_endpoint` (String) Custom endpoint for the Load Balancer service
- `logme_custom_endpoint` (String) Custom endpoint for the LogMe service

38
docs/resources/git.md Normal file
View file

@ -0,0 +1,38 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "stackit_git Resource - stackit"
subcategory: ""
description: |-
Git Instance resource schema.
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our guide https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources for how to opt-in to use beta resources.
---
# stackit_git (Resource)
Git Instance resource schema.
~> This resource is in beta and may be subject to breaking changes in the future. Use with caution. See our [guide](https://registry.terraform.io/providers/stackitcloud/stackit/latest/docs/guides/opting_into_beta_resources) for how to opt-in to use beta resources.
## Example Usage
```terraform
resource "stackit_git" "git" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "git-example-instance"
}
```
<!-- schema generated by tfplugindocs -->
## Schema
### Required
- `name` (String) Unique name linked to the git instance.
- `project_id` (String) STACKIT project ID to which the git instance is associated.
### Read-Only
- `id` (String) Terraform's internal resource ID, structured as "`project_id`,`instance_id`".
- `instance_id` (String) ID linked to the git instance.
- `url` (String) Url linked to the git instance.
- `version` (String) Version linked to the git instance.

View file

@ -0,0 +1,4 @@
data "stackit_git" "git" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
instance_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}

View file

@ -0,0 +1,4 @@
resource "stackit_git" "git" {
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
name = "git-example-instance"
}

1
go.mod
View file

@ -14,6 +14,7 @@ require (
github.com/stackitcloud/stackit-sdk-go/core v0.17.1
github.com/stackitcloud/stackit-sdk-go/services/cdn v1.0.1
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2
github.com/stackitcloud/stackit-sdk-go/services/git v0.3.2
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2
github.com/stackitcloud/stackit-sdk-go/services/logme v0.22.1

2
go.sum
View file

@ -158,6 +158,8 @@ github.com/stackitcloud/stackit-sdk-go/services/cdn v1.0.1 h1:fWCWCefwgPTJ0BIbFQ
github.com/stackitcloud/stackit-sdk-go/services/cdn v1.0.1/go.mod h1:Gd+M/UZR0rIaHRXhJzkb0r7kl/nDRmpcmqnOPN5fCSQ=
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2 h1:6rb3EM0yXuMIBd1U6WsJoMzEiVaHC3WQFWFvT23OE4Y=
github.com/stackitcloud/stackit-sdk-go/services/dns v0.13.2/go.mod h1:PMHoavoIaRZpkI9BA0nsnRjGoHASVSBon45XB3QyhMA=
github.com/stackitcloud/stackit-sdk-go/services/git v0.3.2 h1:AguA1s9FuwLmSyvGNv4I/O9u7c/x7cMwyCsrM6Tm2SU=
github.com/stackitcloud/stackit-sdk-go/services/git v0.3.2/go.mod h1:XhXHJpOVC9Rpwyf1G+EpMbprBafH9aZb8vWBdR+z0WM=
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1 h1:JXcLcbVesTtwVVb+jJjU3o0FmSpXBRnOw6PVETaeK+E=
github.com/stackitcloud/stackit-sdk-go/services/iaas v0.22.1/go.mod h1:QNH50Pq0Hu21lLDOwa02PIjRjTl0LfEdHoz5snGQRn8=
github.com/stackitcloud/stackit-sdk-go/services/loadbalancer v1.0.2 h1:5rVt3n7kDJvJQxFCtxfx8uZI9PGkvJY9fVJ4yar10Uc=

View file

@ -23,6 +23,7 @@ type ProviderData struct {
AuthorizationCustomEndpoint string
CdnCustomEndpoint string
DnsCustomEndpoint string
GitCustomEndpoint string
IaaSCustomEndpoint string
LoadBalancerCustomEndpoint string
LogMeCustomEndpoint string

View file

@ -0,0 +1,175 @@
package git
import (
"context"
_ "embed"
"fmt"
"maps"
"strings"
"testing"
"github.com/hashicorp/terraform-plugin-testing/config"
"github.com/hashicorp/terraform-plugin-testing/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
stackitSdkConfig "github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/git"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil"
)
//go:embed testdata/resource.tf
var resourceConfig string
var name = fmt.Sprintf("git-%s-instance", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum))
var nameUpdated = fmt.Sprintf("git-%s-instance", acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum))
var testConfigVars = config.Variables{
"project_id": config.StringVariable(testutil.ProjectId),
"name": config.StringVariable(name),
}
func testConfigVarsUpdated() config.Variables {
tempConfig := make(config.Variables, len(testConfigVars))
maps.Copy(tempConfig, testConfigVars)
// update git instance to a new name
// should trigger creating a new instance
tempConfig["name"] = config.StringVariable(nameUpdated)
return tempConfig
}
func TestGitInstance(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV6ProviderFactories: testutil.TestAccProtoV6ProviderFactories,
CheckDestroy: testAccCheckGitInstanceDestroy,
Steps: []resource.TestStep{
// Creation
{
ConfigVariables: testConfigVars,
Config: testutil.GitProviderConfig() + resourceConfig,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVars["project_id"])),
resource.TestCheckResourceAttr("stackit_git.git", "name", testutil.ConvertConfigVariable(testConfigVars["name"])),
resource.TestCheckResourceAttrSet("stackit_git.git", "url"),
resource.TestCheckResourceAttrSet("stackit_git.git", "version"),
resource.TestCheckResourceAttrSet("stackit_git.git", "instance_id"),
),
},
// Data source
{
ConfigVariables: testConfigVars,
Config: fmt.Sprintf(`
%s
data "stackit_git" "git" {
project_id = stackit_git.git.project_id
instance_id = stackit_git.git.instance_id
}
`, testutil.GitProviderConfig()+resourceConfig,
),
Check: resource.ComposeAggregateTestCheckFunc(
// Instance
resource.TestCheckResourceAttr("data.stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVars["project_id"])),
resource.TestCheckResourceAttrPair(
"stackit_git.git", "project_id",
"data.stackit_git.git", "project_id",
),
resource.TestCheckResourceAttrPair(
"stackit_git.git", "instance_id",
"data.stackit_git.git", "instance_id",
),
resource.TestCheckResourceAttrPair(
"stackit_git.git", "name",
"data.stackit_git.git", "name",
),
resource.TestCheckResourceAttrPair(
"stackit_git.git", "url",
"data.stackit_git.git", "url",
),
resource.TestCheckResourceAttrPair(
"stackit_git.git", "version",
"data.stackit_git.git", "version",
),
),
},
// Import
{
ConfigVariables: testConfigVars,
ResourceName: "stackit_git.git",
ImportStateIdFunc: func(s *terraform.State) (string, error) {
r, ok := s.RootModule().Resources["stackit_git.git"]
if !ok {
return "", fmt.Errorf("couldn't find resource stackit_git.git")
}
instanceId, ok := r.Primary.Attributes["instance_id"]
if !ok {
return "", fmt.Errorf("couldn't find attribute instance_id")
}
return fmt.Sprintf("%s,%s", testutil.ProjectId, instanceId), nil
},
ImportState: true,
ImportStateVerify: true,
},
// Update
{
ConfigVariables: testConfigVarsUpdated(),
Config: testutil.GitProviderConfig() + resourceConfig,
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("stackit_git.git", "project_id", testutil.ConvertConfigVariable(testConfigVars["project_id"])),
resource.TestCheckResourceAttr("stackit_git.git", "name", testutil.ConvertConfigVariable(testConfigVarsUpdated()["name"])),
resource.TestCheckResourceAttrSet("stackit_git.git", "url"),
resource.TestCheckResourceAttrSet("stackit_git.git", "version"),
resource.TestCheckResourceAttrSet("stackit_git.git", "instance_id"),
),
},
// Deletion is done by the framework implicitly
},
})
}
func testAccCheckGitInstanceDestroy(s *terraform.State) error {
ctx := context.Background()
var client *git.APIClient
var err error
if testutil.GitCustomEndpoint == "" {
client, err = git.NewAPIClient()
} else {
client, err = git.NewAPIClient(
stackitSdkConfig.WithEndpoint(testutil.GitCustomEndpoint),
)
}
if err != nil {
return fmt.Errorf("creating client: %w", err)
}
var instancesToDestroy []string
for _, rs := range s.RootModule().Resources {
if rs.Type != "stackit_git" {
continue
}
instanceId := strings.Split(rs.Primary.ID, core.Separator)[1]
instancesToDestroy = append(instancesToDestroy, instanceId)
}
instancesResp, err := client.ListInstances(ctx, testutil.ProjectId).Execute()
if err != nil {
return fmt.Errorf("getting git instances: %w", err)
}
gitInstances := *instancesResp.Instances
for i := range gitInstances {
if gitInstances[i].Id == nil {
continue
}
if utils.Contains(instancesToDestroy, *gitInstances[i].Id) {
err := client.DeleteInstance(ctx, testutil.ProjectId, *gitInstances[i].Id).Execute()
if err != nil {
return fmt.Errorf("destroying git instance %s during CheckDestroy: %w", *gitInstances[i].Id, err)
}
}
}
return nil
}

View file

@ -0,0 +1,162 @@
package instance
import (
"context"
"errors"
"fmt"
"net/http"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/services/git"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ datasource.DataSource = &gitDataSource{}
)
// NewGitDataSource creates a new instance of the gitDataSource.
func NewGitDataSource() datasource.DataSource {
return &gitDataSource{}
}
// gitDataSource is the datasource implementation.
type gitDataSource struct {
client *git.APIClient
}
// Configure sets up the API client for the git instance resource.
func (g *gitDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
// Prevent potential panics if the provider is not properly configured.
if req.ProviderData == nil {
return
}
// Validate provider data type before proceeding.
providerData, ok := req.ProviderData.(core.ProviderData)
if !ok {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Expected configure type stackit.ProviderData, got %T", req.ProviderData))
return
}
features.CheckBetaResourcesEnabled(ctx, &providerData, &resp.Diagnostics, "stackit_git", "datasource")
if resp.Diagnostics.HasError() {
return
}
// Initialize the API client with the appropriate authentication and endpoint settings.
var apiClient *git.APIClient
var err error
if providerData.GitCustomEndpoint != "" {
apiClient, err = git.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
config.WithEndpoint(providerData.GitCustomEndpoint),
)
} else {
apiClient, err = git.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
)
}
// Handle API client initialization errors.
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "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
}
// Store the initialized client.
g.client = apiClient
tflog.Info(ctx, "git client configured")
}
// Metadata provides metadata for the git datasource.
func (g *gitDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_git"
}
// Schema defines the schema for the git data source.
func (g *gitDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: features.AddBetaDescription("Git Instance datasource schema."),
Description: "Git Instance datasource schema.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: descriptions["id"],
Computed: true,
},
"project_id": schema.StringAttribute{
Description: descriptions["project_id"],
Required: true,
Validators: []validator.String{
validate.UUID(),
validate.NoSeparator(),
},
},
"instance_id": schema.StringAttribute{
Description: descriptions["instance_id"],
Required: true,
Validators: []validator.String{
validate.UUID(),
validate.NoSeparator(),
},
},
"name": schema.StringAttribute{
Description: descriptions["name"],
Computed: true,
},
"url": schema.StringAttribute{
Description: descriptions["url"],
Computed: true,
},
"version": schema.StringAttribute{
Description: descriptions["version"],
Computed: true,
},
},
}
}
func (g *gitDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
var model Model
diags := req.Config.Get(ctx, &model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
// Extract the project ID and instance id of the model
projectId := model.ProjectId.ValueString()
instanceId := model.InstanceId.ValueString()
// Read the current git instance via id
gitInstanceResp, err := g.client.GetInstance(ctx, projectId, instanceId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if ok && oapiErr.StatusCode == http.StatusNotFound {
resp.State.RemoveResource(ctx)
return
}
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading git instance", fmt.Sprintf("Calling API: %v", err))
return
}
err = mapFields(gitInstanceResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading git instance", fmt.Sprintf("Processing API response: %v", err))
return
}
// Set the updated state.
diags = resp.State.Set(ctx, &model)
resp.Diagnostics.Append(diags...)
tflog.Info(ctx, fmt.Sprintf("read git instance %s", instanceId))
}

View file

@ -0,0 +1,339 @@
package instance
import (
"context"
"errors"
"fmt"
"net/http"
"strings"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/stackit-sdk-go/core/oapierror"
"github.com/stackitcloud/stackit-sdk-go/services/git"
"github.com/stackitcloud/stackit-sdk-go/services/git/wait"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate"
)
// Ensure the implementation satisfies the expected interfaces.
var (
_ resource.Resource = &gitResource{}
_ resource.ResourceWithConfigure = &gitResource{}
_ resource.ResourceWithImportState = &gitResource{}
)
// Model represents the schema for the git resource.
type Model struct {
Id types.String `tfsdk:"id"` // Required by Terraform
ProjectId types.String `tfsdk:"project_id"` // ProjectId associated with the git instance
InstanceId types.String `tfsdk:"instance_id"` // InstanceId associated with the git instance
Name types.String `tfsdk:"name"` // Name linked to the git instance
Url types.String `tfsdk:"url"` // Url linked to the git instance
Version types.String `tfsdk:"version"` // Version linked to the git instance
}
// NewGitResource is a helper function to create a new git resource instance.
func NewGitResource() resource.Resource {
return &gitResource{}
}
// gitResource implements the resource interface for git instances.
type gitResource struct {
client *git.APIClient
}
// descriptions for the attributes in the Schema
var descriptions = map[string]string{
"id": "Terraform's internal resource ID, structured as \"`project_id`,`instance_id`\".",
"project_id": "STACKIT project ID to which the git instance is associated.",
"instance_id": "ID linked to the git instance.",
"name": "Unique name linked to the git instance.",
"url": "Url linked to the git instance.",
"version": "Version linked to the git instance.",
}
// Configure sets up the API client for the git instance resource.
func (g *gitResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
// Prevent potential panics if the provider is not properly configured.
if req.ProviderData == nil {
return
}
// Validate provider data type before proceeding.
providerData, ok := req.ProviderData.(core.ProviderData)
if !ok {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring API client", fmt.Sprintf("Expected configure type stackit.ProviderData, got %T", req.ProviderData))
return
}
features.CheckBetaResourcesEnabled(ctx, &providerData, &resp.Diagnostics, "stackit_git", "resource")
if resp.Diagnostics.HasError() {
return
}
// Initialize the API client with the appropriate authentication and endpoint settings.
var apiClient *git.APIClient
var err error
if providerData.GitCustomEndpoint != "" {
apiClient, err = git.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
config.WithEndpoint(providerData.GitCustomEndpoint),
)
} else {
apiClient, err = git.NewAPIClient(
config.WithCustomAuth(providerData.RoundTripper),
)
}
// Handle API client initialization errors.
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "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
}
// Store the initialized client.
g.client = apiClient
tflog.Info(ctx, "git client configured")
}
// Metadata sets the resource type name for the git instance resource.
func (g *gitResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_git"
}
// Schema defines the schema for the resource.
func (g *gitResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: features.AddBetaDescription("Git Instance resource schema."),
Description: "Git Instance resource schema.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Description: descriptions["id"],
Computed: true,
},
"project_id": schema.StringAttribute{
Description: descriptions["project_id"],
Required: true,
Validators: []validator.String{
validate.UUID(),
validate.NoSeparator(),
},
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
},
"instance_id": schema.StringAttribute{
Description: descriptions["instance_id"],
Computed: true,
Validators: []validator.String{
validate.UUID(),
validate.NoSeparator(),
},
},
"name": schema.StringAttribute{
Description: descriptions["name"],
Required: true,
PlanModifiers: []planmodifier.String{
stringplanmodifier.RequiresReplace(),
},
Validators: []validator.String{
stringvalidator.LengthBetween(5, 32),
},
},
"url": schema.StringAttribute{
Description: descriptions["url"],
Computed: true,
},
"version": schema.StringAttribute{
Description: descriptions["version"],
Computed: true,
},
},
}
}
// Create creates the resource and sets the initial Terraform state for the git instance.
func (g *gitResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { // nolint:gocritic // function signature required by Terraform
// Retrieve the planned values for the resource.
var model Model
diags := req.Plan.Get(ctx, &model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
// Set logging context with the project ID and instance ID.
projectId := model.ProjectId.ValueString()
instanceName := model.Name.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_name", instanceName)
// Create the new git instance via the API client.
gitInstanceResp, err := g.client.CreateInstance(ctx, projectId).
CreateInstancePayload(git.CreateInstancePayload{Name: &instanceName}).
Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating git instance", fmt.Sprintf("Calling API: %v", err))
return
}
gitInstanceId := *gitInstanceResp.Id
_, err = wait.CreateGitInstanceWaitHandler(ctx, g.client, projectId, gitInstanceId).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating git instance", fmt.Sprintf("Git instance creation waiting: %v", err))
return
}
err = mapFields(gitInstanceResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating git instance", fmt.Sprintf("Mapping fields: %v", err))
return
}
// Set the state with fully populated data.
diags = resp.State.Set(ctx, model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
tflog.Info(ctx, "Git Instance created")
}
// Read refreshes the Terraform state with the latest git instance data.
func (g *gitResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { // nolint:gocritic // function signature required by Terraform
// Retrieve the current state of the resource.
var model Model
diags := req.State.Get(ctx, &model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
// Extract the project ID and instance id of the model
projectId := model.ProjectId.ValueString()
instanceId := model.InstanceId.ValueString()
// Read the current git instance via id
gitInstanceResp, err := g.client.GetInstance(ctx, projectId, instanceId).Execute()
if err != nil {
var oapiErr *oapierror.GenericOpenAPIError
ok := errors.As(err, &oapiErr)
if ok && oapiErr.StatusCode == http.StatusNotFound {
resp.State.RemoveResource(ctx)
return
}
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading git instance", fmt.Sprintf("Calling API: %v", err))
return
}
err = mapFields(gitInstanceResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error reading git instance", fmt.Sprintf("Processing API response: %v", err))
return
}
// Set the updated state.
diags = resp.State.Set(ctx, &model)
resp.Diagnostics.Append(diags...)
tflog.Info(ctx, fmt.Sprintf("read git instance %s", instanceId))
}
// Update attempts to update the resource. In this case, git instances cannot be updated.
// Note: This method is intentionally left without update logic because changes
// to 'project_id' or 'name' require the resource to be entirely replaced.
// As a result, the Update function is redundant since any modifications will
// automatically trigger a resource recreation through Terraform's built-in
// lifecycle management.
func (g *gitResource) Update(ctx context.Context, _ resource.UpdateRequest, resp *resource.UpdateResponse) { // nolint:gocritic // function signature required by Terraform
// git instances cannot be updated, so we log an error.
core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating git instance", "Git Instance can't be updated")
}
// Delete deletes the git instance and removes it from the Terraform state on success.
func (g *gitResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { // nolint:gocritic // function signature required by Terraform
// Retrieve current state of the resource.
var model Model
diags := req.State.Get(ctx, &model)
resp.Diagnostics.Append(diags...)
if resp.Diagnostics.HasError() {
return
}
projectId := model.ProjectId.ValueString()
instanceId := model.InstanceId.ValueString()
ctx = tflog.SetField(ctx, "project_id", projectId)
ctx = tflog.SetField(ctx, "instance_id", instanceId)
// Call API to delete the existing git instance.
err := g.client.DeleteInstance(ctx, projectId, instanceId).Execute()
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting git instance", fmt.Sprintf("Calling API: %v", err))
return
}
_, err = wait.DeleteGitInstanceWaitHandler(ctx, g.client, projectId, instanceId).WaitWithContext(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error waiting for instance deletion", fmt.Sprintf("Instance deletion waiting: %v", err))
return
}
tflog.Info(ctx, "Git instance deleted")
}
// ImportState imports a resource into the Terraform state on success.
// The expected format of the resource import identifier is: project_id,instance_id
func (g *gitResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
// Split the import identifier to extract project ID and email.
idParts := strings.Split(req.ID, core.Separator)
// Ensure the import identifier format is correct.
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
core.LogAndAddError(ctx, &resp.Diagnostics,
"Error importing git instance",
fmt.Sprintf("Expected import identifier with format: [project_id],[instance_id] Got: %q", req.ID),
)
return
}
projectId := idParts[0]
instanceId := idParts[1]
// Set the project ID and instance ID attributes in the state.
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("project_id"), projectId)...)
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("instance_id"), instanceId)...)
tflog.Info(ctx, "Git instance state imported")
}
// mapFields maps a Git response to the model.
func mapFields(resp *git.Instance, model *Model) error {
if resp == nil {
return fmt.Errorf("response input is nil")
}
if model == nil {
return fmt.Errorf("model input is nil")
}
if resp.Id == nil {
return fmt.Errorf("git instance id not present")
}
// Build the ID by combining the project ID and instance id and assign the model's fields.
idParts := []string{model.ProjectId.ValueString(), *resp.Id}
model.Id = types.StringValue(strings.Join(idParts, core.Separator))
model.Url = types.StringPointerValue(resp.Url)
model.Name = types.StringPointerValue(resp.Name)
model.InstanceId = types.StringPointerValue(resp.Id)
model.Version = types.StringPointerValue(resp.Version)
return nil
}

View file

@ -0,0 +1,79 @@
package instance
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/stackitcloud/stackit-sdk-go/core/utils"
"github.com/stackitcloud/stackit-sdk-go/services/git"
)
func TestMapFields(t *testing.T) {
tests := []struct {
description string
input *git.Instance
expected Model
isValid bool
}{
{
"default_values",
&git.Instance{
Created: nil,
Id: utils.Ptr("id"),
Name: utils.Ptr("foo"),
Url: utils.Ptr("https://foo.com"),
Version: utils.Ptr("v0.0.1"),
},
Model{
Id: types.StringValue("pid,id"),
ProjectId: types.StringValue("pid"),
InstanceId: types.StringValue("id"),
Name: types.StringValue("foo"),
Url: types.StringValue("https://foo.com"),
Version: types.StringValue("v0.0.1"),
},
true,
},
{
"nil_response",
nil,
Model{},
false,
},
{
"nil_response_2",
&git.Instance{},
Model{},
false,
},
{
"no_id",
&git.Instance{
Name: utils.Ptr("foo"),
},
Model{},
false,
},
}
for _, tt := range tests {
t.Run(tt.description, func(t *testing.T) {
state := &Model{
ProjectId: tt.expected.ProjectId,
}
err := mapFields(tt.input, state)
if !tt.isValid && err == nil {
t.Fatalf("Should have failed")
}
if tt.isValid && err != nil {
t.Fatalf("Should not have failed: %v", err)
}
if tt.isValid {
diff := cmp.Diff(state, &tt.expected)
if diff != "" {
t.Fatalf("Data does not match: %s", diff)
}
}
})
}
}

View file

@ -0,0 +1,8 @@
variable "project_id" {}
variable "name" {}
resource "stackit_git" "git" {
project_id = var.project_id
name = var.name
}

View file

@ -173,7 +173,7 @@ func (r *serviceAccountResource) Create(ctx context.Context, req resource.Create
model.Name = types.StringValue(serviceAccountName)
err = mapFields(serviceAccountResp, &model)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating service account", fmt.Sprintf("Processing API payload: %v", err))
core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating service account", fmt.Sprintf("Processing API response: %v", err))
return
}

View file

@ -53,6 +53,7 @@ var (
ArgusCustomEndpoint = os.Getenv("TF_ACC_ARGUS_CUSTOM_ENDPOINT")
CdnCustomEndpoint = os.Getenv("TF_ACC_CDN_CUSTOM_ENDPOINT")
DnsCustomEndpoint = os.Getenv("TF_ACC_DNS_CUSTOM_ENDPOINT")
GitCustomEndpoint = os.Getenv("TF_ACC_GIT_CUSTOM_ENDPOINT")
IaaSCustomEndpoint = os.Getenv("TF_ACC_IAAS_CUSTOM_ENDPOINT")
LoadBalancerCustomEndpoint = os.Getenv("TF_ACC_LOADBALANCER_CUSTOM_ENDPOINT")
LogMeCustomEndpoint = os.Getenv("TF_ACC_LOGME_CUSTOM_ENDPOINT")
@ -433,6 +434,23 @@ func ServiceAccountProviderConfig() string {
)
}
func GitProviderConfig() string {
if GitCustomEndpoint == "" {
return `
provider "stackit" {
default_region = "eu01"
enable_beta_resources = true
}`
}
return fmt.Sprintf(`
provider "stackit" {
git_custom_endpoint = "%s"
enable_beta_resources = true
}`,
GitCustomEndpoint,
)
}
func ResourceNameWithDateTime(name string) string {
dateTime := time.Now().Format(time.RFC3339)
// Remove timezone to have a smaller datetime

View file

@ -12,12 +12,17 @@ import (
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
sdkauth "github.com/stackitcloud/stackit-sdk-go/core/auth"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features"
roleAssignements "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/authorization/roleassignments"
cdnCustomDomain "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/cdn/customdomain"
cdn "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/cdn/distribution"
dnsRecordSet "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/dns/recordset"
dnsZone "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/dns/zone"
gitInstance "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/git/instance"
iaasAffinityGroup "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/affinitygroup"
iaasImage "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/image"
iaasKeyPair "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/keypair"
@ -73,11 +78,6 @@ import (
skeKubeconfig "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/ske/kubeconfig"
sqlServerFlexInstance "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/sqlserverflex/instance"
sqlServerFlexUser "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/sqlserverflex/user"
sdkauth "github.com/stackitcloud/stackit-sdk-go/core/auth"
"github.com/stackitcloud/stackit-sdk-go/core/config"
"github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core"
)
// Ensure the implementation satisfies the expected interfaces
@ -118,6 +118,7 @@ type providerModel struct {
ArgusCustomEndpoint types.String `tfsdk:"argus_custom_endpoint"`
CdnCustomEndpoint types.String `tfsdk:"cdn_custom_endpoint"`
DNSCustomEndpoint types.String `tfsdk:"dns_custom_endpoint"`
GitCustomEndpoint types.String `tfsdk:"git_custom_endpoint"`
IaaSCustomEndpoint types.String `tfsdk:"iaas_custom_endpoint"`
PostgresFlexCustomEndpoint types.String `tfsdk:"postgresflex_custom_endpoint"`
MongoDBFlexCustomEndpoint types.String `tfsdk:"mongodbflex_custom_endpoint"`
@ -159,6 +160,7 @@ func (p *Provider) Schema(_ context.Context, _ provider.SchemaRequest, resp *pro
"argus_custom_endpoint": "Custom endpoint for the Argus service",
"cdn_custom_endpoint": "Custom endpoint for the CDN service",
"dns_custom_endpoint": "Custom endpoint for the DNS service",
"git_custom_endpoint": "Custom endpoint for the Git service",
"iaas_custom_endpoint": "Custom endpoint for the IaaS service",
"mongodbflex_custom_endpoint": "Custom endpoint for the MongoDB Flex service",
"modelserving_custom_endpoint": "Custom endpoint for the AI Model Serving service",
@ -244,6 +246,10 @@ func (p *Provider) Schema(_ context.Context, _ provider.SchemaRequest, resp *pro
Optional: true,
Description: descriptions["dns_custom_endpoint"],
},
"git_custom_endpoint": schema.StringAttribute{
Optional: true,
Description: descriptions["git_custom_endpoint"],
},
"iaas_custom_endpoint": schema.StringAttribute{
Optional: true,
Description: descriptions["iaas_custom_endpoint"],
@ -358,98 +364,61 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
// Configure SDK client
sdkConfig := &config.Configuration{}
var providerData core.ProviderData
if !(providerConfig.CredentialsFilePath.IsUnknown() || providerConfig.CredentialsFilePath.IsNull()) {
sdkConfig.CredentialsFilePath = providerConfig.CredentialsFilePath.ValueString()
// Helper function to set a string field if it's known and not null
setStringField := func(v basetypes.StringValue, setter func(string)) {
if !v.IsUnknown() && !v.IsNull() {
setter(v.ValueString())
}
}
if !(providerConfig.ServiceAccountKey.IsUnknown() || providerConfig.ServiceAccountKey.IsNull()) {
sdkConfig.ServiceAccountKey = providerConfig.ServiceAccountKey.ValueString()
}
if !(providerConfig.ServiceAccountKeyPath.IsUnknown() || providerConfig.ServiceAccountKeyPath.IsNull()) {
sdkConfig.ServiceAccountKeyPath = providerConfig.ServiceAccountKeyPath.ValueString()
}
if !(providerConfig.PrivateKey.IsUnknown() || providerConfig.PrivateKey.IsNull()) {
sdkConfig.PrivateKey = providerConfig.PrivateKey.ValueString()
}
if !(providerConfig.PrivateKeyPath.IsUnknown() || providerConfig.PrivateKeyPath.IsNull()) {
sdkConfig.PrivateKeyPath = providerConfig.PrivateKeyPath.ValueString()
}
if !(providerConfig.Token.IsUnknown() || providerConfig.Token.IsNull()) {
sdkConfig.Token = providerConfig.Token.ValueString()
}
if !(providerConfig.DefaultRegion.IsUnknown() || providerConfig.DefaultRegion.IsNull()) {
providerData.DefaultRegion = providerConfig.DefaultRegion.ValueString()
} else if !(providerConfig.Region.IsUnknown() || providerConfig.Region.IsNull()) { // nolint:staticcheck // preliminary handling of deprecated attribute
providerData.Region = providerConfig.Region.ValueString() // nolint:staticcheck // preliminary handling of deprecated attribute
}
if !(providerConfig.CdnCustomEndpoint.IsUnknown() || providerConfig.CdnCustomEndpoint.IsNull()) {
providerData.CdnCustomEndpoint = providerConfig.CdnCustomEndpoint.ValueString()
}
if !(providerConfig.DNSCustomEndpoint.IsUnknown() || providerConfig.DNSCustomEndpoint.IsNull()) {
providerData.DnsCustomEndpoint = providerConfig.DNSCustomEndpoint.ValueString()
}
if !(providerConfig.IaaSCustomEndpoint.IsUnknown() || providerConfig.IaaSCustomEndpoint.IsNull()) {
providerData.IaaSCustomEndpoint = providerConfig.IaaSCustomEndpoint.ValueString()
}
if !(providerConfig.PostgresFlexCustomEndpoint.IsUnknown() || providerConfig.PostgresFlexCustomEndpoint.IsNull()) {
providerData.PostgresFlexCustomEndpoint = providerConfig.PostgresFlexCustomEndpoint.ValueString()
}
if !(providerConfig.ModelServingCustomEndpoint.IsUnknown() || providerConfig.ModelServingCustomEndpoint.IsNull()) {
providerData.ModelServingCustomEndpoint = providerConfig.ModelServingCustomEndpoint.ValueString()
}
if !(providerConfig.MongoDBFlexCustomEndpoint.IsUnknown() || providerConfig.MongoDBFlexCustomEndpoint.IsNull()) {
providerData.MongoDBFlexCustomEndpoint = providerConfig.MongoDBFlexCustomEndpoint.ValueString()
}
if !(providerConfig.LoadBalancerCustomEndpoint.IsUnknown() || providerConfig.LoadBalancerCustomEndpoint.IsNull()) {
providerData.LoadBalancerCustomEndpoint = providerConfig.LoadBalancerCustomEndpoint.ValueString()
}
if !(providerConfig.LogMeCustomEndpoint.IsUnknown() || providerConfig.LogMeCustomEndpoint.IsNull()) {
providerData.LogMeCustomEndpoint = providerConfig.LogMeCustomEndpoint.ValueString()
}
if !(providerConfig.RabbitMQCustomEndpoint.IsUnknown() || providerConfig.RabbitMQCustomEndpoint.IsNull()) {
providerData.RabbitMQCustomEndpoint = providerConfig.RabbitMQCustomEndpoint.ValueString()
}
if !(providerConfig.MariaDBCustomEndpoint.IsUnknown() || providerConfig.MariaDBCustomEndpoint.IsNull()) {
providerData.MariaDBCustomEndpoint = providerConfig.MariaDBCustomEndpoint.ValueString()
}
if !(providerConfig.AuthorizationCustomEndpoint.IsUnknown() || providerConfig.AuthorizationCustomEndpoint.IsNull()) {
providerData.AuthorizationCustomEndpoint = providerConfig.AuthorizationCustomEndpoint.ValueString()
}
if !(providerConfig.ObjectStorageCustomEndpoint.IsUnknown() || providerConfig.ObjectStorageCustomEndpoint.IsNull()) {
providerData.ObjectStorageCustomEndpoint = providerConfig.ObjectStorageCustomEndpoint.ValueString()
}
if !(providerConfig.ObservabilityCustomEndpoint.IsUnknown() || providerConfig.ObservabilityCustomEndpoint.IsNull()) {
providerData.ObservabilityCustomEndpoint = providerConfig.ObservabilityCustomEndpoint.ValueString()
}
if !(providerConfig.OpenSearchCustomEndpoint.IsUnknown() || providerConfig.OpenSearchCustomEndpoint.IsNull()) {
providerData.OpenSearchCustomEndpoint = providerConfig.OpenSearchCustomEndpoint.ValueString()
}
if !(providerConfig.RedisCustomEndpoint.IsUnknown() || providerConfig.RedisCustomEndpoint.IsNull()) {
providerData.RedisCustomEndpoint = providerConfig.RedisCustomEndpoint.ValueString()
}
if !(providerConfig.ResourceManagerCustomEndpoint.IsUnknown() || providerConfig.ResourceManagerCustomEndpoint.IsNull()) {
providerData.ResourceManagerCustomEndpoint = providerConfig.ResourceManagerCustomEndpoint.ValueString()
}
if !(providerConfig.SecretsManagerCustomEndpoint.IsUnknown() || providerConfig.SecretsManagerCustomEndpoint.IsNull()) {
providerData.SecretsManagerCustomEndpoint = providerConfig.SecretsManagerCustomEndpoint.ValueString()
}
if !(providerConfig.SQLServerFlexCustomEndpoint.IsUnknown() || providerConfig.SQLServerFlexCustomEndpoint.IsNull()) {
providerData.SQLServerFlexCustomEndpoint = providerConfig.SQLServerFlexCustomEndpoint.ValueString()
}
if !(providerConfig.ServiceAccountCustomEndpoint.IsUnknown() || providerConfig.ServiceAccountCustomEndpoint.IsNull()) {
providerData.ServiceAccountCustomEndpoint = providerConfig.ServiceAccountCustomEndpoint.ValueString()
}
if !(providerConfig.SKECustomEndpoint.IsUnknown() || providerConfig.SKECustomEndpoint.IsNull()) {
providerData.SKECustomEndpoint = providerConfig.SKECustomEndpoint.ValueString()
}
if !(providerConfig.ServiceEnablementCustomEndpoint.IsUnknown() || providerConfig.ServiceEnablementCustomEndpoint.IsNull()) {
providerData.ServiceEnablementCustomEndpoint = providerConfig.ServiceEnablementCustomEndpoint.ValueString()
}
if !(providerConfig.TokenCustomEndpoint.IsUnknown() || providerConfig.TokenCustomEndpoint.IsNull()) {
sdkConfig.TokenCustomUrl = providerConfig.TokenCustomEndpoint.ValueString()
}
if !(providerConfig.EnableBetaResources.IsUnknown() || providerConfig.EnableBetaResources.IsNull()) {
providerData.EnableBetaResources = providerConfig.EnableBetaResources.ValueBool()
// Helper function to set a boolean field if it's known and not null
setBoolField := func(v basetypes.BoolValuable, setter func(bool)) {
if !v.IsUnknown() && !v.IsNull() {
val, err := v.ToBoolValue(ctx)
if err != nil {
core.LogAndAddError(ctx, &resp.Diagnostics, "Error configuring provider", fmt.Sprintf("Setting up bool value: %v", diags.Errors()))
}
setter(val.ValueBool())
}
}
// Configure SDK client
setStringField(providerConfig.CredentialsFilePath, func(v string) { sdkConfig.CredentialsFilePath = v })
setStringField(providerConfig.ServiceAccountKey, func(v string) { sdkConfig.ServiceAccountKey = v })
setStringField(providerConfig.ServiceAccountKeyPath, func(v string) { sdkConfig.ServiceAccountKeyPath = v })
setStringField(providerConfig.PrivateKey, func(v string) { sdkConfig.PrivateKey = v })
setStringField(providerConfig.PrivateKeyPath, func(v string) { sdkConfig.PrivateKeyPath = v })
setStringField(providerConfig.Token, func(v string) { sdkConfig.Token = v })
setStringField(providerConfig.TokenCustomEndpoint, func(v string) { sdkConfig.TokenCustomUrl = v })
// Provider Data Configuration
setStringField(providerConfig.DefaultRegion, func(v string) { providerData.DefaultRegion = v })
setStringField(providerConfig.Region, func(v string) { providerData.Region = v }) // nolint:staticcheck // preliminary handling of deprecated attribute
setStringField(providerConfig.CdnCustomEndpoint, func(v string) { providerData.CdnCustomEndpoint = v })
setStringField(providerConfig.DNSCustomEndpoint, func(v string) { providerData.DnsCustomEndpoint = v })
setStringField(providerConfig.GitCustomEndpoint, func(v string) { providerData.GitCustomEndpoint = v })
setStringField(providerConfig.IaaSCustomEndpoint, func(v string) { providerData.IaaSCustomEndpoint = v })
setStringField(providerConfig.PostgresFlexCustomEndpoint, func(v string) { providerData.PostgresFlexCustomEndpoint = v })
setStringField(providerConfig.ModelServingCustomEndpoint, func(v string) { providerData.ModelServingCustomEndpoint = v })
setStringField(providerConfig.MongoDBFlexCustomEndpoint, func(v string) { providerData.MongoDBFlexCustomEndpoint = v })
setStringField(providerConfig.LoadBalancerCustomEndpoint, func(v string) { providerData.LoadBalancerCustomEndpoint = v })
setStringField(providerConfig.LogMeCustomEndpoint, func(v string) { providerData.LogMeCustomEndpoint = v })
setStringField(providerConfig.RabbitMQCustomEndpoint, func(v string) { providerData.RabbitMQCustomEndpoint = v })
setStringField(providerConfig.MariaDBCustomEndpoint, func(v string) { providerData.MariaDBCustomEndpoint = v })
setStringField(providerConfig.AuthorizationCustomEndpoint, func(v string) { providerData.AuthorizationCustomEndpoint = v })
setStringField(providerConfig.ObjectStorageCustomEndpoint, func(v string) { providerData.ObjectStorageCustomEndpoint = v })
setStringField(providerConfig.ObservabilityCustomEndpoint, func(v string) { providerData.ObservabilityCustomEndpoint = v })
setStringField(providerConfig.OpenSearchCustomEndpoint, func(v string) { providerData.OpenSearchCustomEndpoint = v })
setStringField(providerConfig.RedisCustomEndpoint, func(v string) { providerData.RedisCustomEndpoint = v })
setStringField(providerConfig.ResourceManagerCustomEndpoint, func(v string) { providerData.ResourceManagerCustomEndpoint = v })
setStringField(providerConfig.SecretsManagerCustomEndpoint, func(v string) { providerData.SecretsManagerCustomEndpoint = v })
setStringField(providerConfig.SQLServerFlexCustomEndpoint, func(v string) { providerData.SQLServerFlexCustomEndpoint = v })
setStringField(providerConfig.ServiceAccountCustomEndpoint, func(v string) { providerData.ServiceAccountCustomEndpoint = v })
setStringField(providerConfig.SKECustomEndpoint, func(v string) { providerData.SKECustomEndpoint = v })
setStringField(providerConfig.ServiceEnablementCustomEndpoint, func(v string) { providerData.ServiceEnablementCustomEndpoint = v })
setBoolField(providerConfig.EnableBetaResources, func(v bool) { providerData.EnableBetaResources = v })
if !(providerConfig.Experiments.IsUnknown() || providerConfig.Experiments.IsNull()) {
var experimentValues []string
diags := providerConfig.Experiments.ElementsAs(ctx, &experimentValues, false)
@ -480,6 +449,7 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource
cdnCustomDomain.NewCustomDomainDataSource,
dnsZone.NewZoneDataSource,
dnsRecordSet.NewRecordSetDataSource,
gitInstance.NewGitDataSource,
iaasAffinityGroup.NewAffinityGroupDatasource,
iaasImage.NewImageDataSource,
iaasNetwork.NewNetworkDataSource,
@ -537,6 +507,7 @@ func (p *Provider) Resources(_ context.Context) []func() resource.Resource {
cdnCustomDomain.NewCustomDomainResource,
dnsZone.NewZoneResource,
dnsRecordSet.NewRecordSetResource,
gitInstance.NewGitResource,
iaasAffinityGroup.NewAffinityGroupResource,
iaasImage.NewImageResource,
iaasNetwork.NewNetworkResource,