From 71f57d03e20f07e9dbe6afd766f28ea8493c2066 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 20 Dec 2022 14:07:07 +0530 Subject: [PATCH 1/8] Add support for us-iso-east-1 and us-isob-east-1 regions --- pkg/apis/eksctl.io/v1alpha5/types.go | 29 +++++++++++++++++++++++++--- pkg/cfn/builder/karpenter_test.go | 20 +++++++++++++++++++ pkg/cfn/builder/partition.go | 22 +++++++++++++++------ 3 files changed, 62 insertions(+), 9 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 8c1c16e941..57bab5389f 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -194,15 +194,23 @@ const ( // RegionUSGovEast1 represents the region GovCloud (US-East) RegionUSGovEast1 = "us-gov-east-1" + // RegionUSISOEast1 represents the region US ISO East. + RegionUSISOEast1 = "us-iso-east-1" + + // RegionUSISOBEast1 represents the region US ISOB East (Ohio). + RegionUSISOBEast1 = "us-isob-east-1" + // DefaultRegion defines the default region, where to deploy the EKS cluster DefaultRegion = RegionUSWest2 ) // Partitions const ( - PartitionAWS = "aws" - PartitionChina = "aws-cn" - PartitionUSGov = "aws-us-gov" + PartitionAWS = "aws" + PartitionChina = "aws-cn" + PartitionUSGov = "aws-us-gov" + PartitionISOEast = "aws-iso" + PartitionISOBEast = "aws-iso-b" ) // Values for `NodeAMIFamily` @@ -355,6 +363,11 @@ const ( // eksResourceAccountAPSouthEast4 defines the AWS EKS account ID that provides node resources in ap-southeast-4 eksResourceAccountAPSouthEast4 = "491585149902" + // eksResourceAccountUSISOEast1 defines the AWS EKS account ID that provides node resources in us-iso-east-1 + eksResourceAccountUSISOEast1 = "725322719131" + + // eksResourceAccountUSISOEast1 defines the AWS EKS account ID that provides node resources in us-isob-east-1 + eksResourceAccountUSISOBEast1 = "187977181151" ) // Values for `VolumeType` @@ -497,6 +510,8 @@ func SupportedRegions() []string { RegionCNNorth1, RegionUSGovWest1, RegionUSGovEast1, + RegionUSISOEast1, + RegionUSISOBEast1, } } @@ -507,6 +522,10 @@ func Partition(region string) string { return PartitionUSGov case RegionCNNorth1, RegionCNNorthwest1: return PartitionChina + case RegionUSISOEast1: + return PartitionISOEast + case RegionUSISOBEast1: + return PartitionISOBEast default: return PartitionAWS } @@ -632,6 +651,10 @@ func EKSResourceAccountID(region string) string { return eksResourceAccountAPSouthEast3 case RegionAPSouthEast4: return eksResourceAccountAPSouthEast4 + case RegionUSISOEast1: + return eksResourceAccountUSISOEast1 + case RegionUSISOBEast1: + return eksResourceAccountUSISOBEast1 default: return eksResourceAccountStandard } diff --git a/pkg/cfn/builder/karpenter_test.go b/pkg/cfn/builder/karpenter_test.go index 0d9bffb5d9..24edb1830d 100644 --- a/pkg/cfn/builder/karpenter_test.go +++ b/pkg/cfn/builder/karpenter_test.go @@ -82,6 +82,16 @@ var expectedTemplate = `{ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", @@ -209,6 +219,16 @@ var expectedTemplateWithPermissionBoundary = `{ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", diff --git a/pkg/cfn/builder/partition.go b/pkg/cfn/builder/partition.go index 826cf78498..4804b2f5bf 100644 --- a/pkg/cfn/builder/partition.go +++ b/pkg/cfn/builder/partition.go @@ -4,21 +4,31 @@ import ( "fmt" gfnt "github.com/weaveworks/goformation/v4/cloudformation/types" + + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" ) +var standardMappings = map[string]string{ + "EC2": "ec2.amazonaws.com", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com", +} + var servicePrincipalPartitionMappings = map[string]map[string]string{ - "aws": { - "EC2": "ec2.amazonaws.com", + api.PartitionAWS: standardMappings, + api.PartitionUSGov: standardMappings, + api.PartitionChina: { + "EC2": "ec2.amazonaws.com.cn", "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com", }, - "aws-us-gov": { - "EC2": "ec2.amazonaws.com", + api.PartitionISOEast: { + "EC2": "ec2.c2s.ic.gov", "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com", }, - "aws-cn": { - "EC2": "ec2.amazonaws.com.cn", + api.PartitionISOBEast: { + "EC2": "ec2.sc2s.sgov.gov", "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com", }, From 2cec28f3834fee995270505db68fea3bbf78b156 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 20 Dec 2022 14:07:21 +0530 Subject: [PATCH 2/8] Fix unit tests --- .../nodegroup/testdata/al2-force-false-template.json | 10 ++++++++++ .../nodegroup/testdata/al2-no-force-template.json | 10 ++++++++++ .../nodegroup/testdata/al2-updated-template.json | 10 ++++++++++ .../nodegroup/testdata/br-force-false-template.json | 10 ++++++++++ .../nodegroup/testdata/br-force-true-template.json | 10 ++++++++++ .../nodegroup/testdata/br-updated-template.json | 10 ++++++++++ 6 files changed, 60 insertions(+) diff --git a/pkg/actions/nodegroup/testdata/al2-force-false-template.json b/pkg/actions/nodegroup/testdata/al2-force-false-template.json index f0d32145d4..fba5f9fe55 100644 --- a/pkg/actions/nodegroup/testdata/al2-force-false-template.json +++ b/pkg/actions/nodegroup/testdata/al2-force-false-template.json @@ -13,6 +13,16 @@ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", diff --git a/pkg/actions/nodegroup/testdata/al2-no-force-template.json b/pkg/actions/nodegroup/testdata/al2-no-force-template.json index f0389bfd79..2cd2b5c8e5 100644 --- a/pkg/actions/nodegroup/testdata/al2-no-force-template.json +++ b/pkg/actions/nodegroup/testdata/al2-no-force-template.json @@ -13,6 +13,16 @@ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", diff --git a/pkg/actions/nodegroup/testdata/al2-updated-template.json b/pkg/actions/nodegroup/testdata/al2-updated-template.json index 95d05f1d5f..dfbee7d376 100644 --- a/pkg/actions/nodegroup/testdata/al2-updated-template.json +++ b/pkg/actions/nodegroup/testdata/al2-updated-template.json @@ -13,6 +13,16 @@ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", diff --git a/pkg/actions/nodegroup/testdata/br-force-false-template.json b/pkg/actions/nodegroup/testdata/br-force-false-template.json index 89079105c9..7b51077eff 100644 --- a/pkg/actions/nodegroup/testdata/br-force-false-template.json +++ b/pkg/actions/nodegroup/testdata/br-force-false-template.json @@ -14,6 +14,16 @@ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", diff --git a/pkg/actions/nodegroup/testdata/br-force-true-template.json b/pkg/actions/nodegroup/testdata/br-force-true-template.json index ba43850044..f95ec3a952 100644 --- a/pkg/actions/nodegroup/testdata/br-force-true-template.json +++ b/pkg/actions/nodegroup/testdata/br-force-true-template.json @@ -14,6 +14,16 @@ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", diff --git a/pkg/actions/nodegroup/testdata/br-updated-template.json b/pkg/actions/nodegroup/testdata/br-updated-template.json index 8d83845c4a..4dd13b428f 100644 --- a/pkg/actions/nodegroup/testdata/br-updated-template.json +++ b/pkg/actions/nodegroup/testdata/br-updated-template.json @@ -13,6 +13,16 @@ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", From e07f008346e34ccc4d9f3098f09d2e686af3eee5 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Fri, 27 Jan 2023 17:40:00 +0530 Subject: [PATCH 3/8] Refactor handling of partitions, fix validating partition --- pkg/actions/addon/create.go | 4 +- pkg/actions/iamidentitymapping/create.go | 2 +- pkg/apis/eksctl.io/v1alpha5/defaults.go | 3 +- pkg/apis/eksctl.io/v1alpha5/partitions.go | 95 +++++++++++++++++++++++ pkg/apis/eksctl.io/v1alpha5/types.go | 27 +------ pkg/cfn/builder/cluster.go | 2 +- pkg/cfn/builder/fargate.go | 7 +- pkg/cfn/builder/karpenter.go | 2 +- pkg/cfn/builder/managed_nodegroup.go | 2 +- pkg/cfn/builder/nodegroup.go | 2 +- pkg/cfn/builder/partition.go | 30 +------ pkg/cfn/builder/vpc_endpoint.go | 2 +- pkg/cfn/builder/vpc_endpoint_test.go | 2 +- pkg/eks/eks.go | 4 +- 14 files changed, 113 insertions(+), 71 deletions(-) create mode 100644 pkg/apis/eksctl.io/v1alpha5/partitions.go diff --git a/pkg/actions/addon/create.go b/pkg/actions/addon/create.go index d570cb6a62..39376a7b95 100644 --- a/pkg/actions/addon/create.go +++ b/pkg/actions/addon/create.go @@ -251,9 +251,9 @@ func (a *Manager) getRecommendedPolicies(addon *api.Addon) (api.InlineDocument, switch addon.CanonicalName() { case api.VPCCNIAddon: if a.clusterConfig.IPv6Enabled() { - return makeIPv6VPCCNIPolicyDocument(api.Partition(a.clusterConfig.Metadata.Region)), nil, nil + return makeIPv6VPCCNIPolicyDocument(api.Partitions.ForRegion(a.clusterConfig.Metadata.Region)), nil, nil } - return nil, []string{fmt.Sprintf("arn:%s:iam::aws:policy/%s", api.Partition(a.clusterConfig.Metadata.Region), api.IAMPolicyAmazonEKSCNIPolicy)}, nil + return nil, []string{fmt.Sprintf("arn:%s:iam::aws:policy/%s", api.Partitions.ForRegion(a.clusterConfig.Metadata.Region), api.IAMPolicyAmazonEKSCNIPolicy)}, nil case api.AWSEBSCSIDriverAddon: return nil, nil, &api.WellKnownPolicies{ EBSCSIController: true, diff --git a/pkg/actions/iamidentitymapping/create.go b/pkg/actions/iamidentitymapping/create.go index 74610a9038..221afc86d0 100644 --- a/pkg/actions/iamidentitymapping/create.go +++ b/pkg/actions/iamidentitymapping/create.go @@ -26,7 +26,7 @@ func (m *Manager) Create(ctx context.Context, mapping *api.IAMIdentityMapping) e return errors.Wrap(err, "error parsing cluster ARN") } sa := authconfigmap.NewServiceAccess(m.rawClient, acm, parsedARN.AccountID) - return sa.Grant(mapping.ServiceName, mapping.Namespace, api.Partition(m.region)) + return sa.Grant(mapping.ServiceName, mapping.Namespace, api.Partitions.ForRegion(m.region)) } if mapping.Account == "" { diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults.go b/pkg/apis/eksctl.io/v1alpha5/defaults.go index a04dc374fc..20e3323d5b 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults.go @@ -7,6 +7,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/aws/aws-sdk-go-v2/aws" + "github.com/weaveworks/eksctl/pkg/utils" ) @@ -78,7 +79,7 @@ func IAMServiceAccountsWithImplicitServiceAccounts(cfg *ClusterConfig) []*Cluste awsNode := ClusterIAMServiceAccount{ ClusterIAMMeta: AWSNodeMeta, AttachPolicyARNs: []string{ - fmt.Sprintf("arn:%s:iam::aws:policy/%s", Partition(cfg.Metadata.Region), IAMPolicyAmazonEKSCNIPolicy), + fmt.Sprintf("arn:%s:iam::aws:policy/%s", Partitions.ForRegion(cfg.Metadata.Region), IAMPolicyAmazonEKSCNIPolicy), }, } serviceAccounts = append(serviceAccounts, &awsNode) diff --git a/pkg/apis/eksctl.io/v1alpha5/partitions.go b/pkg/apis/eksctl.io/v1alpha5/partitions.go new file mode 100644 index 0000000000..1c13268c43 --- /dev/null +++ b/pkg/apis/eksctl.io/v1alpha5/partitions.go @@ -0,0 +1,95 @@ +package v1alpha5 + +// Partitions. +const ( + PartitionAWS = "aws" + PartitionChina = "aws-cn" + PartitionUSGov = "aws-us-gov" + PartitionISO = "aws-iso" + PartitionISOB = "aws-iso-b" +) + +type partition struct { + name string + serviceMappings map[string]string + regions []string +} + +type partitions []partition + +var standardServiceMappings = map[string]string{ + "EC2": "ec2.amazonaws.com", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com", +} + +// Partitions is a list of supported AWS partitions. +var Partitions = partitions{ + { + name: PartitionAWS, + serviceMappings: standardServiceMappings, + }, + { + name: PartitionUSGov, + serviceMappings: standardServiceMappings, + regions: []string{RegionUSGovEast1, RegionUSGovWest1}, + }, + { + name: PartitionChina, + serviceMappings: map[string]string{ + "EC2": "ec2.amazonaws.com.cn", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com", + }, + regions: []string{RegionCNNorth1, RegionCNNorthwest1}, + }, + { + name: PartitionISO, + serviceMappings: map[string]string{ + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com", + }, + regions: []string{RegionUSISOEast1}, + }, + { + name: PartitionISOB, + serviceMappings: map[string]string{ + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com", + }, + regions: []string{RegionUSISOBEast1}, + }, +} + +// ForRegion returns the partition a region belongs to. +func (p partitions) ForRegion(region string) string { + for _, pt := range p { + for _, r := range pt.regions { + if r == region { + return pt.name + } + } + } + return PartitionAWS +} + +// IsSupported returns true if the partition is supported. +func (p partitions) IsSupported(partition string) bool { + for _, pt := range p { + if pt.name == partition { + return true + } + } + return false +} + +// ServicePrincipalPartitionMappings returns the service principal partition mappings for all supported partitions. +func (p partitions) ServicePrincipalPartitionMappings() map[string]map[string]string { + ret := make(map[string]map[string]string, len(p)) + for _, pt := range p { + ret[pt.name] = pt.serviceMappings + } + return ret +} diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 57bab5389f..269cd43460 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -204,15 +204,6 @@ const ( DefaultRegion = RegionUSWest2 ) -// Partitions -const ( - PartitionAWS = "aws" - PartitionChina = "aws-cn" - PartitionUSGov = "aws-us-gov" - PartitionISOEast = "aws-iso" - PartitionISOBEast = "aws-iso-b" -) - // Values for `NodeAMIFamily` // All valid values of supported families should go in this block const ( @@ -366,7 +357,7 @@ const ( // eksResourceAccountUSISOEast1 defines the AWS EKS account ID that provides node resources in us-iso-east-1 eksResourceAccountUSISOEast1 = "725322719131" - // eksResourceAccountUSISOEast1 defines the AWS EKS account ID that provides node resources in us-isob-east-1 + // eksResourceAccountUSISOBEast1 defines the AWS EKS account ID that provides node resources in us-isob-east-1 eksResourceAccountUSISOBEast1 = "187977181151" ) @@ -515,22 +506,6 @@ func SupportedRegions() []string { } } -// Partition gives the partition a region belongs to -func Partition(region string) string { - switch region { - case RegionUSGovWest1, RegionUSGovEast1: - return PartitionUSGov - case RegionCNNorth1, RegionCNNorthwest1: - return PartitionChina - case RegionUSISOEast1: - return PartitionISOEast - case RegionUSISOBEast1: - return PartitionISOBEast - default: - return PartitionAWS - } -} - // DeprecatedVersions are the versions of Kubernetes that EKS used to support // but no longer does. See also: // https://docs.aws.amazon.com/eks/latest/userguide/kubernetes-versions.html diff --git a/pkg/cfn/builder/cluster.go b/pkg/cfn/builder/cluster.go index ed8d82b5cd..aaf0614639 100644 --- a/pkg/cfn/builder/cluster.go +++ b/pkg/cfn/builder/cluster.go @@ -99,7 +99,7 @@ func (c *ClusterResourceSet) AddAllResources(ctx context.Context) error { return nil }) - c.Template().Mappings[servicePrincipalPartitionMapName] = servicePrincipalPartitionMappings + c.Template().Mappings[servicePrincipalPartitionMapName] = api.Partitions.ServicePrincipalPartitionMappings() c.rs.template.Description = fmt.Sprintf( "%s (dedicated VPC: %v, dedicated IAM: %v) %s", diff --git a/pkg/cfn/builder/fargate.go b/pkg/cfn/builder/fargate.go index 41e37140ca..b621324a30 100644 --- a/pkg/cfn/builder/fargate.go +++ b/pkg/cfn/builder/fargate.go @@ -5,11 +5,12 @@ import ( "github.com/aws/aws-sdk-go-v2/aws/arn" "github.com/aws/aws-sdk-go-v2/service/cloudformation/types" + gfniam "github.com/weaveworks/goformation/v4/cloudformation/iam" + gfnt "github.com/weaveworks/goformation/v4/cloudformation/types" + api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/outputs" cft "github.com/weaveworks/eksctl/pkg/cfn/template" - gfniam "github.com/weaveworks/goformation/v4/cloudformation/iam" - gfnt "github.com/weaveworks/goformation/v4/cloudformation/types" ) const ( @@ -36,7 +37,7 @@ func NewFargateResourceSet(spec *api.ClusterConfig) *FargateResourceSet { } func (rs *FargateResourceSet) AddAllResources() error { - rs.rs.template.Mappings[servicePrincipalPartitionMapName] = servicePrincipalPartitionMappings + rs.rs.template.Mappings[servicePrincipalPartitionMapName] = api.Partitions.ServicePrincipalPartitionMappings() rs.rs.template.Description = fmt.Sprintf( "%s %s", diff --git a/pkg/cfn/builder/karpenter.go b/pkg/cfn/builder/karpenter.go index 7ae95a8ce8..42f0dd6048 100644 --- a/pkg/cfn/builder/karpenter.go +++ b/pkg/cfn/builder/karpenter.go @@ -120,7 +120,7 @@ func (k *KarpenterResourceSet) addResourcesForKarpenter() error { iamPolicyAmazonEC2ContainerRegistryReadOnly, iamPolicyAmazonSSMManagedInstanceCore, ) - k.Template().Mappings[servicePrincipalPartitionMapName] = servicePrincipalPartitionMappings + k.Template().Mappings[servicePrincipalPartitionMapName] = api.Partitions.ServicePrincipalPartitionMappings() roleName := gfnt.NewString(fmt.Sprintf("eksctl-%s-%s", KarpenterNodeRoleName, k.clusterSpec.Metadata.Name)) role := gfniam.Role{ RoleName: roleName, diff --git a/pkg/cfn/builder/managed_nodegroup.go b/pkg/cfn/builder/managed_nodegroup.go index 4c014d8aef..892668fc47 100644 --- a/pkg/cfn/builder/managed_nodegroup.go +++ b/pkg/cfn/builder/managed_nodegroup.go @@ -61,7 +61,7 @@ func (m *ManagedNodeGroupResourceSet) AddAllResources(ctx context.Context) error api.IsEnabled(m.nodeGroup.SSH.Allow), "[created by eksctl]") - m.template.Mappings[servicePrincipalPartitionMapName] = servicePrincipalPartitionMappings + m.template.Mappings[servicePrincipalPartitionMapName] = api.Partitions.ServicePrincipalPartitionMappings() var nodeRole *gfnt.Value if m.nodeGroup.IAM.InstanceRoleARN == "" { diff --git a/pkg/cfn/builder/nodegroup.go b/pkg/cfn/builder/nodegroup.go index fce01b3c6a..b086964a8f 100644 --- a/pkg/cfn/builder/nodegroup.go +++ b/pkg/cfn/builder/nodegroup.go @@ -78,7 +78,7 @@ func (n *NodeGroupResourceSet) AddAllResources(ctx context.Context) error { n.spec.AMIFamily, api.IsEnabled(n.spec.SSH.Allow), n.spec.PrivateNetworking, templateDescriptionSuffix) - n.Template().Mappings[servicePrincipalPartitionMapName] = servicePrincipalPartitionMappings + n.Template().Mappings[servicePrincipalPartitionMapName] = api.Partitions.ServicePrincipalPartitionMappings() n.rs.defineOutputWithoutCollector(outputs.NodeGroupFeaturePrivateNetworking, n.spec.PrivateNetworking, false) n.rs.defineOutputWithoutCollector(outputs.NodeGroupFeatureSharedSecurityGroup, n.spec.SecurityGroups.WithShared, false) diff --git a/pkg/cfn/builder/partition.go b/pkg/cfn/builder/partition.go index 4804b2f5bf..3a650557ea 100644 --- a/pkg/cfn/builder/partition.go +++ b/pkg/cfn/builder/partition.go @@ -4,40 +4,12 @@ import ( "fmt" gfnt "github.com/weaveworks/goformation/v4/cloudformation/types" - - api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" ) -var standardMappings = map[string]string{ - "EC2": "ec2.amazonaws.com", - "EKS": "eks.amazonaws.com", - "EKSFargatePods": "eks-fargate-pods.amazonaws.com", -} - -var servicePrincipalPartitionMappings = map[string]map[string]string{ - api.PartitionAWS: standardMappings, - api.PartitionUSGov: standardMappings, - api.PartitionChina: { - "EC2": "ec2.amazonaws.com.cn", - "EKS": "eks.amazonaws.com", - "EKSFargatePods": "eks-fargate-pods.amazonaws.com", - }, - api.PartitionISOEast: { - "EC2": "ec2.c2s.ic.gov", - "EKS": "eks.amazonaws.com", - "EKSFargatePods": "eks-fargate-pods.amazonaws.com", - }, - api.PartitionISOBEast: { - "EC2": "ec2.sc2s.sgov.gov", - "EKS": "eks.amazonaws.com", - "EKSFargatePods": "eks-fargate-pods.amazonaws.com", - }, -} - const servicePrincipalPartitionMapName = "ServicePrincipalPartitionMap" // MakeServiceRef returns a reference to an intrinsic map function that looks up the servicePrincipalName -// in servicePrincipalPartitionMappings +// in ServicePrincipalPartitionMap. func MakeServiceRef(servicePrincipalName string) *gfnt.Value { return gfnt.MakeFnFindInMap( gfnt.NewString(servicePrincipalPartitionMapName), gfnt.RefPartition, gfnt.NewString(servicePrincipalName), diff --git a/pkg/cfn/builder/vpc_endpoint.go b/pkg/cfn/builder/vpc_endpoint.go index e2099265ec..1db443a6bb 100644 --- a/pkg/cfn/builder/vpc_endpoint.go +++ b/pkg/cfn/builder/vpc_endpoint.go @@ -200,7 +200,7 @@ func serviceEndpointTypeExpected(serviceName string, endpointType ec2types.Servi func makeServiceName(domain, region string, endpointService api.EndpointService) string { serviceName := fmt.Sprintf("%s.%s", domain, endpointService.Name) - if endpointService.RequiresChinaPrefix && api.Partition(region) == api.PartitionChina { + if endpointService.RequiresChinaPrefix && api.Partitions.ForRegion(region) == api.PartitionChina { serviceName = "cn." + serviceName } return serviceName diff --git a/pkg/cfn/builder/vpc_endpoint_test.go b/pkg/cfn/builder/vpc_endpoint_test.go index fa3e2f9704..d3639da9ee 100644 --- a/pkg/cfn/builder/vpc_endpoint_test.go +++ b/pkg/cfn/builder/vpc_endpoint_test.go @@ -42,7 +42,7 @@ var _ = Describe("VPC Endpoint Builder", func() { api.SetClusterConfigDefaults(vc.clusterConfig) if len(vc.clusterConfig.AvailabilityZones) == 0 { - switch api.Partition(vc.clusterConfig.Metadata.Region) { + switch api.Partitions.ForRegion(vc.clusterConfig.Metadata.Region) { case api.PartitionAWS: vc.clusterConfig.AvailabilityZones = []string{"us-west-2a", "us-west-2b", "us-west-2c", "us-west-2d"} case api.PartitionChina: diff --git a/pkg/eks/eks.go b/pkg/eks/eks.go index 08f62c828a..46c6b398d8 100644 --- a/pkg/eks/eks.go +++ b/pkg/eks/eks.go @@ -170,9 +170,7 @@ func (c *ClusterProvider) NewOpenIDConnectManager(ctx context.Context, spec *api if err != nil { return nil, errors.Wrapf(err, "unexpected invalid ARN: %q", spec.Status.ARN) } - switch parsedARN.Partition { - case "aws", "aws-cn", "aws-us-gov": - default: + if !api.Partitions.IsSupported(parsedARN.Partition) { return nil, fmt.Errorf("unknown EKS ARN: %q", spec.Status.ARN) } From 3b851f49c4c84ae5fc66b589e35a01b0f3e03cd7 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 31 Jan 2023 17:38:37 +0530 Subject: [PATCH 4/8] Set default volume type for ISO regions --- pkg/apis/eksctl.io/v1alpha5/defaults.go | 20 +++++++------- pkg/apis/eksctl.io/v1alpha5/defaults_test.go | 29 ++++++++++++++++++++ pkg/apis/eksctl.io/v1alpha5/types.go | 9 ++++++ pkg/ctl/cmdutils/configfile.go | 4 +++ 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults.go b/pkg/apis/eksctl.io/v1alpha5/defaults.go index 20e3323d5b..093857ca90 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults.go @@ -105,8 +105,8 @@ func SetNodeGroupDefaults(ng *NodeGroup, meta *ClusterMeta, controlPlaneOnOutpos ng.AMIFamily = DefaultNodeImageFamily } - setVolumeDefaults(ng.NodeGroupBase, controlPlaneOnOutposts, nil) - setDefaultsForAdditionalVolumes(ng.NodeGroupBase, controlPlaneOnOutposts) + setVolumeDefaults(ng.NodeGroupBase, controlPlaneOnOutposts, meta.Region, nil) + setDefaultsForAdditionalVolumes(ng.NodeGroupBase, controlPlaneOnOutposts, meta.Region) if ng.SecurityGroups.WithLocal == nil { ng.SecurityGroups.WithLocal = Enabled() @@ -134,8 +134,8 @@ func SetManagedNodeGroupDefaults(ng *ManagedNodeGroup, meta *ClusterMeta, contro ng.Tags[NodeGroupNameTag] = ng.Name ng.Tags[NodeGroupTypeTag] = string(NodeGroupTypeManaged) - setVolumeDefaults(ng.NodeGroupBase, controlPlaneOnOutposts, ng.LaunchTemplate) - setDefaultsForAdditionalVolumes(ng.NodeGroupBase, controlPlaneOnOutposts) + setVolumeDefaults(ng.NodeGroupBase, controlPlaneOnOutposts, meta.Region, ng.LaunchTemplate) + setDefaultsForAdditionalVolumes(ng.NodeGroupBase, controlPlaneOnOutposts, meta.Region) } func setNodeGroupBaseDefaults(ng *NodeGroupBase, meta *ClusterMeta) { @@ -178,9 +178,9 @@ func setNodeGroupBaseDefaults(ng *NodeGroupBase, meta *ClusterMeta) { } } -func setVolumeDefaults(ng *NodeGroupBase, controlPlaneOnOutposts bool, template *LaunchTemplate) { +func setVolumeDefaults(ng *NodeGroupBase, controlPlaneOnOutposts bool, region string, template *LaunchTemplate) { if ng.VolumeType == nil { - ng.VolumeType = aws.String(getDefaultVolumeType(controlPlaneOnOutposts || ng.OutpostARN != "")) + ng.VolumeType = aws.String(getDefaultVolumeType(controlPlaneOnOutposts || ng.OutpostARN != "", region)) } if ng.VolumeSize == nil && template == nil { ng.VolumeSize = &DefaultNodeVolumeSize @@ -206,10 +206,10 @@ func setVolumeDefaults(ng *NodeGroupBase, controlPlaneOnOutposts bool, template } } -func setDefaultsForAdditionalVolumes(ng *NodeGroupBase, controlPlaneOnOutposts bool) { +func setDefaultsForAdditionalVolumes(ng *NodeGroupBase, controlPlaneOnOutposts bool, region string) { for i, av := range ng.AdditionalVolumes { if av.VolumeType == nil { - ng.AdditionalVolumes[i].VolumeType = aws.String(getDefaultVolumeType(controlPlaneOnOutposts)) + ng.AdditionalVolumes[i].VolumeType = aws.String(getDefaultVolumeType(controlPlaneOnOutposts, region)) } if av.VolumeSize == nil { ng.AdditionalVolumes[i].VolumeSize = &DefaultNodeVolumeSize @@ -228,11 +228,11 @@ func setDefaultsForAdditionalVolumes(ng *NodeGroupBase, controlPlaneOnOutposts b } } -func getDefaultVolumeType(nodeGroupOnOutposts bool) string { +func getDefaultVolumeType(nodeGroupOnOutposts bool, region string) string { if nodeGroupOnOutposts { return NodeVolumeTypeGP2 } - return DefaultNodeVolumeType + return defaultVolumeTypeForRegion(region) } func setContainerRuntimeDefault(ng *NodeGroup, clusterVersion string) { diff --git a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go index f865880db3..e2511cd96b 100644 --- a/pkg/apis/eksctl.io/v1alpha5/defaults_test.go +++ b/pkg/apis/eksctl.io/v1alpha5/defaults_test.go @@ -192,6 +192,35 @@ var _ = Describe("ClusterConfig validation", func() { Expect(*testNodeGroup.AdditionalVolumes[0].VolumeType).To(Equal(NodeVolumeTypeGP2)) Expect(*testNodeGroup.AdditionalVolumes[0].VolumeSize).To(Equal(DefaultNodeVolumeSize)) }) + + It("sets up defaults for the main volume in an ISO region", func() { + testNodeGroup := NodeGroup{ + NodeGroupBase: &NodeGroupBase{}, + } + + SetNodeGroupDefaults(&testNodeGroup, &ClusterMeta{ + Region: RegionUSISOEast1, + }, false) + Expect(*testNodeGroup.VolumeType).To(Equal(NodeVolumeTypeIO1)) + Expect(*testNodeGroup.VolumeSize).To(Equal(DefaultNodeVolumeSize)) + }) + It("sets up defaults for any additional volume in an ISO region", func() { + testNodeGroup := NodeGroup{ + NodeGroupBase: &NodeGroupBase{ + AdditionalVolumes: []*VolumeMapping{ + { + VolumeName: aws.String("test"), + }, + }, + }, + } + + SetNodeGroupDefaults(&testNodeGroup, &ClusterMeta{ + Region: RegionUSISOBEast1, + }, false) + Expect(*testNodeGroup.AdditionalVolumes[0].VolumeType).To(Equal(NodeVolumeTypeIO1)) + Expect(*testNodeGroup.AdditionalVolumes[0].VolumeSize).To(Equal(DefaultNodeVolumeSize)) + }) }) Context("Bottlerocket Settings", func() { diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 269cd43460..e3e41a2177 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -204,6 +204,15 @@ const ( DefaultRegion = RegionUSWest2 ) +func defaultVolumeTypeForRegion(region string) string { + switch region { + case RegionUSISOEast1, RegionUSISOBEast1: + return NodeVolumeTypeIO1 + default: + return DefaultNodeVolumeType + } +} + // Values for `NodeAMIFamily` // All valid values of supported families should go in this block const ( diff --git a/pkg/ctl/cmdutils/configfile.go b/pkg/ctl/cmdutils/configfile.go index 8a2ca680b2..40b7fc917e 100644 --- a/pkg/ctl/cmdutils/configfile.go +++ b/pkg/ctl/cmdutils/configfile.go @@ -306,6 +306,7 @@ func NewCreateClusterLoader(cmd *Cmd, ngFilter *filter.NodeGroupFilter, ng *api. l.validateWithoutConfigFile = func() error { meta := l.ClusterConfig.Metadata + meta.Region = cmd.ProviderConfig.Region // generate cluster name or use either flag or argument if names.ForCluster(meta.Name, l.NameArg) == "" { @@ -557,6 +558,9 @@ func normalizeBaseNodeGroup(np api.NodePool, cmd *cobra.Command) { if !flags.Changed("enable-ssm") { ng.SSH.EnableSSM = nil } + if !flags.Changed("node-volume-type") { + ng.VolumeType = nil + } } // NewDeleteAndDrainNodeGroupLoader will load config or use flags for 'eksctl delete nodegroup' From 175c0d6c7d24f68a2518cc5abfd1b3bfdbb12a84 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Fri, 10 Feb 2023 15:47:12 +0530 Subject: [PATCH 5/8] Fix support for fully-private clusters for ISO regions --- .../eksctl.io/v1alpha5/endpoint_service.go | 10 +- pkg/apis/eksctl.io/v1alpha5/partitions.go | 64 +++- .../builder/testdata/service_details_iso.json | 162 +++++++++ .../testdata/service_details_outpost.json | 336 ------------------ pkg/cfn/builder/testdata/vpc_private_iso.json | 225 ++++++++++++ pkg/cfn/builder/vpc_endpoint.go | 31 +- pkg/cfn/builder/vpc_endpoint_test.go | 66 ++-- 7 files changed, 506 insertions(+), 388 deletions(-) create mode 100644 pkg/cfn/builder/testdata/service_details_iso.json delete mode 100644 pkg/cfn/builder/testdata/service_details_outpost.json create mode 100644 pkg/cfn/builder/testdata/vpc_private_iso.json diff --git a/pkg/apis/eksctl.io/v1alpha5/endpoint_service.go b/pkg/apis/eksctl.io/v1alpha5/endpoint_service.go index b284bce838..3866c90d44 100644 --- a/pkg/apis/eksctl.io/v1alpha5/endpoint_service.go +++ b/pkg/apis/eksctl.io/v1alpha5/endpoint_service.go @@ -14,6 +14,8 @@ type EndpointService struct { OutpostsOnly bool // RequiresChinaPrefix is true if the endpoint service requires a prefix for China regions. RequiresChinaPrefix bool + // RequiresISOPrefix is true if the endpoint service requires a prefix for ISO regions. + RequiresISOPrefix bool } var ( @@ -33,14 +35,17 @@ var EndpointServices = []EndpointService{ { Name: "ec2", RequiresChinaPrefix: true, + RequiresISOPrefix: true, }, { Name: "ecr.api", RequiresChinaPrefix: true, + RequiresISOPrefix: true, }, { Name: "ecr.dkr", RequiresChinaPrefix: true, + RequiresISOPrefix: true, }, EndpointServiceS3, { @@ -69,8 +74,9 @@ var EndpointServices = []EndpointService{ RequiresChinaPrefix: true, }, { - Name: "autoscaling", - Optional: true, + Name: "autoscaling", + Optional: true, + RequiresISOPrefix: true, }, EndpointServiceCloudWatch, } diff --git a/pkg/apis/eksctl.io/v1alpha5/partitions.go b/pkg/apis/eksctl.io/v1alpha5/partitions.go index 1c13268c43..b73885c79c 100644 --- a/pkg/apis/eksctl.io/v1alpha5/partitions.go +++ b/pkg/apis/eksctl.io/v1alpha5/partitions.go @@ -1,5 +1,7 @@ package v1alpha5 +import "fmt" + // Partitions. const ( PartitionAWS = "aws" @@ -9,10 +11,12 @@ const ( PartitionISOB = "aws-iso-b" ) +// partition is an AWS partition. type partition struct { - name string - serviceMappings map[string]string - regions []string + name string + serviceMappings map[string]string + regions []string + endpointServiceDomainPrefix string } type partitions []partition @@ -23,16 +27,22 @@ var standardServiceMappings = map[string]string{ "EKSFargatePods": "eks-fargate-pods.amazonaws.com", } +const standardPartitionServiceDomainPrefix = "com.amazonaws" + +var awsPartition = partition{ + name: PartitionAWS, + serviceMappings: standardServiceMappings, + endpointServiceDomainPrefix: standardPartitionServiceDomainPrefix, +} + // Partitions is a list of supported AWS partitions. var Partitions = partitions{ + awsPartition, { - name: PartitionAWS, - serviceMappings: standardServiceMappings, - }, - { - name: PartitionUSGov, - serviceMappings: standardServiceMappings, - regions: []string{RegionUSGovEast1, RegionUSGovWest1}, + name: PartitionUSGov, + serviceMappings: standardServiceMappings, + regions: []string{RegionUSGovEast1, RegionUSGovWest1}, + endpointServiceDomainPrefix: standardPartitionServiceDomainPrefix, }, { name: PartitionChina, @@ -41,7 +51,8 @@ var Partitions = partitions{ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com", }, - regions: []string{RegionCNNorth1, RegionCNNorthwest1}, + regions: []string{RegionCNNorth1, RegionCNNorthwest1}, + endpointServiceDomainPrefix: fmt.Sprintf("cn.%s", standardPartitionServiceDomainPrefix), }, { name: PartitionISO, @@ -50,7 +61,8 @@ var Partitions = partitions{ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com", }, - regions: []string{RegionUSISOEast1}, + regions: []string{RegionUSISOEast1}, + endpointServiceDomainPrefix: "gov.ic.c2s", }, { name: PartitionISOB, @@ -59,7 +71,8 @@ var Partitions = partitions{ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com", }, - regions: []string{RegionUSISOBEast1}, + regions: []string{RegionUSISOBEast1}, + endpointServiceDomainPrefix: "gov.sgov.sc2s", }, } @@ -75,6 +88,31 @@ func (p partitions) ForRegion(region string) string { return PartitionAWS } +// GetEndpointServiceDomainPrefix returns the domain prefix for the endpoint service. +func (p partitions) GetEndpointServiceDomainPrefix(endpointService EndpointService, region string) string { + for _, pt := range p { + for _, r := range pt.regions { + if r == region { + switch pt.name { + case PartitionChina: + if endpointService.RequiresChinaPrefix { + return pt.endpointServiceDomainPrefix + } + return standardPartitionServiceDomainPrefix + case PartitionISO: + if endpointService.RequiresISOPrefix { + return pt.endpointServiceDomainPrefix + } + return standardPartitionServiceDomainPrefix + default: + return pt.endpointServiceDomainPrefix + } + } + } + } + return awsPartition.endpointServiceDomainPrefix +} + // IsSupported returns true if the partition is supported. func (p partitions) IsSupported(partition string) bool { for _, pt := range p { diff --git a/pkg/cfn/builder/testdata/service_details_iso.json b/pkg/cfn/builder/testdata/service_details_iso.json new file mode 100644 index 0000000000..e14d04cd11 --- /dev/null +++ b/pkg/cfn/builder/testdata/service_details_iso.json @@ -0,0 +1,162 @@ +{ + "ServiceNames": [ + "gov.ic.c2s.us-iso-east-1.ec2", + "gov.ic.c2s.us-iso-east-1.ecr.api", + "gov.ic.c2s.us-iso-east-1.ecr.dkr", + "com.amazonaws.us-iso-east-1.s3", + "com.amazonaws.us-iso-east-1.sts" + ], + "ServiceDetails": [ + { + "ServiceType": [ + { + "ServiceType": "Interface" + } + ], + "Tags": [], + "ManagesVpcEndpoints": false, + "PrivateDnsName": "ec2.us-iso-east-1.amazonaws.com", + "ServiceName": "gov.ic.c2s.us-iso-east-1.ec2", + "VpcEndpointPolicySupported": true, + "ServiceId": "vpce-svc-1", + "Owner": "amazon", + "AvailabilityZones": [ + "us-iso-east-1a", + "us-iso-east-1b" + ], + "AcceptanceRequired": false, + "BaseEndpointDnsNames": [ + "ec2.us-iso-east-1.vpce.amazonaws.com" + ] + }, + { + "ServiceType": [ + { + "ServiceType": "Interface" + } + ], + "Tags": [], + "ManagesVpcEndpoints": false, + "PrivateDnsName": "api.ecr.us-iso-east-1.amazonaws.com", + "ServiceName": "gov.ic.c2s.us-iso-east-1.ecr.api", + "VpcEndpointPolicySupported": true, + "ServiceId": "vpce-svc-2", + "Owner": "amazon", + "AvailabilityZones": [ + "us-iso-east-1a", + "us-iso-east-1b" + ], + "AcceptanceRequired": false, + "BaseEndpointDnsNames": [ + "api.ecr.us-iso-east-1.vpce.amazonaws.com" + ] + }, + { + "ServiceType": [ + { + "ServiceType": "Interface" + } + ], + "Tags": [], + "ManagesVpcEndpoints": false, + "PrivateDnsName": "*.dkr.ecr.us-iso-east-1.amazonaws.com", + "ServiceName": "gov.ic.c2s.us-iso-east-1.ecr.dkr", + "VpcEndpointPolicySupported": true, + "ServiceId": "vpce-svc-3", + "Owner": "amazon", + "AvailabilityZones": [ + "us-iso-east-1a", + "us-iso-east-1b" + ], + "AcceptanceRequired": false, + "BaseEndpointDnsNames": [ + "dkr.ecr.us-iso-east-1.vpce.amazonaws.com" + ] + }, + { + "ServiceType": [ + { + "ServiceType": "Gateway" + } + ], + "Tags": [], + "ManagesVpcEndpoints": false, + "AcceptanceRequired": false, + "ServiceName": "com.amazonaws.us-iso-east-1.s3", + "VpcEndpointPolicySupported": true, + "ServiceId": "vpce-svc-4", + "Owner": "amazon", + "AvailabilityZones": [ + "us-iso-east-1a", + "us-iso-east-1b" + ], + "BaseEndpointDnsNames": [ + "s3.us-iso-east-1.amazonaws.com" + ] + }, + { + "ServiceType": [ + { + "ServiceType": "Interface" + } + ], + "Tags": [], + "ManagesVpcEndpoints": false, + "AcceptanceRequired": false, + "ServiceName": "com.amazonaws.us-iso-east-1.s3", + "VpcEndpointPolicySupported": true, + "ServiceId": "vpce-svc-5", + "Owner": "amazon", + "AvailabilityZones": [ + "us-iso-east-1a", + "us-iso-east-1b" + ], + "BaseEndpointDnsNames": [ + "s3.us-iso-east-1.amazonaws.com" + ] + }, + { + "ServiceType": [ + { + "ServiceType": "Interface" + } + ], + "Tags": [], + "ManagesVpcEndpoints": false, + "PrivateDnsName": "sts.us-iso-east-1.amazonaws.com", + "ServiceName": "com.amazonaws.us-iso-east-1.sts", + "VpcEndpointPolicySupported": true, + "ServiceId": "vpce-svc-6", + "Owner": "amazon", + "AvailabilityZones": [ + "us-iso-east-1a", + "us-iso-east-1b" + ], + "AcceptanceRequired": false, + "BaseEndpointDnsNames": [ + "sts.us-iso-east-1.vpce.amazonaws.com" + ] + }, + { + "ServiceType": [ + { + "ServiceType": "Gateway" + } + ], + "Tags": [], + "ManagesVpcEndpoints": false, + "AcceptanceRequired": false, + "ServiceName": "gov.ic.c2s.us-iso-east-1.ec2", + "VpcEndpointPolicySupported": true, + "ServiceId": "vpce-svc-non-existing-endpoint-type", + "Owner": "amazon", + "AvailabilityZones": [ + "us-iso-east-1a", + "us-iso-east-1b" + ], + "BaseEndpointDnsNames": [ + "ec2.us-iso-east-1.amazonaws.com" + ] + } + ] +} diff --git a/pkg/cfn/builder/testdata/service_details_outpost.json b/pkg/cfn/builder/testdata/service_details_outpost.json deleted file mode 100644 index f86c869616..0000000000 --- a/pkg/cfn/builder/testdata/service_details_outpost.json +++ /dev/null @@ -1,336 +0,0 @@ -{ - "ServiceDetails": [ - { - "ServiceName": "com.amazonaws.us-west-2.ec2", - "ServiceId": "vpce-svc-1", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "ec2.us-west-2.vpce.amazonaws.com" - ], - "PrivateDnsName": "ec2.us-west-2.amazonaws.com", - "PrivateDnsNames": [ - { - "PrivateDnsName": "ec2.us-west-2.amazonaws.com" - }, - { - "PrivateDnsName": "ec2.us-west-2.api.aws" - } - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "PrivateDnsNameVerificationState": "verified", - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.ec2messages", - "ServiceId": "vpce-svc-2", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "ec2messages.us-west-2.vpce.amazonaws.com" - ], - "PrivateDnsName": "ec2messages.us-west-2.amazonaws.com", - "PrivateDnsNames": [ - { - "PrivateDnsName": "ec2messages.us-west-2.amazonaws.com" - } - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "PrivateDnsNameVerificationState": "verified", - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.ecr.api", - "ServiceId": "vpce-svc-3", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "api.ecr.us-west-2.vpce.amazonaws.com" - ], - "PrivateDnsName": "api.ecr.us-west-2.amazonaws.com", - "PrivateDnsNames": [ - { - "PrivateDnsName": "api.ecr.us-west-2.amazonaws.com" - } - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "PrivateDnsNameVerificationState": "verified", - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.ecr.dkr", - "ServiceId": "vpce-svc-4", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "dkr.ecr.us-west-2.vpce.amazonaws.com" - ], - "PrivateDnsName": "*.dkr.ecr.us-west-2.amazonaws.com", - "PrivateDnsNames": [ - { - "PrivateDnsName": "*.dkr.ecr.us-west-2.amazonaws.com" - } - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "PrivateDnsNameVerificationState": "verified", - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.s3", - "ServiceId": "vpce-svc-5", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "s3.us-west-2.vpce.amazonaws.com" - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.s3", - "ServiceId": "vpce-svc-6", - "ServiceType": [ - { - "ServiceType": "Gateway" - } - ], - "AvailabilityZones": [ - "us-west-2-lax-1a", - "us-west-2-lax-1b", - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "s3.us-west-2.amazonaws.com" - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.secretsmanager", - "ServiceId": "vpce-svc-7", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "secretsmanager.us-west-2.vpce.amazonaws.com" - ], - "PrivateDnsName": "secretsmanager.us-west-2.amazonaws.com", - "PrivateDnsNames": [ - { - "PrivateDnsName": "secretsmanager.us-west-2.amazonaws.com" - } - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "PrivateDnsNameVerificationState": "verified", - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.ssm", - "ServiceId": "vpce-svc-8", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "ssm.us-west-2.vpce.amazonaws.com" - ], - "PrivateDnsName": "ssm.us-west-2.amazonaws.com", - "PrivateDnsNames": [ - { - "PrivateDnsName": "ssm.us-west-2.amazonaws.com" - } - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "PrivateDnsNameVerificationState": "verified", - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.ssmmessages", - "ServiceId": "vpce-svc-9", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "ssmmessages.us-west-2.vpce.amazonaws.com" - ], - "PrivateDnsName": "ssmmessages.us-west-2.amazonaws.com", - "PrivateDnsNames": [ - { - "PrivateDnsName": "ssmmessages.us-west-2.amazonaws.com" - } - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "PrivateDnsNameVerificationState": "verified", - "SupportedIpAddressTypes": [ - "ipv4" - ] - }, - { - "ServiceName": "com.amazonaws.us-west-2.sts", - "ServiceId": "vpce-svc-10", - "ServiceType": [ - { - "ServiceType": "Interface" - } - ], - "AvailabilityZones": [ - "us-west-2a", - "us-west-2b", - "us-west-2c", - "us-west-2d" - ], - "Owner": "amazon", - "BaseEndpointDnsNames": [ - "sts.us-west-2.vpce.amazonaws.com" - ], - "PrivateDnsName": "sts.us-west-2.amazonaws.com", - "PrivateDnsNames": [ - { - "PrivateDnsName": "sts.us-west-2.amazonaws.com" - } - ], - "VpcEndpointPolicySupported": true, - "AcceptanceRequired": false, - "ManagesVpcEndpoints": false, - "Tags": [], - "PrivateDnsNameVerificationState": "verified", - "SupportedIpAddressTypes": [ - "ipv4" - ] - } - ], - "ServiceNames": [ - "com.amazonaws.us-west-2.ec2", - "com.amazonaws.us-west-2.ecr.api", - "com.amazonaws.us-west-2.ecr.dkr", - "com.amazonaws.us-west-2.s3", - "com.amazonaws.us-west-2.sts", - "com.amazonaws.us-west-2.ssm", - "com.amazonaws.us-west-2.ssmmessages", - "com.amazonaws.us-west-2.ec2messages", - "com.amazonaws.us-west-2.secretsmanager" - ] -} diff --git a/pkg/cfn/builder/testdata/vpc_private_iso.json b/pkg/cfn/builder/testdata/vpc_private_iso.json new file mode 100644 index 0000000000..e7754a97dd --- /dev/null +++ b/pkg/cfn/builder/testdata/vpc_private_iso.json @@ -0,0 +1,225 @@ +{ + "AWSTemplateFormatVersion": "2010-09-09", + "Resources": { + "PrivateRouteTableUSISOEAST1A": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": { + "Fn::Sub": "${AWS::StackName}/PrivateRouteTableUSISOEAST1A" + } + } + ], + "VpcId": { + "Ref": "VPC" + } + } + }, + "PrivateRouteTableUSISOEAST1B": { + "Type": "AWS::EC2::RouteTable", + "Properties": { + "Tags": [ + { + "Key": "Name", + "Value": { + "Fn::Sub": "${AWS::StackName}/PrivateRouteTableUSISOEAST1B" + } + } + ], + "VpcId": { + "Ref": "VPC" + } + } + }, + "RouteTableAssociationPrivateUSISOEAST1A": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "PrivateRouteTableUSISOEAST1A" + }, + "SubnetId": { + "Ref": "SubnetPrivateUSISOEAST1A" + } + } + }, + "RouteTableAssociationPrivateUSISOEAST1B": { + "Type": "AWS::EC2::SubnetRouteTableAssociation", + "Properties": { + "RouteTableId": { + "Ref": "PrivateRouteTableUSISOEAST1B" + }, + "SubnetId": { + "Ref": "SubnetPrivateUSISOEAST1B" + } + } + }, + "SubnetPrivateUSISOEAST1A": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "us-iso-east-1a", + "CidrBlock": "192.168.64.0/19", + "Tags": [ + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": { + "Fn::Sub": "${AWS::StackName}/SubnetPrivateUSISOEAST1A" + } + } + ], + "VpcId": { + "Ref": "VPC" + } + } + }, + "SubnetPrivateUSISOEAST1B": { + "Type": "AWS::EC2::Subnet", + "Properties": { + "AvailabilityZone": "us-iso-east-1b", + "CidrBlock": "192.168.96.0/19", + "Tags": [ + { + "Key": "kubernetes.io/role/internal-elb", + "Value": "1" + }, + { + "Key": "Name", + "Value": { + "Fn::Sub": "${AWS::StackName}/SubnetPrivateUSISOEAST1B" + } + } + ], + "VpcId": { + "Ref": "VPC" + } + } + }, + "VPC": { + "Type": "AWS::EC2::VPC", + "Properties": { + "CidrBlock": "192.168.0.0/16", + "EnableDnsHostnames": true, + "EnableDnsSupport": true, + "Tags": [ + { + "Key": "Name", + "Value": { + "Fn::Sub": "${AWS::StackName}/VPC" + } + } + ] + } + }, + "VPCEndpointEC2": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + "sg-test" + ], + "ServiceName": "gov.ic.c2s.us-iso-east-1.ec2", + "SubnetIds": [ + { + "Ref": "SubnetPrivateUSISOEAST1A" + }, + { + "Ref": "SubnetPrivateUSISOEAST1B" + } + ], + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "VPC" + } + } + }, + "VPCEndpointECRAPI": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + "sg-test" + ], + "ServiceName": "gov.ic.c2s.us-iso-east-1.ecr.api", + "SubnetIds": [ + { + "Ref": "SubnetPrivateUSISOEAST1A" + }, + { + "Ref": "SubnetPrivateUSISOEAST1B" + } + ], + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "VPC" + } + } + }, + "VPCEndpointECRDKR": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + "sg-test" + ], + "ServiceName": "gov.ic.c2s.us-iso-east-1.ecr.dkr", + "SubnetIds": [ + { + "Ref": "SubnetPrivateUSISOEAST1A" + }, + { + "Ref": "SubnetPrivateUSISOEAST1B" + } + ], + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "VPC" + } + } + }, + "VPCEndpointS3": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "RouteTableIds": [ + { + "Ref": "PrivateRouteTableUSISOEAST1A" + }, + { + "Ref": "PrivateRouteTableUSISOEAST1B" + } + ], + "ServiceName": "com.amazonaws.us-iso-east-1.s3", + "VpcEndpointType": "Gateway", + "VpcId": { + "Ref": "VPC" + } + } + }, + "VPCEndpointSTS": { + "Type": "AWS::EC2::VPCEndpoint", + "Properties": { + "PrivateDnsEnabled": true, + "SecurityGroupIds": [ + "sg-test" + ], + "ServiceName": "com.amazonaws.us-iso-east-1.sts", + "SubnetIds": [ + { + "Ref": "SubnetPrivateUSISOEAST1A" + }, + { + "Ref": "SubnetPrivateUSISOEAST1B" + } + ], + "VpcEndpointType": "Interface", + "VpcId": { + "Ref": "VPC" + } + } + } + } +} diff --git a/pkg/cfn/builder/vpc_endpoint.go b/pkg/cfn/builder/vpc_endpoint.go index 1db443a6bb..3563474c22 100644 --- a/pkg/cfn/builder/vpc_endpoint.go +++ b/pkg/cfn/builder/vpc_endpoint.go @@ -118,9 +118,8 @@ func (e *VPCEndpointResourceSet) routeTableIDs() []*gfnt.Value { // buildVPCEndpointServices builds a slice of VPCEndpointServiceDetails for the specified endpoint names. func (e *VPCEndpointResourceSet) buildVPCEndpointServices(ctx context.Context, endpointServices []api.EndpointService) ([]VPCEndpointServiceDetails, error) { serviceNames := make([]string, len(endpointServices)) - serviceDomain := fmt.Sprintf("com.amazonaws.%s", e.region) for i, endpoint := range endpointServices { - serviceNames[i] = makeServiceName(serviceDomain, e.region, endpoint) + serviceNames[i] = makeServiceName(endpoint, e.region) } var ( @@ -158,7 +157,7 @@ func (e *VPCEndpointResourceSet) buildVPCEndpointServices(ctx context.Context, e } var ret []VPCEndpointServiceDetails - s3ServiceName := makeServiceName(serviceDomain, e.region, api.EndpointServiceS3) + s3ServiceName := makeServiceName(api.EndpointServiceS3, e.region) for _, sd := range serviceDetails { if len(sd.ServiceType) > 1 { return nil, fmt.Errorf("endpoint service %q with multiple service types isn't supported", *sd.ServiceName) @@ -172,12 +171,10 @@ func (e *VPCEndpointResourceSet) buildVPCEndpointServices(ctx context.Context, e continue } - // Trim the domain (potentially with a partition-specific part) from the `ServiceName`. - parts := strings.Split(*sd.ServiceName, fmt.Sprintf("%s.", serviceDomain)) - if len(parts) != 2 { - return nil, fmt.Errorf("error parsing service name %s %s", *sd.ServiceName, serviceDomain) + readableName, err := makeReadableName(*sd.ServiceName, e.region) + if err != nil { + return nil, err } - readableName := parts[1] ret = append(ret, VPCEndpointServiceDetails{ ServiceName: *sd.ServiceName, @@ -190,6 +187,15 @@ func (e *VPCEndpointResourceSet) buildVPCEndpointServices(ctx context.Context, e return ret, nil } +func makeReadableName(serviceName, region string) (string, error) { + search := fmt.Sprintf(".%s.", region) + idx := strings.Index(serviceName, search) + if idx == -1 { + return "", fmt.Errorf("unexpected format for endpoint service name: %q", serviceName) + } + return serviceName[idx+len(search)-1:], nil +} + // serviceEndpointTypeExpected returns true if the endpoint service is expected to use the specified endpoint type. func serviceEndpointTypeExpected(serviceName string, endpointType ec2types.ServiceType, s3ServiceName string) bool { if serviceName == s3ServiceName { @@ -198,10 +204,7 @@ func serviceEndpointTypeExpected(serviceName string, endpointType ec2types.Servi return endpointType == ec2types.ServiceTypeInterface } -func makeServiceName(domain, region string, endpointService api.EndpointService) string { - serviceName := fmt.Sprintf("%s.%s", domain, endpointService.Name) - if endpointService.RequiresChinaPrefix && api.Partitions.ForRegion(region) == api.PartitionChina { - serviceName = "cn." + serviceName - } - return serviceName +func makeServiceName(endpointService api.EndpointService, region string) string { + serviceDomainPrefix := api.Partitions.GetEndpointServiceDomainPrefix(endpointService, region) + return fmt.Sprintf("%s.%s.%s", serviceDomainPrefix, region, endpointService.Name) } diff --git a/pkg/cfn/builder/vpc_endpoint_test.go b/pkg/cfn/builder/vpc_endpoint_test.go index d3639da9ee..a12980d5c1 100644 --- a/pkg/cfn/builder/vpc_endpoint_test.go +++ b/pkg/cfn/builder/vpc_endpoint_test.go @@ -44,9 +44,11 @@ var _ = Describe("VPC Endpoint Builder", func() { if len(vc.clusterConfig.AvailabilityZones) == 0 { switch api.Partitions.ForRegion(vc.clusterConfig.Metadata.Region) { case api.PartitionAWS: - vc.clusterConfig.AvailabilityZones = []string{"us-west-2a", "us-west-2b", "us-west-2c", "us-west-2d"} + vc.clusterConfig.AvailabilityZones = makeZones("us-west-2", 4) case api.PartitionChina: - vc.clusterConfig.AvailabilityZones = []string{"cn-north-1a", "cn-north-1b"} + vc.clusterConfig.AvailabilityZones = makeZones("cn-north-1", 2) + case api.PartitionISO: + vc.clusterConfig.AvailabilityZones = makeZones("us-iso-east-1", 2) default: panic("not supported in tests") } @@ -114,7 +116,7 @@ var _ = Describe("VPC Endpoint Builder", func() { }, createProvider: func() api.ClusterProvider { provider := mockprovider.NewMockProvider() - mockDescribeVPCEndpoints(provider, false, false) + mockDescribeVPCEndpoints(provider, serviceDetailsJSON) return provider }, expectedFile: "vpc_private.json", @@ -131,7 +133,7 @@ var _ = Describe("VPC Endpoint Builder", func() { }, createProvider: func() api.ClusterProvider { provider := mockprovider.NewMockProvider() - mockDescribeVPCEndpoints(provider, true, false) + mockDescribeVPCEndpoints(provider, serviceDetailsChinaJSON) provider.SetRegion("cn-north-1") return provider }, @@ -193,7 +195,7 @@ var _ = Describe("VPC Endpoint Builder", func() { createProvider: func() api.ClusterProvider { provider := mockprovider.NewMockProvider() mockDescribeVPC(provider) - mockDescribeVPCEndpoints(provider, false, false) + mockDescribeVPCEndpoints(provider, serviceDetailsJSON) mockDescribeRouteTables(provider, []string{"subnet-custom1", "subnet-custom2"}) return provider }, @@ -226,7 +228,7 @@ var _ = Describe("VPC Endpoint Builder", func() { createProvider: func() api.ClusterProvider { provider := mockprovider.NewMockProvider() mockDescribeVPC(provider) - mockDescribeVPCEndpoints(provider, false, false) + mockDescribeVPCEndpoints(provider, serviceDetailsJSON) mockDescribeRouteTablesSame(provider, []string{"subnet-custom1", "subnet-custom2"}) return provider }, @@ -302,7 +304,7 @@ var _ = Describe("VPC Endpoint Builder", func() { }, createProvider: func() api.ClusterProvider { provider := mockprovider.NewMockProvider() - mockDescribeVPCEndpoints(provider, false, true) + mockDescribeVPCEndpoints(provider, serviceDetailsOutpostsJSON) mockOutposts(provider, "arn:aws:outposts:us-west-2:1234:outpost/op-1234", "us-west-2a") return provider }, @@ -326,13 +328,32 @@ var _ = Describe("VPC Endpoint Builder", func() { }, createProvider: func() api.ClusterProvider { provider := mockprovider.NewMockProvider() - mockDescribeVPCEndpoints(provider, true, true) + mockDescribeVPCEndpoints(provider, serviceDetailsOutpostsChinaJSON) mockOutposts(provider, "arn:aws:outposts:cn-north-1:1234:outpost/op-1234", "cn-north-1a") provider.SetRegion("cn-north-1") return provider }, expectedFile: "vpc_private_outposts_china.json", }), + + Entry("Private cluster in an ISO region", vpcResourceSetCase{ + clusterConfig: &api.ClusterConfig{ + Metadata: &api.ClusterMeta{ + Region: "us-iso-east-1", + }, + VPC: api.NewClusterVPC(false), + PrivateCluster: &api.PrivateCluster{ + Enabled: true, + }, + }, + createProvider: func() api.ClusterProvider { + provider := mockprovider.NewMockProvider() + mockDescribeVPCEndpoints(provider, serviceDetailsISOJSON) + provider.SetRegion("us-iso-east-1") + return provider + }, + expectedFile: "vpc_private_iso.json", + }), ) }) @@ -340,7 +361,7 @@ var _ = Describe("VPC Endpoint Builder", func() { var serviceDetailsJSON []byte //go:embed testdata/service_details_china.json -var serviceDetailsJSONChina []byte +var serviceDetailsChinaJSON []byte //go:embed testdata/service_details_outposts.json var serviceDetailsOutpostsJSON []byte @@ -348,6 +369,9 @@ var serviceDetailsOutpostsJSON []byte //go:embed testdata/service_details_outposts_china.json var serviceDetailsOutpostsChinaJSON []byte +//go:embed testdata/service_details_iso.json +var serviceDetailsISOJSON []byte + func mockDescribeVPC(provider *mockprovider.MockProvider) { provider.MockEC2().On("DescribeVpcs", mock.Anything, &ec2.DescribeVpcsInput{ VpcIds: []string{"vpc-custom"}, @@ -365,21 +389,9 @@ func mockDescribeVPC(provider *mockprovider.MockProvider) { }, nil) } -func mockDescribeVPCEndpoints(provider *mockprovider.MockProvider, china, outposts bool) { - var detailsJSON []byte - switch { - case outposts && china: - detailsJSON = serviceDetailsOutpostsChinaJSON - case outposts: - detailsJSON = serviceDetailsOutpostsJSON - case china: - detailsJSON = serviceDetailsJSONChina - default: - detailsJSON = serviceDetailsJSON - } - +func mockDescribeVPCEndpoints(provider *mockprovider.MockProvider, serviceDetailsJSON []byte) { var output *ec2.DescribeVpcEndpointServicesOutput - Expect(json.Unmarshal(detailsJSON, &output)).To(Succeed()) + Expect(json.Unmarshal(serviceDetailsJSON, &output)).To(Succeed()) provider.MockEC2().On("DescribeVpcEndpointServices", mock.Anything, mock.MatchedBy(func(e *ec2.DescribeVpcEndpointServicesInput) bool { return reflect.DeepEqual(e.ServiceNames, output.ServiceNames) @@ -456,3 +468,11 @@ func mockDescribeRouteTablesSame(provider *mockprovider.MockProvider, subnetIDs return len(input.Filters) > 0 })).Return(output, nil) } + +func makeZones(region string, count int) []string { + var ret []string + for i := 0; i < count; i++ { + ret = append(ret, fmt.Sprintf("%s%c", region, 'a'+i)) + } + return ret +} From a03364f8c9aff9bb45c8441b99ca180ce8abc871 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Tue, 6 Jun 2023 14:22:14 +0530 Subject: [PATCH 6/8] Fix Karpenter test --- pkg/cfn/builder/karpenter_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/cfn/builder/karpenter_test.go b/pkg/cfn/builder/karpenter_test.go index 24edb1830d..11935ea3a1 100644 --- a/pkg/cfn/builder/karpenter_test.go +++ b/pkg/cfn/builder/karpenter_test.go @@ -357,6 +357,16 @@ var expectedTemplateWithSpotInterruptionQueue = `{ "EKS": "eks.amazonaws.com", "EKSFargatePods": "eks-fargate-pods.amazonaws.com" }, + "aws-iso": { + "EC2": "ec2.c2s.ic.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, + "aws-iso-b": { + "EC2": "ec2.sc2s.sgov.gov", + "EKS": "eks.amazonaws.com", + "EKSFargatePods": "eks-fargate-pods.amazonaws.com" + }, "aws-us-gov": { "EC2": "ec2.amazonaws.com", "EKS": "eks.amazonaws.com", From 32f2276dcfd84ccc4e8a5c1ca0edafe71e3341c6 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Fri, 23 Jun 2023 12:10:22 +0530 Subject: [PATCH 7/8] Fix S3 endpoint for aws-iso-b --- pkg/apis/eksctl.io/v1alpha5/partitions.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/apis/eksctl.io/v1alpha5/partitions.go b/pkg/apis/eksctl.io/v1alpha5/partitions.go index b73885c79c..09433d73db 100644 --- a/pkg/apis/eksctl.io/v1alpha5/partitions.go +++ b/pkg/apis/eksctl.io/v1alpha5/partitions.go @@ -99,7 +99,7 @@ func (p partitions) GetEndpointServiceDomainPrefix(endpointService EndpointServi return pt.endpointServiceDomainPrefix } return standardPartitionServiceDomainPrefix - case PartitionISO: + case PartitionISO, PartitionISOB: if endpointService.RequiresISOPrefix { return pt.endpointServiceDomainPrefix } From ef8f5aee028d2382d46b1313da17b3d645450447 Mon Sep 17 00:00:00 2001 From: cpu1 Date: Wed, 5 Jul 2023 13:02:27 +0530 Subject: [PATCH 8/8] Update documentation --- userdocs/src/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/userdocs/src/index.md b/userdocs/src/index.md index dcda7d7284..6f04a4a101 100644 --- a/userdocs/src/index.md +++ b/userdocs/src/index.md @@ -4,6 +4,8 @@ sponsored by [![Weaveworks](img/empty.svg#wwinline)](https://www.weave.works/) a !!! tip "New for 2023" `eksctl` now supports creating fully private clusters on [AWS Outposts](/usage/outposts). + + `eksctl` now supports new ISO regions `us-iso-east-1` and `us-isob-east-1`. `eksctl` now supports new regions - Zurich (`eu-central-2`), Spain (`eu-south-2`), Hyderabad (`ap-south-2`) and Melbourne (`ap-southeast-4`).