Skip to content

Commit 0af39f1

Browse files
authored
Merge pull request #43757 from oracle-community/odb-net-peering
Odb net peering resource and data source
2 parents b7dc098 + cdc3b3d commit 0af39f1

9 files changed

+1105
-0
lines changed

.changelog/43757.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
```release-note:new-resource
2+
aws_odb_network_peering_connection
3+
```
4+
5+
```release-note:new-data-source
6+
aws_odb_network_peering_connection
7+
```
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Copyright (c) HashiCorp, Inc.
2+
# SPDX-License-Identifier: MPL-2.0
3+
4+
5+
resource "aws_odb_network_peering_connection" "test" {
6+
display_name = "my_odb_net_peering"
7+
odb_network_id = "<aws_odb_network.test.id>"
8+
peer_network_id = "<vpc_id>"
9+
tags = {
10+
"env" = "dev"
11+
}
12+
}
Lines changed: 375 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,375 @@
1+
// Copyright (c) HashiCorp, Inc.
2+
// SPDX-License-Identifier: MPL-2.0
3+
4+
package odb
5+
6+
import (
7+
"context"
8+
"errors"
9+
"strings"
10+
"time"
11+
12+
"github.com/aws/aws-sdk-go-v2/aws"
13+
"github.com/aws/aws-sdk-go-v2/aws/arn"
14+
"github.com/aws/aws-sdk-go-v2/service/odb"
15+
odbtypes "github.com/aws/aws-sdk-go-v2/service/odb/types"
16+
"github.com/hashicorp/terraform-plugin-framework-timeouts/resource/timeouts"
17+
"github.com/hashicorp/terraform-plugin-framework-timetypes/timetypes"
18+
"github.com/hashicorp/terraform-plugin-framework/path"
19+
"github.com/hashicorp/terraform-plugin-framework/resource"
20+
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
21+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
22+
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
23+
"github.com/hashicorp/terraform-plugin-framework/types"
24+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry"
25+
"github.com/hashicorp/terraform-provider-aws/internal/create"
26+
"github.com/hashicorp/terraform-provider-aws/internal/enum"
27+
"github.com/hashicorp/terraform-provider-aws/internal/errs"
28+
"github.com/hashicorp/terraform-provider-aws/internal/errs/fwdiag"
29+
"github.com/hashicorp/terraform-provider-aws/internal/framework"
30+
"github.com/hashicorp/terraform-provider-aws/internal/framework/flex"
31+
fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types"
32+
tftags "github.com/hashicorp/terraform-provider-aws/internal/tags"
33+
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
34+
"github.com/hashicorp/terraform-provider-aws/names"
35+
)
36+
37+
// Function annotations are used for resource registration to the Provider. DO NOT EDIT.
38+
// @FrameworkResource("aws_odb_network_peering_connection", name="Network Peering Connection")
39+
// @Tags(identifierAttribute="arn")
40+
func newResourceNetworkPeeringConnection(_ context.Context) (resource.ResourceWithConfigure, error) {
41+
r := &resourceNetworkPeeringConnection{}
42+
43+
r.SetDefaultCreateTimeout(24 * time.Hour)
44+
r.SetDefaultUpdateTimeout(24 * time.Hour)
45+
r.SetDefaultDeleteTimeout(24 * time.Hour)
46+
47+
return r, nil
48+
}
49+
50+
const (
51+
ResNameNetworkPeeringConnection = "Network Peering Connection"
52+
)
53+
54+
var OracleDBNetworkPeeringConnection = newResourceNetworkPeeringConnection
55+
56+
type resourceNetworkPeeringConnection struct {
57+
framework.ResourceWithModel[odbNetworkPeeringConnectionResourceModel]
58+
framework.WithTimeouts
59+
framework.WithImportByID
60+
}
61+
62+
func (r *resourceNetworkPeeringConnection) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
63+
resp.Schema = schema.Schema{
64+
Description: "A peering connection between an ODB network and either another ODB network or a customer-owned VPC.",
65+
Attributes: map[string]schema.Attribute{
66+
names.AttrARN: framework.ARNAttributeComputedOnly(),
67+
names.AttrID: framework.IDAttribute(),
68+
"odb_network_id": schema.StringAttribute{
69+
Required: true,
70+
PlanModifiers: []planmodifier.String{
71+
stringplanmodifier.RequiresReplace(),
72+
},
73+
Description: "Required field. The unique identifier of the ODB network that initiates the peering connection. " +
74+
"A sample ID is odbpcx-abcdefgh12345678. Changing this will force terraform to create new resource.",
75+
},
76+
"peer_network_id": schema.StringAttribute{
77+
Required: true,
78+
PlanModifiers: []planmodifier.String{
79+
stringplanmodifier.RequiresReplace(),
80+
},
81+
Description: "Required field. The unique identifier of the ODB peering connection. Changing this will force terraform to create new resource",
82+
},
83+
84+
names.AttrDisplayName: schema.StringAttribute{
85+
Description: "Display name of the odb network peering connection. Changing this will force terraform to create new resource",
86+
Required: true,
87+
PlanModifiers: []planmodifier.String{
88+
stringplanmodifier.RequiresReplace(),
89+
},
90+
},
91+
92+
names.AttrStatus: schema.StringAttribute{
93+
Description: "Status of the odb network peering connection.",
94+
CustomType: fwtypes.StringEnumType[odbtypes.ResourceStatus](),
95+
Computed: true,
96+
},
97+
names.AttrStatusReason: schema.StringAttribute{
98+
Description: "The reason for the current status of the ODB peering connection..",
99+
Computed: true,
100+
},
101+
102+
"odb_network_arn": schema.StringAttribute{
103+
Description: "ARN of the odb network peering connection.",
104+
Computed: true,
105+
},
106+
107+
"peer_network_arn": schema.StringAttribute{
108+
Description: "ARN of the peer network peering connection.",
109+
Computed: true,
110+
},
111+
"odb_peering_connection_type": schema.StringAttribute{
112+
Description: "Type of the odb peering connection.",
113+
Computed: true,
114+
},
115+
names.AttrCreatedAt: schema.StringAttribute{
116+
Description: "Created time of the odb network peering connection.",
117+
Computed: true,
118+
CustomType: timetypes.RFC3339Type{},
119+
},
120+
"percent_progress": schema.Float32Attribute{
121+
Description: "Progress of the odb network peering connection.",
122+
Computed: true,
123+
},
124+
names.AttrTags: tftags.TagsAttribute(),
125+
names.AttrTagsAll: tftags.TagsAttributeComputedOnly(),
126+
},
127+
Blocks: map[string]schema.Block{
128+
names.AttrTimeouts: timeouts.Block(ctx, timeouts.Opts{
129+
Create: true,
130+
Update: true,
131+
Delete: true,
132+
}),
133+
},
134+
}
135+
}
136+
137+
func (r *resourceNetworkPeeringConnection) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
138+
conn := r.Meta().ODBClient(ctx)
139+
var plan odbNetworkPeeringConnectionResourceModel
140+
resp.Diagnostics.Append(req.Plan.Get(ctx, &plan)...)
141+
if resp.Diagnostics.HasError() {
142+
return
143+
}
144+
input := odb.CreateOdbPeeringConnectionInput{
145+
OdbNetworkId: plan.OdbNetworkId.ValueStringPointer(),
146+
PeerNetworkId: plan.PeerNetworkId.ValueStringPointer(),
147+
DisplayName: plan.DisplayName.ValueStringPointer(),
148+
Tags: getTagsIn(ctx),
149+
}
150+
out, err := conn.CreateOdbPeeringConnection(ctx, &input)
151+
if err != nil {
152+
resp.Diagnostics.AddError(
153+
create.ProblemStandardMessage(names.ODB, create.ErrActionCreating, ResNameNetworkPeeringConnection, plan.DisplayName.ValueString(), err),
154+
err.Error(),
155+
)
156+
return
157+
}
158+
if out == nil || out.OdbPeeringConnectionId == nil {
159+
resp.Diagnostics.AddError(
160+
create.ProblemStandardMessage(names.ODB, create.ErrActionCreating, ResNameNetworkPeeringConnection, plan.DisplayName.ValueString(), nil),
161+
errors.New("empty output").Error(),
162+
)
163+
return
164+
}
165+
resp.Diagnostics.Append(flex.Flatten(ctx, out, &plan)...)
166+
if resp.Diagnostics.HasError() {
167+
return
168+
}
169+
createTimeout := r.CreateTimeout(ctx, plan.Timeouts)
170+
createdPeeredConnection, err := waitNetworkPeeringConnectionCreated(ctx, conn, plan.OdbPeeringConnectionId.ValueString(), createTimeout)
171+
resp.Diagnostics.Append(resp.State.SetAttribute(ctx, path.Root(names.AttrID), aws.ToString(out.OdbPeeringConnectionId))...)
172+
if err != nil {
173+
resp.Diagnostics.AddError(
174+
create.ProblemStandardMessage(names.ODB, create.ErrActionWaitingForCreation, ResNameNetworkPeeringConnection, plan.DisplayName.ValueString(), err),
175+
err.Error(),
176+
)
177+
return
178+
}
179+
180+
odbNetworkARNParsed, err := arn.Parse(*createdPeeredConnection.OdbNetworkArn)
181+
if err != nil {
182+
resp.Diagnostics.AddError(
183+
create.ProblemStandardMessage(names.ODB, create.ErrActionReading, ResNameNetworkPeeringConnection, plan.DisplayName.ValueString(), err),
184+
err.Error(),
185+
)
186+
return
187+
}
188+
peerVpcARN, err := arn.Parse(*createdPeeredConnection.PeerNetworkArn)
189+
if err != nil {
190+
resp.Diagnostics.AddError(
191+
create.ProblemStandardMessage(names.ODB, create.ErrActionReading, ResNameNetworkPeeringConnection, plan.DisplayName.ValueString(), err),
192+
err.Error(),
193+
)
194+
return
195+
}
196+
plan.PeerNetworkId = types.StringValue(strings.Split(peerVpcARN.Resource, "/")[1])
197+
plan.OdbNetworkId = types.StringValue(strings.Split(odbNetworkARNParsed.Resource, "/")[1])
198+
resp.Diagnostics.Append(flex.Flatten(ctx, createdPeeredConnection, &plan)...)
199+
if resp.Diagnostics.HasError() {
200+
return
201+
}
202+
resp.Diagnostics.Append(resp.State.Set(ctx, plan)...)
203+
}
204+
205+
func (r *resourceNetworkPeeringConnection) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
206+
conn := r.Meta().ODBClient(ctx)
207+
var state odbNetworkPeeringConnectionResourceModel
208+
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
209+
if resp.Diagnostics.HasError() {
210+
return
211+
}
212+
213+
out, err := findNetworkPeeringConnectionByID(ctx, conn, state.OdbPeeringConnectionId.ValueString())
214+
if tfresource.NotFound(err) {
215+
resp.Diagnostics.Append(fwdiag.NewResourceNotFoundWarningDiagnostic(err))
216+
resp.State.RemoveResource(ctx)
217+
return
218+
}
219+
if err != nil {
220+
resp.Diagnostics.AddError(
221+
create.ProblemStandardMessage(names.ODB, create.ErrActionReading, ResNameNetworkPeeringConnection, state.OdbPeeringConnectionId.ValueString(), err),
222+
err.Error(),
223+
)
224+
return
225+
}
226+
227+
odbNetworkARNParsed, err := arn.Parse(*out.OdbNetworkArn)
228+
if err != nil {
229+
resp.Diagnostics.AddError(
230+
create.ProblemStandardMessage(names.ODB, create.ErrActionReading, ResNameNetworkPeeringConnection, state.OdbPeeringConnectionId.ValueString(), err),
231+
err.Error(),
232+
)
233+
return
234+
}
235+
236+
peerVpcARN, err := arn.Parse(*out.PeerNetworkArn)
237+
if err != nil {
238+
resp.Diagnostics.AddError(
239+
create.ProblemStandardMessage(names.ODB, create.ErrActionReading, ResNameNetworkPeeringConnection, state.OdbPeeringConnectionId.ValueString(), err),
240+
err.Error(),
241+
)
242+
return
243+
}
244+
state.PeerNetworkId = types.StringValue(strings.Split(peerVpcARN.Resource, "/")[1])
245+
state.OdbNetworkId = types.StringValue(strings.Split(odbNetworkARNParsed.Resource, "/")[1])
246+
247+
resp.Diagnostics.Append(flex.Flatten(ctx, out, &state)...)
248+
if resp.Diagnostics.HasError() {
249+
return
250+
}
251+
resp.Diagnostics.Append(resp.State.Set(ctx, &state)...)
252+
}
253+
254+
func (r *resourceNetworkPeeringConnection) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
255+
conn := r.Meta().ODBClient(ctx)
256+
var state odbNetworkPeeringConnectionResourceModel
257+
resp.Diagnostics.Append(req.State.Get(ctx, &state)...)
258+
if resp.Diagnostics.HasError() {
259+
return
260+
}
261+
262+
input := odb.DeleteOdbPeeringConnectionInput{
263+
OdbPeeringConnectionId: state.OdbPeeringConnectionId.ValueStringPointer(),
264+
}
265+
_, err := conn.DeleteOdbPeeringConnection(ctx, &input)
266+
if err != nil {
267+
if errs.IsA[*odbtypes.ResourceNotFoundException](err) {
268+
return
269+
}
270+
resp.Diagnostics.AddError(
271+
create.ProblemStandardMessage(names.ODB, create.ErrActionDeleting, ResNameNetworkPeeringConnection, state.OdbPeeringConnectionId.ValueString(), err),
272+
err.Error(),
273+
)
274+
return
275+
}
276+
277+
deleteTimeout := r.DeleteTimeout(ctx, state.Timeouts)
278+
_, err = waitNetworkPeeringConnectionDeleted(ctx, conn, state.OdbPeeringConnectionId.ValueString(), deleteTimeout)
279+
if err != nil {
280+
resp.Diagnostics.AddError(
281+
create.ProblemStandardMessage(names.ODB, create.ErrActionWaitingForDeletion, ResNameNetworkPeeringConnection, state.OdbPeeringConnectionId.String(), err),
282+
err.Error(),
283+
)
284+
return
285+
}
286+
}
287+
288+
func waitNetworkPeeringConnectionCreated(ctx context.Context, conn *odb.Client, id string, timeout time.Duration) (*odbtypes.OdbPeeringConnection, error) {
289+
stateConf := &retry.StateChangeConf{
290+
Pending: enum.Slice(odbtypes.ResourceStatusProvisioning),
291+
Target: enum.Slice(odbtypes.ResourceStatusAvailable, odbtypes.ResourceStatusFailed),
292+
Refresh: statusNetworkPeeringConnection(ctx, conn, id),
293+
Timeout: timeout,
294+
NotFoundChecks: 20,
295+
ContinuousTargetOccurence: 2,
296+
}
297+
298+
outputRaw, err := stateConf.WaitForStateContext(ctx)
299+
if out, ok := outputRaw.(*odbtypes.OdbPeeringConnection); ok {
300+
return out, err
301+
}
302+
303+
return nil, err
304+
}
305+
306+
func waitNetworkPeeringConnectionDeleted(ctx context.Context, conn *odb.Client, id string, timeout time.Duration) (*odbtypes.OdbPeeringConnection, error) {
307+
stateConf := &retry.StateChangeConf{
308+
Pending: enum.Slice(odbtypes.ResourceStatusTerminating),
309+
Target: []string{},
310+
Refresh: statusNetworkPeeringConnection(ctx, conn, id),
311+
Timeout: timeout,
312+
}
313+
314+
outputRaw, err := stateConf.WaitForStateContext(ctx)
315+
if out, ok := outputRaw.(*odbtypes.OdbPeeringConnection); ok {
316+
return out, err
317+
}
318+
return nil, err
319+
}
320+
321+
func statusNetworkPeeringConnection(ctx context.Context, conn *odb.Client, id string) retry.StateRefreshFunc {
322+
return func() (any, string, error) {
323+
out, err := findNetworkPeeringConnectionByID(ctx, conn, id)
324+
if tfresource.NotFound(err) {
325+
return nil, "", nil
326+
}
327+
if err != nil {
328+
return nil, "", err
329+
}
330+
return out, string(out.Status), nil
331+
}
332+
}
333+
334+
func findNetworkPeeringConnectionByID(ctx context.Context, conn *odb.Client, id string) (*odbtypes.OdbPeeringConnection, error) {
335+
input := odb.GetOdbPeeringConnectionInput{
336+
OdbPeeringConnectionId: &id,
337+
}
338+
339+
out, err := conn.GetOdbPeeringConnection(ctx, &input)
340+
if err != nil {
341+
if errs.IsA[*odbtypes.ResourceNotFoundException](err) {
342+
return nil, &retry.NotFoundError{
343+
LastError: err,
344+
LastRequest: &input,
345+
}
346+
}
347+
348+
return nil, err
349+
}
350+
351+
if out == nil || out.OdbPeeringConnection == nil {
352+
return nil, tfresource.NewEmptyResultError(&input)
353+
}
354+
355+
return out.OdbPeeringConnection, nil
356+
}
357+
358+
type odbNetworkPeeringConnectionResourceModel struct {
359+
framework.WithRegionModel
360+
OdbNetworkId types.String `tfsdk:"odb_network_id" autoflex:",noflatten"`
361+
PeerNetworkId types.String `tfsdk:"peer_network_id" autoflex:",noflatten"`
362+
OdbPeeringConnectionId types.String `tfsdk:"id"`
363+
DisplayName types.String `tfsdk:"display_name"`
364+
Status fwtypes.StringEnum[odbtypes.ResourceStatus] `tfsdk:"status"`
365+
StatusReason types.String `tfsdk:"status_reason"`
366+
OdbPeeringConnectionArn types.String `tfsdk:"arn"`
367+
OdbNetworkArn types.String `tfsdk:"odb_network_arn"`
368+
PeerNetworkArn types.String `tfsdk:"peer_network_arn"`
369+
OdbPeeringConnectionType types.String `tfsdk:"odb_peering_connection_type"`
370+
CreatedAt timetypes.RFC3339 `tfsdk:"created_at"`
371+
PercentProgress types.Float32 `tfsdk:"percent_progress"`
372+
Timeouts timeouts.Value `tfsdk:"timeouts"`
373+
Tags tftags.Map `tfsdk:"tags"`
374+
TagsAll tftags.Map `tfsdk:"tags_all"`
375+
}

0 commit comments

Comments
 (0)