From d47d1a5f7bee19cf7879c96756a42df43a7006bf Mon Sep 17 00:00:00 2001 From: srushti-patl Date: Mon, 3 Feb 2025 22:42:42 -0800 Subject: [PATCH 1/8] feat: Adding Route Aggregation Policy Resource and Data Source --- docs/data-sources/fabric_route_aggregation.md | 95 ++++++ .../data-sources/fabric_route_aggregations.md | 146 +++++++++ docs/resources/fabric_route_aggregation.md | 92 ++++++ .../data-source.tf | 23 ++ .../data-source.tf | 27 ++ .../resource.tf | 8 + internal/provider/services/fabric.go | 4 + .../datasource_all_aggregations.go | 129 ++++++++ .../datasource_by_routeAggregationId.go | 58 ++++ .../route_aggregation/datasource_schema.go | 256 +++++++++++++++ .../route_aggregation/datasource_test.go | 98 ++++++ .../fabric/route_aggregation/resource.go | 301 ++++++++++++++++++ .../route_aggregation/resource_schema.go | 151 +++++++++ .../fabric/route_aggregation/resource_test.go | 100 ++++++ .../fabric/route_aggregation/sweeper.go | 79 +++++ internal/sweep/sweep_test.go | 2 + 16 files changed, 1569 insertions(+) create mode 100644 docs/data-sources/fabric_route_aggregation.md create mode 100644 docs/data-sources/fabric_route_aggregations.md create mode 100644 docs/resources/fabric_route_aggregation.md create mode 100644 examples/data-sources/equinix_fabric_route_aggregation/data-source.tf create mode 100644 examples/data-sources/equinix_fabric_route_aggregations/data-source.tf create mode 100644 examples/resources/equinix_fabric_route_aggregation/resource.tf create mode 100644 internal/resources/fabric/route_aggregation/datasource_all_aggregations.go create mode 100644 internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go create mode 100644 internal/resources/fabric/route_aggregation/datasource_schema.go create mode 100644 internal/resources/fabric/route_aggregation/datasource_test.go create mode 100644 internal/resources/fabric/route_aggregation/resource.go create mode 100644 internal/resources/fabric/route_aggregation/resource_schema.go create mode 100644 internal/resources/fabric/route_aggregation/resource_test.go create mode 100644 internal/resources/fabric/route_aggregation/sweeper.go diff --git a/docs/data-sources/fabric_route_aggregation.md b/docs/data-sources/fabric_route_aggregation.md new file mode 100644 index 000000000..6064fa191 --- /dev/null +++ b/docs/data-sources/fabric_route_aggregation.md @@ -0,0 +1,95 @@ +--- +subcategory: "Fabric" +--- + +# equinix_fabric_route_aggregation (Data Source) + +Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Stream by UUID +Additional Documentation: +* API: https://developer.equinix.com/catalog/fabricv4#tag/Route-Aggregations + +## Example Usage + +```terraform +data "equinix_fabric_route_aggregation" "ra_policy" { + uuid = "" +} + +output "id" { + value = data.equinix_fabric_route_aggregation.ra_policy.id +} + +output "type" { + value = data.equinix_fabric_route_aggregation.ra_policy.type +} + +output "state" { + value = data.equinix_fabric_route_aggregation.ra_policy.state +} + +output "connections_count" { + value = data.equinix_fabric_route_aggregation.ra_policy.connections_count +} + +output "rules_count" { + value = data.equinix_fabric_route_aggregation.ra_policy.rules_count +} +``` + + +## Schema + +### Required + +- `route_aggregation_id` (String) The uuid of the route aggregation this data source should retrieve + +### Read-Only + +- `change` (Attributes) Current state of latest Route Aggregation change (see [below for nested schema](#nestedatt--change)) +- `change_log` (Attributes) Details of the last change on the stream resource (see [below for nested schema](#nestedatt--change_log)) +- `connections_count` (Number) Number of Connections attached to route aggregation +- `description` (String) Customer-provided route aggregation description +- `href` (String) Equinix auto generated URI to the route aggregation resource +- `id` (String) The unique identifier of the resource +- `name` (String) Customer provided name of the route aggregation +- `project` (Attributes) Equinix Project attribute object (see [below for nested schema](#nestedatt--project)) +- `rules_count` (Number) Number of Rules attached to route aggregation +- `state` (String) Value representing provisioning status for the route aggregation resource +- `type` (String) Equinix defined Route Aggregation Type; BGP_IPv4_PREFIX_AGGREGATION, BGP_IPv6_PREFIX_AGGREGATION +- `uuid` (String) Equinix-assigned unique id for the route aggregation resource + + +### Nested Schema for `change` + +Read-Only: + +- `href` (String) Equinix auto generated URI to the route aggregation change +- `type` (String) Equinix defined Route Aggregation Change Type +- `uuid` (String) Equinix-assigned unique id for a change + + + +### Nested Schema for `change_log` + +Read-Only: + +- `created_by` (String) User name of creator of the stream resource +- `created_by_email` (String) Email of creator of the stream resource +- `created_by_full_name` (String) Legal name of creator of the stream resource +- `created_date_time` (String) Creation time of the stream resource +- `deleted_by` (String) User name of deleter of the stream resource +- `deleted_by_email` (String) Email of deleter of the stream resource +- `deleted_by_full_name` (String) Legal name of deleter of the stream resource +- `deleted_date_time` (String) Deletion time of the stream resource +- `updated_by` (String) User name of last updater of the stream resource +- `updated_by_email` (String) Email of last updater of the stream resource +- `updated_by_full_name` (String) Legal name of last updater of the stream resource +- `updated_date_time` (String) Last update time of the stream resource + + + +### Nested Schema for `project` + +Read-Only: + +- `project_id` (String) Equinix Subscriber-assigned project ID diff --git a/docs/data-sources/fabric_route_aggregations.md b/docs/data-sources/fabric_route_aggregations.md new file mode 100644 index 000000000..0b49a654a --- /dev/null +++ b/docs/data-sources/fabric_route_aggregations.md @@ -0,0 +1,146 @@ +--- +subcategory: "Fabric" +--- + +# equinix_fabric_route_aggregations (Data Source) + +Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Streams with pagination details +Additional Documentation: +* Getting Started: https://docs.equinix.com/en-us/Content/KnowledgeCenter/Fabric/GettingStarted/Integrating-with-Fabric-V4-APIs/IntegrateWithSink.htm +* API: https://developer.equinix.com/catalog/fabricv4#tag/Streams + +## Example Usage + +```terraform +data "equinix_fabric_route_aggregations" "ra_policy" { + filter = { + property = "/project/projectId" + operator = "=" + values = [""] + } + pagination = { + limit = 2 + offset = 1 + } +} + +output "first_route_aggregation_name" { + value = data.equinix_fabric_route_aggregations.ra_policy.data.0.name +} + +output "first_route_aggregation_description" { + value = data.equinix_fabric_route_aggregations.ra_policy.data.0.description +} + +output "first_route_aggregation_connections_count" { + value = data.equinix_fabric_route_aggregations.ra_policy.data.0.connections_count +} + +output "first_route_aggregation_rules_count" { + value = data.equinix_fabric_route_aggregations.ra_policy.data.0.rules_count +} +``` + + +## Schema + +### Required + +- `filter` (Attributes) Filters for the Data Source Search Request (see [below for nested schema](#nestedatt--filter)) + +### Optional + +- `pagination` (Attributes) Pagination details for the returned route aggregations list (see [below for nested schema](#nestedatt--pagination)) +- `sort` (Attributes) Filters for the Data Source Search Request (see [below for nested schema](#nestedatt--sort)) + +### Read-Only + +- `data` (Attributes List) Returned list of stream objects (see [below for nested schema](#nestedatt--data)) +- `id` (String) The unique identifier of the resource + + +### Nested Schema for `filter` + +Required: + +- `operator` (String) Operators to use on your filtered field with the values given. One of [ =, !=, >, >=, <, <=, BETWEEN, NOT BETWEEN, LIKE, NOT LIKE, IN, NOT IN, IS NOT NULL, IS NULL] +- `property` (String) possible field names to use on filters. One of [/type /name /project/projectId /uuid /state] +- `values` (List of String) The values that you want to apply the property+operator combination to in order to filter your data search + + + +### Nested Schema for `pagination` + +Optional: + +- `limit` (Number) Maximum number of search results returned per page. Number must be between 1 and 100, and the default is 20 +- `offset` (Number) Index of the first item returned in the response. The default is 0 + +Read-Only: + +- `next` (String) The URL relative to the next item in the response +- `previous` (String) The URL relative to the previous item in the response +- `total` (Number) The total number of streams available to the user making the request + + + +### Nested Schema for `sort` + +Optional: + +- `direction` (String) The sorting direction. Can be one of: [DESC, ASC], Defaults to DESC +- `property` (String) The property name to use in sorting. One of [/type /name /project/projectId /uuid /state] Defaults to /name + + + +### Nested Schema for `data` + +Read-Only: + +- `change` (Attributes) Current state of latest Route Aggregation change (see [below for nested schema](#nestedatt--data--change)) +- `change_log` (Attributes) Details of the last change on the stream resource (see [below for nested schema](#nestedatt--data--change_log)) +- `connections_count` (Number) Number of Connections attached to route aggregation +- `description` (String) Customer-provided route aggregation description +- `href` (String) Equinix auto generated URI to the route aggregation resource +- `name` (String) Customer provided name of the route aggregation +- `project` (Attributes) Equinix Project attribute object (see [below for nested schema](#nestedatt--data--project)) +- `rules_count` (Number) Number of Rules attached to route aggregation +- `state` (String) Value representing provisioning status for the route aggregation resource +- `type` (String) Equinix defined Route Aggregation Type; BGP_IPv4_PREFIX_AGGREGATION, BGP_IPv6_PREFIX_AGGREGATION +- `uuid` (String) Equinix-assigned unique id for the route aggregation resource + + +### Nested Schema for `data.change` + +Read-Only: + +- `href` (String) Equinix auto generated URI to the route aggregation change +- `type` (String) Equinix defined Route Aggregation Change Type +- `uuid` (String) Equinix-assigned unique id for a change + + + +### Nested Schema for `data.change_log` + +Read-Only: + +- `created_by` (String) User name of creator of the stream resource +- `created_by_email` (String) Email of creator of the stream resource +- `created_by_full_name` (String) Legal name of creator of the stream resource +- `created_date_time` (String) Creation time of the stream resource +- `deleted_by` (String) User name of deleter of the stream resource +- `deleted_by_email` (String) Email of deleter of the stream resource +- `deleted_by_full_name` (String) Legal name of deleter of the stream resource +- `deleted_date_time` (String) Deletion time of the stream resource +- `updated_by` (String) User name of last updater of the stream resource +- `updated_by_email` (String) Email of last updater of the stream resource +- `updated_by_full_name` (String) Legal name of last updater of the stream resource +- `updated_date_time` (String) Last update time of the stream resource + + + +### Nested Schema for `data.project` + +Read-Only: + +- `project_id` (String) Equinix Subscriber-assigned project ID diff --git a/docs/resources/fabric_route_aggregation.md b/docs/resources/fabric_route_aggregation.md new file mode 100644 index 000000000..6a808b9ba --- /dev/null +++ b/docs/resources/fabric_route_aggregation.md @@ -0,0 +1,92 @@ +--- +subcategory: "Fabric" +--- + +# equinix_fabric_route_aggregation (Resource) + + + +## Example Usage + +```terraform +resource "equinix_fabric_route_aggregation" "new-ra" { + type = "BGP_IPv4_PREFIX_AGGREGATION" + name = "new-ra" + description = "Test aggregation" + project = { + project_id = "776847000642406" + } +} +``` + + +## Schema + +### Required + +- `name` (String) Customer provided name of the route aggregation +- `project` (Attributes) Equinix Project attribute object (see [below for nested schema](#nestedatt--project)) +- `type` (String) Equinix defined Route Aggregation Type; BGP_IPv4_PREFIX_AGGREGATION, BGP_IPv6_PREFIX_AGGREGATION + +### Optional + +- `description` (String) Customer-provided route aggregation description +- `timeouts` (Attributes) (see [below for nested schema](#nestedatt--timeouts)) + +### Read-Only + +- `change` (Attributes) Current state of latest Route Aggregation change (see [below for nested schema](#nestedatt--change)) +- `change_log` (Attributes) Details of the last change on the stream resource (see [below for nested schema](#nestedatt--change_log)) +- `connections_count` (Number) Number of Connections attached to route aggregation +- `href` (String) Equinix auto generated URI to the route aggregation resource +- `id` (String) The unique identifier of the resource +- `rules_count` (Number) Number of Rules attached to route aggregation +- `state` (String) Value representing provisioning status for the route aggregation resource +- `uuid` (String) Equinix-assigned unique id for the route aggregation resource + + +### Nested Schema for `project` + +Required: + +- `project_id` (String) Equinix Subscriber-assigned project ID + + + +### Nested Schema for `timeouts` + +Optional: + +- `create` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). +- `delete` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Setting a timeout for a Delete operation is only applicable if changes are saved into state before the destroy operation occurs. +- `read` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). Read operations occur during any refresh or planning operation when refresh is enabled. +- `update` (String) A string that can be [parsed as a duration](https://pkg.go.dev/time#ParseDuration) consisting of numbers and unit suffixes, such as "30s" or "2h45m". Valid time units are "s" (seconds), "m" (minutes), "h" (hours). + + + +### Nested Schema for `change` + +Required: + +- `href` (String) Equinix auto generated URI to the route aggregation change +- `type` (String) Equinix defined Route Aggregation Change Type +- `uuid` (String) Equinix-assigned unique id for a change + + + +### Nested Schema for `change_log` + +Read-Only: + +- `created_by` (String) User name of creator of the stream resource +- `created_by_email` (String) Email of creator of the stream resource +- `created_by_full_name` (String) Legal name of creator of the stream resource +- `created_date_time` (String) Creation time of the stream resource +- `deleted_by` (String) User name of deleter of the stream resource +- `deleted_by_email` (String) Email of deleter of the stream resource +- `deleted_by_full_name` (String) Legal name of deleter of the stream resource +- `deleted_date_time` (String) Deletion time of the stream resource +- `updated_by` (String) User name of last updater of the stream resource +- `updated_by_email` (String) Email of last updater of the stream resource +- `updated_by_full_name` (String) Legal name of last updater of the stream resource +- `updated_date_time` (String) Last update time of the stream resource diff --git a/examples/data-sources/equinix_fabric_route_aggregation/data-source.tf b/examples/data-sources/equinix_fabric_route_aggregation/data-source.tf new file mode 100644 index 000000000..52dbf78bf --- /dev/null +++ b/examples/data-sources/equinix_fabric_route_aggregation/data-source.tf @@ -0,0 +1,23 @@ +data "equinix_fabric_route_aggregation" "ra_policy" { + uuid = "" +} + +output "id" { + value = data.equinix_fabric_route_aggregation.ra_policy.id +} + +output "type" { + value = data.equinix_fabric_route_aggregation.ra_policy.type +} + +output "state" { + value = data.equinix_fabric_route_aggregation.ra_policy.state +} + +output "connections_count" { + value = data.equinix_fabric_route_aggregation.ra_policy.connections_count +} + +output "rules_count" { + value = data.equinix_fabric_route_aggregation.ra_policy.rules_count +} diff --git a/examples/data-sources/equinix_fabric_route_aggregations/data-source.tf b/examples/data-sources/equinix_fabric_route_aggregations/data-source.tf new file mode 100644 index 000000000..e898d3c68 --- /dev/null +++ b/examples/data-sources/equinix_fabric_route_aggregations/data-source.tf @@ -0,0 +1,27 @@ +data "equinix_fabric_route_aggregations" "ra_policy" { + filter = { + property = "/project/projectId" + operator = "=" + values = [""] + } + pagination = { + limit = 2 + offset = 1 + } +} + +output "first_route_aggregation_name" { + value = data.equinix_fabric_route_aggregations.ra_policy.data.0.name +} + +output "first_route_aggregation_description" { + value = data.equinix_fabric_route_aggregations.ra_policy.data.0.description +} + +output "first_route_aggregation_connections_count" { + value = data.equinix_fabric_route_aggregations.ra_policy.data.0.connections_count +} + +output "first_route_aggregation_rules_count" { + value = data.equinix_fabric_route_aggregations.ra_policy.data.0.rules_count +} diff --git a/examples/resources/equinix_fabric_route_aggregation/resource.tf b/examples/resources/equinix_fabric_route_aggregation/resource.tf new file mode 100644 index 000000000..afab27b8f --- /dev/null +++ b/examples/resources/equinix_fabric_route_aggregation/resource.tf @@ -0,0 +1,8 @@ +resource "equinix_fabric_route_aggregation" "new-ra" { + type = "BGP_IPv4_PREFIX_AGGREGATION" + name = "new-ra" + description = "Test aggregation" + project = { + project_id = "776847000642406" + } +} diff --git a/internal/provider/services/fabric.go b/internal/provider/services/fabric.go index d89eadf6c..963e8115d 100644 --- a/internal/provider/services/fabric.go +++ b/internal/provider/services/fabric.go @@ -1,6 +1,7 @@ package services import ( + "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/route_aggregation" "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/stream" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -9,6 +10,7 @@ import ( func FabricResources() []func() resource.Resource { return []func() resource.Resource{ stream.NewResource, + route_aggregation.NewResource, } } @@ -16,5 +18,7 @@ func FabricDatasources() []func() datasource.DataSource { return []func() datasource.DataSource{ stream.NewDataSourceByStreamID, stream.NewDataSourceAllStreams, + route_aggregation.NewDataSourceByRouteAggregationID, + route_aggregation.NewDataSourceAllRouteAggregation, } } diff --git a/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go b/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go new file mode 100644 index 000000000..e32198450 --- /dev/null +++ b/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go @@ -0,0 +1,129 @@ +package route_aggregation + +import ( + "context" + "github.com/equinix/equinix-sdk-go/services/fabricv4" + equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" + "github.com/equinix/terraform-provider-equinix/internal/framework" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" +) + +func NewDataSourceAllRouteAggregation() datasource.DataSource { + return &DataSourceAllRouteAggregations{ + BaseDataSource: framework.NewBaseDataSource( + framework.BaseDataSourceConfig{ + Name: "equinix_fabric_route_aggregations", + }, + ), + } +} + +type DataSourceAllRouteAggregations struct { + framework.BaseDataSource +} + +func (r *DataSourceAllRouteAggregations) Schema( + ctx context.Context, + req datasource.SchemaRequest, + resp *datasource.SchemaResponse, +) { + resp.Schema = dataSourceAllRouteAggregationsSchema(ctx) +} + +func (r *DataSourceAllRouteAggregations) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + client := r.Meta.NewFabricClientForFramework(ctx, request.ProviderMeta) + + var data DatsSourceAllRouteAggregationsModel + + response.Diagnostics.Append(request.Config.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + var tffilter FilterModel + + diags := data.Filter.As(ctx, &tffilter, basetypes.ObjectAsOptions{}) + if diags.HasError() { + return + } + values := []string{} + if len(tffilter.Values) > 0 { + for _, strVal := range tffilter.Values { + if !strVal.IsNull() && !strVal.IsUnknown() { + values = append(values, strVal.ValueString()) + } + } + } + + propertyValue := fabricv4.RouteFiltersSearchFilterItemProperty(tffilter.Property.ValueString()) + + filterItem := fabricv4.RouteAggregationsSearchFilterItem{ + Property: &propertyValue, + } + + if !tffilter.Operator.IsNull() && !tffilter.Operator.IsUnknown() { + filterItem.Operator = tffilter.Operator.ValueStringPointer() + } + + if len(values) > 0 { + filterItem.Values = values + } + + filter := fabricv4.RouteAggregationsSearchBaseFilter{ + And: []fabricv4.RouteAggregationsSearchFilterItem{filterItem}, + } + + var tfpagination PaginationModel + diags = data.Pagination.As(ctx, &tfpagination, basetypes.ObjectAsOptions{}) + if diags.HasError() { + return + } + offset := tfpagination.Offset.ValueInt32() + limit := tfpagination.Limit.ValueInt32() + if limit == 0 { + limit = 20 + } + + pagination := fabricv4.Pagination{ + Offset: &offset, + Limit: limit, + } + + var tfsort SortModel + diags = data.Sort.As(ctx, &tfsort, basetypes.ObjectAsOptions{}) + if diags.HasError() { + return + } + direction := tfsort.Direction.ValueString() + property := tfsort.Property.ValueString() + + pValue := fabricv4.RouteAggregationSortItemProperty(property) + dValue := fabricv4.SortItemDirection(direction) + + sort := fabricv4.RouteAggregationSortItem{ + Property: &pValue, + Direction: &dValue, + } + + routeAggregationsSearch := fabricv4.RouteAggregationsSearchBase{ + Filter: &filter, + Pagination: &pagination, + Sort: []fabricv4.RouteAggregationSortItem{sort}, + } + + routeAggregations, _, err := client.RouteAggregationsApi.SearchRouteAggregations(ctx).RouteAggregationsSearchBase(routeAggregationsSearch).Execute() + + if err != nil { + response.State.RemoveResource(ctx) + response.Diagnostics.AddError("api error retrieving route aggregations data", equinix_errors.FormatFabricError(err).Error()) + return + } + + response.Diagnostics.Append(data.parse(ctx, routeAggregations)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &data)...) +} diff --git a/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go b/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go new file mode 100644 index 000000000..a930ab5bd --- /dev/null +++ b/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go @@ -0,0 +1,58 @@ +package route_aggregation + +import ( + "context" + equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" + "github.com/equinix/terraform-provider-equinix/internal/framework" + "github.com/hashicorp/terraform-plugin-framework/datasource" +) + +func NewDataSourceByRouteAggregationID() datasource.DataSource { + return &DataSourceByRouteAggregationID{ + BaseDataSource: framework.NewBaseDataSource( + framework.BaseDataSourceConfig{ + Name: "equinix_fabric_route_aggregation", + }, + ), + } +} + +type DataSourceByRouteAggregationID struct { + framework.BaseDataSource +} + +func (r *DataSourceByRouteAggregationID) Schema( + ctx context.Context, + req datasource.SchemaRequest, + resp *datasource.SchemaResponse, +) { + resp.Schema = dataSourceSingleRouteAggregationSchema(ctx) +} + +func (r *DataSourceByRouteAggregationID) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { + client := r.Meta.NewFabricClientForFramework(ctx, request.ProviderMeta) + + var data DataSourceByIdModel + response.Diagnostics.Append(request.Config.Get(ctx, &data)...) + if response.Diagnostics.HasError() { + return + } + + routeAggregationID := data.RouteAggregationId.ValueString() + + routeAggregation, _, err := client.RouteAggregationsApi.GetRouteAggregationByUuid(ctx, routeAggregationID).Execute() + + if err != nil { + response.State.RemoveResource(ctx) + response.Diagnostics.AddError("api error retrieving route aggregation data", equinix_errors.FormatFabricError(err).Error()) + return + } + + response.Diagnostics.Append(data.parse(ctx, routeAggregation)...) + if response.Diagnostics.HasError() { + return + } + + response.Diagnostics.Append(response.State.Set(ctx, &data)...) + +} diff --git a/internal/resources/fabric/route_aggregation/datasource_schema.go b/internal/resources/fabric/route_aggregation/datasource_schema.go new file mode 100644 index 000000000..9c8ec0939 --- /dev/null +++ b/internal/resources/fabric/route_aggregation/datasource_schema.go @@ -0,0 +1,256 @@ +package route_aggregation + +import ( + "context" + "fmt" + "github.com/equinix/equinix-sdk-go/services/fabricv4" + "github.com/equinix/terraform-provider-equinix/internal/framework" + fwtypes "github.com/equinix/terraform-provider-equinix/internal/framework/types" + "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func dataSourceAllRouteAggregationsSchema(ctx context.Context) schema.Schema { + return schema.Schema{ + Description: `Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Streams with pagination details +Additional Documentation: +* Getting Started: https://docs.equinix.com/en-us/Content/KnowledgeCenter/Fabric/GettingStarted/Integrating-with-Fabric-V4-APIs/IntegrateWithSink.htm +* API: https://developer.equinix.com/catalog/fabricv4#tag/Streams`, + Attributes: map[string]schema.Attribute{ + "id": framework.IDAttributeDefaultDescription(), + "data": schema.ListNestedAttribute{ + Description: "Returned list of stream objects", + Computed: true, + CustomType: fwtypes.NewListNestedObjectTypeOf[BaseRouteAggregationModel](ctx), + NestedObject: schema.NestedAttributeObject{ + Attributes: getRouteAggregationSchema(ctx), + }, + }, + "filter": schema.SingleNestedAttribute{ + Description: "Filters for the Data Source Search Request", + Required: true, + //CustomType: fwtypes.NewObjectTypeOf[FilterModel](ctx), + Attributes: map[string]schema.Attribute{ + "property": schema.StringAttribute{ + Description: fmt.Sprintf("possible field names to use on filters. One of %v", fabricv4.AllowedRouteFiltersSearchFilterItemPropertyEnumValues), + Required: true, + }, + "operator": schema.StringAttribute{ + Description: "Operators to use on your filtered field with the values given. One of [ =, !=, >, >=, <, <=, BETWEEN, NOT BETWEEN, LIKE, NOT LIKE, IN, NOT IN, IS NOT NULL, IS NULL]", + Required: true, + }, + "values": schema.ListAttribute{ + Description: "The values that you want to apply the property+operator combination to in order to filter your data search", + ElementType: types.StringType, + Required: true, + }, + }, + }, + //"filter": schema.ObjectAttribute{ + // Description: "Filters for the Data Source Search Request", + // Required: true, + // AttributeTypes: map[string]attr.Type{ + // "property": schema.String{ + // Description: "The property to be used in the filter condition (e.g., 'status', 'type')", + // Required: true, + // }, + // "operator": schema.StringAttribute{ + // Description: "The operator to be used in the filter condition (e.g., '=', '>', 'IN')", + // Required: true, + // }, + // "values": schema.ListAttribute{ + // Description: "The values that you want to apply the property+operator combination to in order to filter your data search", + // ElementType: types.StringType, + // Required: true, + // }, + // }, + //} + "pagination": schema.SingleNestedAttribute{ + Description: "Pagination details for the returned route aggregations list", + Optional: true, + CustomType: fwtypes.NewObjectTypeOf[PaginationModel](ctx), + Attributes: map[string]schema.Attribute{ + "offset": schema.Int32Attribute{ + Description: "Index of the first item returned in the response. The default is 0", + Optional: true, + Computed: true, + }, + "limit": schema.Int32Attribute{ + Description: "Maximum number of search results returned per page. Number must be between 1 and 100, and the default is 20", + Optional: true, + Computed: true, + }, + "total": schema.Int32Attribute{ + Description: "The total number of streams available to the user making the request", + Computed: true, + }, + "next": schema.StringAttribute{ + Description: "The URL relative to the next item in the response", + Computed: true, + }, + "previous": schema.StringAttribute{ + Description: "The URL relative to the previous item in the response", + Computed: true, + }, + }, + }, + "sort": schema.SingleNestedAttribute{ + Description: "Filters for the Data Source Search Request", + Optional: true, + CustomType: fwtypes.NewObjectTypeOf[SortModel](ctx), + Attributes: map[string]schema.Attribute{ + "direction": schema.StringAttribute{ + Description: "The sorting direction. Can be one of: [DESC, ASC], Defaults to DESC", + Optional: true, + Validators: []validator.String{ + stringvalidator.OneOf("DESC", "ASC"), + }, + }, + "property": schema.StringAttribute{ + Description: fmt.Sprintf("The property name to use in sorting. One of %v Defaults to /name", fabricv4.AllowedRouteFiltersSearchFilterItemPropertyEnumValues), + Optional: true, + }, + }, + }, + }, + } +} +func dataSourceSingleRouteAggregationSchema(ctx context.Context) schema.Schema { + baseRouteAggregationSchema := getRouteAggregationSchema(ctx) + baseRouteAggregationSchema["id"] = framework.IDAttributeDefaultDescription() + baseRouteAggregationSchema["route_aggregation_id"] = schema.StringAttribute{ + Description: "The uuid of the route aggregation this data source should retrieve", + Required: true, + } + return schema.Schema{ + Description: `Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Stream by UUID +Additional Documentation: +* API: https://developer.equinix.com/catalog/fabricv4#tag/Route-Aggregations`, + Attributes: baseRouteAggregationSchema, + } + +} + +func getRouteAggregationSchema(ctx context.Context) map[string]schema.Attribute { + return map[string]schema.Attribute{ + "type": schema.StringAttribute{ + Description: "Equinix defined Route Aggregation Type; BGP_IPv4_PREFIX_AGGREGATION, BGP_IPv6_PREFIX_AGGREGATION", + Computed: true, + }, + "name": schema.StringAttribute{ + Description: "Customer provided name of the route aggregation", + Computed: true, + }, + "description": schema.StringAttribute{ + Description: "Customer-provided route aggregation description", + Computed: true, + }, + "project": schema.SingleNestedAttribute{ + Description: "Equinix Project attribute object", + Computed: true, + CustomType: fwtypes.NewObjectTypeOf[ProjectModel](ctx), + Attributes: map[string]schema.Attribute{ + "project_id": schema.StringAttribute{ + Description: "Equinix Subscriber-assigned project ID", + Computed: true, + }, + }, + }, + "href": schema.StringAttribute{ + Description: "Equinix auto generated URI to the route aggregation resource", + Computed: true, + }, + "uuid": schema.StringAttribute{ + Description: "Equinix-assigned unique id for the route aggregation resource", + Computed: true, + }, + "state": schema.StringAttribute{ + Description: "Value representing provisioning status for the route aggregation resource", + Computed: true, + }, + "change": schema.SingleNestedAttribute{ + Description: "Current state of latest Route Aggregation change", + Computed: true, + CustomType: fwtypes.NewObjectTypeOf[ChangeModel](ctx), + Attributes: map[string]schema.Attribute{ + "uuid": schema.StringAttribute{ + Description: "Equinix-assigned unique id for a change", + Computed: true, + }, + "type": schema.StringAttribute{ + Description: "Equinix defined Route Aggregation Change Type", + Computed: true, + }, + "href": schema.StringAttribute{ + Description: "Equinix auto generated URI to the route aggregation change", + Computed: true, + }, + }, + }, + "connections_count": schema.Int32Attribute{ + Description: "Number of Connections attached to route aggregation", + Computed: true, + }, + "rules_count": schema.Int32Attribute{ + Description: "Number of Rules attached to route aggregation", + Computed: true, + }, + "change_log": schema.SingleNestedAttribute{ + Description: "Details of the last change on the stream resource", + Computed: true, + CustomType: fwtypes.NewObjectTypeOf[ChangeLogModel](ctx), + Attributes: map[string]schema.Attribute{ + "created_by": schema.StringAttribute{ + Description: "User name of creator of the stream resource", + Computed: true, + }, + "created_by_full_name": schema.StringAttribute{ + Description: "Legal name of creator of the stream resource", + Computed: true, + }, + "created_by_email": schema.StringAttribute{ + Description: "Email of creator of the stream resource", + Computed: true, + }, + "created_date_time": schema.StringAttribute{ + Description: "Creation time of the stream resource", + Computed: true, + }, + "updated_by": schema.StringAttribute{ + Description: "User name of last updater of the stream resource", + Computed: true, + }, + "updated_by_full_name": schema.StringAttribute{ + Description: "Legal name of last updater of the stream resource", + Computed: true, + }, + "updated_by_email": schema.StringAttribute{ + Description: "Email of last updater of the stream resource", + Computed: true, + }, + "updated_date_time": schema.StringAttribute{ + Description: "Last update time of the stream resource", + Computed: true, + }, + "deleted_by": schema.StringAttribute{ + Description: "User name of deleter of the stream resource", + Computed: true, + }, + "deleted_by_full_name": schema.StringAttribute{ + Description: "Legal name of deleter of the stream resource", + Computed: true, + }, + "deleted_by_email": schema.StringAttribute{ + Description: "Email of deleter of the stream resource", + Computed: true, + }, + "deleted_date_time": schema.StringAttribute{ + Description: "Deletion time of the stream resource", + Computed: true, + }, + }, + }, + } +} diff --git a/internal/resources/fabric/route_aggregation/datasource_test.go b/internal/resources/fabric/route_aggregation/datasource_test.go new file mode 100644 index 000000000..dc1168d36 --- /dev/null +++ b/internal/resources/fabric/route_aggregation/datasource_test.go @@ -0,0 +1,98 @@ +package route_aggregation_test + +// +//import ( +// "fmt" +// "testing" +// +// "github.com/equinix/terraform-provider-equinix/internal/acceptance" +// "github.com/hashicorp/terraform-plugin-testing/helper/resource" +//) +// +//func testAccFabricRouteAggregationDataSourcesConfig(name, description string) string { +// return fmt.Sprintf(` +// +// resource "equinix_fabric_route_aggregation" "new_ra_1" { +// type = "BGP_IPv4_PREFIX_AGGREGATION" +// name = "%[1]s" +// description = "%[2]s" +// project = { +// project_id = "4f855852-eb47-4721-8e40-b386a3676abf" +// } +// } +// +// resource "equinix_fabric_route_aggregation" "new_ra_2" { +// type = "BGP_IPv4_PREFIX_AGGREGATION" +// name = "%[1]s" +// description = "%[2]s" +// project = { +// project_id = "4f855852-eb47-4721-8e40-b386a3676abf" +// } +// } +// +// data "equinix_fabric_route_aggregation" "data_ra" { +// route_aggregation_id = equinix_fabric_route_aggregation.new_ra_2.id +// } +// +// data "equinix_fabric_route_aggregations" "data_ras" { +// depends_on = [equinix_fabric_route_aggregation.new_ra_1, equinix_fabric_route_aggregation.new_ra_2] +// filter = { +// property = "/type" +// operator = "=" +// values = ["BGP_IPv4_PREFIX_AGGREGATION"] +// } +// pagination = { +// limit = 2 +// offset = 1 +// } +// sort = { +// property = "/changeLog/updatedDateTime" +// direction = "DESC" +// } +// } +// `, name, description) +//} +// +//func TestAccFabricRouteAggregationDataSources_PFCR(t *testing.T) { +// routeAggregationName := "route_agg_PFCR" +// routeAggregatioDescription := "route_agg_PFCR" +// resource.ParallelTest(t, resource.TestCase{ +// PreCheck: func() { acceptance.TestAccPreCheck(t); acceptance.TestAccPreCheckProviderConfigured(t) }, +// ExternalProviders: acceptance.TestExternalProviders, +// ProtoV6ProviderFactories: acceptance.ProtoV6ProviderFactories, +// CheckDestroy: CheckRouteAggregationDelete, +// Steps: []resource.TestStep{ +// { +// Config: testAccFabricRouteAggregationDataSourcesConfig(routeAggregationName, routeAggregatioDescription), +// Check: resource.ComposeTestCheckFunc( +// resource.TestCheckResourceAttr( +// "data.equinix_fabric_route_aggregation.data_ra", "name", routeAggregationName), +// resource.TestCheckResourceAttr( +// "data.equinix_fabric_route_aggregation.data_ra", "type", "BGP_IPv4_PREFIX_AGGREGATION"), +// resource.TestCheckResourceAttr( +// "data.equinix_fabric_route_aggregation.data_ra", "project.project_id", "4f855852-eb47-4721-8e40-b386a3676abf"), +// resource.TestCheckResourceAttr( +// "data.equinix_fabric_route_aggregation.data_ra", "description", routeAggregatioDescription), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "href"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "uuid"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "change_log.created_by"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.name"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.type"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.description"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.project.project_id"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.href"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.connections_count"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.rules_count"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.uuid"), +// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.change_log.created_by"), +// resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "data.#", "2"), +// resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.%", "5"), +// resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.limit", "2"), +// resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.offset", "1"), +// ), +// ExpectNonEmptyPlan: false, +// }, +// }, +// }) +// +//} diff --git a/internal/resources/fabric/route_aggregation/resource.go b/internal/resources/fabric/route_aggregation/resource.go new file mode 100644 index 000000000..732cfbb31 --- /dev/null +++ b/internal/resources/fabric/route_aggregation/resource.go @@ -0,0 +1,301 @@ +package route_aggregation + +import ( + "context" + "fmt" + "github.com/equinix/equinix-sdk-go/services/fabricv4" + equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" + "github.com/equinix/terraform-provider-equinix/internal/framework" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" + "net/http" + "slices" + "strings" + "time" +) + +func NewResource() resource.Resource { + return &Resource{ + BaseResource: framework.NewBaseResource( + framework.BaseResourceConfig{ + Name: "equinix_fabric_route_aggregation", + }, + ), + } +} + +type Resource struct { + framework.BaseResource +} + +func (r Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = resourceSchema(ctx) +} + +func (r *Resource) Create( + ctx context.Context, + req resource.CreateRequest, + resp *resource.CreateResponse, +) { + var plan ResourceModel + diags := req.Plan.Get(ctx, &plan) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + client := r.Meta.NewFabricClientForFramework(ctx, req.ProviderMeta) + + createRequest, diags := buildCreateRequest(ctx, plan) + if diags.HasError() { + return + } + + routeAggregation, _, err := client.RouteAggregationsApi.CreateRouteAggregation(ctx).RouteAggregationsBase(createRequest).Execute() + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Failed creating route aggregation"), equinix_errors.FormatFabricError(err).Error()) + return + } + + createTimeout, diags := plan.Timeouts.Create(ctx, 10*time.Minute) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + createWaiter := getCreateUpdateWaiter(ctx, client, routeAggregation.GetUuid(), createTimeout) + routeAggregationChecked, err := createWaiter.WaitForStateContext(ctx) + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Failed creating Route Aggregation %s", routeAggregation.GetUuid()), err.Error()) + return + } + + resp.Diagnostics.Append(diags...) + if diags.HasError() { + return + } + + resp.Diagnostics.Append(plan.parse(ctx, routeAggregationChecked.(*fabricv4.RouteAggregationsData))...) + if resp.Diagnostics.HasError() { + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) + +} + +func (r *Resource) Read( + ctx context.Context, + req resource.ReadRequest, + resp *resource.ReadResponse, +) { + var state ResourceModel + diags := req.State.Get(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } + + //Retrieve the API client from the provider metadata + client := r.Meta.NewFabricClientForFramework(ctx, req.ProviderMeta) + + // Extract the ID of the resource from the state + id := state.ID.ValueString() + + routeAggregation, _, err := client.RouteAggregationsApi.GetRouteAggregationByUuid(ctx, id).Execute() + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Failed retrieving Route Aggregation %s", id), equinix_errors.FormatFabricError(err).Error()) + return + } + + // Set state to fully populated data + resp.Diagnostics.Append(state.parse(ctx, routeAggregation)...) + if resp.Diagnostics.HasError() { + return + } + + // Update the Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &state)...) + +} + +func (r *Resource) Update( + ctx context.Context, + req resource.UpdateRequest, + resp *resource.UpdateResponse, +) { + client := r.Meta.NewFabricClientForFramework(ctx, req.ProviderMeta) + + //Retrieve values from plan + var state, plan ResourceModel + resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...) + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + id := state.ID.ValueString() + + newName, oldName := plan.Name.ValueString(), plan.Name.ValueString() + + if newName != oldName { + resp.Diagnostics.AddWarning("No updatable fields have changed", "Terraform detected a config change, but it is for a field that isn't updatable for the route aggregation resource. Please revert to prior config") + return + } + + updateRequest := []fabricv4.RouteAggregationsPatchRequestItem{{ + Op: "replace", + Path: "/name", + Value: map[string]interface{}{"": newName}, + }, + } + + _, _, err := client.RouteAggregationsApi.PatchRouteAggregationByUuid(ctx, id).RouteAggregationsPatchRequestItem(updateRequest).Execute() + + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Failed updating Route Aggregation %s", id), equinix_errors.FormatFabricError(err).Error()) + return + } + + updateTimeout, diags := plan.Timeouts.Update(ctx, 10*time.Minute) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + + updateWaiter := getCreateUpdateWaiter(ctx, client, id, updateTimeout) + routeAggregationChecked, err := updateWaiter.WaitForStateContext(ctx) + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("Failed updating Route Aggregation %s", id), err.Error()) + return + } + + //set state to fully populated data + resp.Diagnostics.Append(plan.parse(ctx, routeAggregationChecked.(*fabricv4.RouteAggregationsData))...) + if resp.Diagnostics.HasError() { + return + } + + //Set the updated state back into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &plan)...) +} + +func (r *Resource) Delete( + ctx context.Context, + req resource.DeleteRequest, + resp *resource.DeleteResponse, +) { + //Retrieve the API client + client := r.Meta.NewFabricClientForFramework(ctx, req.ProviderMeta) + + //Retrieve the current state + var state ResourceModel + resp.Diagnostics.Append(req.State.Get(ctx, &state)...) + if resp.Diagnostics.HasError() { + return + } + + id := state.ID.ValueString() + + _, deleteResp, err := client.RouteAggregationsApi.DeleteRouteAggregationByUuid(ctx, id).Execute() + if err != nil { + if deleteResp == nil || !slices.Contains([]int{http.StatusForbidden, http.StatusNotFound}, deleteResp.StatusCode) { + resp.Diagnostics.AddError(fmt.Sprintf("Failed deleting Stream %s", id), equinix_errors.FormatFabricError(err).Error()) + return + } + } + + deleteTimeout, diags := state.Timeouts.Delete(ctx, 10*time.Minute) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + deletewaiter := getDeleteWaiter(ctx, client, id, deleteTimeout) + _, err = deletewaiter.WaitForStateContext(ctx) + + if err != nil { + resp.Diagnostics.AddError(fmt.Sprintf("Failed deleting Stream %s", id), err.Error()) + return + } +} + +func buildCreateRequest(ctx context.Context, plan ResourceModel) (fabricv4.RouteAggregationsBase, diag.Diagnostics) { + var diags diag.Diagnostics + request := fabricv4.RouteAggregationsBase{} + + request.SetType(fabricv4.RouteAggregationsBaseType(plan.Type.ValueString())) + request.SetName(plan.Name.ValueString()) + request.SetDescription(plan.Description.ValueString()) + + var project ProjectModel + if !plan.Project.IsNull() && !plan.Project.IsUnknown() { + diags = plan.Project.As(ctx, &project, basetypes.ObjectAsOptions{}) + if diags.HasError() { + return fabricv4.RouteAggregationsBase{}, diags + } + request.SetProject(fabricv4.Project{ProjectId: project.ProjectId.ValueString()}) + } + return request, diags +} + +func getCreateUpdateWaiter(ctx context.Context, client *fabricv4.APIClient, id string, timeout time.Duration) *retry.StateChangeConf { + return &retry.StateChangeConf{ + Pending: []string{ + string(fabricv4.ROUTEAGGREGATIONSTATE_PROVISIONING), + }, + Target: []string{ + string(fabricv4.ROUTEAGGREGATIONSTATE_PROVISIONED), + }, + Refresh: func() (interface{}, string, error) { + routeAggregation, _, err := client.RouteAggregationsApi.GetRouteAggregationByUuid(ctx, id).Execute() + if err != nil { + return 0, "", err + } + return routeAggregation, string(routeAggregation.GetState()), nil + }, + Timeout: timeout, + Delay: 30 * time.Second, + MinTimeout: 30 * time.Second, + } +} + +func getDeleteWaiter(ctx context.Context, client *fabricv4.APIClient, id string, timeout time.Duration) *retry.StateChangeConf { + // deletedMarker is a terraform-provider-only value that is used by the waiter + // to indicate that the resource appears to be deleted successfully based on + // status code or specific error code + deletedMarker := "tf-marker-for-deleted-route-aggregation" + return &retry.StateChangeConf{ + Pending: []string{ + string(fabricv4.ROUTEAGGREGATIONSTATE_DEPROVISIONING), + }, + Target: []string{ + deletedMarker, + }, + Refresh: func() (interface{}, string, error) { + routeAggregation, resp, err := client.RouteAggregationsApi.GetRouteAggregationByUuid(ctx, id).Execute() + if err != nil { + if resp != nil { + if slices.Contains([]int{http.StatusForbidden, http.StatusNotFound}, resp.StatusCode) { + return routeAggregation, deletedMarker, nil + } + apiError, ok := err.(*fabricv4.GenericOpenAPIError) + if ok { + errorBody := string(apiError.Body()) + if strings.Contains(errorBody, "EQ-3044301") { + return routeAggregation, deletedMarker, nil + } + } + } + return 0, "", err + } + return routeAggregation, string(routeAggregation.GetState()), nil + }, + Timeout: timeout, + Delay: 10 * time.Second, + MinTimeout: 5 * time.Second, + } +} diff --git a/internal/resources/fabric/route_aggregation/resource_schema.go b/internal/resources/fabric/route_aggregation/resource_schema.go new file mode 100644 index 000000000..d842da881 --- /dev/null +++ b/internal/resources/fabric/route_aggregation/resource_schema.go @@ -0,0 +1,151 @@ +package route_aggregation + +import ( + "context" + "github.com/equinix/terraform-provider-equinix/internal/framework" + fwtypes "github.com/equinix/terraform-provider-equinix/internal/framework/types" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" +) + +func resourceSchema(ctx context.Context) schema.Schema { + return schema.Schema{ + Attributes: map[string]schema.Attribute{ + "id": framework.IDAttributeDefaultDescription(), + "timeouts": timeouts.Attributes(ctx, timeouts.Opts{ + Create: true, + Read: true, + Update: true, + Delete: true, + }), + "type": schema.StringAttribute{ + Description: "Equinix defined Route Aggregation Type; BGP_IPv4_PREFIX_AGGREGATION, BGP_IPv6_PREFIX_AGGREGATION", + Required: true, + }, + "name": schema.StringAttribute{ + Description: "Customer provided name of the route aggregation", + Required: true, + }, + "description": schema.StringAttribute{ + Description: "Customer-provided route aggregation description", + Optional: true, + }, + "project": schema.SingleNestedAttribute{ + Description: "Equinix Project attribute object", + Required: true, + PlanModifiers: []planmodifier.Object{ + objectplanmodifier.UseStateForUnknown(), + }, + CustomType: fwtypes.NewObjectTypeOf[ProjectModel](ctx), + Attributes: map[string]schema.Attribute{ + "project_id": schema.StringAttribute{ + Description: "Equinix Subscriber-assigned project ID", + Required: true, + }, + }, + }, + "href": schema.StringAttribute{ + Description: "Equinix auto generated URI to the route aggregation resource", + Computed: true, + }, + "uuid": schema.StringAttribute{ + Description: "Equinix-assigned unique id for the route aggregation resource", + Computed: true, + }, + "state": schema.StringAttribute{ + Description: "Value representing provisioning status for the route aggregation resource", + Computed: true, + }, + "change": schema.SingleNestedAttribute{ + Description: "Current state of latest Route Aggregation change", + Computed: true, + PlanModifiers: []planmodifier.Object{ + objectplanmodifier.UseStateForUnknown(), + }, + CustomType: fwtypes.NewObjectTypeOf[ChangeModel](ctx), + Attributes: map[string]schema.Attribute{ + "uuid": schema.StringAttribute{ + Description: "Equinix-assigned unique id for a change", + Required: true, + }, + "type": schema.StringAttribute{ + Description: "Equinix defined Route Aggregation Change Type", + Required: true, + }, + "href": schema.StringAttribute{ + Description: "Equinix auto generated URI to the route aggregation change", + Required: true, + }, + }, + }, + "connections_count": schema.Int32Attribute{ + Description: "Number of Connections attached to route aggregation", + Computed: true, + }, + "rules_count": schema.Int32Attribute{ + Description: "Number of Rules attached to route aggregation", + Computed: true, + }, + "change_log": schema.SingleNestedAttribute{ + Description: "Details of the last change on the stream resource", + Computed: true, + PlanModifiers: []planmodifier.Object{ + objectplanmodifier.UseStateForUnknown(), + }, + CustomType: fwtypes.NewObjectTypeOf[ChangeLogModel](ctx), + Attributes: map[string]schema.Attribute{ + "created_by": schema.StringAttribute{ + Description: "User name of creator of the stream resource", + Computed: true, + }, + "created_by_full_name": schema.StringAttribute{ + Description: "Legal name of creator of the stream resource", + Computed: true, + }, + "created_by_email": schema.StringAttribute{ + Description: "Email of creator of the stream resource", + Computed: true, + }, + "created_date_time": schema.StringAttribute{ + Description: "Creation time of the stream resource", + Computed: true, + }, + "updated_by": schema.StringAttribute{ + Description: "User name of last updater of the stream resource", + Computed: true, + }, + "updated_by_full_name": schema.StringAttribute{ + Description: "Legal name of last updater of the stream resource", + Computed: true, + }, + "updated_by_email": schema.StringAttribute{ + Description: "Email of last updater of the stream resource", + Computed: true, + }, + "updated_date_time": schema.StringAttribute{ + Description: "Last update time of the stream resource", + Computed: true, + }, + "deleted_by": schema.StringAttribute{ + Description: "User name of deleter of the stream resource", + Computed: true, + }, + "deleted_by_full_name": schema.StringAttribute{ + Description: "Legal name of deleter of the stream resource", + Computed: true, + }, + "deleted_by_email": schema.StringAttribute{ + Description: "Email of deleter of the stream resource", + Computed: true, + }, + "deleted_date_time": schema.StringAttribute{ + Description: "Deletion time of the stream resource", + Computed: true, + }, + }, + }, + }, + } +} diff --git a/internal/resources/fabric/route_aggregation/resource_test.go b/internal/resources/fabric/route_aggregation/resource_test.go new file mode 100644 index 000000000..7bff16038 --- /dev/null +++ b/internal/resources/fabric/route_aggregation/resource_test.go @@ -0,0 +1,100 @@ +package route_aggregation_test + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "github.com/equinix/equinix-sdk-go/services/fabricv4" + "github.com/equinix/terraform-provider-equinix/internal/config" + "testing" + + "github.com/equinix/terraform-provider-equinix/internal/acceptance" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" +) + +func testAccFabricRouteAggregationConfig(name string) string { + return fmt.Sprintf(` + resource "equinix_fabric_route_aggregation" "test" { + type = "BGP_IPv4_PREFIX_AGGREGATION" + name = "%s" + description = "Test Route Aggregation" + project = { + project_id = "4f855852-eb47-4721-8e40-b386a3676abf" + } + } + `, name) +} + +func TestAccFabricRouteAggregation_PFCR(t *testing.T) { + routeAggregationName := "stream_PFCR" + //upRouteAggregationName := "stream_up_PFCR" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t); acceptance.TestAccPreCheckProviderConfigured(t) }, + ExternalProviders: acceptance.TestExternalProviders, + ProtoV6ProviderFactories: acceptance.ProtoV6ProviderFactories, + CheckDestroy: CheckRouteAggregationDelete, + Steps: []resource.TestStep{ + { + Config: testAccFabricRouteAggregationConfig(routeAggregationName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "equinix_fabric_route_aggregation.test", "name", routeAggregationName), + resource.TestCheckResourceAttrSet("equinix_fabric_route_aggregation.test", "uuid"), + resource.TestCheckResourceAttrSet("equinix_fabric_route_aggregation.test", "state"), + resource.TestCheckResourceAttrSet("equinix_fabric_route_aggregation.test", "href"), + resource.TestCheckResourceAttrSet("equinix_fabric_route_aggregation.test", "project.project_id"), + resource.TestCheckResourceAttr("equinix_fabric_route_aggregation.test", "name", routeAggregationName), + resource.TestCheckResourceAttr("equinix_fabric_route_aggregation.test", "type", "BGP_IPv4_PREFIX_AGGREGATION"), + resource.TestCheckResourceAttr("equinix_fabric_route_aggregation.test", "description", "Test Route Aggregation"), + ), + ExpectNonEmptyPlan: false, + }, + }, + }) + +} + +func CheckRouteAggregationDelete(s *terraform.State) error { + ctx := context.Background() + client := acceptance.TestAccProvider.Meta().(*config.Config).NewFabricClientForTesting(ctx) + + for _, rs := range s.RootModule().Resources { + if rs.Type != "equinix_fabric_route_aggregation" { + continue + } + + _, resp, err := client.RouteAggregationsApi.GetRouteAggregationByUuid(ctx, rs.Primary.ID).Execute() + if err != nil { + // Check if the response exists and contains status 400 or 404 + if resp != nil && (resp.StatusCode == 400 || resp.StatusCode == 404) { + fmt.Printf("Resource %s not found, treating as deleted\n", rs.Primary.ID) + return nil + } + + // Handle specific API error messages + var apiErr *fabricv4.GenericOpenAPIError + if errors.As(err, &apiErr) { + errorBody := apiErr.Body() + var errorResponse map[string]interface{} + if jsonErr := json.Unmarshal(errorBody, &errorResponse); jsonErr == nil { + if errorCode, exists := errorResponse["errorCode"]; exists && errorCode == "EQ-3044301" { + fmt.Printf("Detected EQ-3044301 for resource %s, treating as deleted\n", rs.Primary.ID) + return nil // Successfully handled the expected deletion case + } + } + } + + return fmt.Errorf("unexpected API error checking deletion: %v", err) + } + + if routeAggregation, _, err := client.RouteAggregationsApi.GetRouteAggregationByUuid(ctx, rs.Primary.ID).Execute(); err == nil { + if routeAggregation.GetState() == fabricv4.ROUTEAGGREGATIONSTATE_PROVISIONED { + return fmt.Errorf("fabric stream %s still exists and is %s", + rs.Primary.ID, routeAggregation.GetState()) + } + } + } + return nil +} diff --git a/internal/resources/fabric/route_aggregation/sweeper.go b/internal/resources/fabric/route_aggregation/sweeper.go new file mode 100644 index 000000000..f4c848ba1 --- /dev/null +++ b/internal/resources/fabric/route_aggregation/sweeper.go @@ -0,0 +1,79 @@ +package route_aggregation + +import ( + "context" + "errors" + "fmt" + "github.com/equinix/equinix-sdk-go/services/fabricv4" + equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" + "github.com/equinix/terraform-provider-equinix/internal/sweep" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "log" + "net/http" +) + +func AddTestSweeper() { + resource.AddTestSweepers("equinix_fabric_route_aggregation", &resource.Sweeper{ + Name: "equinix_fabric_route_aggregation", + Dependencies: []string{}, + F: testSweepRouteAggregations, + }) +} + +func testSweepRouteAggregations(_ string) error { + var errs []error + log.Printf("[DEBUG] Sweeping Route Aggregations") + ctx := context.Background() + meta, err := sweep.GetConfigForFabric() + if err != nil { + return fmt.Errorf("error getting configuration for sweeping Route Aggregations: %s", err) + } + configLoadErr := meta.Load(ctx) + if configLoadErr != nil { + return fmt.Errorf("error loading configuration for sweeping Route Aggregations: %s", err) + } + fabric := meta.NewFabricClientForTesting(ctx) + + name := fabricv4.ROUTEFILTERSSEARCHFILTERITEMPROPERTY_NAME + equinixState := fabricv4.ROUTEFILTERSSEARCHFILTERITEMPROPERTY_STATE + likeOperator := "like" + equalOperator := "=" + limit := int32(100) + routeAggregationsSearch := fabricv4.RouteAggregationsSearchBase{ + Filter: &fabricv4.RouteAggregationsSearchBaseFilter{ + And: []fabricv4.RouteAggregationsSearchFilterItem{ + { + Property: &name, + Operator: &likeOperator, + Values: []string{"%_PFCR", "%_PNFV"}, + }, + { + Property: &equinixState, + Operator: &equalOperator, + Values: []string{string(fabricv4.ROUTEFILTERSTATE_PROVISIONED)}, + }, + }, + }, + Pagination: &fabricv4.Pagination{ + Limit: limit, + Total: limit, + }, + } + + routeAggregation, _, err := fabric.RouteAggregationsApi.SearchRouteAggregations(ctx).RouteAggregationsSearchBase(routeAggregationsSearch).Execute() + if err != nil { + return fmt.Errorf("error getting streams list for sweeping fabric route aggregations: %s", err) + } + + for _, ra := range routeAggregation.GetData() { + if sweep.IsSweepableFabricTestResource(ra.GetName()) { + log.Printf("[DEBUG] Deleting route aggregation: %s", ra.GetName()) + _, resp, err := fabric.RouteAggregationsApi.DeleteRouteAggregationByUuid(ctx, ra.GetUuid()).Execute() + if equinix_errors.IgnoreHttpResponseErrors(http.StatusForbidden, http.StatusNotFound)(resp, err) != nil { + errs = append(errs, fmt.Errorf("error deleting fabric route aggregation: %s", err)) + } + } + } + + return errors.Join(errs...) +} diff --git a/internal/sweep/sweep_test.go b/internal/sweep/sweep_test.go index 411ff764c..0cf3806f3 100644 --- a/internal/sweep/sweep_test.go +++ b/internal/sweep/sweep_test.go @@ -5,6 +5,7 @@ import ( fabric_cloud_router "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/cloud_router" fabric_connection "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/connection" + fabric_route_aggregation "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/route_aggregation" fabric_route_filter "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/route_filter" fabric_stream "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/stream" @@ -34,6 +35,7 @@ func addTestSweepers() { fabric_cloud_router.AddTestSweeper() fabric_connection.AddTestSweeper() fabric_route_filter.AddTestSweeper() + fabric_route_aggregation.AddTestSweeper() fabric_stream.AddTestSweeper() organization.AddTestSweeper() project.AddTestSweeper() From b1edf8d7cf082e207ee0c262ad8e938404cf3aae Mon Sep 17 00:00:00 2001 From: srushti-patl Date: Mon, 3 Feb 2025 23:13:18 -0800 Subject: [PATCH 2/8] fix: adding route aggregation model file --- .../fabric/route_aggregation/models.go | 245 ++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 internal/resources/fabric/route_aggregation/models.go diff --git a/internal/resources/fabric/route_aggregation/models.go b/internal/resources/fabric/route_aggregation/models.go new file mode 100644 index 000000000..7bd03212d --- /dev/null +++ b/internal/resources/fabric/route_aggregation/models.go @@ -0,0 +1,245 @@ +package route_aggregation + +import ( + "context" + "github.com/equinix/equinix-sdk-go/services/fabricv4" + fwtypes "github.com/equinix/terraform-provider-equinix/internal/framework/types" + "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" +) + +type DataSourceByIdModel struct { + RouteAggregationId types.String `tfsdk:"route_aggregation_id"` + ID types.String `tfsdk:"id"` + BaseRouteAggregationModel +} + +type DatsSourceAllRouteAggregationsModel struct { + ID types.String `tfsdk:"id"` + Data fwtypes.ListNestedObjectValueOf[BaseRouteAggregationModel] `tfsdk:"data"` + Filter types.Object `tfsdk:"filter"` + Pagination fwtypes.ObjectValueOf[PaginationModel] `tfsdk:"pagination"` + Sort fwtypes.ObjectValueOf[SortModel] `tfsdk:"sort"` +} + +type FilterModel struct { + Property types.String `tfsdk:"property"` + Operator types.String `tfsdk:"operator"` + Values []types.String `tfsdk:"values"` +} + +type PaginationModel struct { + Offset types.Int32 `tfsdk:"offset"` + Limit types.Int32 `tfsdk:"limit"` + Total types.Int32 `tfsdk:"total"` + Next types.String `tfsdk:"next"` + Previous types.String `tfsdk:"previous"` +} + +type SortModel struct { + Direction types.String `tfsdk:"direction"` + Property types.String `tfsdk:"property"` +} + +type ResourceModel struct { + ID types.String `tfsdk:"id"` + Timeouts timeouts.Value `tfsdk:"timeouts"` + BaseRouteAggregationModel +} + +type BaseRouteAggregationModel struct { + Type types.String `tfsdk:"type"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + Href types.String `tfsdk:"href"` + Uuid types.String `tfsdk:"uuid"` + State types.String `tfsdk:"state"` + ConnectionsCount types.Int32 `tfsdk:"connections_count"` + RulesCount types.Int32 `tfsdk:"rules_count"` + Project fwtypes.ObjectValueOf[ProjectModel] `tfsdk:"project"` + Change fwtypes.ObjectValueOf[ChangeModel] `tfsdk:"change"` + ChangeLog fwtypes.ObjectValueOf[ChangeLogModel] `tfsdk:"change_log"` +} + +type ProjectModel struct { + ProjectId types.String `tfsdk:"project_id"` +} + +type ChangeModel struct { + Uuid types.String `tfsdk:"uuid"` + Type types.String `tfsdk:"type"` + Href types.String `tfsdk:"href"` +} + +type ChangeLogModel struct { + CreatedBy types.String `tfsdk:"created_by"` + CreatedByFullName types.String `tfsdk:"created_by_full_name"` + CreatedByEmail types.String `tfsdk:"created_by_email"` + CreatedDateTime types.String `tfsdk:"created_date_time"` + UpdatedBy types.String `tfsdk:"updated_by"` + UpdatedByFullName types.String `tfsdk:"updated_by_full_name"` + UpdatedByEmail types.String `tfsdk:"updated_by_email"` + UpdatedDateTime types.String `tfsdk:"updated_date_time"` + DeletedBy types.String `tfsdk:"deleted_by"` + DeletedByFullName types.String `tfsdk:"deleted_by_full_name"` + DeletedByEmail types.String `tfsdk:"deleted_by_email"` + DeletedDateTime types.String `tfsdk:"deleted_date_time"` +} + +func (m *DataSourceByIdModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { + m.RouteAggregationId = types.StringValue(routeAggregation.GetUuid()) + m.ID = types.StringValue(routeAggregation.GetUuid()) + + diags := parseRouteAggregation(ctx, routeAggregation, + &m.Type, + &m.Name, + &m.Description, + &m.Href, + &m.Uuid, + &m.State, + &m.ConnectionsCount, + &m.RulesCount, + &m.Project, + &m.Change, + &m.ChangeLog) + if diags.HasError() { + return diags + } + return diags +} + +func (m *DatsSourceAllRouteAggregationsModel) parse(ctx context.Context, routeAggregationsResponse *fabricv4.RouteAggregationsSearchResponse) diag.Diagnostics { + var diags diag.Diagnostics + + if len(routeAggregationsResponse.GetData()) < 1 { + diags.AddError("no data retrieved by streams data source", "either the account does not have any streams data to pull or the combination of limit and offset needs to be updated") + return diags + } + + data := make([]BaseRouteAggregationModel, len(routeAggregationsResponse.GetData())) + routeAggregations := routeAggregationsResponse.GetData() + for index, routeAggregation := range routeAggregations { + var routeAggregationModel BaseRouteAggregationModel + diags = routeAggregationModel.parse(ctx, &routeAggregation) + if diags.HasError() { + return diags + } + data[index] = routeAggregationModel + } + responsePagination := routeAggregationsResponse.GetPagination() + pagination := PaginationModel{ + Offset: types.Int32Value(responsePagination.GetOffset()), + Limit: types.Int32Value(responsePagination.GetLimit()), + Total: types.Int32Value(responsePagination.GetTotal()), + Next: types.StringValue(responsePagination.GetNext()), + Previous: types.StringValue(responsePagination.GetPrevious()), + } + m.ID = types.StringValue(data[0].Uuid.ValueString()) + m.Pagination = fwtypes.NewObjectValueOf[PaginationModel](ctx, &pagination) + + dataPtr := make([]*BaseRouteAggregationModel, len(data)) + for i := range data { + dataPtr[i] = &data[i] + } + m.Data = fwtypes.NewListNestedObjectValueOfSlice[BaseRouteAggregationModel](ctx, dataPtr) + + return diags +} +func (m *ResourceModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { + var diags diag.Diagnostics + + m.ID = types.StringValue(routeAggregation.GetUuid()) + + diags = parseRouteAggregation(ctx, routeAggregation, + &m.Type, + &m.Name, + &m.Description, + &m.Href, + &m.Uuid, + &m.State, + &m.ConnectionsCount, + &m.RulesCount, + &m.Project, + &m.Change, + &m.ChangeLog) + if diags.HasError() { + return diags + } + + return diags + +} + +func (m *BaseRouteAggregationModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { + var diags diag.Diagnostics + + diags = parseRouteAggregation(ctx, routeAggregation, + &m.Type, + &m.Name, + &m.Description, + &m.Href, + &m.Uuid, + &m.State, + &m.ConnectionsCount, + &m.RulesCount, + &m.Project, + &m.Change, + &m.ChangeLog) + if diags.HasError() { + return diags + } + return diags +} + +func parseRouteAggregation(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData, + type_, name, description, href, uuid, state *basetypes.StringValue, + connectionsCount, rulesCount *basetypes.Int32Value, + project *fwtypes.ObjectValueOf[ProjectModel], + change *fwtypes.ObjectValueOf[ChangeModel], + changeLog *fwtypes.ObjectValueOf[ChangeLogModel]) diag.Diagnostics { + var diag diag.Diagnostics + + *type_ = types.StringValue(string(routeAggregation.GetType())) + *name = types.StringValue(routeAggregation.GetName()) + *description = types.StringValue(routeAggregation.GetDescription()) + *href = types.StringValue(routeAggregation.GetHref()) + *uuid = types.StringValue(routeAggregation.GetUuid()) + *state = types.StringValue(string(routeAggregation.GetState())) + *connectionsCount = types.Int32Value(routeAggregation.GetConnectionsCount()) + *rulesCount = types.Int32Value(routeAggregation.GetRulesCount()) + + routeAggregationProject := routeAggregation.GetProject() + projectModel := ProjectModel{ + ProjectId: types.StringValue(routeAggregationProject.GetProjectId()), + } + *project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel) + + routeAggregationChange := routeAggregation.GetChange() + changeModel := ChangeModel{ + Uuid: types.StringValue(routeAggregationChange.GetUuid()), + Type: types.StringValue(string(routeAggregationChange.GetType())), + Href: types.StringValue(routeAggregationChange.GetHref()), + } + *change = fwtypes.NewObjectValueOf[ChangeModel](ctx, &changeModel) + + const TIMEFORMAT = "2008-02-02T14:02:02.000Z" + routeAggregationChangeLog := routeAggregation.GetChangeLog() + changeLogModel := ChangeLogModel{ + CreatedBy: types.StringValue(routeAggregationChangeLog.GetCreatedBy()), + CreatedByFullName: types.StringValue(routeAggregationChangeLog.GetCreatedByFullName()), + CreatedByEmail: types.StringValue(routeAggregationChangeLog.GetCreatedByEmail()), + CreatedDateTime: types.StringValue(routeAggregationChangeLog.GetCreatedDateTime().Format(TIMEFORMAT)), + UpdatedBy: types.StringValue(routeAggregationChangeLog.GetUpdatedBy()), + UpdatedByFullName: types.StringValue(routeAggregationChangeLog.GetUpdatedByFullName()), + UpdatedByEmail: types.StringValue(routeAggregationChangeLog.GetUpdatedByEmail()), + UpdatedDateTime: types.StringValue(routeAggregationChangeLog.GetUpdatedDateTime().Format(TIMEFORMAT)), + DeletedBy: types.StringValue(routeAggregationChangeLog.GetDeletedBy()), + DeletedByFullName: types.StringValue(routeAggregationChangeLog.GetDeletedByFullName()), + DeletedByEmail: types.StringValue(routeAggregationChangeLog.GetDeletedByEmail()), + DeletedDateTime: types.StringValue(routeAggregationChangeLog.GetDeletedDateTime().Format(TIMEFORMAT)), + } + *changeLog = fwtypes.NewObjectValueOf[ChangeLogModel](ctx, &changeLogModel) + return diag +} From d7cc83c2ca31b10fe221dda23a923074542bc896 Mon Sep 17 00:00:00 2001 From: srushti-patl Date: Tue, 4 Feb 2025 12:32:33 -0800 Subject: [PATCH 3/8] fix: Fixing lint errors --- .../route_aggregation/datasource_all_aggregations.go | 1 + .../datasource_by_routeAggregationId.go | 1 + .../fabric/route_aggregation/datasource_schema.go | 1 + internal/resources/fabric/route_aggregation/models.go | 5 ++--- .../resources/fabric/route_aggregation/resource.go | 11 ++++++----- .../fabric/route_aggregation/resource_schema.go | 1 + .../fabric/route_aggregation/resource_test.go | 3 ++- .../resources/fabric/route_aggregation/sweeper.go | 5 +++-- 8 files changed, 17 insertions(+), 11 deletions(-) diff --git a/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go b/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go index e32198450..40a55b294 100644 --- a/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go +++ b/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go @@ -2,6 +2,7 @@ package route_aggregation import ( "context" + "github.com/equinix/equinix-sdk-go/services/fabricv4" equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" "github.com/equinix/terraform-provider-equinix/internal/framework" diff --git a/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go b/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go index a930ab5bd..5c3578ac6 100644 --- a/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go +++ b/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go @@ -2,6 +2,7 @@ package route_aggregation import ( "context" + equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" "github.com/equinix/terraform-provider-equinix/internal/framework" "github.com/hashicorp/terraform-plugin-framework/datasource" diff --git a/internal/resources/fabric/route_aggregation/datasource_schema.go b/internal/resources/fabric/route_aggregation/datasource_schema.go index 9c8ec0939..e90df0a0d 100644 --- a/internal/resources/fabric/route_aggregation/datasource_schema.go +++ b/internal/resources/fabric/route_aggregation/datasource_schema.go @@ -3,6 +3,7 @@ package route_aggregation import ( "context" "fmt" + "github.com/equinix/equinix-sdk-go/services/fabricv4" "github.com/equinix/terraform-provider-equinix/internal/framework" fwtypes "github.com/equinix/terraform-provider-equinix/internal/framework/types" diff --git a/internal/resources/fabric/route_aggregation/models.go b/internal/resources/fabric/route_aggregation/models.go index 7bd03212d..79198f131 100644 --- a/internal/resources/fabric/route_aggregation/models.go +++ b/internal/resources/fabric/route_aggregation/models.go @@ -2,6 +2,7 @@ package route_aggregation import ( "context" + "github.com/equinix/equinix-sdk-go/services/fabricv4" fwtypes "github.com/equinix/terraform-provider-equinix/internal/framework/types" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" @@ -173,9 +174,7 @@ func (m *ResourceModel) parse(ctx context.Context, routeAggregation *fabricv4.Ro } func (m *BaseRouteAggregationModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { - var diags diag.Diagnostics - - diags = parseRouteAggregation(ctx, routeAggregation, + var diags diag.Diagnostics = parseRouteAggregation(ctx, routeAggregation, &m.Type, &m.Name, &m.Description, diff --git a/internal/resources/fabric/route_aggregation/resource.go b/internal/resources/fabric/route_aggregation/resource.go index 732cfbb31..54f8b0ca9 100644 --- a/internal/resources/fabric/route_aggregation/resource.go +++ b/internal/resources/fabric/route_aggregation/resource.go @@ -3,6 +3,11 @@ package route_aggregation import ( "context" "fmt" + "net/http" + "slices" + "strings" + "time" + "github.com/equinix/equinix-sdk-go/services/fabricv4" equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" "github.com/equinix/terraform-provider-equinix/internal/framework" @@ -10,10 +15,6 @@ import ( "github.com/hashicorp/terraform-plugin-framework/resource" "github.com/hashicorp/terraform-plugin-framework/types/basetypes" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" - "net/http" - "slices" - "strings" - "time" ) func NewResource() resource.Resource { @@ -56,7 +57,7 @@ func (r *Resource) Create( routeAggregation, _, err := client.RouteAggregationsApi.CreateRouteAggregation(ctx).RouteAggregationsBase(createRequest).Execute() if err != nil { resp.Diagnostics.AddError( - fmt.Sprintf("Failed creating route aggregation"), equinix_errors.FormatFabricError(err).Error()) + "Failed creating route aggregation", equinix_errors.FormatFabricError(err).Error()) return } diff --git a/internal/resources/fabric/route_aggregation/resource_schema.go b/internal/resources/fabric/route_aggregation/resource_schema.go index d842da881..2999841f6 100644 --- a/internal/resources/fabric/route_aggregation/resource_schema.go +++ b/internal/resources/fabric/route_aggregation/resource_schema.go @@ -2,6 +2,7 @@ package route_aggregation import ( "context" + "github.com/equinix/terraform-provider-equinix/internal/framework" fwtypes "github.com/equinix/terraform-provider-equinix/internal/framework/types" "github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts" diff --git a/internal/resources/fabric/route_aggregation/resource_test.go b/internal/resources/fabric/route_aggregation/resource_test.go index 7bff16038..db56efc2e 100644 --- a/internal/resources/fabric/route_aggregation/resource_test.go +++ b/internal/resources/fabric/route_aggregation/resource_test.go @@ -5,9 +5,10 @@ import ( "encoding/json" "errors" "fmt" + "testing" + "github.com/equinix/equinix-sdk-go/services/fabricv4" "github.com/equinix/terraform-provider-equinix/internal/config" - "testing" "github.com/equinix/terraform-provider-equinix/internal/acceptance" "github.com/hashicorp/terraform-plugin-testing/helper/resource" diff --git a/internal/resources/fabric/route_aggregation/sweeper.go b/internal/resources/fabric/route_aggregation/sweeper.go index f4c848ba1..5e318b66c 100644 --- a/internal/resources/fabric/route_aggregation/sweeper.go +++ b/internal/resources/fabric/route_aggregation/sweeper.go @@ -4,12 +4,13 @@ import ( "context" "errors" "fmt" + "log" + "net/http" + "github.com/equinix/equinix-sdk-go/services/fabricv4" equinix_errors "github.com/equinix/terraform-provider-equinix/internal/errors" "github.com/equinix/terraform-provider-equinix/internal/sweep" "github.com/hashicorp/terraform-plugin-testing/helper/resource" - "log" - "net/http" ) func AddTestSweeper() { From c248a7ec33877250a5a0f9cebeddd41c1437d772 Mon Sep 17 00:00:00 2001 From: srushti-patl Date: Thu, 6 Feb 2025 15:32:31 -0800 Subject: [PATCH 4/8] fix: Updating datasource test file --- .../route_aggregation/datasource_schema.go | 54 ++--- .../route_aggregation/datasource_test.go | 191 +++++++++--------- .../fabric/route_aggregation/models.go | 2 +- .../fabric/route_aggregation/resource.go | 6 +- .../route_aggregation/resource_schema.go | 26 +-- .../fabric/route_aggregation/resource_test.go | 2 +- 6 files changed, 130 insertions(+), 151 deletions(-) diff --git a/internal/resources/fabric/route_aggregation/datasource_schema.go b/internal/resources/fabric/route_aggregation/datasource_schema.go index e90df0a0d..1167c988c 100644 --- a/internal/resources/fabric/route_aggregation/datasource_schema.go +++ b/internal/resources/fabric/route_aggregation/datasource_schema.go @@ -15,14 +15,14 @@ import ( func dataSourceAllRouteAggregationsSchema(ctx context.Context) schema.Schema { return schema.Schema{ - Description: `Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Streams with pagination details + Description: `Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Route Aggregations with pagination details Additional Documentation: * Getting Started: https://docs.equinix.com/en-us/Content/KnowledgeCenter/Fabric/GettingStarted/Integrating-with-Fabric-V4-APIs/IntegrateWithSink.htm * API: https://developer.equinix.com/catalog/fabricv4#tag/Streams`, Attributes: map[string]schema.Attribute{ "id": framework.IDAttributeDefaultDescription(), "data": schema.ListNestedAttribute{ - Description: "Returned list of stream objects", + Description: "Returned list of route aggregation objects", Computed: true, CustomType: fwtypes.NewListNestedObjectTypeOf[BaseRouteAggregationModel](ctx), NestedObject: schema.NestedAttributeObject{ @@ -32,7 +32,6 @@ Additional Documentation: "filter": schema.SingleNestedAttribute{ Description: "Filters for the Data Source Search Request", Required: true, - //CustomType: fwtypes.NewObjectTypeOf[FilterModel](ctx), Attributes: map[string]schema.Attribute{ "property": schema.StringAttribute{ Description: fmt.Sprintf("possible field names to use on filters. One of %v", fabricv4.AllowedRouteFiltersSearchFilterItemPropertyEnumValues), @@ -49,25 +48,6 @@ Additional Documentation: }, }, }, - //"filter": schema.ObjectAttribute{ - // Description: "Filters for the Data Source Search Request", - // Required: true, - // AttributeTypes: map[string]attr.Type{ - // "property": schema.String{ - // Description: "The property to be used in the filter condition (e.g., 'status', 'type')", - // Required: true, - // }, - // "operator": schema.StringAttribute{ - // Description: "The operator to be used in the filter condition (e.g., '=', '>', 'IN')", - // Required: true, - // }, - // "values": schema.ListAttribute{ - // Description: "The values that you want to apply the property+operator combination to in order to filter your data search", - // ElementType: types.StringType, - // Required: true, - // }, - // }, - //} "pagination": schema.SingleNestedAttribute{ Description: "Pagination details for the returned route aggregations list", Optional: true, @@ -84,7 +64,7 @@ Additional Documentation: Computed: true, }, "total": schema.Int32Attribute{ - Description: "The total number of streams available to the user making the request", + Description: "The total number of route aggregations available to the user making the request", Computed: true, }, "next": schema.StringAttribute{ @@ -126,7 +106,7 @@ func dataSourceSingleRouteAggregationSchema(ctx context.Context) schema.Schema { Required: true, } return schema.Schema{ - Description: `Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Stream by UUID + Description: `Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Route Aggregation by UUID Additional Documentation: * API: https://developer.equinix.com/catalog/fabricv4#tag/Route-Aggregations`, Attributes: baseRouteAggregationSchema, @@ -199,56 +179,56 @@ func getRouteAggregationSchema(ctx context.Context) map[string]schema.Attribute Computed: true, }, "change_log": schema.SingleNestedAttribute{ - Description: "Details of the last change on the stream resource", + Description: "Details of the last change on the route aggregation resource", Computed: true, CustomType: fwtypes.NewObjectTypeOf[ChangeLogModel](ctx), Attributes: map[string]schema.Attribute{ "created_by": schema.StringAttribute{ - Description: "User name of creator of the stream resource", + Description: "User name of creator of the route aggregation resource", Computed: true, }, "created_by_full_name": schema.StringAttribute{ - Description: "Legal name of creator of the stream resource", + Description: "Legal name of creator of the route aggregation resource", Computed: true, }, "created_by_email": schema.StringAttribute{ - Description: "Email of creator of the stream resource", + Description: "Email of creator of the route aggregation resource", Computed: true, }, "created_date_time": schema.StringAttribute{ - Description: "Creation time of the stream resource", + Description: "Creation time of the route aggregation resource", Computed: true, }, "updated_by": schema.StringAttribute{ - Description: "User name of last updater of the stream resource", + Description: "User name of last updater of the route aggregation resource", Computed: true, }, "updated_by_full_name": schema.StringAttribute{ - Description: "Legal name of last updater of the stream resource", + Description: "Legal name of last updater of the route aggregation resource", Computed: true, }, "updated_by_email": schema.StringAttribute{ - Description: "Email of last updater of the stream resource", + Description: "Email of last updater of the route aggregation resource", Computed: true, }, "updated_date_time": schema.StringAttribute{ - Description: "Last update time of the stream resource", + Description: "Last update time of the route aggregation resource", Computed: true, }, "deleted_by": schema.StringAttribute{ - Description: "User name of deleter of the stream resource", + Description: "User name of deleter of the route aggregation resource", Computed: true, }, "deleted_by_full_name": schema.StringAttribute{ - Description: "Legal name of deleter of the stream resource", + Description: "Legal name of deleter of the route aggregation resource", Computed: true, }, "deleted_by_email": schema.StringAttribute{ - Description: "Email of deleter of the stream resource", + Description: "Email of deleter of the route aggregation resource", Computed: true, }, "deleted_date_time": schema.StringAttribute{ - Description: "Deletion time of the stream resource", + Description: "Deletion time of the route aggregation resource", Computed: true, }, }, diff --git a/internal/resources/fabric/route_aggregation/datasource_test.go b/internal/resources/fabric/route_aggregation/datasource_test.go index dc1168d36..c1b2addc0 100644 --- a/internal/resources/fabric/route_aggregation/datasource_test.go +++ b/internal/resources/fabric/route_aggregation/datasource_test.go @@ -1,98 +1,97 @@ package route_aggregation_test -// -//import ( -// "fmt" -// "testing" -// -// "github.com/equinix/terraform-provider-equinix/internal/acceptance" -// "github.com/hashicorp/terraform-plugin-testing/helper/resource" -//) -// -//func testAccFabricRouteAggregationDataSourcesConfig(name, description string) string { -// return fmt.Sprintf(` -// -// resource "equinix_fabric_route_aggregation" "new_ra_1" { -// type = "BGP_IPv4_PREFIX_AGGREGATION" -// name = "%[1]s" -// description = "%[2]s" -// project = { -// project_id = "4f855852-eb47-4721-8e40-b386a3676abf" -// } -// } -// -// resource "equinix_fabric_route_aggregation" "new_ra_2" { -// type = "BGP_IPv4_PREFIX_AGGREGATION" -// name = "%[1]s" -// description = "%[2]s" -// project = { -// project_id = "4f855852-eb47-4721-8e40-b386a3676abf" -// } -// } -// -// data "equinix_fabric_route_aggregation" "data_ra" { -// route_aggregation_id = equinix_fabric_route_aggregation.new_ra_2.id -// } -// -// data "equinix_fabric_route_aggregations" "data_ras" { -// depends_on = [equinix_fabric_route_aggregation.new_ra_1, equinix_fabric_route_aggregation.new_ra_2] -// filter = { -// property = "/type" -// operator = "=" -// values = ["BGP_IPv4_PREFIX_AGGREGATION"] -// } -// pagination = { -// limit = 2 -// offset = 1 -// } -// sort = { -// property = "/changeLog/updatedDateTime" -// direction = "DESC" -// } -// } -// `, name, description) -//} -// -//func TestAccFabricRouteAggregationDataSources_PFCR(t *testing.T) { -// routeAggregationName := "route_agg_PFCR" -// routeAggregatioDescription := "route_agg_PFCR" -// resource.ParallelTest(t, resource.TestCase{ -// PreCheck: func() { acceptance.TestAccPreCheck(t); acceptance.TestAccPreCheckProviderConfigured(t) }, -// ExternalProviders: acceptance.TestExternalProviders, -// ProtoV6ProviderFactories: acceptance.ProtoV6ProviderFactories, -// CheckDestroy: CheckRouteAggregationDelete, -// Steps: []resource.TestStep{ -// { -// Config: testAccFabricRouteAggregationDataSourcesConfig(routeAggregationName, routeAggregatioDescription), -// Check: resource.ComposeTestCheckFunc( -// resource.TestCheckResourceAttr( -// "data.equinix_fabric_route_aggregation.data_ra", "name", routeAggregationName), -// resource.TestCheckResourceAttr( -// "data.equinix_fabric_route_aggregation.data_ra", "type", "BGP_IPv4_PREFIX_AGGREGATION"), -// resource.TestCheckResourceAttr( -// "data.equinix_fabric_route_aggregation.data_ra", "project.project_id", "4f855852-eb47-4721-8e40-b386a3676abf"), -// resource.TestCheckResourceAttr( -// "data.equinix_fabric_route_aggregation.data_ra", "description", routeAggregatioDescription), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "href"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "uuid"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "change_log.created_by"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.name"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.type"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.description"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.project.project_id"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.href"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.connections_count"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.rules_count"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.uuid"), -// resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.change_log.created_by"), -// resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "data.#", "2"), -// resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.%", "5"), -// resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.limit", "2"), -// resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.offset", "1"), -// ), -// ExpectNonEmptyPlan: false, -// }, -// }, -// }) -// -//} +import ( + "fmt" + "testing" + + "github.com/equinix/terraform-provider-equinix/internal/acceptance" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func testAccFabricRouteAggregationDataSourcesConfig(name, description string) string { + return fmt.Sprintf(` + + resource "equinix_fabric_route_aggregation" "new_ra_1" { + type = "BGP_IPv4_PREFIX_AGGREGATION" + name = "%[1]s" + description = "%[2]s" + project = { + project_id = "4f855852-eb47-4721-8e40-b386a3676abf" + } + } + + resource "equinix_fabric_route_aggregation" "new_ra_2" { + type = "BGP_IPv4_PREFIX_AGGREGATION" + name = "%[1]s" + description = "%[2]s" + project = { + project_id = "4f855852-eb47-4721-8e40-b386a3676abf" + } + } + + data "equinix_fabric_route_aggregation" "data_ra" { + route_aggregation_id = equinix_fabric_route_aggregation.new_ra_2.id + } + + data "equinix_fabric_route_aggregations" "data_ras" { + depends_on = [equinix_fabric_route_aggregation.new_ra_1, equinix_fabric_route_aggregation.new_ra_2] + filter = { + property = "/type" + operator = "=" + values = ["BGP_IPv4_PREFIX_AGGREGATION"] + } + pagination = { + limit = 2 + offset = 1 + } + sort = { + property = "/changeLog/updatedDateTime" + direction = "DESC" + } + } + `, name, description) +} + +func TestAccFabricRouteAggregationDataSources_PFCR(t *testing.T) { + routeAggregationName := "route_agg_PFCR" + routeAggregatioDescription := "route_agg_PFCR" + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acceptance.TestAccPreCheck(t); acceptance.TestAccPreCheckProviderConfigured(t) }, + ExternalProviders: acceptance.TestExternalProviders, + ProtoV6ProviderFactories: acceptance.ProtoV6ProviderFactories, + CheckDestroy: CheckRouteAggregationDelete, + Steps: []resource.TestStep{ + { + Config: testAccFabricRouteAggregationDataSourcesConfig(routeAggregationName, routeAggregatioDescription), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr( + "data.equinix_fabric_route_aggregation.data_ra", "name", routeAggregationName), + resource.TestCheckResourceAttr( + "data.equinix_fabric_route_aggregation.data_ra", "type", "BGP_IPv4_PREFIX_AGGREGATION"), + resource.TestCheckResourceAttr( + "data.equinix_fabric_route_aggregation.data_ra", "project.project_id", "4f855852-eb47-4721-8e40-b386a3676abf"), + resource.TestCheckResourceAttr( + "data.equinix_fabric_route_aggregation.data_ra", "description", routeAggregatioDescription), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "href"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "uuid"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregation.data_ra", "change_log.created_by"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.name"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.type"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.description"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.project.project_id"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.href"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.connections_count"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.rules_count"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.uuid"), + resource.TestCheckResourceAttrSet("data.equinix_fabric_route_aggregations.data_ras", "data.0.change_log.created_by"), + resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "data.#", "2"), + resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.%", "5"), + resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.limit", "2"), + resource.TestCheckResourceAttr("data.equinix_fabric_route_aggregations.data_ras", "pagination.offset", "1"), + ), + ExpectNonEmptyPlan: false, + }, + }, + }) + +} diff --git a/internal/resources/fabric/route_aggregation/models.go b/internal/resources/fabric/route_aggregation/models.go index 79198f131..568307da3 100644 --- a/internal/resources/fabric/route_aggregation/models.go +++ b/internal/resources/fabric/route_aggregation/models.go @@ -115,7 +115,7 @@ func (m *DatsSourceAllRouteAggregationsModel) parse(ctx context.Context, routeAg var diags diag.Diagnostics if len(routeAggregationsResponse.GetData()) < 1 { - diags.AddError("no data retrieved by streams data source", "either the account does not have any streams data to pull or the combination of limit and offset needs to be updated") + diags.AddError("no data retrieved by route aggregations data source", "either the account does not have any route aggregations data to pull or the combination of limit and offset needs to be updated") return diags } diff --git a/internal/resources/fabric/route_aggregation/resource.go b/internal/resources/fabric/route_aggregation/resource.go index 54f8b0ca9..478d50b45 100644 --- a/internal/resources/fabric/route_aggregation/resource.go +++ b/internal/resources/fabric/route_aggregation/resource.go @@ -142,7 +142,7 @@ func (r *Resource) Update( newName, oldName := plan.Name.ValueString(), plan.Name.ValueString() - if newName != oldName { + if newName == oldName { resp.Diagnostics.AddWarning("No updatable fields have changed", "Terraform detected a config change, but it is for a field that isn't updatable for the route aggregation resource. Please revert to prior config") return } @@ -205,7 +205,7 @@ func (r *Resource) Delete( _, deleteResp, err := client.RouteAggregationsApi.DeleteRouteAggregationByUuid(ctx, id).Execute() if err != nil { if deleteResp == nil || !slices.Contains([]int{http.StatusForbidden, http.StatusNotFound}, deleteResp.StatusCode) { - resp.Diagnostics.AddError(fmt.Sprintf("Failed deleting Stream %s", id), equinix_errors.FormatFabricError(err).Error()) + resp.Diagnostics.AddError(fmt.Sprintf("Failed deleting Route Aggregation %s", id), equinix_errors.FormatFabricError(err).Error()) return } } @@ -219,7 +219,7 @@ func (r *Resource) Delete( _, err = deletewaiter.WaitForStateContext(ctx) if err != nil { - resp.Diagnostics.AddError(fmt.Sprintf("Failed deleting Stream %s", id), err.Error()) + resp.Diagnostics.AddError(fmt.Sprintf("Failed deleting Route Aggregation %s", id), err.Error()) return } } diff --git a/internal/resources/fabric/route_aggregation/resource_schema.go b/internal/resources/fabric/route_aggregation/resource_schema.go index 2999841f6..bc2a37c46 100644 --- a/internal/resources/fabric/route_aggregation/resource_schema.go +++ b/internal/resources/fabric/route_aggregation/resource_schema.go @@ -90,7 +90,7 @@ func resourceSchema(ctx context.Context) schema.Schema { Computed: true, }, "change_log": schema.SingleNestedAttribute{ - Description: "Details of the last change on the stream resource", + Description: "Details of the last change on the route aggregation resource", Computed: true, PlanModifiers: []planmodifier.Object{ objectplanmodifier.UseStateForUnknown(), @@ -98,51 +98,51 @@ func resourceSchema(ctx context.Context) schema.Schema { CustomType: fwtypes.NewObjectTypeOf[ChangeLogModel](ctx), Attributes: map[string]schema.Attribute{ "created_by": schema.StringAttribute{ - Description: "User name of creator of the stream resource", + Description: "User name of creator of the route aggregation resource", Computed: true, }, "created_by_full_name": schema.StringAttribute{ - Description: "Legal name of creator of the stream resource", + Description: "Legal name of creator of the route aggregation resource", Computed: true, }, "created_by_email": schema.StringAttribute{ - Description: "Email of creator of the stream resource", + Description: "Email of creator of the route aggregation resource", Computed: true, }, "created_date_time": schema.StringAttribute{ - Description: "Creation time of the stream resource", + Description: "Creation time of the route aggregation resource", Computed: true, }, "updated_by": schema.StringAttribute{ - Description: "User name of last updater of the stream resource", + Description: "User name of last updater of the route aggregation resource", Computed: true, }, "updated_by_full_name": schema.StringAttribute{ - Description: "Legal name of last updater of the stream resource", + Description: "Legal name of last updater of the route aggregation resource", Computed: true, }, "updated_by_email": schema.StringAttribute{ - Description: "Email of last updater of the stream resource", + Description: "Email of last updater of the route aggregation resource", Computed: true, }, "updated_date_time": schema.StringAttribute{ - Description: "Last update time of the stream resource", + Description: "Last update time of the route aggregation resource", Computed: true, }, "deleted_by": schema.StringAttribute{ - Description: "User name of deleter of the stream resource", + Description: "User name of deleter of the route aggregation resource", Computed: true, }, "deleted_by_full_name": schema.StringAttribute{ - Description: "Legal name of deleter of the stream resource", + Description: "Legal name of deleter of the route aggregation resource", Computed: true, }, "deleted_by_email": schema.StringAttribute{ - Description: "Email of deleter of the stream resource", + Description: "Email of deleter of the route aggregation resource", Computed: true, }, "deleted_date_time": schema.StringAttribute{ - Description: "Deletion time of the stream resource", + Description: "Deletion time of the route aggregation resource", Computed: true, }, }, diff --git a/internal/resources/fabric/route_aggregation/resource_test.go b/internal/resources/fabric/route_aggregation/resource_test.go index db56efc2e..b33e4648c 100644 --- a/internal/resources/fabric/route_aggregation/resource_test.go +++ b/internal/resources/fabric/route_aggregation/resource_test.go @@ -92,7 +92,7 @@ func CheckRouteAggregationDelete(s *terraform.State) error { if routeAggregation, _, err := client.RouteAggregationsApi.GetRouteAggregationByUuid(ctx, rs.Primary.ID).Execute(); err == nil { if routeAggregation.GetState() == fabricv4.ROUTEAGGREGATIONSTATE_PROVISIONED { - return fmt.Errorf("fabric stream %s still exists and is %s", + return fmt.Errorf("fabric route aggregation %s still exists and is %s", rs.Primary.ID, routeAggregation.GetState()) } } From fde74f1b92e39705aa1b05b53dc12384ef3d3f29 Mon Sep 17 00:00:00 2001 From: srushti-patl Date: Thu, 6 Feb 2025 15:37:23 -0800 Subject: [PATCH 5/8] fix: Updating datasource test file --- docs/data-sources/fabric_route_aggregation.md | 28 ++++++++-------- .../data-sources/fabric_route_aggregations.md | 32 +++++++++---------- docs/index.md | 4 +-- docs/resources/fabric_route_aggregation.md | 26 +++++++-------- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/docs/data-sources/fabric_route_aggregation.md b/docs/data-sources/fabric_route_aggregation.md index 6064fa191..042bc66c4 100644 --- a/docs/data-sources/fabric_route_aggregation.md +++ b/docs/data-sources/fabric_route_aggregation.md @@ -4,7 +4,7 @@ subcategory: "Fabric" # equinix_fabric_route_aggregation (Data Source) -Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Stream by UUID +Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Route Aggregation by UUID Additional Documentation: * API: https://developer.equinix.com/catalog/fabricv4#tag/Route-Aggregations @@ -46,7 +46,7 @@ output "rules_count" { ### Read-Only - `change` (Attributes) Current state of latest Route Aggregation change (see [below for nested schema](#nestedatt--change)) -- `change_log` (Attributes) Details of the last change on the stream resource (see [below for nested schema](#nestedatt--change_log)) +- `change_log` (Attributes) Details of the last change on the route aggregation resource (see [below for nested schema](#nestedatt--change_log)) - `connections_count` (Number) Number of Connections attached to route aggregation - `description` (String) Customer-provided route aggregation description - `href` (String) Equinix auto generated URI to the route aggregation resource @@ -73,18 +73,18 @@ Read-Only: Read-Only: -- `created_by` (String) User name of creator of the stream resource -- `created_by_email` (String) Email of creator of the stream resource -- `created_by_full_name` (String) Legal name of creator of the stream resource -- `created_date_time` (String) Creation time of the stream resource -- `deleted_by` (String) User name of deleter of the stream resource -- `deleted_by_email` (String) Email of deleter of the stream resource -- `deleted_by_full_name` (String) Legal name of deleter of the stream resource -- `deleted_date_time` (String) Deletion time of the stream resource -- `updated_by` (String) User name of last updater of the stream resource -- `updated_by_email` (String) Email of last updater of the stream resource -- `updated_by_full_name` (String) Legal name of last updater of the stream resource -- `updated_date_time` (String) Last update time of the stream resource +- `created_by` (String) User name of creator of the route aggregation resource +- `created_by_email` (String) Email of creator of the route aggregation resource +- `created_by_full_name` (String) Legal name of creator of the route aggregation resource +- `created_date_time` (String) Creation time of the route aggregation resource +- `deleted_by` (String) User name of deleter of the route aggregation resource +- `deleted_by_email` (String) Email of deleter of the route aggregation resource +- `deleted_by_full_name` (String) Legal name of deleter of the route aggregation resource +- `deleted_date_time` (String) Deletion time of the route aggregation resource +- `updated_by` (String) User name of last updater of the route aggregation resource +- `updated_by_email` (String) Email of last updater of the route aggregation resource +- `updated_by_full_name` (String) Legal name of last updater of the route aggregation resource +- `updated_date_time` (String) Last update time of the route aggregation resource diff --git a/docs/data-sources/fabric_route_aggregations.md b/docs/data-sources/fabric_route_aggregations.md index 0b49a654a..4a4bd5c74 100644 --- a/docs/data-sources/fabric_route_aggregations.md +++ b/docs/data-sources/fabric_route_aggregations.md @@ -4,7 +4,7 @@ subcategory: "Fabric" # equinix_fabric_route_aggregations (Data Source) -Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Streams with pagination details +Fabric V4 API compatible data resource that allow user to fetch Equinix Fabric Route Aggregations with pagination details Additional Documentation: * Getting Started: https://docs.equinix.com/en-us/Content/KnowledgeCenter/Fabric/GettingStarted/Integrating-with-Fabric-V4-APIs/IntegrateWithSink.htm * API: https://developer.equinix.com/catalog/fabricv4#tag/Streams @@ -55,7 +55,7 @@ output "first_route_aggregation_rules_count" { ### Read-Only -- `data` (Attributes List) Returned list of stream objects (see [below for nested schema](#nestedatt--data)) +- `data` (Attributes List) Returned list of route aggregation objects (see [below for nested schema](#nestedatt--data)) - `id` (String) The unique identifier of the resource @@ -80,7 +80,7 @@ Read-Only: - `next` (String) The URL relative to the next item in the response - `previous` (String) The URL relative to the previous item in the response -- `total` (Number) The total number of streams available to the user making the request +- `total` (Number) The total number of route aggregations available to the user making the request @@ -98,7 +98,7 @@ Optional: Read-Only: - `change` (Attributes) Current state of latest Route Aggregation change (see [below for nested schema](#nestedatt--data--change)) -- `change_log` (Attributes) Details of the last change on the stream resource (see [below for nested schema](#nestedatt--data--change_log)) +- `change_log` (Attributes) Details of the last change on the route aggregation resource (see [below for nested schema](#nestedatt--data--change_log)) - `connections_count` (Number) Number of Connections attached to route aggregation - `description` (String) Customer-provided route aggregation description - `href` (String) Equinix auto generated URI to the route aggregation resource @@ -124,18 +124,18 @@ Read-Only: Read-Only: -- `created_by` (String) User name of creator of the stream resource -- `created_by_email` (String) Email of creator of the stream resource -- `created_by_full_name` (String) Legal name of creator of the stream resource -- `created_date_time` (String) Creation time of the stream resource -- `deleted_by` (String) User name of deleter of the stream resource -- `deleted_by_email` (String) Email of deleter of the stream resource -- `deleted_by_full_name` (String) Legal name of deleter of the stream resource -- `deleted_date_time` (String) Deletion time of the stream resource -- `updated_by` (String) User name of last updater of the stream resource -- `updated_by_email` (String) Email of last updater of the stream resource -- `updated_by_full_name` (String) Legal name of last updater of the stream resource -- `updated_date_time` (String) Last update time of the stream resource +- `created_by` (String) User name of creator of the route aggregation resource +- `created_by_email` (String) Email of creator of the route aggregation resource +- `created_by_full_name` (String) Legal name of creator of the route aggregation resource +- `created_date_time` (String) Creation time of the route aggregation resource +- `deleted_by` (String) User name of deleter of the route aggregation resource +- `deleted_by_email` (String) Email of deleter of the route aggregation resource +- `deleted_by_full_name` (String) Legal name of deleter of the route aggregation resource +- `deleted_date_time` (String) Deletion time of the route aggregation resource +- `updated_by` (String) User name of last updater of the route aggregation resource +- `updated_by_email` (String) Email of last updater of the route aggregation resource +- `updated_by_full_name` (String) Legal name of last updater of the route aggregation resource +- `updated_date_time` (String) Last update time of the route aggregation resource diff --git a/docs/index.md b/docs/index.md index fad52e4f9..3d35e10e0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,8 +1,8 @@ --- -page_title: "Equinix Provider" +page_title: "terraform-provider-equinix Provider" --- -# Equinix Provider +# terraform-provider-equinix Provider The Equinix provider is used to interact with the resources provided by Equinix Platform. The provider needs to be configured with the proper credentials before it can be used. diff --git a/docs/resources/fabric_route_aggregation.md b/docs/resources/fabric_route_aggregation.md index 6a808b9ba..b0a81ac11 100644 --- a/docs/resources/fabric_route_aggregation.md +++ b/docs/resources/fabric_route_aggregation.md @@ -36,7 +36,7 @@ resource "equinix_fabric_route_aggregation" "new-ra" { ### Read-Only - `change` (Attributes) Current state of latest Route Aggregation change (see [below for nested schema](#nestedatt--change)) -- `change_log` (Attributes) Details of the last change on the stream resource (see [below for nested schema](#nestedatt--change_log)) +- `change_log` (Attributes) Details of the last change on the route aggregation resource (see [below for nested schema](#nestedatt--change_log)) - `connections_count` (Number) Number of Connections attached to route aggregation - `href` (String) Equinix auto generated URI to the route aggregation resource - `id` (String) The unique identifier of the resource @@ -78,15 +78,15 @@ Required: Read-Only: -- `created_by` (String) User name of creator of the stream resource -- `created_by_email` (String) Email of creator of the stream resource -- `created_by_full_name` (String) Legal name of creator of the stream resource -- `created_date_time` (String) Creation time of the stream resource -- `deleted_by` (String) User name of deleter of the stream resource -- `deleted_by_email` (String) Email of deleter of the stream resource -- `deleted_by_full_name` (String) Legal name of deleter of the stream resource -- `deleted_date_time` (String) Deletion time of the stream resource -- `updated_by` (String) User name of last updater of the stream resource -- `updated_by_email` (String) Email of last updater of the stream resource -- `updated_by_full_name` (String) Legal name of last updater of the stream resource -- `updated_date_time` (String) Last update time of the stream resource +- `created_by` (String) User name of creator of the route aggregation resource +- `created_by_email` (String) Email of creator of the route aggregation resource +- `created_by_full_name` (String) Legal name of creator of the route aggregation resource +- `created_date_time` (String) Creation time of the route aggregation resource +- `deleted_by` (String) User name of deleter of the route aggregation resource +- `deleted_by_email` (String) Email of deleter of the route aggregation resource +- `deleted_by_full_name` (String) Legal name of deleter of the route aggregation resource +- `deleted_date_time` (String) Deletion time of the route aggregation resource +- `updated_by` (String) User name of last updater of the route aggregation resource +- `updated_by_email` (String) Email of last updater of the route aggregation resource +- `updated_by_full_name` (String) Legal name of last updater of the route aggregation resource +- `updated_date_time` (String) Last update time of the route aggregation resource From 292bce6a23d38ef5dbe75cca5a830076844faa21 Mon Sep 17 00:00:00 2001 From: srushti-patl Date: Fri, 21 Feb 2025 14:42:52 -0800 Subject: [PATCH 6/8] fix: Adding patch for Route Aggregation and Route Aggregation Patch Request --- go.mod | 3 ++- go.sum | 9 ++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 5aefb52e8..c7bad3f1f 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/equinix/terraform-provider-equinix go 1.23 require ( - github.com/equinix/equinix-sdk-go v0.48.0 + github.com/equinix/equinix-sdk-go v0.49.0 github.com/equinix/ne-go v1.19.0 github.com/equinix/oauth2-go v1.0.0 github.com/equinix/rest-go v1.3.0 @@ -95,6 +95,7 @@ require ( google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect google.golang.org/grpc v1.67.1 // indirect google.golang.org/protobuf v1.35.1 // indirect + gopkg.in/validator.v2 v2.0.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index add3d7b91..af1566f69 100644 --- a/go.sum +++ b/go.sum @@ -39,8 +39,8 @@ github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/equinix/equinix-sdk-go v0.48.0 h1:2iQmK8gX+PR83FqvnBDCyPlN8coxEmCKtDucf3tYc+M= -github.com/equinix/equinix-sdk-go v0.48.0/go.mod h1:uaiNpYcy2/zq7P2TKOOLO/kwO6SSLt6zJm0XUGPKb2M= +github.com/equinix/equinix-sdk-go v0.49.0 h1:7VNYQSHL4+m6v/dqH71+pIKNbU5KmTzOLaDovQGuHF8= +github.com/equinix/equinix-sdk-go v0.49.0/go.mod h1:tUf2f7SQyztsdCnI0pu2cVTGQvZvmFi6trEvVjdMyvY= github.com/equinix/ne-go v1.19.0 h1:aueOpe8yh/t3/mjhc/R3ZGAIPYSvixNQ/fU3t2HUQZk= github.com/equinix/ne-go v1.19.0/go.mod h1:eHkkxM4nbTB7DZ9X9zGnwfYnxIJWIsU3aHA+FAoZ1EI= github.com/equinix/oauth2-go v1.0.0 h1:fHtAPGq82PdgtK5vEThs8Vwz6f7D/8SX4tE3NJu+KcU= @@ -322,8 +322,11 @@ google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA= google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= +gopkg.in/validator.v2 v2.0.1 h1:xF0KWyGWXm/LM2G1TrEjqOu4pa6coO9AlWSf3msVfDY= +gopkg.in/validator.v2 v2.0.1/go.mod h1:lIUZBlB3Im4s/eYp39Ry/wkR02yOPhZ9IwIRBjuPuG8= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= From a38363c2e3de307fc2253f7fbac75d309cfcf6b6 Mon Sep 17 00:00:00 2001 From: srushti-patl Date: Mon, 24 Feb 2025 15:40:25 -0800 Subject: [PATCH 7/8] fix: Fixing lint erros --- go.mod | 2 +- internal/provider/services/fabric.go | 9 ++--- .../datasource_all_aggregations.go | 4 +-- .../datasource_by_routeAggregationId.go | 8 ++--- .../datasource_schema.go | 2 +- .../datasource_test.go | 2 +- .../models.go | 36 +++++++++---------- .../resource.go | 6 ++-- .../resource_schema.go | 2 +- .../resource_test.go | 2 +- .../sweeper.go | 2 +- internal/sweep/sweep_test.go | 2 +- 12 files changed, 39 insertions(+), 38 deletions(-) rename internal/resources/fabric/{route_aggregation => routeaggregation}/datasource_all_aggregations.go (98%) rename internal/resources/fabric/{route_aggregation => routeaggregation}/datasource_by_routeAggregationId.go (91%) rename internal/resources/fabric/{route_aggregation => routeaggregation}/datasource_schema.go (99%) rename internal/resources/fabric/{route_aggregation => routeaggregation}/datasource_test.go (99%) rename internal/resources/fabric/{route_aggregation => routeaggregation}/models.go (92%) rename internal/resources/fabric/{route_aggregation => routeaggregation}/resource.go (98%) rename internal/resources/fabric/{route_aggregation => routeaggregation}/resource_schema.go (99%) rename internal/resources/fabric/{route_aggregation => routeaggregation}/resource_test.go (99%) rename internal/resources/fabric/{route_aggregation => routeaggregation}/sweeper.go (98%) diff --git a/go.mod b/go.mod index bdb998708..5e7c7aaf6 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/equinix/terraform-provider-equinix -go 1.23 +go 1.23.0 require ( github.com/equinix/equinix-sdk-go v0.49.1 diff --git a/internal/provider/services/fabric.go b/internal/provider/services/fabric.go index b67c33a29..a2e1a687c 100644 --- a/internal/provider/services/fabric.go +++ b/internal/provider/services/fabric.go @@ -2,8 +2,9 @@ package services import ( "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/metro" - "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/route_aggregation" + "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/routeaggregation" "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/stream" + "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/resource" ) @@ -11,7 +12,7 @@ import ( func FabricResources() []func() resource.Resource { return []func() resource.Resource{ stream.NewResource, - route_aggregation.NewResource, + routeaggregation.NewResource, } } @@ -19,8 +20,8 @@ func FabricDatasources() []func() datasource.DataSource { return []func() datasource.DataSource{ metro.NewDataSourceMetroCode, metro.NewDataSourceMetros, - route_aggregation.NewDataSourceByRouteAggregationID, - route_aggregation.NewDataSourceAllRouteAggregation, + routeaggregation.NewDataSourceByRouteAggregationID, + routeaggregation.NewDataSourceAllRouteAggregation, stream.NewDataSourceByStreamID, stream.NewDataSourceAllStreams, } diff --git a/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go b/internal/resources/fabric/routeaggregation/datasource_all_aggregations.go similarity index 98% rename from internal/resources/fabric/route_aggregation/datasource_all_aggregations.go rename to internal/resources/fabric/routeaggregation/datasource_all_aggregations.go index 40a55b294..76a3adc88 100644 --- a/internal/resources/fabric/route_aggregation/datasource_all_aggregations.go +++ b/internal/resources/fabric/routeaggregation/datasource_all_aggregations.go @@ -1,4 +1,4 @@ -package route_aggregation +package routeaggregation import ( "context" @@ -26,7 +26,7 @@ type DataSourceAllRouteAggregations struct { func (r *DataSourceAllRouteAggregations) Schema( ctx context.Context, - req datasource.SchemaRequest, + _ datasource.SchemaRequest, resp *datasource.SchemaResponse, ) { resp.Schema = dataSourceAllRouteAggregationsSchema(ctx) diff --git a/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go b/internal/resources/fabric/routeaggregation/datasource_by_routeAggregationId.go similarity index 91% rename from internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go rename to internal/resources/fabric/routeaggregation/datasource_by_routeAggregationId.go index 5c3578ac6..b80ecce2c 100644 --- a/internal/resources/fabric/route_aggregation/datasource_by_routeAggregationId.go +++ b/internal/resources/fabric/routeaggregation/datasource_by_routeAggregationId.go @@ -1,4 +1,4 @@ -package route_aggregation +package routeaggregation import ( "context" @@ -24,7 +24,7 @@ type DataSourceByRouteAggregationID struct { func (r *DataSourceByRouteAggregationID) Schema( ctx context.Context, - req datasource.SchemaRequest, + _ datasource.SchemaRequest, resp *datasource.SchemaResponse, ) { resp.Schema = dataSourceSingleRouteAggregationSchema(ctx) @@ -33,13 +33,13 @@ func (r *DataSourceByRouteAggregationID) Schema( func (r *DataSourceByRouteAggregationID) Read(ctx context.Context, request datasource.ReadRequest, response *datasource.ReadResponse) { client := r.Meta.NewFabricClientForFramework(ctx, request.ProviderMeta) - var data DataSourceByIdModel + var data DataSourceByIDModel response.Diagnostics.Append(request.Config.Get(ctx, &data)...) if response.Diagnostics.HasError() { return } - routeAggregationID := data.RouteAggregationId.ValueString() + routeAggregationID := data.RouteAggregationID.ValueString() routeAggregation, _, err := client.RouteAggregationsApi.GetRouteAggregationByUuid(ctx, routeAggregationID).Execute() diff --git a/internal/resources/fabric/route_aggregation/datasource_schema.go b/internal/resources/fabric/routeaggregation/datasource_schema.go similarity index 99% rename from internal/resources/fabric/route_aggregation/datasource_schema.go rename to internal/resources/fabric/routeaggregation/datasource_schema.go index 1167c988c..1c274df75 100644 --- a/internal/resources/fabric/route_aggregation/datasource_schema.go +++ b/internal/resources/fabric/routeaggregation/datasource_schema.go @@ -1,4 +1,4 @@ -package route_aggregation +package routeaggregation import ( "context" diff --git a/internal/resources/fabric/route_aggregation/datasource_test.go b/internal/resources/fabric/routeaggregation/datasource_test.go similarity index 99% rename from internal/resources/fabric/route_aggregation/datasource_test.go rename to internal/resources/fabric/routeaggregation/datasource_test.go index b9fde66a1..cc5bdf19b 100644 --- a/internal/resources/fabric/route_aggregation/datasource_test.go +++ b/internal/resources/fabric/routeaggregation/datasource_test.go @@ -1,4 +1,4 @@ -package route_aggregation_test +package routeaggregation_test import ( "fmt" diff --git a/internal/resources/fabric/route_aggregation/models.go b/internal/resources/fabric/routeaggregation/models.go similarity index 92% rename from internal/resources/fabric/route_aggregation/models.go rename to internal/resources/fabric/routeaggregation/models.go index 7d3791a68..048ef5f85 100644 --- a/internal/resources/fabric/route_aggregation/models.go +++ b/internal/resources/fabric/routeaggregation/models.go @@ -1,4 +1,4 @@ -package route_aggregation +package routeaggregation import ( "context" @@ -10,8 +10,8 @@ import ( "github.com/hashicorp/terraform-plugin-framework/types" ) -type DataSourceByIdModel struct { - RouteAggregationId types.String `tfsdk:"route_aggregation_id"` +type DataSourceByIDModel struct { + RouteAggregationID types.String `tfsdk:"route_aggregation_id"` ID types.String `tfsdk:"id"` BaseRouteAggregationModel } @@ -54,7 +54,7 @@ type BaseRouteAggregationModel struct { Name types.String `tfsdk:"name"` Description types.String `tfsdk:"description"` Href types.String `tfsdk:"href"` - Uuid types.String `tfsdk:"uuid"` + UUID types.String `tfsdk:"uuid"` State types.String `tfsdk:"state"` ConnectionsCount types.Int32 `tfsdk:"connections_count"` RulesCount types.Int32 `tfsdk:"rules_count"` @@ -64,11 +64,11 @@ type BaseRouteAggregationModel struct { } type ProjectModel struct { - ProjectId types.String `tfsdk:"project_id"` + ProjectID types.String `tfsdk:"project_id"` } type ChangeModel struct { - Uuid types.String `tfsdk:"uuid"` + UUID types.String `tfsdk:"uuid"` Type types.String `tfsdk:"type"` Href types.String `tfsdk:"href"` } @@ -88,8 +88,8 @@ type ChangeLogModel struct { DeletedDateTime types.String `tfsdk:"deleted_date_time"` } -func (m *DataSourceByIdModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { - m.RouteAggregationId = types.StringValue(routeAggregation.GetUuid()) +func (m *DataSourceByIDModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { + m.RouteAggregationID = types.StringValue(routeAggregation.GetUuid()) m.ID = types.StringValue(routeAggregation.GetUuid()) if routeAggregation != nil { @@ -97,18 +97,18 @@ func (m *DataSourceByIdModel) parse(ctx context.Context, routeAggregation *fabri m.Name = types.StringValue(routeAggregation.GetName()) m.Description = types.StringValue(routeAggregation.GetDescription()) m.Href = types.StringValue(routeAggregation.GetHref()) - m.Uuid = types.StringValue(routeAggregation.GetUuid()) + m.UUID = types.StringValue(routeAggregation.GetUuid()) m.State = types.StringValue(string(routeAggregation.GetState())) m.ConnectionsCount = types.Int32Value(routeAggregation.GetConnectionsCount()) m.RulesCount = types.Int32Value(routeAggregation.GetRulesCount()) routeAggregationProject := routeAggregation.GetProject() projectModel := ProjectModel{ - ProjectId: types.StringValue(routeAggregationProject.GetProjectId()), + ProjectID: types.StringValue(routeAggregationProject.GetProjectId()), } m.Project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel) routeAggregationChange := routeAggregation.GetChange() changeModel := ChangeModel{ - Uuid: types.StringValue(routeAggregationChange.GetUuid()), + UUID: types.StringValue(routeAggregationChange.GetUuid()), Type: types.StringValue(string(routeAggregationChange.GetType())), Href: types.StringValue(routeAggregationChange.GetHref()), } @@ -161,7 +161,7 @@ func (m *DatsSourceAllRouteAggregationsModel) parse(ctx context.Context, routeAg Next: types.StringValue(responsePagination.GetNext()), Previous: types.StringValue(responsePagination.GetPrevious()), } - m.ID = types.StringValue(data[0].Uuid.ValueString()) + m.ID = types.StringValue(data[0].UUID.ValueString()) m.Pagination = fwtypes.NewObjectValueOf[PaginationModel](ctx, &pagination) dataPtr := make([]*BaseRouteAggregationModel, len(data)) @@ -181,18 +181,18 @@ func (m *ResourceModel) parse(ctx context.Context, routeAggregation *fabricv4.Ro m.Name = types.StringValue(routeAggregation.GetName()) m.Description = types.StringValue(routeAggregation.GetDescription()) m.Href = types.StringValue(routeAggregation.GetHref()) - m.Uuid = types.StringValue(routeAggregation.GetUuid()) + m.UUID = types.StringValue(routeAggregation.GetUuid()) m.State = types.StringValue(string(routeAggregation.GetState())) m.ConnectionsCount = types.Int32Value(routeAggregation.GetConnectionsCount()) m.RulesCount = types.Int32Value(routeAggregation.GetRulesCount()) routeAggregationProject := routeAggregation.GetProject() projectModel := ProjectModel{ - ProjectId: types.StringValue(routeAggregationProject.GetProjectId()), + ProjectID: types.StringValue(routeAggregationProject.GetProjectId()), } m.Project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel) routeAggregationChange := routeAggregation.GetChange() changeModel := ChangeModel{ - Uuid: types.StringValue(routeAggregationChange.GetUuid()), + UUID: types.StringValue(routeAggregationChange.GetUuid()), Type: types.StringValue(string(routeAggregationChange.GetType())), Href: types.StringValue(routeAggregationChange.GetHref()), } @@ -226,18 +226,18 @@ func (m *BaseRouteAggregationModel) parse(ctx context.Context, routeAggregation m.Name = types.StringValue(routeAggregation.GetName()) m.Description = types.StringValue(routeAggregation.GetDescription()) m.Href = types.StringValue(routeAggregation.GetHref()) - m.Uuid = types.StringValue(routeAggregation.GetUuid()) + m.UUID = types.StringValue(routeAggregation.GetUuid()) m.State = types.StringValue(string(routeAggregation.GetState())) m.ConnectionsCount = types.Int32Value(routeAggregation.GetConnectionsCount()) m.RulesCount = types.Int32Value(routeAggregation.GetRulesCount()) routeAggregationProject := routeAggregation.GetProject() projectModel := ProjectModel{ - ProjectId: types.StringValue(routeAggregationProject.GetProjectId()), + ProjectID: types.StringValue(routeAggregationProject.GetProjectId()), } m.Project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel) routeAggregationChange := routeAggregation.GetChange() changeModel := ChangeModel{ - Uuid: types.StringValue(routeAggregationChange.GetUuid()), + UUID: types.StringValue(routeAggregationChange.GetUuid()), Type: types.StringValue(string(routeAggregationChange.GetType())), Href: types.StringValue(routeAggregationChange.GetHref()), } diff --git a/internal/resources/fabric/route_aggregation/resource.go b/internal/resources/fabric/routeaggregation/resource.go similarity index 98% rename from internal/resources/fabric/route_aggregation/resource.go rename to internal/resources/fabric/routeaggregation/resource.go index 44f2a788d..343c778a3 100644 --- a/internal/resources/fabric/route_aggregation/resource.go +++ b/internal/resources/fabric/routeaggregation/resource.go @@ -1,4 +1,4 @@ -package route_aggregation +package routeaggregation import ( "context" @@ -30,7 +30,7 @@ type Resource struct { framework.BaseResource } -func (r Resource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) { +func (r Resource) Schema(ctx context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = resourceSchema(ctx) } @@ -235,7 +235,7 @@ func buildCreateRequest(ctx context.Context, plan ResourceModel) (fabricv4.Route if diags.HasError() { return fabricv4.RouteAggregationsBase{}, diags } - request.SetProject(fabricv4.Project{ProjectId: project.ProjectId.ValueString()}) + request.SetProject(fabricv4.Project{ProjectId: project.ProjectID.ValueString()}) } return request, diags } diff --git a/internal/resources/fabric/route_aggregation/resource_schema.go b/internal/resources/fabric/routeaggregation/resource_schema.go similarity index 99% rename from internal/resources/fabric/route_aggregation/resource_schema.go rename to internal/resources/fabric/routeaggregation/resource_schema.go index 0b8c44222..871fcd7f7 100644 --- a/internal/resources/fabric/route_aggregation/resource_schema.go +++ b/internal/resources/fabric/routeaggregation/resource_schema.go @@ -1,4 +1,4 @@ -package route_aggregation +package routeaggregation import ( "context" diff --git a/internal/resources/fabric/route_aggregation/resource_test.go b/internal/resources/fabric/routeaggregation/resource_test.go similarity index 99% rename from internal/resources/fabric/route_aggregation/resource_test.go rename to internal/resources/fabric/routeaggregation/resource_test.go index cfeb9dc02..dc173fbe4 100644 --- a/internal/resources/fabric/route_aggregation/resource_test.go +++ b/internal/resources/fabric/routeaggregation/resource_test.go @@ -1,4 +1,4 @@ -package route_aggregation_test +package routeaggregation_test import ( "context" diff --git a/internal/resources/fabric/route_aggregation/sweeper.go b/internal/resources/fabric/routeaggregation/sweeper.go similarity index 98% rename from internal/resources/fabric/route_aggregation/sweeper.go rename to internal/resources/fabric/routeaggregation/sweeper.go index 5e318b66c..7179bb0b0 100644 --- a/internal/resources/fabric/route_aggregation/sweeper.go +++ b/internal/resources/fabric/routeaggregation/sweeper.go @@ -1,4 +1,4 @@ -package route_aggregation +package routeaggregation import ( "context" diff --git a/internal/sweep/sweep_test.go b/internal/sweep/sweep_test.go index 023d37ada..7abfe94d8 100644 --- a/internal/sweep/sweep_test.go +++ b/internal/sweep/sweep_test.go @@ -5,8 +5,8 @@ import ( fabric_cloud_router "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/cloud_router" fabric_connection "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/connection" - fabric_route_aggregation "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/route_aggregation" fabric_route_filter "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/route_filter" + fabric_route_aggregation "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/routeaggregation" fabric_stream "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/stream" "github.com/equinix/terraform-provider-equinix/internal/resources/fabric/network" From 4de8b90fffeba79a91ce39b59a67ccffe4bb5c3c Mon Sep 17 00:00:00 2001 From: srushti-patl Date: Mon, 24 Feb 2025 17:01:32 -0800 Subject: [PATCH 8/8] fix: Updating PR comments --- .../fabric/routeaggregation/models.go | 171 +++++------------- .../fabric/routeaggregation/resource.go | 6 +- 2 files changed, 47 insertions(+), 130 deletions(-) diff --git a/internal/resources/fabric/routeaggregation/models.go b/internal/resources/fabric/routeaggregation/models.go index 048ef5f85..1b956bb0f 100644 --- a/internal/resources/fabric/routeaggregation/models.go +++ b/internal/resources/fabric/routeaggregation/models.go @@ -91,48 +91,8 @@ type ChangeLogModel struct { func (m *DataSourceByIDModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { m.RouteAggregationID = types.StringValue(routeAggregation.GetUuid()) m.ID = types.StringValue(routeAggregation.GetUuid()) - - if routeAggregation != nil { - m.Type = types.StringValue(string(routeAggregation.GetType())) - m.Name = types.StringValue(routeAggregation.GetName()) - m.Description = types.StringValue(routeAggregation.GetDescription()) - m.Href = types.StringValue(routeAggregation.GetHref()) - m.UUID = types.StringValue(routeAggregation.GetUuid()) - m.State = types.StringValue(string(routeAggregation.GetState())) - m.ConnectionsCount = types.Int32Value(routeAggregation.GetConnectionsCount()) - m.RulesCount = types.Int32Value(routeAggregation.GetRulesCount()) - routeAggregationProject := routeAggregation.GetProject() - projectModel := ProjectModel{ - ProjectID: types.StringValue(routeAggregationProject.GetProjectId()), - } - m.Project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel) - routeAggregationChange := routeAggregation.GetChange() - changeModel := ChangeModel{ - UUID: types.StringValue(routeAggregationChange.GetUuid()), - Type: types.StringValue(string(routeAggregationChange.GetType())), - Href: types.StringValue(routeAggregationChange.GetHref()), - } - m.Change = fwtypes.NewObjectValueOf[ChangeModel](ctx, &changeModel) - - const TIMEFORMAT = "2008-02-02T14:02:02.000Z" - routeAggregationChangeLog := routeAggregation.GetChangeLog() - changeLogModel := ChangeLogModel{ - CreatedBy: types.StringValue(routeAggregationChangeLog.GetCreatedBy()), - CreatedByFullName: types.StringValue(routeAggregationChangeLog.GetCreatedByFullName()), - CreatedByEmail: types.StringValue(routeAggregationChangeLog.GetCreatedByEmail()), - CreatedDateTime: types.StringValue(routeAggregationChangeLog.GetCreatedDateTime().Format(TIMEFORMAT)), - UpdatedBy: types.StringValue(routeAggregationChangeLog.GetUpdatedBy()), - UpdatedByFullName: types.StringValue(routeAggregationChangeLog.GetUpdatedByFullName()), - UpdatedByEmail: types.StringValue(routeAggregationChangeLog.GetUpdatedByEmail()), - UpdatedDateTime: types.StringValue(routeAggregationChangeLog.GetUpdatedDateTime().Format(TIMEFORMAT)), - DeletedBy: types.StringValue(routeAggregationChangeLog.GetDeletedBy()), - DeletedByFullName: types.StringValue(routeAggregationChangeLog.GetDeletedByFullName()), - DeletedByEmail: types.StringValue(routeAggregationChangeLog.GetDeletedByEmail()), - DeletedDateTime: types.StringValue(routeAggregationChangeLog.GetDeletedDateTime().Format(TIMEFORMAT)), - } - m.ChangeLog = fwtypes.NewObjectValueOf[ChangeLogModel](ctx, &changeLogModel) - } - return nil + diags := m.BaseRouteAggregationModel.parse(ctx, routeAggregation) + return diags } func (m *DatsSourceAllRouteAggregationsModel) parse(ctx context.Context, routeAggregationsResponse *fabricv4.RouteAggregationsSearchResponse) diag.Diagnostics { @@ -173,93 +133,52 @@ func (m *DatsSourceAllRouteAggregationsModel) parse(ctx context.Context, routeAg return diags } func (m *ResourceModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { - m.ID = types.StringValue(routeAggregation.GetUuid()) - - if routeAggregation != nil { - m.Type = types.StringValue(string(routeAggregation.GetType())) - m.Name = types.StringValue(routeAggregation.GetName()) - m.Description = types.StringValue(routeAggregation.GetDescription()) - m.Href = types.StringValue(routeAggregation.GetHref()) - m.UUID = types.StringValue(routeAggregation.GetUuid()) - m.State = types.StringValue(string(routeAggregation.GetState())) - m.ConnectionsCount = types.Int32Value(routeAggregation.GetConnectionsCount()) - m.RulesCount = types.Int32Value(routeAggregation.GetRulesCount()) - routeAggregationProject := routeAggregation.GetProject() - projectModel := ProjectModel{ - ProjectID: types.StringValue(routeAggregationProject.GetProjectId()), - } - m.Project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel) - routeAggregationChange := routeAggregation.GetChange() - changeModel := ChangeModel{ - UUID: types.StringValue(routeAggregationChange.GetUuid()), - Type: types.StringValue(string(routeAggregationChange.GetType())), - Href: types.StringValue(routeAggregationChange.GetHref()), - } - m.Change = fwtypes.NewObjectValueOf[ChangeModel](ctx, &changeModel) - - const TIMEFORMAT = "2008-02-02T14:02:02.000Z" - routeAggregationChangeLog := routeAggregation.GetChangeLog() - changeLogModel := ChangeLogModel{ - CreatedBy: types.StringValue(routeAggregationChangeLog.GetCreatedBy()), - CreatedByFullName: types.StringValue(routeAggregationChangeLog.GetCreatedByFullName()), - CreatedByEmail: types.StringValue(routeAggregationChangeLog.GetCreatedByEmail()), - CreatedDateTime: types.StringValue(routeAggregationChangeLog.GetCreatedDateTime().Format(TIMEFORMAT)), - UpdatedBy: types.StringValue(routeAggregationChangeLog.GetUpdatedBy()), - UpdatedByFullName: types.StringValue(routeAggregationChangeLog.GetUpdatedByFullName()), - UpdatedByEmail: types.StringValue(routeAggregationChangeLog.GetUpdatedByEmail()), - UpdatedDateTime: types.StringValue(routeAggregationChangeLog.GetUpdatedDateTime().Format(TIMEFORMAT)), - DeletedBy: types.StringValue(routeAggregationChangeLog.GetDeletedBy()), - DeletedByFullName: types.StringValue(routeAggregationChangeLog.GetDeletedByFullName()), - DeletedByEmail: types.StringValue(routeAggregationChangeLog.GetDeletedByEmail()), - DeletedDateTime: types.StringValue(routeAggregationChangeLog.GetDeletedDateTime().Format(TIMEFORMAT)), - } - m.ChangeLog = fwtypes.NewObjectValueOf[ChangeLogModel](ctx, &changeLogModel) - } - return nil - + diags := m.BaseRouteAggregationModel.parse(ctx, routeAggregation) + return diags } func (m *BaseRouteAggregationModel) parse(ctx context.Context, routeAggregation *fabricv4.RouteAggregationsData) diag.Diagnostics { - if routeAggregation != nil { - m.Type = types.StringValue(string(routeAggregation.GetType())) - m.Name = types.StringValue(routeAggregation.GetName()) - m.Description = types.StringValue(routeAggregation.GetDescription()) - m.Href = types.StringValue(routeAggregation.GetHref()) - m.UUID = types.StringValue(routeAggregation.GetUuid()) - m.State = types.StringValue(string(routeAggregation.GetState())) - m.ConnectionsCount = types.Int32Value(routeAggregation.GetConnectionsCount()) - m.RulesCount = types.Int32Value(routeAggregation.GetRulesCount()) - routeAggregationProject := routeAggregation.GetProject() - projectModel := ProjectModel{ - ProjectID: types.StringValue(routeAggregationProject.GetProjectId()), - } - m.Project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel) - routeAggregationChange := routeAggregation.GetChange() - changeModel := ChangeModel{ - UUID: types.StringValue(routeAggregationChange.GetUuid()), - Type: types.StringValue(string(routeAggregationChange.GetType())), - Href: types.StringValue(routeAggregationChange.GetHref()), - } - m.Change = fwtypes.NewObjectValueOf[ChangeModel](ctx, &changeModel) - - const TIMEFORMAT = "2008-02-02T14:02:02.000Z" - routeAggregationChangeLog := routeAggregation.GetChangeLog() - changeLogModel := ChangeLogModel{ - CreatedBy: types.StringValue(routeAggregationChangeLog.GetCreatedBy()), - CreatedByFullName: types.StringValue(routeAggregationChangeLog.GetCreatedByFullName()), - CreatedByEmail: types.StringValue(routeAggregationChangeLog.GetCreatedByEmail()), - CreatedDateTime: types.StringValue(routeAggregationChangeLog.GetCreatedDateTime().Format(TIMEFORMAT)), - UpdatedBy: types.StringValue(routeAggregationChangeLog.GetUpdatedBy()), - UpdatedByFullName: types.StringValue(routeAggregationChangeLog.GetUpdatedByFullName()), - UpdatedByEmail: types.StringValue(routeAggregationChangeLog.GetUpdatedByEmail()), - UpdatedDateTime: types.StringValue(routeAggregationChangeLog.GetUpdatedDateTime().Format(TIMEFORMAT)), - DeletedBy: types.StringValue(routeAggregationChangeLog.GetDeletedBy()), - DeletedByFullName: types.StringValue(routeAggregationChangeLog.GetDeletedByFullName()), - DeletedByEmail: types.StringValue(routeAggregationChangeLog.GetDeletedByEmail()), - DeletedDateTime: types.StringValue(routeAggregationChangeLog.GetDeletedDateTime().Format(TIMEFORMAT)), - } - m.ChangeLog = fwtypes.NewObjectValueOf[ChangeLogModel](ctx, &changeLogModel) + var diag diag.Diagnostics + + m.Type = types.StringValue(string(routeAggregation.GetType())) + m.Name = types.StringValue(routeAggregation.GetName()) + m.Description = types.StringValue(routeAggregation.GetDescription()) + m.Href = types.StringValue(routeAggregation.GetHref()) + m.UUID = types.StringValue(routeAggregation.GetUuid()) + m.State = types.StringValue(string(routeAggregation.GetState())) + m.ConnectionsCount = types.Int32Value(routeAggregation.GetConnectionsCount()) + m.RulesCount = types.Int32Value(routeAggregation.GetRulesCount()) + routeAggregationProject := routeAggregation.GetProject() + projectModel := ProjectModel{ + ProjectID: types.StringValue(routeAggregationProject.GetProjectId()), + } + m.Project = fwtypes.NewObjectValueOf[ProjectModel](ctx, &projectModel) + routeAggregationChange := routeAggregation.GetChange() + changeModel := ChangeModel{ + UUID: types.StringValue(routeAggregationChange.GetUuid()), + Type: types.StringValue(string(routeAggregationChange.GetType())), + Href: types.StringValue(routeAggregationChange.GetHref()), } - return nil + m.Change = fwtypes.NewObjectValueOf[ChangeModel](ctx, &changeModel) + + const TIMEFORMAT = "2008-02-02T14:02:02.000Z" + routeAggregationChangeLog := routeAggregation.GetChangeLog() + changeLogModel := ChangeLogModel{ + CreatedBy: types.StringValue(routeAggregationChangeLog.GetCreatedBy()), + CreatedByFullName: types.StringValue(routeAggregationChangeLog.GetCreatedByFullName()), + CreatedByEmail: types.StringValue(routeAggregationChangeLog.GetCreatedByEmail()), + CreatedDateTime: types.StringValue(routeAggregationChangeLog.GetCreatedDateTime().Format(TIMEFORMAT)), + UpdatedBy: types.StringValue(routeAggregationChangeLog.GetUpdatedBy()), + UpdatedByFullName: types.StringValue(routeAggregationChangeLog.GetUpdatedByFullName()), + UpdatedByEmail: types.StringValue(routeAggregationChangeLog.GetUpdatedByEmail()), + UpdatedDateTime: types.StringValue(routeAggregationChangeLog.GetUpdatedDateTime().Format(TIMEFORMAT)), + DeletedBy: types.StringValue(routeAggregationChangeLog.GetDeletedBy()), + DeletedByFullName: types.StringValue(routeAggregationChangeLog.GetDeletedByFullName()), + DeletedByEmail: types.StringValue(routeAggregationChangeLog.GetDeletedByEmail()), + DeletedDateTime: types.StringValue(routeAggregationChangeLog.GetDeletedDateTime().Format(TIMEFORMAT)), + } + m.ChangeLog = fwtypes.NewObjectValueOf[ChangeLogModel](ctx, &changeLogModel) + + return diag } diff --git a/internal/resources/fabric/routeaggregation/resource.go b/internal/resources/fabric/routeaggregation/resource.go index 343c778a3..dbcc5e02c 100644 --- a/internal/resources/fabric/routeaggregation/resource.go +++ b/internal/resources/fabric/routeaggregation/resource.go @@ -50,6 +50,7 @@ func (r *Resource) Create( createRequest, diags := buildCreateRequest(ctx, plan) if diags.HasError() { + resp.Diagnostics.Append(diags...) return } @@ -73,10 +74,6 @@ func (r *Resource) Create( return } - if diags.HasError() { - return - } - resp.Diagnostics.Append(plan.parse(ctx, routeAggregationChecked.(*fabricv4.RouteAggregationsData))...) if resp.Diagnostics.HasError() { return @@ -271,6 +268,7 @@ func getDeleteWaiter(ctx context.Context, client *fabricv4.APIClient, id string, string(fabricv4.ROUTEAGGREGATIONSTATE_DEPROVISIONING), }, Target: []string{ + deletedMarker, string(fabricv4.ROUTEAGGREGATIONSTATE_DEPROVISIONED), }, Refresh: func() (interface{}, string, error) {