Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Route 53: IP-based routing #29407

Merged
merged 21 commits into from
Feb 15, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
492e6a5
r/aws_route53_cidr_collection: Add documentation.
ewbankkit Feb 14, 2023
ed15f33
r/aws_route53_cidr_collection: New resources.
ewbankkit Feb 14, 2023
40e7a13
r/aws_route53_cidr_collection: Add 'version' attribute.
ewbankkit Feb 14, 2023
deb5912
r/aws_route53_cidr_location: Add documentation.
ewbankkit Feb 14, 2023
5622afe
Add types.CIDRBlock'.
ewbankkit Feb 14, 2023
5d37983
r/aws_route53_cidr_collection: Tidy up acceptance tests.
ewbankkit Feb 14, 2023
106ebe0
r/aws_route53_cidr_location: New resources.
ewbankkit Feb 14, 2023
5f6c8d4
Correct CHANGELOG entry file name.
ewbankkit Feb 14, 2023
25425a6
Add 'route53_cidr_' documentation prefix.
ewbankkit Feb 14, 2023
bb8c00c
r/aws_route53_record: Alphabetize attributes.
ewbankkit Feb 14, 2023
495b04d
Run 'make gen'.
ewbankkit Feb 14, 2023
a04a553
r/aws_route53_record: CRUD handlers in the correct order.
ewbankkit Feb 14, 2023
33d523d
r/aws_reoute53_record: Use 'validation.StringInSlice'.
ewbankkit Feb 15, 2023
c2a62e3
Route 53: Finder corrections.
ewbankkit Feb 15, 2023
aa0d302
Acceptance test output:
ewbankkit Feb 15, 2023
88f0ac1
Fix golangci-lint 'whitespace'.
ewbankkit Feb 15, 2023
32e35b1
Rename 'ChangeRecordSet' to 'ChangeResourceRecordSets'.
ewbankkit Feb 15, 2023
a6cdc58
r/aws_route53_record: Add 'cidr_routing_policy' attribute.
ewbankkit Feb 15, 2023
5a03290
r/aws_route53_route: Start testing 'cidr_routing_policy' attribute.
ewbankkit Feb 15, 2023
3aa13b5
r/aws_route53_route: Testing 'cidr_routing_policy' attribute.
ewbankkit Feb 15, 2023
250768e
r/aws_route53_record: Fix delete when changing name.
ewbankkit Feb 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changelog/29407.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```release-note:new-resource
aws_route53_cidr_collection
```

```release-note:new-resource
aws_route53_cidr_location
```

```release-note:enhancement
resource/aws_route53_cidr_location: Add `cidr_routing_policy` argument
```
1 change: 1 addition & 0 deletions .github/labeler-pr-triage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -841,6 +841,7 @@ service/rolesanywhere:
- 'website/**/rolesanywhere_*'
service/route53:
- 'internal/service/route53/**/*'
- 'website/**/route53_cidr_*'
- 'website/**/route53_delegation_*'
- 'website/**/route53_health_*'
- 'website/**/route53_hosted_*'
Expand Down
18 changes: 18 additions & 0 deletions internal/flex/framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,24 @@ func FlattenFrameworkStringValueListLegacy(_ context.Context, vs []string) types
return types.ListValueMust(types.StringType, elems)
}

// FlattenFrameworkStringSet converts a slice of string pointers to a framework Set value.
//
// A nil slice is converted to a null Set.
// An empty slice is converted to a null Set.
func FlattenFrameworkStringSet(_ context.Context, vs []*string) types.Set {
if len(vs) == 0 {
return types.SetNull(types.StringType)
}

elems := make([]attr.Value, len(vs))

for i, v := range vs {
elems[i] = types.StringValue(aws.ToString(v))
}

return types.SetValueMust(types.StringType, elems)
}

// FlattenFrameworkStringValueSet converts a slice of string values to a framework Set value.
//
// A nil slice is converted to a null Set.
Expand Down
216 changes: 216 additions & 0 deletions internal/framework/types/cidr_block.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
package types

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/attr/xattr"
"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-framework/types/basetypes"
"github.com/hashicorp/terraform-plugin-go/tftypes"
"github.com/hashicorp/terraform-provider-aws/internal/verify"
)

