diff --git a/client/client.go b/client/client.go index 608b778..fb657ca 100644 --- a/client/client.go +++ b/client/client.go @@ -44,6 +44,7 @@ type endpoints struct { TagDefinitions *url.URL `json:"meshtagdefinitions"` LandingZones *url.URL `json:"meshlandingzones"` Platforms *url.URL `json:"meshplatforms"` + PaymentMethods *url.URL `json:"meshpaymentmethods"` } type loginRequest struct { @@ -80,6 +81,7 @@ func NewClient(rootUrl *url.URL, apiKey string, apiSecret string) (*MeshStackPro TagDefinitions: rootUrl.JoinPath(apiMeshObjectsRoot, "meshtagdefinitions"), LandingZones: rootUrl.JoinPath(apiMeshObjectsRoot, "meshlandingzones"), Platforms: rootUrl.JoinPath(apiMeshObjectsRoot, "meshplatforms"), + PaymentMethods: rootUrl.JoinPath(apiMeshObjectsRoot, "meshpaymentmethods"), } return client, nil diff --git a/client/payment_method.go b/client/payment_method.go new file mode 100644 index 0000000..1555fa5 --- /dev/null +++ b/client/payment_method.go @@ -0,0 +1,169 @@ +package client + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + "net/http" + "net/url" +) + +const CONTENT_TYPE_PAYMENT_METHOD = "application/vnd.meshcloud.api.meshpaymentmethod.v2.hal+json" + +type MeshPaymentMethod struct { + ApiVersion string `json:"apiVersion" tfsdk:"api_version"` + Kind string `json:"kind" tfsdk:"kind"` + Metadata MeshPaymentMethodMetadata `json:"metadata" tfsdk:"metadata"` + Spec MeshPaymentMethodSpec `json:"spec" tfsdk:"spec"` +} + +type MeshPaymentMethodMetadata struct { + Name string `json:"name" tfsdk:"name"` + OwnedByWorkspace string `json:"ownedByWorkspace" tfsdk:"owned_by_workspace"` + CreatedOn string `json:"createdOn" tfsdk:"created_on"` + DeletedOn *string `json:"deletedOn" tfsdk:"deleted_on"` +} + +type MeshPaymentMethodSpec struct { + DisplayName string `json:"displayName" tfsdk:"display_name"` + ExpirationDate *string `json:"expirationDate,omitempty" tfsdk:"expiration_date"` + Amount *int64 `json:"amount,omitempty" tfsdk:"amount"` + Tags map[string][]string `json:"tags,omitempty" tfsdk:"tags"` +} + +type MeshPaymentMethodCreate struct { + ApiVersion string `json:"apiVersion" tfsdk:"api_version"` + Metadata MeshPaymentMethodCreateMetadata `json:"metadata" tfsdk:"metadata"` + Spec MeshPaymentMethodSpec `json:"spec" tfsdk:"spec"` +} + +type MeshPaymentMethodCreateMetadata struct { + Name string `json:"name" tfsdk:"name"` + OwnedByWorkspace string `json:"ownedByWorkspace" tfsdk:"owned_by_workspace"` +} + +func (c *MeshStackProviderClient) urlForPaymentMethod(identifier string) *url.URL { + return c.endpoints.PaymentMethods.JoinPath(identifier) +} + +func (c *MeshStackProviderClient) ReadPaymentMethod(workspace string, identifier string) (*MeshPaymentMethod, error) { + targetUrl := c.urlForPaymentMethod(identifier) + + req, err := http.NewRequest("GET", targetUrl.String(), nil) + if err != nil { + return nil, err + } + req.Header.Set("Accept", CONTENT_TYPE_PAYMENT_METHOD) + + res, err := c.doAuthenticatedRequest(req) + if err != nil { + return nil, err + } + + defer res.Body.Close() + + if res.StatusCode == http.StatusNotFound { + return nil, nil + } + + data, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + if !isSuccessHTTPStatus(res) { + return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data) + } + + var paymentMethod MeshPaymentMethod + err = json.Unmarshal(data, &paymentMethod) + if err != nil { + return nil, err + } + + return &paymentMethod, nil +} + +func (c *MeshStackProviderClient) CreatePaymentMethod(paymentMethod *MeshPaymentMethodCreate) (*MeshPaymentMethod, error) { + payload, err := json.Marshal(paymentMethod) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", c.endpoints.PaymentMethods.String(), bytes.NewBuffer(payload)) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", CONTENT_TYPE_PAYMENT_METHOD) + req.Header.Set("Accept", CONTENT_TYPE_PAYMENT_METHOD) + + res, err := c.doAuthenticatedRequest(req) + if err != nil { + return nil, err + } + + defer res.Body.Close() + + data, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + if !isSuccessHTTPStatus(res) { + return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data) + } + + var createdPaymentMethod MeshPaymentMethod + err = json.Unmarshal(data, &createdPaymentMethod) + if err != nil { + return nil, err + } + + return &createdPaymentMethod, nil +} + +func (c *MeshStackProviderClient) UpdatePaymentMethod(identifier string, paymentMethod *MeshPaymentMethodCreate) (*MeshPaymentMethod, error) { + targetUrl := c.urlForPaymentMethod(identifier) + + payload, err := json.Marshal(paymentMethod) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("PUT", targetUrl.String(), bytes.NewBuffer(payload)) + if err != nil { + return nil, err + } + req.Header.Set("Content-Type", CONTENT_TYPE_PAYMENT_METHOD) + req.Header.Set("Accept", CONTENT_TYPE_PAYMENT_METHOD) + + res, err := c.doAuthenticatedRequest(req) + if err != nil { + return nil, err + } + + defer res.Body.Close() + + data, err := io.ReadAll(res.Body) + if err != nil { + return nil, err + } + + if !isSuccessHTTPStatus(res) { + return nil, fmt.Errorf("unexpected status code: %d, %s", res.StatusCode, data) + } + + var updatedPaymentMethod MeshPaymentMethod + err = json.Unmarshal(data, &updatedPaymentMethod) + if err != nil { + return nil, err + } + + return &updatedPaymentMethod, nil +} + +func (c *MeshStackProviderClient) DeletePaymentMethod(identifier string) error { + targetUrl := c.urlForPaymentMethod(identifier) + return c.deleteMeshObject(*targetUrl, 204) +} diff --git a/docs/data-sources/payment_method.md b/docs/data-sources/payment_method.md new file mode 100644 index 0000000..34dedc4 --- /dev/null +++ b/docs/data-sources/payment_method.md @@ -0,0 +1,59 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "meshstack_payment_method Data Source - terraform-provider-meshstack" +subcategory: "" +description: |- + Read a single payment method by workspace and identifier. +--- + +# meshstack_payment_method (Data Source) + +Read a single payment method by workspace and identifier. + +## Example Usage + +```terraform +data "meshstack_payment_method" "example" { + metadata = { + name = "my-payment-method" + owned_by_workspace = "my-workspace-identifier" + } +} +``` + + +## Schema + +### Required + +- `metadata` (Attributes) (see [below for nested schema](#nestedatt--metadata)) + +### Read-Only + +- `api_version` (String) Payment method API version. +- `kind` (String) meshObject type, always `meshPaymentMethod`. +- `spec` (Attributes) (see [below for nested schema](#nestedatt--spec)) + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Payment method identifier. +- `owned_by_workspace` (String) Identifier of the workspace that owns this payment method. + +Read-Only: + +- `created_on` (String) Creation date of the payment method. +- `deleted_on` (String) Deletion date of the payment method. + + + +### Nested Schema for `spec` + +Read-Only: + +- `amount` (Number) Amount associated with the payment method. +- `display_name` (String) Display name of the payment method. +- `expiration_date` (String) Expiration date of the payment method (ISO 8601 format). +- `tags` (Map of List of String) Tags of the payment method. diff --git a/docs/resources/payment_method.md b/docs/resources/payment_method.md new file mode 100644 index 0000000..05949cc --- /dev/null +++ b/docs/resources/payment_method.md @@ -0,0 +1,93 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "meshstack_payment_method Resource - terraform-provider-meshstack" +subcategory: "" +description: |- + Represents a meshStack payment method. + ~> Note: Managing payment methods requires an API key with sufficient admin permissions. +--- + +# meshstack_payment_method (Resource) + +Represents a meshStack payment method. + +~> **Note:** Managing payment methods requires an API key with sufficient admin permissions. + +## Example Usage + +```terraform +data "meshstack_workspace" "example" { + metadata = { + name = "my-workspace-identifier" + } +} + +resource "meshstack_payment_method" "example" { + metadata = { + name = "my-payment-method" + owned_by_workspace = data.meshstack_workspace.example.metadata.name + } + + spec = { + display_name = "My Payment Method" + expiration_date = "2025-12-31" + amount = 10000 + tags = { + CostCenter = ["0000"] + Type = ["production"] + } + } +} +``` + + +## Schema + +### Required + +- `metadata` (Attributes) (see [below for nested schema](#nestedatt--metadata)) +- `spec` (Attributes) (see [below for nested schema](#nestedatt--spec)) + +### Read-Only + +- `api_version` (String) Payment method datatype version +- `kind` (String) meshObject type, always `meshPaymentMethod`. + + +### Nested Schema for `metadata` + +Required: + +- `name` (String) Payment method identifier. +- `owned_by_workspace` (String) Identifier of the workspace that owns this payment method. + +Read-Only: + +- `created_on` (String) Creation date of the payment method. +- `deleted_on` (String) Deletion date of the payment method. + + + +### Nested Schema for `spec` + +Required: + +- `display_name` (String) Display name of the payment method. + +Optional: + +- `amount` (Number) Amount associated with the payment method. +- `expiration_date` (String) Expiration date of the payment method (ISO 8601 format). +- `tags` (Map of List of String) Tags of the payment method. + +## Import + +Import is supported using the following syntax: + +The [`terraform import` command](https://developer.hashicorp.com/terraform/cli/commands/import) can be used, for example: + +```shell +#!/bin/bash +# import via workspace and payment method identifier . +terraform import 'meshstack_payment_method.example' 'my-workspace-identifier.my-payment-method' +``` diff --git a/examples/data-sources/meshstack_payment_method/data-source.tf b/examples/data-sources/meshstack_payment_method/data-source.tf new file mode 100644 index 0000000..c3d9077 --- /dev/null +++ b/examples/data-sources/meshstack_payment_method/data-source.tf @@ -0,0 +1,6 @@ +data "meshstack_payment_method" "example" { + metadata = { + name = "my-payment-method" + owned_by_workspace = "my-workspace-identifier" + } +} diff --git a/examples/resources/meshstack_payment_method/import.sh b/examples/resources/meshstack_payment_method/import.sh new file mode 100644 index 0000000..8ff9b2e --- /dev/null +++ b/examples/resources/meshstack_payment_method/import.sh @@ -0,0 +1,3 @@ +#!/bin/bash +# import via workspace and payment method identifier . +terraform import 'meshstack_payment_method.example' 'my-workspace-identifier.my-payment-method' diff --git a/examples/resources/meshstack_payment_method/resource.tf b/examples/resources/meshstack_payment_method/resource.tf new file mode 100644 index 0000000..2cf5987 --- /dev/null +++ b/examples/resources/meshstack_payment_method/resource.tf @@ -0,0 +1,22 @@ +data "meshstack_workspace" "example" { + metadata = { + name = "my-workspace-identifier" + } +} + +resource "meshstack_payment_method" "example" { + metadata = { + name = "my-payment-method" + owned_by_workspace = data.meshstack_workspace.example.metadata.name + } + + spec = { + display_name = "My Payment Method" + expiration_date = "2025-12-31" + amount = 10000 + tags = { + CostCenter = ["0000"] + Type = ["production"] + } + } +} diff --git a/internal/provider/payment_method_data_source.go b/internal/provider/payment_method_data_source.go new file mode 100644 index 0000000..84731e1 --- /dev/null +++ b/internal/provider/payment_method_data_source.go @@ -0,0 +1,147 @@ +package provider + +import ( + "context" + "fmt" + + "github.com/meshcloud/terraform-provider-meshstack/client" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +var ( + _ datasource.DataSource = &paymentMethodDataSource{} + _ datasource.DataSourceWithConfigure = &paymentMethodDataSource{} +) + +func NewPaymentMethodDataSource() datasource.DataSource { + return &paymentMethodDataSource{} +} + +type paymentMethodDataSource struct { + client *client.MeshStackProviderClient +} + +func (d *paymentMethodDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_payment_method" +} + +func (d *paymentMethodDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Read a single payment method by workspace and identifier.", + + Attributes: map[string]schema.Attribute{ + "api_version": schema.StringAttribute{ + MarkdownDescription: "Payment method API version.", + Computed: true, + }, + "kind": schema.StringAttribute{ + MarkdownDescription: "meshObject type, always `meshPaymentMethod`.", + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf([]string{"meshPaymentMethod"}...), + }, + }, + + "metadata": schema.SingleNestedAttribute{ + Required: true, + Attributes: map[string]schema.Attribute{ + "name": schema.StringAttribute{ + MarkdownDescription: "Payment method identifier.", + Required: true, + }, + "owned_by_workspace": schema.StringAttribute{ + MarkdownDescription: "Identifier of the workspace that owns this payment method.", + Required: true, + }, + "created_on": schema.StringAttribute{ + MarkdownDescription: "Creation date of the payment method.", + Computed: true, + }, + "deleted_on": schema.StringAttribute{ + MarkdownDescription: "Deletion date of the payment method.", + Computed: true, + }, + }, + }, + + "spec": schema.SingleNestedAttribute{ + Computed: true, + Attributes: map[string]schema.Attribute{ + "display_name": schema.StringAttribute{ + MarkdownDescription: "Display name of the payment method.", + Computed: true, + }, + "expiration_date": schema.StringAttribute{ + MarkdownDescription: "Expiration date of the payment method (ISO 8601 format).", + Computed: true, + }, + "amount": schema.Int64Attribute{ + MarkdownDescription: "Amount associated with the payment method.", + Computed: true, + }, + "tags": schema.MapAttribute{ + MarkdownDescription: "Tags of the payment method.", + ElementType: types.ListType{ElemType: types.StringType}, + Computed: true, + }, + }, + }, + }, + } +} + +func (d *paymentMethodDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*client.MeshStackProviderClient) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *client.MeshStackProviderClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + d.client = client +} + +func (d *paymentMethodDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + var workspace, name string + + resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("metadata").AtName("owned_by_workspace"), &workspace)...) + resp.Diagnostics.Append(req.Config.GetAttribute(ctx, path.Root("metadata").AtName("name"), &name)...) + + if resp.Diagnostics.HasError() { + return + } + + paymentMethod, err := d.client.ReadPaymentMethod(workspace, name) + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Could not read payment method '%s' in workspace '%s'", name, workspace), + err.Error(), + ) + return + } + + if paymentMethod == nil { + resp.Diagnostics.AddError( + "Payment method not found", + fmt.Sprintf("The requested payment method '%s' in workspace '%s' was not found.", name, workspace), + ) + return + } + + if paymentMethod.Spec.Tags == nil { + paymentMethod.Spec.Tags = make(map[string][]string) + } + + resp.Diagnostics.Append(resp.State.Set(ctx, paymentMethod)...) +} diff --git a/internal/provider/payment_method_resource.go b/internal/provider/payment_method_resource.go new file mode 100644 index 0000000..d747d99 --- /dev/null +++ b/internal/provider/payment_method_resource.go @@ -0,0 +1,272 @@ +package provider + +import ( + "context" + "fmt" + "regexp" + "strings" + + "github.com/meshcloud/terraform-provider-meshstack/client" + + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/mapdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringdefault" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +var ( + _ resource.Resource = &paymentMethodResource{} + _ resource.ResourceWithConfigure = &paymentMethodResource{} + _ resource.ResourceWithImportState = &paymentMethodResource{} +) + +func NewPaymentMethodResource() resource.Resource { + return &paymentMethodResource{} +} + +type paymentMethodResource struct { + client *client.MeshStackProviderClient +} + +func (r *paymentMethodResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_payment_method" +} + +func (r *paymentMethodResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + client, ok := req.ProviderData.(*client.MeshStackProviderClient) + + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *MeshStackProviderClient, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + r.client = client +} + +func (r *paymentMethodResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + MarkdownDescription: "Represents a meshStack payment method.\n\n~> **Note:** Managing payment methods requires an API key with sufficient admin permissions.", + + Attributes: map[string]schema.Attribute{ + "api_version": schema.StringAttribute{ + MarkdownDescription: "Payment method datatype version", + Computed: true, + Default: stringdefault.StaticString("v2"), + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, + "kind": schema.StringAttribute{ + MarkdownDescription: "meshObject type, always `meshPaymentMethod`.", + Computed: true, + Validators: []validator.String{ + stringvalidator.OneOf([]string{"meshPaymentMethod"}...), + }, + }, + + "metadata": schema.SingleNestedAttribute{ + Required: true, + Attributes: map[string]schema.Attribute{ + "name": schema.StringAttribute{ + MarkdownDescription: "Payment method identifier.", + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + Validators: []validator.String{ + stringvalidator.RegexMatches( + regexp.MustCompile(`^[a-z0-9]+(-[a-z0-9]+)*$`), + "must be alphanumeric with dashes, must be lowercase, and have no leading, trailing or consecutive dashes", + ), + }, + }, + "owned_by_workspace": schema.StringAttribute{ + MarkdownDescription: "Identifier of the workspace that owns this payment method.", + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "created_on": schema.StringAttribute{ + MarkdownDescription: "Creation date of the payment method.", + Computed: true, + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, + "deleted_on": schema.StringAttribute{ + MarkdownDescription: "Deletion date of the payment method.", + Computed: true, + PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()}, + }, + }, + }, + + "spec": schema.SingleNestedAttribute{ + Required: true, + Attributes: map[string]schema.Attribute{ + "display_name": schema.StringAttribute{ + MarkdownDescription: "Display name of the payment method.", + Required: true, + }, + "expiration_date": schema.StringAttribute{ + MarkdownDescription: "Expiration date of the payment method (ISO 8601 format).", + Optional: true, + }, + "amount": schema.Int64Attribute{ + MarkdownDescription: "Amount associated with the payment method.", + Optional: true, + }, + "tags": schema.MapAttribute{ + MarkdownDescription: "Tags of the payment method.", + ElementType: types.ListType{ElemType: types.StringType}, + Optional: true, + Computed: true, + Default: mapdefault.StaticValue(types.MapValueMust(types.ListType{ElemType: types.StringType}, map[string]attr.Value{})), + }, + }, + }, + }, + } +} + +func (r *paymentMethodResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + paymentMethod := client.MeshPaymentMethodCreate{ + Metadata: client.MeshPaymentMethodCreateMetadata{}, + } + + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("api_version"), &paymentMethod.ApiVersion)...) + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("spec"), &paymentMethod.Spec)...) + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("metadata").AtName("name"), &paymentMethod.Metadata.Name)...) + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("metadata").AtName("owned_by_workspace"), &paymentMethod.Metadata.OwnedByWorkspace)...) + + if resp.Diagnostics.HasError() { + return + } + + createdPaymentMethod, err := r.client.CreatePaymentMethod(&paymentMethod) + if err != nil { + resp.Diagnostics.AddError( + "Error Creating Payment Method", + "Could not create payment method, unexpected error: "+err.Error(), + ) + return + } + + if createdPaymentMethod.Spec.Tags == nil { + createdPaymentMethod.Spec.Tags = make(map[string][]string) + } + + resp.Diagnostics.Append(resp.State.Set(ctx, createdPaymentMethod)...) +} + +func (r *paymentMethodResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var workspace, name string + + resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("metadata").AtName("owned_by_workspace"), &workspace)...) + resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("metadata").AtName("name"), &name)...) + + if resp.Diagnostics.HasError() { + return + } + + paymentMethod, err := r.client.ReadPaymentMethod(workspace, name) + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Could not read payment method '%s' in workspace '%s'", name, workspace), + err.Error(), + ) + return + } + + if paymentMethod == nil { + resp.State.RemoveResource(ctx) + return + } + + if paymentMethod.Spec.Tags == nil { + paymentMethod.Spec.Tags = make(map[string][]string) + } + + resp.Diagnostics.Append(resp.State.Set(ctx, paymentMethod)...) +} + +func (r *paymentMethodResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) { + paymentMethod := client.MeshPaymentMethodCreate{ + Metadata: client.MeshPaymentMethodCreateMetadata{}, + } + + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("api_version"), &paymentMethod.ApiVersion)...) + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("spec"), &paymentMethod.Spec)...) + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("metadata").AtName("name"), &paymentMethod.Metadata.Name)...) + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("metadata").AtName("owned_by_workspace"), &paymentMethod.Metadata.OwnedByWorkspace)...) + resp.Diagnostics.Append(req.Plan.GetAttribute(ctx, path.Root("spec").AtName("tags"), &paymentMethod.Spec.Tags)...) + + if resp.Diagnostics.HasError() { + return + } + + updatedPaymentMethod, err := r.client.UpdatePaymentMethod(paymentMethod.Metadata.Name, &paymentMethod) + if err != nil { + resp.Diagnostics.AddError( + "Error Updating Payment Method", + "Could not update payment method, unexpected error: "+err.Error(), + ) + return + } + + if updatedPaymentMethod.Spec.Tags == nil { + updatedPaymentMethod.Spec.Tags = make(map[string][]string) + } + + resp.Diagnostics.Append(resp.State.Set(ctx, updatedPaymentMethod)...) +} + +func (r *paymentMethodResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var workspace, name string + + resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("metadata").AtName("owned_by_workspace"), &workspace)...) + resp.Diagnostics.Append(req.State.GetAttribute(ctx, path.Root("metadata").AtName("name"), &name)...) + + if resp.Diagnostics.HasError() { + return + } + + err := r.client.DeletePaymentMethod(name) + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Could not delete payment method '%s' in workspace '%s'", name, workspace), + err.Error(), + ) + return + } +} + +func (r *paymentMethodResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + identifier := strings.Split(req.ID, ".") + + if len(identifier) != 2 { + resp.Diagnostics.AddError( + "Unexpected Import Identifier", + fmt.Sprintf("Expected import identifier with format: workspace.payment-method-identifier Got: %q", req.ID), + ) + return + } + + workspace := identifier[0] + paymentMethodName := identifier[1] + + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("metadata").AtName("owned_by_workspace"), workspace)...) + resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root("metadata").AtName("name"), paymentMethodName)...) +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 669b935..da9473c 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -125,6 +125,7 @@ func (p *MeshStackProvider) Resources(ctx context.Context) []func() resource.Res NewTagDefinitionResource, NewLandingZoneResource, NewPlatformResource, + NewPaymentMethodResource, } } @@ -143,6 +144,7 @@ func (p *MeshStackProvider) DataSources(ctx context.Context) []func() datasource NewTenantV4DataSource, NewLandingZoneDataSource, NewPlatformDataSource, + NewPaymentMethodDataSource, } }