cleanup + rel notes
parent
730494af98
commit
a4c7f3817e
Binary file not shown.
|
After Width: | Height: | Size: 71 KiB |
|
|
@ -0,0 +1,97 @@
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9s_small.png" align="right" width="200" height="auto"/>
|
||||||
|
|
||||||
|
# Release v0.24.2
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
Thank you to all that contributed with flushing out issues and enhancements for K9s! I'll try to mark some of these issues as fixed. But if you don't mind grab the latest rev and see if we're happier with some of the fixes! If you've filed an issue please help me verify and close. Your support, kindness and awesome suggestions to make K9s better are as ever very much noted and appreciated!
|
||||||
|
|
||||||
|
If you feel K9s is helping your Kubernetes journey, please consider joining our [sponsorhip program](https://github.com/sponsors/derailed) and/or make some noise on social! [@kitesurfer](https://twitter.com/kitesurfer)
|
||||||
|
|
||||||
|
On Slack? Please join us [K9slackers](https://join.slack.com/t/k9sers/shared_invite/enQtOTA5MDEyNzI5MTU0LWQ1ZGI3MzliYzZhZWEyNzYxYzA3NjE0YTk1YmFmNzViZjIyNzhkZGI0MmJjYzhlNjdlMGJhYzE2ZGU1NjkyNTM)
|
||||||
|
|
||||||
|
## ♫ Sounds Behind The Release ♭
|
||||||
|
|
||||||
|
* [ZZ Top - My Head's in Mississippi](https://www.youtube.com/watch?v=0968f0VWvd8)
|
||||||
|
|
||||||
|
## A Word From Our Sponsors...
|
||||||
|
|
||||||
|
I would like to extend a `Big Thank You` to the following generous K9s friends for joining our sponsorship program and supporting this project!
|
||||||
|
|
||||||
|
* [Tim Orling](https://github.com/moto-timo)
|
||||||
|
* [Jiri Valnoha](https://github.com/waldauf)
|
||||||
|
* [Osx2000](https://github.com/osx2000)
|
||||||
|
|
||||||
|
## Our Release Heroes
|
||||||
|
|
||||||
|
Please join me in recognizing and applauding this drop contributors that went the extra mile to make sure K9s is better and more useful for all of us!!
|
||||||
|
|
||||||
|
Big ATTA BOY/GIRL! in full effect this week to the good folks below for their efforts and contributions to K9s!!
|
||||||
|
|
||||||
|
* [Ainslie Hsu](https://github.com/ainslie-hsu)
|
||||||
|
* [Lucas Teligioridis](https://github.com/lucasteligioridis)
|
||||||
|
* [Gergely Tankovics](https://github.com/gtankovics)
|
||||||
|
* [Michal Kuratczyk](https://github.com/mkuratczyk)
|
||||||
|
* [Simon Caron](https://github.com/simoncaron)
|
||||||
|
|
||||||
|
## She Can't Take Much More Capt'n!!
|
||||||
|
|
||||||
|
### Background
|
||||||
|
|
||||||
|
Thanks to all of you for supporting K9s and being avid fans. I am truly humbled and amazed by your continued kindness and support!! As we're nearing K9s second anniversary, the project has reached over 10k stars and 384k downloads! That said, while these numbers sound stunning, there is another number on this project that is not so and that is number of sponsors 😿.
|
||||||
|
As I understand it, there are a several organizations leveraging K9s productivity to better their bottom line, without much care for ours...
|
||||||
|
As you all know, K9s is a complex tool in a continually evolving space and we find ourselves spending a lot of our free time, thinking, experimenting and supporting K9s to continually improve the offering. As it stands, there is currently a very small fraction of you that actively sponsor this project either financially or by filing issues/PRs while the rest are benefiting from these efforts. This just does not sound like a fair deal and if we were in the music business it would be a total outrage!
|
||||||
|
|
||||||
|
### There Are Some That Call Me... Alpha!
|
||||||
|
|
||||||
|
To this end, I would like to introduce a new member of the K9s pack, the main dog, ie `k9sAlpha`. This is going to be a licensed version of K9s. The current plan is to offer a tiered license scheme starting at just `$10/month` for a basic license. The current K9s branch will be effectively in feature freeze. K9s𝞪 will provide fixes, enhancements, further integrations and a bunch of new features that have been sitting in the back burner.
|
||||||
|
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/k9salpha.png" align="center" width="300" height="auto"/>
|
||||||
|
|
||||||
|
### So what does this entails?
|
||||||
|
|
||||||
|
1. Current K9s branch will be in feature freeze and will remain OSS and free
|
||||||
|
1. Active K9s sponsors will get a corresponding K9s𝞪 license
|
||||||
|
1. Contributors will get a free K9s𝞪 license
|
||||||
|
1. K9s𝞪 users will need to purchase a license from our store
|
||||||
|
1. Documentation, binaries, issue trackers, will be provisioned under a new K9s𝞪 site
|
||||||
|
|
||||||
|
Given any license schemes are all meant to be hacked, we're not going to over complicate things with calling out to license servers and such to ensure the keys are legit.
|
||||||
|
The current plan is to email out your license keys and trusting our `Gentlemen Agreement` that you will not share or distribute your keys to other folks.
|
||||||
|
In the current economic climate, if you can't afford a K9s𝞪 license, we will provide you one on a case by case basis.
|
||||||
|
|
||||||
|
The process should be simple:
|
||||||
|
|
||||||
|
1. Store your key somewhere on disk
|
||||||
|
2. Download the K9s𝞪 binary
|
||||||
|
3. Start administering your Kubernetes clusters
|
||||||
|
|
||||||
|
### K9s𝞪 Needs You!
|
||||||
|
|
||||||
|
To this end, I'd like to enlist a few of you to help me validate license keys, K9s𝞪 store and site to ensure the flow well... flows!
|
||||||
|
If you are so inclined, please reach out for your `shoephones` and send me an email with why you want to participate. Looking for folks with K9s chops in multi clusters env would be preferred.
|
||||||
|
It should not take too much of your time to ensure all is cool, but want to make sure I have at least another 5 pairs of eyes to help out with the K9s𝞪 drop.
|
||||||
|
My hope is to get an initial K9s𝞪 revision dropped before Santa comes around...
|
||||||
|
|
||||||
|
### Pipe In!
|
||||||
|
|
||||||
|
By all means, this is a democracy and not a dictatorship! So... if you have better/other ideas or concerns please pipe in! Open an issue on the repo so we can track, discuss, opiniate and figure out a course of action that will be fair for both K9s contributors and users alike.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Resolved Issues/Features
|
||||||
|
|
||||||
|
* [Issue #972](https://github.com/derailed/k9s/issues/972) Default color is no longer transparent.
|
||||||
|
* [Issue #933](https://github.com/derailed/k9s/issues/933) Unable to cordon node.
|
||||||
|
|
||||||
|
## Resolved PRs
|
||||||
|
|
||||||
|
* [PR #982](https://github.com/derailed/k9s/pull/982) Fix typo
|
||||||
|
* [PR #976](https://github.com/derailed/k9s/pull/976) Add OneDark color theme
|
||||||
|
* [PR #975](https://github.com/derailed/k9s/pull/982) Handling non json lines as raw with red color
|
||||||
|
* [PR #968](https://github.com/dserailed/k9s/pull/968) Disable filtering on help screen ... and broke the build ;)
|
||||||
|
* [PR #960](https://github.com/derailed/k9s/pull/960) Handle empty port list in PortForward view
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<img src="https://raw.githubusercontent.com/derailed/k9s/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2020 Imhotep Software LLC. All materials licensed under [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
|
@ -312,7 +312,7 @@ func ToMB(v int64) int64 {
|
||||||
return v / MegaByte
|
return v / MegaByte
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToPercentage computes percentage.
|
// ToPercentage computes percentage as string otherwise n/aa.
|
||||||
func ToPercentage(v1, v2 int64) int {
|
func ToPercentage(v1, v2 int64) int {
|
||||||
if v2 == 0 {
|
if v2 == 0 {
|
||||||
return 0
|
return 0
|
||||||
|
|
@ -323,7 +323,7 @@ func ToPercentage(v1, v2 int64) int {
|
||||||
// ToPercentageStr computes percentage, but if v2 is 0, it will return NAValue instead of 0
|
// ToPercentageStr computes percentage, but if v2 is 0, it will return NAValue instead of 0
|
||||||
func ToPercentageStr(v1, v2 int64) string {
|
func ToPercentageStr(v1, v2 int64) string {
|
||||||
if v2 == 0 {
|
if v2 == 0 {
|
||||||
return "0"
|
return NA
|
||||||
}
|
}
|
||||||
return strconv.Itoa(ToPercentage(v1, v2))
|
return strconv.Itoa(ToPercentage(v1, v2))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/derailed/k9s/internal/client"
|
"github.com/derailed/k9s/internal/client"
|
||||||
|
|
@ -21,8 +20,6 @@ import (
|
||||||
"k8s.io/client-go/transport/spdy"
|
"k8s.io/client-go/transport/spdy"
|
||||||
)
|
)
|
||||||
|
|
||||||
const localhost = "localhost"
|
|
||||||
|
|
||||||
// PortForwarder tracks a port forward stream.
|
// PortForwarder tracks a port forward stream.
|
||||||
type PortForwarder struct {
|
type PortForwarder struct {
|
||||||
Factory
|
Factory
|
||||||
|
|
@ -107,9 +104,9 @@ func (p *PortForwarder) Start(path, co string, tt []client.PortTunnel) (*portfor
|
||||||
if len(tt) == 0 {
|
if len(tt) == 0 {
|
||||||
return nil, fmt.Errorf("no ports assigned")
|
return nil, fmt.Errorf("no ports assigned")
|
||||||
}
|
}
|
||||||
fwds := make([]string, 0, len(tt))
|
fwds, addrs := make([]string, 0, len(tt)), make([]string, 0, len(tt))
|
||||||
for _, t := range tt {
|
for _, t := range tt {
|
||||||
fwds = append(fwds, t.PortMap())
|
fwds, addrs = append(fwds, t.PortMap()), append(addrs, t.Address)
|
||||||
}
|
}
|
||||||
p.path, p.container, p.ports, p.age = path, co, fwds, time.Now()
|
p.path, p.container, p.ports, p.age = path, co, fwds, time.Now()
|
||||||
|
|
||||||
|
|
@ -158,10 +155,10 @@ func (p *PortForwarder) Start(path, co string, tt []client.PortTunnel) (*portfor
|
||||||
Name(n).
|
Name(n).
|
||||||
SubResource("portforward")
|
SubResource("portforward")
|
||||||
|
|
||||||
return p.forwardPorts("POST", req.URL(), tt[0].Address, fwds)
|
return p.forwardPorts("POST", req.URL(), addrs, fwds)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PortForwarder) forwardPorts(method string, url *url.URL, address string, ports []string) (*portforward.PortForwarder, error) {
|
func (p *PortForwarder) forwardPorts(method string, url *url.URL, addrs, ports []string) (*portforward.PortForwarder, error) {
|
||||||
cfg, err := p.Client().Config().RESTConfig()
|
cfg, err := p.Client().Config().RESTConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -170,12 +167,8 @@ func (p *PortForwarder) forwardPorts(method string, url *url.URL, address string
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, method, url)
|
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, method, url)
|
||||||
if address == "" {
|
|
||||||
address = localhost
|
|
||||||
}
|
|
||||||
addrs := strings.Split(address, ",")
|
|
||||||
return portforward.NewOnAddresses(dialer, addrs, ports, p.stopChan, p.readyChan, p.Out, p.ErrOut)
|
return portforward.NewOnAddresses(dialer, addrs, ports, p.stopChan, p.readyChan, p.Out, p.ErrOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ func (c Container) Render(o interface{}, name string, r *Row) error {
|
||||||
return fmt.Errorf("Expected ContainerRes, but got %T", o)
|
return fmt.Errorf("Expected ContainerRes, but got %T", o)
|
||||||
}
|
}
|
||||||
|
|
||||||
cur, perc, res := gatherMetrics(co.Container, co.MX)
|
cur, res := gatherMetrics(co.Container, co.MX)
|
||||||
ready, state, restarts := "false", MissingValue, "0"
|
ready, state, restarts := "false", MissingValue, "0"
|
||||||
if co.Status != nil {
|
if co.Status != nil {
|
||||||
ready, state, restarts = boolToStr(co.Status.Ready), ToContainerState(co.Status.State), strconv.Itoa(int(co.Status.RestartCount))
|
ready, state, restarts = boolToStr(co.Status.Ready), ToContainerState(co.Status.State), strconv.Itoa(int(co.Status.RestartCount))
|
||||||
|
|
@ -117,10 +117,10 @@ func (c Container) Render(o interface{}, name string, r *Row) error {
|
||||||
toMi(cur.mem),
|
toMi(cur.mem),
|
||||||
toMc(res.cpu) + ":" + toMc(res.lcpu),
|
toMc(res.cpu) + ":" + toMc(res.lcpu),
|
||||||
toMi(res.mem) + ":" + toMi(res.lmem),
|
toMi(res.mem) + ":" + toMi(res.lmem),
|
||||||
strconv.Itoa(perc.rCPU()),
|
client.ToPercentageStr(cur.cpu, res.cpu),
|
||||||
strconv.Itoa(perc.lCPU()),
|
client.ToPercentageStr(cur.cpu, res.lcpu),
|
||||||
strconv.Itoa(perc.rMEM()),
|
client.ToPercentageStr(cur.mem, res.mem),
|
||||||
strconv.Itoa(perc.lMEM()),
|
client.ToPercentageStr(cur.mem, res.lmem),
|
||||||
ToContainerPorts(co.Container.Ports),
|
ToContainerPorts(co.Container.Ports),
|
||||||
asStatus(c.diagnose(state, ready)),
|
asStatus(c.diagnose(state, ready)),
|
||||||
toAge(co.Age),
|
toAge(co.Age),
|
||||||
|
|
@ -144,12 +144,8 @@ func (Container) diagnose(state, ready string) error {
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Helpers...
|
// Helpers...
|
||||||
|
|
||||||
func gatherMetrics(co *v1.Container, mx *mv1beta1.ContainerMetrics) (metric, percentages, metric) {
|
func gatherMetrics(co *v1.Container, mx *mv1beta1.ContainerMetrics) (c, r metric) {
|
||||||
rList, lList := containerRequests(co), co.Resources.Limits
|
rList, lList := containerRequests(co), co.Resources.Limits
|
||||||
var c metric
|
|
||||||
p := newPercentages()
|
|
||||||
|
|
||||||
var r metric
|
|
||||||
if rList.Cpu() != nil {
|
if rList.Cpu() != nil {
|
||||||
r.cpu = rList.Cpu().MilliValue()
|
r.cpu = rList.Cpu().MilliValue()
|
||||||
}
|
}
|
||||||
|
|
@ -162,23 +158,16 @@ func gatherMetrics(co *v1.Container, mx *mv1beta1.ContainerMetrics) (metric, per
|
||||||
if lList.Memory() != nil {
|
if lList.Memory() != nil {
|
||||||
r.lmem = lList.Memory().Value()
|
r.lmem = lList.Memory().Value()
|
||||||
}
|
}
|
||||||
|
if mx != nil {
|
||||||
if mx == nil {
|
|
||||||
return c, p, r
|
|
||||||
}
|
|
||||||
|
|
||||||
if mx.Usage.Cpu() != nil {
|
if mx.Usage.Cpu() != nil {
|
||||||
c.cpu = mx.Usage.Cpu().MilliValue()
|
c.cpu = mx.Usage.Cpu().MilliValue()
|
||||||
}
|
}
|
||||||
if mx.Usage.Memory() != nil {
|
if mx.Usage.Memory() != nil {
|
||||||
c.mem = mx.Usage.Memory().Value()
|
c.mem = mx.Usage.Memory().Value()
|
||||||
}
|
}
|
||||||
p[requestCPU] = client.ToPercentage(c.cpu, r.cpu)
|
}
|
||||||
p[limitCPU] = client.ToPercentage(c.cpu, r.lcpu)
|
|
||||||
p[requestMEM] = client.ToPercentage(c.mem, r.mem)
|
|
||||||
p[limitMEM] = client.ToPercentage(c.mem, r.lmem)
|
|
||||||
|
|
||||||
return c, p, r
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToContainerPorts returns container ports as a string.
|
// ToContainerPorts returns container ports as a string.
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ func (n Node) Render(o interface{}, ns string, r *Row) error {
|
||||||
iIP, eIP := getIPs(no.Status.Addresses)
|
iIP, eIP := getIPs(no.Status.Addresses)
|
||||||
iIP, eIP = missing(iIP), missing(eIP)
|
iIP, eIP = missing(iIP), missing(eIP)
|
||||||
|
|
||||||
c, p, a := gatherNodeMX(&no, oo.MX)
|
c, a := gatherNodeMX(&no, oo.MX)
|
||||||
statuses := make(sort.StringSlice, 10)
|
statuses := make(sort.StringSlice, 10)
|
||||||
status(no.Status.Conditions, no.Spec.Unschedulable, statuses)
|
status(no.Status.Conditions, no.Spec.Unschedulable, statuses)
|
||||||
sort.Sort(statuses)
|
sort.Sort(statuses)
|
||||||
|
|
@ -92,8 +92,8 @@ func (n Node) Render(o interface{}, ns string, r *Row) error {
|
||||||
strconv.Itoa(oo.PodCount),
|
strconv.Itoa(oo.PodCount),
|
||||||
toMc(c.cpu),
|
toMc(c.cpu),
|
||||||
toMi(c.mem),
|
toMi(c.mem),
|
||||||
strconv.Itoa(p.rCPU()),
|
client.ToPercentageStr(c.cpu, a.cpu),
|
||||||
strconv.Itoa(p.rMEM()),
|
client.ToPercentageStr(c.mem, a.mem),
|
||||||
toMc(a.cpu),
|
toMc(a.cpu),
|
||||||
toMi(a.mem),
|
toMi(a.mem),
|
||||||
mapToStr(no.Labels),
|
mapToStr(no.Labels),
|
||||||
|
|
@ -154,22 +154,13 @@ type metric struct {
|
||||||
lcpu, lmem int64
|
lcpu, lmem int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func gatherNodeMX(no *v1.Node, mx *mv1beta1.NodeMetrics) (metric, percentages, metric) {
|
func gatherNodeMX(no *v1.Node, mx *mv1beta1.NodeMetrics) (c, a metric) {
|
||||||
var c metric
|
a.cpu, a.mem = no.Status.Allocatable.Cpu().MilliValue(), no.Status.Allocatable.Memory().Value()
|
||||||
p := newPercentages()
|
if mx != nil {
|
||||||
a := metric{
|
|
||||||
cpu: no.Status.Allocatable.Cpu().MilliValue(),
|
|
||||||
mem: no.Status.Allocatable.Memory().Value(),
|
|
||||||
}
|
|
||||||
if mx == nil {
|
|
||||||
return c, p, a
|
|
||||||
}
|
|
||||||
|
|
||||||
c.cpu, c.mem = mx.Usage.Cpu().MilliValue(), mx.Usage.Memory().Value()
|
c.cpu, c.mem = mx.Usage.Cpu().MilliValue(), mx.Usage.Memory().Value()
|
||||||
p[requestCPU] = client.ToPercentage(c.cpu, a.cpu)
|
}
|
||||||
p[requestMEM] = client.ToPercentage(c.mem, a.mem)
|
|
||||||
|
|
||||||
return c, p, a
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func nodeRoles(node *v1.Node, res []string) {
|
func nodeRoles(node *v1.Node, res []string) {
|
||||||
|
|
|
||||||
|
|
@ -16,34 +16,6 @@ import (
|
||||||
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
mv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
requestCPU qualifiedResource = "rcpu"
|
|
||||||
requestMEM qualifiedResource = "rmem"
|
|
||||||
limitCPU qualifiedResource = "lcpu"
|
|
||||||
limitMEM qualifiedResource = "lmem"
|
|
||||||
)
|
|
||||||
|
|
||||||
type (
|
|
||||||
qualifiedResource string
|
|
||||||
percentages map[qualifiedResource]int
|
|
||||||
)
|
|
||||||
|
|
||||||
func newPercentages() percentages {
|
|
||||||
return make(percentages, 4)
|
|
||||||
}
|
|
||||||
func (p percentages) rCPU() int {
|
|
||||||
return p[requestCPU]
|
|
||||||
}
|
|
||||||
func (p percentages) rMEM() int {
|
|
||||||
return p[requestMEM]
|
|
||||||
}
|
|
||||||
func (p percentages) lCPU() int {
|
|
||||||
return p[limitCPU]
|
|
||||||
}
|
|
||||||
func (p percentages) lMEM() int {
|
|
||||||
return p[limitMEM]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pod renders a K8s Pod to screen.
|
// Pod renders a K8s Pod to screen.
|
||||||
type Pod struct{}
|
type Pod struct{}
|
||||||
|
|
||||||
|
|
@ -109,7 +81,7 @@ func (Pod) Header(ns string) Header {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render renders a K8s resource to screen.
|
// Render renders a K8s resource to screen.
|
||||||
func (p Pod) Render(o interface{}, ns string, r *Row) error {
|
func (p Pod) Render(o interface{}, ns string, row *Row) error {
|
||||||
pwm, ok := o.(*PodWithMetrics)
|
pwm, ok := o.(*PodWithMetrics)
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("Expected PodWithMetrics, but got %T", o)
|
return fmt.Errorf("Expected PodWithMetrics, but got %T", o)
|
||||||
|
|
@ -122,10 +94,11 @@ func (p Pod) Render(o interface{}, ns string, r *Row) error {
|
||||||
|
|
||||||
ss := po.Status.ContainerStatuses
|
ss := po.Status.ContainerStatuses
|
||||||
cr, _, rc := p.Statuses(ss)
|
cr, _, rc := p.Statuses(ss)
|
||||||
c, perc, res := p.gatherPodMX(&po, pwm.MX)
|
|
||||||
|
c, r := p.gatherPodMX(&po, pwm.MX)
|
||||||
phase := p.Phase(&po)
|
phase := p.Phase(&po)
|
||||||
r.ID = client.MetaFQN(po.ObjectMeta)
|
row.ID = client.MetaFQN(po.ObjectMeta)
|
||||||
r.Fields = Fields{
|
row.Fields = Fields{
|
||||||
po.Namespace,
|
po.Namespace,
|
||||||
po.ObjectMeta.Name,
|
po.ObjectMeta.Name,
|
||||||
"●",
|
"●",
|
||||||
|
|
@ -134,12 +107,12 @@ func (p Pod) Render(o interface{}, ns string, r *Row) error {
|
||||||
phase,
|
phase,
|
||||||
toMc(c.cpu),
|
toMc(c.cpu),
|
||||||
toMi(c.mem),
|
toMi(c.mem),
|
||||||
toMc(res.cpu) + ":" + toMc(res.lcpu),
|
toMc(r.cpu) + ":" + toMc(r.lcpu),
|
||||||
toMi(res.mem) + ":" + toMi(res.lmem),
|
toMi(r.mem) + ":" + toMi(r.lmem),
|
||||||
strconv.Itoa(perc.rCPU()),
|
client.ToPercentageStr(c.cpu, r.cpu),
|
||||||
strconv.Itoa(perc.lCPU()),
|
client.ToPercentageStr(c.cpu, r.lcpu),
|
||||||
strconv.Itoa(perc.rMEM()),
|
client.ToPercentageStr(c.mem, r.mem),
|
||||||
strconv.Itoa(perc.lMEM()),
|
client.ToPercentageStr(c.mem, r.lmem),
|
||||||
na(po.Status.PodIP),
|
na(po.Status.PodIP),
|
||||||
na(po.Spec.NodeName),
|
na(po.Spec.NodeName),
|
||||||
p.mapQOS(po.Status.QOSClass),
|
p.mapQOS(po.Status.QOSClass),
|
||||||
|
|
@ -181,27 +154,16 @@ func (p *PodWithMetrics) DeepCopyObject() runtime.Object {
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Pod) gatherPodMX(pod *v1.Pod, mx *mv1beta1.PodMetrics) (metric, percentages, metric) {
|
func (*Pod) gatherPodMX(pod *v1.Pod, mx *mv1beta1.PodMetrics) (c, r metric) {
|
||||||
var c, r metric
|
|
||||||
p := newPercentages()
|
|
||||||
|
|
||||||
rcpu, rmem := podRequests(pod.Spec)
|
rcpu, rmem := podRequests(pod.Spec)
|
||||||
lcpu, lmem := podLimits(pod.Spec)
|
lcpu, lmem := podLimits(pod.Spec)
|
||||||
r.cpu, r.lcpu = rcpu.MilliValue(), lcpu.MilliValue()
|
r.cpu, r.lcpu, r.mem, r.lmem = rcpu.MilliValue(), lcpu.MilliValue(), rmem.Value(), lmem.Value()
|
||||||
r.mem, r.lmem = rmem.Value(), lmem.Value()
|
if mx != nil {
|
||||||
|
ccpu, cmem := currentRes(mx)
|
||||||
if mx == nil {
|
c.cpu, c.mem = ccpu.MilliValue(), cmem.Value()
|
||||||
return c, p, r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ccpu, cmem := currentRes(mx)
|
return
|
||||||
c.cpu = ccpu.MilliValue()
|
|
||||||
c.mem = cmem.Value()
|
|
||||||
|
|
||||||
p[requestCPU], p[limitCPU] = client.ToPercentage(c.cpu, r.cpu), client.ToPercentage(c.cpu, r.lcpu)
|
|
||||||
p[requestMEM], p[limitMEM] = client.ToPercentage(c.mem, r.mem), client.ToPercentage(c.mem, r.lmem)
|
|
||||||
|
|
||||||
return c, p, r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func containerRequests(co *v1.Container) v1.ResourceList {
|
func containerRequests(co *v1.Container) v1.ResourceList {
|
||||||
|
|
@ -220,12 +182,15 @@ func containerRequests(co *v1.Container) v1.ResourceList {
|
||||||
func podLimits(spec v1.PodSpec) (resource.Quantity, resource.Quantity) {
|
func podLimits(spec v1.PodSpec) (resource.Quantity, resource.Quantity) {
|
||||||
cpu, mem := new(resource.Quantity), new(resource.Quantity)
|
cpu, mem := new(resource.Quantity), new(resource.Quantity)
|
||||||
for _, co := range spec.Containers {
|
for _, co := range spec.Containers {
|
||||||
limit := co.Resources.Limits
|
limits := co.Resources.Limits
|
||||||
if limit.Cpu() != nil {
|
if len(limits) == 0 {
|
||||||
cpu.Add(*limit.Cpu())
|
return resource.Quantity{}, resource.Quantity{}
|
||||||
}
|
}
|
||||||
if limit.Memory() != nil {
|
if limits.Cpu() != nil {
|
||||||
mem.Add(*limit.Memory())
|
cpu.Add(*limits.Cpu())
|
||||||
|
}
|
||||||
|
if limits.Memory() != nil {
|
||||||
|
mem.Add(*limits.Memory())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *cpu, *mem
|
return *cpu, *mem
|
||||||
|
|
|
||||||
|
|
@ -159,7 +159,7 @@ func TestPodRender(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "default/nginx", r.ID)
|
assert.Equal(t, "default/nginx", r.ID)
|
||||||
e := render.Fields{"default", "nginx", "●", "1/1", "0", "Running", "100", "50", "100:0", "70:170", "100", "0", "71", "29", "172.17.0.6", "minikube", "BE"}
|
e := render.Fields{"default", "nginx", "●", "1/1", "0", "Running", "100", "50", "100:0", "70:170", "100", "n/a", "71", "29", "172.17.0.6", "minikube", "BE"}
|
||||||
assert.Equal(t, e, r.Fields[:17])
|
assert.Equal(t, e, r.Fields[:17])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,7 +190,7 @@ func TestPodInitRender(t *testing.T) {
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "default/nginx", r.ID)
|
assert.Equal(t, "default/nginx", r.ID)
|
||||||
e := render.Fields{"default", "nginx", "●", "1/1", "0", "Init:0/1", "10", "10", "100:0", "70:170", "10", "0", "14", "5", "172.17.0.6", "minikube", "BE"}
|
e := render.Fields{"default", "nginx", "●", "1/1", "0", "Init:0/1", "10", "10", "100:0", "70:170", "10", "n/a", "14", "5", "172.17.0.6", "minikube", "BE"}
|
||||||
assert.Equal(t, e, r.Fields[:17])
|
assert.Equal(t, e, r.Fields[:17])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ func startFwdCB(v ResourceViewer, path, co string, tt []client.PortTunnel) {
|
||||||
func showFwdDialog(v ResourceViewer, path string, cb PortForwardCB) error {
|
func showFwdDialog(v ResourceViewer, path string, cb PortForwardCB) error {
|
||||||
mm, err := fetchPodPorts(v.App().factory, path)
|
mm, err := fetchPodPorts(v.App().factory, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
ports := make([]string, 0, len(mm))
|
ports := make([]string, 0, len(mm))
|
||||||
for co, pp := range mm {
|
for co, pp := range mm {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue