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  }