type cidrBlockType uint8

const (
CIDRBlockType cidrBlockType = iota
)

var (
_ xattr.TypeWithValidate = CIDRBlockType
)

func (t cidrBlockType) TerraformType(_ context.Context) tftypes.Type {
return tftypes.String
}

func (t cidrBlockType) ValueFromString(_ context.Context, st types.String) (basetypes.StringValuable, diag.Diagnostics) {
if st.IsNull() {
return CIDRBlockNull(), nil
}
if st.IsUnknown() {
return CIDRBlockUnknown(), nil
}

return CIDRBlockValue(st.ValueString()), nil
}

func (t cidrBlockType) ValueFromTerraform(_ context.Context, in tftypes.Value) (attr.Value, error) {
if in.IsNull() {
return CIDRBlockNull(), nil
}
if !in.IsKnown() {
return CIDRBlockUnknown(), nil
}

var s string
err := in.As(&s)

if err != nil {
return nil, err
}

if err := verify.ValidateCIDRBlock(s); err != nil {
return nil, err
}

return CIDRBlockValue(s), nil
}

func (t cidrBlockType) ValueType(context.Context) attr.Value {
return CIDRBlock{}
}

func (t cidrBlockType) Equal(o attr.Type) bool {
_, ok := o.(cidrBlockType)
return ok
}

func (t cidrBlockType) ApplyTerraform5AttributePathStep(step tftypes.AttributePathStep) (interface{}, error) {
return nil, fmt.Errorf("cannot apply AttributePathStep %T to %s", step, t.String())
}

func (t cidrBlockType) String() string {
return "types.CIDRBlockType"
}

func (t cidrBlockType) Validate(ctx context.Context, in tftypes.Value, path path.Path) diag.Diagnostics {
var diags diag.Diagnostics

if !in.Type().Is(tftypes.String) {
diags.AddAttributeError(
path,
"CIDRBlock Type Validation Error",
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+
fmt.Sprintf("Expected String value, received %T with value: %v", in, in),
)
return diags
}

if !in.IsKnown() || in.IsNull() {
return diags
}

var value string
err := in.As(&value)
if err != nil {
diags.AddAttributeError(
path,
"CIDRBlock Type Validation Error",
"An unexpected error was encountered trying to validate an attribute value. This is always an error in the provider. Please report the following to the provider developer:\n\n"+
fmt.Sprintf("Cannot convert value to string: %s", err),
)
return diags
}

if err := verify.ValidateCIDRBlock(value); err != nil {
diags.AddAttributeError(
path,
"CIDRBlock Type Validation Error",
err.Error(),
)
return diags
}

return diags
}

func (t cidrBlockType) Description() string {
return `A CIDR block.`
}

func CIDRBlockNull() CIDRBlock {
return CIDRBlock{
state: attr.ValueStateNull,
}
}

func CIDRBlockUnknown() CIDRBlock {
return CIDRBlock{
state: attr.ValueStateUnknown,
}
}

func CIDRBlockValue(value string) CIDRBlock {
return CIDRBlock{
state: attr.ValueStateKnown,
value: value,
}
}

type CIDRBlock struct {
state attr.ValueState
value string
}

func (c CIDRBlock) Type(_ context.Context) attr.Type {
return CIDRBlockType
}

func (c CIDRBlock) ToStringValue(ctx context.Context) (types.String, diag.Diagnostics) {
return types.StringValue(c.value), nil
}

func (c CIDRBlock) ToTerraformValue(ctx context.Context) (tftypes.Value, error) {
t := CIDRBlockType.TerraformType(ctx)

switch c.state {
case attr.ValueStateKnown:
if err := tftypes.ValidateValue(t, c.value); err != nil {
return tftypes.NewValue(t, tftypes.UnknownValue), err
}

return tftypes.NewValue(t, c.value), nil
case attr.ValueStateNull:
return tftypes.NewValue(t, nil), nil
case attr.ValueStateUnknown:
return tftypes.NewValue(t, tftypes.UnknownValue), nil
default:
return tftypes.NewValue(t, tftypes.UnknownValue), fmt.Errorf("unhandled CIDRBlock state in ToTerraformValue: %s", c.state)
}
}

