feat: implement stackit git instances (#791)
* feat: implement stackit git instances * review changes
This commit is contained in:
parent
c7c64a5806
commit
cf7a7d154e
16 changed files with 937 additions and 96 deletions
38
docs/data-sources/git.md
Normal file
38
docs/data-sources/git.md
Normal 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.
|
||||
|
|
@ -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
38
docs/resources/git.md
Normal 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.
|
||||
4
examples/data-sources/stackit_git/data-source.tf
Normal file
4
examples/data-sources/stackit_git/data-source.tf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
data "stackit_git" "git" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
instance_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
}
|
||||
4
examples/resources/stackit_git/resource.tf
Normal file
4
examples/resources/stackit_git/resource.tf
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
resource "stackit_git" "git" {
|
||||
project_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
|
||||
name = "git-example-instance"
|
||||
}
|
||||
1
go.mod
1
go.mod
|
|
@ -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
2
go.sum
|
|
@ -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=
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ type ProviderData struct {
|
|||
AuthorizationCustomEndpoint string
|
||||
CdnCustomEndpoint string
|
||||
DnsCustomEndpoint string
|
||||
GitCustomEndpoint string
|
||||
IaaSCustomEndpoint string
|
||||
LoadBalancerCustomEndpoint string
|
||||
LogMeCustomEndpoint string
|
||||
|
|
|
|||
175
stackit/internal/services/git/git_acc_test.go
Normal file
175
stackit/internal/services/git/git_acc_test.go
Normal 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
|
||||
}
|
||||
162
stackit/internal/services/git/instance/datasource.go
Normal file
162
stackit/internal/services/git/instance/datasource.go
Normal 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))
|
||||
}
|
||||
339
stackit/internal/services/git/instance/resource.go
Normal file
339
stackit/internal/services/git/instance/resource.go
Normal 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
|
||||
}
|
||||
79
stackit/internal/services/git/instance/resource_test.go
Normal file
79
stackit/internal/services/git/instance/resource_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
8
stackit/internal/services/git/testdata/resource.tf
vendored
Normal file
8
stackit/internal/services/git/testdata/resource.tf
vendored
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
|
||||
variable "project_id" {}
|
||||
variable "name" {}
|
||||
|
||||
resource "stackit_git" "git" {
|
||||
project_id = var.project_id
|
||||
name = var.name
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue