github.com/kubernetes-incubator/kube-aws@v0.16.4/pkg/api/api_endpoint_lb.go (about)

     1  package api
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  )
     7  
     8  // DefaultRecordSetTTL is the default value for the loadBalancer.recordSetTTL key
     9  const DefaultRecordSetTTL = 300
    10  
    11  // APIEndpointLB is a set of an ELB and relevant settings and resources to serve a Kubernetes API hosted by controller nodes
    12  type APIEndpointLB struct {
    13  	// APIAccessAllowedSourceCIDRs is network ranges of sources you'd like Kubernetes API accesses to be allowed from, in CIDR notation
    14  	APIAccessAllowedSourceCIDRs CIDRRanges `yaml:"apiAccessAllowedSourceCIDRs,omitempty"`
    15  	// Identifier specifies an existing load-balancer used for load-balancing controller nodes and serving this endpoint
    16  	Identifier Identifier `yaml:",inline"`
    17  	// Managed is set to true when want to create an ELB for this API endpoint. It is false by default i.e. considered to be false if nil
    18  	Managed *bool `yaml:"managed,omitempty"`
    19  	// Subnets contains all the subnets assigned to this load-balancer. Specified only when this load balancer is not reused but managed one
    20  	SubnetReferences []SubnetReference `yaml:"subnets,omitempty"`
    21  	// PrivateSpecified determines the resulting load balancer uses an internal elb for an endpoint
    22  	PrivateSpecified *bool `yaml:"private,omitempty"`
    23  	// RecordSetManaged represents if the user wants kube-aws not to create a record set for this API load balancer
    24  	// i.e. the user wants to configure Route53 or one's own DNS oneself
    25  	RecordSetManaged *bool `yaml:"recordSetManaged,omitempty"`
    26  	// RecordSetTTLSpecified is the TTL for the record set to this load balancer. Defaults to 300 if nil
    27  	RecordSetTTLSpecified *int `yaml:"recordSetTTL,omitempty"`
    28  	// HostedZone is where the resulting Alias record is created for an endpoint
    29  	HostedZone HostedZone `yaml:"hostedZone,omitempty"`
    30  	//// SecurityGroups contains extra security groups must be associated to the lb serving API requests from clients
    31  	//SecurityGroups []SecurityGroup
    32  	// SecurityGroupIds represents SGs associated to this LB. Required when APIAccessAllowedSourceCIDRs is explicitly set to empty
    33  	SecurityGroupIds []string `yaml:"securityGroupIds"`
    34  	// Load balancer type. It is 'classic' by default, but can be changed to 'network'
    35  	Type *string `yaml:"type,omitempty"`
    36  }
    37  
    38  // UnmarshalYAML unmarshals YAML data to an APIEndpointLB object with defaults
    39  // This doesn't work due to a go-yaml issue described in http://ghodss.com/2014/the-right-way-to-handle-yaml-in-golang/
    40  // And that's why we need to implement `func (e APIEndpointLB) RecordSetTTL() int` for defaulting.
    41  // TODO Migrate to ghodss/yaml
    42  func (e *APIEndpointLB) UnmarshalYAML(unmarshal func(interface{}) error) error {
    43  	ttl := DefaultRecordSetTTL
    44  	type t APIEndpointLB
    45  	work := t(APIEndpointLB{
    46  		RecordSetTTLSpecified:       &ttl,
    47  		APIAccessAllowedSourceCIDRs: DefaultCIDRRanges(),
    48  	})
    49  	if err := unmarshal(&work); err != nil {
    50  		return fmt.Errorf("failed to parse API endpoint LB config: %v", err)
    51  	}
    52  	*e = APIEndpointLB(work)
    53  	return nil
    54  }
    55  
    56  // ManageELB returns true if an ELB should be managed by kube-aws
    57  func (e APIEndpointLB) ManageELB() bool {
    58  	return e.managedELBImplied() || (e.Managed != nil && *e.Managed)
    59  }
    60  
    61  // ClassicLoadBalancer returns true if the load balancer is a classic ELB
    62  func (e APIEndpointLB) ClassicLoadBalancer() bool {
    63  	return e.Type == nil || *e.Type == "classic"
    64  }
    65  
    66  // LoadBalancerV2 returns true if the load balancer is a ELBV2 load balancer (only network load balancer is supported for now)
    67  func (e APIEndpointLB) LoadBalancerV2() bool {
    68  	return e.Type != nil && *e.Type != "classic"
    69  }
    70  
    71  // NetworkLoadBalancer returns true if the load balancer is a ELBV2 network load balancer
    72  func (e APIEndpointLB) NetworkLoadBalancer() bool {
    73  	return e.Type != nil && *e.Type == "network"
    74  }
    75  
    76  // ManageELBRecordSet returns true if kube-aws should create a record set for the ELB
    77  func (e APIEndpointLB) ManageELBRecordSet() bool {
    78  	return e.HostedZone.HasIdentifier()
    79  }
    80  
    81  // ManageSecurityGroup returns true if kube-aws should create a security group for this ELB
    82  func (e APIEndpointLB) ManageSecurityGroup() bool {
    83  	return !e.NetworkLoadBalancer() && len(e.APIAccessAllowedSourceCIDRs) > 0
    84  }
    85  
    86  // Validate returns an error when there's any user error in the settings of the `loadBalancer` field
    87  func (e APIEndpointLB) Validate() error {
    88  	if e.Identifier.HasIdentifier() {
    89  		if e.PrivateSpecified != nil || !e.ClassicLoadBalancer() || len(e.SubnetReferences) > 0 || e.HostedZone.HasIdentifier() {
    90  			return errors.New("type, private, subnets, hostedZone must be omitted when id is specified to reuse an existing ELB")
    91  		}
    92  
    93  		return nil
    94  	}
    95  
    96  	if e.Managed != nil && !*e.Managed {
    97  		if e.RecordSetTTL() != DefaultRecordSetTTL {
    98  			return errors.New("recordSetTTL should not be modified when an API endpoint LB is not managed by kube-aws")
    99  		}
   100  
   101  		if e.HostedZone.HasIdentifier() {
   102  			return errors.New("hostedZone.id should not be specified when an API endpoint LB is not managed by kube-aws")
   103  		}
   104  
   105  		if e.Type != nil && len(*e.Type) > 0 {
   106  			return errors.New("type should not be specified when an API endpoint LB is not managed by kube-aws")
   107  		}
   108  
   109  		return nil
   110  	}
   111  
   112  	if e.HostedZone.HasIdentifier() {
   113  		if e.RecordSetManaged != nil && !*e.RecordSetManaged {
   114  			return errors.New("hostedZone.id must be omitted when you want kube-aws not to touch Route53")
   115  		}
   116  
   117  		if e.RecordSetTTL() < 1 {
   118  			return errors.New("recordSetTTL must be at least 1 second")
   119  		}
   120  	} else {
   121  		if e.RecordSetManaged == nil || *e.RecordSetManaged {
   122  			return errors.New("missing hostedZone.id: hostedZone.id is required when `recordSetManaged` is set to true. If you do want to configure DNS yourself, set it to true")
   123  		}
   124  
   125  		if e.RecordSetTTL() != DefaultRecordSetTTL {
   126  			return errors.New(
   127  				"recordSetTTL should not be modified when hostedZone id is nil",
   128  			)
   129  		}
   130  	}
   131  
   132  	if e.ClassicLoadBalancer() && e.ManageELB() && len(e.APIAccessAllowedSourceCIDRs) == 0 && len(e.SecurityGroupIds) == 0 {
   133  		return errors.New("either apiAccessAllowedSourceCIDRs or securityGroupIds must be present. Try not to explicitly empty apiAccessAllowedSourceCIDRs or set one or more securityGroupIDs")
   134  	}
   135  
   136  	if !e.NetworkLoadBalancer() && !e.ClassicLoadBalancer() {
   137  		return errors.New("load balancer type must be either 'classic' or 'network'")
   138  	}
   139  
   140  	if e.NetworkLoadBalancer() {
   141  		if len(e.SecurityGroupIds) > 0 {
   142  			return errors.New("cannot specify security group IDs for a network load balancer")
   143  		}
   144  	}
   145  
   146  	return nil
   147  }
   148  
   149  func (e APIEndpointLB) managedELBImplied() bool {
   150  	return len(e.SubnetReferences) > 0 ||
   151  		e.explicitlyPrivate() ||
   152  		e.explicitlyPublic() ||
   153  		e.HostedZone.HasIdentifier() ||
   154  		len(e.SecurityGroupIds) > 0 ||
   155  		e.RecordSetManaged != nil
   156  }
   157  
   158  func (e APIEndpointLB) explicitlyPrivate() bool {
   159  	return e.PrivateSpecified != nil && *e.PrivateSpecified
   160  }
   161  
   162  func (e APIEndpointLB) explicitlyPublic() bool {
   163  	return e.PrivateSpecified != nil && !*e.PrivateSpecified
   164  }
   165  
   166  // RecordSetTTL is the TTL for the record set to this load balancer. Defaults to 300 if `recordSetTTL` is omitted/set to nil
   167  func (e APIEndpointLB) RecordSetTTL() int {
   168  	if e.RecordSetTTLSpecified != nil {
   169  		return *e.RecordSetTTLSpecified
   170  	}
   171  	return DefaultRecordSetTTL
   172  }
   173  
   174  // Private returns true when this LB is a private one i.e. the `private` field is explicitly set to true
   175  func (e APIEndpointLB) Private() bool {
   176  	return e.explicitlyPrivate()
   177  }