From b70654aaa293c7fbab2b06080863d1e42a057155 Mon Sep 17 00:00:00 2001 From: Kim Schuhmacher Date: Fri, 19 Jan 2024 12:36:34 +0100 Subject: [PATCH] Implement PeeringConnection read to VPC Implement reading peering connection and mapping the values for VPC as a datasource --- docs/data-sources/vpcs.md | 11 +- internal/client/queries/create_vpc.graphql | 12 -- internal/client/queries/vpc_by_id.graphql | 1 - internal/client/queries/vpc_by_name.graphql | 1 - internal/client/queries/vpcs.graphql | 25 ++- internal/client/vpc.go | 10 +- internal/provider/vpcs_data_source.go | 164 ++++++++++---------- internal/provider/vpcs_data_source_test.go | 30 ++++ 8 files changed, 132 insertions(+), 122 deletions(-) create mode 100644 internal/provider/vpcs_data_source_test.go diff --git a/docs/data-sources/vpcs.md b/docs/data-sources/vpcs.md index f6f18f2..fdc5aa3 100644 --- a/docs/data-sources/vpcs.md +++ b/docs/data-sources/vpcs.md @@ -30,7 +30,7 @@ Read-Only: - `error_message` (String) - `id` (Number) - `name` (String) -- `peering_connections` (Attributes List) (see [below for nested schema](#nestedatt--vpcs--peering_connections)) +- `peering_connections` (List of Object) (see [below for nested schema](#nestedatt--vpcs--peering_connections)) - `project_id` (String) - `provisioned_id` (String) - `region_code` (String) @@ -43,17 +43,16 @@ Read-Only: Read-Only: - `error_message` (String) -- `id` (Number) -- `peer_vpc` (Attributes List) (see [below for nested schema](#nestedatt--vpcs--peering_connections--peer_vpc)) +- `peer_vpc` (Object) (see [below for nested schema](#nestedobjatt--vpcs--peering_connections--peer_vpc)) - `status` (String) -- `vpc_id` (Number) +- `vpc_id` (String) - + ### Nested Schema for `vpcs.peering_connections.peer_vpc` Read-Only: - `account_id` (String) - `cidr` (String) -- `id` (Number) +- `id` (String) - `region_code` (String) diff --git a/internal/client/queries/create_vpc.graphql b/internal/client/queries/create_vpc.graphql index 132ef5e..0b8b36b 100644 --- a/internal/client/queries/create_vpc.graphql +++ b/internal/client/queries/create_vpc.graphql @@ -12,18 +12,6 @@ mutation CreateVPC($projectId: ID!, $name: String!, $cidr: String!, $regionCode: name created updated - # peeringConnections { - # id - # vpcId - # peerVpc { - # id - # accountId - # regionCode - # cidr - # } - # errorMessage - # status - # } errorMessage status regionCode diff --git a/internal/client/queries/vpc_by_id.graphql b/internal/client/queries/vpc_by_id.graphql index 176affe..d6d923c 100644 --- a/internal/client/queries/vpc_by_id.graphql +++ b/internal/client/queries/vpc_by_id.graphql @@ -7,7 +7,6 @@ created updated # peeringConnections { - # id # vpcId # peerVpc { # id diff --git a/internal/client/queries/vpc_by_name.graphql b/internal/client/queries/vpc_by_name.graphql index fa602f5..e81480f 100644 --- a/internal/client/queries/vpc_by_name.graphql +++ b/internal/client/queries/vpc_by_name.graphql @@ -10,7 +10,6 @@ query GetVPCByName($projectId: ID!, $name: String!) { created updated # peeringConnections { - # id # vpcId # peerVpc { # id diff --git a/internal/client/queries/vpcs.graphql b/internal/client/queries/vpcs.graphql index 2d5dcad..f804d44 100644 --- a/internal/client/queries/vpcs.graphql +++ b/internal/client/queries/vpcs.graphql @@ -1,4 +1,4 @@ - query GetAllVpcs($projectId: ID!) { + query GetAllVPCs($projectId: ID!) { getAllVpcs(projectId: $projectId) { id projectId @@ -6,18 +6,17 @@ name created updated - # peeringConnections { - # id - # vpcId - # peerVpc { - # id - # accountId - # regionCode - # cidr - # } - # errorMessage - # status - # } + peeringConnections { + vpcId + peerVpc { + id + accountId + regionCode + cidr + } + errorMessage + status + } errorMessage status regionCode diff --git a/internal/client/vpc.go b/internal/client/vpc.go index 19b26ba..5c39b2a 100644 --- a/internal/client/vpc.go +++ b/internal/client/vpc.go @@ -25,11 +25,11 @@ type VPC struct { } type PeeringConnection struct { - ID string `json:"id"` - VPCID string `json:"vpcId"` - Status string `json:"status"` - ErrorMessage string `json:"errorMessage"` - PeerVPCs []*PeerVPC `json:"peerVPC"` + ID string `json:"id"` + VPCID string `json:"vpcId"` + Status string `json:"status"` + ErrorMessage string `json:"errorMessage"` + PeerVPCs *PeerVPC `json:"peerVPC"` } type PeerVPC struct { diff --git a/internal/provider/vpcs_data_source.go b/internal/provider/vpcs_data_source.go index 4a081fa..2641f6a 100644 --- a/internal/provider/vpcs_data_source.go +++ b/internal/provider/vpcs_data_source.go @@ -5,6 +5,7 @@ import ( "fmt" "strconv" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" "github.com/hashicorp/terraform-plugin-framework/types" @@ -23,6 +24,31 @@ func NewVpcsDataSource() datasource.DataSource { return &vpcsDataSource{} } +var ( + PeerVpcDSType = map[string]attr.Type{ + "id": types.StringType, + "cidr": types.StringType, + "account_id": types.StringType, + "region_code": types.StringType, + } + + PeeringConnectionsDSType = types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "vpc_id": types.StringType, + "status": types.StringType, + "error_message": types.StringType, + "peer_vpc": types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "id": types.StringType, + "cidr": types.StringType, + "account_id": types.StringType, + "region_code": types.StringType, + }, + }, + }, + } +) + // vpcsDataSource is the data source implementation. type vpcsDataSource struct { client *tsClient.Client @@ -30,36 +56,35 @@ type vpcsDataSource struct { // vpcsDataSourceModel maps the data source schema data. type vpcsDataSourceModel struct { - Vpcs []vpcDataSourceModel `tfsdk:"vpcs"` + Vpcs []vpcDSModel `tfsdk:"vpcs"` // following is a placeholder, required by terraform to run test suite ID types.String `tfsdk:"id"` } // vpcDataSourceModel maps vpcs schema data. -type vpcDataSourceModel struct { - ID types.Int64 `tfsdk:"id"` - ProvisionedID types.String `tfsdk:"provisioned_id"` - ProjectID types.String `tfsdk:"project_id"` - CIDR types.String `tfsdk:"cidr"` - Name types.String `tfsdk:"name"` - RegionCode types.String `tfsdk:"region_code"` - Status types.String `tfsdk:"status"` - ErrorMessage types.String `tfsdk:"error_message"` - Created types.String `tfsdk:"created"` - Updated types.String `tfsdk:"updated"` - PeeringConnections []*peeringConnectionModel `tfsdk:"peering_connections"` +type vpcDSModel struct { + ID types.Int64 `tfsdk:"id"` + ProvisionedID types.String `tfsdk:"provisioned_id"` + ProjectID types.String `tfsdk:"project_id"` + CIDR types.String `tfsdk:"cidr"` + Name types.String `tfsdk:"name"` + RegionCode types.String `tfsdk:"region_code"` + Status types.String `tfsdk:"status"` + ErrorMessage types.String `tfsdk:"error_message"` + Created types.String `tfsdk:"created"` + Updated types.String `tfsdk:"updated"` + PeeringConnections []peeringConnectionDSModel `tfsdk:"peering_connections"` } -type peeringConnectionModel struct { - ID types.Int64 `tfsdk:"id"` - VpcID types.Int64 `tfsdk:"vpc_id"` - Status types.String `tfsdk:"status"` - ErrorMessage types.String `tfsdk:"error_message"` - PeerVpcs []*peerVpcModel `tfsdk:"peer_vpc"` +type peeringConnectionDSModel struct { + VpcID types.String `tfsdk:"vpc_id"` + Status types.String `tfsdk:"status"` + ErrorMessage types.String `tfsdk:"error_message"` + PeerVpcs types.Object `tfsdk:"peer_vpc"` } -type peerVpcModel struct { - ID types.Int64 `tfsdk:"id"` +type peerVpcDSModel struct { + ID types.String `tfsdk:"id"` CIDR types.String `tfsdk:"cidr"` AccountID types.String `tfsdk:"account_id"` RegionCode types.String `tfsdk:"region_code"` @@ -89,50 +114,41 @@ func (d *vpcsDataSource) Read(ctx context.Context, req datasource.ReadRequest, r resp.Diagnostics.AddError("Unable to Convert Vpc ID", err.Error()) return } - vpcState := vpcDataSourceModel{ + vpcState := vpcDSModel{ ID: types.Int64Value(vpcId), Name: types.StringValue(vpc.Name), ProvisionedID: types.StringValue(vpc.ProvisionedID), ProjectID: types.StringValue(vpc.ProjectID), CIDR: types.StringValue(vpc.CIDR), - RegionCode: types.StringValue(vpc.RegionCode), Status: types.StringValue(vpc.Status), ErrorMessage: types.StringValue(vpc.ErrorMessage), - Created: types.StringValue(vpc.Created), Updated: types.StringValue(vpc.Updated), + RegionCode: types.StringValue(vpc.RegionCode), + Created: types.StringValue(vpc.Created), } - for _, peeringConn := range vpc.PeeringConnections { - peeringConnID, err := strconv.ParseInt(peeringConn.ID, 10, 64) - if err != nil { - resp.Diagnostics.AddError("Unable to Convert Vpc ID", err.Error()) - return - } - peeringConnVpcID, err := strconv.ParseInt(peeringConn.VPCID, 10, 64) - if err != nil { - resp.Diagnostics.AddError("Unable to Convert Vpc ID", err.Error()) - return - } - peerConn := &peeringConnectionModel{ - ID: types.Int64Value(peeringConnID), - VpcID: types.Int64Value(peeringConnVpcID), - Status: types.StringValue(peeringConn.Status), - ErrorMessage: types.StringValue(peeringConn.ErrorMessage), - } - for _, peerVpc := range peeringConn.PeerVPCs { - peerVpcId, err := strconv.ParseInt(peerVpc.ID, 10, 64) - if err != nil { - resp.Diagnostics.AddError("Unable to Convert Vpc ID", err.Error()) - return + if len(vpc.PeeringConnections) > 0 { + var pcms []peeringConnectionDSModel + for _, pc := range vpc.PeeringConnections { + var pcm peeringConnectionDSModel + if pc.ErrorMessage != "" { + pcm.ErrorMessage = types.StringValue(pc.ErrorMessage) } - peerConn.PeerVpcs = append(peerConn.PeerVpcs, &peerVpcModel{ - ID: types.Int64Value(peerVpcId), - AccountID: types.StringValue(peerVpc.AccountID), - CIDR: types.StringValue(peerVpc.CIDR), - RegionCode: types.StringValue(peerVpc.RegionCode), + pcm.VpcID = types.StringValue(pc.VPCID) + pcm.Status = types.StringValue(pc.Status) + peerVpcs, errDiag := types.ObjectValueFrom(ctx, PeerVpcDSType, peerVpcDSModel{ + ID: types.StringValue(pc.PeerVPCs.ID), + AccountID: types.StringValue(pc.PeerVPCs.AccountID), + CIDR: types.StringValue(pc.PeerVPCs.CIDR), + RegionCode: types.StringValue(pc.PeerVPCs.RegionCode), }) + if errDiag.HasError() { + resp.Diagnostics.Append(errDiag...) + } + pcm.PeerVpcs = peerVpcs + pcms = append(pcms, pcm) } - vpcState.PeeringConnections = append(vpcState.PeeringConnections, peerConn) + vpcState.PeeringConnections = pcms } state.Vpcs = append(state.Vpcs, vpcState) } @@ -196,39 +212,19 @@ func (d *vpcsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, r "updated": schema.StringAttribute{ Computed: true, }, - "peering_connections": schema.ListNestedAttribute{ + "peering_connections": schema.ListAttribute{ Computed: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "id": schema.Int64Attribute{ - Computed: true, - }, - "vpc_id": schema.Int64Attribute{ - Computed: true, - }, - "status": schema.StringAttribute{ - Computed: true, - }, - "error_message": schema.StringAttribute{ - Computed: true, - }, - "peer_vpc": schema.ListNestedAttribute{ - Computed: true, - NestedObject: schema.NestedAttributeObject{ - Attributes: map[string]schema.Attribute{ - "id": schema.Int64Attribute{ - Computed: true, - }, - "cidr": schema.StringAttribute{ - Computed: true, - }, - "region_code": schema.StringAttribute{ - Computed: true, - }, - "account_id": schema.StringAttribute{ - Computed: true, - }, - }, + ElementType: types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "vpc_id": types.StringType, + "status": types.StringType, + "error_message": types.StringType, + "peer_vpc": types.ObjectType{ + AttrTypes: map[string]attr.Type{ + "id": types.StringType, + "cidr": types.StringType, + "region_code": types.StringType, + "account_id": types.StringType, }, }, }, diff --git a/internal/provider/vpcs_data_source_test.go b/internal/provider/vpcs_data_source_test.go new file mode 100644 index 0000000..3795ca4 --- /dev/null +++ b/internal/provider/vpcs_data_source_test.go @@ -0,0 +1,30 @@ +package provider + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestVPCDataSource(t *testing.T) { + resource.ParallelTest(t, resource.TestCase{ + ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + // Read testing + { + Config: getVPCConfig(t, config.WithName("data-source-test").WithCIDR("10.0.0.0/21").WithRegionCode("us-east-1")) + ` + data "timescale_vpcs" "data_source" { + }`, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttrSet("data.timescale_vpcs.data_source", "id"), + resource.TestCheckResourceAttrSet("data.timescale_vpcs.data_source", "name"), + resource.TestCheckResourceAttrSet("data.timescale_vpcs.data_source", "region_code"), + resource.TestCheckResourceAttrSet("data.timescale_vpcs.data_source", "created"), + resource.TestCheckResourceAttrSet("data.timescale_vpcs.data_source", "cidr"), + resource.TestCheckResourceAttrSet("data.timescale_vpcs.data_source", "status"), + resource.TestCheckResourceAttrSet("data.timescale_vpcs.data_source", "project_id"), + ), + }, + }, + }) +}