Skip to content

Commit

Permalink
Merge pull request #286 from weaveworks/vpc-cidr
Browse files Browse the repository at this point in the history
 Add `--vpc-cidr` flag

- close #158
- close #279
  • Loading branch information
errordeveloper committed Oct 26, 2018
2 parents c9f2545 + 9a9ccfc commit 43771c6
Show file tree
Hide file tree
Showing 22 changed files with 314 additions and 130 deletions.
7 changes: 4 additions & 3 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ required = [

[[constraint]]
name = "k8s.io/kops"
branch = "master"
source = "https://github.com/errordeveloper/kops"
revision = "17a2c474956b3aa8513124efe6f5f431212e5216"

# copied from https://github.com/kubernetes/kops/blob/master/Gopkg.toml
[[override]]
Expand Down
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,13 @@ build: ## Build eksctl
test: generate ## Run unit tests
@git diff --exit-code pkg/nodebootstrap/assets.go > /dev/null || (git --no-pager diff; exit 1)
@git diff --exit-code ./pkg/eks/mocks > /dev/null || (git --no-pager diff; exit 1)
@CGO_ENABLED=0 go test -v -covermode=count -coverprofile=coverage.out ./pkg/... ./cmd/...
@$(MAKE) unit-test
@test -z $(COVERALLS_TOKEN) || $(GOPATH)/bin/goveralls -coverprofile=coverage.out -service=circle-ci

.PHONY: unit-test
unit-test:
@CGO_ENABLED=0 go test -v -covermode=count -coverprofile=coverage.out ./pkg/... ./cmd/...

LINTER ?= gometalinter ./...
.PHONY: lint
lint: ## Run linter over the codebase
Expand Down
72 changes: 58 additions & 14 deletions pkg/cfn/builder/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
. "github.com/onsi/gomega"
. "github.com/weaveworks/eksctl/pkg/cfn/builder"
"github.com/weaveworks/eksctl/pkg/cloudconfig"
"github.com/weaveworks/eksctl/pkg/eks"
"github.com/weaveworks/eksctl/pkg/eks/api"
"github.com/weaveworks/eksctl/pkg/nodebootstrap"
)
Expand Down Expand Up @@ -100,6 +101,8 @@ var _ = Describe("CloudFormation template builder API", func() {
cfg.AvailabilityZones = testAZs
ng.InstanceType = "t2.medium"

*cfg.VPC.CIDR = api.DefaultCIDR()

return cfg
}

Expand All @@ -115,7 +118,7 @@ var _ = Describe("CloudFormation template builder API", func() {
ARN: arn,
AvailabilityZones: testAZs,

VPC: api.ClusterVPC{
VPC: &api.ClusterVPC{
Network: api.Network{
ID: "vpc-0e265ad953062b94b",
CIDR: &net.IPNet{
Expand All @@ -129,22 +132,45 @@ var _ = Describe("CloudFormation template builder API", func() {
"us-west-2b": {
ID: "subnet-0f98135715dfcf55f",
CIDR: &net.IPNet{
IP: []byte{192, 168, 64, 0},
Mask: []byte{255, 255, 192, 0},
IP: []byte{192, 168, 0, 0},
Mask: []byte{255, 255, 224, 0},
},
},
"us-west-2a": {
ID: "subnet-0ade11bad78dced9e",
CIDR: &net.IPNet{
IP: []byte{192, 168, 128, 0},
Mask: []byte{255, 255, 192, 0},
IP: []byte{192, 168, 32, 0},
Mask: []byte{255, 255, 224, 0},
},
},
"us-west-2c": {
ID: "subnet-0e2e63ff1712bf6ef",
CIDR: &net.IPNet{
IP: []byte{192, 168, 192, 0},
Mask: []byte{255, 255, 192, 0},
IP: []byte{192, 168, 64, 0},
Mask: []byte{255, 255, 224, 0},
},
},
},
"Private": map[string]api.Network{
"us-west-2b": {
ID: "subnet-0f98135715dfcf55a",
CIDR: &net.IPNet{
IP: []byte{192, 168, 96, 0},
Mask: []byte{255, 255, 224, 0},
},
},
"us-west-2a": {
ID: "subnet-0ade11bad78dced9f",
CIDR: &net.IPNet{
IP: []byte{192, 168, 128, 0},
Mask: []byte{255, 255, 224, 0},
},
},
"us-west-2c": {
ID: "subnet-0e2e63ff1712bf6ea",
CIDR: &net.IPNet{
IP: []byte{192, 168, 160, 0},
Mask: []byte{255, 255, 224, 0},
},
},
},
Expand All @@ -159,30 +185,48 @@ var _ = Describe("CloudFormation template builder API", func() {
},
}

initial := newClusterConfig()
cfg := newClusterConfig()
ctl := eks.New(cfg)

initial.SetSubnets()
It("should not error when calling SetSubnets", func() {
err := ctl.SetSubnets()
Expect(err).ShouldNot(HaveOccurred())
})

rs := NewClusterResourceSet(initial)
rs.AddAllResources()
It("should have public and private subnets", func() {
Expect(len(cfg.VPC.Subnets)).To(Equal(2))
for _, k := range []api.SubnetTopology{"Public", "Private"} {
Expect(cfg.VPC.Subnets).To(HaveKey(k))
Expect(len(cfg.VPC.Subnets[k])).To(Equal(3))
}
})

rs := NewClusterResourceSet(cfg)
It("should add all resources without error", func() {
err := rs.AddAllResources()
Expect(err).ShouldNot(HaveOccurred())
})

sampleStack := newStackWithOutputs(map[string]string{
sampleOutputs := map[string]string{
"SecurityGroup": "sg-0b44c48bcba5b7362",
"SubnetsPublic": "subnet-0f98135715dfcf55f,subnet-0ade11bad78dced9e,subnet-0e2e63ff1712bf6ef",
"SubnetsPrivate": "subnet-0f98135715dfcf55a,subnet-0ade11bad78dced9f,subnet-0e2e63ff1712bf6ea",
"VPC": "vpc-0e265ad953062b94b",
"Endpoint": endpoint,
"CertificateAuthorityData": caCert,
"ARN": arn,
"ClusterStackName": "",
})
}

sampleStack := newStackWithOutputs(sampleOutputs)

It("should not error", func() {
err := rs.GetAllOutputs(sampleStack)
Expect(err).ShouldNot(HaveOccurred())
})

It("should be equal", func() {
Expect(*initial).To(Equal(*expected))
Expect(*cfg).To(Equal(*expected))
})
})

Expand Down
17 changes: 14 additions & 3 deletions pkg/cfn/builder/cluster.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package builder

import (
"fmt"

cfn "github.com/aws/aws-sdk-go/service/cloudformation"
gfn "github.com/awslabs/goformation/cloudformation"

Expand Down Expand Up @@ -31,10 +33,19 @@ func (c *ClusterResourceSet) AddAllResources() error {

templateDescriptionFeatures := clusterTemplateDescriptionDefaultFeatures

if c.spec.VPC.ID != "" && c.spec.VPC.HasSufficientPublicSubnets() {
if c.spec.VPC.ID != "" && c.spec.HasSufficientPublicSubnets() {
c.importResourcesForVPC()
templateDescriptionFeatures = " (with shared VPC and dedicated IAM role) "
} else {
topologies := len(c.spec.VPC.Subnets)
switch {
case topologies < 1:
return fmt.Errorf("too few subnet topologies: %v", c.spec.VPC.Subnets)
case topologies == 1 && !c.spec.HasSufficientPublicSubnets():
return fmt.Errorf("too few public subnets: %v", c.spec.VPC.Subnets["Public"])
case topologies == 2 && !c.spec.HasSufficientPrivateSubnets():
return fmt.Errorf("too few private subnets: %v", c.spec.VPC.Subnets["Private"])
}
c.addResourcesForVPC()
}
c.addOutputsForVPC()
Expand Down Expand Up @@ -93,11 +104,11 @@ func (c *ClusterResourceSet) GetAllOutputs(stack cfn.Stack) error {

// TODO: shouldn't assume the order is the same, can probably do an API lookup
for i, subnet := range c.outputs.SubnetsPrivate {
c.spec.VPC.ImportSubnet(api.SubnetTopologyPrivate, c.spec.AvailabilityZones[i], subnet)
c.spec.ImportSubnet(api.SubnetTopologyPrivate, c.spec.AvailabilityZones[i], subnet)
}

for i, subnet := range c.outputs.SubnetsPublic {
c.spec.VPC.ImportSubnet(api.SubnetTopologyPublic, c.spec.AvailabilityZones[i], subnet)
c.spec.ImportSubnet(api.SubnetTopologyPublic, c.spec.AvailabilityZones[i], subnet)
}

c.spec.ClusterStackName = c.outputs.ClusterStackName
Expand Down
2 changes: 1 addition & 1 deletion pkg/cfn/builder/nodegroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func (n *NodeGroupResourceSet) addResourcesForNodeGroup() {
// and tags don't have `PropagateAtLaunch` field, so we have a custom method here until this gets resolved
var vpcZoneIdentifier interface{}
if len(n.spec.AvailabilityZones) > 0 {
vpcZoneIdentifier = n.clusterSpec.VPC.SubnetIDs(api.SubnetTopologyPublic)
vpcZoneIdentifier = n.clusterSpec.SubnetIDs(api.SubnetTopologyPublic)
} else {
vpcZoneIdentifier = map[string][]interface{}{
gfn.FnSplit: []interface{}{
Expand Down
9 changes: 5 additions & 4 deletions pkg/cfn/builder/vpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
)

func (c *ClusterResourceSet) addSubnets(refRT *gfn.Value, topology api.SubnetTopology) {
c.subnets = make(map[api.SubnetTopology][]*gfn.Value)
for az, subnet := range c.spec.VPC.Subnets[topology] {
alias := strings.ToUpper(strings.Join(strings.Split(az, "-"), ""))
refSubnet := c.newResource("Subnet"+string(topology)+alias, &gfn.AWSEC2Subnet{
Expand All @@ -32,6 +31,8 @@ func (c *ClusterResourceSet) addResourcesForVPC() {
EnableDnsHostnames: gfn.True(),
})

c.subnets = make(map[api.SubnetTopology][]*gfn.Value)

refIG := c.newResource("InternetGateway", &gfn.AWSEC2InternetGateway{})
c.newResource("VPCGatewayAttachment", &gfn.AWSEC2VPCGatewayAttachment{
InternetGatewayId: refIG,
Expand Down Expand Up @@ -59,16 +60,16 @@ func (c *ClusterResourceSet) addResourcesForVPC() {

func (c *ClusterResourceSet) importResourcesForVPC() {
c.vpc = gfn.NewString(c.spec.VPC.ID)
for _, topology := range c.spec.VPC.SubnetTopologies() {
for _, subnet := range c.spec.VPC.SubnetIDs(topology) {
for topology := range c.spec.VPC.Subnets {
for _, subnet := range c.spec.SubnetIDs(topology) {
c.subnets[topology] = append(c.subnets[topology], gfn.NewString(subnet))
}
}
}

func (c *ClusterResourceSet) addOutputsForVPC() {
c.rs.newOutput(cfnOutputClusterVPC, c.vpc, true)
for _, topology := range c.spec.VPC.SubnetTopologies() {
for topology := range c.spec.VPC.Subnets {
c.rs.newJoinedOutput(cfnOutputClusterSubnets+string(topology), c.subnets[topology], true)
}
}
Expand Down
8 changes: 6 additions & 2 deletions pkg/ctl/create/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ func createClusterCmd() *cobra.Command {

fs.StringVar(&kopsClusterNameForVPC, "vpc-from-kops-cluster", "", "re-use VPC from a given kops cluster")

fs.IPNetVar(cfg.VPC.CIDR, "vpc-cidr", api.DefaultCIDR(), "global CIDR to use for VPC")

return cmd
}

Expand Down Expand Up @@ -132,13 +134,15 @@ func doCreateCluster(cfg *api.ClusterConfig, ng *api.NodeGroup, name string) err
if err := kw.UseVPC(cfg); err != nil {
return err
}
logger.Success("using VPC (%s) and subnets (%v) from kops cluster %q", cfg.VPC.ID, cfg.VPC.SubnetIDs(api.SubnetTopologyPublic), kopsClusterNameForVPC)
logger.Success("using VPC (%s) and subnets (%v) from kops cluster %q", cfg.VPC.ID, cfg.SubnetIDs(api.SubnetTopologyPublic), kopsClusterNameForVPC)
} else {
// kw.UseVPC() sets AZs based on subenets used
if err := ctl.SetAvailabilityZones(availabilityZones); err != nil {
return err
}
cfg.SetSubnets()
if err := ctl.SetSubnets(); err != nil {
return err
}
}

if err := ctl.EnsureAMI(ng); err != nil {
Expand Down
Loading

0 comments on commit 43771c6

Please sign in to comment.