diff --git a/pkg/actions/nodegroup/create.go b/pkg/actions/nodegroup/create.go index 57205cc409..5924d066bd 100644 --- a/pkg/actions/nodegroup/create.go +++ b/pkg/actions/nodegroup/create.go @@ -15,6 +15,7 @@ import ( "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/printers" "github.com/weaveworks/eksctl/pkg/utils" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" "github.com/weaveworks/eksctl/pkg/utils/tasks" "github.com/weaveworks/eksctl/pkg/vpc" @@ -72,6 +73,10 @@ func (m *Manager) Create(options CreateOpts, nodegroupFilter filter.NodegroupFil return errors.New("Managed Nodegroups are not supported for this cluster version. Please update the cluster before adding managed nodegroups") } + if utilsstrings.Value(cfg.VPC.IPFamily) == string(api.IPV6Family) && len(cfg.NodeGroups) > 0 { + return errors.New("unmanaged nodegroups are not supported with IPv6 clusters") + } + if err := eks.ValidateBottlerocketSupport(ctl.ControlPlaneVersion(), cmdutils.ToKubeNodeGroups(cfg)); err != nil { return err } diff --git a/pkg/actions/nodegroup/create_test.go b/pkg/actions/nodegroup/create_test.go index b85de28d7a..56208502f7 100644 --- a/pkg/actions/nodegroup/create_test.go +++ b/pkg/actions/nodegroup/create_test.go @@ -4,10 +4,12 @@ import ( "fmt" "strings" + . "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" "github.com/pkg/errors" + "github.com/weaveworks/eksctl/pkg/actions/nodegroup" api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/manager" @@ -17,6 +19,7 @@ import ( "github.com/weaveworks/eksctl/pkg/kubernetes" "github.com/weaveworks/eksctl/pkg/testutils" "github.com/weaveworks/eksctl/pkg/testutils/mockprovider" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" ) type ngEntry struct { @@ -299,6 +302,53 @@ var _ = DescribeTable("Create", func(t ngEntry) { }), ) +var _ = Describe("create", func() { + When("creating an unmanaged nodegroup for an ipv6 cluster", func() { + It("returns an error", func() { + cfg := newClusterConfig() + cfg.Metadata.Version = api.Version1_21 + cfg.IAM = &api.ClusterIAM{ + WithOIDC: api.Enabled(), + } + cfg.Addons = []*api.Addon{ + { + Name: api.VPCCNIAddon, + }, + { + Name: api.KubeProxyAddon, + }, + { + Name: api.CoreDNSAddon, + }, + } + cfg.VPC.IPFamily = utilsstrings.Pointer(string(api.IPV6Family)) + + p := mockprovider.NewMockProvider() + ctl := &eks.ClusterProvider{ + Provider: p, + Status: &eks.ProviderStatus{ + ClusterInfo: &eks.ClusterInfo{ + Cluster: testutils.NewFakeCluster("my-cluster", ""), + }, + }, + } + m := nodegroup.New(cfg, ctl, nil) + + k := &fakes.FakeKubeProvider{} + k.SupportsManagedNodesReturns(true, nil) + m.MockKubeProvider(k) + + init := &fakes.FakeNodeGroupInitialiser{} + m.MockNodeGroupService(init) + + ngFilter := utilFakes.FakeNodegroupFilter{} + + err := m.Create(nodegroup.CreateOpts{}, &ngFilter) + Expect(err).To(MatchError(ContainSubstring("unmanaged nodegroups are not supported with IPv6 clusters"))) + }) + }) +}) + func newClusterConfig() *api.ClusterConfig { return &api.ClusterConfig{ TypeMeta: api.ClusterConfigTypeMeta(), diff --git a/pkg/apis/eksctl.io/v1alpha5/types.go b/pkg/apis/eksctl.io/v1alpha5/types.go index 30ac35f697..5292579cba 100644 --- a/pkg/apis/eksctl.io/v1alpha5/types.go +++ b/pkg/apis/eksctl.io/v1alpha5/types.go @@ -26,6 +26,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" "github.com/weaveworks/eksctl/pkg/utils/taints" ) @@ -743,12 +744,11 @@ func NewClusterConfig() *ClusterConfig { // NewClusterVPC creates new VPC config for a cluster func NewClusterVPC() *ClusterVPC { cidr := DefaultCIDR() - defaultIPFamily := string(DefaultIPFamily) return &ClusterVPC{ Network: Network{ CIDR: &cidr, - IPFamily: &defaultIPFamily, + IPFamily: utilsstrings.Pointer(string(DefaultIPFamily)), }, ManageSharedNodeSecurityGroupRules: Enabled(), NAT: DefaultClusterNAT(), diff --git a/pkg/cfn/builder/nodegroup.go b/pkg/cfn/builder/nodegroup.go index 238e163f5d..ce14d7d651 100644 --- a/pkg/cfn/builder/nodegroup.go +++ b/pkg/cfn/builder/nodegroup.go @@ -17,6 +17,7 @@ import ( api "github.com/weaveworks/eksctl/pkg/apis/eksctl.io/v1alpha5" "github.com/weaveworks/eksctl/pkg/cfn/outputs" "github.com/weaveworks/eksctl/pkg/nodebootstrap" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" "github.com/weaveworks/eksctl/pkg/vpc" ) @@ -51,6 +52,11 @@ func NewNodeGroupResourceSet(ec2API ec2iface.EC2API, iamAPI iamiface.IAMAPI, spe // AddAllResources adds all the information about the nodegroup to the resource set func (n *NodeGroupResourceSet) AddAllResources() error { + + if utilsstrings.Value(n.clusterSpec.VPC.IPFamily) == string(api.IPV6Family) { + return errors.New("unmanaged nodegroups are not supported with IPv6 clusters") + } + n.rs.template.Description = fmt.Sprintf( "%s (AMI family: %s, SSH access: %v, private networking: %v) %s", nodeGroupTemplateDescription, diff --git a/pkg/cfn/builder/nodegroup_test.go b/pkg/cfn/builder/nodegroup_test.go index 480369406f..81fedce1d3 100644 --- a/pkg/cfn/builder/nodegroup_test.go +++ b/pkg/cfn/builder/nodegroup_test.go @@ -16,6 +16,7 @@ import ( "github.com/weaveworks/eksctl/pkg/cfn/outputs" "github.com/weaveworks/eksctl/pkg/eks/mocks" bootstrapfakes "github.com/weaveworks/eksctl/pkg/nodebootstrap/fakes" + utilsstrings "github.com/weaveworks/eksctl/pkg/utils/strings" vpcfakes "github.com/weaveworks/eksctl/pkg/vpc/fakes" ) @@ -74,6 +75,21 @@ var _ = Describe("Unmanaged NodeGroup Template Builder", func() { Expect(ngTemplate.Outputs).To(HaveKey(outputs.NodeGroupFeatureLocalSecurityGroup)) }) + Context("ipv6 cluster", func() { + BeforeEach(func() { + cfg.VPC.IPFamily = utilsstrings.Pointer(string(api.IPV6Family)) + }) + AfterEach(func() { + cfg.VPC.IPFamily = utilsstrings.Pointer(string(api.IPV4Family)) + }) + + When("an unmanaged nodegroup is created", func() { + It("returns an error", func() { + Expect(addErr).To(MatchError(ContainSubstring("unmanaged nodegroups are not supported with IPv6 clusters"))) + }) + }) + }) + Context("if ng.MinSize is nil", func() { BeforeEach(func() { ng.MinSize = nil diff --git a/pkg/utils/strings/strings.go b/pkg/utils/strings/strings.go index ab45d8e9cd..1354bf82cb 100644 --- a/pkg/utils/strings/strings.go +++ b/pkg/utils/strings/strings.go @@ -7,6 +7,14 @@ func Pointer(s string) *string { return &s } +// Value returns the value of a pointer, empty string if it's nil. +func Value(s *string) string { + if s == nil { + return "" + } + return *s +} + // HasPrefix tests whether the string s begins with prefix. func HasPrefix(s, prefix string) bool { return strings.HasPrefix(s, prefix) diff --git a/userdocs/src/usage/vpc-networking.md b/userdocs/src/usage/vpc-networking.md index 35794077e4..5574288adf 100644 --- a/userdocs/src/usage/vpc-networking.md +++ b/userdocs/src/usage/vpc-networking.md @@ -56,6 +56,7 @@ This is an in config file setting only. When IPv6 is set, the following restrict - OIDC is enabled - managed addons are defined as shows above - version must be => 1.21 +- unmanaged nodegroups are not yet supported with IPv6 clusters - `vpc.NAT` and `serviceIPv4CIDR` fields are created by eksctl for ipv6 clusters and thus, are not supported configuration options - AutoAllocateIPv6 is not supported together with IPv6