github.com/kubernetes-incubator/kube-aws@v0.16.4/pkg/api/nat_gateway.go (about) 1 package api 2 3 import ( 4 "fmt" 5 ) 6 7 type NATGatewayConfig struct { 8 Identifier `yaml:",inline"` 9 EIPAllocationID string `yaml:"eipAllocationId,omitempty"` 10 } 11 12 func (c NATGatewayConfig) Validate() error { 13 if c.HasIdentifier() && c.EIPAllocationID != "" { 14 return fmt.Errorf("eipAllocationId can't be specified for a existing nat gatway. It is an user's responsibility to configure the nat gateway if one tried to reuse an existing one: %+v", c) 15 } 16 if err := c.Identifier.Validate(); err != nil { 17 return fmt.Errorf("failed to validate id for nat gateway: %v", err) 18 } 19 return nil 20 } 21 22 // kube-aws manages at most one NAT gateway per subnet 23 type NATGateway interface { 24 EIPAllocationIDRef() (string, error) 25 EIPLogicalName() (string, error) 26 IsConnectedToPrivateSubnet(Subnet) bool 27 LogicalName() string 28 ManageEIP() bool 29 ManageNATGateway() bool 30 ManageRoute() bool 31 Ref() string 32 PublicSubnetRef() (string, error) 33 PrivateSubnets() []Subnet 34 Validate() error 35 } 36 37 type natGatewayImpl struct { 38 NATGatewayConfig 39 privateSubnets []Subnet 40 publicSubnet Subnet 41 } 42 43 func NewManagedNATGateway(c NATGatewayConfig, private Subnet, public Subnet) NATGateway { 44 return natGatewayImpl{ 45 NATGatewayConfig: c, 46 privateSubnets: []Subnet{private}, 47 publicSubnet: public, 48 } 49 } 50 51 func NewUnmanagedNATGateway(c NATGatewayConfig, private Subnet) NATGateway { 52 return natGatewayImpl{ 53 NATGatewayConfig: c, 54 privateSubnets: []Subnet{private}, 55 } 56 } 57 58 func (g natGatewayImpl) LogicalName() string { 59 name := "" 60 for _, s := range g.privateSubnets { 61 name = name + s.LogicalName() 62 } 63 return fmt.Sprintf("NatGateway%s", name) 64 } 65 66 func (g natGatewayImpl) ManageNATGateway() bool { 67 allTrue := true 68 allFalse := true 69 for _, s := range g.privateSubnets { 70 allTrue = allTrue && s.ManageNATGateway() 71 allFalse = allFalse && !s.ManageNATGateway() 72 } 73 if allTrue { 74 return true 75 } else if allFalse { 76 return false 77 } 78 79 panic(fmt.Sprintf("[bug] assertion failed: private subnets associated to this nat gateway(%+v) conflicts in their settings. kube-aws is confused and can't decide whether it should manage the nat gateway or not", g)) 80 } 81 82 func (g natGatewayImpl) ManageEIP() bool { 83 return g.ManageNATGateway() && g.EIPAllocationID == "" 84 } 85 86 func (g natGatewayImpl) ManageRoute() bool { 87 allTrue := true 88 allFalse := true 89 for _, s := range g.privateSubnets { 90 allTrue = allTrue && s.ManageRouteToNATGateway() 91 allFalse = allFalse && !s.ManageRouteToNATGateway() 92 } 93 if allTrue { 94 return true 95 } else if allFalse { 96 return false 97 } 98 99 panic(fmt.Sprintf("[bug] assertion failed: private subnets associated to this nat gateway(%+v) conflicts in their settings. kube-aws is confused and can't decide whether it should manage the route to nat gateway or not", g)) 100 } 101 102 func (g natGatewayImpl) EIPLogicalName() (string, error) { 103 if !g.ManageEIP() { 104 return "", fmt.Errorf("[bug] assertion failed: EIPLogicalName shouldn't be called for NATGateway when an EIP is not going to be managed by kube-aws : %+v", g) 105 } 106 return fmt.Sprintf("%sEIP", g.LogicalName()), nil 107 } 108 109 func (g natGatewayImpl) EIPAllocationIDRef() (string, error) { 110 if g.ManageEIP() { 111 name, err := g.EIPLogicalName() 112 if err != nil { 113 return "", fmt.Errorf("failed to call EIPAlloationIDRef: %v", err) 114 } 115 return fmt.Sprintf(`{"Fn::GetAtt": ["%s", "AllocationId"]}`, name), nil 116 } 117 return fmt.Sprintf(`"%s"`, g.EIPAllocationID), nil 118 } 119 120 func (g natGatewayImpl) IsConnectedToPrivateSubnet(s Subnet) bool { 121 for _, ps := range g.privateSubnets { 122 if ps.LogicalName() == s.LogicalName() { 123 return true 124 } 125 } 126 return false 127 } 128 129 func (g natGatewayImpl) Ref() string { 130 return g.Identifier.Ref(g.LogicalName) 131 } 132 133 func (g natGatewayImpl) PublicSubnetRef() (string, error) { 134 if !g.ManageNATGateway() { 135 return "", fmt.Errorf("[bug] assertion failed: PublicSubnetRef should't be called for an unmanaged NAT gateway: %+v", g) 136 } 137 return g.publicSubnet.Ref(), nil 138 } 139 140 func (g natGatewayImpl) PrivateSubnets() []Subnet { 141 return g.privateSubnets 142 } 143 144 func (g natGatewayImpl) Validate() error { 145 if err := g.NATGatewayConfig.Validate(); err != nil { 146 return fmt.Errorf("failed to validate nat gateway: %v", err) 147 } 148 if !g.ManageNATGateway() { 149 for i, s := range g.privateSubnets { 150 if !s.HasIdentifier() && !s.RouteTable.HasIdentifier() && !s.NATGateway.HasIdentifier() { 151 return fmt.Errorf("[bug] assertion failed: subnet #%d associated to preconfigured NGW be either a managed one with an unmanaged route table/ngw or an unmanaged one but it was not: subnet=%+v ngw=%+v", i, s, g) 152 } 153 } 154 155 if !g.HasIdentifier() { 156 return fmt.Errorf("Preconfigured NGW must have id or idFromStackOutput but it didn't: %+v", g) 157 } 158 159 if g.EIPAllocationID != "" { 160 return fmt.Errorf("Preconfigured NGW must not have an eipAllocactionID but it didn't: %+v", g) 161 } 162 } 163 return nil 164 }