Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/image/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ func (o *buildImageOptions) run(ctx context.Context) error {
return err
}

interactive := term.IsTerminal(int(os.Stdout.Fd()))
progress := map[string]int{}
p := 0
for {
Expand Down Expand Up @@ -61,7 +62,7 @@ func (o *buildImageOptions) run(ctx context.Context) error {
progress[msg.Id] = p
fmt.Println(data)
p++
} else if term.IsTerminal(int(os.Stdout.Fd())) {
} else if interactive {
fmt.Printf(progressRewrite, p-pos, data)
} else {
fmt.Println(data)
Expand Down
25 changes: 6 additions & 19 deletions cmd/image/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package image

import (
"context"
"errors"
"fmt"

corepb "github.com/projecteru2/core/rpc/gen"
Expand Down Expand Up @@ -42,29 +41,17 @@ func cmdImageList(ctx context.Context, cmd *cli.Command) error {
return err
}

opts, err := generateListOptions(cmd)
if err != nil {
return err
}

o := &listImageOptions{
client: client,
opts: opts,
opts: generateListOptions(cmd),
}
return o.run(ctx)
}

func generateListOptions(cmd *cli.Command) (*corepb.ListImageOptions, error) {
filter := cmd.String("filter")
podname := cmd.String(flagPod)
nodename := cmd.StringSlice(flagNode)
if len(nodename) == 0 && podname == "" {
return nil, errors.New("podname or nodenames should be given")
}

func generateListOptions(cmd *cli.Command) *corepb.ListImageOptions {
return &corepb.ListImageOptions{
Podname: podname,
Nodenames: nodename,
Filter: filter,
}, nil
Podname: cmd.String(flagPod),
Nodenames: cmd.StringSlice(flagNode),
Filter: cmd.String("filter"),
}
}
5 changes: 2 additions & 3 deletions cmd/node/add.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"context"
"errors"
"fmt"
"strconv"
"strings"

resourcetypes "github.com/projecteru2/core/resource/types"
Expand All @@ -26,7 +25,7 @@ func (o *addNodeOptions) run(ctx context.Context) error {
return err
}

describe.Nodes(describe.ToChan(node), false, false)
describe.Nodes(false, node)
return nil
}

Expand Down Expand Up @@ -66,7 +65,7 @@ func generateAddNodeOptions(cmd *cli.Command) (*corepb.AddNodeOptions, error) {
cpumem["cpu"] = cmd.Int("cpu")
}
if cmd.IsSet("share") {
cpumem["share"] = strconv.Itoa(cmd.Int("share"))
cpumem["share"] = cmd.Int("share")
}

resources, err := utils.EncodeResources(cmd, resourcetypes.Resources{
Expand Down
8 changes: 4 additions & 4 deletions cmd/node/add_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func TestGenerateAddNodeOptions(t *testing.T) {
name string
args []string
wantCPU int64
wantShare string
wantShare int64
wantMemory string
wantStorage string
wantVolumes []string
Expand All @@ -27,7 +27,7 @@ func TestGenerateAddNodeOptions(t *testing.T) {
name: "cpu and share",
args: []string{"node", "add", "--endpoint", "process://127.0.0.1", "--cpu", "64", "--share", "100", "dev"},
wantCPU: 64,
wantShare: "100",
wantShare: 100,
},
{
name: "memory storage and volumes",
Expand All @@ -49,8 +49,8 @@ func TestGenerateAddNodeOptions(t *testing.T) {
if got := cpumem.Int64("cpu"); got != tt.wantCPU {
t.Errorf("cpu: got %d, want %d", got, tt.wantCPU)
}
if got := cpumem.String("share"); got != tt.wantShare {
t.Errorf("share: got %q, want %q", got, tt.wantShare)
if got := cpumem.Int64("share"); got != tt.wantShare {
t.Errorf("share: got %d, want %d", got, tt.wantShare)
}
if got := cpumem.String("memory"); got != tt.wantMemory {
t.Errorf("memory: got %q, want %q", got, tt.wantMemory)
Expand Down
2 changes: 1 addition & 1 deletion cmd/node/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (o *getNodeOptions) run(ctx context.Context) error {
return err
}

describe.Nodes(describe.ToChan(node), true, false)
describe.Nodes(true, node)
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/node/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (o *nodeResourceOptions) run(ctx context.Context) error {
return err
}

describe.NodeResources(ctx, describe.ToChan(resource), false)
describe.NodeResource(ctx, resource)
return nil
}

Expand Down
62 changes: 18 additions & 44 deletions cmd/pod/nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package pod
import (
"context"
"errors"
"slices"
"strings"

corepb "github.com/projecteru2/core/rpc/gen"
Expand All @@ -24,59 +23,21 @@ type listPodNodesOptions struct {
}

func (o *listPodNodesOptions) run(ctx context.Context) error {
if o.filter == up || o.filter == all {
return o.listUpOrAll(ctx)
}
return o.listDown(ctx)
}

func (o *listPodNodesOptions) listDown(ctx context.Context) error {
allNodes, err := o.list(ctx, &corepb.ListNodesOptions{
Podname: o.name,
All: true,
Labels: o.labels,
TimeoutInSecond: o.timeoutInSecond,
SkipInfo: !o.showInfo,
})
if err != nil {
return err
}

downNodes := slices.DeleteFunc(allNodes, func(node *corepb.Node) bool {
return node.Available && !node.Bypass
})
describe.Nodes(describe.ToChan(downNodes...), o.showInfo, o.stream)
return nil
}

func (o *listPodNodesOptions) listUpOrAll(ctx context.Context) error {
ch, wait, err := o.listChan(ctx, &corepb.ListNodesOptions{
Podname: o.name,
All: o.filter == all,
All: o.filter != up,
Labels: o.labels,
TimeoutInSecond: o.timeoutInSecond,
SkipInfo: !o.showInfo,
})
if err != nil {
return err
}

describe.Nodes(ch, o.showInfo, o.stream)

return wait()
}

func (o *listPodNodesOptions) list(ctx context.Context, opt *corepb.ListNodesOptions) ([]*corepb.Node, error) {
ch, wait, err := o.listChan(ctx, opt)
if err != nil {
return nil, err
}

nodes := []*corepb.Node{}
for n := range ch {
nodes = append(nodes, n)
if o.filter == down {
ch = downOnly(ch)
}
return nodes, wait()
describe.NodesStream(ch, o.showInfo, o.stream)
return wait()
}

func (o *listPodNodesOptions) listChan(ctx context.Context, opt *corepb.ListNodesOptions) (<-chan *corepb.Node, func() error, error) {
Expand Down Expand Up @@ -110,3 +71,16 @@ func cmdPodListNodes(ctx context.Context, cmd *cli.Command) error {
}
return o.run(ctx)
}

func downOnly(nodes <-chan *corepb.Node) <-chan *corepb.Node {
down := make(chan *corepb.Node)
go func() {
defer close(down)
for node := range nodes {
if !node.Available || node.Bypass {
down <- node
}
}
}()
return down
}
7 changes: 0 additions & 7 deletions describe/image.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
package describe

import (
"fmt"
"os"
"slices"

"github.com/jedib0t/go-pretty/v6/table"
"github.com/jedib0t/go-pretty/v6/text"
Expand All @@ -15,11 +13,6 @@ func Images(msgs ...*corepb.ListImageMessage) {
}

func describeImages(msgs []*corepb.ListImageMessage) {
if !slices.ContainsFunc(msgs, func(msg *corepb.ListImageMessage) bool { return len(msg.Images) > 0 }) {
fmt.Println("no images")
return
}

t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{"Node", "Image", "Tags"})
Expand Down
5 changes: 3 additions & 2 deletions describe/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@ func TestImagesWithoutAnyImage(t *testing.T) {

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := captureStdout(t, func() { Images(tt.msgs...) }); got != "no images\n" {
t.Errorf("got %q, want %q", got, "no images\n")
want := "┌──────┬───────┬──────┐\n│ NODE │ IMAGE │ TAGS │\n├──────┼───────┼──────┤\n└──────┴───────┴──────┘\n"
if got := captureStdout(t, func() { Images(tt.msgs...) }); got != want {
t.Errorf("got %q, want the header-only table", got)
}
})
}
Expand Down
47 changes: 30 additions & 17 deletions describe/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,21 @@ import (
corepb "github.com/projecteru2/core/rpc/gen"
)

func Nodes(nodes <-chan *corepb.Node, showInfo, stream bool) {
// Nodes describes nodes a command already holds.
func Nodes(showInfo bool, nodes ...*corepb.Node) {
describeOr(nodes, func(all []*corepb.Node) { renderNodes(showInfo, all...) })
}

// NodesStream describes nodes as they arrive, one table per node when stream is set.
func NodesStream(nodes <-chan *corepb.Node, showInfo, stream bool) {
describeChOr(nodes, func(ch <-chan *corepb.Node) { describeNodes(ch, showInfo, stream) })
}

// NodeResource describes one node's resource.
func NodeResource(ctx context.Context, resource *corepb.NodeResource) {
describeOr(resource, func(r *corepb.NodeResource) { renderNodeResources(ctx, r) })
}

func NodeResources(ctx context.Context, resources <-chan *corepb.NodeResource, stream bool) {
describeChOr(resources, func(ch <-chan *corepb.NodeResource) { describeNodeResources(ctx, ch, stream) })
}
Expand All @@ -42,10 +53,6 @@ func describeNodes(nodes <-chan *corepb.Node, showInfo, stream bool) {
}

func renderNodes(showInfo bool, nodes ...*corepb.Node) {
if len(nodes) == 0 {
return
}

capacities := make([]resourcetypes.Resources, len(nodes))
usages := make([]resourcetypes.Resources, len(nodes))
for i, node := range nodes {
Expand Down Expand Up @@ -99,12 +106,25 @@ func nodePluginRows(capacity, usage resourcetypes.RawParams) []string {
}

func describeNodeResources(ctx context.Context, resources <-chan *corepb.NodeResource, stream bool) {
logger := log.WithFunc("describe.describeNodeResources")
if stream {
for resource := range resources {
renderNodeResources(ctx, resource)
}
return
}
all := []*corepb.NodeResource{}
for resource := range resources {
all = append(all, resource)
}
renderNodeResources(ctx, all...)
}

func renderNodeResources(ctx context.Context, resources ...*corepb.NodeResource) {
logger := log.WithFunc("describe.renderNodeResources")
t := table.NewWriter()
t.SetOutputMirror(os.Stdout)
t.AppendHeader(table.Row{headerName, "Cpu", "Memory", "Storage", "Volume", "Diffs"})

for resource := range resources {
for _, resource := range resources {
cr, sr, err := ToResourcePercent(resource)
if err != nil {
logger.Errorf(ctx, err, "resource percent of node %s", resource.Name)
Expand All @@ -120,16 +140,9 @@ func describeNodeResources(ctx context.Context, resources <-chan *corepb.NodeRes
}
t.AppendRows(toTableRows(rows))
t.AppendSeparator()
if stream {
t.SetStyle(table.StyleLight)
t.Render()
t.ResetRows()
}
}
if !stream {
t.SetStyle(table.StyleLight)
t.Render()
}
t.SetStyle(table.StyleLight)
t.Render()
}

func describeNodeStatusMessage(ctx context.Context, ms []*corepb.NodeStatusStreamMessage) {
Expand Down
10 changes: 5 additions & 5 deletions describe/node_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ func TestNodes(t *testing.T) {
Format = tt.format
t.Cleanup(func() { Format = "" })

if got := captureStdout(t, func() { Nodes(ToChan(testNodes()...), false, false) }); got != tt.want {
if got := captureStdout(t, func() { NodesStream(ToChan(testNodes()...), false, false) }); got != tt.want {
t.Errorf("got\n%s\nwant\n%s", got, tt.want)
}
})
Expand Down Expand Up @@ -114,7 +114,7 @@ func TestNodesWithInfo(t *testing.T) {
│ │ │ │ memory: 1024 │ │
└───────┴─────────────────────┴─────────────────┴──────────────┴───────────────────────┘
`
got := captureStdout(t, func() { Nodes(ToChan(testNodes()...), true, false) })
got := captureStdout(t, func() { NodesStream(ToChan(testNodes()...), true, false) })
if got != want {
t.Errorf("got\n%s\nwant\n%s", got, want)
}
Expand Down Expand Up @@ -195,7 +195,7 @@ func TestNodesStream(t *testing.T) {
│ │ │ │ memory: 1024 │
└───────┴─────────────────────┴─────────────────┴──────────────┘
`
got := captureStdout(t, func() { Nodes(ToChan(testNodes()...), false, true) })
got := captureStdout(t, func() { NodesStream(ToChan(testNodes()...), false, true) })
if got != want {
t.Errorf("got\n%s\nwant\n%s", got, want)
}
Expand Down Expand Up @@ -340,10 +340,10 @@ func TestNodesPluginColumns(t *testing.T) {
t.Run(tt.name, func(t *testing.T) {
got := captureStdout(t, func() {
if tt.showInfo {
Nodes(ToChan(tt.nodes...), true, false)
NodesStream(ToChan(tt.nodes...), true, false)
return
}
Nodes(ToChan(tt.nodes...), false, false)
NodesStream(ToChan(tt.nodes...), false, false)
})
if got != tt.want {
t.Errorf("got\n%s\nwant\n%s", got, tt.want)
Expand Down
4 changes: 0 additions & 4 deletions describe/workload.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,6 @@ func describeStatistics(stat workloadStatistics) {
}

func describeWorkloads(workloads []*corepb.Workload) {
if len(workloads) == 0 {
return
}

resources := make([]resourcetypes.Resources, len(workloads))
for i, workload := range workloads {
resources[i] = unmarshalResources(workload.Resources)
Expand Down
Loading