Skip to content

Commit

Permalink
Merge pull request #40371 from bryantbiggs/feat/eks-hybrid-nodes
Browse files Browse the repository at this point in the history
r/aws_eks_cluster: Add support for EKS Hybrid nodes
  • Loading branch information
gdavison authored Dec 2, 2024
2 parents ed22efa + 23841dc commit b1f44a7
Show file tree
Hide file tree
Showing 9 changed files with 623 additions and 184 deletions.
3 changes: 3 additions & 0 deletions .changelog/40371.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
resource/aws_eks_cluster: Add `remote_network_config` argument for EKS Auto Mode
```
185 changes: 182 additions & 3 deletions internal/service/eks/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"log"
"time"

"github.com/YakDriver/regexache"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/eks"
"github.com/aws/aws-sdk-go-v2/service/eks/types"
Expand Down Expand Up @@ -203,7 +202,7 @@ func resourceCluster() *schema.Resource {
ForceNew: true,
ValidateFunc: validation.All(
validation.IsCIDRNetwork(12, 24),
validation.StringMatch(regexache.MustCompile(`^(10|172\.(1[6-9]|2[0-9]|3[0-1])|192\.168)\..*`), "must be within 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16"),
validateIPv4CIDRPrivateRange,
),
},
"service_ipv6_cidr": {
Expand All @@ -223,7 +222,7 @@ func resourceCluster() *schema.Resource {
Type: schema.TypeList,
MaxItems: 1,
Optional: true,
ConflictsWith: []string{"encryption_config", "kubernetes_network_config"},
ConflictsWith: []string{"encryption_config", "kubernetes_network_config", "remote_network_config"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"control_plane_instance_type": {
Expand Down Expand Up @@ -260,6 +259,63 @@ func resourceCluster() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"remote_network_config": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
MaxItems: 1,
ConflictsWith: []string{"outpost_config"},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"remote_node_networks": {
Type: schema.TypeList,
MinItems: 1,
MaxItems: 1,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cidrs": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
MinItems: 1,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.All(
verify.ValidIPv4CIDRNetworkAddress,
validateIPv4CIDRPrivateRange,
),
},
},
},
},
},
"remote_pod_networks": {
Type: schema.TypeList,
Optional: true,
Computed: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cidrs": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
MinItems: 1,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateFunc: validation.All(
verify.ValidIPv4CIDRNetworkAddress,
validateIPv4CIDRPrivateRange,
),
},
},
},
},
},
},
},
},
names.AttrRoleARN: {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -386,6 +442,10 @@ func resourceClusterCreate(ctx context.Context, d *schema.ResourceData, meta int
input.OutpostConfig = expandOutpostConfigRequest(v.([]interface{}))
}

if v, ok := d.GetOk("remote_network_config"); ok {
input.RemoteNetworkConfig = expandRemoteNetworkConfigRequest(v.([]interface{}))
}

if v, ok := d.GetOk("upgrade_policy"); ok {
input.UpgradePolicy = expandUpgradePolicy(v.([]interface{}))
}
Expand Down Expand Up @@ -499,6 +559,9 @@ func resourceClusterRead(ctx context.Context, d *schema.ResourceData, meta inter
return sdkdiag.AppendErrorf(diags, "setting outpost_config: %s", err)
}
d.Set("platform_version", cluster.PlatformVersion)
if err := d.Set("remote_network_config", flattenRemoteNetworkConfigResponse(cluster.RemoteNetworkConfig)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting remote_network_config: %s", err)
}
d.Set(names.AttrRoleARN, cluster.RoleArn)
d.Set(names.AttrStatus, cluster.Status)
if err := d.Set("upgrade_policy", flattenUpgradePolicy(cluster.UpgradePolicy)); err != nil {
Expand Down Expand Up @@ -1085,6 +1148,73 @@ func expandKubernetesNetworkConfigRequest(tfList []interface{}) *types.Kubernete
return apiObject
}

func expandRemoteNetworkConfigRequest(tfList []interface{}) *types.RemoteNetworkConfigRequest {
if len(tfList) == 0 {
return nil
}

tfMap, ok := tfList[0].(map[string]interface{})
if !ok {
return nil
}

apiObject := &types.RemoteNetworkConfigRequest{
RemoteNodeNetworks: expandRemoteNodeNetworks(tfMap["remote_node_networks"].([]interface{})),
}

if v, ok := tfMap["remote_pod_networks"].([]interface{}); ok {
apiObject.RemotePodNetworks = expandRemotePodNetworks(v)
}

return apiObject
}

func expandRemoteNodeNetworks(tfList []interface{}) []types.RemoteNodeNetwork {
if len(tfList) == 0 {
return nil
}

var apiObjects []types.RemoteNodeNetwork

for _, tfMapRaw := range tfList {
tfMap, ok := tfMapRaw.(map[string]interface{})
if !ok {
continue
}

apiObject := types.RemoteNodeNetwork{
Cidrs: flex.ExpandStringValueSet(tfMap["cidrs"].(*schema.Set)),
}

apiObjects = append(apiObjects, apiObject)
}

return apiObjects
}

func expandRemotePodNetworks(tfList []interface{}) []types.RemotePodNetwork {
if len(tfList) == 0 {
return nil
}

var apiObjects []types.RemotePodNetwork

for _, tfMapRaw := range tfList {
tfMap, ok := tfMapRaw.(map[string]interface{})
if !ok {
continue
}

apiObject := types.RemotePodNetwork{
Cidrs: flex.ExpandStringValueSet(tfMap["cidrs"].(*schema.Set)),
}

apiObjects = append(apiObjects, apiObject)
}

return apiObjects
}

func expandLogging(vEnabledLogTypes *schema.Set) *types.Logging {
allLogTypes := enum.EnumValues[types.LogType]()
enabledLogTypes := flex.ExpandStringyValueSet[types.LogType](vEnabledLogTypes)
Expand Down Expand Up @@ -1290,6 +1420,55 @@ func flattenOutpostConfigResponse(apiObject *types.OutpostConfigResponse) []inte
return []interface{}{tfMap}
}

func flattenRemoteNetworkConfigResponse(apiObject *types.RemoteNetworkConfigResponse) []interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{
"remote_node_networks": flattenRemoteNodeNetwork(apiObject.RemoteNodeNetworks),
"remote_pod_networks": flattenRemotePodNetwork(apiObject.RemotePodNetworks),
}

return []interface{}{tfMap}
}

func flattenRemoteNodeNetwork(apiObjects []types.RemoteNodeNetwork) []interface{} {
if len(apiObjects) == 0 {
return nil
}

var tfList []interface{}

for _, apiObject := range apiObjects {
tfMap := map[string]interface{}{
"cidrs": flex.FlattenStringValueList(apiObject.Cidrs),
}

tfList = append(tfList, tfMap)
}

return tfList
}

func flattenRemotePodNetwork(apiObjects []types.RemotePodNetwork) []interface{} {
if len(apiObjects) == 0 {
return nil
}

var tfList []interface{}

for _, apiObject := range apiObjects {
tfMap := map[string]interface{}{
"cidrs": flex.FlattenStringValueList(apiObject.Cidrs),
}

tfList = append(tfList, tfMap)
}

return tfList
}

func flattenControlPlanePlacementResponse(apiObject *types.ControlPlanePlacementResponse) []interface{} {
if apiObject == nil {
return nil
Expand Down
37 changes: 37 additions & 0 deletions internal/service/eks/cluster_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,40 @@ func dataSourceCluster() *schema.Resource {
Type: schema.TypeString,
Computed: true,
},
"remote_network_config": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"remote_node_networks": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cidrs": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
"remote_pod_networks": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"cidrs": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
},
},
},
},
},
},
names.AttrRoleARN: {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -271,6 +305,9 @@ func dataSourceClusterRead(ctx context.Context, d *schema.ResourceData, meta int
return sdkdiag.AppendErrorf(diags, "setting outpost_config: %s", err)
}
d.Set("platform_version", cluster.PlatformVersion)
if err := d.Set("remote_network_config", flattenRemoteNetworkConfigResponse(cluster.RemoteNetworkConfig)); err != nil {
return sdkdiag.AppendErrorf(diags, "setting remote_network_config: %s", err)
}
d.Set(names.AttrRoleARN, cluster.RoleArn)
d.Set(names.AttrStatus, cluster.Status)
if err := d.Set("upgrade_policy", flattenUpgradePolicy(cluster.UpgradePolicy)); err != nil {
Expand Down
66 changes: 66 additions & 0 deletions internal/service/eks/cluster_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func TestAccEKSClusterDataSource_basic(t *testing.T) {
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.0.service_ipv6_cidr", dataSourceResourceName, "kubernetes_network_config.0.service_ipv6_cidr"),
resource.TestCheckResourceAttrPair(resourceName, "outpost_config.#", dataSourceResourceName, "outpost_config.#"),
resource.TestMatchResourceAttr(dataSourceResourceName, "platform_version", regexache.MustCompile(`^eks\.\d+$`)),
resource.TestCheckResourceAttr(dataSourceResourceName, "remote_network_config.#", "0"),
resource.TestCheckResourceAttrPair(resourceName, names.AttrRoleARN, dataSourceResourceName, names.AttrRoleARN),
resource.TestCheckResourceAttrPair(resourceName, names.AttrStatus, dataSourceResourceName, names.AttrStatus),
resource.TestCheckResourceAttrPair(resourceName, acctest.CtTagsPercent, dataSourceResourceName, acctest.CtTagsPercent),
Expand Down Expand Up @@ -95,6 +96,7 @@ func TestAccEKSClusterDataSource_outpost(t *testing.T) {
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.0.service_ipv4_cidr", dataSourceResourceName, "kubernetes_network_config.0.service_ipv4_cidr"),
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.0.service_ipv6_cidr", dataSourceResourceName, "kubernetes_network_config.0.service_ipv6_cidr"),
resource.TestMatchResourceAttr(dataSourceResourceName, "platform_version", regexache.MustCompile(`^eks-local-outposts\.\d+$`)),
resource.TestCheckResourceAttr(dataSourceResourceName, "remote_network_config.#", "0"),
resource.TestCheckResourceAttrPair(resourceName, names.AttrRoleARN, dataSourceResourceName, names.AttrRoleARN),
resource.TestCheckResourceAttrPair(resourceName, names.AttrStatus, dataSourceResourceName, names.AttrStatus),
resource.TestCheckResourceAttrPair(resourceName, acctest.CtTagsPercent, dataSourceResourceName, acctest.CtTagsPercent),
Expand All @@ -118,6 +120,62 @@ func TestAccEKSClusterDataSource_outpost(t *testing.T) {
})
}

func TestAccEKSClusterDataSource_remoteNetwork(t *testing.T) {
ctx := acctest.Context(t)
rName := sdkacctest.RandomWithPrefix(acctest.ResourcePrefix)
dataSourceResourceName := "data.aws_eks_cluster.test"
resourceName := "aws_eks_cluster.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { acctest.PreCheck(ctx, t); testAccPreCheck(ctx, t) },
ErrorCheck: acctest.ErrorCheck(t, names.EKSServiceID),
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories,
CheckDestroy: testAccCheckClusterDestroy(ctx),
Steps: []resource.TestStep{
{
Config: testAccClusterDataSourceConfig_remoteNetwork(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(resourceName, names.AttrARN, dataSourceResourceName, names.AttrARN),
resource.TestCheckResourceAttr(dataSourceResourceName, "certificate_authority.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "certificate_authority.0.data", dataSourceResourceName, "certificate_authority.0.data"),
resource.TestCheckResourceAttrPair(resourceName, names.AttrCreatedAt, dataSourceResourceName, names.AttrCreatedAt),
resource.TestCheckResourceAttr(dataSourceResourceName, "enabled_cluster_log_types.#", "0"),
resource.TestCheckResourceAttrPair(resourceName, names.AttrEndpoint, dataSourceResourceName, names.AttrEndpoint),
resource.TestCheckResourceAttr(dataSourceResourceName, "identity.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.#", dataSourceResourceName, "kubernetes_network_config.#"),
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.0.ip_family", dataSourceResourceName, "kubernetes_network_config.0.ip_family"),
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.0.service_ipv4_cidr", dataSourceResourceName, "kubernetes_network_config.0.service_ipv4_cidr"),
resource.TestCheckResourceAttrPair(resourceName, "kubernetes_network_config.0.service_ipv6_cidr", dataSourceResourceName, "kubernetes_network_config.0.service_ipv6_cidr"),
resource.TestCheckResourceAttrPair(resourceName, "outpost_config.#", dataSourceResourceName, "outpost_config.#"),
resource.TestMatchResourceAttr(dataSourceResourceName, "platform_version", regexache.MustCompile(`^eks\.\d+$`)),
resource.TestCheckResourceAttr(resourceName, "remote_network_config.#", "1"),
resource.TestCheckResourceAttr(resourceName, "remote_network_config.0.remote_node_networks.#", "1"),
resource.TestCheckResourceAttr(resourceName, "remote_network_config.0.remote_node_networks.0.cidrs.#", "1"),
resource.TestCheckResourceAttr(resourceName, "remote_network_config.0.remote_node_networks.0.cidrs.0", "10.90.0.0/22"),
resource.TestCheckResourceAttr(resourceName, "remote_network_config.0.remote_pod_networks.#", "1"),
resource.TestCheckResourceAttr(resourceName, "remote_network_config.0.remote_pod_networks.0.cidrs.#", "1"),
resource.TestCheckResourceAttr(resourceName, "remote_network_config.0.remote_pod_networks.0.cidrs.0", "10.80.0.0/22"),
resource.TestCheckResourceAttrPair(resourceName, names.AttrRoleARN, dataSourceResourceName, names.AttrRoleARN),
resource.TestCheckResourceAttrPair(resourceName, names.AttrStatus, dataSourceResourceName, names.AttrStatus),
resource.TestCheckResourceAttrPair(resourceName, acctest.CtTagsPercent, dataSourceResourceName, acctest.CtTagsPercent),
resource.TestCheckResourceAttr(resourceName, "upgrade_policy.#", "1"),
resource.TestCheckResourceAttr(resourceName, "upgrade_policy.0.support_type", "EXTENDED"),
resource.TestCheckResourceAttrPair(resourceName, names.AttrVersion, dataSourceResourceName, names.AttrVersion),
resource.TestCheckResourceAttr(dataSourceResourceName, "vpc_config.#", "1"),
resource.TestCheckResourceAttrPair(resourceName, "vpc_config.0.cluster_security_group_id", dataSourceResourceName, "vpc_config.0.cluster_security_group_id"),
resource.TestCheckResourceAttrPair(resourceName, "vpc_config.0.endpoint_private_access", dataSourceResourceName, "vpc_config.0.endpoint_private_access"),
resource.TestCheckResourceAttrPair(resourceName, "vpc_config.0.endpoint_public_access", dataSourceResourceName, "vpc_config.0.endpoint_public_access"),
resource.TestCheckResourceAttrPair(resourceName, "vpc_config.0.security_group_ids.#", dataSourceResourceName, "vpc_config.0.security_group_ids.#"),
resource.TestCheckResourceAttrPair(resourceName, "vpc_config.0.subnet_ids.#", dataSourceResourceName, "vpc_config.0.subnet_ids.#"),
resource.TestCheckResourceAttrPair(resourceName, "vpc_config.0.public_access_cidrs.#", dataSourceResourceName, "vpc_config.0.public_access_cidrs.#"),
resource.TestCheckResourceAttrPair(resourceName, "vpc_config.0.vpc_id", dataSourceResourceName, "vpc_config.0.vpc_id"),
resource.TestCheckResourceAttr(resourceName, "zonal_shift_config.#", "0"),
),
},
},
})
}

func testAccClusterDataSourceConfig_basic(rName string) string {
return acctest.ConfigCompose(testAccClusterConfig_logging(rName, []string{"api", "audit"}), `
data "aws_eks_cluster" "test" {
Expand All @@ -133,3 +191,11 @@ data "aws_eks_cluster" "test" {
}
`)
}

func testAccClusterDataSourceConfig_remoteNetwork(rName string) string {
return acctest.ConfigCompose(testAccClusterConfig_remotePodNetwork(rName, "10.90.0.0/22", "10.80.0.0/22"), `
data "aws_eks_cluster" "test" {
name = aws_eks_cluster.test.name
}
`)
}
Loading

0 comments on commit b1f44a7

Please sign in to comment.