func (c CIDRBlock) Equal(other attr.Value) bool {
o, ok := other.(CIDRBlock)

if !ok {
return false
}

if c.state != o.state {
return false
}

if c.state != attr.ValueStateKnown {
return true
}

return c.value == o.value
}

func (c CIDRBlock) IsNull() bool {
return c.state == attr.ValueStateNull
}

func (c CIDRBlock) IsUnknown() bool {
return c.state == attr.ValueStateUnknown
}

func (c CIDRBlock) String() string {
if c.IsNull() {
return attr.NullValueString
}
if c.IsUnknown() {
return attr.UnknownValueString
}

return c.value
}

func (c CIDRBlock) ValueCIDRBlock() string {
return c.value
}
114 changes: 114 additions & 0 deletions internal/framework/types/cidr_block_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package types_test

import (
"context"
"testing"

"github.com/google/go-cmp/cmp"
"github.com/hashicorp/terraform-plugin-framework/attr"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-go/tftypes"
fwtypes "github.com/hashicorp/terraform-provider-aws/internal/framework/types"
)

func TestCIDRBlockTypeValueFromTerraform(t *testing.T) {
t.Parallel()

tests := map[string]struct {
val tftypes.Value
expected attr.Value
expectError bool
}{
"null value": {
val: tftypes.NewValue(tftypes.String, nil),
expected: fwtypes.CIDRBlockNull(),
},
"unknown value": {
val: tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
expected: fwtypes.CIDRBlockUnknown(),
},
"valid CIDR block": {
val: tftypes.NewValue(tftypes.String, "0.0.0.0/0"),
expected: fwtypes.CIDRBlockValue("0.0.0.0/0"),
},
"invalid CIDR block": {
val: tftypes.NewValue(tftypes.String, "not ok"),
expectError: true,
},
}

for name, test := range tests {
name, test := name, test
t.Run(name, func(t *testing.T) {
t.Parallel()

ctx := context.Background()
val, err := fwtypes.CIDRBlockType.ValueFromTerraform(ctx, test.val)

if err == nil && test.expectError {
t.Fatal("expected error, got no error")
}
if err != nil && !test.expectError {
t.Fatalf("got unexpected error: %s", err)
}

if diff := cmp.Diff(val, test.expected); diff != "" {
t.Errorf("unexpected diff (+wanted, -got): %s", diff)
}
})
}
}

func TestCIDRBlockTypeValidate(t *testing.T) {
t.Parallel()

type testCase struct {
val tftypes.Value
expectError bool
}
tests := map[string]testCase{
"not a string": {
val: tftypes.NewValue(tftypes.Bool, true),
expectError: true,
},
"unknown string": {
val: tftypes.NewValue(tftypes.String, tftypes.UnknownValue),
},
"null string": {
val: tftypes.NewValue(tftypes.String, nil),
},
"valid IPv4 string": {
val: tftypes.NewValue(tftypes.String, "10.2.2.0/24"),
},
"invalid IPv4 string": {
val: tftypes.NewValue(tftypes.String, "10.2.2.2/24"),
expectError: true,
},
"valid IPv6 string": {
val: tftypes.NewValue(tftypes.String, "2000::/15"),
},
"invalid IPv6 string": {
val: tftypes.NewValue(tftypes.String, "2001::/15"),
expectError: true,
},
}

for name, test := range tests {
name, test := name, test
t.Run(name, func(t *testing.T) {
t.Parallel()

ctx := context.Background()

diags := fwtypes.CIDRBlockType.Validate(ctx, test.val, path.Root("test"))

if !diags.HasError() && test.expectError {
t.Fatal("expected error, got no error")
}

if diags.HasError() && !test.expectError {
t.Fatalf("got unexpected error: %#v", diags)
}
})
}
}
Loading