mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-28 14:07:14 +00:00
Introduce a new service generator that leaves service port unnamed
This commit is contained in:
parent
59bc8db554
commit
496f30a92f
@ -35,8 +35,8 @@ re\-use the labels from the resource it exposes.
|
|||||||
If true, only print the object that would be sent, without creating it.
|
If true, only print the object that would be sent, without creating it.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-\-generator\fP="service/v1"
|
\fB\-\-generator\fP="service/v2"
|
||||||
The name of the API generator to use. Default is 'service/v1'.
|
The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.
|
||||||
|
|
||||||
.PP
|
.PP
|
||||||
\fB\-h\fP, \fB\-\-help\fP=false
|
\fB\-h\fP, \fB\-\-help\fP=false
|
||||||
|
@ -56,7 +56,7 @@ $ kubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream
|
|||||||
--container-port="": Synonym for --target-port
|
--container-port="": Synonym for --target-port
|
||||||
--create-external-load-balancer=false: If true, create an external load balancer for this service (trumped by --type). Implementation is cloud provider dependent. Default is 'false'.
|
--create-external-load-balancer=false: If true, create an external load balancer for this service (trumped by --type). Implementation is cloud provider dependent. Default is 'false'.
|
||||||
--dry-run=false: If true, only print the object that would be sent, without creating it.
|
--dry-run=false: If true, only print the object that would be sent, without creating it.
|
||||||
--generator="service/v1": The name of the API generator to use. Default is 'service/v1'.
|
--generator="service/v2": The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.
|
||||||
-h, --help=false: help for expose
|
-h, --help=false: help for expose
|
||||||
-l, --labels="": Labels to apply to the service created by this call.
|
-l, --labels="": Labels to apply to the service created by this call.
|
||||||
--name="": The name for the newly created object.
|
--name="": The name for the newly created object.
|
||||||
@ -105,7 +105,7 @@ $ kubectl expose rc streamer --port=4100 --protocol=udp --name=video-stream
|
|||||||
### SEE ALSO
|
### SEE ALSO
|
||||||
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
* [kubectl](kubectl.md) - kubectl controls the Kubernetes cluster manager
|
||||||
|
|
||||||
###### Auto generated by spf13/cobra at 2015-07-14 00:11:42.957615868 +0000 UTC
|
###### Auto generated by spf13/cobra at 2015-07-16 21:22:36.08263026 +0000 UTC
|
||||||
|
|
||||||
|
|
||||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||||
|
@ -178,6 +178,7 @@ runTests() {
|
|||||||
rc_status_replicas_field=".status.replicas"
|
rc_status_replicas_field=".status.replicas"
|
||||||
rc_container_image_field=".spec.template.spec.containers"
|
rc_container_image_field=".spec.template.spec.containers"
|
||||||
port_field="(index .spec.ports 0).port"
|
port_field="(index .spec.ports 0).port"
|
||||||
|
port_name="(index .spec.ports 0).name"
|
||||||
image_field="(index .spec.containers 0).image"
|
image_field="(index .spec.containers 0).image"
|
||||||
|
|
||||||
# Passing no arguments to create is an error
|
# Passing no arguments to create is an error
|
||||||
@ -623,20 +624,24 @@ __EOF__
|
|||||||
kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
|
kube::test::get_object_assert 'rc frontend' "{{$rc_replicas_field}}" '3'
|
||||||
# Command
|
# Command
|
||||||
kubectl expose rc frontend --port=80 "${kube_flags[@]}"
|
kubectl expose rc frontend --port=80 "${kube_flags[@]}"
|
||||||
# Post-condition: service exists
|
# Post-condition: service exists and the port is unnamed
|
||||||
kube::test::get_object_assert 'service frontend' "{{$port_field}}" '80'
|
kube::test::get_object_assert 'service frontend' "{{$port_name}} {{$port_field}}" '<no value> 80'
|
||||||
# Command
|
# Command
|
||||||
kubectl expose service frontend --port=443 --name=frontend-2 "${kube_flags[@]}"
|
kubectl expose service frontend --port=443 --name=frontend-2 "${kube_flags[@]}"
|
||||||
# Post-condition: service exists
|
# Post-condition: service exists and the port is unnamed
|
||||||
kube::test::get_object_assert 'service frontend-2' "{{$port_field}}" '443'
|
kube::test::get_object_assert 'service frontend-2' "{{$port_name}} {{$port_field}}" '<no value> 443'
|
||||||
# Command
|
# Command
|
||||||
kubectl create -f docs/user-guide/limitrange/valid-pod.yaml "${kube_flags[@]}"
|
kubectl create -f docs/user-guide/limitrange/valid-pod.yaml "${kube_flags[@]}"
|
||||||
kubectl expose pod valid-pod --port=444 --name=frontend-3 "${kube_flags[@]}"
|
kubectl expose pod valid-pod --port=444 --name=frontend-3 "${kube_flags[@]}"
|
||||||
# Post-condition: service exists
|
# Post-condition: service exists and the port is unnamed
|
||||||
kube::test::get_object_assert 'service frontend-3' "{{$port_field}}" '444'
|
kube::test::get_object_assert 'service frontend-3' "{{$port_name}} {{$port_field}}" '<no value> 444'
|
||||||
|
# Create a service using service/v1 generator
|
||||||
|
kubectl expose rc frontend --port=80 --name=frontend-4 --generator=service/v1 "${kube_flags[@]}"
|
||||||
|
# Post-condition: service exists and the port is named default.
|
||||||
|
kube::test::get_object_assert 'service frontend-4' "{{$port_name}} {{$port_field}}" 'default 80'
|
||||||
# Cleanup services
|
# Cleanup services
|
||||||
kubectl delete pod valid-pod "${kube_flags[@]}"
|
kubectl delete pod valid-pod "${kube_flags[@]}"
|
||||||
kubectl delete service frontend{,-2,-3} "${kube_flags[@]}"
|
kubectl delete service frontend{,-2,-3,-4} "${kube_flags[@]}"
|
||||||
|
|
||||||
### Perform a rolling update with --image
|
### Perform a rolling update with --image
|
||||||
# Command
|
# Command
|
||||||
|
@ -177,7 +177,8 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
|
|||||||
}
|
}
|
||||||
generators := map[string]kubectl.Generator{
|
generators := map[string]kubectl.Generator{
|
||||||
"run/v1": kubectl.BasicReplicationController{},
|
"run/v1": kubectl.BasicReplicationController{},
|
||||||
"service/v1": kubectl.ServiceGenerator{},
|
"service/v1": kubectl.ServiceGeneratorV1{},
|
||||||
|
"service/v2": kubectl.ServiceGeneratorV2{},
|
||||||
}
|
}
|
||||||
return &cmdutil.Factory{
|
return &cmdutil.Factory{
|
||||||
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
||||||
|
@ -56,7 +56,7 @@ func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmdutil.AddPrinterFlags(cmd)
|
cmdutil.AddPrinterFlags(cmd)
|
||||||
cmd.Flags().String("generator", "service/v1", "The name of the API generator to use. Default is 'service/v1'.")
|
cmd.Flags().String("generator", "service/v2", "The name of the API generator to use. There are 2 generators: 'service/v1' and 'service/v2'. The only difference between them is that service port in v1 is named 'default', while it is left unnamed in v2. Default is 'service/v2'.")
|
||||||
cmd.Flags().String("protocol", "TCP", "The network protocol for the service to be created. Default is 'tcp'.")
|
cmd.Flags().String("protocol", "TCP", "The network protocol for the service to be created. Default is 'tcp'.")
|
||||||
cmd.Flags().Int("port", -1, "The port that the service should serve on. Required.")
|
cmd.Flags().Int("port", -1, "The port that the service should serve on. Required.")
|
||||||
cmd.MarkFlagRequired("port")
|
cmd.MarkFlagRequired("port")
|
||||||
|
@ -97,7 +97,8 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
|||||||
|
|
||||||
generators := map[string]kubectl.Generator{
|
generators := map[string]kubectl.Generator{
|
||||||
"run/v1": kubectl.BasicReplicationController{},
|
"run/v1": kubectl.BasicReplicationController{},
|
||||||
"service/v1": kubectl.ServiceGenerator{},
|
"service/v1": kubectl.ServiceGeneratorV1{},
|
||||||
|
"service/v2": kubectl.ServiceGeneratorV2{},
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConfig := optionalClientConfig
|
clientConfig := optionalClientConfig
|
||||||
|
@ -25,9 +25,29 @@ import (
|
|||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ServiceGenerator struct{}
|
// The only difference between ServiceGeneratorV1 and V2 is that the service port is named "default" in V1, while it is left unnamed in V2.
|
||||||
|
type ServiceGeneratorV1 struct{}
|
||||||
|
|
||||||
func (ServiceGenerator) ParamNames() []GeneratorParam {
|
func (ServiceGeneratorV1) ParamNames() []GeneratorParam {
|
||||||
|
return paramNames()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ServiceGeneratorV1) Generate(params map[string]string) (runtime.Object, error) {
|
||||||
|
params["port-name"] = "default"
|
||||||
|
return generate(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ServiceGeneratorV2 struct{}
|
||||||
|
|
||||||
|
func (ServiceGeneratorV2) ParamNames() []GeneratorParam {
|
||||||
|
return paramNames()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ServiceGeneratorV2) Generate(params map[string]string) (runtime.Object, error) {
|
||||||
|
return generate(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func paramNames() []GeneratorParam {
|
||||||
return []GeneratorParam{
|
return []GeneratorParam{
|
||||||
{"default-name", true},
|
{"default-name", true},
|
||||||
{"name", false},
|
{"name", false},
|
||||||
@ -40,10 +60,11 @@ func (ServiceGenerator) ParamNames() []GeneratorParam {
|
|||||||
{"protocol", false},
|
{"protocol", false},
|
||||||
{"container-port", false}, // alias of target-port
|
{"container-port", false}, // alias of target-port
|
||||||
{"target-port", false},
|
{"target-port", false},
|
||||||
|
{"port-name", false},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ServiceGenerator) Generate(params map[string]string) (runtime.Object, error) {
|
func generate(params map[string]string) (runtime.Object, error) {
|
||||||
selectorString, found := params["selector"]
|
selectorString, found := params["selector"]
|
||||||
if !found || len(selectorString) == 0 {
|
if !found || len(selectorString) == 0 {
|
||||||
return nil, fmt.Errorf("'selector' is a required parameter.")
|
return nil, fmt.Errorf("'selector' is a required parameter.")
|
||||||
@ -77,6 +98,11 @@ func (ServiceGenerator) Generate(params map[string]string) (runtime.Object, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
servicePortName, found := params["port-name"]
|
||||||
|
if !found {
|
||||||
|
// Leave the port unnamed.
|
||||||
|
servicePortName = ""
|
||||||
|
}
|
||||||
service := api.Service{
|
service := api.Service{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: name,
|
Name: name,
|
||||||
@ -86,7 +112,7 @@ func (ServiceGenerator) Generate(params map[string]string) (runtime.Object, erro
|
|||||||
Selector: selector,
|
Selector: selector,
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "default",
|
Name: servicePortName,
|
||||||
Port: port,
|
Port: port,
|
||||||
Protocol: api.Protocol(params["protocol"]),
|
Protocol: api.Protocol(params["protocol"]),
|
||||||
},
|
},
|
||||||
|
@ -26,10 +26,12 @@ import (
|
|||||||
|
|
||||||
func TestGenerateService(t *testing.T) {
|
func TestGenerateService(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
params map[string]string
|
generator Generator
|
||||||
expected api.Service
|
params map[string]string
|
||||||
|
expected api.Service
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]string{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
@ -48,7 +50,6 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "default",
|
|
||||||
Port: 80,
|
Port: 80,
|
||||||
Protocol: "TCP",
|
Protocol: "TCP",
|
||||||
TargetPort: util.NewIntOrStringFromInt(1234),
|
TargetPort: util.NewIntOrStringFromInt(1234),
|
||||||
@ -58,6 +59,8 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
||||||
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]string{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
@ -76,7 +79,6 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "default",
|
|
||||||
Port: 80,
|
Port: 80,
|
||||||
Protocol: "UDP",
|
Protocol: "UDP",
|
||||||
TargetPort: util.NewIntOrStringFromString("foobar"),
|
TargetPort: util.NewIntOrStringFromString("foobar"),
|
||||||
@ -86,6 +88,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]string{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"labels": "key1=value1,key2=value2",
|
"labels": "key1=value1,key2=value2",
|
||||||
@ -109,7 +112,6 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "default",
|
|
||||||
Port: 80,
|
Port: 80,
|
||||||
Protocol: "TCP",
|
Protocol: "TCP",
|
||||||
TargetPort: util.NewIntOrStringFromInt(1234),
|
TargetPort: util.NewIntOrStringFromInt(1234),
|
||||||
@ -119,6 +121,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]string{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
@ -138,7 +141,6 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "default",
|
|
||||||
Port: 80,
|
Port: 80,
|
||||||
Protocol: "UDP",
|
Protocol: "UDP",
|
||||||
TargetPort: util.NewIntOrStringFromString("foobar"),
|
TargetPort: util.NewIntOrStringFromString("foobar"),
|
||||||
@ -149,6 +151,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]string{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
@ -169,7 +172,6 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "default",
|
|
||||||
Port: 80,
|
Port: 80,
|
||||||
Protocol: "UDP",
|
Protocol: "UDP",
|
||||||
TargetPort: util.NewIntOrStringFromString("foobar"),
|
TargetPort: util.NewIntOrStringFromString("foobar"),
|
||||||
@ -181,6 +183,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]string{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
@ -200,7 +203,6 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "default",
|
|
||||||
Port: 80,
|
Port: 80,
|
||||||
Protocol: "UDP",
|
Protocol: "UDP",
|
||||||
TargetPort: util.NewIntOrStringFromString("foobar"),
|
TargetPort: util.NewIntOrStringFromString("foobar"),
|
||||||
@ -211,6 +213,7 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
generator: ServiceGeneratorV2{},
|
||||||
params: map[string]string{
|
params: map[string]string{
|
||||||
"selector": "foo=bar,baz=blah",
|
"selector": "foo=bar,baz=blah",
|
||||||
"name": "test",
|
"name": "test",
|
||||||
@ -231,7 +234,6 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
Ports: []api.ServicePort{
|
Ports: []api.ServicePort{
|
||||||
{
|
{
|
||||||
Name: "default",
|
|
||||||
Port: 80,
|
Port: 80,
|
||||||
Protocol: "UDP",
|
Protocol: "UDP",
|
||||||
TargetPort: util.NewIntOrStringFromString("foobar"),
|
TargetPort: util.NewIntOrStringFromString("foobar"),
|
||||||
@ -241,10 +243,38 @@ func TestGenerateService(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
generator: ServiceGeneratorV1{},
|
||||||
|
params: map[string]string{
|
||||||
|
"selector": "foo=bar,baz=blah",
|
||||||
|
"name": "test",
|
||||||
|
"port": "80",
|
||||||
|
"protocol": "TCP",
|
||||||
|
"container-port": "1234",
|
||||||
|
},
|
||||||
|
expected: api.Service{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
Name: "test",
|
||||||
|
},
|
||||||
|
Spec: api.ServiceSpec{
|
||||||
|
Selector: map[string]string{
|
||||||
|
"foo": "bar",
|
||||||
|
"baz": "blah",
|
||||||
|
},
|
||||||
|
Ports: []api.ServicePort{
|
||||||
|
{
|
||||||
|
Name: "default",
|
||||||
|
Port: 80,
|
||||||
|
Protocol: "TCP",
|
||||||
|
TargetPort: util.NewIntOrStringFromInt(1234),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
generator := ServiceGenerator{}
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
obj, err := generator.Generate(test.params)
|
obj, err := test.generator.Generate(test.params)
|
||||||
if !reflect.DeepEqual(obj, &test.expected) {
|
if !reflect.DeepEqual(obj, &test.expected) {
|
||||||
t.Errorf("expected:\n%#v\ngot\n%#v\n", &test.expected, obj)
|
t.Errorf("expected:\n%#v\ngot\n%#v\n", &test.expected, obj)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user