2014-11-03 03:51:05 +00:00
/ *
2015-05-01 16:19:44 +00:00
Copyright 2014 The Kubernetes Authors All rights reserved .
2014-11-03 03:51:05 +00:00
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 cmd
import (
2015-02-24 14:50:22 +00:00
"fmt"
2014-11-03 03:51:05 +00:00
"io"
2015-05-21 20:14:32 +00:00
"os"
2014-12-15 11:07:25 +00:00
"strconv"
2015-08-31 02:44:41 +00:00
"strings"
2014-12-03 12:15:48 +00:00
2015-08-05 22:05:17 +00:00
"github.com/spf13/cobra"
2015-08-05 22:03:47 +00:00
"k8s.io/kubernetes/pkg/api"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
libutil "k8s.io/kubernetes/pkg/util"
2014-11-03 03:51:05 +00:00
)
2015-02-20 21:28:43 +00:00
const (
2015-09-02 09:56:29 +00:00
log_example = ` # Return snapshot of ruby - container logs from pod 123456 - 7890.
2015-05-21 20:14:32 +00:00
$ kubectl logs 123456 - 7890 ruby - container
2014-12-15 11:07:25 +00:00
2015-09-02 09:56:29 +00:00
# Return snapshot of previous terminated ruby - container logs from pod 123456 - 7890.
2015-05-21 20:14:32 +00:00
$ kubectl logs - p 123456 - 7890 ruby - container
2015-04-22 22:35:49 +00:00
2015-09-02 09:56:29 +00:00
# Start streaming of ruby - container logs from pod 123456 - 7890.
2015-05-21 20:14:32 +00:00
$ kubectl logs - f 123456 - 7890 ruby - container `
2015-02-20 21:28:43 +00:00
)
2015-02-03 17:59:21 +00:00
2015-02-24 14:50:22 +00:00
func selectContainer ( pod * api . Pod , in io . Reader , out io . Writer ) string {
fmt . Fprintf ( out , "Please select a container:\n" )
options := libutil . StringSet { }
for ix := range pod . Spec . Containers {
fmt . Fprintf ( out , "[%d] %s\n" , ix + 1 , pod . Spec . Containers [ ix ] . Name )
options . Insert ( pod . Spec . Containers [ ix ] . Name )
}
for {
var input string
fmt . Fprintf ( out , "> " )
fmt . Fscanln ( in , & input )
if options . Has ( input ) {
return input
}
ix , err := strconv . Atoi ( input )
if err == nil && ix > 0 && ix <= len ( pod . Spec . Containers ) {
return pod . Spec . Containers [ ix - 1 ] . Name
}
fmt . Fprintf ( out , "Invalid input: %s" , input )
}
}
2015-06-30 00:48:00 +00:00
type logParams struct {
containerName string
}
2015-04-23 18:11:42 +00:00
// NewCmdLog creates a new pod log command
2015-04-07 18:21:25 +00:00
func NewCmdLog ( f * cmdutil . Factory , out io . Writer ) * cobra . Command {
2015-06-30 00:48:00 +00:00
params := & logParams { }
2015-02-20 21:28:43 +00:00
cmd := & cobra . Command {
2015-06-30 00:48:00 +00:00
Use : "logs [-f] [-p] POD [-c CONTAINER]" ,
2015-02-20 21:28:43 +00:00
Short : "Print the logs for a container in a pod." ,
Long : "Print the logs for a container in a pod. If the pod has only one container, the container name is optional." ,
Example : log_example ,
2014-11-03 03:51:05 +00:00
Run : func ( cmd * cobra . Command , args [ ] string ) {
2015-06-30 00:48:00 +00:00
err := RunLog ( f , out , cmd , args , params )
2015-04-07 18:21:25 +00:00
cmdutil . CheckErr ( err )
2015-03-09 22:08:16 +00:00
} ,
2015-05-21 20:14:32 +00:00
Aliases : [ ] string { "log" } ,
2015-03-09 22:08:16 +00:00
}
cmd . Flags ( ) . BoolP ( "follow" , "f" , false , "Specify if the logs should be streamed." )
cmd . Flags ( ) . Bool ( "interactive" , true , "If true, prompt the user for input when required. Default true." )
2015-04-22 22:35:49 +00:00
cmd . Flags ( ) . BoolP ( "previous" , "p" , false , "If true, print the logs for the previous instance of the container in a pod if it exists." )
2015-06-30 00:48:00 +00:00
cmd . Flags ( ) . StringVarP ( & params . containerName , "container" , "c" , "" , "Container name" )
2015-03-09 22:08:16 +00:00
return cmd
}
2014-11-25 18:10:32 +00:00
2015-04-23 18:11:42 +00:00
// RunLog retrieves a pod log
2015-06-30 00:48:00 +00:00
func RunLog ( f * cmdutil . Factory , out io . Writer , cmd * cobra . Command , args [ ] string , p * logParams ) error {
2015-05-21 20:14:32 +00:00
if len ( os . Args ) > 1 && os . Args [ 1 ] == "log" {
printDeprecationWarning ( "logs" , "log" )
}
2015-03-09 22:08:16 +00:00
if len ( args ) == 0 {
2015-04-07 18:21:25 +00:00
return cmdutil . UsageError ( cmd , "POD is required for log" )
2015-03-09 22:08:16 +00:00
}
2014-12-12 01:40:47 +00:00
2015-03-09 22:08:16 +00:00
if len ( args ) > 2 {
2015-04-07 18:21:25 +00:00
return cmdutil . UsageError ( cmd , "log POD [CONTAINER]" )
2015-03-09 22:08:16 +00:00
}
2015-06-26 20:49:34 +00:00
namespace , _ , err := f . DefaultNamespace ( )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2015-03-14 10:45:18 +00:00
client , err := f . Client ( )
2015-03-09 22:08:16 +00:00
if err != nil {
return err
}
2014-12-11 18:39:20 +00:00
2015-03-09 22:08:16 +00:00
podID := args [ 0 ]
2014-12-11 18:39:20 +00:00
2015-03-09 22:08:16 +00:00
pod , err := client . Pods ( namespace ) . Get ( podID )
if err != nil {
return err
}
2014-11-03 03:51:05 +00:00
2015-08-31 02:44:41 +00:00
// [-c CONTAINER]
container := p . containerName
if len ( container ) == 0 {
2015-06-30 00:48:00 +00:00
// [CONTAINER] (container as arg not flag) is supported as legacy behavior. See PR #10519 for more details.
if len ( args ) == 1 {
if len ( pod . Spec . Containers ) != 1 {
2015-08-31 02:44:41 +00:00
podContainersNames := [ ] string { }
for _ , container := range pod . Spec . Containers {
podContainersNames = append ( podContainersNames , container . Name )
}
return fmt . Errorf ( "Pod %s has the following containers: %s; please specify the container to print logs for with -c" , pod . ObjectMeta . Name , strings . Join ( podContainersNames , ", " ) )
2015-06-30 00:48:00 +00:00
}
container = pod . Spec . Containers [ 0 ] . Name
} else {
container = args [ 1 ]
}
2015-03-09 22:08:16 +00:00
}
2014-11-03 03:51:05 +00:00
2015-03-09 22:08:16 +00:00
follow := false
2015-04-07 18:21:25 +00:00
if cmdutil . GetFlagBool ( cmd , "follow" ) {
2015-03-09 22:08:16 +00:00
follow = true
2014-11-03 03:51:05 +00:00
}
2015-03-09 22:08:16 +00:00
2015-04-22 22:35:49 +00:00
previous := false
if cmdutil . GetFlagBool ( cmd , "previous" ) {
previous = true
}
2015-03-09 22:08:16 +00:00
readCloser , err := client . RESTClient . Get ( ) .
2015-04-23 18:11:42 +00:00
Namespace ( namespace ) .
Name ( podID ) .
Resource ( "pods" ) .
SubResource ( "log" ) .
2015-03-09 22:08:16 +00:00
Param ( "follow" , strconv . FormatBool ( follow ) ) .
2015-04-23 18:11:42 +00:00
Param ( "container" , container ) .
2015-04-22 22:35:49 +00:00
Param ( "previous" , strconv . FormatBool ( previous ) ) .
2015-03-09 22:08:16 +00:00
Stream ( )
if err != nil {
return err
}
defer readCloser . Close ( )
_ , err = io . Copy ( out , readCloser )
return err
2014-11-03 03:51:05 +00:00
}