diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index 3e5e84ca89..1b149d6d06 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -26,11 +26,9 @@ import ( "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/api/meta" client "k8s.io/kubernetes/pkg/client/unversioned" - "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/kubectl" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" "k8s.io/kubernetes/pkg/kubectl/resource" - "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" ) @@ -170,7 +168,7 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob } } - obj, kind, mapper, mapping, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace) + obj, _, mapper, mapping, err := createGeneratedObject(f, cmd, generator, names, params, cmdutil.GetFlagString(cmd, "overrides"), namespace) if err != nil { return err } @@ -202,15 +200,12 @@ func Run(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cob return err } opts.Client = client - // TODO: this should be abstracted into Factory to support other types - switch t := obj.(type) { - case *api.ReplicationController: - return handleAttachReplicationController(client, t, opts) - case *api.Pod: - return handleAttachPod(client, t, opts) - default: - return fmt.Errorf("cannot attach to %s: not implemented", kind) + + attachablePod, err := f.AttachablePodForObject(obj) + if err != nil { + return err } + return handleAttachPod(client, attachablePod, opts) } outputFormat := cmdutil.GetFlagString(cmd, "output") @@ -249,22 +244,6 @@ func waitForPodRunning(c *client.Client, pod *api.Pod, out io.Writer) (status ap } } -func handleAttachReplicationController(c *client.Client, controller *api.ReplicationController, opts *AttachOptions) error { - var pods *api.PodList - for pods == nil || len(pods.Items) == 0 { - var err error - if pods, err = c.Pods(controller.Namespace).List(labels.SelectorFromSet(controller.Spec.Selector), fields.Everything()); err != nil { - return err - } - if len(pods.Items) == 0 { - fmt.Fprint(opts.Out, "Waiting for pod to be scheduled\n") - time.Sleep(2 * time.Second) - } - } - pod := &pods.Items[0] - return handleAttachPod(c, pod, opts) -} - func handleAttachPod(c *client.Client, pod *api.Pod, opts *AttachOptions) error { status, err := waitForPodRunning(c, pod, opts.Out) if err != nil { diff --git a/pkg/kubectl/cmd/util/factory.go b/pkg/kubectl/cmd/util/factory.go index 97416009b2..f2b8f67a33 100644 --- a/pkg/kubectl/cmd/util/factory.go +++ b/pkg/kubectl/cmd/util/factory.go @@ -27,6 +27,7 @@ import ( "os/user" "path" "strconv" + "time" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -37,8 +38,10 @@ import ( "k8s.io/kubernetes/pkg/api/validation" client "k8s.io/kubernetes/pkg/client/unversioned" "k8s.io/kubernetes/pkg/client/unversioned/clientcmd" + "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl/resource" + "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/runtime" "k8s.io/kubernetes/pkg/util" ) @@ -92,6 +95,8 @@ type Factory struct { CanBeExposed func(kind string) error // Check whether the kind of resources could be autoscaled CanBeAutoscaled func(kind string) error + // AttachablePodForObject returns the pod to which to attach given an object. + AttachablePodForObject func(object runtime.Object) (*api.Pod, error) } // NewFactory creates a factory with the default Kubernetes resources defined @@ -268,6 +273,35 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { } return nil }, + AttachablePodForObject: func(object runtime.Object) (*api.Pod, error) { + client, err := clients.ClientForVersion("") + if err != nil { + return nil, err + } + switch t := object.(type) { + case *api.ReplicationController: + var pods *api.PodList + for pods == nil || len(pods.Items) == 0 { + var err error + if pods, err = client.Pods(t.Namespace).List(labels.SelectorFromSet(t.Spec.Selector), fields.Everything()); err != nil { + return nil, err + } + if len(pods.Items) == 0 { + time.Sleep(2 * time.Second) + } + } + pod := &pods.Items[0] + return pod, nil + case *api.Pod: + return t, nil + default: + _, kind, err := api.Scheme.ObjectVersionAndKind(object) + if err != nil { + return nil, err + } + return nil, fmt.Errorf("cannot attach to %s: not implemented", kind) + } + }, } }