mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 20:53:33 +00:00
Merge pull request #32811 from fraenkel/headless_service
Automatic merge from submit-queue (batch tested with PRs 38260, 32811, 28458, 33570, 37096) Allow no ports when exposing headless service fixes #32795
This commit is contained in:
commit
fa5556b92b
@ -177,6 +177,8 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
|
|||||||
params["selector"] = s
|
params["selector"] = s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isHeadlessService := params["cluster-ip"] == "None"
|
||||||
|
|
||||||
// For objects that need a port, derive it from the exposed object in case a user
|
// For objects that need a port, derive it from the exposed object in case a user
|
||||||
// didn't explicitly specify one via --port
|
// didn't explicitly specify one via --port
|
||||||
if port, found := params["port"]; found && kubectl.IsZero(port) {
|
if port, found := params["port"]; found && kubectl.IsZero(port) {
|
||||||
@ -186,7 +188,9 @@ func RunExpose(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []stri
|
|||||||
}
|
}
|
||||||
switch len(ports) {
|
switch len(ports) {
|
||||||
case 0:
|
case 0:
|
||||||
return cmdutil.UsageError(cmd, "couldn't find port via --port flag or introspection")
|
if !isHeadlessService {
|
||||||
|
return cmdutil.UsageError(cmd, "couldn't find port via --port flag or introspection")
|
||||||
|
}
|
||||||
case 1:
|
case 1:
|
||||||
params["port"] = ports[0]
|
params["port"] = ports[0]
|
||||||
default:
|
default:
|
||||||
|
@ -264,6 +264,32 @@ func TestRunExposeService(t *testing.T) {
|
|||||||
expected: "service \"foo\" exposed",
|
expected: "service \"foo\" exposed",
|
||||||
status: 200,
|
status: 200,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "expose-headless-service-no-port",
|
||||||
|
args: []string{"service", "baz"},
|
||||||
|
ns: "test",
|
||||||
|
calls: map[string]string{
|
||||||
|
"GET": "/namespaces/test/services/baz",
|
||||||
|
"POST": "/namespaces/test/services",
|
||||||
|
},
|
||||||
|
input: &api.Service{
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "baz", Namespace: "test", ResourceVersion: "12"},
|
||||||
|
Spec: api.ServiceSpec{
|
||||||
|
Selector: map[string]string{"app": "go"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
flags: map[string]string{"selector": "func=stream", "name": "foo", "labels": "svc=test", "cluster-ip": "None", "dry-run": "true"},
|
||||||
|
output: &api.Service{
|
||||||
|
ObjectMeta: api.ObjectMeta{Name: "foo", Namespace: "", Labels: map[string]string{"svc": "test"}},
|
||||||
|
Spec: api.ServiceSpec{
|
||||||
|
Ports: []api.ServicePort{},
|
||||||
|
Selector: map[string]string{"func": "stream"},
|
||||||
|
ClusterIP: api.ClusterIPNone,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: "service \"foo\" exposed",
|
||||||
|
status: 200,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "expose-from-file",
|
name: "expose-from-file",
|
||||||
args: []string{},
|
args: []string{},
|
||||||
|
@ -110,6 +110,9 @@ func generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
|||||||
return nil, fmt.Errorf("'name' is a required parameter.")
|
return nil, fmt.Errorf("'name' is a required parameter.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isHeadlessService := params["cluster-ip"] == "None"
|
||||||
|
|
||||||
ports := []api.ServicePort{}
|
ports := []api.ServicePort{}
|
||||||
servicePortName, found := params["port-name"]
|
servicePortName, found := params["port-name"]
|
||||||
if !found {
|
if !found {
|
||||||
@ -131,44 +134,46 @@ func generate(genericParams map[string]interface{}) (runtime.Object, error) {
|
|||||||
var portString string
|
var portString string
|
||||||
if portString, found = params["ports"]; !found {
|
if portString, found = params["ports"]; !found {
|
||||||
portString, found = params["port"]
|
portString, found = params["port"]
|
||||||
if !found {
|
if !found && !isHeadlessService {
|
||||||
return nil, fmt.Errorf("'port' is a required parameter.")
|
return nil, fmt.Errorf("'port' is a required parameter.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
portStringSlice := strings.Split(portString, ",")
|
if portString != "" {
|
||||||
for i, stillPortString := range portStringSlice {
|
portStringSlice := strings.Split(portString, ",")
|
||||||
port, err := strconv.Atoi(stillPortString)
|
for i, stillPortString := range portStringSlice {
|
||||||
if err != nil {
|
port, err := strconv.Atoi(stillPortString)
|
||||||
return nil, err
|
if err != nil {
|
||||||
}
|
return nil, err
|
||||||
name := servicePortName
|
|
||||||
// If we are going to assign multiple ports to a service, we need to
|
|
||||||
// generate a different name for each one.
|
|
||||||
if len(portStringSlice) > 1 {
|
|
||||||
name = fmt.Sprintf("port-%d", i+1)
|
|
||||||
}
|
|
||||||
protocol := params["protocol"]
|
|
||||||
|
|
||||||
switch {
|
|
||||||
case len(protocol) == 0 && len(portProtocolMap) == 0:
|
|
||||||
// Default to TCP, what the flag was doing previously.
|
|
||||||
protocol = "TCP"
|
|
||||||
case len(protocol) > 0 && len(portProtocolMap) > 0:
|
|
||||||
// User has specified the --protocol while exposing a multiprotocol resource
|
|
||||||
// We should stomp multiple protocols with the one specified ie. do nothing
|
|
||||||
case len(protocol) == 0 && len(portProtocolMap) > 0:
|
|
||||||
// no --protocol and we expose a multiprotocol resource
|
|
||||||
protocol = "TCP" // have the default so we can stay sane
|
|
||||||
if exposeProtocol, found := portProtocolMap[stillPortString]; found {
|
|
||||||
protocol = exposeProtocol
|
|
||||||
}
|
}
|
||||||
|
name := servicePortName
|
||||||
|
// If we are going to assign multiple ports to a service, we need to
|
||||||
|
// generate a different name for each one.
|
||||||
|
if len(portStringSlice) > 1 {
|
||||||
|
name = fmt.Sprintf("port-%d", i+1)
|
||||||
|
}
|
||||||
|
protocol := params["protocol"]
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case len(protocol) == 0 && len(portProtocolMap) == 0:
|
||||||
|
// Default to TCP, what the flag was doing previously.
|
||||||
|
protocol = "TCP"
|
||||||
|
case len(protocol) > 0 && len(portProtocolMap) > 0:
|
||||||
|
// User has specified the --protocol while exposing a multiprotocol resource
|
||||||
|
// We should stomp multiple protocols with the one specified ie. do nothing
|
||||||
|
case len(protocol) == 0 && len(portProtocolMap) > 0:
|
||||||
|
// no --protocol and we expose a multiprotocol resource
|
||||||
|
protocol = "TCP" // have the default so we can stay sane
|
||||||
|
if exposeProtocol, found := portProtocolMap[stillPortString]; found {
|
||||||
|
protocol = exposeProtocol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ports = append(ports, api.ServicePort{
|
||||||
|
Name: name,
|
||||||
|
Port: int32(port),
|
||||||
|
Protocol: api.Protocol(protocol),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ports = append(ports, api.ServicePort{
|
|
||||||
Name: name,
|
|
||||||
Port: int32(port),
|
|
||||||
Protocol: api.Protocol(protocol),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
service := api.Service{
|
service := api.Service{
|
||||||
|
@ -536,6 +536,29 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
generator: ServiceGeneratorV2{},
|
||||||
|
params: map[string]interface{}{
|
||||||
|
"selector": "foo=bar,baz=blah",
|
||||||
|
"name": "test",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"container-port": "1234",
|
||||||
|
"cluster-ip": "None",
|
||||||
|
},
|
||||||
|
expected: api.Service{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "test",
|
||||||
|
},
|
||||||
|
Spec: api.ServiceSpec{
|
||||||
|
Selector: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": "blah",
|
||||||
|
},
|
||||||
|
Ports: []api.ServicePort{},
|
||||||
|
ClusterIP: api.ClusterIPNone,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
obj, err := test.generator.Generate(test.params)
|
obj, err := test.generator.Generate(test.params)
|
||||||
|
Loading…
Reference in New Issue
Block a user