mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 11:21:47 +00:00
Support multi-container pod for "kubectl logs"
kubectl logs -l will print logs for pods with the same label, however it doesn't support pods with multi containers. This change adds support to it with --all-containers. Ussage: $ kubectl logs my-pod --all-containers $ kubectl logs -laa=bb --all-containers $ kubectl logs my-pod my-container --all-containers (err: --all-containers=true should not be specifiled with container name my-container)
This commit is contained in:
parent
7d4bf1c338
commit
a06f0077bd
@ -18,6 +18,7 @@ package cmd
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
@ -41,8 +42,11 @@ var (
|
||||
# Return snapshot logs from pod nginx with only one container
|
||||
kubectl logs nginx
|
||||
|
||||
# Return snapshot logs for the pods defined by label app=nginx
|
||||
kubectl logs -lapp=nginx
|
||||
# Return snapshot logs from pod nginx with multi containers
|
||||
kubectl logs nginx --all-containers=true
|
||||
|
||||
# Return snapshot logs from all containers in pods defined by label app=nginx
|
||||
kubectl logs -lapp=nginx --all-containers=true
|
||||
|
||||
# Return snapshot of previous terminated ruby container logs from pod web-1
|
||||
kubectl logs -p -c ruby web-1
|
||||
@ -70,9 +74,10 @@ const (
|
||||
)
|
||||
|
||||
type LogsOptions struct {
|
||||
Namespace string
|
||||
ResourceArg string
|
||||
Options runtime.Object
|
||||
Namespace string
|
||||
ResourceArg string
|
||||
AllContainers bool
|
||||
Options runtime.Object
|
||||
|
||||
Mapper meta.RESTMapper
|
||||
Typer runtime.ObjectTyper
|
||||
@ -106,6 +111,7 @@ func NewCmdLogs(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
},
|
||||
Aliases: []string{"log"},
|
||||
}
|
||||
cmd.Flags().Bool("all-containers", false, "Get all containers's logs in the pod(s).")
|
||||
cmd.Flags().BoolP("follow", "f", false, "Specify if the logs should be streamed.")
|
||||
cmd.Flags().Bool("timestamps", false, "Include timestamps on each line in the log output")
|
||||
cmd.Flags().Int64("limit-bytes", 0, "Maximum bytes of logs to return. Defaults to no limit.")
|
||||
@ -125,6 +131,7 @@ func NewCmdLogs(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
func (o *LogsOptions) Complete(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
containerName := cmdutil.GetFlagString(cmd, "container")
|
||||
selector := cmdutil.GetFlagString(cmd, "selector")
|
||||
o.AllContainers = cmdutil.GetFlagBool(cmd, "all-containers")
|
||||
switch len(args) {
|
||||
case 0:
|
||||
if len(selector) == 0 {
|
||||
@ -221,6 +228,9 @@ func (o LogsOptions) Validate() error {
|
||||
if !ok {
|
||||
return errors.New("unexpected logs options object")
|
||||
}
|
||||
if o.AllContainers && len(logsOptions.Container) > 0 {
|
||||
return fmt.Errorf("--all-containers=true should not be specifiled with container name %s", logsOptions.Container)
|
||||
}
|
||||
if errs := validation.ValidatePodLogOptions(logsOptions); len(errs) > 0 {
|
||||
return errs.ToAggregate()
|
||||
}
|
||||
@ -233,16 +243,40 @@ func (o LogsOptions) RunLogs() error {
|
||||
switch t := o.Object.(type) {
|
||||
case *api.PodList:
|
||||
for _, p := range t.Items {
|
||||
if err := o.getLogs(&p); err != nil {
|
||||
if err := o.getPodLogs(&p); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
case *api.Pod:
|
||||
return o.getPodLogs(t)
|
||||
default:
|
||||
return o.getLogs(o.Object)
|
||||
}
|
||||
}
|
||||
|
||||
// getPodLogs checks whether o.AllContainers is set to true.
|
||||
// If so, it retrives all containers' log in the pod.
|
||||
func (o LogsOptions) getPodLogs(pod *api.Pod) error {
|
||||
if !o.AllContainers {
|
||||
return o.getLogs(pod)
|
||||
}
|
||||
|
||||
for _, c := range pod.Spec.InitContainers {
|
||||
o.Options.(*api.PodLogOptions).Container = c.Name
|
||||
if err := o.getLogs(pod); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for _, c := range pod.Spec.Containers {
|
||||
o.Options.(*api.PodLogOptions).Container = c.Name
|
||||
if err := o.getLogs(pod); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o LogsOptions) getLogs(obj runtime.Object) error {
|
||||
req, err := o.LogsForObject(obj, o.Options, o.GetPodTimeout)
|
||||
if err != nil {
|
||||
|
@ -109,28 +109,39 @@ func TestValidateLogFlags(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
flags map[string]string
|
||||
args []string
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "since & since-time",
|
||||
flags: map[string]string{"since": "1h", "since-time": "2006-01-02T15:04:05Z"},
|
||||
args: []string{"foo"},
|
||||
expected: "at most one of `sinceTime` or `sinceSeconds` may be specified",
|
||||
},
|
||||
{
|
||||
name: "negative since-time",
|
||||
flags: map[string]string{"since": "-1s"},
|
||||
args: []string{"foo"},
|
||||
expected: "must be greater than 0",
|
||||
},
|
||||
{
|
||||
name: "negative limit-bytes",
|
||||
flags: map[string]string{"limit-bytes": "-100"},
|
||||
args: []string{"foo"},
|
||||
expected: "must be greater than 0",
|
||||
},
|
||||
{
|
||||
name: "negative tail",
|
||||
flags: map[string]string{"tail": "-100"},
|
||||
args: []string{"foo"},
|
||||
expected: "must be greater than or equal to 0",
|
||||
},
|
||||
{
|
||||
name: "container name combined with --all-containers",
|
||||
flags: map[string]string{"all-containers": "true"},
|
||||
args: []string{"my-pod", "my-container"},
|
||||
expected: "--all-containers=true should not be specifiled with container",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
@ -146,7 +157,7 @@ func TestValidateLogFlags(t *testing.T) {
|
||||
o.Complete(f, os.Stdout, cmd, args)
|
||||
out = o.Validate().Error()
|
||||
}
|
||||
cmd.Run(cmd, []string{"foo"})
|
||||
cmd.Run(cmd, test.args)
|
||||
|
||||
if !strings.Contains(out, test.expected) {
|
||||
t.Errorf("%s: expected to find:\n\t%s\nfound:\n\t%s\n", test.name, test.expected, out)
|
||||
|
Loading…
Reference in New Issue
Block a user