Show the default container as the first entry (#2158)
* Switch to new default-container pod annotation
kubectl.kubernetes.io/default-logs-container has been deprecated and
removed in kubectl, see
3a9c6f2a2f
* Show the default container as the first entry
In container selections show the default container as the first entry of
the list.
mine
parent
8af2956d61
commit
062e7ef439
|
|
@ -33,9 +33,9 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
logRetryCount = 20
|
logRetryCount = 20
|
||||||
logRetryWait = 1 * time.Second
|
logRetryWait = 1 * time.Second
|
||||||
defaultLogContainerAnnotation = "kubectl.kubernetes.io/default-logs-container"
|
defaultContainerAnnotation = "kubectl.kubernetes.io/default-container"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Pod represents a pod resource.
|
// Pod represents a pod resource.
|
||||||
|
|
@ -197,7 +197,7 @@ func (p *Pod) TailLogs(ctx context.Context, opts *LogOptions) ([]LogChan, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
outs := make([]LogChan, 0, coCounts)
|
outs := make([]LogChan, 0, coCounts)
|
||||||
if co, ok := GetDefaultLogContainer(po.ObjectMeta, po.Spec); ok && !opts.AllContainers {
|
if co, ok := GetDefaultContainer(po.ObjectMeta, po.Spec); ok && !opts.AllContainers {
|
||||||
opts.DefaultContainer = co
|
opts.DefaultContainer = co
|
||||||
return append(outs, tailLogs(ctx, p, opts)), nil
|
return append(outs, tailLogs(ctx, p, opts)), nil
|
||||||
}
|
}
|
||||||
|
|
@ -486,16 +486,16 @@ func (p *Pod) isControlled(path string) (string, bool, error) {
|
||||||
return "", false, nil
|
return "", false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDefaultLogContainer returns a container name if specified in an annotation.
|
// GetDefaultContainer returns a container name if specified in an annotation.
|
||||||
func GetDefaultLogContainer(m metav1.ObjectMeta, spec v1.PodSpec) (string, bool) {
|
func GetDefaultContainer(m metav1.ObjectMeta, spec v1.PodSpec) (string, bool) {
|
||||||
defaultContainer, ok := m.Annotations[defaultLogContainerAnnotation]
|
defaultContainer, ok := m.Annotations[defaultContainerAnnotation]
|
||||||
if ok {
|
if ok {
|
||||||
for _, container := range spec.Containers {
|
for _, container := range spec.Containers {
|
||||||
if container.Name == defaultContainer {
|
if container.Name == defaultContainer {
|
||||||
return defaultContainer, true
|
return defaultContainer, true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
log.Warn().Msg(defaultContainer + " container not found. " + defaultLogContainerAnnotation + " annotation will be ignored")
|
log.Warn().Msg(defaultContainer + " container not found. " + defaultContainerAnnotation + " annotation will be ignored")
|
||||||
}
|
}
|
||||||
|
|
||||||
return "", false
|
return "", false
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import (
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetDefaultLogContainer(t *testing.T) {
|
func TestGetDefaultContainer(t *testing.T) {
|
||||||
uu := map[string]struct {
|
uu := map[string]struct {
|
||||||
po *v1.Pod
|
po *v1.Pod
|
||||||
wantContainer string
|
wantContainer string
|
||||||
|
|
@ -26,7 +26,7 @@ func TestGetDefaultLogContainer(t *testing.T) {
|
||||||
"container_not_present": {
|
"container_not_present": {
|
||||||
po: &v1.Pod{
|
po: &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Annotations: map[string]string{"kubectl.kubernetes.io/default-logs-container": "container1"},
|
Annotations: map[string]string{"kubectl.kubernetes.io/default-container": "container1"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
wantContainer: "",
|
wantContainer: "",
|
||||||
|
|
@ -35,7 +35,7 @@ func TestGetDefaultLogContainer(t *testing.T) {
|
||||||
"container_found": {
|
"container_found": {
|
||||||
po: &v1.Pod{
|
po: &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Annotations: map[string]string{"kubectl.kubernetes.io/default-logs-container": "container1"},
|
Annotations: map[string]string{"kubectl.kubernetes.io/default-container": "container1"},
|
||||||
},
|
},
|
||||||
Spec: v1.PodSpec{
|
Spec: v1.PodSpec{
|
||||||
Containers: []v1.Container{{Name: "container1"}},
|
Containers: []v1.Container{{Name: "container1"}},
|
||||||
|
|
@ -48,7 +48,7 @@ func TestGetDefaultLogContainer(t *testing.T) {
|
||||||
for k := range uu {
|
for k := range uu {
|
||||||
u := uu[k]
|
u := uu[k]
|
||||||
t.Run(k, func(t *testing.T) {
|
t.Run(k, func(t *testing.T) {
|
||||||
container, ok := GetDefaultLogContainer(u.po.ObjectMeta, u.po.Spec)
|
container, ok := GetDefaultContainer(u.po.ObjectMeta, u.po.Spec)
|
||||||
assert.Equal(t, u.wantContainer, container)
|
assert.Equal(t, u.wantContainer, container)
|
||||||
assert.Equal(t, u.wantOk, ok)
|
assert.Equal(t, u.wantOk, ok)
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ func (d *Deploy) logOptions(prev bool) (*dao.LogOptions, error) {
|
||||||
co, dco string
|
co, dco string
|
||||||
allCos bool
|
allCos bool
|
||||||
)
|
)
|
||||||
if c, ok := dao.GetDefaultLogContainer(sts.Spec.Template.ObjectMeta, sts.Spec.Template.Spec); ok {
|
if c, ok := dao.GetDefaultContainer(sts.Spec.Template.ObjectMeta, sts.Spec.Template.Spec); ok {
|
||||||
co, dco = c, c
|
co, dco = c, c
|
||||||
} else if len(cc) == 1 {
|
} else if len(cc) == 1 {
|
||||||
co = cc[0].Name
|
co = cc[0].Name
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import (
|
||||||
"github.com/fatih/color"
|
"github.com/fatih/color"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
|
@ -95,7 +96,7 @@ func (p *Pod) logOptions(prev bool) (*dao.LogOptions, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cc, cfg := fetchContainers(pod.Spec, true), p.App().Config.K9s.Logger
|
cc, cfg := fetchContainers(pod.ObjectMeta, pod.Spec, true), p.App().Config.K9s.Logger
|
||||||
opts := dao.LogOptions{
|
opts := dao.LogOptions{
|
||||||
Path: path,
|
Path: path,
|
||||||
Lines: int64(cfg.TailCount),
|
Lines: int64(cfg.TailCount),
|
||||||
|
|
@ -104,7 +105,7 @@ func (p *Pod) logOptions(prev bool) (*dao.LogOptions, error) {
|
||||||
ShowTimestamp: cfg.ShowTime,
|
ShowTimestamp: cfg.ShowTime,
|
||||||
Previous: prev,
|
Previous: prev,
|
||||||
}
|
}
|
||||||
if c, ok := dao.GetDefaultLogContainer(pod.ObjectMeta, pod.Spec); ok {
|
if c, ok := dao.GetDefaultContainer(pod.ObjectMeta, pod.Spec); ok {
|
||||||
opts.Container, opts.DefaultContainer = c, c
|
opts.Container, opts.DefaultContainer = c, c
|
||||||
} else if len(cc) == 1 {
|
} else if len(cc) == 1 {
|
||||||
opts.Container = cc[0]
|
opts.Container = cc[0]
|
||||||
|
|
@ -261,7 +262,7 @@ func containerShellin(a *App, comp model.Component, path, co string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cc := fetchContainers(pod.Spec, false)
|
cc := fetchContainers(pod.ObjectMeta, pod.Spec, false)
|
||||||
if len(cc) == 1 {
|
if len(cc) == 1 {
|
||||||
resumeShellIn(a, comp, path, cc[0])
|
resumeShellIn(a, comp, path, cc[0])
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -305,7 +306,7 @@ func containerAttachIn(a *App, comp model.Component, path, co string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
cc := fetchContainers(pod.Spec, false)
|
cc := fetchContainers(pod.ObjectMeta, pod.Spec, false)
|
||||||
if len(cc) == 1 {
|
if len(cc) == 1 {
|
||||||
resumeAttachIn(a, comp, path, cc[0])
|
resumeAttachIn(a, comp, path, cc[0])
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -363,10 +364,19 @@ func buildShellArgs(cmd, path, co string, kcfg *string) []string {
|
||||||
return args
|
return args
|
||||||
}
|
}
|
||||||
|
|
||||||
func fetchContainers(spec v1.PodSpec, allContainers bool) []string {
|
func fetchContainers(meta metav1.ObjectMeta, spec v1.PodSpec, allContainers bool) []string {
|
||||||
nn := make([]string, 0, len(spec.Containers)+len(spec.InitContainers))
|
nn := make([]string, 0, len(spec.Containers)+len(spec.InitContainers))
|
||||||
|
|
||||||
|
// put the default container as the first entry
|
||||||
|
defaultContainer, hasDefaultContainer := dao.GetDefaultContainer(meta, spec)
|
||||||
|
if hasDefaultContainer {
|
||||||
|
nn = append(nn, defaultContainer)
|
||||||
|
}
|
||||||
|
|
||||||
for _, c := range spec.Containers {
|
for _, c := range spec.Containers {
|
||||||
nn = append(nn, c.Name)
|
if !hasDefaultContainer || c.Name != defaultContainer {
|
||||||
|
nn = append(nn, c.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !allContainers {
|
if !allContainers {
|
||||||
return nn
|
return nn
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ func (s *StatefulSet) logOptions(prev bool) (*dao.LogOptions, error) {
|
||||||
co, dco string
|
co, dco string
|
||||||
allCos bool
|
allCos bool
|
||||||
)
|
)
|
||||||
if c, ok := dao.GetDefaultLogContainer(sts.Spec.Template.ObjectMeta, sts.Spec.Template.Spec); ok {
|
if c, ok := dao.GetDefaultContainer(sts.Spec.Template.ObjectMeta, sts.Spec.Template.Spec); ok {
|
||||||
co, dco = c, c
|
co, dco = c, c
|
||||||
} else if len(cc) == 1 {
|
} else if len(cc) == 1 {
|
||||||
co = cc[0].Name
|
co = cc[0].Name
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue