mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-03 17:30:00 +00:00
Use helper to init ClusterIP and NodePort in Create of service
This commit is contained in:
parent
d026286d39
commit
dc7fb0c9e5
@ -95,71 +95,19 @@ func (rs *REST) Create(ctx genericapirequest.Context, obj runtime.Object, includ
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if helper.IsServiceIPRequested(service) {
|
var err error
|
||||||
// Allocate next available.
|
if service.Spec.Type != api.ServiceTypeExternalName {
|
||||||
ip, err := rs.serviceIPs.AllocateNext()
|
if releaseServiceIP, err = rs.initClusterIP(service); err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
// TODO: what error should be returned here? It's not a
|
|
||||||
// field-level validation failure (the field is valid), and it's
|
|
||||||
// not really an internal error.
|
|
||||||
return nil, errors.NewInternalError(fmt.Errorf("failed to allocate a serviceIP: %v", err))
|
|
||||||
}
|
}
|
||||||
service.Spec.ClusterIP = ip.String()
|
|
||||||
releaseServiceIP = true
|
|
||||||
} else if helper.IsServiceIPSet(service) {
|
|
||||||
// Try to respect the requested IP.
|
|
||||||
if err := rs.serviceIPs.Allocate(net.ParseIP(service.Spec.ClusterIP)); err != nil {
|
|
||||||
// TODO: when validation becomes versioned, this gets more complicated.
|
|
||||||
el := field.ErrorList{field.Invalid(field.NewPath("spec", "clusterIP"), service.Spec.ClusterIP, err.Error())}
|
|
||||||
return nil, errors.NewInvalid(api.Kind("Service"), service.Name, el)
|
|
||||||
}
|
|
||||||
releaseServiceIP = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
nodePortOp := portallocator.StartOperation(rs.serviceNodePorts)
|
nodePortOp := portallocator.StartOperation(rs.serviceNodePorts)
|
||||||
defer nodePortOp.Finish()
|
defer nodePortOp.Finish()
|
||||||
|
|
||||||
assignNodePorts := shouldAssignNodePorts(service)
|
if service.Spec.Type == api.ServiceTypeNodePort || service.Spec.Type == api.ServiceTypeLoadBalancer {
|
||||||
svcPortToNodePort := map[int]int{}
|
if err := rs.initNodePort(service, nodePortOp); err != nil {
|
||||||
for i := range service.Spec.Ports {
|
return nil, err
|
||||||
servicePort := &service.Spec.Ports[i]
|
|
||||||
allocatedNodePort := svcPortToNodePort[int(servicePort.Port)]
|
|
||||||
if allocatedNodePort == 0 {
|
|
||||||
// This will only scan forward in the service.Spec.Ports list because any matches
|
|
||||||
// before the current port would have been found in svcPortToNodePort. This is really
|
|
||||||
// looking for any user provided values.
|
|
||||||
np := findRequestedNodePort(int(servicePort.Port), service.Spec.Ports)
|
|
||||||
if np != 0 {
|
|
||||||
err := nodePortOp.Allocate(np)
|
|
||||||
if err != nil {
|
|
||||||
// TODO: when validation becomes versioned, this gets more complicated.
|
|
||||||
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), np, err.Error())}
|
|
||||||
return nil, errors.NewInvalid(api.Kind("Service"), service.Name, el)
|
|
||||||
}
|
|
||||||
servicePort.NodePort = int32(np)
|
|
||||||
svcPortToNodePort[int(servicePort.Port)] = np
|
|
||||||
} else if assignNodePorts {
|
|
||||||
nodePort, err := nodePortOp.AllocateNext()
|
|
||||||
if err != nil {
|
|
||||||
// TODO: what error should be returned here? It's not a
|
|
||||||
// field-level validation failure (the field is valid), and it's
|
|
||||||
// not really an internal error.
|
|
||||||
return nil, errors.NewInternalError(fmt.Errorf("failed to allocate a nodePort: %v", err))
|
|
||||||
}
|
|
||||||
servicePort.NodePort = int32(nodePort)
|
|
||||||
svcPortToNodePort[int(servicePort.Port)] = nodePort
|
|
||||||
}
|
|
||||||
} else if int(servicePort.NodePort) != allocatedNodePort {
|
|
||||||
if servicePort.NodePort == 0 {
|
|
||||||
servicePort.NodePort = int32(allocatedNodePort)
|
|
||||||
} else {
|
|
||||||
err := nodePortOp.Allocate(int(servicePort.NodePort))
|
|
||||||
if err != nil {
|
|
||||||
// TODO: when validation becomes versioned, this gets more complicated.
|
|
||||||
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), servicePort.NodePort, err.Error())}
|
|
||||||
return nil, errors.NewInvalid(api.Kind("Service"), service.Name, el)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,6 +534,54 @@ func (rs *REST) initClusterIP(service *api.Service) (bool, error) {
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (rs *REST) initNodePort(service *api.Service, nodePortOp *portallocator.PortAllocationOperation) error {
|
||||||
|
assignNodePorts := shouldAssignNodePorts(service)
|
||||||
|
svcPortToNodePort := map[int]int{}
|
||||||
|
for i := range service.Spec.Ports {
|
||||||
|
servicePort := &service.Spec.Ports[i]
|
||||||
|
allocatedNodePort := svcPortToNodePort[int(servicePort.Port)]
|
||||||
|
if allocatedNodePort == 0 {
|
||||||
|
// This will only scan forward in the service.Spec.Ports list because any matches
|
||||||
|
// before the current port would have been found in svcPortToNodePort. This is really
|
||||||
|
// looking for any user provided values.
|
||||||
|
np := findRequestedNodePort(int(servicePort.Port), service.Spec.Ports)
|
||||||
|
if np != 0 {
|
||||||
|
err := nodePortOp.Allocate(np)
|
||||||
|
if err != nil {
|
||||||
|
// TODO: when validation becomes versioned, this gets more complicated.
|
||||||
|
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), np, err.Error())}
|
||||||
|
return errors.NewInvalid(api.Kind("Service"), service.Name, el)
|
||||||
|
}
|
||||||
|
servicePort.NodePort = int32(np)
|
||||||
|
svcPortToNodePort[int(servicePort.Port)] = np
|
||||||
|
} else if assignNodePorts {
|
||||||
|
nodePort, err := nodePortOp.AllocateNext()
|
||||||
|
if err != nil {
|
||||||
|
// TODO: what error should be returned here? It's not a
|
||||||
|
// field-level validation failure (the field is valid), and it's
|
||||||
|
// not really an internal error.
|
||||||
|
return errors.NewInternalError(fmt.Errorf("failed to allocate a nodePort: %v", err))
|
||||||
|
}
|
||||||
|
servicePort.NodePort = int32(nodePort)
|
||||||
|
svcPortToNodePort[int(servicePort.Port)] = nodePort
|
||||||
|
}
|
||||||
|
} else if int(servicePort.NodePort) != allocatedNodePort {
|
||||||
|
if servicePort.NodePort == 0 {
|
||||||
|
servicePort.NodePort = int32(allocatedNodePort)
|
||||||
|
} else {
|
||||||
|
err := nodePortOp.Allocate(int(servicePort.NodePort))
|
||||||
|
if err != nil {
|
||||||
|
// TODO: when validation becomes versioned, this gets more complicated.
|
||||||
|
el := field.ErrorList{field.Invalid(field.NewPath("spec", "ports").Index(i).Child("nodePort"), servicePort.NodePort, err.Error())}
|
||||||
|
return errors.NewInvalid(api.Kind("Service"), service.Name, el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (rs *REST) updateNodePort(oldService, newService *api.Service, nodePortOp *portallocator.PortAllocationOperation) error {
|
func (rs *REST) updateNodePort(oldService, newService *api.Service, nodePortOp *portallocator.PortAllocationOperation) error {
|
||||||
oldNodePorts := CollectServiceNodePorts(oldService)
|
oldNodePorts := CollectServiceNodePorts(oldService)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user