mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +00:00
kubectl: move printObjectSpecificMessage in factory
This commit is contained in:
parent
3b2b647409
commit
3cbb6b0104
@ -334,6 +334,7 @@ func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
|
|||||||
f.ProtocolsForObject = rf.ProtocolsForObject
|
f.ProtocolsForObject = rf.ProtocolsForObject
|
||||||
f.LabelsForObject = rf.LabelsForObject
|
f.LabelsForObject = rf.LabelsForObject
|
||||||
f.CanBeExposed = rf.CanBeExposed
|
f.CanBeExposed = rf.CanBeExposed
|
||||||
|
f.PrintObjectSpecificMessage = rf.PrintObjectSpecificMessage
|
||||||
return f, t, testapi.Default.Codec()
|
return f, t, testapi.Default.Codec()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,17 +19,13 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
|
||||||
"k8s.io/kubernetes/pkg/api/service"
|
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/kubectl"
|
"k8s.io/kubernetes/pkg/kubectl"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
|
// CreateOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
|
||||||
@ -140,7 +136,7 @@ func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *C
|
|||||||
count++
|
count++
|
||||||
shortOutput := cmdutil.GetFlagString(cmd, "output") == "name"
|
shortOutput := cmdutil.GetFlagString(cmd, "output") == "name"
|
||||||
if !shortOutput {
|
if !shortOutput {
|
||||||
printObjectSpecificMessage(info.Object, out)
|
f.PrintObjectSpecificMessage(info.Object, out)
|
||||||
}
|
}
|
||||||
cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created")
|
cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "created")
|
||||||
return nil
|
return nil
|
||||||
@ -154,49 +150,6 @@ func RunCreate(f *cmdutil.Factory, cmd *cobra.Command, out io.Writer, options *C
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func printObjectSpecificMessage(obj runtime.Object, out io.Writer) {
|
|
||||||
switch obj := obj.(type) {
|
|
||||||
case *api.Service:
|
|
||||||
if obj.Spec.Type == api.ServiceTypeNodePort {
|
|
||||||
msg := fmt.Sprintf(
|
|
||||||
`You have exposed your service on an external port on all nodes in your
|
|
||||||
cluster. If you want to expose this service to the external internet, you may
|
|
||||||
need to set up firewall rules for the service port(s) (%s) to serve traffic.
|
|
||||||
|
|
||||||
See http://releases.k8s.io/HEAD/docs/user-guide/services-firewalls.md for more details.
|
|
||||||
`,
|
|
||||||
makePortsString(obj.Spec.Ports, true))
|
|
||||||
out.Write([]byte(msg))
|
|
||||||
}
|
|
||||||
|
|
||||||
_, ok := obj.Annotations[service.AnnotationLoadBalancerSourceRangesKey]
|
|
||||||
if ok {
|
|
||||||
msg := fmt.Sprintf(
|
|
||||||
`You are using service annotation [service.beta.kubernetes.io/load-balancer-source-ranges].
|
|
||||||
It has been promoted to field [loadBalancerSourceRanges] in service spec. This annotation will be deprecated in the future.
|
|
||||||
Please use the loadBalancerSourceRanges field instead.
|
|
||||||
|
|
||||||
See http://releases.k8s.io/HEAD/docs/user-guide/services-firewalls.md for more details.
|
|
||||||
`)
|
|
||||||
out.Write([]byte(msg))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makePortsString(ports []api.ServicePort, useNodePort bool) string {
|
|
||||||
pieces := make([]string, len(ports))
|
|
||||||
for ix := range ports {
|
|
||||||
var port int32
|
|
||||||
if useNodePort {
|
|
||||||
port = ports[ix].NodePort
|
|
||||||
} else {
|
|
||||||
port = ports[ix].Port
|
|
||||||
}
|
|
||||||
pieces[ix] = fmt.Sprintf("%s:%d", strings.ToLower(string(ports[ix].Protocol)), port)
|
|
||||||
}
|
|
||||||
return strings.Join(pieces, ",")
|
|
||||||
}
|
|
||||||
|
|
||||||
// createAndRefresh creates an object from input info and refreshes info with that object
|
// createAndRefresh creates an object from input info and refreshes info with that object
|
||||||
func createAndRefresh(info *resource.Info) error {
|
func createAndRefresh(info *resource.Info) error {
|
||||||
obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object)
|
obj, err := resource.NewHelper(info.Client, info.Mapping).Create(info.Namespace, true, info.Object)
|
||||||
|
@ -21,9 +21,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
|
||||||
"k8s.io/kubernetes/pkg/client/unversioned/fake"
|
"k8s.io/kubernetes/pkg/client/unversioned/fake"
|
||||||
"k8s.io/kubernetes/pkg/runtime"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExtraArgsFail(t *testing.T) {
|
func TestExtraArgsFail(t *testing.T) {
|
||||||
@ -136,95 +134,3 @@ func TestCreateDirectory(t *testing.T) {
|
|||||||
t.Errorf("unexpected output: %s", buf.String())
|
t.Errorf("unexpected output: %s", buf.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPrintObjectSpecificMessage(t *testing.T) {
|
|
||||||
initTestErrorHandler(t)
|
|
||||||
tests := []struct {
|
|
||||||
obj runtime.Object
|
|
||||||
expectOutput bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
obj: &api.Service{},
|
|
||||||
expectOutput: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
obj: &api.Pod{},
|
|
||||||
expectOutput: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
obj: &api.Service{Spec: api.ServiceSpec{Type: api.ServiceTypeLoadBalancer}},
|
|
||||||
expectOutput: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
obj: &api.Service{Spec: api.ServiceSpec{Type: api.ServiceTypeNodePort}},
|
|
||||||
expectOutput: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
buff := &bytes.Buffer{}
|
|
||||||
printObjectSpecificMessage(test.obj, buff)
|
|
||||||
if test.expectOutput && buff.Len() == 0 {
|
|
||||||
t.Errorf("Expected output, saw none for %v", test.obj)
|
|
||||||
}
|
|
||||||
if !test.expectOutput && buff.Len() > 0 {
|
|
||||||
t.Errorf("Expected no output, saw %s for %v", buff.String(), test.obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMakePortsString(t *testing.T) {
|
|
||||||
initTestErrorHandler(t)
|
|
||||||
tests := []struct {
|
|
||||||
ports []api.ServicePort
|
|
||||||
useNodePort bool
|
|
||||||
expectedOutput string
|
|
||||||
}{
|
|
||||||
{ports: nil, expectedOutput: ""},
|
|
||||||
{ports: []api.ServicePort{}, expectedOutput: ""},
|
|
||||||
{ports: []api.ServicePort{
|
|
||||||
{
|
|
||||||
Port: 80,
|
|
||||||
Protocol: "TCP",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedOutput: "tcp:80",
|
|
||||||
},
|
|
||||||
{ports: []api.ServicePort{
|
|
||||||
{
|
|
||||||
Port: 80,
|
|
||||||
Protocol: "TCP",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Port: 8080,
|
|
||||||
Protocol: "UDP",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Port: 9000,
|
|
||||||
Protocol: "TCP",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
expectedOutput: "tcp:80,udp:8080,tcp:9000",
|
|
||||||
},
|
|
||||||
{ports: []api.ServicePort{
|
|
||||||
{
|
|
||||||
Port: 80,
|
|
||||||
NodePort: 9090,
|
|
||||||
Protocol: "TCP",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Port: 8080,
|
|
||||||
NodePort: 80,
|
|
||||||
Protocol: "UDP",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
useNodePort: true,
|
|
||||||
expectedOutput: "tcp:9090,udp:80",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, test := range tests {
|
|
||||||
output := makePortsString(test.ports, test.useNodePort)
|
|
||||||
if output != test.expectedOutput {
|
|
||||||
t.Errorf("expected: %s, saw: %s.", test.expectedOutput, output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -151,7 +151,7 @@ func RunReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
info.Refresh(obj, true)
|
info.Refresh(obj, true)
|
||||||
printObjectSpecificMessage(obj, out)
|
f.PrintObjectSpecificMessage(obj, out)
|
||||||
cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "replaced")
|
cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "replaced")
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
@ -244,7 +244,7 @@ func forceReplace(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []
|
|||||||
|
|
||||||
count++
|
count++
|
||||||
info.Refresh(obj, true)
|
info.Refresh(obj, true)
|
||||||
printObjectSpecificMessage(obj, out)
|
f.PrintObjectSpecificMessage(obj, out)
|
||||||
cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "replaced")
|
cmdutil.PrintSuccess(mapper, shortOutput, out, info.Mapping.Resource, info.Name, "replaced")
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
@ -39,6 +39,7 @@ import (
|
|||||||
"k8s.io/kubernetes/federation/apis/federation"
|
"k8s.io/kubernetes/federation/apis/federation"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/api/meta"
|
"k8s.io/kubernetes/pkg/api/meta"
|
||||||
|
"k8s.io/kubernetes/pkg/api/service"
|
||||||
"k8s.io/kubernetes/pkg/api/unversioned"
|
"k8s.io/kubernetes/pkg/api/unversioned"
|
||||||
"k8s.io/kubernetes/pkg/api/validation"
|
"k8s.io/kubernetes/pkg/api/validation"
|
||||||
"k8s.io/kubernetes/pkg/apimachinery"
|
"k8s.io/kubernetes/pkg/apimachinery"
|
||||||
@ -147,6 +148,8 @@ type Factory struct {
|
|||||||
// can range over in order to determine if the user has specified an editor
|
// can range over in order to determine if the user has specified an editor
|
||||||
// of their choice.
|
// of their choice.
|
||||||
EditorEnvs func() []string
|
EditorEnvs func() []string
|
||||||
|
// PrintObjectSpecificMessage prints object-specific messages on the provided writer
|
||||||
|
PrintObjectSpecificMessage func(obj runtime.Object, out io.Writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -747,6 +750,33 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
|||||||
EditorEnvs: func() []string {
|
EditorEnvs: func() []string {
|
||||||
return []string{"KUBE_EDITOR", "EDITOR"}
|
return []string{"KUBE_EDITOR", "EDITOR"}
|
||||||
},
|
},
|
||||||
|
PrintObjectSpecificMessage: func(obj runtime.Object, out io.Writer) {
|
||||||
|
switch obj := obj.(type) {
|
||||||
|
case *api.Service:
|
||||||
|
if obj.Spec.Type == api.ServiceTypeNodePort {
|
||||||
|
msg := fmt.Sprintf(
|
||||||
|
`You have exposed your service on an external port on all nodes in your
|
||||||
|
cluster. If you want to expose this service to the external internet, you may
|
||||||
|
need to set up firewall rules for the service port(s) (%s) to serve traffic.
|
||||||
|
|
||||||
|
See http://releases.k8s.io/HEAD/docs/user-guide/services-firewalls.md for more details.
|
||||||
|
`,
|
||||||
|
makePortsString(obj.Spec.Ports, true))
|
||||||
|
out.Write([]byte(msg))
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, ok := obj.Annotations[service.AnnotationLoadBalancerSourceRangesKey]; ok {
|
||||||
|
msg := fmt.Sprintf(
|
||||||
|
`You are using service annotation [service.beta.kubernetes.io/load-balancer-source-ranges].
|
||||||
|
It has been promoted to field [loadBalancerSourceRanges] in service spec. This annotation will be deprecated in the future.
|
||||||
|
Please use the loadBalancerSourceRanges field instead.
|
||||||
|
|
||||||
|
See http://releases.k8s.io/HEAD/docs/user-guide/services-firewalls.md for more details.
|
||||||
|
`)
|
||||||
|
out.Write([]byte(msg))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -825,6 +855,20 @@ func (f *Factory) BindExternalFlags(flags *pflag.FlagSet) {
|
|||||||
flags.AddGoFlagSet(flag.CommandLine)
|
flags.AddGoFlagSet(flag.CommandLine)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makePortsString(ports []api.ServicePort, useNodePort bool) string {
|
||||||
|
pieces := make([]string, len(ports))
|
||||||
|
for ix := range ports {
|
||||||
|
var port int32
|
||||||
|
if useNodePort {
|
||||||
|
port = ports[ix].NodePort
|
||||||
|
} else {
|
||||||
|
port = ports[ix].Port
|
||||||
|
}
|
||||||
|
pieces[ix] = fmt.Sprintf("%s:%d", strings.ToLower(string(ports[ix].Protocol)), port)
|
||||||
|
}
|
||||||
|
return strings.Join(pieces, ",")
|
||||||
|
}
|
||||||
|
|
||||||
func getPorts(spec api.PodSpec) []string {
|
func getPorts(spec api.PodSpec) []string {
|
||||||
result := []string{}
|
result := []string{}
|
||||||
for _, container := range spec.Containers {
|
for _, container := range spec.Containers {
|
||||||
|
@ -623,3 +623,94 @@ func TestGetFirstPod(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestPrintObjectSpecificMessage(t *testing.T) {
|
||||||
|
f := NewFactory(nil)
|
||||||
|
tests := []struct {
|
||||||
|
obj runtime.Object
|
||||||
|
expectOutput bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
obj: &api.Service{},
|
||||||
|
expectOutput: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: &api.Pod{},
|
||||||
|
expectOutput: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: &api.Service{Spec: api.ServiceSpec{Type: api.ServiceTypeLoadBalancer}},
|
||||||
|
expectOutput: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
obj: &api.Service{Spec: api.ServiceSpec{Type: api.ServiceTypeNodePort}},
|
||||||
|
expectOutput: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
buff := &bytes.Buffer{}
|
||||||
|
f.PrintObjectSpecificMessage(test.obj, buff)
|
||||||
|
if test.expectOutput && buff.Len() == 0 {
|
||||||
|
t.Errorf("Expected output, saw none for %v", test.obj)
|
||||||
|
}
|
||||||
|
if !test.expectOutput && buff.Len() > 0 {
|
||||||
|
t.Errorf("Expected no output, saw %s for %v", buff.String(), test.obj)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMakePortsString(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
ports []api.ServicePort
|
||||||
|
useNodePort bool
|
||||||
|
expectedOutput string
|
||||||
|
}{
|
||||||
|
{ports: nil, expectedOutput: ""},
|
||||||
|
{ports: []api.ServicePort{}, expectedOutput: ""},
|
||||||
|
{ports: []api.ServicePort{
|
||||||
|
{
|
||||||
|
Port: 80,
|
||||||
|
Protocol: "TCP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedOutput: "tcp:80",
|
||||||
|
},
|
||||||
|
{ports: []api.ServicePort{
|
||||||
|
{
|
||||||
|
Port: 80,
|
||||||
|
Protocol: "TCP",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Port: 8080,
|
||||||
|
Protocol: "UDP",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Port: 9000,
|
||||||
|
Protocol: "TCP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedOutput: "tcp:80,udp:8080,tcp:9000",
|
||||||
|
},
|
||||||
|
{ports: []api.ServicePort{
|
||||||
|
{
|
||||||
|
Port: 80,
|
||||||
|
NodePort: 9090,
|
||||||
|
Protocol: "TCP",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Port: 8080,
|
||||||
|
NodePort: 80,
|
||||||
|
Protocol: "UDP",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
useNodePort: true,
|
||||||
|
expectedOutput: "tcp:9090,udp:80",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, test := range tests {
|
||||||
|
output := makePortsString(test.ports, test.useNodePort)
|
||||||
|
if output != test.expectedOutput {
|
||||||
|
t.Errorf("expected: %s, saw: %s.", test.expectedOutput, output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user