mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Add LoadBalancer status to ServiceStatus
This will replace publicIPs
This commit is contained in:
parent
1ad4549f5f
commit
3884d5fc59
@ -141,3 +141,40 @@ func HashObject(obj runtime.Object, codec runtime.Codec) (string, error) {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf("%x", md5.Sum(data)), nil
|
return fmt.Sprintf("%x", md5.Sum(data)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: make method on LoadBalancerStatus?
|
||||||
|
func LoadBalancerStatusEqual(l, r *LoadBalancerStatus) bool {
|
||||||
|
return ingressSliceEqual(l.Ingress, r.Ingress)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ingressSliceEqual(lhs, rhs []LoadBalancerIngress) bool {
|
||||||
|
if len(lhs) != len(rhs) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for i := range lhs {
|
||||||
|
if !ingressEqual(&lhs[i], &rhs[i]) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ingressEqual(lhs, rhs *LoadBalancerIngress) bool {
|
||||||
|
if lhs.IP != rhs.IP {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if lhs.Hostname != rhs.Hostname {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make method on LoadBalancerStatus?
|
||||||
|
func LoadBalancerStatusDeepCopy(lb *LoadBalancerStatus) *LoadBalancerStatus {
|
||||||
|
c := &LoadBalancerStatus{}
|
||||||
|
c.Ingress = make([]LoadBalancerIngress, len(lb.Ingress))
|
||||||
|
for i := range lb.Ingress {
|
||||||
|
c.Ingress[i] = lb.Ingress[i]
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
@ -1012,7 +1012,30 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ServiceStatus represents the current status of a service
|
// ServiceStatus represents the current status of a service
|
||||||
type ServiceStatus struct{}
|
type ServiceStatus struct {
|
||||||
|
// LoadBalancer contains the current status of the load-balancer,
|
||||||
|
// if one is present.
|
||||||
|
LoadBalancer LoadBalancerStatus `json:"loadBalancer,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerStatus represents the status of a load-balancer
|
||||||
|
type LoadBalancerStatus struct {
|
||||||
|
// Ingress is a list containing ingress points for the load-balancer;
|
||||||
|
// traffic intended for the service should be sent to these ingress points.
|
||||||
|
Ingress []LoadBalancerIngress `json:"ingress,omitempty" description:"load-balancer ingress points"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerIngress represents the status of a load-balancer ingress point:
|
||||||
|
// traffic intended for the service should be sent to an ingress point.
|
||||||
|
type LoadBalancerIngress struct {
|
||||||
|
// IP is set for load-balancer ingress points that are IP based
|
||||||
|
// (typically GCE or OpenStack load-balancers)
|
||||||
|
IP string `json:"ip,omitempty" description:"IP address of ingress point"`
|
||||||
|
|
||||||
|
// Hostname is set for load-balancer ingress points that are DNS based
|
||||||
|
// (typically AWS load-balancers)
|
||||||
|
Hostname string `json:"hostname,omitempty" description:"hostname of ingress point"`
|
||||||
|
}
|
||||||
|
|
||||||
// ServiceSpec describes the attributes that a user creates on a service
|
// ServiceSpec describes the attributes that a user creates on a service
|
||||||
type ServiceSpec struct {
|
type ServiceSpec struct {
|
||||||
|
@ -812,6 +812,32 @@ func convert_api_ListOptions_To_v1_ListOptions(in *api.ListOptions, out *ListOpt
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convert_api_LoadBalancerIngress_To_v1_LoadBalancerIngress(in *api.LoadBalancerIngress, out *LoadBalancerIngress, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*api.LoadBalancerIngress))(in)
|
||||||
|
}
|
||||||
|
out.IP = in.IP
|
||||||
|
out.Hostname = in.Hostname
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convert_api_LoadBalancerStatus_To_v1_LoadBalancerStatus(in *api.LoadBalancerStatus, out *LoadBalancerStatus, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*api.LoadBalancerStatus))(in)
|
||||||
|
}
|
||||||
|
if in.Ingress != nil {
|
||||||
|
out.Ingress = make([]LoadBalancerIngress, len(in.Ingress))
|
||||||
|
for i := range in.Ingress {
|
||||||
|
if err := convert_api_LoadBalancerIngress_To_v1_LoadBalancerIngress(&in.Ingress[i], &out.Ingress[i], s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Ingress = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func convert_api_LocalObjectReference_To_v1_LocalObjectReference(in *api.LocalObjectReference, out *LocalObjectReference, s conversion.Scope) error {
|
func convert_api_LocalObjectReference_To_v1_LocalObjectReference(in *api.LocalObjectReference, out *LocalObjectReference, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*api.LocalObjectReference))(in)
|
defaulting.(func(*api.LocalObjectReference))(in)
|
||||||
@ -2088,6 +2114,9 @@ func convert_api_ServiceStatus_To_v1_ServiceStatus(in *api.ServiceStatus, out *S
|
|||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*api.ServiceStatus))(in)
|
defaulting.(func(*api.ServiceStatus))(in)
|
||||||
}
|
}
|
||||||
|
if err := convert_api_LoadBalancerStatus_To_v1_LoadBalancerStatus(&in.LoadBalancer, &out.LoadBalancer, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3038,6 +3067,32 @@ func convert_v1_ListOptions_To_api_ListOptions(in *ListOptions, out *api.ListOpt
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convert_v1_LoadBalancerIngress_To_api_LoadBalancerIngress(in *LoadBalancerIngress, out *api.LoadBalancerIngress, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*LoadBalancerIngress))(in)
|
||||||
|
}
|
||||||
|
out.IP = in.IP
|
||||||
|
out.Hostname = in.Hostname
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convert_v1_LoadBalancerStatus_To_api_LoadBalancerStatus(in *LoadBalancerStatus, out *api.LoadBalancerStatus, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*LoadBalancerStatus))(in)
|
||||||
|
}
|
||||||
|
if in.Ingress != nil {
|
||||||
|
out.Ingress = make([]api.LoadBalancerIngress, len(in.Ingress))
|
||||||
|
for i := range in.Ingress {
|
||||||
|
if err := convert_v1_LoadBalancerIngress_To_api_LoadBalancerIngress(&in.Ingress[i], &out.Ingress[i], s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Ingress = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func convert_v1_LocalObjectReference_To_api_LocalObjectReference(in *LocalObjectReference, out *api.LocalObjectReference, s conversion.Scope) error {
|
func convert_v1_LocalObjectReference_To_api_LocalObjectReference(in *LocalObjectReference, out *api.LocalObjectReference, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*LocalObjectReference))(in)
|
defaulting.(func(*LocalObjectReference))(in)
|
||||||
@ -4314,6 +4369,9 @@ func convert_v1_ServiceStatus_To_api_ServiceStatus(in *ServiceStatus, out *api.S
|
|||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*ServiceStatus))(in)
|
defaulting.(func(*ServiceStatus))(in)
|
||||||
}
|
}
|
||||||
|
if err := convert_v1_LoadBalancerStatus_To_api_LoadBalancerStatus(&in.LoadBalancer, &out.LoadBalancer, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4520,6 +4578,8 @@ func init() {
|
|||||||
convert_api_ListMeta_To_v1_ListMeta,
|
convert_api_ListMeta_To_v1_ListMeta,
|
||||||
convert_api_ListOptions_To_v1_ListOptions,
|
convert_api_ListOptions_To_v1_ListOptions,
|
||||||
convert_api_List_To_v1_List,
|
convert_api_List_To_v1_List,
|
||||||
|
convert_api_LoadBalancerIngress_To_v1_LoadBalancerIngress,
|
||||||
|
convert_api_LoadBalancerStatus_To_v1_LoadBalancerStatus,
|
||||||
convert_api_LocalObjectReference_To_v1_LocalObjectReference,
|
convert_api_LocalObjectReference_To_v1_LocalObjectReference,
|
||||||
convert_api_NFSVolumeSource_To_v1_NFSVolumeSource,
|
convert_api_NFSVolumeSource_To_v1_NFSVolumeSource,
|
||||||
convert_api_NamespaceList_To_v1_NamespaceList,
|
convert_api_NamespaceList_To_v1_NamespaceList,
|
||||||
@ -4629,6 +4689,8 @@ func init() {
|
|||||||
convert_v1_ListMeta_To_api_ListMeta,
|
convert_v1_ListMeta_To_api_ListMeta,
|
||||||
convert_v1_ListOptions_To_api_ListOptions,
|
convert_v1_ListOptions_To_api_ListOptions,
|
||||||
convert_v1_List_To_api_List,
|
convert_v1_List_To_api_List,
|
||||||
|
convert_v1_LoadBalancerIngress_To_api_LoadBalancerIngress,
|
||||||
|
convert_v1_LoadBalancerStatus_To_api_LoadBalancerStatus,
|
||||||
convert_v1_LocalObjectReference_To_api_LocalObjectReference,
|
convert_v1_LocalObjectReference_To_api_LocalObjectReference,
|
||||||
convert_v1_NFSVolumeSource_To_api_NFSVolumeSource,
|
convert_v1_NFSVolumeSource_To_api_NFSVolumeSource,
|
||||||
convert_v1_NamespaceList_To_api_NamespaceList,
|
convert_v1_NamespaceList_To_api_NamespaceList,
|
||||||
|
@ -994,7 +994,30 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ServiceStatus represents the current status of a service
|
// ServiceStatus represents the current status of a service
|
||||||
type ServiceStatus struct{}
|
type ServiceStatus struct {
|
||||||
|
// LoadBalancer contains the current status of the load-balancer,
|
||||||
|
// if one is present.
|
||||||
|
LoadBalancer LoadBalancerStatus `json:"loadBalancer,omitempty" description:"status of load-balancer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerStatus represents the status of a load-balancer
|
||||||
|
type LoadBalancerStatus struct {
|
||||||
|
// Ingress is a list containing ingress points for the load-balancer;
|
||||||
|
// traffic intended for the service should be sent to these ingress points.
|
||||||
|
Ingress []LoadBalancerIngress `json:"ingress,omitempty" description:"load-balancer ingress points"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerIngress represents the status of a load-balancer ingress point:
|
||||||
|
// traffic intended for the service should be sent to an ingress point.
|
||||||
|
type LoadBalancerIngress struct {
|
||||||
|
// IP is set for load-balancer ingress points that are IP based
|
||||||
|
// (typically GCE or OpenStack load-balancers)
|
||||||
|
IP string `json:"ip,omitempty" description:"IP address of ingress point"`
|
||||||
|
|
||||||
|
// Hostname is set for load-balancer ingress points that are DNS based
|
||||||
|
// (typically AWS load-balancers)
|
||||||
|
Hostname string `json:"hostname,omitempty" description:"hostname of ingress point"`
|
||||||
|
}
|
||||||
|
|
||||||
// ServiceSpec describes the attributes that a user creates on a service
|
// ServiceSpec describes the attributes that a user creates on a service
|
||||||
type ServiceSpec struct {
|
type ServiceSpec struct {
|
||||||
|
@ -787,6 +787,10 @@ func addConversionFuncs() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.Convert(&in.Status.LoadBalancer, &out.LoadBalancerStatus, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
func(in *Service, out *api.Service, s conversion.Scope) error {
|
func(in *Service, out *api.Service, s conversion.Scope) error {
|
||||||
@ -830,6 +834,22 @@ func addConversionFuncs() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.Convert(&in.LoadBalancerStatus, &out.Status.LoadBalancer, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
typeIn := in.Type
|
||||||
|
if typeIn == "" {
|
||||||
|
if in.CreateExternalLoadBalancer {
|
||||||
|
typeIn = ServiceTypeLoadBalancer
|
||||||
|
} else {
|
||||||
|
typeIn = ServiceTypeClusterIP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := s.Convert(&typeIn, &out.Spec.Type, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -896,6 +896,29 @@ type Service struct {
|
|||||||
// array. If this field is not specified, it will be populated from
|
// array. If this field is not specified, it will be populated from
|
||||||
// the legacy fields.
|
// the legacy fields.
|
||||||
Ports []ServicePort `json:"ports" description:"ports to be exposed on the service; if this field is specified, the legacy fields (Port, PortName, Protocol, and ContainerPort) will be overwritten by the first member of this array; if this field is not specified, it will be populated from the legacy fields"`
|
Ports []ServicePort `json:"ports" description:"ports to be exposed on the service; if this field is specified, the legacy fields (Port, PortName, Protocol, and ContainerPort) will be overwritten by the first member of this array; if this field is not specified, it will be populated from the legacy fields"`
|
||||||
|
|
||||||
|
// LoadBalancer contains the current status of the load-balancer,
|
||||||
|
// if one is present.
|
||||||
|
LoadBalancerStatus LoadBalancerStatus `json:"loadBalancerStatus,omitempty" description:"status of load-balancer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerStatus represents the status of a load-balancer
|
||||||
|
type LoadBalancerStatus struct {
|
||||||
|
// Ingress is a list containing ingress points for the load-balancer;
|
||||||
|
// traffic intended for the service should be sent to these ingress points.
|
||||||
|
Ingress []LoadBalancerIngress `json:"ingress,omitempty" description:"load-balancer ingress points"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerIngress represents the status of a load-balancer ingress point:
|
||||||
|
// traffic intended for the service should be sent to an ingress point.
|
||||||
|
type LoadBalancerIngress struct {
|
||||||
|
// IP is set for load-balancer ingress points that are IP based
|
||||||
|
// (typically GCE or OpenStack load-balancers)
|
||||||
|
IP string `json:"ip,omitempty" description:"IP address of ingress point"`
|
||||||
|
|
||||||
|
// Hostname is set for load-balancer ingress points that are DNS based
|
||||||
|
// (typically AWS load-balancers)
|
||||||
|
Hostname string `json:"hostname,omitempty" description:"hostname of ingress point"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServicePort struct {
|
type ServicePort struct {
|
||||||
|
@ -709,6 +709,10 @@ func addConversionFuncs() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.Convert(&in.Status.LoadBalancer, &out.LoadBalancerStatus, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
func(in *Service, out *api.Service, s conversion.Scope) error {
|
func(in *Service, out *api.Service, s conversion.Scope) error {
|
||||||
@ -752,6 +756,22 @@ func addConversionFuncs() {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := s.Convert(&in.LoadBalancerStatus, &out.Status.LoadBalancer, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
typeIn := in.Type
|
||||||
|
if typeIn == "" {
|
||||||
|
if in.CreateExternalLoadBalancer {
|
||||||
|
typeIn = ServiceTypeLoadBalancer
|
||||||
|
} else {
|
||||||
|
typeIn = ServiceTypeClusterIP
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := s.Convert(&typeIn, &out.Spec.Type, 0); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -900,6 +900,29 @@ type Service struct {
|
|||||||
// array. If this field is not specified, it will be populated from
|
// array. If this field is not specified, it will be populated from
|
||||||
// the legacy fields.
|
// the legacy fields.
|
||||||
Ports []ServicePort `json:"ports" description:"ports to be exposed on the service; if this field is specified, the legacy fields (Port, PortName, Protocol, and ContainerPort) will be overwritten by the first member of this array; if this field is not specified, it will be populated from the legacy fields"`
|
Ports []ServicePort `json:"ports" description:"ports to be exposed on the service; if this field is specified, the legacy fields (Port, PortName, Protocol, and ContainerPort) will be overwritten by the first member of this array; if this field is not specified, it will be populated from the legacy fields"`
|
||||||
|
|
||||||
|
// LoadBalancer contains the current status of the load-balancer,
|
||||||
|
// if one is present.
|
||||||
|
LoadBalancerStatus LoadBalancerStatus `json:"loadBalancerStatus,omitempty" description:"status of load-balancer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerStatus represents the status of a load-balancer
|
||||||
|
type LoadBalancerStatus struct {
|
||||||
|
// Ingress is a list containing ingress points for the load-balancer;
|
||||||
|
// traffic intended for the service should be sent to these ingress points.
|
||||||
|
Ingress []LoadBalancerIngress `json:"ingress,omitempty" description:"load-balancer ingress points"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerIngress represents the status of a load-balancer ingress point:
|
||||||
|
// traffic intended for the service should be sent to an ingress point.
|
||||||
|
type LoadBalancerIngress struct {
|
||||||
|
// IP is set for load-balancer ingress points that are IP based
|
||||||
|
// (typically GCE or OpenStack load-balancers)
|
||||||
|
IP string `json:"ip,omitempty" description:"IP address of ingress point"`
|
||||||
|
|
||||||
|
// Hostname is set for load-balancer ingress points that are DNS based
|
||||||
|
// (typically AWS load-balancers)
|
||||||
|
Hostname string `json:"hostname,omitempty" description:"hostname of ingress point"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServicePort struct {
|
type ServicePort struct {
|
||||||
|
@ -719,6 +719,32 @@ func convert_api_ListOptions_To_v1beta3_ListOptions(in *api.ListOptions, out *Li
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convert_api_LoadBalancerIngress_To_v1beta3_LoadBalancerIngress(in *api.LoadBalancerIngress, out *LoadBalancerIngress, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*api.LoadBalancerIngress))(in)
|
||||||
|
}
|
||||||
|
out.IP = in.IP
|
||||||
|
out.Hostname = in.Hostname
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convert_api_LoadBalancerStatus_To_v1beta3_LoadBalancerStatus(in *api.LoadBalancerStatus, out *LoadBalancerStatus, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*api.LoadBalancerStatus))(in)
|
||||||
|
}
|
||||||
|
if in.Ingress != nil {
|
||||||
|
out.Ingress = make([]LoadBalancerIngress, len(in.Ingress))
|
||||||
|
for i := range in.Ingress {
|
||||||
|
if err := convert_api_LoadBalancerIngress_To_v1beta3_LoadBalancerIngress(&in.Ingress[i], &out.Ingress[i], s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Ingress = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func convert_api_LocalObjectReference_To_v1beta3_LocalObjectReference(in *api.LocalObjectReference, out *LocalObjectReference, s conversion.Scope) error {
|
func convert_api_LocalObjectReference_To_v1beta3_LocalObjectReference(in *api.LocalObjectReference, out *LocalObjectReference, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*api.LocalObjectReference))(in)
|
defaulting.(func(*api.LocalObjectReference))(in)
|
||||||
@ -2027,6 +2053,9 @@ func convert_api_ServiceStatus_To_v1beta3_ServiceStatus(in *api.ServiceStatus, o
|
|||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*api.ServiceStatus))(in)
|
defaulting.(func(*api.ServiceStatus))(in)
|
||||||
}
|
}
|
||||||
|
if err := convert_api_LoadBalancerStatus_To_v1beta3_LoadBalancerStatus(&in.LoadBalancer, &out.LoadBalancer, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2914,6 +2943,32 @@ func convert_v1beta3_ListOptions_To_api_ListOptions(in *ListOptions, out *api.Li
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func convert_v1beta3_LoadBalancerIngress_To_api_LoadBalancerIngress(in *LoadBalancerIngress, out *api.LoadBalancerIngress, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*LoadBalancerIngress))(in)
|
||||||
|
}
|
||||||
|
out.IP = in.IP
|
||||||
|
out.Hostname = in.Hostname
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func convert_v1beta3_LoadBalancerStatus_To_api_LoadBalancerStatus(in *LoadBalancerStatus, out *api.LoadBalancerStatus, s conversion.Scope) error {
|
||||||
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
|
defaulting.(func(*LoadBalancerStatus))(in)
|
||||||
|
}
|
||||||
|
if in.Ingress != nil {
|
||||||
|
out.Ingress = make([]api.LoadBalancerIngress, len(in.Ingress))
|
||||||
|
for i := range in.Ingress {
|
||||||
|
if err := convert_v1beta3_LoadBalancerIngress_To_api_LoadBalancerIngress(&in.Ingress[i], &out.Ingress[i], s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.Ingress = nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func convert_v1beta3_LocalObjectReference_To_api_LocalObjectReference(in *LocalObjectReference, out *api.LocalObjectReference, s conversion.Scope) error {
|
func convert_v1beta3_LocalObjectReference_To_api_LocalObjectReference(in *LocalObjectReference, out *api.LocalObjectReference, s conversion.Scope) error {
|
||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*LocalObjectReference))(in)
|
defaulting.(func(*LocalObjectReference))(in)
|
||||||
@ -4222,6 +4277,9 @@ func convert_v1beta3_ServiceStatus_To_api_ServiceStatus(in *ServiceStatus, out *
|
|||||||
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
if defaulting, found := s.DefaultingInterface(reflect.TypeOf(*in)); found {
|
||||||
defaulting.(func(*ServiceStatus))(in)
|
defaulting.(func(*ServiceStatus))(in)
|
||||||
}
|
}
|
||||||
|
if err := convert_v1beta3_LoadBalancerStatus_To_api_LoadBalancerStatus(&in.LoadBalancer, &out.LoadBalancer, s); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4457,6 +4515,8 @@ func init() {
|
|||||||
convert_api_ListMeta_To_v1beta3_ListMeta,
|
convert_api_ListMeta_To_v1beta3_ListMeta,
|
||||||
convert_api_ListOptions_To_v1beta3_ListOptions,
|
convert_api_ListOptions_To_v1beta3_ListOptions,
|
||||||
convert_api_List_To_v1beta3_List,
|
convert_api_List_To_v1beta3_List,
|
||||||
|
convert_api_LoadBalancerIngress_To_v1beta3_LoadBalancerIngress,
|
||||||
|
convert_api_LoadBalancerStatus_To_v1beta3_LoadBalancerStatus,
|
||||||
convert_api_LocalObjectReference_To_v1beta3_LocalObjectReference,
|
convert_api_LocalObjectReference_To_v1beta3_LocalObjectReference,
|
||||||
convert_api_NFSVolumeSource_To_v1beta3_NFSVolumeSource,
|
convert_api_NFSVolumeSource_To_v1beta3_NFSVolumeSource,
|
||||||
convert_api_NamespaceList_To_v1beta3_NamespaceList,
|
convert_api_NamespaceList_To_v1beta3_NamespaceList,
|
||||||
@ -4568,6 +4628,8 @@ func init() {
|
|||||||
convert_v1beta3_ListMeta_To_api_ListMeta,
|
convert_v1beta3_ListMeta_To_api_ListMeta,
|
||||||
convert_v1beta3_ListOptions_To_api_ListOptions,
|
convert_v1beta3_ListOptions_To_api_ListOptions,
|
||||||
convert_v1beta3_List_To_api_List,
|
convert_v1beta3_List_To_api_List,
|
||||||
|
convert_v1beta3_LoadBalancerIngress_To_api_LoadBalancerIngress,
|
||||||
|
convert_v1beta3_LoadBalancerStatus_To_api_LoadBalancerStatus,
|
||||||
convert_v1beta3_LocalObjectReference_To_api_LocalObjectReference,
|
convert_v1beta3_LocalObjectReference_To_api_LocalObjectReference,
|
||||||
convert_v1beta3_NFSVolumeSource_To_api_NFSVolumeSource,
|
convert_v1beta3_NFSVolumeSource_To_api_NFSVolumeSource,
|
||||||
convert_v1beta3_NamespaceList_To_api_NamespaceList,
|
convert_v1beta3_NamespaceList_To_api_NamespaceList,
|
||||||
|
@ -998,7 +998,30 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// ServiceStatus represents the current status of a service
|
// ServiceStatus represents the current status of a service
|
||||||
type ServiceStatus struct{}
|
type ServiceStatus struct {
|
||||||
|
// LoadBalancer contains the current status of the load-balancer,
|
||||||
|
// if one is present.
|
||||||
|
LoadBalancer LoadBalancerStatus `json:"loadBalancer,omitempty" description:"status of load-balancer"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerStatus represents the status of a load-balancer
|
||||||
|
type LoadBalancerStatus struct {
|
||||||
|
// Ingress is a list containing ingress points for the load-balancer;
|
||||||
|
// traffic intended for the service should be sent to these ingress points.
|
||||||
|
Ingress []LoadBalancerIngress `json:"ingress,omitempty" description:"load-balancer ingress points"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadBalancerIngress represents the status of a load-balancer ingress point:
|
||||||
|
// traffic intended for the service should be sent to an ingress point.
|
||||||
|
type LoadBalancerIngress struct {
|
||||||
|
// IP is set for load-balancer ingress points that are IP based
|
||||||
|
// (typically GCE or OpenStack load-balancers)
|
||||||
|
IP string `json:"ip,omitempty" description:"IP address of ingress point"`
|
||||||
|
|
||||||
|
// Hostname is set for load-balancer ingress points that are DNS based
|
||||||
|
// (typically AWS load-balancers)
|
||||||
|
Hostname string `json:"hostname,omitempty" description:"hostname of ingress point"`
|
||||||
|
}
|
||||||
|
|
||||||
// ServiceSpec describes the attributes that a user creates on a service
|
// ServiceSpec describes the attributes that a user creates on a service
|
||||||
type ServiceSpec struct {
|
type ServiceSpec struct {
|
||||||
|
@ -63,10 +63,10 @@ func GetLoadBalancerName(service *api.Service) string {
|
|||||||
type TCPLoadBalancer interface {
|
type TCPLoadBalancer interface {
|
||||||
// TODO: Break this up into different interfaces (LB, etc) when we have more than one type of service
|
// TODO: Break this up into different interfaces (LB, etc) when we have more than one type of service
|
||||||
// GetTCPLoadBalancer returns whether the specified load balancer exists, and
|
// GetTCPLoadBalancer returns whether the specified load balancer exists, and
|
||||||
// if so, what its IP address or hostname is.
|
// if so, what its status is.
|
||||||
GetTCPLoadBalancer(name, region string) (endpoint string, exists bool, err error)
|
GetTCPLoadBalancer(name, region string) (status *api.LoadBalancerStatus, exists bool, err error)
|
||||||
// CreateTCPLoadBalancer creates a new tcp load balancer. Returns the IP address or hostname of the balancer
|
// CreateTCPLoadBalancer creates a new tcp load balancer. Returns the status of the balancer
|
||||||
CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []int, hosts []string, affinityType api.ServiceAffinity) (string, error)
|
CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []int, hosts []string, affinityType api.ServiceAffinity) (*api.LoadBalancerStatus, error)
|
||||||
// UpdateTCPLoadBalancer updates hosts under the specified load balancer.
|
// UpdateTCPLoadBalancer updates hosts under the specified load balancer.
|
||||||
UpdateTCPLoadBalancer(name, region string, hosts []string) error
|
UpdateTCPLoadBalancer(name, region string, hosts []string) error
|
||||||
// EnsureTCPLoadBalancerDeleted deletes the specified load balancer if it
|
// EnsureTCPLoadBalancerDeleted deletes the specified load balancer if it
|
||||||
|
@ -103,16 +103,23 @@ func (f *FakeCloud) Routes() (cloudprovider.Routes, bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTCPLoadBalancer is a stub implementation of TCPLoadBalancer.GetTCPLoadBalancer.
|
// GetTCPLoadBalancer is a stub implementation of TCPLoadBalancer.GetTCPLoadBalancer.
|
||||||
func (f *FakeCloud) GetTCPLoadBalancer(name, region string) (endpoint string, exists bool, err error) {
|
func (f *FakeCloud) GetTCPLoadBalancer(name, region string) (*api.LoadBalancerStatus, bool, error) {
|
||||||
return f.ExternalIP.String(), f.Exists, f.Err
|
status := &api.LoadBalancerStatus{}
|
||||||
|
status.Ingress = []api.LoadBalancerIngress{{IP: f.ExternalIP.String()}}
|
||||||
|
|
||||||
|
return status, f.Exists, f.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTCPLoadBalancer is a test-spy implementation of TCPLoadBalancer.CreateTCPLoadBalancer.
|
// CreateTCPLoadBalancer is a test-spy implementation of TCPLoadBalancer.CreateTCPLoadBalancer.
|
||||||
// It adds an entry "create" into the internal method call record.
|
// It adds an entry "create" into the internal method call record.
|
||||||
func (f *FakeCloud) CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []int, hosts []string, affinityType api.ServiceAffinity) (string, error) {
|
func (f *FakeCloud) CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []int, hosts []string, affinityType api.ServiceAffinity) (*api.LoadBalancerStatus, error) {
|
||||||
f.addCall("create")
|
f.addCall("create")
|
||||||
f.Balancers = append(f.Balancers, FakeBalancer{name, region, externalIP, ports, hosts})
|
f.Balancers = append(f.Balancers, FakeBalancer{name, region, externalIP, ports, hosts})
|
||||||
return f.ExternalIP.String(), f.Err
|
|
||||||
|
status := &api.LoadBalancerStatus{}
|
||||||
|
status.Ingress = []api.LoadBalancerIngress{{IP: f.ExternalIP.String()}}
|
||||||
|
|
||||||
|
return status, f.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTCPLoadBalancer is a test-spy implementation of TCPLoadBalancer.UpdateTCPLoadBalancer.
|
// UpdateTCPLoadBalancer is a test-spy implementation of TCPLoadBalancer.UpdateTCPLoadBalancer.
|
||||||
|
@ -282,15 +282,18 @@ func (gce *GCECloud) waitForZoneOp(op *compute.Operation) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetTCPLoadBalancer is an implementation of TCPLoadBalancer.GetTCPLoadBalancer
|
// GetTCPLoadBalancer is an implementation of TCPLoadBalancer.GetTCPLoadBalancer
|
||||||
func (gce *GCECloud) GetTCPLoadBalancer(name, region string) (endpoint string, exists bool, err error) {
|
func (gce *GCECloud) GetTCPLoadBalancer(name, region string) (*api.LoadBalancerStatus, bool, error) {
|
||||||
fw, err := gce.service.ForwardingRules.Get(gce.projectID, region, name).Do()
|
fwd, err := gce.service.ForwardingRules.Get(gce.projectID, region, name).Do()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
return fw.IPAddress, true, nil
|
status := &api.LoadBalancerStatus{}
|
||||||
|
status.Ingress = []api.LoadBalancerIngress{{IP: fwd.IPAddress}}
|
||||||
|
|
||||||
|
return status, true, nil
|
||||||
}
|
}
|
||||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||||
return "", false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
return "", false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func isHTTPErrorCode(err error, code int) bool {
|
func isHTTPErrorCode(err error, code int) bool {
|
||||||
@ -314,17 +317,17 @@ func translateAffinityType(affinityType api.ServiceAffinity) GCEAffinityType {
|
|||||||
// CreateTCPLoadBalancer is an implementation of TCPLoadBalancer.CreateTCPLoadBalancer.
|
// CreateTCPLoadBalancer is an implementation of TCPLoadBalancer.CreateTCPLoadBalancer.
|
||||||
// TODO(a-robinson): Don't just ignore specified IP addresses. Check if they're
|
// TODO(a-robinson): Don't just ignore specified IP addresses. Check if they're
|
||||||
// owned by the project and available to be used, and use them if they are.
|
// owned by the project and available to be used, and use them if they are.
|
||||||
func (gce *GCECloud) CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []int, hosts []string, affinityType api.ServiceAffinity) (string, error) {
|
func (gce *GCECloud) CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []int, hosts []string, affinityType api.ServiceAffinity) (*api.LoadBalancerStatus, error) {
|
||||||
err := gce.makeTargetPool(name, region, hosts, translateAffinityType(affinityType))
|
err := gce.makeTargetPool(name, region, hosts, translateAffinityType(affinityType))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !isHTTPErrorCode(err, http.StatusConflict) {
|
if !isHTTPErrorCode(err, http.StatusConflict) {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
glog.Infof("Creating forwarding rule pointing at target pool that already exists: %v", err)
|
glog.Infof("Creating forwarding rule pointing at target pool that already exists: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(ports) == 0 {
|
if len(ports) == 0 {
|
||||||
return "", fmt.Errorf("no ports specified for GCE load balancer")
|
return nil, fmt.Errorf("no ports specified for GCE load balancer")
|
||||||
}
|
}
|
||||||
minPort := 65536
|
minPort := 65536
|
||||||
maxPort := 0
|
maxPort := 0
|
||||||
@ -344,19 +347,22 @@ func (gce *GCECloud) CreateTCPLoadBalancer(name, region string, externalIP net.I
|
|||||||
}
|
}
|
||||||
op, err := gce.service.ForwardingRules.Insert(gce.projectID, region, req).Do()
|
op, err := gce.service.ForwardingRules.Insert(gce.projectID, region, req).Do()
|
||||||
if err != nil && !isHTTPErrorCode(err, http.StatusConflict) {
|
if err != nil && !isHTTPErrorCode(err, http.StatusConflict) {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
if op != nil {
|
if op != nil {
|
||||||
err = gce.waitForRegionOp(op, region)
|
err = gce.waitForRegionOp(op, region)
|
||||||
if err != nil && !isHTTPErrorCode(err, http.StatusConflict) {
|
if err != nil && !isHTTPErrorCode(err, http.StatusConflict) {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fwd, err := gce.service.ForwardingRules.Get(gce.projectID, region, name).Do()
|
fwd, err := gce.service.ForwardingRules.Get(gce.projectID, region, name).Do()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
return fwd.IPAddress, nil
|
|
||||||
|
status := &api.LoadBalancerStatus{}
|
||||||
|
status.Ingress = []api.LoadBalancerIngress{{IP: fwd.IPAddress}}
|
||||||
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateTCPLoadBalancer is an implementation of TCPLoadBalancer.UpdateTCPLoadBalancer.
|
// UpdateTCPLoadBalancer is an implementation of TCPLoadBalancer.UpdateTCPLoadBalancer.
|
||||||
|
@ -457,15 +457,19 @@ func getVipByName(client *gophercloud.ServiceClient, name string) (*vips.Virtual
|
|||||||
return &vipList[0], nil
|
return &vipList[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lb *LoadBalancer) GetTCPLoadBalancer(name, region string) (endpoint string, exists bool, err error) {
|
func (lb *LoadBalancer) GetTCPLoadBalancer(name, region string) (*api.LoadBalancerStatus, bool, error) {
|
||||||
vip, err := getVipByName(lb.network, name)
|
vip, err := getVipByName(lb.network, name)
|
||||||
if err == ErrNotFound {
|
if err == ErrNotFound {
|
||||||
return "", false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
if vip == nil {
|
if vip == nil {
|
||||||
return "", false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
return vip.Address, true, err
|
|
||||||
|
status := &api.LoadBalancerStatus{}
|
||||||
|
status.Ingress = []api.LoadBalancerIngress{{IP: vip.Address}}
|
||||||
|
|
||||||
|
return status, true, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: This code currently ignores 'region' and always creates a
|
// TODO: This code currently ignores 'region' and always creates a
|
||||||
@ -473,11 +477,11 @@ func (lb *LoadBalancer) GetTCPLoadBalancer(name, region string) (endpoint string
|
|||||||
// a list of regions (from config) and query/create loadbalancers in
|
// a list of regions (from config) and query/create loadbalancers in
|
||||||
// each region.
|
// each region.
|
||||||
|
|
||||||
func (lb *LoadBalancer) CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []int, hosts []string, affinity api.ServiceAffinity) (string, error) {
|
func (lb *LoadBalancer) CreateTCPLoadBalancer(name, region string, externalIP net.IP, ports []int, hosts []string, affinity api.ServiceAffinity) (*api.LoadBalancerStatus, error) {
|
||||||
glog.V(4).Infof("CreateTCPLoadBalancer(%v, %v, %v, %v, %v, %v)", name, region, externalIP, ports, hosts, affinity)
|
glog.V(4).Infof("CreateTCPLoadBalancer(%v, %v, %v, %v, %v, %v)", name, region, externalIP, ports, hosts, affinity)
|
||||||
|
|
||||||
if len(ports) > 1 {
|
if len(ports) > 1 {
|
||||||
return "", fmt.Errorf("multiple ports are not yet supported in openstack load balancers")
|
return nil, fmt.Errorf("multiple ports are not yet supported in openstack load balancers")
|
||||||
}
|
}
|
||||||
|
|
||||||
var persistence *vips.SessionPersistence
|
var persistence *vips.SessionPersistence
|
||||||
@ -487,7 +491,7 @@ func (lb *LoadBalancer) CreateTCPLoadBalancer(name, region string, externalIP ne
|
|||||||
case api.ServiceAffinityClientIP:
|
case api.ServiceAffinityClientIP:
|
||||||
persistence = &vips.SessionPersistence{Type: "SOURCE_IP"}
|
persistence = &vips.SessionPersistence{Type: "SOURCE_IP"}
|
||||||
default:
|
default:
|
||||||
return "", fmt.Errorf("unsupported load balancer affinity: %v", affinity)
|
return nil, fmt.Errorf("unsupported load balancer affinity: %v", affinity)
|
||||||
}
|
}
|
||||||
|
|
||||||
lbmethod := lb.opts.LBMethod
|
lbmethod := lb.opts.LBMethod
|
||||||
@ -501,13 +505,13 @@ func (lb *LoadBalancer) CreateTCPLoadBalancer(name, region string, externalIP ne
|
|||||||
LBMethod: lbmethod,
|
LBMethod: lbmethod,
|
||||||
}).Extract()
|
}).Extract()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, host := range hosts {
|
for _, host := range hosts {
|
||||||
addr, err := getAddressByName(lb.compute, host)
|
addr, err := getAddressByName(lb.compute, host)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = members.Create(lb.network, members.CreateOpts{
|
_, err = members.Create(lb.network, members.CreateOpts{
|
||||||
@ -517,7 +521,7 @@ func (lb *LoadBalancer) CreateTCPLoadBalancer(name, region string, externalIP ne
|
|||||||
}).Extract()
|
}).Extract()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pools.Delete(lb.network, pool.ID)
|
pools.Delete(lb.network, pool.ID)
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,14 +535,14 @@ func (lb *LoadBalancer) CreateTCPLoadBalancer(name, region string, externalIP ne
|
|||||||
}).Extract()
|
}).Extract()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
pools.Delete(lb.network, pool.ID)
|
pools.Delete(lb.network, pool.ID)
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = pools.AssociateMonitor(lb.network, pool.ID, mon.ID).Extract()
|
_, err = pools.AssociateMonitor(lb.network, pool.ID, mon.ID).Extract()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
monitors.Delete(lb.network, mon.ID)
|
monitors.Delete(lb.network, mon.ID)
|
||||||
pools.Delete(lb.network, pool.ID)
|
pools.Delete(lb.network, pool.ID)
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -556,10 +560,13 @@ func (lb *LoadBalancer) CreateTCPLoadBalancer(name, region string, externalIP ne
|
|||||||
monitors.Delete(lb.network, mon.ID)
|
monitors.Delete(lb.network, mon.ID)
|
||||||
}
|
}
|
||||||
pools.Delete(lb.network, pool.ID)
|
pools.Delete(lb.network, pool.ID)
|
||||||
return "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return vip.Address, nil
|
status := &api.LoadBalancerStatus{}
|
||||||
|
status.Ingress = []api.LoadBalancerIngress{{IP: vip.Address}}
|
||||||
|
|
||||||
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lb *LoadBalancer) UpdateTCPLoadBalancer(name, region string, hosts []string) error {
|
func (lb *LoadBalancer) UpdateTCPLoadBalancer(name, region string, hosts []string) error {
|
||||||
|
@ -240,20 +240,16 @@ func (s *ServiceController) createLoadBalancerIfNeeded(namespacedName types.Name
|
|||||||
} else {
|
} else {
|
||||||
// If we don't have any cached memory of the load balancer, we have to ask
|
// If we don't have any cached memory of the load balancer, we have to ask
|
||||||
// the cloud provider for what it knows about it.
|
// the cloud provider for what it knows about it.
|
||||||
endpoint, exists, err := s.balancer.GetTCPLoadBalancer(s.loadBalancerName(service), s.zone.Region)
|
status, exists, err := s.balancer.GetTCPLoadBalancer(s.loadBalancerName(service), s.zone.Region)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error getting LB for service %s", namespacedName), retryable
|
return fmt.Errorf("Error getting LB for service %s", namespacedName), retryable
|
||||||
}
|
}
|
||||||
if exists && stringSlicesEqual(service.Spec.PublicIPs, []string{endpoint}) {
|
if exists && api.LoadBalancerStatusEqual(status, &service.Status.LoadBalancer) {
|
||||||
// TODO: If we could read more of the spec (ports, affinityType) of the
|
glog.Infof("LB already exists with status %s for previously uncached service %s", status, namespacedName)
|
||||||
// existing load balancer, we could better determine if an update is
|
|
||||||
// necessary in more cases. For now, we optimistically assume that a
|
|
||||||
// matching IP suffices.
|
|
||||||
glog.Infof("LB already exists with endpoint %s for previously uncached service %s", endpoint, namespacedName)
|
|
||||||
return nil, notRetryable
|
return nil, notRetryable
|
||||||
} else if exists {
|
} else if exists {
|
||||||
glog.Infof("Deleting old LB for previously uncached service %s whose endpoint %s doesn't match the service's desired IPs %v",
|
glog.Infof("Deleting old LB for previously uncached service %s whose endpoint %s doesn't match the service's desired IPs %v",
|
||||||
namespacedName, endpoint, service.Spec.PublicIPs)
|
namespacedName, status, service.Spec.PublicIPs)
|
||||||
if err := s.balancer.EnsureTCPLoadBalancerDeleted(s.loadBalancerName(service), s.zone.Region); err != nil {
|
if err := s.balancer.EnsureTCPLoadBalancerDeleted(s.loadBalancerName(service), s.zone.Region); err != nil {
|
||||||
return err, retryable
|
return err, retryable
|
||||||
}
|
}
|
||||||
@ -268,20 +264,24 @@ func (s *ServiceController) createLoadBalancerIfNeeded(namespacedName types.Name
|
|||||||
glog.V(2).Infof("Creating LB for service %s", namespacedName)
|
glog.V(2).Infof("Creating LB for service %s", namespacedName)
|
||||||
|
|
||||||
// The load balancer doesn't exist yet, so create it.
|
// The load balancer doesn't exist yet, so create it.
|
||||||
publicIPstring := fmt.Sprint(service.Spec.PublicIPs)
|
|
||||||
|
// Save the state so we can avoid a write if it doesn't change
|
||||||
|
previousState := api.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer)
|
||||||
|
|
||||||
err := s.createExternalLoadBalancer(service)
|
err := s.createExternalLoadBalancer(service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create external load balancer for service %s: %v", namespacedName, err), retryable
|
return fmt.Errorf("failed to create external load balancer for service %s: %v", namespacedName, err), retryable
|
||||||
}
|
}
|
||||||
|
|
||||||
if publicIPstring == fmt.Sprint(service.Spec.PublicIPs) {
|
// Write the state if changed
|
||||||
|
if api.LoadBalancerStatusEqual(previousState, &service.Status.LoadBalancer) {
|
||||||
glog.Infof("Not persisting unchanged service to registry.")
|
glog.Infof("Not persisting unchanged service to registry.")
|
||||||
return nil, notRetryable
|
return nil, notRetryable
|
||||||
}
|
}
|
||||||
|
|
||||||
// If creating the load balancer succeeded, persist the updated service.
|
// If creating the load balancer succeeded, persist the updated service.
|
||||||
if err = s.persistUpdate(service); err != nil {
|
if err = s.persistUpdate(service); err != nil {
|
||||||
return fmt.Errorf("Failed to persist updated publicIPs to apiserver, even after retries. Giving up: %v", err), notRetryable
|
return fmt.Errorf("Failed to persist updated status to apiserver, even after retries. Giving up: %v", err), notRetryable
|
||||||
}
|
}
|
||||||
return nil, notRetryable
|
return nil, notRetryable
|
||||||
}
|
}
|
||||||
@ -301,13 +301,13 @@ func (s *ServiceController) persistUpdate(service *api.Service) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
// TODO: Try to resolve the conflict if the change was unrelated to load
|
// TODO: Try to resolve the conflict if the change was unrelated to load
|
||||||
// balancers and public IPs. For now, just rely on the fact that we'll
|
// balancer status. For now, just rely on the fact that we'll
|
||||||
// also process the update that caused the resource version to change.
|
// also process the update that caused the resource version to change.
|
||||||
if errors.IsConflict(err) {
|
if errors.IsConflict(err) {
|
||||||
glog.Infof("Not persisting update to service that has been changed since we received it: %v", err)
|
glog.Infof("Not persisting update to service that has been changed since we received it: %v", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
glog.Warningf("Failed to persist updated PublicIPs to service %s after creating its external load balancer: %v",
|
glog.Warningf("Failed to persist updated LoadBalancerStatus to service %s after creating its external load balancer: %v",
|
||||||
service.Name, err)
|
service.Name, err)
|
||||||
time.Sleep(clientRetryInterval)
|
time.Sleep(clientRetryInterval)
|
||||||
}
|
}
|
||||||
@ -328,21 +328,23 @@ func (s *ServiceController) createExternalLoadBalancer(service *api.Service) err
|
|||||||
for _, publicIP := range service.Spec.PublicIPs {
|
for _, publicIP := range service.Spec.PublicIPs {
|
||||||
// TODO: Make this actually work for multiple IPs by using different
|
// TODO: Make this actually work for multiple IPs by using different
|
||||||
// names for each. For now, we'll just create the first and break.
|
// names for each. For now, we'll just create the first and break.
|
||||||
endpoint, err := s.balancer.CreateTCPLoadBalancer(name, s.zone.Region, net.ParseIP(publicIP),
|
status, err := s.balancer.CreateTCPLoadBalancer(name, s.zone.Region, net.ParseIP(publicIP),
|
||||||
ports, hostsFromNodeList(nodes), service.Spec.SessionAffinity)
|
ports, hostsFromNodeList(nodes), service.Spec.SessionAffinity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else {
|
||||||
|
service.Status.LoadBalancer = *status
|
||||||
}
|
}
|
||||||
service.Spec.PublicIPs = []string{endpoint}
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
endpoint, err := s.balancer.CreateTCPLoadBalancer(name, s.zone.Region, nil,
|
status, err := s.balancer.CreateTCPLoadBalancer(name, s.zone.Region, nil,
|
||||||
ports, hostsFromNodeList(nodes), service.Spec.SessionAffinity)
|
ports, hostsFromNodeList(nodes), service.Spec.SessionAffinity)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
} else {
|
||||||
|
service.Status.LoadBalancer = *status
|
||||||
}
|
}
|
||||||
service.Spec.PublicIPs = []string{endpoint}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -72,9 +72,14 @@ func RunClusterInfo(factory *cmdutil.Factory, out io.Writer, cmd *cobra.Command)
|
|||||||
services := r.Object.(*api.ServiceList).Items
|
services := r.Object.(*api.ServiceList).Items
|
||||||
for _, service := range services {
|
for _, service := range services {
|
||||||
var link string
|
var link string
|
||||||
if len(service.Spec.PublicIPs) > 0 {
|
if len(service.Status.LoadBalancer.Ingress) > 0 {
|
||||||
|
ingress := service.Status.LoadBalancer.Ingress[0]
|
||||||
|
ip := ingress.IP
|
||||||
|
if ip == "" {
|
||||||
|
ip = ingress.Hostname
|
||||||
|
}
|
||||||
for _, port := range service.Spec.Ports {
|
for _, port := range service.Spec.Ports {
|
||||||
link += "http://" + service.Spec.PublicIPs[0] + ":" + strconv.Itoa(port.Port) + " "
|
link += "http://" + ip + ":" + strconv.Itoa(port.Port) + " "
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
link = client.Host + "/api/v1beta3/proxy/namespaces/" + service.ObjectMeta.Namespace + "/services/" + service.ObjectMeta.Name
|
link = client.Host + "/api/v1beta3/proxy/namespaces/" + service.ObjectMeta.Namespace + "/services/" + service.ObjectMeta.Name
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package kubectl
|
package kubectl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
@ -480,6 +481,22 @@ func (d *ServiceDescriber) Describe(namespace, name string) (string, error) {
|
|||||||
return describeService(service, endpoints, events)
|
return describeService(service, endpoints, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildIngressString(ingress []api.LoadBalancerIngress) string {
|
||||||
|
var buffer bytes.Buffer
|
||||||
|
|
||||||
|
for i := range ingress {
|
||||||
|
if i != 0 {
|
||||||
|
buffer.WriteString(", ")
|
||||||
|
}
|
||||||
|
if ingress[i].IP != "" {
|
||||||
|
buffer.WriteString(ingress[i].IP)
|
||||||
|
} else {
|
||||||
|
buffer.WriteString(ingress[i].Hostname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return buffer.String()
|
||||||
|
}
|
||||||
|
|
||||||
func describeService(service *api.Service, endpoints *api.Endpoints, events *api.EventList) (string, error) {
|
func describeService(service *api.Service, endpoints *api.Endpoints, events *api.EventList) (string, error) {
|
||||||
if endpoints == nil {
|
if endpoints == nil {
|
||||||
endpoints = &api.Endpoints{}
|
endpoints = &api.Endpoints{}
|
||||||
@ -489,9 +506,9 @@ func describeService(service *api.Service, endpoints *api.Endpoints, events *api
|
|||||||
fmt.Fprintf(out, "Labels:\t%s\n", formatLabels(service.Labels))
|
fmt.Fprintf(out, "Labels:\t%s\n", formatLabels(service.Labels))
|
||||||
fmt.Fprintf(out, "Selector:\t%s\n", formatLabels(service.Spec.Selector))
|
fmt.Fprintf(out, "Selector:\t%s\n", formatLabels(service.Spec.Selector))
|
||||||
fmt.Fprintf(out, "IP:\t%s\n", service.Spec.PortalIP)
|
fmt.Fprintf(out, "IP:\t%s\n", service.Spec.PortalIP)
|
||||||
if len(service.Spec.PublicIPs) > 0 {
|
if len(service.Status.LoadBalancer.Ingress) > 0 {
|
||||||
list := strings.Join(service.Spec.PublicIPs, ", ")
|
list := buildIngressString(service.Status.LoadBalancer.Ingress)
|
||||||
fmt.Fprintf(out, "Public IPs:\t%s\n", list)
|
fmt.Fprintf(out, "Ingress:\t%s\n", list)
|
||||||
}
|
}
|
||||||
for i := range service.Spec.Ports {
|
for i := range service.Spec.Ports {
|
||||||
sp := &service.Spec.Ports[i]
|
sp := &service.Spec.Ports[i]
|
||||||
|
@ -552,8 +552,12 @@ func printService(svc *api.Service, w io.Writer, withNamespace bool) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ips := []string{svc.Spec.PortalIP}
|
ips := []string{svc.Spec.PortalIP}
|
||||||
for _, publicIP := range svc.Spec.PublicIPs {
|
|
||||||
ips = append(ips, publicIP)
|
ingress := svc.Status.LoadBalancer.Ingress
|
||||||
|
for i := range ingress {
|
||||||
|
if ingress[i].IP != "" {
|
||||||
|
ips = append(ips, ingress[i].IP)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d/%s\n", name, formatLabels(svc.Labels),
|
if _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%d/%s\n", name, formatLabels(svc.Labels),
|
||||||
|
@ -646,10 +646,6 @@ func TestPrintHumanReadableService(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Spec: api.ServiceSpec{
|
Spec: api.ServiceSpec{
|
||||||
PortalIP: "1.2.3.4",
|
PortalIP: "1.2.3.4",
|
||||||
PublicIPs: []string{
|
|
||||||
"2.3.4.5",
|
|
||||||
"3.4.5.6",
|
|
||||||
},
|
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Port: 80,
|
Port: 80,
|
||||||
@ -657,6 +653,18 @@ func TestPrintHumanReadableService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Status: api.ServiceStatus{
|
||||||
|
LoadBalancer: api.LoadBalancerStatus{
|
||||||
|
Ingress: []api.LoadBalancerIngress{
|
||||||
|
{
|
||||||
|
IP: "2.3.4.5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
IP: "3.4.5.6",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Spec: api.ServiceSpec{
|
Spec: api.ServiceSpec{
|
||||||
@ -680,9 +688,6 @@ func TestPrintHumanReadableService(t *testing.T) {
|
|||||||
{
|
{
|
||||||
Spec: api.ServiceSpec{
|
Spec: api.ServiceSpec{
|
||||||
PortalIP: "1.2.3.4",
|
PortalIP: "1.2.3.4",
|
||||||
PublicIPs: []string{
|
|
||||||
"2.3.4.5",
|
|
||||||
},
|
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Port: 80,
|
Port: 80,
|
||||||
@ -698,15 +703,19 @@ func TestPrintHumanReadableService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Status: api.ServiceStatus{
|
||||||
|
LoadBalancer: api.LoadBalancerStatus{
|
||||||
|
Ingress: []api.LoadBalancerIngress{
|
||||||
|
{
|
||||||
|
IP: "2.3.4.5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Spec: api.ServiceSpec{
|
Spec: api.ServiceSpec{
|
||||||
PortalIP: "1.2.3.4",
|
PortalIP: "1.2.3.4",
|
||||||
PublicIPs: []string{
|
|
||||||
"2.3.4.5",
|
|
||||||
"4.5.6.7",
|
|
||||||
"5.6.7.8",
|
|
||||||
},
|
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Port: 80,
|
Port: 80,
|
||||||
@ -722,6 +731,22 @@ func TestPrintHumanReadableService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Status: api.ServiceStatus{
|
||||||
|
LoadBalancer: api.LoadBalancerStatus{
|
||||||
|
Ingress: []api.LoadBalancerIngress{
|
||||||
|
{
|
||||||
|
IP: "2.3.4.5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
IP: "3.4.5.6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
IP: "5.6.7.8",
|
||||||
|
Hostname: "host5678",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -734,9 +759,10 @@ func TestPrintHumanReadableService(t *testing.T) {
|
|||||||
t.Errorf("expected to contain portal ip %s, but doesn't: %s", ip, output)
|
t.Errorf("expected to contain portal ip %s, but doesn't: %s", ip, output)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ip = range svc.Spec.PublicIPs {
|
for _, ingress := range svc.Status.LoadBalancer.Ingress {
|
||||||
|
ip = ingress.IP
|
||||||
if !strings.Contains(output, ip) {
|
if !strings.Contains(output, ip) {
|
||||||
t.Errorf("expected to contain public ip %s, but doesn't: %s", ip, output)
|
t.Errorf("expected to contain ingress ip %s, but doesn't: %s", ip, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,8 +774,8 @@ func TestPrintHumanReadableService(t *testing.T) {
|
|||||||
}
|
}
|
||||||
// Max of # ports and (# public ip + portal ip)
|
// Max of # ports and (# public ip + portal ip)
|
||||||
count := len(svc.Spec.Ports)
|
count := len(svc.Spec.Ports)
|
||||||
if len(svc.Spec.PublicIPs)+1 > count {
|
if len(svc.Status.LoadBalancer.Ingress)+1 > count {
|
||||||
count = len(svc.Spec.PublicIPs) + 1
|
count = len(svc.Status.LoadBalancer.Ingress) + 1
|
||||||
}
|
}
|
||||||
if count != strings.Count(output, "\n") {
|
if count != strings.Count(output, "\n") {
|
||||||
t.Errorf("expected %d newlines, found %d", count, strings.Count(output, "\n"))
|
t.Errorf("expected %d newlines, found %d", count, strings.Count(output, "\n"))
|
||||||
|
@ -40,8 +40,8 @@ type serviceInfo struct {
|
|||||||
proxyPort int
|
proxyPort int
|
||||||
socket proxySocket
|
socket proxySocket
|
||||||
timeout time.Duration
|
timeout time.Duration
|
||||||
publicIPs []string // TODO: make this net.IP
|
|
||||||
nodePort int
|
nodePort int
|
||||||
|
loadBalancerStatus api.LoadBalancerStatus
|
||||||
sessionAffinityType api.ServiceAffinity
|
sessionAffinityType api.ServiceAffinity
|
||||||
stickyMaxAgeMinutes int
|
stickyMaxAgeMinutes int
|
||||||
}
|
}
|
||||||
@ -287,9 +287,10 @@ func (proxier *Proxier) OnUpdate(services []api.Service) {
|
|||||||
}
|
}
|
||||||
info.portalIP = serviceIP
|
info.portalIP = serviceIP
|
||||||
info.portalPort = servicePort.Port
|
info.portalPort = servicePort.Port
|
||||||
info.publicIPs = service.Spec.PublicIPs
|
|
||||||
// TODO(justinsb): switch to servicePort.NodePort when that lands
|
// TODO(justinsb): switch to servicePort.NodePort when that lands
|
||||||
info.nodePort = 0
|
info.nodePort = 0
|
||||||
|
// Deep-copy in case the service instance changes
|
||||||
|
info.loadBalancerStatus = *api.LoadBalancerStatusDeepCopy(&service.Status.LoadBalancer)
|
||||||
info.sessionAffinityType = service.Spec.SessionAffinity
|
info.sessionAffinityType = service.Spec.SessionAffinity
|
||||||
glog.V(4).Infof("info: %+v", info)
|
glog.V(4).Infof("info: %+v", info)
|
||||||
|
|
||||||
@ -325,7 +326,7 @@ func sameConfig(info *serviceInfo, service *api.Service, port *api.ServicePort)
|
|||||||
if !info.portalIP.Equal(net.ParseIP(service.Spec.PortalIP)) {
|
if !info.portalIP.Equal(net.ParseIP(service.Spec.PortalIP)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !ipsEqual(info.publicIPs, service.Spec.PublicIPs) {
|
if !api.LoadBalancerStatusEqual(&info.loadBalancerStatus, &service.Status.LoadBalancer) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if info.sessionAffinityType != service.Spec.SessionAffinity {
|
if info.sessionAffinityType != service.Spec.SessionAffinity {
|
||||||
@ -351,12 +352,14 @@ func (proxier *Proxier) openPortal(service ServicePortName, info *serviceInfo) e
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, publicIP := range info.publicIPs {
|
for _, ingress := range info.loadBalancerStatus.Ingress {
|
||||||
err = proxier.openOnePortal(net.ParseIP(publicIP), info.portalPort, info.protocol, proxier.listenIP, info.proxyPort, service)
|
if ingress.IP != "" {
|
||||||
|
err = proxier.openOnePortal(net.ParseIP(ingress.IP), info.portalPort, info.protocol, proxier.listenIP, info.proxyPort, service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if info.nodePort != 0 {
|
if info.nodePort != 0 {
|
||||||
err = proxier.openNodePort(info.nodePort, info.protocol, proxier.listenIP, info.proxyPort, service)
|
err = proxier.openNodePort(info.nodePort, info.protocol, proxier.listenIP, info.proxyPort, service)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -468,8 +471,10 @@ func (proxier *Proxier) openNodePort(nodePort int, protocol api.Protocol, proxyI
|
|||||||
func (proxier *Proxier) closePortal(service ServicePortName, info *serviceInfo) error {
|
func (proxier *Proxier) closePortal(service ServicePortName, info *serviceInfo) error {
|
||||||
// Collect errors and report them all at the end.
|
// Collect errors and report them all at the end.
|
||||||
el := proxier.closeOnePortal(info.portalIP, info.portalPort, info.protocol, proxier.listenIP, info.proxyPort, service)
|
el := proxier.closeOnePortal(info.portalIP, info.portalPort, info.protocol, proxier.listenIP, info.proxyPort, service)
|
||||||
for _, publicIP := range info.publicIPs {
|
for _, ingress := range info.loadBalancerStatus.Ingress {
|
||||||
el = append(el, proxier.closeOnePortal(net.ParseIP(publicIP), info.portalPort, info.protocol, proxier.listenIP, info.proxyPort, service)...)
|
if ingress.IP != "" {
|
||||||
|
el = append(el, proxier.closeOnePortal(net.ParseIP(ingress.IP), info.portalPort, info.protocol, proxier.listenIP, info.proxyPort, service)...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if info.nodePort != 0 {
|
if info.nodePort != 0 {
|
||||||
el = append(el, proxier.closeNodePort(info.nodePort, info.protocol, proxier.listenIP, info.proxyPort, service)...)
|
el = append(el, proxier.closeNodePort(info.nodePort, info.protocol, proxier.listenIP, info.proxyPort, service)...)
|
||||||
|
@ -289,10 +289,14 @@ var _ = Describe("Services", func() {
|
|||||||
// currently indicated by a public IP address being added to the spec.
|
// currently indicated by a public IP address being added to the spec.
|
||||||
result, err = waitForPublicIPs(c, serviceName, ns)
|
result, err = waitForPublicIPs(c, serviceName, ns)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
if len(result.Spec.PublicIPs) != 1 {
|
if len(result.Status.LoadBalancer.Ingress) != 1 {
|
||||||
Failf("got unexpected number (%d) of public IPs for externally load balanced service: %v", result.Spec.PublicIPs, result)
|
Failf("got unexpected number (%v) of ingress points for externally load balanced service: %v", result.Status.LoadBalancer.Ingress, result)
|
||||||
|
}
|
||||||
|
ingress := result.Status.LoadBalancer.Ingress[0]
|
||||||
|
ip := ingress.IP
|
||||||
|
if ip == "" {
|
||||||
|
ip = ingress.Hostname
|
||||||
}
|
}
|
||||||
ip := result.Spec.PublicIPs[0]
|
|
||||||
port := result.Spec.Ports[0].Port
|
port := result.Spec.Ports[0].Port
|
||||||
|
|
||||||
pod := &api.Pod{
|
pod := &api.Pod{
|
||||||
@ -370,7 +374,7 @@ var _ = Describe("Services", func() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
publicIPs := []string{}
|
ingressPoints := []string{}
|
||||||
for _, namespace := range namespaces {
|
for _, namespace := range namespaces {
|
||||||
for _, serviceName := range serviceNames {
|
for _, serviceName := range serviceNames {
|
||||||
service.ObjectMeta.Name = serviceName
|
service.ObjectMeta.Name = serviceName
|
||||||
@ -389,10 +393,16 @@ var _ = Describe("Services", func() {
|
|||||||
for _, serviceName := range serviceNames {
|
for _, serviceName := range serviceNames {
|
||||||
result, err := waitForPublicIPs(c, serviceName, namespace)
|
result, err := waitForPublicIPs(c, serviceName, namespace)
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
publicIPs = append(publicIPs, result.Spec.PublicIPs...) // Save 'em to check uniqueness
|
for i := range result.Status.LoadBalancer.Ingress {
|
||||||
|
ingress := result.Status.LoadBalancer.Ingress[i].IP
|
||||||
|
if ingress == "" {
|
||||||
|
ingress = result.Status.LoadBalancer.Ingress[i].Hostname
|
||||||
|
}
|
||||||
|
ingressPoints = append(ingressPoints, ingress) // Save 'em to check uniqueness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
validateUniqueOrFail(publicIPs)
|
}
|
||||||
|
validateUniqueOrFail(ingressPoints)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -406,12 +416,12 @@ func waitForPublicIPs(c *client.Client, serviceName, namespace string) (*api.Ser
|
|||||||
Logf("Get service failed, ignoring for 5s: %v", err)
|
Logf("Get service failed, ignoring for 5s: %v", err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(service.Spec.PublicIPs) > 0 {
|
if len(service.Status.LoadBalancer.Ingress) > 0 {
|
||||||
return service, nil
|
return service, nil
|
||||||
}
|
}
|
||||||
Logf("Waiting for service %s in namespace %s to have a public IP (%v)", serviceName, namespace, time.Since(start))
|
Logf("Waiting for service %s in namespace %s to have an ingress point (%v)", serviceName, namespace, time.Since(start))
|
||||||
}
|
}
|
||||||
return service, fmt.Errorf("service %s in namespace %s doesn't have a public IP after %.2f seconds", serviceName, namespace, timeout.Seconds())
|
return service, fmt.Errorf("service %s in namespace %s doesn't have an ingress point after %.2f seconds", serviceName, namespace, timeout.Seconds())
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateUniqueOrFail(s []string) {
|
func validateUniqueOrFail(s []string) {
|
||||||
|
Loading…
Reference in New Issue
Block a user