Unverified Commit 98bab89f authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #63927 from deads2k/cli-60-factory-prune

Automatic merge from submit-queue (batch tested with PRs 63871, 63927, 63966, 63957, 63844). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>. start splitting polymorphic functions out of the factory the polymorphic behavior in `kubectl` has been gathered in the factory, but with the new kubeconfigflags and interfaces, it can actually be re-written as a set of helper calls. These functions are special. They are indications of areas of flexibility that we eventually need to build generically. In addition, unit tests make heavy use of injection. For these reasons we aren't inlining them. Instead we'll extra to a polymorphic package and have them as assignable functions for mocking. Individual commands should support injection for cleaner mocking and we'll be able to use the package to hunt internal dependencies. @kubernetes/sig-cli-maintainers @soltysh @juanvallejo ```release-note NONE ```
parents 091b811a eabfcfaa
...@@ -205,6 +205,7 @@ filegroup( ...@@ -205,6 +205,7 @@ filegroup(
"//pkg/kubectl/genericclioptions:all-srcs", "//pkg/kubectl/genericclioptions:all-srcs",
"//pkg/kubectl/metricsutil:all-srcs", "//pkg/kubectl/metricsutil:all-srcs",
"//pkg/kubectl/plugins:all-srcs", "//pkg/kubectl/plugins:all-srcs",
"//pkg/kubectl/polymorphichelpers:all-srcs",
"//pkg/kubectl/proxy:all-srcs", "//pkg/kubectl/proxy:all-srcs",
"//pkg/kubectl/scheme:all-srcs", "//pkg/kubectl/scheme:all-srcs",
"//pkg/kubectl/util:all-srcs", "//pkg/kubectl/util:all-srcs",
......
...@@ -82,6 +82,7 @@ go_library( ...@@ -82,6 +82,7 @@ go_library(
"//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library",
"//pkg/kubectl/metricsutil:go_default_library", "//pkg/kubectl/metricsutil:go_default_library",
"//pkg/kubectl/plugins:go_default_library", "//pkg/kubectl/plugins:go_default_library",
"//pkg/kubectl/polymorphichelpers:go_default_library",
"//pkg/kubectl/proxy:go_default_library", "//pkg/kubectl/proxy:go_default_library",
"//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/scheme:go_default_library",
"//pkg/kubectl/util:go_default_library", "//pkg/kubectl/util:go_default_library",
...@@ -193,6 +194,7 @@ go_test( ...@@ -193,6 +194,7 @@ go_test(
"//pkg/apis/batch:go_default_library", "//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/create:go_default_library", "//pkg/kubectl/cmd/create:go_default_library",
"//pkg/kubectl/cmd/testing:go_default_library", "//pkg/kubectl/cmd/testing:go_default_library",
...@@ -201,6 +203,7 @@ go_test( ...@@ -201,6 +203,7 @@ go_test(
"//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library",
"//pkg/kubectl/plugins:go_default_library", "//pkg/kubectl/plugins:go_default_library",
"//pkg/kubectl/polymorphichelpers:go_default_library",
"//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/scheme:go_default_library",
"//pkg/kubectl/util/i18n:go_default_library", "//pkg/kubectl/util/i18n:go_default_library",
"//pkg/kubectl/util/term:go_default_library", "//pkg/kubectl/util/term:go_default_library",
......
...@@ -113,7 +113,7 @@ func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Fact ...@@ -113,7 +113,7 @@ func (o *ApiResourcesOptions) RunApiResources(cmd *cobra.Command, f cmdutil.Fact
w := printers.GetNewTabWriter(o.Out) w := printers.GetNewTabWriter(o.Out)
defer w.Flush() defer w.Flush()
discoveryclient, err := f.DiscoveryClient() discoveryclient, err := f.ToDiscoveryClient()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -65,7 +65,7 @@ func NewCmdApiVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) ...@@ -65,7 +65,7 @@ func NewCmdApiVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams)
func (o *ApiVersionsOptions) Complete(f cmdutil.Factory) error { func (o *ApiVersionsOptions) Complete(f cmdutil.Factory) error {
var err error var err error
o.discoveryClient, err = f.DiscoveryClient() o.discoveryClient, err = f.ToDiscoveryClient()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -219,7 +219,7 @@ func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { ...@@ -219,7 +219,7 @@ func (o *ApplyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
o.ClientSetFunc = f.ClientSet o.ClientSetFunc = f.ClientSet
o.Validator, err = f.Validator(cmdutil.GetFlagBool(cmd, "validate")) o.Validator, err = f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
o.Builder = f.NewBuilder() o.Builder = f.NewBuilder()
o.Mapper, err = f.RESTMapper() o.Mapper, err = f.ToRESTMapper()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -177,7 +177,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [ ...@@ -177,7 +177,7 @@ func (p *AttachOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn [
p.SuggestedCmdUsage = fmt.Sprintf("Use '%s describe pod/%s -n %s' to see all of the containers in this pod.", fullCmdName, p.PodName, p.Namespace) p.SuggestedCmdUsage = fmt.Sprintf("Use '%s describe pod/%s -n %s' to see all of the containers in this pod.", fullCmdName, p.PodName, p.Namespace)
} }
config, err := f.ClientConfig() config, err := f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -125,7 +125,7 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error { ...@@ -125,7 +125,7 @@ func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error {
break break
} }
resourceTokens := strings.SplitN(args[1], "/", 2) resourceTokens := strings.SplitN(args[1], "/", 2)
restMapper, err := f.RESTMapper() restMapper, err := f.ToRESTMapper()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -76,7 +76,7 @@ func NewCmdClusterInfo(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) ...@@ -76,7 +76,7 @@ func NewCmdClusterInfo(f cmdutil.Factory, ioStreams genericclioptions.IOStreams)
func (o *ClusterInfoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { func (o *ClusterInfoOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
var err error var err error
o.Client, err = f.ClientConfig() o.Client, err = f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -26,14 +26,13 @@ import ( ...@@ -26,14 +26,13 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
"k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/printers"
) )
...@@ -46,10 +45,11 @@ type ClusterInfoDumpOptions struct { ...@@ -46,10 +45,11 @@ type ClusterInfoDumpOptions struct {
AllNamespaces bool AllNamespaces bool
Namespaces []string Namespaces []string
timeout time.Duration Timeout time.Duration
clientset internalclientset.Interface Clientset internalclientset.Interface
namespace string Namespace string
logsForObject func(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) RESTClientGetter genericclioptions.RESTClientGetter
LogsForObject polymorphichelpers.LogsForObjectFunc
genericclioptions.IOStreams genericclioptions.IOStreams
} }
...@@ -126,25 +126,27 @@ func (o *ClusterInfoDumpOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) ...@@ -126,25 +126,27 @@ func (o *ClusterInfoDumpOptions) Complete(f cmdutil.Factory, cmd *cobra.Command)
o.PrintFlags.OutputFormat = &jsonOutputFmt o.PrintFlags.OutputFormat = &jsonOutputFmt
o.PrintObj = printer.PrintObj o.PrintObj = printer.PrintObj
o.timeout, err = cmdutil.GetPodRunningTimeoutFlag(cmd) o.Timeout, err = cmdutil.GetPodRunningTimeoutFlag(cmd)
if err != nil { if err != nil {
return err return err
} }
o.clientset, err = f.ClientSet() o.Clientset, err = f.ClientSet()
if err != nil { if err != nil {
return err return err
} }
o.namespace, _, err = f.DefaultNamespace() o.Namespace, _, err = f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
} }
o.logsForObject = f.LogsForObject // TODO this should eventually just be the completed kubeconfigflag struct
o.RESTClientGetter = f
o.LogsForObject = polymorphichelpers.LogsForObjectFn
return nil return nil
} }
func (o *ClusterInfoDumpOptions) Run() error { func (o *ClusterInfoDumpOptions) Run() error {
nodes, err := o.clientset.Core().Nodes().List(metav1.ListOptions{}) nodes, err := o.Clientset.Core().Nodes().List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -155,7 +157,7 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -155,7 +157,7 @@ func (o *ClusterInfoDumpOptions) Run() error {
var namespaces []string var namespaces []string
if o.AllNamespaces { if o.AllNamespaces {
namespaceList, err := o.clientset.Core().Namespaces().List(metav1.ListOptions{}) namespaceList, err := o.Clientset.Core().Namespaces().List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -166,14 +168,14 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -166,14 +168,14 @@ func (o *ClusterInfoDumpOptions) Run() error {
if len(o.Namespaces) == 0 { if len(o.Namespaces) == 0 {
namespaces = []string{ namespaces = []string{
metav1.NamespaceSystem, metav1.NamespaceSystem,
o.namespace, o.Namespace,
} }
} }
} }
for _, namespace := range namespaces { for _, namespace := range namespaces {
// TODO: this is repetitive in the extreme. Use reflection or // TODO: this is repetitive in the extreme. Use reflection or
// something to make this a for loop. // something to make this a for loop.
events, err := o.clientset.Core().Events(namespace).List(metav1.ListOptions{}) events, err := o.Clientset.Core().Events(namespace).List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -181,7 +183,7 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -181,7 +183,7 @@ func (o *ClusterInfoDumpOptions) Run() error {
return err return err
} }
rcs, err := o.clientset.Core().ReplicationControllers(namespace).List(metav1.ListOptions{}) rcs, err := o.Clientset.Core().ReplicationControllers(namespace).List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -189,7 +191,7 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -189,7 +191,7 @@ func (o *ClusterInfoDumpOptions) Run() error {
return err return err
} }
svcs, err := o.clientset.Core().Services(namespace).List(metav1.ListOptions{}) svcs, err := o.Clientset.Core().Services(namespace).List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -197,7 +199,7 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -197,7 +199,7 @@ func (o *ClusterInfoDumpOptions) Run() error {
return err return err
} }
sets, err := o.clientset.Extensions().DaemonSets(namespace).List(metav1.ListOptions{}) sets, err := o.Clientset.Extensions().DaemonSets(namespace).List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -205,7 +207,7 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -205,7 +207,7 @@ func (o *ClusterInfoDumpOptions) Run() error {
return err return err
} }
deps, err := o.clientset.Extensions().Deployments(namespace).List(metav1.ListOptions{}) deps, err := o.Clientset.Extensions().Deployments(namespace).List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -213,7 +215,7 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -213,7 +215,7 @@ func (o *ClusterInfoDumpOptions) Run() error {
return err return err
} }
rps, err := o.clientset.Extensions().ReplicaSets(namespace).List(metav1.ListOptions{}) rps, err := o.Clientset.Extensions().ReplicaSets(namespace).List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -221,7 +223,7 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -221,7 +223,7 @@ func (o *ClusterInfoDumpOptions) Run() error {
return err return err
} }
pods, err := o.clientset.Core().Pods(namespace).List(metav1.ListOptions{}) pods, err := o.Clientset.Core().Pods(namespace).List(metav1.ListOptions{})
if err != nil { if err != nil {
return err return err
} }
...@@ -234,7 +236,7 @@ func (o *ClusterInfoDumpOptions) Run() error { ...@@ -234,7 +236,7 @@ func (o *ClusterInfoDumpOptions) Run() error {
writer.Write([]byte(fmt.Sprintf("==== START logs for container %s of pod %s/%s ====\n", container.Name, pod.Namespace, pod.Name))) writer.Write([]byte(fmt.Sprintf("==== START logs for container %s of pod %s/%s ====\n", container.Name, pod.Namespace, pod.Name)))
defer writer.Write([]byte(fmt.Sprintf("==== END logs for container %s of pod %s/%s ====\n", container.Name, pod.Namespace, pod.Name))) defer writer.Write([]byte(fmt.Sprintf("==== END logs for container %s of pod %s/%s ====\n", container.Name, pod.Namespace, pod.Name)))
request, err := o.logsForObject(pod, &api.PodLogOptions{Container: container.Name}, timeout) request, err := o.LogsForObject(o.RESTClientGetter, pod, &api.PodLogOptions{Container: container.Name}, timeout)
if err != nil { if err != nil {
// Print error and return. // Print error and return.
writer.Write([]byte(fmt.Sprintf("Create log request error: %s\n", err.Error()))) writer.Write([]byte(fmt.Sprintf("Create log request error: %s\n", err.Error())))
......
...@@ -154,7 +154,7 @@ func (o *CopyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { ...@@ -154,7 +154,7 @@ func (o *CopyOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
return err return err
} }
o.ClientConfig, err = f.ClientConfig() o.ClientConfig, err = f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -395,7 +395,7 @@ func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command ...@@ -395,7 +395,7 @@ func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command
return err return err
} }
o.Mapper, err = f.RESTMapper() o.Mapper, err = f.ToRESTMapper()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -438,7 +438,7 @@ func TestClusterRoleValidate(t *testing.T) { ...@@ -438,7 +438,7 @@ func TestClusterRoleValidate(t *testing.T) {
for name, test := range tests { for name, test := range tests {
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {
var err error var err error
test.clusterRoleOptions.Mapper, err = tf.RESTMapper() test.clusterRoleOptions.Mapper, err = tf.ToRESTMapper()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -206,7 +206,7 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args ...@@ -206,7 +206,7 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
o.ResourceNames = resourceNames o.ResourceNames = resourceNames
// Complete other options for Run. // Complete other options for Run.
o.Mapper, err = f.RESTMapper() o.Mapper, err = f.ToRESTMapper()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -340,7 +340,7 @@ func TestValidate(t *testing.T) { ...@@ -340,7 +340,7 @@ func TestValidate(t *testing.T) {
for name, test := range tests { for name, test := range tests {
var err error var err error
test.roleOptions.Mapper, err = tf.RESTMapper() test.roleOptions.Mapper, err = tf.ToRESTMapper()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -189,7 +189,7 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Co ...@@ -189,7 +189,7 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Co
} }
o.Result = r o.Result = r
o.Mapper, err = f.RESTMapper() o.Mapper, err = f.ToRESTMapper()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -399,7 +399,7 @@ func NewDownloader(f cmdutil.Factory) (*Downloader, error) { ...@@ -399,7 +399,7 @@ func NewDownloader(f cmdutil.Factory) (*Downloader, error) {
var err error var err error
var d Downloader var d Downloader
d.mapper, err = f.RESTMapper() d.mapper, err = f.ToRESTMapper()
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -180,7 +180,7 @@ func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []s ...@@ -180,7 +180,7 @@ func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []s
p.SuggestedCmdUsage = fmt.Sprintf("Use '%s describe pod/%s -n %s' to see all of the containers in this pod.", p.FullCmdName, p.PodName, p.Namespace) p.SuggestedCmdUsage = fmt.Sprintf("Use '%s describe pod/%s -n %s' to see all of the containers in this pod.", p.FullCmdName, p.PodName, p.Namespace)
} }
config, err := f.ClientConfig() config, err := f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -92,7 +92,7 @@ func NewCmdExplain(parent string, f cmdutil.Factory, streams genericclioptions.I ...@@ -92,7 +92,7 @@ func NewCmdExplain(parent string, f cmdutil.Factory, streams genericclioptions.I
func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { func (o *ExplainOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
var err error var err error
o.Mapper, err = f.RESTMapper() o.Mapper, err = f.ToRESTMapper()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -195,7 +195,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e ...@@ -195,7 +195,7 @@ func (o *ExposeServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) e
o.MapBasedSelectorForObject = f.MapBasedSelectorForObject o.MapBasedSelectorForObject = f.MapBasedSelectorForObject
o.PortsForObject = f.PortsForObject o.PortsForObject = f.PortsForObject
o.ProtocolsForObject = f.ProtocolsForObject o.ProtocolsForObject = f.ProtocolsForObject
o.Mapper, err = f.RESTMapper() o.Mapper, err = f.ToRESTMapper()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -26,16 +26,15 @@ import ( ...@@ -26,16 +26,15 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
restclient "k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/core/validation" "k8s.io/kubernetes/pkg/apis/core/validation"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/util" "k8s.io/kubernetes/pkg/kubectl/util"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
) )
...@@ -82,13 +81,10 @@ type LogsOptions struct { ...@@ -82,13 +81,10 @@ type LogsOptions struct {
AllContainers bool AllContainers bool
Options runtime.Object Options runtime.Object
Mapper meta.RESTMapper Object runtime.Object
Typer runtime.ObjectTyper GetPodTimeout time.Duration
Decoder runtime.Decoder RESTClientGetter genericclioptions.RESTClientGetter
LogsForObject polymorphichelpers.LogsForObjectFunc
Object runtime.Object
GetPodTimeout time.Duration
LogsForObject func(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error)
genericclioptions.IOStreams genericclioptions.IOStreams
} }
...@@ -196,7 +192,8 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []str ...@@ -196,7 +192,8 @@ func (o *LogsOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []str
return err return err
} }
o.Options = logOptions o.Options = logOptions
o.LogsForObject = f.LogsForObject o.RESTClientGetter = f
o.LogsForObject = polymorphichelpers.LogsForObjectFn
if len(selector) != 0 { if len(selector) != 0 {
if logOptions.Follow { if logOptions.Follow {
...@@ -286,7 +283,7 @@ func (o LogsOptions) getPodLogs(pod *api.Pod) error { ...@@ -286,7 +283,7 @@ func (o LogsOptions) getPodLogs(pod *api.Pod) error {
} }
func (o LogsOptions) getLogs(obj runtime.Object) error { func (o LogsOptions) getLogs(obj runtime.Object) error {
req, err := o.LogsForObject(obj, o.Options, o.GetPodTimeout) req, err := o.LogsForObject(o.RESTClientGetter, obj, o.Options, o.GetPodTimeout)
if err != nil { if err != nil {
return err return err
} }
......
...@@ -18,19 +18,27 @@ package cmd ...@@ -18,19 +18,27 @@ package cmd
import ( import (
"bytes" "bytes"
"errors"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings" "strings"
"testing" "testing"
"time"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"fmt"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake" "k8s.io/client-go/rest/fake"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing" cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
) )
...@@ -74,6 +82,16 @@ func TestLog(t *testing.T) { ...@@ -74,6 +82,16 @@ func TestLog(t *testing.T) {
} }
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfigVal = defaultClientConfig() tf.ClientConfigVal = defaultClientConfig()
oldLogFn := polymorphichelpers.LogsForObjectFn
defer func() {
polymorphichelpers.LogsForObjectFn = oldLogFn
}()
clientset, err := tf.ClientSet()
if err != nil {
t.Fatal(err)
}
polymorphichelpers.LogsForObjectFn = logTestMock{client: clientset}.logsForObject
streams, _, buf, _ := genericclioptions.NewTestIOStreams() streams, _, buf, _ := genericclioptions.NewTestIOStreams()
cmd := NewCmdLogs(tf, streams) cmd := NewCmdLogs(tf, streams)
...@@ -221,3 +239,20 @@ func TestLogComplete(t *testing.T) { ...@@ -221,3 +239,20 @@ func TestLogComplete(t *testing.T) {
} }
} }
} }
type logTestMock struct {
client internalclientset.Interface
}
func (m logTestMock) logsForObject(restClientGetter genericclioptions.RESTClientGetter, object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) {
switch t := object.(type) {
case *api.Pod:
opts, ok := options.(*api.PodLogOptions)
if !ok {
return nil, errors.New("provided options object is not a PodLogOptions")
}
return m.client.Core().Pods(t.Namespace).GetLogs(t.Name, opts), nil
default:
return nil, fmt.Errorf("cannot get the logs from %T", object)
}
}
...@@ -220,7 +220,7 @@ func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg ...@@ -220,7 +220,7 @@ func (o *PortForwardOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
} }
o.PodClient = clientset.Core() o.PodClient = clientset.Core()
o.Config, err = f.ClientConfig() o.Config, err = f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -105,7 +105,7 @@ func RunProxy(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error { ...@@ -105,7 +105,7 @@ func RunProxy(f cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
return errors.New("Don't specify both --unix-socket and --port") return errors.New("Don't specify both --unix-socket and --port")
} }
clientConfig, err := f.ClientConfig() clientConfig, err := f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -41,6 +41,7 @@ import ( ...@@ -41,6 +41,7 @@ import (
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
"k8s.io/kubernetes/pkg/util/interrupt" "k8s.io/kubernetes/pkg/util/interrupt"
...@@ -374,7 +375,7 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e ...@@ -374,7 +375,7 @@ func (o *RunOptions) Run(f cmdutil.Factory, cmd *cobra.Command, args []string) e
Attach: &DefaultRemoteAttach{}, Attach: &DefaultRemoteAttach{},
} }
config, err := f.ClientConfig() config, err := f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
...@@ -525,13 +526,13 @@ func handleAttachPod(f cmdutil.Factory, podClient coreclient.PodsGetter, ns, nam ...@@ -525,13 +526,13 @@ func handleAttachPod(f cmdutil.Factory, podClient coreclient.PodsGetter, ns, nam
} }
// logOpts logs output from opts to the pods log. // logOpts logs output from opts to the pods log.
func logOpts(f cmdutil.Factory, pod *api.Pod, opts *AttachOptions) error { func logOpts(restClientGetter genericclioptions.RESTClientGetter, pod *api.Pod, opts *AttachOptions) error {
ctrName, err := opts.GetContainerName(pod) ctrName, err := opts.GetContainerName(pod)
if err != nil { if err != nil {
return err return err
} }
req, err := f.LogsForObject(pod, &api.PodLogOptions{Container: ctrName}, opts.GetPodTimeout) req, err := polymorphichelpers.LogsForObjectFn(restClientGetter, pod, &api.PodLogOptions{Container: ctrName}, opts.GetPodTimeout)
if err != nil { if err != nil {
return err return err
} }
...@@ -638,7 +639,7 @@ func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command ...@@ -638,7 +639,7 @@ func (o *RunOptions) createGeneratedObject(f cmdutil.Factory, cmd *cobra.Command
return nil, err return nil, err
} }
mapper, err := f.RESTMapper() mapper, err := f.ToRESTMapper()
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -10,7 +10,6 @@ go_library( ...@@ -10,7 +10,6 @@ go_library(
visibility = ["//build/visible_to:pkg_kubectl_cmd_testing_CONSUMERS"], visibility = ["//build/visible_to:pkg_kubectl_cmd_testing_CONSUMERS"],
deps = [ deps = [
"//pkg/api/legacyscheme:go_default_library", "//pkg/api/legacyscheme:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util:go_default_library",
......
...@@ -44,7 +44,6 @@ import ( ...@@ -44,7 +44,6 @@ import (
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api" clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"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"
...@@ -287,7 +286,7 @@ func (f *TestFactory) Cleanup() { ...@@ -287,7 +286,7 @@ func (f *TestFactory) Cleanup() {
os.Remove(f.tempConfigFile.Name()) os.Remove(f.tempConfigFile.Name())
} }
func (f *TestFactory) ClientConfig() (*restclient.Config, error) { func (f *TestFactory) ToRESTConfig() (*restclient.Config, error) {
return f.ClientConfigVal, nil return f.ClientConfigVal, nil
} }
...@@ -330,7 +329,7 @@ func (f *TestFactory) Command(*cobra.Command, bool) string { ...@@ -330,7 +329,7 @@ func (f *TestFactory) Command(*cobra.Command, bool) string {
} }
func (f *TestFactory) NewBuilder() *resource.Builder { func (f *TestFactory) NewBuilder() *resource.Builder {
mapper, err := f.RESTMapper() mapper, err := f.ToRESTMapper()
return resource.NewFakeBuilder( return resource.NewFakeBuilder(
func(version schema.GroupVersion) (resource.RESTClient, error) { func(version schema.GroupVersion) (resource.RESTClient, error) {
...@@ -446,24 +445,6 @@ func testRESTMapper() meta.RESTMapper { ...@@ -446,24 +445,6 @@ func testRESTMapper() meta.RESTMapper {
return expander return expander
} }
func (f *TestFactory) LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error) {
c, err := f.ClientSet()
if err != nil {
panic(err)
}
switch t := object.(type) {
case *api.Pod:
opts, ok := options.(*api.PodLogOptions)
if !ok {
return nil, errors.New("provided options object is not a PodLogOptions")
}
return c.Core().Pods(f.Namespace).GetLogs(t.Name, opts), nil
default:
return nil, fmt.Errorf("cannot get the logs from %T", object)
}
}
func (f *TestFactory) ScaleClient() (scaleclient.ScalesGetter, error) { func (f *TestFactory) ScaleClient() (scaleclient.ScalesGetter, error) {
return f.ScaleGetter, nil return f.ScaleGetter, nil
} }
......
...@@ -136,7 +136,7 @@ func (o *TopNodeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [] ...@@ -136,7 +136,7 @@ func (o *TopNodeOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
o.DiscoveryClient = clientset.DiscoveryClient o.DiscoveryClient = clientset.DiscoveryClient
config, err := f.ClientConfig() config, err := f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -131,7 +131,7 @@ func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s ...@@ -131,7 +131,7 @@ func (o *TopPodOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []s
} }
o.DiscoveryClient = clientset.DiscoveryClient o.DiscoveryClient = clientset.DiscoveryClient
config, err := f.ClientConfig() config, err := f.ToRESTConfig()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -22,13 +22,14 @@ go_library( ...@@ -22,13 +22,14 @@ go_library(
"//pkg/apis/core/v1:go_default_library", "//pkg/apis/core/v1:go_default_library",
"//pkg/apis/extensions:go_default_library", "//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/controller:go_default_library", "//pkg/controller:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library",
"//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library",
"//pkg/kubectl/cmd/util/openapi/validation:go_default_library", "//pkg/kubectl/cmd/util/openapi/validation:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/genericclioptions/resource:go_default_library", "//pkg/kubectl/genericclioptions/resource:go_default_library",
"//pkg/kubectl/polymorphichelpers:go_default_library",
"//pkg/kubectl/validation:go_default_library", "//pkg/kubectl/validation:go_default_library",
"//pkg/printers:go_default_library", "//pkg/printers:go_default_library",
"//pkg/printers/internalversion:go_default_library", "//pkg/printers/internalversion:go_default_library",
...@@ -49,13 +50,11 @@ go_library( ...@@ -49,13 +50,11 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/discovery:go_default_library", "//vendor/k8s.io/client-go/discovery:go_default_library",
"//vendor/k8s.io/client-go/dynamic:go_default_library", "//vendor/k8s.io/client-go/dynamic:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library", "//vendor/k8s.io/client-go/kubernetes:go_default_library",
...@@ -69,7 +68,6 @@ go_library( ...@@ -69,7 +68,6 @@ go_library(
go_test( go_test(
name = "go_default_test", name = "go_default_test",
srcs = [ srcs = [
"factory_object_mapping_test.go",
"factory_test.go", "factory_test.go",
"helpers_test.go", "helpers_test.go",
], ],
...@@ -77,28 +75,17 @@ go_test( ...@@ -77,28 +75,17 @@ go_test(
deps = [ deps = [
"//pkg/api/testapi:go_default_library", "//pkg/api/testapi:go_default_library",
"//pkg/api/testing:go_default_library", "//pkg/api/testing:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library", "//pkg/kubectl/genericclioptions:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library", "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library", "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library", "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/testing:go_default_library",
"//vendor/k8s.io/utils/exec:go_default_library", "//vendor/k8s.io/utils/exec:go_default_library",
], ],
) )
......
...@@ -18,7 +18,6 @@ package util ...@@ -18,7 +18,6 @@ package util
import ( import (
"fmt" "fmt"
"sort"
"strconv" "strconv"
"strings" "strings"
"time" "time"
...@@ -27,21 +26,17 @@ import ( ...@@ -27,21 +26,17 @@ import (
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
"k8s.io/client-go/dynamic" "k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
restclient "k8s.io/client-go/rest" restclient "k8s.io/client-go/rest"
scaleclient "k8s.io/client-go/scale" scaleclient "k8s.io/client-go/scale"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
apiv1 "k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
"k8s.io/kubernetes/pkg/kubectl/validation" "k8s.io/kubernetes/pkg/kubectl/validation"
"k8s.io/kubernetes/pkg/printers" "k8s.io/kubernetes/pkg/printers"
...@@ -67,8 +62,7 @@ type Factory interface { ...@@ -67,8 +62,7 @@ type Factory interface {
// Generally provides discovery, negotiation, and no-dep calls. // Generally provides discovery, negotiation, and no-dep calls.
// TODO The polymorphic calls probably deserve their own interface. // TODO The polymorphic calls probably deserve their own interface.
type ClientAccessFactory interface { type ClientAccessFactory interface {
// Returns a discovery client genericclioptions.RESTClientGetter
DiscoveryClient() (discovery.CachedDiscoveryInterface, error)
// ClientSet gives you back an internal, generated clientset // ClientSet gives you back an internal, generated clientset
ClientSet() (internalclientset.Interface, error) ClientSet() (internalclientset.Interface, error)
...@@ -79,16 +73,8 @@ type ClientAccessFactory interface { ...@@ -79,16 +73,8 @@ type ClientAccessFactory interface {
// KubernetesClientSet gives you back an external clientset // KubernetesClientSet gives you back an external clientset
KubernetesClientSet() (*kubernetes.Clientset, error) KubernetesClientSet() (*kubernetes.Clientset, error)
// Returns interfaces for dealing with arbitrary runtime.Objects.
RESTMapper() (meta.RESTMapper, error)
// Returns a RESTClient for accessing Kubernetes resources or an error. // Returns a RESTClient for accessing Kubernetes resources or an error.
RESTClient() (*restclient.RESTClient, error) RESTClient() (*restclient.RESTClient, error)
// Returns a client.Config for accessing the Kubernetes server.
ClientConfig() (*restclient.Config, error)
// BareClientConfig returns a client.Config that has NOT been negotiated. It's
// just directions to the server. People use this to build RESTMappers on top of
BareClientConfig() (*restclient.Config, error)
// NewBuilder returns an object that assists in loading objects from both disk and the server // NewBuilder returns an object that assists in loading objects from both disk and the server
// and which implements the common patterns for CLI interactions with generic resources. // and which implements the common patterns for CLI interactions with generic resources.
...@@ -153,8 +139,6 @@ type ObjectMappingFactory interface { ...@@ -153,8 +139,6 @@ type ObjectMappingFactory interface {
// Returns a Describer for displaying the specified RESTMapping type or an error. // Returns a Describer for displaying the specified RESTMapping type or an error.
Describer(mapping *meta.RESTMapping) (printers.Describer, error) Describer(mapping *meta.RESTMapping) (printers.Describer, error)
// LogsForObject returns a request for the logs associated with the provided object
LogsForObject(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error)
// Returns a HistoryViewer for viewing change history // Returns a HistoryViewer for viewing change history
HistoryViewer(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error) HistoryViewer(mapping *meta.RESTMapping) (kubectl.HistoryViewer, error)
// Returns a Rollbacker for changing the rollback version of the specified RESTMapping type or an error // Returns a Rollbacker for changing the rollback version of the specified RESTMapping type or an error
...@@ -193,7 +177,7 @@ type factory struct { ...@@ -193,7 +177,7 @@ type factory struct {
// NewFactory creates a factory with the default Kubernetes resources defined // NewFactory creates a factory with the default Kubernetes resources defined
// Receives a clientGetter capable of providing a discovery client and a REST client configuration. // Receives a clientGetter capable of providing a discovery client and a REST client configuration.
func NewFactory(clientGetter RESTClientGetter) Factory { func NewFactory(clientGetter genericclioptions.RESTClientGetter) Factory {
clientAccessFactory := NewClientAccessFactory(clientGetter) clientAccessFactory := NewClientAccessFactory(clientGetter)
objectMappingFactory := NewObjectMappingFactory(clientAccessFactory) objectMappingFactory := NewObjectMappingFactory(clientAccessFactory)
builderFactory := NewBuilderFactory(clientAccessFactory, objectMappingFactory) builderFactory := NewBuilderFactory(clientAccessFactory, objectMappingFactory)
...@@ -205,51 +189,6 @@ func NewFactory(clientGetter RESTClientGetter) Factory { ...@@ -205,51 +189,6 @@ func NewFactory(clientGetter RESTClientGetter) Factory {
} }
} }
// GetFirstPod returns a pod matching the namespace and label selector
// and the number of all pods that match the label selector.
func GetFirstPod(client coreclient.PodsGetter, namespace string, selector string, timeout time.Duration, sortBy func([]*v1.Pod) sort.Interface) (*api.Pod, int, error) {
options := metav1.ListOptions{LabelSelector: selector}
podList, err := client.Pods(namespace).List(options)
if err != nil {
return nil, 0, err
}
pods := []*v1.Pod{}
for i := range podList.Items {
pod := podList.Items[i]
externalPod := &v1.Pod{}
apiv1.Convert_core_Pod_To_v1_Pod(&pod, externalPod, nil)
pods = append(pods, externalPod)
}
if len(pods) > 0 {
sort.Sort(sortBy(pods))
internalPod := &api.Pod{}
apiv1.Convert_v1_Pod_To_core_Pod(pods[0], internalPod, nil)
return internalPod, len(podList.Items), nil
}
// Watch until we observe a pod
options.ResourceVersion = podList.ResourceVersion
w, err := client.Pods(namespace).Watch(options)
if err != nil {
return nil, 0, err
}
defer w.Stop()
condition := func(event watch.Event) (bool, error) {
return event.Type == watch.Added || event.Type == watch.Modified, nil
}
event, err := watch.Until(timeout, w, condition)
if err != nil {
return nil, 0, err
}
pod, ok := event.Object.(*api.Pod)
if !ok {
return nil, 0, fmt.Errorf("%#v is not a pod event", event)
}
return pod, 1, nil
}
func makePortsString(ports []api.ServicePort, useNodePort bool) string { func makePortsString(ports []api.ServicePort, useNodePort bool) string {
pieces := make([]string, len(ports)) pieces := make([]string, len(ports))
for ix := range ports { for ix := range ports {
......
...@@ -40,7 +40,7 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac ...@@ -40,7 +40,7 @@ func NewBuilderFactory(clientAccessFactory ClientAccessFactory, objectMappingFac
} }
func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) { func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) {
discoClient, err := f.clientAccessFactory.DiscoveryClient() discoClient, err := f.clientAccessFactory.ToDiscoveryClient()
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -49,7 +49,7 @@ func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) { ...@@ -49,7 +49,7 @@ func (f *ring2Factory) ScaleClient() (scaleclient.ScalesGetter, error) {
return nil, err return nil, err
} }
resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient) resolver := scaleclient.NewDiscoveryScaleKindResolver(discoClient)
mapper, err := f.clientAccessFactory.RESTMapper() mapper, err := f.clientAccessFactory.ToRESTMapper()
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -55,21 +55,15 @@ import ( ...@@ -55,21 +55,15 @@ import (
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource" "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
) )
type RESTClientGetter interface {
ToRESTConfig() (*restclient.Config, error)
ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error)
ToRESTMapper() (meta.RESTMapper, error)
ToRawKubeConfigLoader() clientcmd.ClientConfig
}
type ring0Factory struct { type ring0Factory struct {
clientGetter RESTClientGetter clientGetter genericclioptions.RESTClientGetter
} }
func NewClientAccessFactory(clientGetter RESTClientGetter) ClientAccessFactory { func NewClientAccessFactory(clientGetter genericclioptions.RESTClientGetter) ClientAccessFactory {
if clientGetter == nil { if clientGetter == nil {
panic("attempt to instantiate client_access_factory with nil clientGetter") panic("attempt to instantiate client_access_factory with nil clientGetter")
} }
...@@ -81,24 +75,24 @@ func NewClientAccessFactory(clientGetter RESTClientGetter) ClientAccessFactory { ...@@ -81,24 +75,24 @@ func NewClientAccessFactory(clientGetter RESTClientGetter) ClientAccessFactory {
return f return f
} }
func (f *ring0Factory) ClientConfig() (*restclient.Config, error) { func (f *ring0Factory) ToRESTConfig() (*restclient.Config, error) {
return f.clientGetter.ToRESTConfig() return f.clientGetter.ToRESTConfig()
} }
func (f *ring0Factory) RESTMapper() (meta.RESTMapper, error) { func (f *ring0Factory) ToRESTMapper() (meta.RESTMapper, error) {
return f.clientGetter.ToRESTMapper() return f.clientGetter.ToRESTMapper()
} }
func (f *ring0Factory) BareClientConfig() (*restclient.Config, error) { func (f *ring0Factory) ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error) {
return f.clientGetter.ToRESTConfig() return f.clientGetter.ToDiscoveryClient()
} }
func (f *ring0Factory) DiscoveryClient() (discovery.CachedDiscoveryInterface, error) { func (f *ring0Factory) ToRawKubeConfigLoader() clientcmd.ClientConfig {
return f.clientGetter.ToDiscoveryClient() return f.clientGetter.ToRawKubeConfigLoader()
} }
func (f *ring0Factory) KubernetesClientSet() (*kubernetes.Clientset, error) { func (f *ring0Factory) KubernetesClientSet() (*kubernetes.Clientset, error) {
clientConfig, err := f.ClientConfig() clientConfig, err := f.ToRESTConfig()
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -106,7 +100,7 @@ func (f *ring0Factory) KubernetesClientSet() (*kubernetes.Clientset, error) { ...@@ -106,7 +100,7 @@ func (f *ring0Factory) KubernetesClientSet() (*kubernetes.Clientset, error) {
} }
func (f *ring0Factory) ClientSet() (internalclientset.Interface, error) { func (f *ring0Factory) ClientSet() (internalclientset.Interface, error) {
clientConfig, err := f.ClientConfig() clientConfig, err := f.ToRESTConfig()
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -114,7 +108,7 @@ func (f *ring0Factory) ClientSet() (internalclientset.Interface, error) { ...@@ -114,7 +108,7 @@ func (f *ring0Factory) ClientSet() (internalclientset.Interface, error) {
} }
func (f *ring0Factory) DynamicClient() (dynamic.Interface, error) { func (f *ring0Factory) DynamicClient() (dynamic.Interface, error) {
clientConfig, err := f.ClientConfig() clientConfig, err := f.ToRESTConfig()
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -127,7 +121,7 @@ func (f *ring0Factory) NewBuilder() *resource.Builder { ...@@ -127,7 +121,7 @@ func (f *ring0Factory) NewBuilder() *resource.Builder {
} }
func (f *ring0Factory) RESTClient() (*restclient.RESTClient, error) { func (f *ring0Factory) RESTClient() (*restclient.RESTClient, error) {
clientConfig, err := f.ClientConfig() clientConfig, err := f.ToRESTConfig()
if err != nil { if err != nil {
return nil, err return nil, err
} }
......
...@@ -17,25 +17,14 @@ limitations under the License. ...@@ -17,25 +17,14 @@ limitations under the License.
package util package util
import ( import (
"fmt"
"sort"
"strings" "strings"
"testing" "testing"
"time"
"k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/watch"
testcore "k8s.io/client-go/testing"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions" "k8s.io/kubernetes/pkg/kubectl/genericclioptions"
) )
...@@ -187,200 +176,6 @@ func TestCanBeExposed(t *testing.T) { ...@@ -187,200 +176,6 @@ func TestCanBeExposed(t *testing.T) {
} }
} }
func newPodList(count, isUnready, isUnhealthy int, labels map[string]string) *api.PodList {
pods := []api.Pod{}
for i := 0; i < count; i++ {
newPod := api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("pod-%d", i+1),
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, i, 0, time.UTC),
Labels: labels,
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
}
pods = append(pods, newPod)
}
if isUnready > -1 && isUnready < count {
pods[isUnready].Status.Conditions[0].Status = api.ConditionFalse
}
if isUnhealthy > -1 && isUnhealthy < count {
pods[isUnhealthy].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 5}}
}
return &api.PodList{
Items: pods,
}
}
func TestGetFirstPod(t *testing.T) {
labelSet := map[string]string{"test": "selector"}
tests := []struct {
name string
podList *api.PodList
watching []watch.Event
sortBy func([]*v1.Pod) sort.Interface
expected *api.Pod
expectedNum int
expectedErr bool
}{
{
name: "kubectl logs - two ready pods",
podList: newPodList(2, -1, -1, labelSet),
sortBy: func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) },
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
},
expectedNum: 2,
},
{
name: "kubectl logs - one unhealthy, one healthy",
podList: newPodList(2, -1, 1, labelSet),
sortBy: func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) },
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-2",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 1, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
ContainerStatuses: []api.ContainerStatus{{RestartCount: 5}},
},
},
expectedNum: 2,
},
{
name: "kubectl attach - two ready pods",
podList: newPodList(2, -1, -1, labelSet),
sortBy: func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) },
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
},
expectedNum: 2,
},
{
name: "kubectl attach - wait for ready pod",
podList: newPodList(1, 1, -1, labelSet),
watching: []watch.Event{
{
Type: watch.Modified,
Object: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
},
},
},
sortBy: func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) },
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
},
expectedNum: 1,
},
}
for i := range tests {
test := tests[i]
fake := fake.NewSimpleClientset(test.podList)
if len(test.watching) > 0 {
watcher := watch.NewFake()
for _, event := range test.watching {
switch event.Type {
case watch.Added:
go watcher.Add(event.Object)
case watch.Modified:
go watcher.Modify(event.Object)
}
}
fake.PrependWatchReactor("pods", testcore.DefaultWatchReactor(watcher, nil))
}
selector := labels.Set(labelSet).AsSelector()
pod, numPods, err := GetFirstPod(fake.Core(), metav1.NamespaceDefault, selector.String(), 1*time.Minute, test.sortBy)
pod.Spec.SecurityContext = nil
if !test.expectedErr && err != nil {
t.Errorf("%s: unexpected error: %v", test.name, err)
continue
}
if test.expectedErr && err == nil {
t.Errorf("%s: expected an error", test.name)
continue
}
if test.expectedNum != numPods {
t.Errorf("%s: expected %d pods, got %d", test.name, test.expectedNum, numPods)
continue
}
if !apiequality.Semantic.DeepEqual(test.expected, pod) {
t.Errorf("%s:\nexpected pod:\n%#v\ngot:\n%#v\n\n", test.name, test.expected, pod)
}
}
}
func TestMakePortsString(t *testing.T) { func TestMakePortsString(t *testing.T) {
tests := []struct { tests := []struct {
ports []api.ServicePort ports []api.ServicePort
......
...@@ -28,6 +28,7 @@ import ( ...@@ -28,6 +28,7 @@ import (
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
"k8s.io/kubernetes/pkg/api/legacyscheme" "k8s.io/kubernetes/pkg/api/legacyscheme"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/version" "k8s.io/kubernetes/pkg/version"
) )
...@@ -37,14 +38,14 @@ const ( ...@@ -37,14 +38,14 @@ const (
// MatchVersionFlags is for setting the "match server version" function. // MatchVersionFlags is for setting the "match server version" function.
type MatchVersionFlags struct { type MatchVersionFlags struct {
Delegate RESTClientGetter Delegate genericclioptions.RESTClientGetter
RequireMatchedServerVersion bool RequireMatchedServerVersion bool
checkServerVersion sync.Once checkServerVersion sync.Once
matchesServerVersionErr error matchesServerVersionErr error
} }
var _ RESTClientGetter = &MatchVersionFlags{} var _ genericclioptions.RESTClientGetter = &MatchVersionFlags{}
func (f *MatchVersionFlags) checkMatchingServerVersion() error { func (f *MatchVersionFlags) checkMatchingServerVersion() error {
f.checkServerVersion.Do(func() { f.checkServerVersion.Do(func() {
...@@ -102,7 +103,7 @@ func (f *MatchVersionFlags) AddFlags(flags *pflag.FlagSet) { ...@@ -102,7 +103,7 @@ func (f *MatchVersionFlags) AddFlags(flags *pflag.FlagSet) {
flags.BoolVar(&f.RequireMatchedServerVersion, flagMatchBinaryVersion, f.RequireMatchedServerVersion, "Require server version to match client version") flags.BoolVar(&f.RequireMatchedServerVersion, flagMatchBinaryVersion, f.RequireMatchedServerVersion, "Require server version to match client version")
} }
func NewMatchVersionFlags(delegate RESTClientGetter) *MatchVersionFlags { func NewMatchVersionFlags(delegate genericclioptions.RESTClientGetter) *MatchVersionFlags {
return &MatchVersionFlags{ return &MatchVersionFlags{
Delegate: delegate, Delegate: delegate,
} }
......
...@@ -83,7 +83,7 @@ func NewCmdVersion(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *co ...@@ -83,7 +83,7 @@ func NewCmdVersion(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *co
func (o *VersionOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error { func (o *VersionOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
var err error var err error
o.discoveryClient, err = f.DiscoveryClient() o.discoveryClient, err = f.ToDiscoveryClient()
if err != nil { if err != nil {
return err return err
} }
......
...@@ -54,6 +54,22 @@ const ( ...@@ -54,6 +54,22 @@ const (
var defaultCacheDir = filepath.Join(homedir.HomeDir(), ".kube", "http-cache") var defaultCacheDir = filepath.Join(homedir.HomeDir(), ".kube", "http-cache")
// RESTClientGetter is an interface that the ConfigFlags describe to provide an easier way to mock for commands
// and eliminate the direct coupling to a struct type. Users may wish to duplicate this type in their own packages
// as per the golang type overlapping.
type RESTClientGetter interface {
// ToRESTConfig returns restconfig
ToRESTConfig() (*rest.Config, error)
// ToDiscoveryClient returns discovery client
ToDiscoveryClient() (discovery.CachedDiscoveryInterface, error)
// ToRESTMapper returns a restmapper
ToRESTMapper() (meta.RESTMapper, error)
// ToRawKubeConfigLoader return kubeconfig loader as-is
ToRawKubeConfigLoader() clientcmd.ClientConfig
}
var _ RESTClientGetter = &ConfigFlags{}
// ConfigFlags composes the set of values necessary // ConfigFlags composes the set of values necessary
// for obtaining a REST client config // for obtaining a REST client config
type ConfigFlags struct { type ConfigFlags struct {
......
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"helpers.go",
"interface.go",
"logsforobject.go",
],
importpath = "k8s.io/kubernetes/pkg/kubectl/polymorphichelpers",
visibility = ["//visibility:public"],
deps = [
"//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/v1:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library",
"//vendor/k8s.io/api/apps/v1:go_default_library",
"//vendor/k8s.io/api/apps/v1beta1:go_default_library",
"//vendor/k8s.io/api/apps/v1beta2:go_default_library",
"//vendor/k8s.io/api/batch/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
"helpers_test.go",
"logsforobject_test.go",
],
embed = [":go_default_library"],
deps = [
"//pkg/apis/apps:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/core:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/client/clientset_generated/internalclientset/fake:go_default_library",
"//pkg/controller:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/testing:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"fmt"
"sort"
"time"
appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1"
appsv1beta2 "k8s.io/api/apps/v1beta2"
batchv1 "k8s.io/api/batch/v1"
"k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
extensionsv1beta1 "k8s.io/api/extensions/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/kubernetes/pkg/apis/apps"
"k8s.io/kubernetes/pkg/apis/batch"
api "k8s.io/kubernetes/pkg/apis/core"
apiv1 "k8s.io/kubernetes/pkg/apis/core/v1"
"k8s.io/kubernetes/pkg/apis/extensions"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
)
// GetFirstPod returns a pod matching the namespace and label selector
// and the number of all pods that match the label selector.
func GetFirstPod(client coreclient.PodsGetter, namespace string, selector string, timeout time.Duration, sortBy func([]*v1.Pod) sort.Interface) (*api.Pod, int, error) {
options := metav1.ListOptions{LabelSelector: selector}
podList, err := client.Pods(namespace).List(options)
if err != nil {
return nil, 0, err
}
pods := []*v1.Pod{}
for i := range podList.Items {
pod := podList.Items[i]
externalPod := &v1.Pod{}
apiv1.Convert_core_Pod_To_v1_Pod(&pod, externalPod, nil)
pods = append(pods, externalPod)
}
if len(pods) > 0 {
sort.Sort(sortBy(pods))
internalPod := &api.Pod{}
apiv1.Convert_v1_Pod_To_core_Pod(pods[0], internalPod, nil)
return internalPod, len(podList.Items), nil
}
// Watch until we observe a pod
options.ResourceVersion = podList.ResourceVersion
w, err := client.Pods(namespace).Watch(options)
if err != nil {
return nil, 0, err
}
defer w.Stop()
condition := func(event watch.Event) (bool, error) {
return event.Type == watch.Added || event.Type == watch.Modified, nil
}
event, err := watch.Until(timeout, w, condition)
if err != nil {
return nil, 0, err
}
pod, ok := event.Object.(*api.Pod)
if !ok {
return nil, 0, fmt.Errorf("%#v is not a pod event", event)
}
return pod, 1, nil
}
// SelectorsForObject returns the pod label selector for a given object
func SelectorsForObject(object runtime.Object) (namespace string, selector labels.Selector, err error) {
switch t := object.(type) {
case *extensions.ReplicaSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *extensionsv1beta1.ReplicaSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1.ReplicaSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1beta2.ReplicaSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *api.ReplicationController:
namespace = t.Namespace
selector = labels.SelectorFromSet(t.Spec.Selector)
case *corev1.ReplicationController:
namespace = t.Namespace
selector = labels.SelectorFromSet(t.Spec.Selector)
case *apps.StatefulSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1.StatefulSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1beta1.StatefulSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1beta2.StatefulSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *extensions.DaemonSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *extensionsv1beta1.DaemonSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1.DaemonSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1beta2.DaemonSet:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *extensions.Deployment:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *extensionsv1beta1.Deployment:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1.Deployment:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1beta1.Deployment:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *appsv1beta2.Deployment:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *batch.Job:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *batchv1.Job:
namespace = t.Namespace
selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector)
if err != nil {
return "", nil, fmt.Errorf("invalid label selector: %v", err)
}
case *api.Service:
namespace = t.Namespace
if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 {
return "", nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name)
}
selector = labels.SelectorFromSet(t.Spec.Selector)
case *corev1.Service:
namespace = t.Namespace
if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 {
return "", nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name)
}
selector = labels.SelectorFromSet(t.Spec.Selector)
default:
return "", nil, fmt.Errorf("selector for %T not implemented", object)
}
return namespace, selector, nil
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"fmt"
"sort"
"testing"
"time"
"k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/watch"
testcore "k8s.io/client-go/testing"
api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
"k8s.io/kubernetes/pkg/controller"
)
func TestGetFirstPod(t *testing.T) {
labelSet := map[string]string{"test": "selector"}
tests := []struct {
name string
podList *api.PodList
watching []watch.Event
sortBy func([]*v1.Pod) sort.Interface
expected *api.Pod
expectedNum int
expectedErr bool
}{
{
name: "kubectl logs - two ready pods",
podList: newPodList(2, -1, -1, labelSet),
sortBy: func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) },
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
},
expectedNum: 2,
},
{
name: "kubectl logs - one unhealthy, one healthy",
podList: newPodList(2, -1, 1, labelSet),
sortBy: func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) },
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-2",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 1, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
ContainerStatuses: []api.ContainerStatus{{RestartCount: 5}},
},
},
expectedNum: 2,
},
{
name: "kubectl attach - two ready pods",
podList: newPodList(2, -1, -1, labelSet),
sortBy: func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) },
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
},
expectedNum: 2,
},
{
name: "kubectl attach - wait for ready pod",
podList: newPodList(1, 1, -1, labelSet),
watching: []watch.Event{
{
Type: watch.Modified,
Object: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
},
},
},
sortBy: func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) },
expected: &api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: "pod-1",
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, 0, 0, time.UTC),
Labels: map[string]string{"test": "selector"},
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
},
expectedNum: 1,
},
}
for i := range tests {
test := tests[i]
fake := fake.NewSimpleClientset(test.podList)
if len(test.watching) > 0 {
watcher := watch.NewFake()
for _, event := range test.watching {
switch event.Type {
case watch.Added:
go watcher.Add(event.Object)
case watch.Modified:
go watcher.Modify(event.Object)
}
}
fake.PrependWatchReactor("pods", testcore.DefaultWatchReactor(watcher, nil))
}
selector := labels.Set(labelSet).AsSelector()
pod, numPods, err := GetFirstPod(fake.Core(), metav1.NamespaceDefault, selector.String(), 1*time.Minute, test.sortBy)
pod.Spec.SecurityContext = nil
if !test.expectedErr && err != nil {
t.Errorf("%s: unexpected error: %v", test.name, err)
continue
}
if test.expectedErr && err == nil {
t.Errorf("%s: expected an error", test.name)
continue
}
if test.expectedNum != numPods {
t.Errorf("%s: expected %d pods, got %d", test.name, test.expectedNum, numPods)
continue
}
if !apiequality.Semantic.DeepEqual(test.expected, pod) {
t.Errorf("%s:\nexpected pod:\n%#v\ngot:\n%#v\n\n", test.name, test.expected, pod)
}
}
}
func newPodList(count, isUnready, isUnhealthy int, labels map[string]string) *api.PodList {
pods := []api.Pod{}
for i := 0; i < count; i++ {
newPod := api.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("pod-%d", i+1),
Namespace: metav1.NamespaceDefault,
CreationTimestamp: metav1.Date(2016, time.April, 1, 1, 0, i, 0, time.UTC),
Labels: labels,
},
Status: api.PodStatus{
Conditions: []api.PodCondition{
{
Status: api.ConditionTrue,
Type: api.PodReady,
},
},
},
}
pods = append(pods, newPod)
}
if isUnready > -1 && isUnready < count {
pods[isUnready].Status.Conditions[0].Status = api.ConditionFalse
}
if isUnhealthy > -1 && isUnhealthy < count {
pods[isUnhealthy].Status.ContainerStatuses = []api.ContainerStatus{{RestartCount: 5}}
}
return &api.PodList{
Items: pods,
}
}
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"time"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
)
// LogsForObjectFunc is a function type that can tell you how to get logs for a runtime.object
type LogsForObjectFunc func(restClientGetter genericclioptions.RESTClientGetter, object, options runtime.Object, timeout time.Duration) (*rest.Request, error)
// LogsForObjectFn gives a way to easily override the function for unit testing if needed.
var LogsForObjectFn LogsForObjectFunc = logsForObject
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package polymorphichelpers
import (
"errors"
"fmt"
"os"
"sort"
"time"
"k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
coreinternal "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
)
func logsForObject(restClientGetter genericclioptions.RESTClientGetter, object, options runtime.Object, timeout time.Duration) (*rest.Request, error) {
clientConfig, err := restClientGetter.ToRESTConfig()
if err != nil {
return nil, err
}
clientset, err := internalclientset.NewForConfig(clientConfig)
if err != nil {
return nil, err
}
return logsForObjectWithClient(clientset, object, options, timeout)
}
// this is split for easy test-ability
func logsForObjectWithClient(clientset internalclientset.Interface, object, options runtime.Object, timeout time.Duration) (*rest.Request, error) {
opts, ok := options.(*coreinternal.PodLogOptions)
if !ok {
return nil, errors.New("provided options object is not a PodLogOptions")
}
switch t := object.(type) {
case *coreinternal.Pod:
return clientset.Core().Pods(t.Namespace).GetLogs(t.Name, opts), nil
case *corev1.Pod:
return clientset.Core().Pods(t.Namespace).GetLogs(t.Name, opts), nil
}
namespace, selector, err := SelectorsForObject(object)
if err != nil {
return nil, fmt.Errorf("cannot get the logs from %T: %v", object, err)
}
sortBy := func(pods []*v1.Pod) sort.Interface { return controller.ByLogging(pods) }
pod, numPods, err := GetFirstPod(clientset.Core(), namespace, selector.String(), timeout, sortBy)
if err != nil {
return nil, err
}
if numPods > 1 {
fmt.Fprintf(os.Stderr, "Found %v pods, using pod/%v\n", numPods, pod.Name)
}
return clientset.Core().Pods(pod.Namespace).GetLogs(pod.Name, opts), nil
}
...@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and ...@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package util package polymorphichelpers
import ( import (
"reflect" "reflect"
...@@ -30,26 +30,9 @@ import ( ...@@ -30,26 +30,9 @@ import (
"k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/batch"
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/apis/extensions" "k8s.io/kubernetes/pkg/apis/extensions"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
) )
type fakeClientAccessFactory struct {
ClientAccessFactory
fakeClientset *fake.Clientset
}
func (f *fakeClientAccessFactory) ClientSet() (internalclientset.Interface, error) {
return f.fakeClientset, nil
}
func newFakeClientAccessFactory(objs []runtime.Object) *fakeClientAccessFactory {
return &fakeClientAccessFactory{
fakeClientset: fake.NewSimpleClientset(objs...),
}
}
var ( var (
podsResource = schema.GroupVersionResource{Resource: "pods"} podsResource = schema.GroupVersionResource{Resource: "pods"}
podsKind = schema.GroupVersionKind{Kind: "Pod"} podsKind = schema.GroupVersionKind{Kind: "Pod"}
...@@ -146,20 +129,19 @@ func TestLogsForObject(t *testing.T) { ...@@ -146,20 +129,19 @@ func TestLogsForObject(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
caf := newFakeClientAccessFactory(test.pods) fakeClientset := fake.NewSimpleClientset(test.pods...)
omf := NewObjectMappingFactory(caf) _, err := logsForObjectWithClient(fakeClientset, test.obj, test.opts, 20*time.Second)
_, err := omf.LogsForObject(test.obj, test.opts, 20*time.Second)
if err != nil { if err != nil {
t.Errorf("%s: unexpected error: %v", test.name, err) t.Errorf("%s: unexpected error: %v", test.name, err)
continue continue
} }
for i := range test.actions { for i := range test.actions {
if len(caf.fakeClientset.Actions()) < i { if len(fakeClientset.Actions()) < i {
t.Errorf("%s: action %d does not exists in actual actions: %#v", t.Errorf("%s: action %d does not exists in actual actions: %#v",
test.name, i, caf.fakeClientset.Actions()) test.name, i, fakeClientset.Actions())
continue continue
} }
got := caf.fakeClientset.Actions()[i] got := fakeClientset.Actions()[i]
want := test.actions[i] want := test.actions[i]
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Errorf("%s: unexpected action: %s", test.name, diff.ObjectDiff(got, want)) t.Errorf("%s: unexpected action: %s", test.name, diff.ObjectDiff(got, want))
......
...@@ -15,7 +15,7 @@ go_library( ...@@ -15,7 +15,7 @@ go_library(
importpath = "k8s.io/kubernetes/test/e2e/kubectl", importpath = "k8s.io/kubernetes/test/e2e/kubectl",
deps = [ deps = [
"//pkg/controller:go_default_library", "//pkg/controller:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/polymorphichelpers:go_default_library",
"//test/e2e/framework:go_default_library", "//test/e2e/framework:go_default_library",
"//test/e2e/generated:go_default_library", "//test/e2e/generated:go_default_library",
"//test/e2e/scheduling:go_default_library", "//test/e2e/scheduling:go_default_library",
......
...@@ -58,7 +58,6 @@ import ( ...@@ -58,7 +58,6 @@ import (
genericregistry "k8s.io/apiserver/pkg/registry/generic/registry" genericregistry "k8s.io/apiserver/pkg/registry/generic/registry"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
"k8s.io/kubernetes/pkg/controller" "k8s.io/kubernetes/pkg/controller"
"k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/test/e2e/framework" "k8s.io/kubernetes/test/e2e/framework"
"k8s.io/kubernetes/test/e2e/generated" "k8s.io/kubernetes/test/e2e/generated"
"k8s.io/kubernetes/test/e2e/scheduling" "k8s.io/kubernetes/test/e2e/scheduling"
...@@ -67,6 +66,7 @@ import ( ...@@ -67,6 +66,7 @@ import (
. "github.com/onsi/ginkgo" . "github.com/onsi/ginkgo"
. "github.com/onsi/gomega" . "github.com/onsi/gomega"
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
imageutils "k8s.io/kubernetes/test/utils/image" imageutils "k8s.io/kubernetes/test/utils/image"
) )
...@@ -529,7 +529,7 @@ var _ = SIGDescribe("Kubectl client", func() { ...@@ -529,7 +529,7 @@ var _ = SIGDescribe("Kubectl client", func() {
ExecOrDie() ExecOrDie()
Expect(runOutput).ToNot(ContainSubstring("stdin closed")) Expect(runOutput).ToNot(ContainSubstring("stdin closed"))
g := func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) } g := func(pods []*v1.Pod) sort.Interface { return sort.Reverse(controller.ActivePods(pods)) }
runTestPod, _, err := util.GetFirstPod(f.InternalClientset.Core(), ns, "run=run-test-3", 1*time.Minute, g) runTestPod, _, err := polymorphichelpers.GetFirstPod(f.InternalClientset.Core(), ns, "run=run-test-3", 1*time.Minute, g)
if err != nil { if err != nil {
os.Exit(1) os.Exit(1)
} }
......
...@@ -174,7 +174,7 @@ func TestServerSidePrint(t *testing.T) { ...@@ -174,7 +174,7 @@ func TestServerSidePrint(t *testing.T) {
configFlags.WithDiscoveryClient(cachedClient) configFlags.WithDiscoveryClient(cachedClient)
factory := util.NewFactory(configFlags) factory := util.NewFactory(configFlags)
mapper, err := factory.RESTMapper() mapper, err := factory.ToRESTMapper()
if err != nil { if err != nil {
t.Errorf("unexpected error getting mapper: %v", err) t.Errorf("unexpected error getting mapper: %v", err)
return return
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment