From c63222ae0db47f13115c6772dd6a89195ed50cbf Mon Sep 17 00:00:00 2001 From: Peter Paul Schaffrath Date: Tue, 5 May 2026 15:41:06 +0200 Subject: [PATCH] chore(provider): refactor sdk client creation to allow mock injection --- .../services/iaas/affinitygroup/datasource.go | 18 +-- .../services/iaas/affinitygroup/resource.go | 23 ++-- .../services/iaas/image/datasource.go | 17 ++- .../internal/services/iaas/image/resource.go | 31 +++-- .../services/iaas/imagev2/datasource.go | 19 +-- .../services/iaas/keypair/datasource.go | 18 +-- .../services/iaas/keypair/resource.go | 23 ++-- .../services/iaas/machinetype/datasource.go | 12 +- .../services/iaas/network/datasource.go | 17 ++- .../services/iaas/network/resource.go | 30 +++-- .../services/iaas/networkarea/datasource.go | 25 ++-- .../services/iaas/networkarea/resource.go | 42 ++++--- .../iaas/networkarearegion/datasource.go | 23 ++-- .../iaas/networkarearegion/resource.go | 34 +++--- .../iaas/networkarearoute/datasource.go | 18 +-- .../iaas/networkarearoute/resource.go | 23 ++-- .../iaas/networkinterface/datasource.go | 18 +-- .../iaas/networkinterface/resource.go | 23 ++-- .../iaas/networkinterfaceattach/resource.go | 26 ++-- .../services/iaas/publicip/datasource.go | 18 +-- .../services/iaas/publicip/resource.go | 23 ++-- .../iaas/publicipassociate/resource.go | 22 ++-- .../iaas/publicipranges/datasource.go | 18 +-- .../iaas/routingtable/route/datasource.go | 19 +-- .../iaas/routingtable/route/resource.go | 27 ++-- .../iaas/routingtable/routes/datasource.go | 19 +-- .../iaas/routingtable/table/datasource.go | 18 +-- .../iaas/routingtable/table/resource.go | 24 ++-- .../iaas/routingtable/tables/datasource.go | 21 ++-- .../services/iaas/securitygroup/datasource.go | 18 +-- .../services/iaas/securitygroup/resource.go | 23 ++-- .../iaas/securitygrouprule/datasource.go | 18 +-- .../iaas/securitygrouprule/resource.go | 22 ++-- .../services/iaas/server/datasource.go | 17 ++- .../internal/services/iaas/server/resource.go | 44 ++++--- .../iaas/serviceaccountattach/resource.go | 26 ++-- stackit/internal/services/iaas/utils/util.go | 19 --- .../services/iaas/volume/datasource.go | 18 ++- .../internal/services/iaas/volume/resource.go | 30 +++-- .../services/iaas/volume/resource_test.go | 1 + .../iaas/volume/unittest/resource_test.go | 75 ++++++++++++ .../iaas/volume/unittest/testdata/resource.tf | 13 ++ .../services/iaas/volumeattach/resource.go | 25 ++-- stackit/internal/testutil/testutil.go | 103 +++++++++------- .../utils/clientutils/clienttestutils.go | 36 ++++++ .../internal/utils/clientutils/clientutils.go | 60 +++++++++ .../utils/clientutils/clientutils_test.go | 35 ++++++ stackit/provider.go | 115 ++++++++++++------ 48 files changed, 887 insertions(+), 460 deletions(-) create mode 100644 stackit/internal/services/iaas/volume/unittest/resource_test.go create mode 100644 stackit/internal/services/iaas/volume/unittest/testdata/resource.tf create mode 100644 stackit/internal/utils/clientutils/clienttestutils.go create mode 100644 stackit/internal/utils/clientutils/clientutils.go create mode 100644 stackit/internal/utils/clientutils/clientutils_test.go diff --git a/stackit/internal/services/iaas/affinitygroup/datasource.go b/stackit/internal/services/iaas/affinitygroup/datasource.go index 937f6a43e..c610bb139 100644 --- a/stackit/internal/services/iaas/affinitygroup/datasource.go +++ b/stackit/internal/services/iaas/affinitygroup/datasource.go @@ -7,7 +7,7 @@ import ( "regexp" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" @@ -28,12 +28,16 @@ var ( _ datasource.DataSourceWithConfigure = &affinityGroupDatasource{} ) -func NewAffinityGroupDatasource() datasource.DataSource { - return &affinityGroupDatasource{} +func NewAffinityGroupDatasource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &affinityGroupDatasource{ + clientFactory: clientFactory, + } } type affinityGroupDatasource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -44,11 +48,11 @@ func (d *affinityGroupDatasource) Configure(ctx context.Context, req datasource. return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -133,7 +137,7 @@ func (d *affinityGroupDatasource) Read(ctx context.Context, req datasource.ReadR ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "affinity_group_id", affinityGroupId) - affinityGroupResp, err := d.client.DefaultAPI.GetAffinityGroup(ctx, projectId, region, affinityGroupId).Execute() + affinityGroupResp, err := d.client.GetAffinityGroup(ctx, projectId, region, affinityGroupId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/affinitygroup/resource.go b/stackit/internal/services/iaas/affinitygroup/resource.go index 5b48672b3..2c019dcc7 100644 --- a/stackit/internal/services/iaas/affinitygroup/resource.go +++ b/stackit/internal/services/iaas/affinitygroup/resource.go @@ -9,8 +9,7 @@ import ( "strings" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" - - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" @@ -47,13 +46,17 @@ type Model struct { Members types.List `tfsdk:"members"` } -func NewAffinityGroupResource() resource.Resource { - return &affinityGroupResource{} +func NewAffinityGroupResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &affinityGroupResource{ + clientFactory: clientFactory, + } } // affinityGroupResource is the resource implementation. type affinityGroupResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -100,11 +103,11 @@ func (r *affinityGroupResource) Configure(ctx context.Context, req resource.Conf return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -210,7 +213,7 @@ func (r *affinityGroupResource) Create(ctx context.Context, req resource.CreateR core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating affinity group", fmt.Sprintf("Creating API payload: %v", err)) return } - affinityGroupResp, err := r.client.DefaultAPI.CreateAffinityGroup(ctx, projectId, region).CreateAffinityGroupPayload(*payload).Execute() + affinityGroupResp, err := r.client.CreateAffinityGroup(ctx, projectId, region).CreateAffinityGroupPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating affinity group", fmt.Sprintf("Calling API: %v", err)) return @@ -258,7 +261,7 @@ func (r *affinityGroupResource) Read(ctx context.Context, req resource.ReadReque ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "affinity_group_id", affinityGroupId) - affinityGroupResp, err := r.client.DefaultAPI.GetAffinityGroup(ctx, projectId, region, affinityGroupId).Execute() + affinityGroupResp, err := r.client.GetAffinityGroup(ctx, projectId, region, affinityGroupId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -309,7 +312,7 @@ func (r *affinityGroupResource) Delete(ctx context.Context, req resource.DeleteR ctx = tflog.SetField(ctx, "affinity_group_id", affinityGroupId) // Delete existing affinity group - err := r.client.DefaultAPI.DeleteAffinityGroup(ctx, projectId, region, affinityGroupId).Execute() + err := r.client.DeleteAffinityGroup(ctx, projectId, region, affinityGroupId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/image/datasource.go b/stackit/internal/services/iaas/image/datasource.go index d224eb6f7..05479cee3 100644 --- a/stackit/internal/services/iaas/image/datasource.go +++ b/stackit/internal/services/iaas/image/datasource.go @@ -7,6 +7,7 @@ import ( "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource" @@ -45,13 +46,17 @@ type DataSourceModel struct { } // NewImageDataSource is a helper function to simplify the provider implementation. -func NewImageDataSource() datasource.DataSource { - return &imageDataSource{} +func NewImageDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &imageDataSource{ + clientFactory: clientFactory, + } } // imageDataSource is the data source implementation. type imageDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -67,11 +72,11 @@ func (d *imageDataSource) Configure(ctx context.Context, req datasource.Configur return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -231,7 +236,7 @@ func (d *imageDataSource) Read(ctx context.Context, req datasource.ReadRequest, ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "image_id", imageId) - imageResp, err := d.client.DefaultAPI.GetImage(ctx, projectId, region, imageId).Execute() + imageResp, err := d.client.GetImage(ctx, projectId, region, imageId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/image/resource.go b/stackit/internal/services/iaas/image/resource.go index 2441818b4..54e78d805 100644 --- a/stackit/internal/services/iaas/image/resource.go +++ b/stackit/internal/services/iaas/image/resource.go @@ -11,6 +11,7 @@ import ( "time" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" @@ -108,13 +109,17 @@ var checksumTypes = map[string]attr.Type{ } // NewImageResource is a helper function to simplify the provider implementation. -func NewImageResource() resource.Resource { - return &imageResource{} +func NewImageResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &imageResource{ + clientFactory: clientFactory, + } } // imageResource is the resource implementation. type imageResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -161,11 +166,11 @@ func (r *imageResource) Configure(ctx context.Context, req resource.ConfigureReq return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -436,7 +441,7 @@ func (r *imageResource) Create(ctx context.Context, req resource.CreateRequest, } // Create new image - imageCreateResp, err := r.client.DefaultAPI.CreateImage(ctx, projectId, region).CreateImagePayload(*payload).Execute() + imageCreateResp, err := r.client.CreateImage(ctx, projectId, region).CreateImagePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating image", fmt.Sprintf("Calling API: %v", err)) return @@ -447,7 +452,7 @@ func (r *imageResource) Create(ctx context.Context, req resource.CreateRequest, ctx = tflog.SetField(ctx, "image_id", imageCreateResp.Id) // Get the image object, as the creation response does not contain all fields - image, err := r.client.DefaultAPI.GetImage(ctx, projectId, region, imageCreateResp.Id).Execute() + image, err := r.client.GetImage(ctx, projectId, region, imageCreateResp.Id).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating image", fmt.Sprintf("Calling API: %v", err)) return @@ -475,8 +480,8 @@ func (r *imageResource) Create(ctx context.Context, req resource.CreateRequest, } // Wait for image to become available - waiter := wait.UploadImageWaitHandler(ctx, r.client.DefaultAPI, projectId, region, imageCreateResp.Id) //nolint:tfwriteid // false positive - id fields are actually stored already using the mapFields() call above - waiter = waiter.SetTimeout(7 * 24 * time.Hour) // Set timeout to one week, to make the timeout useless + waiter := wait.UploadImageWaitHandler(ctx, r.client, projectId, region, imageCreateResp.Id) //nolint:tfwriteid // false positive - id fields are actually stored already using the mapFields() call above + waiter = waiter.SetTimeout(7 * 24 * time.Hour) // Set timeout to one week, to make the timeout useless waitResp, err := waiter.WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating image", fmt.Sprintf("Waiting for image to become available: %v", err)) @@ -523,7 +528,7 @@ func (r *imageResource) Read(ctx context.Context, req resource.ReadRequest, resp ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "image_id", imageId) - imageResp, err := r.client.DefaultAPI.GetImage(ctx, projectId, region, imageId).Execute() + imageResp, err := r.client.GetImage(ctx, projectId, region, imageId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -586,7 +591,7 @@ func (r *imageResource) Update(ctx context.Context, req resource.UpdateRequest, return } // Update existing image - updatedImage, err := r.client.DefaultAPI.UpdateImage(ctx, projectId, region, imageId).UpdateImagePayload(*payload).Execute() + updatedImage, err := r.client.UpdateImage(ctx, projectId, region, imageId).UpdateImagePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating image", fmt.Sprintf("Calling API: %v", err)) return @@ -627,7 +632,7 @@ func (r *imageResource) Delete(ctx context.Context, req resource.DeleteRequest, ctx = core.InitProviderContext(ctx) // Delete existing image - err := r.client.DefaultAPI.DeleteImage(ctx, projectId, region, imageId).Execute() + err := r.client.DeleteImage(ctx, projectId, region, imageId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -640,7 +645,7 @@ func (r *imageResource) Delete(ctx context.Context, req resource.DeleteRequest, ctx = core.LogResponse(ctx) - _, err = wait.DeleteImageWaitHandler(ctx, r.client.DefaultAPI, projectId, region, imageId).WaitWithContext(ctx) + _, err = wait.DeleteImageWaitHandler(ctx, r.client, projectId, region, imageId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting image", fmt.Sprintf("image deletion waiting: %v", err)) return diff --git a/stackit/internal/services/iaas/imagev2/datasource.go b/stackit/internal/services/iaas/imagev2/datasource.go index 1ea0b0d06..8130f02bd 100644 --- a/stackit/internal/services/iaas/imagev2/datasource.go +++ b/stackit/internal/services/iaas/imagev2/datasource.go @@ -11,6 +11,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/path" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features" @@ -109,13 +111,17 @@ var checksumTypes = map[string]attr.Type{ } // NewImageV2DataSource is a helper function to simplify the provider implementation. -func NewImageV2DataSource() datasource.DataSource { - return &imageDataV2Source{} +func NewImageV2DataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &imageDataV2Source{ + clientFactory: clientFactory, + } } // imageDataV2Source is the data source implementation. type imageDataV2Source struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -136,12 +142,11 @@ func (d *imageDataV2Source) Configure(ctx context.Context, req datasource.Config return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient tflog.Info(ctx, "iaas client configured") } @@ -394,7 +399,7 @@ func (d *imageDataV2Source) Read(ctx context.Context, req datasource.ReadRequest // Case 1: Direct lookup by image ID if imageID != "" { - imageResp, err = d.client.DefaultAPI.GetImage(ctx, projectID, region, imageID).Execute() + imageResp, err = d.client.GetImage(ctx, projectID, region, imageID).Execute() if err != nil { utils.LogError(ctx, &resp.Diagnostics, err, "Reading image", fmt.Sprintf("Image with ID %q does not exist in project %q.", imageID, projectID), @@ -420,7 +425,7 @@ func (d *imageDataV2Source) Read(ctx context.Context, req datasource.ReadRequest } // Fetch all available images - imageList, err := d.client.DefaultAPI.ListImages(ctx, projectID, region).Execute() + imageList, err := d.client.ListImages(ctx, projectID, region).Execute() if err != nil { utils.LogError(ctx, &resp.Diagnostics, err, "List images", "Unable to fetch images", nil) return diff --git a/stackit/internal/services/iaas/keypair/datasource.go b/stackit/internal/services/iaas/keypair/datasource.go index 556a9e69b..22f5c5afe 100644 --- a/stackit/internal/services/iaas/keypair/datasource.go +++ b/stackit/internal/services/iaas/keypair/datasource.go @@ -5,7 +5,7 @@ import ( "fmt" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -23,13 +23,17 @@ var ( ) // NewKeyPairDataSource is a helper function to simplify the provider implementation. -func NewKeyPairDataSource() datasource.DataSource { - return &keyPairDataSource{} +func NewKeyPairDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &keyPairDataSource{ + clientFactory: clientFactory, + } } // keyPairDataSource is the data source implementation. type keyPairDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI } // Metadata returns the data source type name. @@ -43,11 +47,11 @@ func (d *keyPairDataSource) Configure(ctx context.Context, req datasource.Config return } - apiClient := iaasUtils.ConfigureClient(ctx, &providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -98,7 +102,7 @@ func (d *keyPairDataSource) Read(ctx context.Context, req datasource.ReadRequest ctx = tflog.SetField(ctx, "name", name) - keypairResp, err := d.client.DefaultAPI.GetKeyPair(ctx, name).Execute() + keypairResp, err := d.client.GetKeyPair(ctx, name).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/keypair/resource.go b/stackit/internal/services/iaas/keypair/resource.go index d943c0863..f27af6baa 100644 --- a/stackit/internal/services/iaas/keypair/resource.go +++ b/stackit/internal/services/iaas/keypair/resource.go @@ -8,6 +8,7 @@ import ( "strings" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -39,13 +40,17 @@ type Model struct { } // NewKeyPairResource is a helper function to simplify the provider implementation. -func NewKeyPairResource() resource.Resource { - return &keyPairResource{} +func NewKeyPairResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &keyPairResource{ + clientFactory: clientFactory, + } } // keyPairResource is the resource implementation. type keyPairResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI } // Metadata returns the resource type name. @@ -60,11 +65,11 @@ func (r *keyPairResource) Configure(ctx context.Context, req resource.ConfigureR return } - apiClient := iaasUtils.ConfigureClient(ctx, &providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -162,7 +167,7 @@ func (r *keyPairResource) Create(ctx context.Context, req resource.CreateRequest // Create new key pair - keyPair, err := r.client.DefaultAPI.CreateKeyPair(ctx).CreateKeyPairPayload(*payload).Execute() + keyPair, err := r.client.CreateKeyPair(ctx).CreateKeyPairPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating key pair", fmt.Sprintf("Calling API: %v", err)) return @@ -199,7 +204,7 @@ func (r *keyPairResource) Read(ctx context.Context, req resource.ReadRequest, re ctx = tflog.SetField(ctx, "name", name) - keyPairResp, err := r.client.DefaultAPI.GetKeyPair(ctx, name).Execute() + keyPairResp, err := r.client.GetKeyPair(ctx, name).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -257,7 +262,7 @@ func (r *keyPairResource) Update(ctx context.Context, req resource.UpdateRequest return } // Update existing key pair - updatedKeyPair, err := r.client.DefaultAPI.UpdateKeyPair(ctx, name).UpdateKeyPairPayload(*payload).Execute() + updatedKeyPair, err := r.client.UpdateKeyPair(ctx, name).UpdateKeyPairPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating key pair", fmt.Sprintf("Calling API: %v", err)) return @@ -295,7 +300,7 @@ func (r *keyPairResource) Delete(ctx context.Context, req resource.DeleteRequest ctx = tflog.SetField(ctx, "name", name) // Delete existing key pair - err := r.client.DefaultAPI.DeleteKeyPair(ctx, name).Execute() + err := r.client.DeleteKeyPair(ctx, name).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/machinetype/datasource.go b/stackit/internal/services/iaas/machinetype/datasource.go index ba0904acf..a94f6fbd2 100644 --- a/stackit/internal/services/iaas/machinetype/datasource.go +++ b/stackit/internal/services/iaas/machinetype/datasource.go @@ -9,6 +9,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" "github.com/hashicorp/terraform-plugin-framework/datasource" @@ -21,7 +23,6 @@ import ( "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" ) @@ -48,7 +49,9 @@ func NewMachineTypeDataSource() datasource.DataSource { } type machineTypeDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -68,11 +71,10 @@ func (d *machineTypeDataSource) Configure(ctx context.Context, req datasource.Co return } - client := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = client tflog.Info(ctx, "IAAS client configured") } @@ -163,7 +165,7 @@ func (d *machineTypeDataSource) Read(ctx context.Context, req datasource.ReadReq ctx = tflog.SetField(ctx, "filter_is_null", model.Filter.IsNull()) ctx = tflog.SetField(ctx, "filter_is_unknown", model.Filter.IsUnknown()) - listMachineTypeReq := d.client.DefaultAPI.ListMachineTypes(ctx, projectId, region) + listMachineTypeReq := d.client.ListMachineTypes(ctx, projectId, region) if !model.Filter.IsNull() && !model.Filter.IsUnknown() && strings.TrimSpace(model.Filter.ValueString()) != "" { listMachineTypeReq = listMachineTypeReq.Filter(strings.TrimSpace(model.Filter.ValueString())) diff --git a/stackit/internal/services/iaas/network/datasource.go b/stackit/internal/services/iaas/network/datasource.go index c130e3484..b4ea46a87 100644 --- a/stackit/internal/services/iaas/network/datasource.go +++ b/stackit/internal/services/iaas/network/datasource.go @@ -7,6 +7,7 @@ import ( "net/http" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" "github.com/hashicorp/terraform-plugin-framework/datasource" @@ -54,13 +55,17 @@ type DataSourceModel struct { } // NewNetworkDataSource is a helper function to simplify the provider implementation. -func NewNetworkDataSource() datasource.DataSource { - return &networkDataSource{} +func NewNetworkDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &networkDataSource{ + clientFactory: clientFactory, + } } // networkDataSource is the data source implementation. type networkDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -76,11 +81,11 @@ func (d *networkDataSource) Configure(ctx context.Context, req datasource.Config return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -238,7 +243,7 @@ func (d *networkDataSource) Read(ctx context.Context, req datasource.ReadRequest ctx = tflog.SetField(ctx, "project_id", projectId) ctx = tflog.SetField(ctx, "network_id", networkId) - networkResp, err := d.client.DefaultAPI.GetNetwork(ctx, projectId, region, networkId).Execute() + networkResp, err := d.client.GetNetwork(ctx, projectId, region, networkId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/network/resource.go b/stackit/internal/services/iaas/network/resource.go index 844bb53a9..15921b0ea 100644 --- a/stackit/internal/services/iaas/network/resource.go +++ b/stackit/internal/services/iaas/network/resource.go @@ -27,6 +27,8 @@ import ( iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api/wait" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" @@ -80,13 +82,17 @@ type Model struct { } // NewNetworkResource is a helper function to simplify the provider implementation. -func NewNetworkResource() resource.Resource { - return &networkResource{} +func NewNetworkResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &networkResource{ + clientFactory: clientFactory, + } } // networkResource is the resource implementation. type networkResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -103,11 +109,11 @@ func (r *networkResource) Configure(ctx context.Context, req resource.ConfigureR return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -480,7 +486,7 @@ func (r *networkResource) Create(ctx context.Context, req resource.CreateRequest // Create new network - network, err := r.client.DefaultAPI.CreateNetwork(ctx, projectId, region).CreateNetworkPayload(*payload).Execute() + network, err := r.client.CreateNetwork(ctx, projectId, region).CreateNetworkPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network", fmt.Sprintf("Calling API: %v", err)) return @@ -499,7 +505,7 @@ func (r *networkResource) Create(ctx context.Context, req resource.CreateRequest return } - network, err = wait.CreateNetworkWaitHandler(ctx, r.client.DefaultAPI, projectId, region, networkId).WaitWithContext(ctx) + network, err = wait.CreateNetworkWaitHandler(ctx, r.client, projectId, region, networkId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network", fmt.Sprintf("Network creation waiting: %v", err)) return @@ -543,7 +549,7 @@ func (r *networkResource) Read(ctx context.Context, req resource.ReadRequest, re ctx = tflog.SetField(ctx, "network_id", networkId) ctx = tflog.SetField(ctx, "region", region) - networkResp, err := r.client.DefaultAPI.GetNetwork(ctx, projectId, region, networkId).Execute() + networkResp, err := r.client.GetNetwork(ctx, projectId, region, networkId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -606,13 +612,13 @@ func (r *networkResource) Update(ctx context.Context, req resource.UpdateRequest } // Update existing network - err = r.client.DefaultAPI.PartialUpdateNetwork(ctx, projectId, region, networkId).PartialUpdateNetworkPayload(*payload).Execute() + err = r.client.PartialUpdateNetwork(ctx, projectId, region, networkId).PartialUpdateNetworkPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network", fmt.Sprintf("Calling API: %v", err)) return } - waitResp, err := wait.UpdateNetworkWaitHandler(ctx, r.client.DefaultAPI, projectId, region, networkId).WaitWithContext(ctx) + waitResp, err := wait.UpdateNetworkWaitHandler(ctx, r.client, projectId, region, networkId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network", fmt.Sprintf("Network update waiting: %v", err)) return @@ -653,7 +659,7 @@ func (r *networkResource) Delete(ctx context.Context, req resource.DeleteRequest ctx = core.InitProviderContext(ctx) // Delete existing network - err := r.client.DefaultAPI.DeleteNetwork(ctx, projectId, region, networkId).Execute() + err := r.client.DeleteNetwork(ctx, projectId, region, networkId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -666,7 +672,7 @@ func (r *networkResource) Delete(ctx context.Context, req resource.DeleteRequest ctx = core.LogResponse(ctx) - _, err = wait.DeleteNetworkWaitHandler(ctx, r.client.DefaultAPI, projectId, region, networkId).WaitWithContext(ctx) + _, err = wait.DeleteNetworkWaitHandler(ctx, r.client, projectId, region, networkId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting network", fmt.Sprintf("Network deletion waiting: %v", err)) return diff --git a/stackit/internal/services/iaas/networkarea/datasource.go b/stackit/internal/services/iaas/networkarea/datasource.go index 72b9001ff..b6a103426 100644 --- a/stackit/internal/services/iaas/networkarea/datasource.go +++ b/stackit/internal/services/iaas/networkarea/datasource.go @@ -8,12 +8,11 @@ import ( "github.com/stackitcloud/stackit-sdk-go/core/oapierror" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" - "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" - "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -24,6 +23,8 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" ) @@ -33,13 +34,17 @@ var ( ) // NewNetworkDataSource is a helper function to simplify the provider implementation. -func NewNetworkAreaDataSource() datasource.DataSource { - return &networkAreaDataSource{} +func NewNetworkAreaDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &networkAreaDataSource{ + clientFactory: clientFactory, + } } // networkDataSource is the data source implementation. type networkAreaDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI } // Metadata returns the data source type name. @@ -53,11 +58,11 @@ func (d *networkAreaDataSource) Configure(ctx context.Context, req datasource.Co return } - apiClient := iaasUtils.ConfigureClient(ctx, &providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -191,7 +196,7 @@ func (d *networkAreaDataSource) Read(ctx context.Context, req datasource.ReadReq ctx = tflog.SetField(ctx, "organization_id", organizationId) ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) - networkAreaResp, err := d.client.DefaultAPI.GetNetworkArea(ctx, organizationId, networkAreaId).Execute() + networkAreaResp, err := d.client.GetNetworkArea(ctx, organizationId, networkAreaId).Execute() if err != nil { utils.LogError( ctx, @@ -216,7 +221,7 @@ func (d *networkAreaDataSource) Read(ctx context.Context, req datasource.ReadReq } // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionResp, err := d.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() + networkAreaRegionResp, err := d.client.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError ok := errors.As(err, &oapiErr) diff --git a/stackit/internal/services/iaas/networkarea/resource.go b/stackit/internal/services/iaas/networkarea/resource.go index c0344dc3e..22d517fd2 100644 --- a/stackit/internal/services/iaas/networkarea/resource.go +++ b/stackit/internal/services/iaas/networkarea/resource.go @@ -9,6 +9,8 @@ import ( resourcemanager "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager/v0api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" resourcemanagerUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/resourcemanager/utils" @@ -106,13 +108,17 @@ var networkRangeTypes = map[string]attr.Type{ } // NewNetworkAreaResource is a helper function to simplify the provider implementation. -func NewNetworkAreaResource() resource.Resource { - return &networkAreaResource{} +func NewNetworkAreaResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &networkAreaResource{ + clientFactory: clientFactory, + } } // networkResource is the resource implementation. type networkAreaResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI resourceManagerClient *resourcemanager.APIClient } @@ -160,7 +166,7 @@ func (r *networkAreaResource) Configure(ctx context.Context, req resource.Config return } - r.client = iaasUtils.ConfigureClient(ctx, &providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } @@ -351,7 +357,7 @@ func (r *networkAreaResource) Create(ctx context.Context, req resource.CreateReq } // Create new network area - networkArea, err := r.client.DefaultAPI.CreateNetworkArea(ctx, organizationId).CreateNetworkAreaPayload(*payload).Execute() + networkArea, err := r.client.CreateNetworkArea(ctx, organizationId).CreateNetworkAreaPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network area", fmt.Sprintf("Calling API: %v", err)) return @@ -391,7 +397,7 @@ func (r *networkAreaResource) Create(ctx context.Context, req resource.CreateReq } // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionCreateResp, err := r.client.DefaultAPI.CreateNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").CreateNetworkAreaRegionPayload(*regionCreatePayload).Execute() + networkAreaRegionCreateResp, err := r.client.CreateNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").CreateNetworkAreaRegionPayload(*regionCreatePayload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network area region", fmt.Sprintf("Calling API: %v", err)) return @@ -405,7 +411,7 @@ func (r *networkAreaResource) Create(ctx context.Context, req resource.CreateReq } // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionResp, err := wait.CreateNetworkAreaRegionWaitHandler(ctx, r.client.DefaultAPI, organizationId, networkAreaId, "eu01").WaitWithContext(ctx) + networkAreaRegionResp, err := wait.CreateNetworkAreaRegionWaitHandler(ctx, r.client, organizationId, networkAreaId, "eu01").WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error waiting for network area region creation", fmt.Sprintf("Calling API: %v", err)) return @@ -456,7 +462,7 @@ func (r *networkAreaResource) Read(ctx context.Context, req resource.ReadRequest ctx = tflog.SetField(ctx, "organization_id", organizationId) ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) - networkAreaResp, err := r.client.DefaultAPI.GetNetworkArea(ctx, organizationId, networkAreaId).Execute() + networkAreaResp, err := r.client.GetNetworkArea(ctx, organizationId, networkAreaId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -481,7 +487,7 @@ func (r *networkAreaResource) Read(ctx context.Context, req resource.ReadRequest core.LogAndAddWarning(ctx, &resp.Diagnostics, deprecationWarningSummary, deprecationWarningDetails) // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionResp, err := r.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() + networkAreaRegionResp, err := r.client.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if !(errors.As(err, &oapiErr) && (oapiErr.StatusCode == http.StatusNotFound || oapiErr.StatusCode == http.StatusBadRequest)) { // TODO: iaas api returns http 400 in case network area region is not found @@ -560,7 +566,7 @@ func (r *networkAreaResource) Update(ctx context.Context, req resource.UpdateReq return } // Update existing network - networkAreaUpdateResp, err := r.client.DefaultAPI.PartialUpdateNetworkArea(ctx, organizationId, networkAreaId).PartialUpdateNetworkAreaPayload(*payload).Execute() + networkAreaUpdateResp, err := r.client.PartialUpdateNetworkArea(ctx, organizationId, networkAreaId).PartialUpdateNetworkAreaPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area", fmt.Sprintf("Calling API: %v", err)) return @@ -586,7 +592,7 @@ func (r *networkAreaResource) Update(ctx context.Context, req resource.UpdateReq } // Deprecated: Update network area region. Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionUpdateResp, err := r.client.DefaultAPI.UpdateNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").UpdateNetworkAreaRegionPayload(*regionUpdatePayload).Execute() + networkAreaRegionUpdateResp, err := r.client.UpdateNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").UpdateNetworkAreaRegionPayload(*regionUpdatePayload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Calling API: %v", err)) return @@ -600,14 +606,14 @@ func (r *networkAreaResource) Update(ctx context.Context, req resource.UpdateReq } // Deprecated: Update network ranges. Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - err = updateNetworkRanges(ctx, organizationId, networkAreaId, ranges, r.client.DefaultAPI) + err = updateNetworkRanges(ctx, organizationId, networkAreaId, ranges, r.client) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Updating Network ranges: %v", err)) return } // Deprecated: Will be removed in May 2026. Only introduced to make the IaaS v1 -> v2 API migration non-breaking in the Terraform provider. - networkAreaRegionResp, err := r.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() + networkAreaRegionResp, err := r.client.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, "eu01").Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && (oapiErr.StatusCode == http.StatusNotFound || oapiErr.StatusCode == http.StatusBadRequest) { // TODO: iaas api returns http 400 in case network area region is not found @@ -658,7 +664,7 @@ func (r *networkAreaResource) Delete(ctx context.Context, req resource.DeleteReq ctx = tflog.SetField(ctx, "organization_id", organizationId) ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) - _, err := wait.ReadyForNetworkAreaDeletionWaitHandler(ctx, r.client.DefaultAPI, r.resourceManagerClient.DefaultAPI, organizationId, networkAreaId).WaitWithContext(ctx) + _, err := wait.ReadyForNetworkAreaDeletionWaitHandler(ctx, r.client, r.resourceManagerClient.DefaultAPI, organizationId, networkAreaId).WaitWithContext(ctx) if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -670,7 +676,7 @@ func (r *networkAreaResource) Delete(ctx context.Context, req resource.DeleteReq } // Get all configured regions so we can delete them one by one before deleting the network area - regionsListResp, err := r.client.DefaultAPI.ListNetworkAreaRegions(ctx, organizationId, networkAreaId).Execute() + regionsListResp, err := r.client.ListNetworkAreaRegions(ctx, organizationId, networkAreaId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -683,7 +689,7 @@ func (r *networkAreaResource) Delete(ctx context.Context, req resource.DeleteReq // Delete network region configurations for region := range regionsListResp.Regions { - err = r.client.DefaultAPI.DeleteNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() + err = r.client.DeleteNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && (oapiErr.StatusCode == http.StatusNotFound || oapiErr.StatusCode == http.StatusBadRequest) { // TODO: iaas api returns http 400 in case network area region is not found @@ -693,7 +699,7 @@ func (r *networkAreaResource) Delete(ctx context.Context, req resource.DeleteReq return } - _, err = wait.DeleteNetworkAreaRegionWaitHandler(ctx, r.client.DefaultAPI, organizationId, networkAreaId, region).WaitWithContext(ctx) + _, err = wait.DeleteNetworkAreaRegionWaitHandler(ctx, r.client, organizationId, networkAreaId, region).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting network area region", fmt.Sprintf("Waiting for networea deletion: %v", err)) return @@ -701,7 +707,7 @@ func (r *networkAreaResource) Delete(ctx context.Context, req resource.DeleteReq } // Delete existing network area - err = r.client.DefaultAPI.DeleteNetworkArea(ctx, organizationId, networkAreaId).Execute() + err = r.client.DeleteNetworkArea(ctx, organizationId, networkAreaId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/networkarearegion/datasource.go b/stackit/internal/services/iaas/networkarearegion/datasource.go index 8dea6f51f..db7ce7424 100644 --- a/stackit/internal/services/iaas/networkarearegion/datasource.go +++ b/stackit/internal/services/iaas/networkarearegion/datasource.go @@ -7,10 +7,9 @@ import ( "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework/schema/validator" - "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" - "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -18,6 +17,8 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" ) @@ -28,13 +29,17 @@ var ( ) // NewNetworkAreaRegionDataSource is a helper function to simplify the provider implementation. -func NewNetworkAreaRegionDataSource() datasource.DataSource { - return &networkAreaRegionDataSource{} +func NewNetworkAreaRegionDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &networkAreaRegionDataSource{ + clientFactory: clientFactory, + } } // networkAreaRegionDataSource is the data source implementation. type networkAreaRegionDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -50,11 +55,11 @@ func (d *networkAreaRegionDataSource) Configure(ctx context.Context, req datasou return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -163,7 +168,7 @@ func (d *networkAreaRegionDataSource) Read(ctx context.Context, req datasource.R ctx = core.InitProviderContext(ctx) - networkAreaRegionResp, err := d.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() + networkAreaRegionResp, err := d.client.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() if err != nil { utils.LogError(ctx, &resp.Diagnostics, err, "Reading network area region", fmt.Sprintf("Region configuration for %q for network area %q does not exist.", region, networkAreaId), nil) resp.State.RemoveResource(ctx) diff --git a/stackit/internal/services/iaas/networkarearegion/resource.go b/stackit/internal/services/iaas/networkarearegion/resource.go index 8856175c0..ce06780bd 100644 --- a/stackit/internal/services/iaas/networkarearegion/resource.go +++ b/stackit/internal/services/iaas/networkarearegion/resource.go @@ -9,6 +9,8 @@ import ( resourcemanager "github.com/stackitcloud/stackit-sdk-go/services/resourcemanager/v0api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + resourcemanagerUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/resourcemanager/utils" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" @@ -20,8 +22,6 @@ import ( "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" - "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" @@ -68,13 +68,17 @@ type networkRangeModel struct { } // NewNetworkAreaRegionResource is a helper function to simplify the provider implementation. -func NewNetworkAreaRegionResource() resource.Resource { - return &networkAreaRegionResource{} +func NewNetworkAreaRegionResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &networkAreaRegionResource{ + clientFactory: clientFactory, + } } // networkAreaRegionResource is the resource implementation. type networkAreaRegionResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI resourceManagerClient *resourcemanager.APIClient providerData core.ProviderData } @@ -122,7 +126,7 @@ func (r *networkAreaRegionResource) Configure(ctx context.Context, req resource. return } - r.client = iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } @@ -282,7 +286,7 @@ func (r *networkAreaRegionResource) Create(ctx context.Context, req resource.Cre } // Create new network area region configuration - networkAreaRegion, err := r.client.DefaultAPI.CreateNetworkAreaRegion(ctx, organizationId, networkAreaId, region).CreateNetworkAreaRegionPayload(*payload).Execute() + networkAreaRegion, err := r.client.CreateNetworkAreaRegion(ctx, organizationId, networkAreaId, region).CreateNetworkAreaRegionPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network area region", fmt.Sprintf("Calling API: %v", err)) return @@ -298,7 +302,7 @@ func (r *networkAreaRegionResource) Create(ctx context.Context, req resource.Cre }) // wait for creation of network area region to complete - _, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, r.client.DefaultAPI, organizationId, networkAreaId, region).WaitWithContext(ctx) + _, err = wait.CreateNetworkAreaRegionWaitHandler(ctx, r.client, organizationId, networkAreaId, region).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating server", fmt.Sprintf("server creation waiting: %v", err)) return @@ -341,7 +345,7 @@ func (r *networkAreaRegionResource) Read(ctx context.Context, req resource.ReadR ctx = core.InitProviderContext(ctx) - networkAreaRegionResp, err := r.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() + networkAreaRegionResp, err := r.client.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -402,7 +406,7 @@ func (r *networkAreaRegionResource) Update(ctx context.Context, req resource.Upd } // Update existing network area region configuration - _, err = r.client.DefaultAPI.UpdateNetworkAreaRegion(ctx, organizationId, networkAreaId, region).UpdateNetworkAreaRegionPayload(*payload).Execute() + _, err = r.client.UpdateNetworkAreaRegion(ctx, organizationId, networkAreaId, region).UpdateNetworkAreaRegionPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Calling API: %v", err)) return @@ -410,13 +414,13 @@ func (r *networkAreaRegionResource) Update(ctx context.Context, req resource.Upd ctx = core.LogResponse(ctx) - err = updateIpv4NetworkRanges(ctx, organizationId, networkAreaId, model.Ipv4.NetworkRanges, r.client.DefaultAPI, region) + err = updateIpv4NetworkRanges(ctx, organizationId, networkAreaId, model.Ipv4.NetworkRanges, r.client, region) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Updating Network ranges: %v", err)) return } - updatedNetworkAreaRegion, err := r.client.DefaultAPI.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() + updatedNetworkAreaRegion, err := r.client.GetNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area region", fmt.Sprintf("Calling API: %v", err)) return @@ -453,14 +457,14 @@ func (r *networkAreaRegionResource) Delete(ctx context.Context, req resource.Del ctx = core.InitProviderContext(ctx) - _, err := wait.ReadyForNetworkAreaDeletionWaitHandler(ctx, r.client.DefaultAPI, r.resourceManagerClient.DefaultAPI, organizationId, networkAreaId).WaitWithContext(ctx) + _, err := wait.ReadyForNetworkAreaDeletionWaitHandler(ctx, r.client, r.resourceManagerClient.DefaultAPI, organizationId, networkAreaId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting network area region", fmt.Sprintf("Network area ready for deletion waiting: %v", err)) return } // Delete network area region configuration - err = r.client.DefaultAPI.DeleteNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() + err = r.client.DeleteNetworkAreaRegion(ctx, organizationId, networkAreaId, region).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -472,7 +476,7 @@ func (r *networkAreaRegionResource) Delete(ctx context.Context, req resource.Del ctx = core.LogResponse(ctx) - _, err = wait.DeleteNetworkAreaRegionWaitHandler(ctx, r.client.DefaultAPI, organizationId, networkAreaId, region).WaitWithContext(ctx) + _, err = wait.DeleteNetworkAreaRegionWaitHandler(ctx, r.client, organizationId, networkAreaId, region).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting network area region", fmt.Sprintf("network area deletion waiting: %v", err)) return diff --git a/stackit/internal/services/iaas/networkarearoute/datasource.go b/stackit/internal/services/iaas/networkarearoute/datasource.go index 4fa92165b..4c9dbbded 100644 --- a/stackit/internal/services/iaas/networkarearoute/datasource.go +++ b/stackit/internal/services/iaas/networkarearoute/datasource.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -26,13 +26,17 @@ var ( ) // NewNetworkAreaRouteDataSource is a helper function to simplify the provider implementation. -func NewNetworkAreaRouteDataSource() datasource.DataSource { - return &networkAreaRouteDataSource{} +func NewNetworkAreaRouteDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &networkAreaRouteDataSource{ + clientFactory: clientFactory, + } } // networkDataSource is the data source implementation. type networkAreaRouteDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -48,11 +52,11 @@ func (d *networkAreaRouteDataSource) Configure(ctx context.Context, req datasour return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -155,7 +159,7 @@ func (d *networkAreaRouteDataSource) Read(ctx context.Context, req datasource.Re ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "network_area_route_id", networkAreaRouteId) - networkAreaRouteResp, err := d.client.DefaultAPI.GetNetworkAreaRoute(ctx, organizationId, networkAreaId, region, networkAreaRouteId).Execute() + networkAreaRouteResp, err := d.client.GetNetworkAreaRoute(ctx, organizationId, networkAreaId, region, networkAreaRouteId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/networkarearoute/resource.go b/stackit/internal/services/iaas/networkarearoute/resource.go index b3789d378..0e88f77e7 100644 --- a/stackit/internal/services/iaas/networkarearoute/resource.go +++ b/stackit/internal/services/iaas/networkarearoute/resource.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" @@ -71,13 +72,17 @@ type NexthopModelV1 struct { } // NewNetworkAreaRouteResource is a helper function to simplify the provider implementation. -func NewNetworkAreaRouteResource() resource.Resource { - return &networkAreaRouteResource{} +func NewNetworkAreaRouteResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &networkAreaRouteResource{ + clientFactory: clientFactory, + } } // networkResource is the resource implementation. type networkAreaRouteResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -124,11 +129,11 @@ func (r *networkAreaRouteResource) Configure(ctx context.Context, req resource.C return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -355,7 +360,7 @@ func (r *networkAreaRouteResource) Create(ctx context.Context, req resource.Crea } // Create new network area route - routes, err := r.client.DefaultAPI.CreateNetworkAreaRoute(ctx, organizationId, networkAreaId, region).CreateNetworkAreaRoutePayload(*payload).Execute() + routes, err := r.client.CreateNetworkAreaRoute(ctx, organizationId, networkAreaId, region).CreateNetworkAreaRoutePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network area route", fmt.Sprintf("Calling API: %v", err)) return @@ -420,7 +425,7 @@ func (r *networkAreaRouteResource) Read(ctx context.Context, req resource.ReadRe ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "network_area_route_id", networkAreaRouteId) - networkAreaRouteResp, err := r.client.DefaultAPI.GetNetworkAreaRoute(ctx, organizationId, networkAreaId, region, networkAreaRouteId).Execute() + networkAreaRouteResp, err := r.client.GetNetworkAreaRoute(ctx, organizationId, networkAreaId, region, networkAreaRouteId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -471,7 +476,7 @@ func (r *networkAreaRouteResource) Delete(ctx context.Context, req resource.Dele ctx = tflog.SetField(ctx, "network_area_route_id", networkAreaRouteId) // Delete existing network - err := r.client.DefaultAPI.DeleteNetworkAreaRoute(ctx, organizationId, networkAreaId, region, networkAreaRouteId).Execute() + err := r.client.DeleteNetworkAreaRoute(ctx, organizationId, networkAreaId, region, networkAreaRouteId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -523,7 +528,7 @@ func (r *networkAreaRouteResource) Update(ctx context.Context, req resource.Upda return } // Update existing network area route - networkAreaRouteResp, err := r.client.DefaultAPI.UpdateNetworkAreaRoute(ctx, organizationId, networkAreaId, region, networkAreaRouteId).UpdateNetworkAreaRoutePayload(*payload).Execute() + networkAreaRouteResp, err := r.client.UpdateNetworkAreaRoute(ctx, organizationId, networkAreaId, region, networkAreaRouteId).UpdateNetworkAreaRoutePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network area route", fmt.Sprintf("Calling API: %v", err)) return diff --git a/stackit/internal/services/iaas/networkinterface/datasource.go b/stackit/internal/services/iaas/networkinterface/datasource.go index b3a44e019..4c0479d89 100644 --- a/stackit/internal/services/iaas/networkinterface/datasource.go +++ b/stackit/internal/services/iaas/networkinterface/datasource.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -26,13 +26,17 @@ var ( ) // NewNetworkInterfaceDataSource is a helper function to simplify the provider implementation. -func NewNetworkInterfaceDataSource() datasource.DataSource { - return &networkInterfaceDataSource{} +func NewNetworkInterfaceDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &networkInterfaceDataSource{ + clientFactory: clientFactory, + } } // networkInterfaceDataSource is the data source implementation. type networkInterfaceDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -48,11 +52,11 @@ func (d *networkInterfaceDataSource) Configure(ctx context.Context, req datasour return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -162,7 +166,7 @@ func (d *networkInterfaceDataSource) Read(ctx context.Context, req datasource.Re ctx = tflog.SetField(ctx, "network_id", networkId) ctx = tflog.SetField(ctx, "network_interface_id", networkInterfaceId) - networkInterfaceResp, err := d.client.DefaultAPI.GetNic(ctx, projectId, region, networkId, networkInterfaceId).Execute() + networkInterfaceResp, err := d.client.GetNic(ctx, projectId, region, networkId, networkInterfaceId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/networkinterface/resource.go b/stackit/internal/services/iaas/networkinterface/resource.go index 5fce1bc74..70135a49f 100644 --- a/stackit/internal/services/iaas/networkinterface/resource.go +++ b/stackit/internal/services/iaas/networkinterface/resource.go @@ -9,6 +9,7 @@ import ( "strings" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -56,13 +57,17 @@ type Model struct { } // NewNetworkInterfaceResource is a helper function to simplify the provider implementation. -func NewNetworkInterfaceResource() resource.Resource { - return &networkInterfaceResource{} +func NewNetworkInterfaceResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &networkInterfaceResource{ + clientFactory: clientFactory, + } } // networkResource is the resource implementation. type networkInterfaceResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -122,11 +127,11 @@ func (r *networkInterfaceResource) Configure(ctx context.Context, req resource.C return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -299,7 +304,7 @@ func (r *networkInterfaceResource) Create(ctx context.Context, req resource.Crea } // Create new network interface - networkInterface, err := r.client.DefaultAPI.CreateNic(ctx, projectId, region, networkId).CreateNicPayload(*payload).Execute() + networkInterface, err := r.client.CreateNic(ctx, projectId, region, networkId).CreateNicPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating network interface", fmt.Sprintf("Calling API: %v", err)) return @@ -351,7 +356,7 @@ func (r *networkInterfaceResource) Read(ctx context.Context, req resource.ReadRe ctx = tflog.SetField(ctx, "network_id", networkId) ctx = tflog.SetField(ctx, "network_interface_id", networkInterfaceId) - networkInterfaceResp, err := r.client.DefaultAPI.GetNic(ctx, projectId, region, networkId, networkInterfaceId).Execute() + networkInterfaceResp, err := r.client.GetNic(ctx, projectId, region, networkId, networkInterfaceId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -415,7 +420,7 @@ func (r *networkInterfaceResource) Update(ctx context.Context, req resource.Upda return } // Update existing network - nicResp, err := r.client.DefaultAPI.UpdateNic(ctx, projectId, region, networkId, networkInterfaceId).UpdateNicPayload(*payload).Execute() + nicResp, err := r.client.UpdateNic(ctx, projectId, region, networkId, networkInterfaceId).UpdateNicPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating network interface", fmt.Sprintf("Calling API: %v", err)) return @@ -459,7 +464,7 @@ func (r *networkInterfaceResource) Delete(ctx context.Context, req resource.Dele ctx = tflog.SetField(ctx, "network_interface_id", networkInterfaceId) // Delete existing network interface - err := r.client.DefaultAPI.DeleteNic(ctx, projectId, region, networkId, networkInterfaceId).Execute() + err := r.client.DeleteNic(ctx, projectId, region, networkId, networkInterfaceId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/networkinterfaceattach/resource.go b/stackit/internal/services/iaas/networkinterfaceattach/resource.go index 4275fd159..b0fada766 100644 --- a/stackit/internal/services/iaas/networkinterfaceattach/resource.go +++ b/stackit/internal/services/iaas/networkinterfaceattach/resource.go @@ -8,9 +8,7 @@ import ( "strings" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" - - "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -22,6 +20,8 @@ import ( "github.com/stackitcloud/stackit-sdk-go/core/oapierror" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" ) @@ -43,13 +43,17 @@ type Model struct { } // NewNetworkInterfaceAttachResource is a helper function to simplify the provider implementation. -func NewNetworkInterfaceAttachResource() resource.Resource { - return &networkInterfaceAttachResource{} +func NewNetworkInterfaceAttachResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &networkInterfaceAttachResource{ + clientFactory: clientFactory, + } } // networkInterfaceAttachResource is the resource implementation. type networkInterfaceAttachResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -96,11 +100,11 @@ func (r *networkInterfaceAttachResource) Configure(ctx context.Context, req reso return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -186,7 +190,7 @@ func (r *networkInterfaceAttachResource) Create(ctx context.Context, req resourc ctx = tflog.SetField(ctx, "network_interface_id", networkInterfaceId) // Create new network interface attachment - err := r.client.DefaultAPI.AddNicToServer(ctx, projectId, region, serverId, networkInterfaceId).Execute() + err := r.client.AddNicToServer(ctx, projectId, region, serverId, networkInterfaceId).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error attaching network interface to server", fmt.Sprintf("Calling API: %v", err)) return @@ -225,7 +229,7 @@ func (r *networkInterfaceAttachResource) Read(ctx context.Context, req resource. ctx = tflog.SetField(ctx, "server_id", serverId) ctx = tflog.SetField(ctx, "network_interface_id", networkInterfaceId) - nics, err := r.client.DefaultAPI.ListServerNICs(ctx, projectId, region, serverId).Execute() + nics, err := r.client.ListServerNICs(ctx, projectId, region, serverId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -293,7 +297,7 @@ func (r *networkInterfaceAttachResource) Delete(ctx context.Context, req resourc ctx = tflog.SetField(ctx, "network_interface_id", network_interfaceId) // Remove network_interface from server - err := r.client.DefaultAPI.RemoveNicFromServer(ctx, projectId, region, serverId, network_interfaceId).Execute() + err := r.client.RemoveNicFromServer(ctx, projectId, region, serverId, network_interfaceId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/publicip/datasource.go b/stackit/internal/services/iaas/publicip/datasource.go index 2acf98f05..1ca629ed8 100644 --- a/stackit/internal/services/iaas/publicip/datasource.go +++ b/stackit/internal/services/iaas/publicip/datasource.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -26,13 +26,17 @@ var ( ) // NewPublicIpDataSource is a helper function to simplify the provider implementation. -func NewPublicIpDataSource() datasource.DataSource { - return &publicIpDataSource{} +func NewPublicIpDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &publicIpDataSource{ + clientFactory: clientFactory, + } } // publicIpDataSource is the data source implementation. type publicIpDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -48,11 +52,11 @@ func (d *publicIpDataSource) Configure(ctx context.Context, req datasource.Confi return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -127,7 +131,7 @@ func (d *publicIpDataSource) Read(ctx context.Context, req datasource.ReadReques ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "public_ip_id", publicIpId) - publicIpResp, err := d.client.DefaultAPI.GetPublicIP(ctx, projectId, region, publicIpId).Execute() + publicIpResp, err := d.client.GetPublicIP(ctx, projectId, region, publicIpId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/publicip/resource.go b/stackit/internal/services/iaas/publicip/resource.go index 507a182f8..b7470859a 100644 --- a/stackit/internal/services/iaas/publicip/resource.go +++ b/stackit/internal/services/iaas/publicip/resource.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" @@ -45,13 +46,17 @@ type Model struct { } // NewPublicIpResource is a helper function to simplify the provider implementation. -func NewPublicIpResource() resource.Resource { - return &publicIpResource{} +func NewPublicIpResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &publicIpResource{ + clientFactory: clientFactory, + } } // publicIpResource is the resource implementation. type publicIpResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -98,11 +103,11 @@ func (r *publicIpResource) Configure(ctx context.Context, req resource.Configure return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -205,7 +210,7 @@ func (r *publicIpResource) Create(ctx context.Context, req resource.CreateReques // Create new public IP - publicIp, err := r.client.DefaultAPI.CreatePublicIP(ctx, projectId, region).CreatePublicIPPayload(*payload).Execute() + publicIp, err := r.client.CreatePublicIP(ctx, projectId, region).CreatePublicIPPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating public IP", fmt.Sprintf("Calling API: %v", err)) return @@ -253,7 +258,7 @@ func (r *publicIpResource) Read(ctx context.Context, req resource.ReadRequest, r ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "public_ip_id", publicIpId) - publicIpResp, err := r.client.DefaultAPI.GetPublicIP(ctx, projectId, region, publicIpId).Execute() + publicIpResp, err := r.client.GetPublicIP(ctx, projectId, region, publicIpId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -315,7 +320,7 @@ func (r *publicIpResource) Update(ctx context.Context, req resource.UpdateReques return } // Update existing public IP - updatedPublicIp, err := r.client.DefaultAPI.UpdatePublicIP(ctx, projectId, region, publicIpId).UpdatePublicIPPayload(*payload).Execute() + updatedPublicIp, err := r.client.UpdatePublicIP(ctx, projectId, region, publicIpId).UpdatePublicIPPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating public IP", fmt.Sprintf("Calling API: %v", err)) return @@ -357,7 +362,7 @@ func (r *publicIpResource) Delete(ctx context.Context, req resource.DeleteReques ctx = tflog.SetField(ctx, "public_ip_id", publicIpId) // Delete existing publicIp - err := r.client.DefaultAPI.DeletePublicIP(ctx, projectId, region, publicIpId).Execute() + err := r.client.DeletePublicIP(ctx, projectId, region, publicIpId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/publicipassociate/resource.go b/stackit/internal/services/iaas/publicipassociate/resource.go index 216f11647..bef4db4e2 100644 --- a/stackit/internal/services/iaas/publicipassociate/resource.go +++ b/stackit/internal/services/iaas/publicipassociate/resource.go @@ -8,8 +8,7 @@ import ( "strings" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" - - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -44,13 +43,17 @@ type Model struct { } // NewPublicIpAssociateResource is a helper function to simplify the provider implementation. -func NewPublicIpAssociateResource() resource.Resource { - return &publicIpAssociateResource{} +func NewPublicIpAssociateResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &publicIpAssociateResource{ + clientFactory: clientFactory, + } } // publicIpAssociateResource is the resource implementation. type publicIpAssociateResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -97,7 +100,7 @@ func (r *publicIpAssociateResource) Configure(ctx context.Context, req resource. return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } @@ -105,7 +108,6 @@ func (r *publicIpAssociateResource) Configure(ctx context.Context, req resource. core.LogAndAddWarning(ctx, &resp.Diagnostics, "The `stackit_public_ip_associate` resource should not be used together with the `stackit_public_ip` resource for the same public IP or for the same network interface.", "Using both resources together for the same public IP or network interface WILL lead to conflicts, as they both have control of the public IP and network interface association.") - r.client = apiClient tflog.Info(ctx, "iaas client configured") } @@ -213,7 +215,7 @@ func (r *publicIpAssociateResource) Create(ctx context.Context, req resource.Cre return } // Update existing public IP - updatedPublicIp, err := r.client.DefaultAPI.UpdatePublicIP(ctx, projectId, region, publicIpId).UpdatePublicIPPayload(*payload).Execute() + updatedPublicIp, err := r.client.UpdatePublicIP(ctx, projectId, region, publicIpId).UpdatePublicIPPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error associating public IP to network interface", fmt.Sprintf("Calling API: %v", err)) return @@ -254,7 +256,7 @@ func (r *publicIpAssociateResource) Read(ctx context.Context, req resource.ReadR ctx = tflog.SetField(ctx, "public_ip_id", publicIpId) ctx = tflog.SetField(ctx, "network_interface_id", networkInterfaceId) - publicIpResp, err := r.client.DefaultAPI.GetPublicIP(ctx, projectId, region, publicIpId).Execute() + publicIpResp, err := r.client.GetPublicIP(ctx, projectId, region, publicIpId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -313,7 +315,7 @@ func (r *publicIpAssociateResource) Delete(ctx context.Context, req resource.Del NetworkInterface: *iaas.NewNullableString(nil), } - _, err := r.client.DefaultAPI.UpdatePublicIP(ctx, projectId, region, publicIpId).UpdatePublicIPPayload(*payload).Execute() + _, err := r.client.UpdatePublicIP(ctx, projectId, region, publicIpId).UpdatePublicIPPayload(*payload).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/publicipranges/datasource.go b/stackit/internal/services/iaas/publicipranges/datasource.go index 826f89ff9..f505e159c 100644 --- a/stackit/internal/services/iaas/publicipranges/datasource.go +++ b/stackit/internal/services/iaas/publicipranges/datasource.go @@ -7,7 +7,7 @@ import ( "sort" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" @@ -30,13 +30,17 @@ var ( ) // NewPublicIpRangesDataSource is a helper function to simplify the provider implementation. -func NewPublicIpRangesDataSource() datasource.DataSource { - return &publicIpRangesDataSource{} +func NewPublicIpRangesDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &publicIpRangesDataSource{ + clientFactory: clientFactory, + } } // publicIpRangesDataSource is the data source implementation. type publicIpRangesDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI } type Model struct { @@ -60,11 +64,11 @@ func (d *publicIpRangesDataSource) Configure(ctx context.Context, req datasource return } - apiClient := iaasUtils.ConfigureClient(ctx, &providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -119,7 +123,7 @@ func (d *publicIpRangesDataSource) Read(ctx context.Context, req datasource.Read ctx = core.InitProviderContext(ctx) - publicIpRangeResp, err := d.client.DefaultAPI.ListPublicIPRanges(ctx).Execute() + publicIpRangeResp, err := d.client.ListPublicIPRanges(ctx).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/routingtable/route/datasource.go b/stackit/internal/services/iaas/routingtable/route/datasource.go index 9c68b670d..5f8fdd2b2 100644 --- a/stackit/internal/services/iaas/routingtable/route/datasource.go +++ b/stackit/internal/services/iaas/routingtable/route/datasource.go @@ -10,11 +10,12 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features" shared "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/routingtable/shared" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" ) @@ -24,13 +25,17 @@ var ( ) // NewRoutingTableRouteDataSource is a helper function to simplify the provider implementation. -func NewRoutingTableRouteDataSource() datasource.DataSource { - return &routingTableRouteDataSource{} +func NewRoutingTableRouteDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &routingTableRouteDataSource{ + clientFactory: clientFactory, + } } // routingTableRouteDataSource is the data source implementation. type routingTableRouteDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -51,11 +56,11 @@ func (d *routingTableRouteDataSource) Configure(ctx context.Context, req datasou return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -92,7 +97,7 @@ func (d *routingTableRouteDataSource) Read(ctx context.Context, req datasource.R ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) ctx = tflog.SetField(ctx, "route_id", routeId) - routeResp, err := d.client.DefaultAPI.GetRouteOfRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId, routeId).Execute() + routeResp, err := d.client.GetRouteOfRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId, routeId).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, err.Error(), err.Error()) utils.LogError( diff --git a/stackit/internal/services/iaas/routingtable/route/resource.go b/stackit/internal/services/iaas/routingtable/route/resource.go index 66a60d77d..e9af699ef 100644 --- a/stackit/internal/services/iaas/routingtable/route/resource.go +++ b/stackit/internal/services/iaas/routingtable/route/resource.go @@ -10,8 +10,7 @@ import ( "github.com/stackitcloud/stackit-sdk-go/core/oapierror" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" - "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/routingtable/shared" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -23,6 +22,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/routingtable/shared" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features" @@ -39,13 +40,17 @@ var ( ) // NewRoutingTableRouteResource is a helper function to simplify the provider implementation. -func NewRoutingTableRouteResource() resource.Resource { - return &routeResource{} +func NewRoutingTableRouteResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &routeResource{ + clientFactory: clientFactory, + } } // routeResource is the resource implementation. type routeResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -67,11 +72,11 @@ func (r *routeResource) Configure(ctx context.Context, req resource.ConfigureReq return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "IaaS alpha client configured") } @@ -267,7 +272,7 @@ func (r *routeResource) Create(ctx context.Context, req resource.CreateRequest, return } - routeResp, err := r.client.DefaultAPI.AddRoutesToRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId).AddRoutesToRoutingTablePayload(*payload).Execute() + routeResp, err := r.client.AddRoutesToRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId).AddRoutesToRoutingTablePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating routing table route", fmt.Sprintf("Calling API: %v", err)) return @@ -319,7 +324,7 @@ func (r *routeResource) Read(ctx context.Context, req resource.ReadRequest, resp ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "route_id", routeId) - routeResp, err := r.client.DefaultAPI.GetRouteOfRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId, routeId).Execute() + routeResp, err := r.client.GetRouteOfRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId, routeId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -387,7 +392,7 @@ func (r *routeResource) Update(ctx context.Context, req resource.UpdateRequest, return } - route, err := r.client.DefaultAPI.UpdateRouteOfRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId, routeId).UpdateRouteOfRoutingTablePayload(*payload).Execute() + route, err := r.client.UpdateRouteOfRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId, routeId).UpdateRouteOfRoutingTablePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating routing table route", fmt.Sprintf("Calling API: %v", err)) return @@ -434,7 +439,7 @@ func (r *routeResource) Delete(ctx context.Context, req resource.DeleteRequest, ctx = tflog.SetField(ctx, "region", region) // Delete existing routing table route - err := r.client.DefaultAPI.DeleteRouteFromRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId, routeId).Execute() + err := r.client.DeleteRouteFromRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId, routeId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/routingtable/routes/datasource.go b/stackit/internal/services/iaas/routingtable/routes/datasource.go index e54290cac..ea7cb957f 100644 --- a/stackit/internal/services/iaas/routingtable/routes/datasource.go +++ b/stackit/internal/services/iaas/routingtable/routes/datasource.go @@ -13,11 +13,12 @@ import ( "github.com/hashicorp/terraform-plugin-log/tflog" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features" shared "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/routingtable/shared" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" ) @@ -36,13 +37,17 @@ type RoutingTableRoutesDataSourceModel struct { } // NewRoutingTableRoutesDataSource is a helper function to simplify the provider implementation. -func NewRoutingTableRoutesDataSource() datasource.DataSource { - return &routingTableRoutesDataSource{} +func NewRoutingTableRoutesDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &routingTableRoutesDataSource{ + clientFactory: clientFactory, + } } // routingTableDataSource is the data source implementation. type routingTableRoutesDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -63,11 +68,11 @@ func (d *routingTableRoutesDataSource) Configure(ctx context.Context, req dataso return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -102,7 +107,7 @@ func (d *routingTableRoutesDataSource) Read(ctx context.Context, req datasource. ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) ctx = tflog.SetField(ctx, "routing_table_id", routingTableId) - routesResp, err := d.client.DefaultAPI.ListRoutesOfRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId).Execute() + routesResp, err := d.client.ListRoutesOfRoutingTable(ctx, organizationId, networkAreaId, region, routingTableId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/routingtable/table/datasource.go b/stackit/internal/services/iaas/routingtable/table/datasource.go index e720885ec..368b4ef7f 100644 --- a/stackit/internal/services/iaas/routingtable/table/datasource.go +++ b/stackit/internal/services/iaas/routingtable/table/datasource.go @@ -9,7 +9,7 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/routingtable/shared" @@ -29,13 +29,17 @@ var ( ) // NewRoutingTableDataSource is a helper function to simplify the provider implementation. -func NewRoutingTableDataSource() datasource.DataSource { - return &routingTableDataSource{} +func NewRoutingTableDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &routingTableDataSource{ + clientFactory: clientFactory, + } } // routingTableDataSource is the data source implementation. type routingTableDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -56,11 +60,11 @@ func (d *routingTableDataSource) Configure(ctx context.Context, req datasource.C return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -95,7 +99,7 @@ func (d *routingTableDataSource) Read(ctx context.Context, req datasource.ReadRe ctx = tflog.SetField(ctx, "routing_table_id", routingTableId) ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) - routingTableResp, err := d.client.DefaultAPI.GetRoutingTableOfArea(ctx, organizationId, networkAreaId, region, routingTableId).Execute() + routingTableResp, err := d.client.GetRoutingTableOfArea(ctx, organizationId, networkAreaId, region, routingTableId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/routingtable/table/resource.go b/stackit/internal/services/iaas/routingtable/table/resource.go index f63fcefeb..f7e926c12 100644 --- a/stackit/internal/services/iaas/routingtable/table/resource.go +++ b/stackit/internal/services/iaas/routingtable/table/resource.go @@ -11,6 +11,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -55,13 +57,17 @@ type Model struct { } // NewRoutingTableResource is a helper function to simplify the provider implementation. -func NewRoutingTableResource() resource.Resource { - return &routingTableResource{} +func NewRoutingTableResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &routingTableResource{ + clientFactory: clientFactory, + } } // routingTableResource is the resource implementation. type routingTableResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -83,11 +89,11 @@ func (r *routingTableResource) Configure(ctx context.Context, req resource.Confi return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "IaaS alpha client configured") } @@ -251,7 +257,7 @@ func (r *routingTableResource) Create(ctx context.Context, req resource.CreateRe return } - routingTable, err := r.client.DefaultAPI.AddRoutingTableToArea(ctx, organizationId, networkAreaId, region).AddRoutingTableToAreaPayload(*payload).Execute() + routingTable, err := r.client.AddRoutingTableToArea(ctx, organizationId, networkAreaId, region).AddRoutingTableToAreaPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating routing table", fmt.Sprintf("Calling API: %v", err)) return @@ -300,7 +306,7 @@ func (r *routingTableResource) Read(ctx context.Context, req resource.ReadReques ctx = tflog.SetField(ctx, "routing_table_id", routingTableId) ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) - routingTableResp, err := r.client.DefaultAPI.GetRoutingTableOfArea(ctx, organizationId, networkAreaId, region, routingTableId).Execute() + routingTableResp, err := r.client.GetRoutingTableOfArea(ctx, organizationId, networkAreaId, region, routingTableId).Execute() if err != nil { utils.LogError( ctx, @@ -370,7 +376,7 @@ func (r *routingTableResource) Update(ctx context.Context, req resource.UpdateRe return } - routingTable, err := r.client.DefaultAPI.UpdateRoutingTableOfArea(ctx, organizationId, networkAreaId, region, routingTableId).UpdateRoutingTableOfAreaPayload(*payload).Execute() + routingTable, err := r.client.UpdateRoutingTableOfArea(ctx, organizationId, networkAreaId, region, routingTableId).UpdateRoutingTableOfAreaPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating routing table", fmt.Sprintf("Calling API: %v", err)) return @@ -415,7 +421,7 @@ func (r *routingTableResource) Delete(ctx context.Context, req resource.DeleteRe ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) // Delete existing routing table - err := r.client.DefaultAPI.DeleteRoutingTableFromArea(ctx, organizationId, networkAreaId, region, routingTableId).Execute() + err := r.client.DeleteRoutingTableFromArea(ctx, organizationId, networkAreaId, region, routingTableId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/routingtable/tables/datasource.go b/stackit/internal/services/iaas/routingtable/tables/datasource.go index 4c3c03733..6cd3e2f97 100644 --- a/stackit/internal/services/iaas/routingtable/tables/datasource.go +++ b/stackit/internal/services/iaas/routingtable/tables/datasource.go @@ -7,8 +7,7 @@ import ( iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" - "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/routingtable/shared" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource" @@ -17,6 +16,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" "github.com/hashicorp/terraform-plugin-log/tflog" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/routingtable/shared" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/features" @@ -38,13 +39,17 @@ type DataSourceModelTables struct { } // NewRoutingTablesDataSource is a helper function to simplify the provider implementation. -func NewRoutingTablesDataSource() datasource.DataSource { - return &routingTablesDataSource{} +func NewRoutingTablesDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &routingTablesDataSource{ + clientFactory: clientFactory, + } } // routingTableDataSource is the data source implementation. type routingTablesDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -65,11 +70,11 @@ func (d *routingTablesDataSource) Configure(ctx context.Context, req datasource. return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "IaaS client configured") } @@ -135,7 +140,7 @@ func (d *routingTablesDataSource) Read(ctx context.Context, req datasource.ReadR ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "network_area_id", networkAreaId) - routingTablesResp, err := d.client.DefaultAPI.ListRoutingTablesOfArea(ctx, organizationId, networkAreaId, region).Execute() + routingTablesResp, err := d.client.ListRoutingTablesOfArea(ctx, organizationId, networkAreaId, region).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/securitygroup/datasource.go b/stackit/internal/services/iaas/securitygroup/datasource.go index 71e1209a0..702b15e6b 100644 --- a/stackit/internal/services/iaas/securitygroup/datasource.go +++ b/stackit/internal/services/iaas/securitygroup/datasource.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -26,13 +26,17 @@ var ( ) // NewSecurityGroupDataSource is a helper function to simplify the provider implementation. -func NewSecurityGroupDataSource() datasource.DataSource { - return &securityGroupDataSource{} +func NewSecurityGroupDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &securityGroupDataSource{ + clientFactory: clientFactory, + } } // securityGroupDataSource is the data source implementation. type securityGroupDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -48,11 +52,11 @@ func (d *securityGroupDataSource) Configure(ctx context.Context, req datasource. return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -127,7 +131,7 @@ func (d *securityGroupDataSource) Read(ctx context.Context, req datasource.ReadR ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "security_group_id", securityGroupId) - securityGroupResp, err := d.client.DefaultAPI.GetSecurityGroup(ctx, projectId, region, securityGroupId).Execute() + securityGroupResp, err := d.client.GetSecurityGroup(ctx, projectId, region, securityGroupId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/securitygroup/resource.go b/stackit/internal/services/iaas/securitygroup/resource.go index ae7afb505..d8e4cb8fa 100644 --- a/stackit/internal/services/iaas/securitygroup/resource.go +++ b/stackit/internal/services/iaas/securitygroup/resource.go @@ -9,6 +9,7 @@ import ( "strings" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" @@ -49,13 +50,17 @@ type Model struct { } // NewSecurityGroupResource is a helper function to simplify the provider implementation. -func NewSecurityGroupResource() resource.Resource { - return &securityGroupResource{} +func NewSecurityGroupResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &securityGroupResource{ + clientFactory: clientFactory, + } } // securityGroupResource is the resource implementation. type securityGroupResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -102,11 +107,11 @@ func (r *securityGroupResource) Configure(ctx context.Context, req resource.Conf return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -222,7 +227,7 @@ func (r *securityGroupResource) Create(ctx context.Context, req resource.CreateR // Create new security group - securityGroup, err := r.client.DefaultAPI.CreateSecurityGroup(ctx, projectId, region).CreateSecurityGroupPayload(*payload).Execute() + securityGroup, err := r.client.CreateSecurityGroup(ctx, projectId, region).CreateSecurityGroupPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating security group", fmt.Sprintf("Calling API: %v", err)) return @@ -272,7 +277,7 @@ func (r *securityGroupResource) Read(ctx context.Context, req resource.ReadReque ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "security_id", securityGroupId) - securityGroupResp, err := r.client.DefaultAPI.GetSecurityGroup(ctx, projectId, region, securityGroupId).Execute() + securityGroupResp, err := r.client.GetSecurityGroup(ctx, projectId, region, securityGroupId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -334,7 +339,7 @@ func (r *securityGroupResource) Update(ctx context.Context, req resource.UpdateR return } // Update existing security group - updatedSecurityGroup, err := r.client.DefaultAPI.UpdateSecurityGroup(ctx, projectId, region, securityGroupId).UpdateSecurityGroupPayload(*payload).Execute() + updatedSecurityGroup, err := r.client.UpdateSecurityGroup(ctx, projectId, region, securityGroupId).UpdateSecurityGroupPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating security group", fmt.Sprintf("Calling API: %v", err)) return @@ -376,7 +381,7 @@ func (r *securityGroupResource) Delete(ctx context.Context, req resource.DeleteR ctx = tflog.SetField(ctx, "security_group_id", securityGroupId) // Delete existing security group - err := r.client.DefaultAPI.DeleteSecurityGroup(ctx, projectId, region, securityGroupId).Execute() + err := r.client.DeleteSecurityGroup(ctx, projectId, region, securityGroupId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/securitygrouprule/datasource.go b/stackit/internal/services/iaas/securitygrouprule/datasource.go index 0093525e8..ff7dbe208 100644 --- a/stackit/internal/services/iaas/securitygrouprule/datasource.go +++ b/stackit/internal/services/iaas/securitygrouprule/datasource.go @@ -6,7 +6,7 @@ import ( "net/http" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" @@ -25,13 +25,17 @@ var ( ) // NewSecurityGroupRuleDataSource is a helper function to simplify the provider implementation. -func NewSecurityGroupRuleDataSource() datasource.DataSource { - return &securityGroupRuleDataSource{} +func NewSecurityGroupRuleDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &securityGroupRuleDataSource{ + clientFactory: clientFactory, + } } // securityGroupRuleDataSource is the data source implementation. type securityGroupRuleDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -47,11 +51,11 @@ func (d *securityGroupRuleDataSource) Configure(ctx context.Context, req datasou return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -183,7 +187,7 @@ func (d *securityGroupRuleDataSource) Read(ctx context.Context, req datasource.R ctx = tflog.SetField(ctx, "security_group_id", securityGroupId) ctx = tflog.SetField(ctx, "security_group_rule_id", securityGroupRuleId) - securityGroupRuleResp, err := d.client.DefaultAPI.GetSecurityGroupRule(ctx, projectId, region, securityGroupId, securityGroupRuleId).Execute() + securityGroupRuleResp, err := d.client.GetSecurityGroupRule(ctx, projectId, region, securityGroupId, securityGroupRuleId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/securitygrouprule/resource.go b/stackit/internal/services/iaas/securitygrouprule/resource.go index 70982b74c..5cc13ca8e 100644 --- a/stackit/internal/services/iaas/securitygrouprule/resource.go +++ b/stackit/internal/services/iaas/securitygrouprule/resource.go @@ -9,7 +9,7 @@ import ( "slices" "strings" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" @@ -98,13 +98,17 @@ var protocolTypes = map[string]attr.Type{ } // NewSecurityGroupRuleResource is a helper function to simplify the provider implementation. -func NewSecurityGroupRuleResource() resource.Resource { - return &securityGroupRuleResource{} +func NewSecurityGroupRuleResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &securityGroupRuleResource{ + clientFactory: clientFactory, + } } // securityGroupRuleResource is the resource implementation. type securityGroupRuleResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -151,11 +155,11 @@ func (r *securityGroupRuleResource) Configure(ctx context.Context, req resource. return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -482,7 +486,7 @@ func (r *securityGroupRuleResource) Create(ctx context.Context, req resource.Cre } // Create new security group rule - securityGroupRule, err := r.client.DefaultAPI.CreateSecurityGroupRule(ctx, projectId, region, securityGroupId).CreateSecurityGroupRulePayload(*payload).Execute() + securityGroupRule, err := r.client.CreateSecurityGroupRule(ctx, projectId, region, securityGroupId).CreateSecurityGroupRulePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating security group rule", fmt.Sprintf("Calling API: %v", err)) return @@ -532,7 +536,7 @@ func (r *securityGroupRuleResource) Read(ctx context.Context, req resource.ReadR ctx = tflog.SetField(ctx, "security_group_id", securityGroupId) ctx = tflog.SetField(ctx, "security_group_rule_id", securityGroupRuleId) - securityGroupRuleResp, err := r.client.DefaultAPI.GetSecurityGroupRule(ctx, projectId, region, securityGroupId, securityGroupRuleId).Execute() + securityGroupRuleResp, err := r.client.GetSecurityGroupRule(ctx, projectId, region, securityGroupId, securityGroupRuleId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -589,7 +593,7 @@ func (r *securityGroupRuleResource) Delete(ctx context.Context, req resource.Del ctx = tflog.SetField(ctx, "security_group_rule_id", securityGroupRuleId) // Delete existing security group rule - err := r.client.DefaultAPI.DeleteSecurityGroupRule(ctx, projectId, region, securityGroupId, securityGroupRuleId).Execute() + err := r.client.DeleteSecurityGroupRule(ctx, projectId, region, securityGroupId, securityGroupRuleId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/server/datasource.go b/stackit/internal/services/iaas/server/datasource.go index 032bebc9c..339e2e0b4 100644 --- a/stackit/internal/services/iaas/server/datasource.go +++ b/stackit/internal/services/iaas/server/datasource.go @@ -9,6 +9,7 @@ import ( "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource" @@ -60,13 +61,17 @@ var agentDataTypes = map[string]attr.Type{ } // NewServerDataSource is a helper function to simplify the provider implementation. -func NewServerDataSource() datasource.DataSource { - return &serverDataSource{} +func NewServerDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &serverDataSource{ + clientFactory: clientFactory, + } } // serverDataSource is the data source implementation. type serverDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -82,11 +87,11 @@ func (d *serverDataSource) Configure(ctx context.Context, req datasource.Configu return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -218,7 +223,7 @@ func (d *serverDataSource) Read(ctx context.Context, req datasource.ReadRequest, ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "server_id", serverId) - serverReq := d.client.DefaultAPI.GetServer(ctx, projectId, region, serverId) + serverReq := d.client.GetServer(ctx, projectId, region, serverId) serverReq = serverReq.Details(true) serverResp, err := serverReq.Execute() if err != nil { diff --git a/stackit/internal/services/iaas/server/resource.go b/stackit/internal/services/iaas/server/resource.go index 552126f88..0e24afec4 100644 --- a/stackit/internal/services/iaas/server/resource.go +++ b/stackit/internal/services/iaas/server/resource.go @@ -12,6 +12,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" "github.com/hashicorp/terraform-plugin-framework-validators/listvalidator" @@ -114,13 +116,17 @@ var agentTypes = map[string]attr.Type{ } // NewServerResource is a helper function to simplify the provider implementation. -func NewServerResource() resource.Resource { - return &serverResource{} +func NewServerResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &serverResource{ + clientFactory: clientFactory, + } } // serverResource is the resource implementation. type serverResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -208,11 +214,11 @@ func (r *serverResource) Configure(ctx context.Context, req resource.ConfigureRe return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -541,7 +547,7 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest, // Create new server - server, err := r.client.DefaultAPI.CreateServer(ctx, projectId, region).CreateServerPayload(*payload).Execute() + server, err := r.client.CreateServer(ctx, projectId, region).CreateServerPayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating server", fmt.Sprintf("Calling API: %v", err)) return @@ -564,14 +570,14 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest, return } - _, err = wait.CreateServerWaitHandler(ctx, r.client.DefaultAPI, projectId, region, serverId).WaitWithContext(ctx) + _, err = wait.CreateServerWaitHandler(ctx, r.client, projectId, region, serverId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating server", fmt.Sprintf("server creation waiting: %v", err)) return } // Get Server with details - serverReq := r.client.DefaultAPI.GetServer(ctx, projectId, region, serverId) + serverReq := r.client.GetServer(ctx, projectId, region, serverId) serverReq = serverReq.Details(true) server, err = serverReq.Execute() if err != nil { @@ -585,7 +591,7 @@ func (r *serverResource) Create(ctx context.Context, req resource.CreateRequest, return } - if err := updateServerStatus(ctx, r.client.DefaultAPI, server.Status, &model, region); err != nil { + if err := updateServerStatus(ctx, r.client, server.Status, &model, region); err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating server", fmt.Sprintf("update server state: %v", err)) return } @@ -724,7 +730,7 @@ func (r *serverResource) Read(ctx context.Context, req resource.ReadRequest, res ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "server_id", serverId) - serverReq := r.client.DefaultAPI.GetServer(ctx, projectId, region, serverId) + serverReq := r.client.GetServer(ctx, projectId, region, serverId) serverReq = serverReq.Details(true) serverResp, err := serverReq.Execute() if err != nil { @@ -765,7 +771,7 @@ func (r *serverResource) updateServerAttributes(ctx context.Context, model, stat var updatedServer *iaas.Server // Update existing server - updatedServer, err = r.client.DefaultAPI.UpdateServer(ctx, projectId, region, serverId).UpdateServerPayload(*payload).Execute() + updatedServer, err = r.client.UpdateServer(ctx, projectId, region, serverId).UpdateServerPayload(*payload).Execute() if err != nil { return nil, fmt.Errorf("calling API: %w", err) } @@ -776,12 +782,12 @@ func (r *serverResource) updateServerAttributes(ctx context.Context, model, stat payload := iaas.ResizeServerPayload{ MachineType: *modelMachineType, } - err := r.client.DefaultAPI.ResizeServer(ctx, projectId, region, serverId).ResizeServerPayload(payload).Execute() + err := r.client.ResizeServer(ctx, projectId, region, serverId).ResizeServerPayload(payload).Execute() if err != nil { return nil, fmt.Errorf("resizing the server, calling API: %w", err) } - _, err = wait.ResizeServerWaitHandler(ctx, r.client.DefaultAPI, projectId, region, serverId).WaitWithContext(ctx) + _, err = wait.ResizeServerWaitHandler(ctx, r.client, projectId, region, serverId).WaitWithContext(ctx) if err != nil { return nil, fmt.Errorf("server resize waiting: %w", err) } @@ -822,7 +828,7 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest, server *iaas.Server err error ) - if server, err = r.client.DefaultAPI.GetServer(ctx, projectId, region, serverId).Execute(); err != nil { + if server, err = r.client.GetServer(ctx, projectId, region, serverId).Execute(); err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error retrieving server state", fmt.Sprintf("Getting server state: %v", err)) } @@ -837,13 +843,13 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest, ctx = core.LogResponse(ctx) - if err := updateServerStatus(ctx, r.client.DefaultAPI, server.Status, &model, region); err != nil { + if err := updateServerStatus(ctx, r.client, server.Status, &model, region); err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating server", err.Error()) return } } else { // potentially unfreeze first and update afterwards - if err := updateServerStatus(ctx, r.client.DefaultAPI, server.Status, &model, region); err != nil { + if err := updateServerStatus(ctx, r.client, server.Status, &model, region); err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating server", err.Error()) return } @@ -858,7 +864,7 @@ func (r *serverResource) Update(ctx context.Context, req resource.UpdateRequest, } // Re-fetch the server data, to get the details values. - serverReq := r.client.DefaultAPI.GetServer(ctx, projectId, region, serverId) + serverReq := r.client.GetServer(ctx, projectId, region, serverId) serverReq = serverReq.Details(true) updatedServer, err := serverReq.Execute() if err != nil { @@ -901,7 +907,7 @@ func (r *serverResource) Delete(ctx context.Context, req resource.DeleteRequest, ctx = tflog.SetField(ctx, "server_id", serverId) // Delete existing server - err := r.client.DefaultAPI.DeleteServer(ctx, projectId, region, serverId).Execute() + err := r.client.DeleteServer(ctx, projectId, region, serverId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -914,7 +920,7 @@ func (r *serverResource) Delete(ctx context.Context, req resource.DeleteRequest, ctx = core.LogResponse(ctx) - _, err = wait.DeleteServerWaitHandler(ctx, r.client.DefaultAPI, projectId, region, serverId).WaitWithContext(ctx) + _, err = wait.DeleteServerWaitHandler(ctx, r.client, projectId, region, serverId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting server", fmt.Sprintf("server deletion waiting: %v", err)) return diff --git a/stackit/internal/services/iaas/serviceaccountattach/resource.go b/stackit/internal/services/iaas/serviceaccountattach/resource.go index d2cceddee..63cc705c1 100644 --- a/stackit/internal/services/iaas/serviceaccountattach/resource.go +++ b/stackit/internal/services/iaas/serviceaccountattach/resource.go @@ -8,9 +8,7 @@ import ( "strings" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" - - "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" - iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/resource/schema" @@ -22,6 +20,8 @@ import ( "github.com/stackitcloud/stackit-sdk-go/core/oapierror" iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/validate" ) @@ -43,13 +43,17 @@ type Model struct { } // NewServiceAccountAttachResource is a helper function to simplify the provider implementation. -func NewServiceAccountAttachResource() resource.Resource { - return &serviceAccountAttachResource{} +func NewServiceAccountAttachResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &serviceAccountAttachResource{ + clientFactory: clientFactory, + } } // serviceAccountAttachResource is the resource implementation. type serviceAccountAttachResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -96,11 +100,11 @@ func (r *serviceAccountAttachResource) Configure(ctx context.Context, req resour return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -182,7 +186,7 @@ func (r *serviceAccountAttachResource) Create(ctx context.Context, req resource. ctx = tflog.SetField(ctx, "service_account_email", serviceAccountEmail) // Create new service account attachment - _, err := r.client.DefaultAPI.AddServiceAccountToServer(ctx, projectId, region, serverId, serviceAccountEmail).Execute() + _, err := r.client.AddServiceAccountToServer(ctx, projectId, region, serverId, serviceAccountEmail).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error attaching service account to server", fmt.Sprintf("Calling API: %v", err)) return @@ -222,7 +226,7 @@ func (r *serviceAccountAttachResource) Read(ctx context.Context, req resource.Re ctx = tflog.SetField(ctx, "server_id", serverId) ctx = tflog.SetField(ctx, "service_account_email", serviceAccountEmail) - serviceAccounts, err := r.client.DefaultAPI.ListServerServiceAccounts(ctx, projectId, region, serverId).Execute() + serviceAccounts, err := r.client.ListServerServiceAccounts(ctx, projectId, region, serverId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -290,7 +294,7 @@ func (r *serviceAccountAttachResource) Delete(ctx context.Context, req resource. ctx = tflog.SetField(ctx, "service_account_email", service_accountId) // Remove service_account from server - _, err := r.client.DefaultAPI.RemoveServiceAccountFromServer(ctx, projectId, region, serverId, service_accountId).Execute() + _, err := r.client.RemoveServiceAccountFromServer(ctx, projectId, region, serverId, service_accountId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { diff --git a/stackit/internal/services/iaas/utils/util.go b/stackit/internal/services/iaas/utils/util.go index a5f846de2..922786d1a 100644 --- a/stackit/internal/services/iaas/utils/util.go +++ b/stackit/internal/services/iaas/utils/util.go @@ -12,30 +12,11 @@ import ( "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/stackitcloud/stackit-sdk-go/core/config" iaasLegacy "github.com/stackitcloud/stackit-sdk-go/services/iaas" //nolint:staticcheck // TODO: will be done within STACKITTPR-713 - iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" ) -func ConfigureClient(ctx context.Context, providerData *core.ProviderData, diags *diag.Diagnostics) *iaas.APIClient { - apiClientConfigOptions := []config.ConfigurationOption{ - config.WithCustomAuth(providerData.RoundTripper), - utils.UserAgentConfigOption(providerData.Version), - } - if providerData.IaaSCustomEndpoint != "" { - apiClientConfigOptions = append(apiClientConfigOptions, config.WithEndpoint(providerData.IaaSCustomEndpoint)) - } - - apiClient, err := iaas.NewAPIClient(apiClientConfigOptions...) - if err != nil { - core.LogAndAddError(ctx, diags, "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 nil - } - - return apiClient -} - // Deprecated: Use ConfigureClient instead func ConfigureClientLegacy(ctx context.Context, providerData *core.ProviderData, diags *diag.Diagnostics) *iaasLegacy.APIClient { //nolint:staticcheck // TODO: will be done within STACKITTPR-713 apiClientConfigOptions := []config.ConfigurationOption{ diff --git a/stackit/internal/services/iaas/volume/datasource.go b/stackit/internal/services/iaas/volume/datasource.go index f276a8bf4..a9218fe9e 100644 --- a/stackit/internal/services/iaas/volume/datasource.go +++ b/stackit/internal/services/iaas/volume/datasource.go @@ -9,6 +9,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" @@ -47,13 +49,17 @@ type DatasourceModel struct { } // NewVolumeDataSource is a helper function to simplify the provider implementation. -func NewVolumeDataSource() datasource.DataSource { - return &volumeDataSource{} +func NewVolumeDataSource(clientFactory clientutils.ClientFactory) datasource.DataSource { + return &volumeDataSource{ + clientFactory: clientFactory, + } } // volumeDataSource is the data source implementation. type volumeDataSource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -69,11 +75,11 @@ func (d *volumeDataSource) Configure(ctx context.Context, req datasource.Configu return } - apiClient := iaasUtils.ConfigureClient(ctx, &d.providerData, &resp.Diagnostics) + d.client = d.clientFactory.NewIaaSV2Client(ctx, &d.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - d.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -182,7 +188,7 @@ func (d *volumeDataSource) Read(ctx context.Context, req datasource.ReadRequest, ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "volume_id", volumeId) - volumeResp, err := d.client.DefaultAPI.GetVolume(ctx, projectId, region, volumeId).Execute() + volumeResp, err := d.client.GetVolume(ctx, projectId, region, volumeId).Execute() if err != nil { utils.LogError( ctx, diff --git a/stackit/internal/services/iaas/volume/resource.go b/stackit/internal/services/iaas/volume/resource.go index 4fe39e8b1..35eeea03f 100644 --- a/stackit/internal/services/iaas/volume/resource.go +++ b/stackit/internal/services/iaas/volume/resource.go @@ -10,6 +10,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework-validators/int64validator" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/int64planmodifier" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" @@ -88,13 +90,17 @@ var sourceTypes = map[string]attr.Type{ } // NewVolumeResource is a helper function to simplify the provider implementation. -func NewVolumeResource() resource.Resource { - return &volumeResource{} +func NewVolumeResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &volumeResource{ + clientFactory: clientFactory, + } } // volumeResource is the resource implementation. type volumeResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -151,11 +157,11 @@ func (r *volumeResource) Configure(ctx context.Context, req resource.ConfigureRe return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -458,7 +464,7 @@ func (r *volumeResource) Create(ctx context.Context, req resource.CreateRequest, // Create new volume - volume, err := r.client.DefaultAPI.CreateVolume(ctx, projectId, region).CreateVolumePayload(*payload).Execute() + volume, err := r.client.CreateVolume(ctx, projectId, region).CreateVolumePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating volume", fmt.Sprintf("Calling API: %v", err)) return @@ -481,7 +487,7 @@ func (r *volumeResource) Create(ctx context.Context, req resource.CreateRequest, return } - volume, err = wait.CreateVolumeWaitHandler(ctx, r.client.DefaultAPI, projectId, region, volumeId).WaitWithContext(ctx) + volume, err = wait.CreateVolumeWaitHandler(ctx, r.client, projectId, region, volumeId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error creating volume", fmt.Sprintf("volume creation waiting: %v", err)) return @@ -526,7 +532,7 @@ func (r *volumeResource) Read(ctx context.Context, req resource.ReadRequest, res ctx = tflog.SetField(ctx, "region", region) ctx = tflog.SetField(ctx, "volume_id", volumeId) - volumeResp, err := r.client.DefaultAPI.GetVolume(ctx, projectId, region, volumeId).Execute() + volumeResp, err := r.client.GetVolume(ctx, projectId, region, volumeId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -588,7 +594,7 @@ func (r *volumeResource) Update(ctx context.Context, req resource.UpdateRequest, return } // Update existing volume - updatedVolume, err := r.client.DefaultAPI.UpdateVolume(ctx, projectId, region, volumeId).UpdateVolumePayload(*payload).Execute() + updatedVolume, err := r.client.UpdateVolume(ctx, projectId, region, volumeId).UpdateVolumePayload(*payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating volume", fmt.Sprintf("Calling API: %v", err)) return @@ -606,7 +612,7 @@ func (r *volumeResource) Update(ctx context.Context, req resource.UpdateRequest, resizePayload := iaas.ResizeVolumePayload{ Size: *modelSize, } - err = r.client.DefaultAPI.ResizeVolume(ctx, projectId, region, volumeId).ResizeVolumePayload(resizePayload).Execute() + err = r.client.ResizeVolume(ctx, projectId, region, volumeId).ResizeVolumePayload(resizePayload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error updating volume", fmt.Sprintf("Resizing the volume, calling API: %v", err)) } @@ -648,7 +654,7 @@ func (r *volumeResource) Delete(ctx context.Context, req resource.DeleteRequest, ctx = tflog.SetField(ctx, "volume_id", volumeId) // Delete existing volume - err := r.client.DefaultAPI.DeleteVolume(ctx, projectId, region, volumeId).Execute() + err := r.client.DeleteVolume(ctx, projectId, region, volumeId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -661,7 +667,7 @@ func (r *volumeResource) Delete(ctx context.Context, req resource.DeleteRequest, ctx = core.LogResponse(ctx) - _, err = wait.DeleteVolumeWaitHandler(ctx, r.client.DefaultAPI, projectId, region, volumeId).WaitWithContext(ctx) + _, err = wait.DeleteVolumeWaitHandler(ctx, r.client, projectId, region, volumeId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error deleting volume", fmt.Sprintf("volume deletion waiting: %v", err)) return diff --git a/stackit/internal/services/iaas/volume/resource_test.go b/stackit/internal/services/iaas/volume/resource_test.go index 511a2a2fd..2ba7c5086 100644 --- a/stackit/internal/services/iaas/volume/resource_test.go +++ b/stackit/internal/services/iaas/volume/resource_test.go @@ -2,6 +2,7 @@ package volume import ( "context" + _ "embed" "testing" "github.com/google/go-cmp/cmp" diff --git a/stackit/internal/services/iaas/volume/unittest/resource_test.go b/stackit/internal/services/iaas/volume/unittest/resource_test.go new file mode 100644 index 000000000..20b40ae58 --- /dev/null +++ b/stackit/internal/services/iaas/volume/unittest/resource_test.go @@ -0,0 +1,75 @@ +package unittest + +import ( + _ "embed" + "testing" + + "github.com/google/uuid" + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/stackitcloud/stackit-sdk-go/core/utils" + iaas "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/testutil" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" +) + +//go:embed testdata/resource.tf +var tfConfig string + +func TestVolumeResource(t *testing.T) { + projectId := uuid.NewString() + volumeId := uuid.NewString() + + variables := func(mods ...func(variables config.Variables)) config.Variables { + vars := config.Variables{ + "project_id": config.StringVariable(projectId), + "availability_zone": config.StringVariable("eu01-1"), + "size": config.IntegerVariable(64), + } + + for _, mod := range mods { + mod(vars) + } + + return vars + } + + mockClient := iaas.DefaultAPIServiceMock{ + CreateVolumeExecuteMock: utils.Ptr(func(r iaas.ApiCreateVolumeRequest) (*iaas.Volume, error) { + return &iaas.Volume{ + Id: new(volumeId), + }, nil + }), + GetVolumeExecuteMock: utils.Ptr(func(r iaas.ApiGetVolumeRequest) (*iaas.Volume, error) { + return &iaas.Volume{ + Id: new(volumeId), + Status: new("AVAILABLE"), + Size: new(int64(64)), + AvailabilityZone: "eu01-1", + }, nil + }), + } + + resource.UnitTest(t, resource.TestCase{ + ProtoV6ProviderFactories: testutil.NewTestUnitV6ProviderFactories(&clientutils.MockClientFactory{ + IaaSV2ClientMock: mockClient, + }), + Steps: []resource.TestStep{ + { + Config: tfConfig, + ConfigVariables: variables(), + }, + { + Config: tfConfig, + ConfigVariables: variables(), + Check: func(s *terraform.State) error { + // Clear the root module resources so the auto-destroy finds nothing + s.RootModule().Resources = make(map[string]*terraform.ResourceState) + return nil + }, + }, + }, + }) +} diff --git a/stackit/internal/services/iaas/volume/unittest/testdata/resource.tf b/stackit/internal/services/iaas/volume/unittest/testdata/resource.tf new file mode 100644 index 000000000..5c7f30da8 --- /dev/null +++ b/stackit/internal/services/iaas/volume/unittest/testdata/resource.tf @@ -0,0 +1,13 @@ +provider "stackit" { + service_account_token = "mock-server-needs-no-auth" +} + +variable "project_id" {} +variable "availability_zone" {} +variable "size" {} + +resource "stackit_volume" "volume" { + project_id = var.project_id + availability_zone = var.availability_zone + size = var.size +} \ No newline at end of file diff --git a/stackit/internal/services/iaas/volumeattach/resource.go b/stackit/internal/services/iaas/volumeattach/resource.go index 97cda061a..1826c50c7 100644 --- a/stackit/internal/services/iaas/volumeattach/resource.go +++ b/stackit/internal/services/iaas/volumeattach/resource.go @@ -8,6 +8,7 @@ import ( "strings" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/conversion" iaasUtils "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/services/iaas/utils" @@ -44,13 +45,17 @@ type Model struct { } // NewVolumeAttachResource is a helper function to simplify the provider implementation. -func NewVolumeAttachResource() resource.Resource { - return &volumeAttachResource{} +func NewVolumeAttachResource(clientFactory clientutils.ClientFactory) resource.Resource { + return &volumeAttachResource{ + clientFactory: clientFactory, + } } // volumeAttachResource is the resource implementation. type volumeAttachResource struct { - client *iaas.APIClient + clientFactory clientutils.ClientFactory + + client iaas.DefaultAPI providerData core.ProviderData } @@ -97,11 +102,11 @@ func (r *volumeAttachResource) Configure(ctx context.Context, req resource.Confi return } - apiClient := iaasUtils.ConfigureClient(ctx, &r.providerData, &resp.Diagnostics) + r.client = r.clientFactory.NewIaaSV2Client(ctx, &r.providerData, &resp.Diagnostics) if resp.Diagnostics.HasError() { return } - r.client = apiClient + tflog.Info(ctx, "iaas client configured") } @@ -191,7 +196,7 @@ func (r *volumeAttachResource) Create(ctx context.Context, req resource.CreateRe payload := iaas.AddVolumeToServerPayload{ DeleteOnTermination: new(false), } - _, err := r.client.DefaultAPI.AddVolumeToServer(ctx, projectId, region, serverId, volumeId).AddVolumeToServerPayload(payload).Execute() + _, err := r.client.AddVolumeToServer(ctx, projectId, region, serverId, volumeId).AddVolumeToServerPayload(payload).Execute() if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error attaching volume to server", fmt.Sprintf("Calling API: %v", err)) return @@ -214,7 +219,7 @@ func (r *volumeAttachResource) Create(ctx context.Context, req resource.CreateRe core.LogAndAddError(ctx, &resp.Diagnostics, "Error attaching volume to server", fmt.Sprintf("Reading x-request-ID: %v", err)) return } - _, err = wait.ProjectRequestWaitHandler(ctx, r.client.DefaultAPI, projectId, region, requestId).WaitWithContext(ctx) + _, err = wait.ProjectRequestWaitHandler(ctx, r.client, projectId, region, requestId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error attaching volume to server", fmt.Sprintf("volume attachment waiting: %v", err)) return @@ -252,7 +257,7 @@ func (r *volumeAttachResource) Read(ctx context.Context, req resource.ReadReques ctx = tflog.SetField(ctx, "server_id", serverId) ctx = tflog.SetField(ctx, "volume_id", volumeId) - _, err := r.client.DefaultAPI.GetAttachedVolume(ctx, projectId, region, serverId, volumeId).Execute() + _, err := r.client.GetAttachedVolume(ctx, projectId, region, serverId, volumeId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -305,7 +310,7 @@ func (r *volumeAttachResource) Delete(ctx context.Context, req resource.DeleteRe ctx = tflog.SetField(ctx, "volume_id", volumeId) // Remove volume from server - err := r.client.DefaultAPI.RemoveVolumeFromServer(ctx, projectId, region, serverId, volumeId).Execute() + err := r.client.RemoveVolumeFromServer(ctx, projectId, region, serverId, volumeId).Execute() if err != nil { var oapiErr *oapierror.GenericOpenAPIError if errors.As(err, &oapiErr) && oapiErr.StatusCode == http.StatusNotFound { @@ -322,7 +327,7 @@ func (r *volumeAttachResource) Delete(ctx context.Context, req resource.DeleteRe core.LogAndAddError(ctx, &resp.Diagnostics, "Error attaching volume to server", fmt.Sprintf("Reading x-request-ID: %v", err)) return } - _, err = wait.ProjectRequestWaitHandler(ctx, r.client.DefaultAPI, projectId, region, requestId).WaitWithContext(ctx) + _, err = wait.ProjectRequestWaitHandler(ctx, r.client, projectId, region, requestId).WaitWithContext(ctx) if err != nil { core.LogAndAddError(ctx, &resp.Diagnostics, "Error removing volume from server", fmt.Sprintf("volume removal waiting: %v", err)) return diff --git a/stackit/internal/testutil/testutil.go b/stackit/internal/testutil/testutil.go index 512a08641..723af712f 100644 --- a/stackit/internal/testutil/testutil.go +++ b/stackit/internal/testutil/testutil.go @@ -19,6 +19,8 @@ import ( "github.com/hashicorp/terraform-plugin-testing/helper/resource" sdkConf "github.com/stackitcloud/stackit-sdk-go/core/config" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "github.com/stackitcloud/terraform-provider-stackit/stackit" ) @@ -68,80 +70,83 @@ var ( // TestImageLocalFilePath is the local path to an image file used for image acceptance tests TestImageLocalFilePath = getenv("TF_ACC_TEST_IMAGE_LOCAL_FILE_PATH", "default") - ALBCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_ALB_CUSTOM_ENDPOINT", providerName: "alb_custom_endpoint"} - ALBCertCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_ALB_CERT_CUSTOM_ENDPOINT", providerName: "alb_certificates_custom_endpoint"} - AlbWafCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_ALB_WAF_CUSTOM_ENDPOINT", providerName: "alb_waf_custom_endpoint"} - CdnCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_CDN_CUSTOM_ENDPOINT", providerName: "cdn_custom_endpoint"} - DnsCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_DNS_CUSTOM_ENDPOINT", providerName: "dns_custom_endpoint"} - DremioCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_DREMIO_CUSTOM_ENDPOINT", providerName: "dremio_custom_endpoint"} - EdgeCloudCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_EDGECLOUD_CUSTOM_ENDPOINT", providerName: "edgecloud_custom_endpoint"} - GitCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_GIT_CUSTOM_ENDPOINT", providerName: "git_custom_endpoint"} - IaaSCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_IAAS_CUSTOM_ENDPOINT", providerName: "iaas_custom_endpoint"} - KMSCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_KMS_CUSTOM_ENDPOINT", providerName: "kms_custom_endpoint"} - LoadBalancerCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_LOADBALANCER_CUSTOM_ENDPOINT", providerName: "loadbalancer_custom_endpoint"} - LogMeCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_LOGME_CUSTOM_ENDPOINT", providerName: "logme_custom_endpoint"} - LogsCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_LOGS_CUSTOM_ENDPOINT", providerName: "logs_custom_endpoint"} - MariaDBCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_MARIADB_CUSTOM_ENDPOINT", providerName: "mariadb_custom_endpoint"} - ModelServingCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_MODELSERVING_CUSTOM_ENDPOINT", providerName: "modelserving_custom_endpoint"} - AuthorizationCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_AUTHORIZATION_CUSTOM_ENDPOINT", providerName: "authorization_custom_endpoint"} - MongoDBFlexCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_MONGODBFLEX_CUSTOM_ENDPOINT", providerName: "mongodbflex_custom_endpoint"} - OpenSearchCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_OPENSEARCH_CUSTOM_ENDPOINT", providerName: "opensearch_custom_endpoint"} - ObservabilityCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_OBSERVABILITY_CUSTOM_ENDPOINT", providerName: "observability_custom_endpoint"} - ObjectStorageCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_OBJECTSTORAGE_CUSTOM_ENDPOINT", providerName: "objectstorage_custom_endpoint"} - PostgresFlexCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_POSTGRESFLEX_CUSTOM_ENDPOINT", providerName: "postgresflex_custom_endpoint"} - RabbitMQCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_RABBITMQ_CUSTOM_ENDPOINT", providerName: "rabbitmq_custom_endpoint"} - RedisCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_REDIS_CUSTOM_ENDPOINT", providerName: "redis_custom_endpoint"} - ResourceManagerCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_RESOURCEMANAGER_CUSTOM_ENDPOINT", providerName: "resourcemanager_custom_endpoint"} - ScfCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SCF_CUSTOM_ENDPOINT", providerName: "scf_custom_endpoint"} - SecretsManagerCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SECRETSMANAGER_CUSTOM_ENDPOINT", providerName: "secretsmanager_custom_endpoint"} - SQLServerFlexCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SQLSERVERFLEX_CUSTOM_ENDPOINT", providerName: "sqlserverflex_custom_endpoint"} - ServerBackupCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SERVER_BACKUP_CUSTOM_ENDPOINT", providerName: "server_backup_custom_endpoint"} - ServerUpdateCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SERVER_UPDATE_CUSTOM_ENDPOINT", providerName: "server_update_custom_endpoint"} - SFSCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SFS_CUSTOM_ENDPOINT", providerName: "sfs_custom_endpoint"} - ServiceAccountCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SERVICE_ACCOUNT_CUSTOM_ENDPOINT", providerName: "service_account_custom_endpoint"} - TokenCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_TOKEN_CUSTOM_ENDPOINT", providerName: "token_custom_endpoint"} - VpnCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_VPN_CUSTOM_ENDPOINT", providerName: "vpn_custom_endpoint"} - SKECustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SKE_CUSTOM_ENDPOINT", providerName: "ske_custom_endpoint"} - IntakeCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_INTAKE_CUSTOM_ENDPOINT", providerName: "intake_custom_endpoint"} - TelemetryRouterCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_TELEMETRYROUTER_CUSTOM_ENDPOINT", providerName: "telemetryrouter_custom_endpoint"} - TelemetryLinkCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_TELEMETRYLINK_CUSTOM_ENDPOINT", providerName: "telemetrylink_custom_endpoint"} + ALBCertCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_ALB_CERT_CUSTOM_ENDPOINT", providerName: "alb_certificates_custom_endpoint"} + ALBCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_ALB_CUSTOM_ENDPOINT", providerName: "alb_custom_endpoint"} + AlbWafCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_ALB_WAF_CUSTOM_ENDPOINT", providerName: "alb_waf_custom_endpoint"} + AuthorizationCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_AUTHORIZATION_CUSTOM_ENDPOINT", providerName: "authorization_custom_endpoint"} + CdnCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_CDN_CUSTOM_ENDPOINT", providerName: "cdn_custom_endpoint"} + DnsCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_DNS_CUSTOM_ENDPOINT", providerName: "dns_custom_endpoint"} + DremioCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_DREMIO_CUSTOM_ENDPOINT", providerName: "dremio_custom_endpoint"} + EdgeCloudCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_EDGECLOUD_CUSTOM_ENDPOINT", providerName: "edgecloud_custom_endpoint"} + GitCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_GIT_CUSTOM_ENDPOINT", providerName: "git_custom_endpoint"} + IaaSCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_IAAS_CUSTOM_ENDPOINT", providerName: "iaas_custom_endpoint"} + IntakeCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_INTAKE_CUSTOM_ENDPOINT", providerName: "intake_custom_endpoint"} + KMSCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_KMS_CUSTOM_ENDPOINT", providerName: "kms_custom_endpoint"} + LoadBalancerCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_LOADBALANCER_CUSTOM_ENDPOINT", providerName: "loadbalancer_custom_endpoint"} + LogMeCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_LOGME_CUSTOM_ENDPOINT", providerName: "logme_custom_endpoint"} + LogsCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_LOGS_CUSTOM_ENDPOINT", providerName: "logs_custom_endpoint"} + MariaDBCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_MARIADB_CUSTOM_ENDPOINT", providerName: "mariadb_custom_endpoint"} + ModelServingCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_MODELSERVING_CUSTOM_ENDPOINT", providerName: "modelserving_custom_endpoint"} + MongoDBFlexCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_MONGODBFLEX_CUSTOM_ENDPOINT", providerName: "mongodbflex_custom_endpoint"} + ObjectStorageCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_OBJECTSTORAGE_CUSTOM_ENDPOINT", providerName: "objectstorage_custom_endpoint"} + ObservabilityCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_OBSERVABILITY_CUSTOM_ENDPOINT", providerName: "observability_custom_endpoint"} + OpenSearchCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_OPENSEARCH_CUSTOM_ENDPOINT", providerName: "opensearch_custom_endpoint"} + PostgresFlexCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_POSTGRESFLEX_CUSTOM_ENDPOINT", providerName: "postgresflex_custom_endpoint"} + RabbitMQCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_RABBITMQ_CUSTOM_ENDPOINT", providerName: "rabbitmq_custom_endpoint"} + RedisCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_REDIS_CUSTOM_ENDPOINT", providerName: "redis_custom_endpoint"} + ResourceManagerCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_RESOURCEMANAGER_CUSTOM_ENDPOINT", providerName: "resourcemanager_custom_endpoint"} + SFSCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SFS_CUSTOM_ENDPOINT", providerName: "sfs_custom_endpoint"} + SKECustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SKE_CUSTOM_ENDPOINT", providerName: "ske_custom_endpoint"} + SQLServerFlexCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SQLSERVERFLEX_CUSTOM_ENDPOINT", providerName: "sqlserverflex_custom_endpoint"} + ScfCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SCF_CUSTOM_ENDPOINT", providerName: "scf_custom_endpoint"} + SecretsManagerCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SECRETSMANAGER_CUSTOM_ENDPOINT", providerName: "secretsmanager_custom_endpoint"} + ServerBackupCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SERVER_BACKUP_CUSTOM_ENDPOINT", providerName: "server_backup_custom_endpoint"} + ServerUpdateCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SERVER_UPDATE_CUSTOM_ENDPOINT", providerName: "server_update_custom_endpoint"} + ServiceAccountCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SERVICE_ACCOUNT_CUSTOM_ENDPOINT", providerName: "service_account_custom_endpoint"} + ServiceEnablementCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_SERVICE_ENABLEMENT_CUSTOM_ENDPOINT", providerName: "service_enablement_custom_endpoint"} + TelemetryLinkCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_TELEMETRYLINK_CUSTOM_ENDPOINT", providerName: "telemetrylink_custom_endpoint"} + TelemetryRouterCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_TELEMETRYROUTER_CUSTOM_ENDPOINT", providerName: "telemetryrouter_custom_endpoint"} + TokenCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_TOKEN_CUSTOM_ENDPOINT", providerName: "token_custom_endpoint"} + VpnCustomEndpoint = customEndpointConfig{envVarName: "TF_ACC_VPN_CUSTOM_ENDPOINT", providerName: "vpn_custom_endpoint"} allCustomEndpoints = []customEndpointConfig{ - ALBCustomEndpoint, ALBCertCustomEndpoint, + ALBCustomEndpoint, AlbWafCustomEndpoint, + AuthorizationCustomEndpoint, CdnCustomEndpoint, DnsCustomEndpoint, EdgeCloudCustomEndpoint, GitCustomEndpoint, IaaSCustomEndpoint, + IntakeCustomEndpoint, KMSCustomEndpoint, LoadBalancerCustomEndpoint, LogMeCustomEndpoint, LogsCustomEndpoint, MariaDBCustomEndpoint, ModelServingCustomEndpoint, - AuthorizationCustomEndpoint, MongoDBFlexCustomEndpoint, - OpenSearchCustomEndpoint, - ObservabilityCustomEndpoint, ObjectStorageCustomEndpoint, + ObservabilityCustomEndpoint, + OpenSearchCustomEndpoint, PostgresFlexCustomEndpoint, RabbitMQCustomEndpoint, RedisCustomEndpoint, ResourceManagerCustomEndpoint, + SFSCustomEndpoint, + SKECustomEndpoint, + SQLServerFlexCustomEndpoint, ScfCustomEndpoint, SecretsManagerCustomEndpoint, - SQLServerFlexCustomEndpoint, ServerBackupCustomEndpoint, ServerUpdateCustomEndpoint, - SFSCustomEndpoint, ServiceAccountCustomEndpoint, + ServiceEnablementCustomEndpoint, + TelemetryLinkCustomEndpoint, + TelemetryRouterCustomEndpoint, TokenCustomEndpoint, VpnCustomEndpoint, - SKECustomEndpoint, - TelemetryRouterCustomEndpoint, - TelemetryLinkCustomEndpoint, } ) @@ -513,3 +518,9 @@ func CheckAttrHasPrefix(prefix string) resource.CheckResourceAttrWithFunc { return nil } } + +func NewTestUnitV6ProviderFactories(clientFactory clientutils.ClientFactory) map[string]func() (tfprotov6.ProviderServer, error) { + return map[string]func() (tfprotov6.ProviderServer, error){ + "stackit": providerserver.NewProtocol6WithError(stackit.NewTestProvider("test-version", clientFactory)()), + } +} diff --git a/stackit/internal/utils/clientutils/clienttestutils.go b/stackit/internal/utils/clientutils/clienttestutils.go new file mode 100644 index 000000000..618861c9b --- /dev/null +++ b/stackit/internal/utils/clientutils/clienttestutils.go @@ -0,0 +1,36 @@ +package clientutils + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/diag" + iaasV2 "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + serviceenablementV2 "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/v2api" + + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" +) + +var _ ClientFactory = &MockClientFactory{} + +type MockClientFactory struct { + defaultClientFactory DefaultClientFactory + + ServiceEnablementV2ClientMock serviceenablementV2.DefaultAPI + IaaSV2ClientMock iaasV2.DefaultAPI +} + +func (m *MockClientFactory) NewServiceEnablementV2Client(ctx context.Context, providerData *core.ProviderData, diags *diag.Diagnostics) serviceenablementV2.DefaultAPI { + if m.ServiceEnablementV2ClientMock != nil { + return m.ServiceEnablementV2ClientMock + } + + return m.defaultClientFactory.NewServiceEnablementV2Client(ctx, providerData, diags) +} + +func (m *MockClientFactory) NewIaaSV2Client(ctx context.Context, providerData *core.ProviderData, diags *diag.Diagnostics) iaasV2.DefaultAPI { + if m.IaaSV2ClientMock != nil { + return m.IaaSV2ClientMock + } + + return m.defaultClientFactory.NewIaaSV2Client(ctx, providerData, diags) +} diff --git a/stackit/internal/utils/clientutils/clientutils.go b/stackit/internal/utils/clientutils/clientutils.go new file mode 100644 index 000000000..dd5857c7a --- /dev/null +++ b/stackit/internal/utils/clientutils/clientutils.go @@ -0,0 +1,60 @@ +package clientutils + +import ( + "context" + "fmt" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/stackitcloud/stackit-sdk-go/core/config" + iaasV2 "github.com/stackitcloud/stackit-sdk-go/services/iaas/v2api" + serviceenablementV2 "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/v2api" + + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils" +) + +type ClientFactory interface { + // methods are having the API versions in them here so we can still mix & match API versions just as we need + + // Service enablement + NewServiceEnablementV2Client(ctx context.Context, providerData *core.ProviderData, diags *diag.Diagnostics) serviceenablementV2.DefaultAPI + + NewIaaSV2Client(ctx context.Context, providerData *core.ProviderData, diags *diag.Diagnostics) iaasV2.DefaultAPI +} + +type DefaultClientFactory struct { +} + +func (f *DefaultClientFactory) NewServiceEnablementV2Client(ctx context.Context, providerData *core.ProviderData, diags *diag.Diagnostics) serviceenablementV2.DefaultAPI { + apiClientConfigOptions := []config.ConfigurationOption{ + config.WithCustomAuth(providerData.RoundTripper), + utils.UserAgentConfigOption(providerData.Version), + } + if providerData.ServiceEnablementCustomEndpoint != "" { + apiClientConfigOptions = append(apiClientConfigOptions, config.WithEndpoint(providerData.ServiceEnablementCustomEndpoint)) + } + apiClient, err := serviceenablementV2.NewAPIClient(apiClientConfigOptions...) + if err != nil { + core.LogAndAddError(ctx, diags, "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 nil + } + + return apiClient.DefaultAPI +} + +func (f *DefaultClientFactory) NewIaaSV2Client(ctx context.Context, providerData *core.ProviderData, diags *diag.Diagnostics) iaasV2.DefaultAPI { + apiClientConfigOptions := []config.ConfigurationOption{ + config.WithCustomAuth(providerData.RoundTripper), + utils.UserAgentConfigOption(providerData.Version), + } + if providerData.IaaSCustomEndpoint != "" { + apiClientConfigOptions = append(apiClientConfigOptions, config.WithEndpoint(providerData.IaaSCustomEndpoint)) + } + apiClient, err := iaasV2.NewAPIClient(apiClientConfigOptions...) + if err != nil { + core.LogAndAddError(ctx, diags, "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 nil + } + + return apiClient.DefaultAPI +} diff --git a/stackit/internal/utils/clientutils/clientutils_test.go b/stackit/internal/utils/clientutils/clientutils_test.go new file mode 100644 index 000000000..e5a4e539f --- /dev/null +++ b/stackit/internal/utils/clientutils/clientutils_test.go @@ -0,0 +1,35 @@ +package clientutils + +import ( + "context" + "reflect" + "testing" + + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/stackitcloud/stackit-sdk-go/services/serviceenablement/v2api" + + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/core" +) + +func TestDefaultClientFactory_NewServiceEnablementV2Client(t *testing.T) { + type args struct { + ctx context.Context + providerData *core.ProviderData + diags *diag.Diagnostics + } + tests := []struct { + name string + args args + want v2api.DefaultAPI + }{ + // TODO: Add test cases. + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + f := &DefaultClientFactory{} + if got := f.NewServiceEnablementV2Client(tt.args.ctx, tt.args.providerData, tt.args.diags); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewServiceEnablementV2Client() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/stackit/provider.go b/stackit/provider.go index 3a88d9dc4..8cb945c0e 100644 --- a/stackit/provider.go +++ b/stackit/provider.go @@ -19,6 +19,8 @@ import ( "github.com/stackitcloud/stackit-sdk-go/core/config" "github.com/stackitcloud/stackit-sdk-go/core/oidcadapters" + "github.com/stackitcloud/terraform-provider-stackit/stackit/internal/utils/clientutils" + "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/services/access_token" @@ -150,14 +152,25 @@ var ( // Provider is the provider implementation. type Provider struct { - version string + version string + clientFactory clientutils.ClientFactory } // New is a helper function to simplify provider server and testing implementation. func New(version string) func() provider.Provider { return func() provider.Provider { return &Provider{ - version: version, + version: version, + clientFactory: &clientutils.DefaultClientFactory{}, + } + } +} + +func NewTestProvider(version string, clientFactory clientutils.ClientFactory) func() provider.Provider { + return func() provider.Provider { + return &Provider{ + version: version, + clientFactory: clientFactory, } } } @@ -698,26 +711,7 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource iaasAlphaVpcNetworkRange.NewVpcNetworkRangeDatasource, iaasAlphaVpcRegion.NewVPCRegionDatasource, iaasAlphaVpcStaticRoute.NewStaticRouteDatasource, - iaasAffinityGroup.NewAffinityGroupDatasource, - iaasImage.NewImageDataSource, - iaasImageV2.NewImageV2DataSource, - iaasNetwork.NewNetworkDataSource, - iaasNetworkArea.NewNetworkAreaDataSource, - iaasNetworkAreaRegion.NewNetworkAreaRegionDataSource, - iaasNetworkAreaRoute.NewNetworkAreaRouteDataSource, - iaasNetworkInterface.NewNetworkInterfaceDataSource, - iaasVolume.NewVolumeDataSource, iaasProject.NewProjectDataSource, - iaasPublicIp.NewPublicIpDataSource, - iaasPublicIpRanges.NewPublicIpRangesDataSource, - iaasKeyPair.NewKeyPairDataSource, - iaasServer.NewServerDataSource, - iaasSecurityGroup.NewSecurityGroupDataSource, - iaasRoutingTable.NewRoutingTableDataSource, - iaasRoutingTableRoute.NewRoutingTableRouteDataSource, - iaasRoutingTables.NewRoutingTablesDataSource, - iaasRoutingTableRoutes.NewRoutingTableRoutesDataSource, - iaasSecurityGroupRule.NewSecurityGroupRuleDataSource, intakeRunner.NewRunnerDataSource, kmsKey.NewKeyDataSource, kmsKeyRing.NewKeyRingDataSource, @@ -788,6 +782,36 @@ func (p *Provider) DataSources(_ context.Context) []func() datasource.DataSource dataSources = append(dataSources, customRole.NewCustomRoleDataSources()...) dataSources = append(dataSources, iamRoleBindingsV1.NewRoleBindingsDatasources()...) + // client factory approach + refactoredDatasources := []func(factory clientutils.ClientFactory) datasource.DataSource{ + iaasAffinityGroup.NewAffinityGroupDatasource, + iaasImage.NewImageDataSource, + iaasImageV2.NewImageV2DataSource, + iaasNetwork.NewNetworkDataSource, + iaasNetworkArea.NewNetworkAreaDataSource, + iaasNetworkAreaRegion.NewNetworkAreaRegionDataSource, + iaasNetworkAreaRoute.NewNetworkAreaRouteDataSource, + iaasNetworkInterface.NewNetworkInterfaceDataSource, + iaasPublicIp.NewPublicIpDataSource, + iaasPublicIpRanges.NewPublicIpRangesDataSource, + iaasKeyPair.NewKeyPairDataSource, + iaasServer.NewServerDataSource, + iaasSecurityGroup.NewSecurityGroupDataSource, + iaasRoutingTable.NewRoutingTableDataSource, + iaasRoutingTableRoute.NewRoutingTableRouteDataSource, + iaasRoutingTables.NewRoutingTablesDataSource, + iaasRoutingTableRoutes.NewRoutingTableRoutesDataSource, + iaasSecurityGroupRule.NewSecurityGroupRuleDataSource, + iaasVolume.NewVolumeDataSource, + } + + // won't be needed after refactoring is completed + for _, d := range refactoredDatasources { + dataSources = append(dataSources, func() datasource.DataSource { + return d(p.clientFactory) + }) + } + return dataSources } @@ -813,25 +837,6 @@ func (p *Provider) Resources(_ context.Context) []func() resource.Resource { iaasAlphaVpcNetworkRange.NewVpcNetworkRangeResource, iaasAlphaVpcRegion.NewVPCRegion, iaasAlphaVpcStaticRoute.NewStaticRouteResource, - iaasAffinityGroup.NewAffinityGroupResource, - iaasImage.NewImageResource, - iaasNetwork.NewNetworkResource, - iaasNetworkArea.NewNetworkAreaResource, - iaasNetworkAreaRegion.NewNetworkAreaRegionResource, - iaasNetworkAreaRoute.NewNetworkAreaRouteResource, - iaasNetworkInterface.NewNetworkInterfaceResource, - iaasVolume.NewVolumeResource, - iaasPublicIp.NewPublicIpResource, - iaasKeyPair.NewKeyPairResource, - iaasVolumeAttach.NewVolumeAttachResource, - iaasNetworkInterfaceAttach.NewNetworkInterfaceAttachResource, - iaasServiceAccountAttach.NewServiceAccountAttachResource, - iaasPublicIpAssociate.NewPublicIpAssociateResource, - iaasServer.NewServerResource, - iaasSecurityGroup.NewSecurityGroupResource, - iaasSecurityGroupRule.NewSecurityGroupRuleResource, - iaasRoutingTable.NewRoutingTableResource, - iaasRoutingTableRoute.NewRoutingTableRouteResource, intakeRunner.NewRunnerResource, kmsKey.NewKeyResource, kmsKeyRing.NewKeyRingResource, @@ -898,6 +903,36 @@ func (p *Provider) Resources(_ context.Context) []func() resource.Resource { resources = append(resources, customRole.NewCustomRoleResources()...) resources = append(resources, iamRoleBindingsV1.NewRoleBindingResources()...) + // client factory approach + refactoredResources := []func(factory clientutils.ClientFactory) resource.Resource{ + iaasAffinityGroup.NewAffinityGroupResource, + iaasImage.NewImageResource, + iaasNetwork.NewNetworkResource, + iaasNetworkArea.NewNetworkAreaResource, + iaasNetworkAreaRegion.NewNetworkAreaRegionResource, + iaasNetworkAreaRoute.NewNetworkAreaRouteResource, + iaasNetworkInterface.NewNetworkInterfaceResource, + iaasPublicIp.NewPublicIpResource, + iaasKeyPair.NewKeyPairResource, + iaasVolumeAttach.NewVolumeAttachResource, + iaasNetworkInterfaceAttach.NewNetworkInterfaceAttachResource, + iaasServiceAccountAttach.NewServiceAccountAttachResource, + iaasPublicIpAssociate.NewPublicIpAssociateResource, + iaasServer.NewServerResource, + iaasSecurityGroup.NewSecurityGroupResource, + iaasSecurityGroupRule.NewSecurityGroupRuleResource, + iaasRoutingTable.NewRoutingTableResource, + iaasRoutingTableRoute.NewRoutingTableRouteResource, + iaasVolume.NewVolumeResource, + } + + // won't be needed after refactoring + for _, r := range refactoredResources { + resources = append(resources, func() resource.Resource { + return r(p.clientFactory) + }) + } + return resources }