From f631ec6c2de954b98f66e15ffbf4eb67bf012380 Mon Sep 17 00:00:00 2001 From: Nick Ethier Date: Tue, 27 Aug 2019 23:59:36 -0400 Subject: [PATCH] cli: display group ports and address in alloc status command output (#6189) * cli: display group ports and address in alloc status command output * add assertions for port.To = -1 case and convert assertions to testify --- api/resources.go | 9 ++++- command/alloc_status.go | 31 ++++++++++++++++ nomad/structs/network.go | 7 ++++ nomad/structs/network_test.go | 70 +++++++++++++---------------------- 4 files changed, 71 insertions(+), 46 deletions(-) diff --git a/api/resources.go b/api/resources.go index c5fb8f49f..cbd24c4bf 100644 --- a/api/resources.go +++ b/api/resources.go @@ -99,7 +99,6 @@ type NetworkResource struct { MBits *int ReservedPorts []Port DynamicPorts []Port - Services []*Service } func (n *NetworkResource) Canonicalize() { @@ -108,6 +107,14 @@ func (n *NetworkResource) Canonicalize() { } } +func (n *NetworkResource) HasPorts() bool { + if n == nil { + return false + } + + return len(n.ReservedPorts)+len(n.DynamicPorts) > 0 +} + // NodeDeviceResource captures a set of devices sharing a common // vendor/type/device_name tuple. type NodeDeviceResource struct { diff --git a/command/alloc_status.go b/command/alloc_status.go index 152d35986..350894ea7 100644 --- a/command/alloc_status.go +++ b/command/alloc_status.go @@ -191,6 +191,11 @@ func (c *AllocStatusCommand) Run(args []string) int { } c.Ui.Output(output) + if len(alloc.AllocatedResources.Shared.Networks) > 0 && alloc.AllocatedResources.Shared.Networks[0].HasPorts() { + c.Ui.Output("") + c.Ui.Output(formatAllocNetworkInfo(alloc)) + } + if short { c.shortTaskStatus(alloc) } else { @@ -299,6 +304,32 @@ func formatAllocBasicInfo(alloc *api.Allocation, client *api.Client, uuidLength return formatKV(basic), nil } +func formatAllocNetworkInfo(alloc *api.Allocation) string { + nw := alloc.AllocatedResources.Shared.Networks[0] + addrs := make([]string, len(nw.DynamicPorts)+len(nw.ReservedPorts)+1) + addrs[0] = "Label|Dynamic|Address" + portFmt := func(port *api.Port, dyn string) string { + s := fmt.Sprintf("%s|%s|%s:%d", port.Label, dyn, nw.IP, port.Value) + if port.To > 0 { + s += fmt.Sprintf(" -> %d", port.To) + } + return s + } + for idx, port := range nw.DynamicPorts { + addrs[idx+1] = portFmt(&port, "yes") + } + for idx, port := range nw.ReservedPorts { + addrs[idx+1+len(nw.DynamicPorts)] = portFmt(&port, "yes") + } + + var mode string + if nw.Mode != "" { + mode = fmt.Sprintf(" (mode = %q)", nw.Mode) + } + + return fmt.Sprintf("Allocation Addresses%s\n%s", mode, formatList(addrs)) +} + // futureEvalTimePretty returns when the eval is eligible to reschedule // relative to current time, based on the WaitUntil field func futureEvalTimePretty(evalID string, client *api.Client) string { diff --git a/nomad/structs/network.go b/nomad/structs/network.go index d76eeaf96..e37158cf1 100644 --- a/nomad/structs/network.go +++ b/nomad/structs/network.go @@ -286,6 +286,7 @@ func (idx *NetworkIndex) AssignNetwork(ask *NetworkResource) (out *NetworkResour // Create the offer offer := &NetworkResource{ + Mode: ask.Mode, Device: n.Device, IP: ipStr, MBits: ask.MBits, @@ -312,6 +313,12 @@ func (idx *NetworkIndex) AssignNetwork(ask *NetworkResource) (out *NetworkResour BUILD_OFFER: for i, port := range dynPorts { offer.DynamicPorts[i].Value = port + + // This syntax allows you to set the mapped to port to the same port + // allocated by the scheduler on the host. + if offer.DynamicPorts[i].To == -1 { + offer.DynamicPorts[i].To = port + } } // Stop, we have an offer! diff --git a/nomad/structs/network_test.go b/nomad/structs/network_test.go index 1806f9482..ece42c964 100644 --- a/nomad/structs/network_test.go +++ b/nomad/structs/network_test.go @@ -5,6 +5,8 @@ import ( "net" "reflect" "testing" + + "github.com/stretchr/testify/require" ) func TestNetworkIndex_Overcommitted(t *testing.T) { @@ -252,42 +254,30 @@ func TestNetworkIndex_AssignNetwork(t *testing.T) { ReservedPorts: []Port{{"main", 8000, 0}}, } offer, err := idx.AssignNetwork(ask) - if err != nil { - t.Fatalf("err: %v", err) - } - if offer == nil { - t.Fatalf("bad") - } - if offer.IP != "192.168.0.101" { - t.Fatalf("bad: %#v", offer) - } + require.NoError(t, err) + require.NotNil(t, offer) + require.Equal(t, "192.168.0.101", offer.IP) rp := Port{"main", 8000, 0} - if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp { - t.Fatalf("bad: %#v", offer) - } + require.Len(t, offer.ReservedPorts, 1) + require.Exactly(t, rp, offer.ReservedPorts[0]) // Ask for dynamic ports ask = &NetworkResource{ - DynamicPorts: []Port{{"http", 0, 80}, {"https", 0, 443}, {"admin", 0, 8080}}, + DynamicPorts: []Port{{"http", 0, 80}, {"https", 0, 443}, {"admin", 0, -1}}, } offer, err = idx.AssignNetwork(ask) - if err != nil { - t.Fatalf("err: %v", err) - } - if offer == nil { - t.Fatalf("bad") - } - if offer.IP != "192.168.0.100" { - t.Fatalf("bad: %#v", offer) - } - if len(offer.DynamicPorts) != 3 { - t.Fatalf("There should be three dynamic ports") - } + require.NoError(t, err) + require.NotNil(t, offer) + require.Equal(t, "192.168.0.100", offer.IP) + require.Len(t, offer.DynamicPorts, 3) + var adminPort Port for _, port := range offer.DynamicPorts { - if port.Value == 0 { - t.Fatalf("Dynamic Port: %v should have been assigned a host port", port.Label) + require.NotZero(t, port.Value) + if port.Label == "admin" { + adminPort = port } } + require.Equal(t, adminPort.Value, adminPort.To) // Ask for reserved + dynamic ports ask = &NetworkResource{ @@ -295,32 +285,22 @@ func TestNetworkIndex_AssignNetwork(t *testing.T) { DynamicPorts: []Port{{"http", 0, 80}, {"https", 0, 443}, {"admin", 0, 8080}}, } offer, err = idx.AssignNetwork(ask) - if err != nil { - t.Fatalf("err: %v", err) - } - if offer == nil { - t.Fatalf("bad") - } - if offer.IP != "192.168.0.100" { - t.Fatalf("bad: %#v", offer) - } + require.NoError(t, err) + require.NotNil(t, offer) + require.Equal(t, "192.168.0.100", offer.IP) rp = Port{"main", 2345, 0} - if len(offer.ReservedPorts) != 1 || offer.ReservedPorts[0] != rp { - t.Fatalf("bad: %#v", offer) - } + require.Len(t, offer.ReservedPorts, 1) + require.Exactly(t, rp, offer.ReservedPorts[0]) // Ask for too much bandwidth ask = &NetworkResource{ MBits: 1000, } offer, err = idx.AssignNetwork(ask) - if err.Error() != "bandwidth exceeded" { - t.Fatalf("err: %v", err) - } - if offer != nil { - t.Fatalf("bad") - } + require.Error(t, err) + require.Equal(t, "bandwidth exceeded", err.Error()) + require.Nil(t, offer) } // This test ensures that even with a small domain of available ports we are