diff --git a/go.sum b/go.sum index dfbdf025..a37e8a33 100644 --- a/go.sum +++ b/go.sum @@ -733,14 +733,6 @@ github.com/tsuru/config v0.0.0-20201023175036-375aaee8b560 h1:fniQ/BmYAHdnNmY333 github.com/tsuru/config v0.0.0-20201023175036-375aaee8b560/go.mod h1:mj6t8JKWU51GScTT50XRmDj65T5XhTyNvO5FUNV5zS4= github.com/tsuru/gnuflag v0.0.0-20151217162021-86b8c1b864aa h1:JlLQP1xa13a994p/Aau2e3K9xXYaHNoNvTDVIMHSUa4= github.com/tsuru/gnuflag v0.0.0-20151217162021-86b8c1b864aa/go.mod h1:UibOSvkMFKRe/eiwktAPAvQG8L+p8nYsECJvu3Dgw7I= -github.com/tsuru/go-tsuruclient v0.0.0-20231004185254-b386081b2ca8 h1:ne140iJLe0drfwdz4cvTrTf/rmyirD8VI+Ivm+l6XxU= -github.com/tsuru/go-tsuruclient v0.0.0-20231004185254-b386081b2ca8/go.mod h1:BmePxHey9hxrxk0kzTMHFFr7aJWXSxtlrUx6FIeV0Ic= -github.com/tsuru/go-tsuruclient v0.0.0-20231005173907-4607cc1f111e h1:SyzgPCFdzo4u8BKIXKGm5+wqSSX5kttnsjMPEzThl3I= -github.com/tsuru/go-tsuruclient v0.0.0-20231005173907-4607cc1f111e/go.mod h1:BmePxHey9hxrxk0kzTMHFFr7aJWXSxtlrUx6FIeV0Ic= -github.com/tsuru/tablecli v0.0.0-20190131152944-7ded8a3383c6 h1:1XDdWFAjIbCSG1OjN9v9KdWhuM8UtYlFcfHe/Ldkchk= -github.com/tsuru/tablecli v0.0.0-20190131152944-7ded8a3383c6/go.mod h1:ztYpOhW+u1k21FEqp7nZNgpWbr0dUKok5lgGCZi+1AQ= -github.com/tsuru/tsuru v0.0.0-20231003184130-e29d84f36397 h1:9NpNEFIUgmEPI4H+ngFQGisRrpHv2UWKoiPApXUaCfI= -github.com/tsuru/tsuru v0.0.0-20231003184130-e29d84f36397/go.mod h1:is8CUBIZaH1mwyvvL3br5Bts/a29iTAQqEQbV7jSOJQ= github.com/tsuru/go-tsuruclient v0.0.0-20231009130311-a01dfd615e16 h1:gjwhjJTOuPlHhytkBXvfEzIzyYytePVvGeq7REbeBGY= github.com/tsuru/go-tsuruclient v0.0.0-20231009130311-a01dfd615e16/go.mod h1:BmePxHey9hxrxk0kzTMHFFr7aJWXSxtlrUx6FIeV0Ic= github.com/tsuru/tablecli v0.0.0-20190131152944-7ded8a3383c6 h1:1XDdWFAjIbCSG1OjN9v9KdWhuM8UtYlFcfHe/Ldkchk= diff --git a/tsuru/client/plan.go b/tsuru/client/plan.go index e3d486ea..d8094b5e 100644 --- a/tsuru/client/plan.go +++ b/tsuru/client/plan.go @@ -54,15 +54,7 @@ func renderPlans(plans []apptypes.Plan, isBytes, showDefaultColumn bool, showMax showBurstColumn := false for _, p := range plans { - if p.CPUMilli == 0 { - continue - } - if p.CPUBurst.Default != 0 { - showBurstColumn = true - break - } - - if p.Override.CPUBurst != nil { + if hasBurst(p) { showBurstColumn = true break } @@ -129,7 +121,21 @@ func renderPlans(plans []apptypes.Plan, isBytes, showDefaultColumn bool, showMax func renderPlansK8SFriendly(plans []apptypes.Plan, showMaxBurstAllowed bool) string { table := tablecli.NewTable() - table.Headers = []string{"Name", "CPU requests", "CPU limits"} + table.Headers = []string{"Name"} + + showCPULimitsColumn := false + for _, p := range plans { + if hasBurst(p) { + showCPULimitsColumn = true + break + } + } + + if showCPULimitsColumn { + table.Headers = append(table.Headers, "CPU requests", "CPU limits") + } else { + table.Headers = append(table.Headers, "CPU requests/limits") + } if showMaxBurstAllowed { table.Headers = append(table.Headers, "CPU limits (max customizable)") @@ -140,13 +146,21 @@ func renderPlansK8SFriendly(plans []apptypes.Plan, showMaxBurstAllowed bool) str for _, p := range plans { memory := resource.NewQuantity(p.Memory, resource.BinarySI).String() cpuRequest := resource.NewMilliQuantity(int64(p.CPUMilli), resource.DecimalSI).String() - defaultCPULimit := resource.NewMilliQuantity(int64(float64(p.CPUMilli)*p.CPUBurst.Default), resource.DecimalSI).String() maxCPULimit := resource.NewMilliQuantity(int64(float64(p.CPUMilli)*p.CPUBurst.MaxAllowed), resource.DecimalSI).String() row := []string{ p.Name, - cpuRequest, - defaultCPULimit, + } + + if showCPULimitsColumn { + cpuBurst := p.CPUBurst.Default + if cpuBurst < 1 { + cpuBurst = 1 + } + defaultCPULimit := resource.NewMilliQuantity(int64(float64(p.CPUMilli)*cpuBurst), resource.DecimalSI).String() + row = append(row, cpuRequest, defaultCPULimit) + } else { + row = append(row, cpuRequest) } if showMaxBurstAllowed { @@ -160,6 +174,20 @@ func renderPlansK8SFriendly(plans []apptypes.Plan, showMaxBurstAllowed bool) str return table.String() } +func hasBurst(p apptypes.Plan) bool { + if p.CPUMilli == 0 { + return false + } + if p.CPUBurst.Default != 0 { + return true + } + + if p.Override.CPUBurst != nil { + return true + } + return false +} + func displayCPUBurst(currentCPU int, burst float64) string { if currentCPU == 0 || burst < 1 { return "" diff --git a/tsuru/client/plan_test.go b/tsuru/client/plan_test.go index dcc8fd13..2ed7f986 100644 --- a/tsuru/client/plan_test.go +++ b/tsuru/client/plan_test.go @@ -82,6 +82,36 @@ func (s *S) TestPlanListHuman(c *check.C) { c.Assert(stdout.String(), check.Equals, expected) } +func (s *S) TestPlanListKubernetesFriendly(c *check.C) { + var stdout, stderr bytes.Buffer + result := `[ + {"name": "test", "cpumilli": 300, "memory": 536870912, "default": false} +]` + expected := `+------+---------------------+------------------------+---------+ +| Name | CPU requests/limits | Memory requests/limits | Default | ++------+---------------------+------------------------+---------+ +| test | 300m | 512Mi | false | ++------+---------------------+------------------------+---------+ +` + context := cmd.Context{ + Args: []string{}, + Stdout: &stdout, + Stderr: &stderr, + } + trans := &cmdtest.ConditionalTransport{ + Transport: cmdtest.Transport{Message: string(result), Status: http.StatusOK}, + CondFunc: func(req *http.Request) bool { + return strings.HasSuffix(req.URL.Path, "/plans") && req.Method == "GET" + }, + } + client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager) + command := PlanList{k8sFriendly: true} + // command.Flags().Parse(true, []string{"-h"}) + err := command.Run(&context, client) + c.Assert(err, check.IsNil) + c.Assert(stdout.String(), check.Equals, expected) +} + func (s *S) TestPlanListOverride(c *check.C) { var stdout, stderr bytes.Buffer result := `[ @@ -142,6 +172,36 @@ func (s *S) TestPlanListWithBurst(c *check.C) { c.Assert(stdout.String(), check.Equals, expected) } +func (s *S) TestPlanListWithBurstKubernetesFriendly(c *check.C) { + var stdout, stderr bytes.Buffer + result := `[ + {"name": "test", "cpumilli": 300, "memory": 536870912, "default": false, "cpuBurst": {"default": 1.1}} +]` + expected := `+------+--------------+------------+------------------------+---------+ +| Name | CPU requests | CPU limits | Memory requests/limits | Default | ++------+--------------+------------+------------------------+---------+ +| test | 300m | 330m | 512Mi | false | ++------+--------------+------------+------------------------+---------+ +` + context := cmd.Context{ + Args: []string{}, + Stdout: &stdout, + Stderr: &stderr, + } + trans := &cmdtest.ConditionalTransport{ + Transport: cmdtest.Transport{Message: string(result), Status: http.StatusOK}, + CondFunc: func(req *http.Request) bool { + return strings.HasSuffix(req.URL.Path, "/plans") && req.Method == "GET" + }, + } + client := cmd.NewClient(&http.Client{Transport: trans}, nil, manager) + command := PlanList{k8sFriendly: true} + // command.Flags().Parse(true, []string{"-h"}) + err := command.Run(&context, client) + c.Assert(err, check.IsNil) + c.Assert(stdout.String(), check.Equals, expected) +} + func (s *S) TestPlanListWithBurstAndMaxAllowed(c *check.C) { var stdout, stderr bytes.Buffer result := `[