fix: provide peer remote address for 'NODE': as default in osctl

This change is pretty mechanical, just wrap every API so that remote
peer address is used as default for `resp.Metadata.Hostname`.

This makes `NODE:` non-empty in all the API calls.

Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
This commit is contained in:
Andrey Smirnov 2019-12-04 21:57:10 +03:00 committed by Andrey Smirnov
parent 43e6703b8b
commit fc52025490
13 changed files with 325 additions and 116 deletions

View File

@ -14,7 +14,9 @@ import (
criconstants "github.com/containerd/cri/pkg/constants"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
"github.com/talos-systems/talos/api/common"
osapi "github.com/talos-systems/talos/api/os"
@ -50,20 +52,24 @@ var containersCmd = &cobra.Command{
md := metadata.New(make(map[string]string))
md.Set("targets", target...)
reply, err := c.Containers(metadata.NewOutgoingContext(globalCtx, md), namespace, driver)
var remotePeer peer.Peer
reply, err := c.Containers(metadata.NewOutgoingContext(globalCtx, md), namespace, driver, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error getting process list: %s", err)
}
containerRender(reply)
containerRender(&remotePeer, reply)
})
},
}
func containerRender(reply *osapi.ContainersReply) {
func containerRender(remotePeer *peer.Peer, reply *osapi.ContainersReply) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tNAMESPACE\tID\tIMAGE\tPID\tSTATUS")
defaultNode := addrFromPeer(remotePeer)
for _, rep := range reply.Response {
resp := rep
sort.Slice(resp.Containers,
@ -78,7 +84,7 @@ func containerRender(reply *osapi.ContainersReply) {
display = "└─ " + display
}
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -11,6 +11,8 @@ import (
"text/tabwriter"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/peer"
networkapi "github.com/talos-systems/talos/api/network"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
@ -29,22 +31,26 @@ var interfacesCmd = &cobra.Command{
}
setupClient(func(c *client.Client) {
reply, err := c.Interfaces(globalCtx)
var remotePeer peer.Peer
reply, err := c.Interfaces(globalCtx, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error getting interfaces: %s", err)
}
intersRender(reply)
intersRender(&remotePeer, reply)
})
},
}
func intersRender(reply *networkapi.InterfacesReply) {
func intersRender(remotePeer *peer.Peer, reply *networkapi.InterfacesReply) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tINDEX\tNAME\tMAC\tMTU\tADDRESS")
defaultNode := addrFromPeer(remotePeer)
for _, resp := range reply.Response {
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -11,6 +11,8 @@ import (
"text/tabwriter"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/peer"
osapi "github.com/talos-systems/talos/api/os"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
@ -32,26 +34,30 @@ var memoryCmd = &cobra.Command{
}
setupClient(func(c *client.Client) {
reply, err := c.Memory(globalCtx)
var remotePeer peer.Peer
reply, err := c.Memory(globalCtx, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error getting memory stats: %s", err)
}
if verbose {
verboseRender(reply)
verboseRender(&remotePeer, reply)
} else {
briefRender(reply)
briefRender(&remotePeer, reply)
}
})
},
}
func briefRender(reply *osapi.MemInfoReply) {
func briefRender(remotePeer *peer.Peer, reply *osapi.MemInfoReply) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tTOTAL\tUSED\tFREE\tSHARED\tBUFFERS\tCACHE\tAVAILABLE")
defaultNode := addrFromPeer(remotePeer)
for _, resp := range reply.Response {
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname
@ -73,13 +79,18 @@ func briefRender(reply *osapi.MemInfoReply) {
helpers.Should(w.Flush())
}
func verboseRender(reply *osapi.MemInfoReply) {
func verboseRender(remotePeer *peer.Peer, reply *osapi.MemInfoReply) {
defaultNode := addrFromPeer(remotePeer)
// Dump as /proc/meminfo
for _, resp := range reply.Response {
node := defaultNode
if resp.Metadata != nil {
fmt.Printf("%s: %s\n", "NODE", resp.Metadata.Hostname)
node = resp.Metadata.Hostname
}
fmt.Printf("%s: %s\n", "NODE", node)
fmt.Printf("%s: %d %s\n", "MemTotal", resp.Meminfo.Memtotal, "kB")
fmt.Printf("%s: %d %s\n", "MemFree", resp.Meminfo.Memfree, "kB")
fmt.Printf("%s: %d %s\n", "MemAvailable", resp.Meminfo.Memavailable, "kB")

View File

@ -12,6 +12,8 @@ import (
"text/tabwriter"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/peer"
machineapi "github.com/talos-systems/talos/api/machine"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
@ -31,15 +33,24 @@ var mountsCmd = &cobra.Command{
}
setupClient(func(c *client.Client) {
mountsRender(c.Mounts(globalCtx))
var remotePeer peer.Peer
reply, err := c.Mounts(globalCtx, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error getting interfaces: %s", err)
}
mountsRender(&remotePeer, reply)
})
},
}
func mountsRender(reply *machineapi.MountsReply, err error) {
func mountsRender(remotePeer *peer.Peer, reply *machineapi.MountsReply) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tFILESYSTEM\tSIZE(GB)\tUSED(GB)\tAVAILABLE(GB)\tPERCENT USED\tMOUNTED ON")
defaultNode := addrFromPeer(remotePeer)
for _, resp := range reply.Response {
for _, r := range resp.Stats {
percentAvailable := 100.0 - 100.0*(float64(r.Available)/float64(r.Size))
@ -48,7 +59,7 @@ func mountsRender(reply *machineapi.MountsReply, err error) {
continue
}
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -20,7 +20,9 @@ import (
"github.com/ryanuber/columnize"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
osapi "github.com/talos-systems/talos/api/os"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
@ -182,7 +184,9 @@ var cpu = func(p1, p2 *osapi.Process) bool {
//nolint: gocyclo
func processesOutput(ctx context.Context, c *client.Client) (output string, err error) {
reply, err := c.Processes(ctx)
var remotePeer peer.Peer
reply, err := c.Processes(ctx, grpc.Peer(&remotePeer))
if err != nil {
// TODO: Figure out how to expose errors to client without messing
// up display
@ -191,6 +195,8 @@ func processesOutput(ctx context.Context, c *client.Client) (output string, err
return output, nil
}
defaultNode := addrFromPeer(&remotePeer)
s := []string{}
s = append(s, "NODE | PID | STATE | THREADS | CPU-TIME | VIRTMEM | RESMEM | COMMAND")
@ -217,7 +223,7 @@ func processesOutput(ctx context.Context, c *client.Client) (output string, err
args = p.Args
}
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -200,9 +200,15 @@ func remotePeer(ctx context.Context) (peerHost string) {
remote, ok := peer.FromContext(ctx)
if ok {
peerHost = remote.Addr.String()
peerHost, _, _ = net.SplitHostPort(peerHost) //nolint: errcheck
peerHost = addrFromPeer(remote)
}
return
}
func addrFromPeer(remote *peer.Peer) (peerHost string) {
peerHost = remote.Addr.String()
peerHost, _, _ = net.SplitHostPort(peerHost) //nolint: errcheck
return peerHost
}

View File

@ -11,6 +11,8 @@ import (
"text/tabwriter"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/peer"
networkapi "github.com/talos-systems/talos/api/network"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
@ -29,22 +31,25 @@ var routesCmd = &cobra.Command{
}
setupClient(func(c *client.Client) {
reply, err := c.Routes(globalCtx)
var remotePeer peer.Peer
reply, err := c.Routes(globalCtx, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error getting routes: %s", err)
}
routesRender(reply)
routesRender(&remotePeer, reply)
})
},
}
func routesRender(reply *networkapi.RoutesReply) {
func routesRender(remotePeer *peer.Peer, reply *networkapi.RoutesReply) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tINTERFACE\tDESTINATION\tGATEWAY\tMETRIC")
defaultNode := addrFromPeer(remotePeer)
for _, resp := range reply.Response {
var node string
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -12,6 +12,8 @@ import (
"github.com/golang/protobuf/ptypes"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/peer"
machineapi "github.com/talos-systems/talos/api/machine"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
@ -63,7 +65,9 @@ With actions 'start', 'stop', 'restart', service state is updated respectively.`
}
func serviceList(c *client.Client) {
reply, err := c.ServiceList(globalCtx)
var remotePeer peer.Peer
reply, err := c.ServiceList(globalCtx, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error listing services: %s", err)
}
@ -71,11 +75,13 @@ func serviceList(c *client.Client) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tSERVICE\tSTATE\tHEALTH\tLAST CHANGE\tLAST EVENT")
defaultNode := addrFromPeer(&remotePeer)
for _, resp := range reply.Response {
for _, s := range resp.Services {
svc := serviceInfoWrapper{s}
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname
@ -89,29 +95,27 @@ func serviceList(c *client.Client) {
}
func serviceInfo(c *client.Client, id string) {
reply, err := c.ServiceInfo(globalCtx, id)
var remotePeer peer.Peer
services, err := c.ServiceInfo(globalCtx, id, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error listing services: %s", err)
}
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
services := make([]*machineapi.ServiceInfo, 0, len(reply.Response))
defaultNode := addrFromPeer(&remotePeer)
for _, resp := range reply.Response {
for _, svc := range resp.Services {
if svc.Id == id {
services = append(services, svc)
for _, s := range services {
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname
if s.Metadata != nil {
node = s.Metadata.Hostname
}
fmt.Fprintf(w, "NODE\t%s\n", node)
svc := serviceInfoWrapper{s}
svc := serviceInfoWrapper{s.Service}
fmt.Fprintf(w, "ID\t%s\n", svc.Id)
fmt.Fprintf(w, "STATE\t%s\n", svc.State)
fmt.Fprintf(w, "HEALTH\t%s\n", svc.HealthStatus())
@ -131,9 +135,6 @@ func serviceInfo(c *client.Client, id string) {
label = ""
}
}
}
}
}
if len(services) == 0 {
helpers.Fatalf("service %q is not registered on any nodes", id)
@ -143,16 +144,20 @@ func serviceInfo(c *client.Client, id string) {
}
func serviceStart(c *client.Client, id string) {
reply, err := c.ServiceStart(globalCtx, id)
var remotePeer peer.Peer
reply, err := c.ServiceStart(globalCtx, id, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error starting service: %s", err)
}
defaultNode := addrFromPeer(&remotePeer)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tRESPONSE")
for _, resp := range reply.Response {
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname
@ -165,16 +170,20 @@ func serviceStart(c *client.Client, id string) {
}
func serviceStop(c *client.Client, id string) {
reply, err := c.ServiceStop(globalCtx, id)
var remotePeer peer.Peer
reply, err := c.ServiceStop(globalCtx, id, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error starting service: %s", err)
}
defaultNode := addrFromPeer(&remotePeer)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tRESPONSE")
for _, resp := range reply.Response {
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname
@ -187,16 +196,20 @@ func serviceStop(c *client.Client, id string) {
}
func serviceRestart(c *client.Client, id string) {
reply, err := c.ServiceRestart(globalCtx, id)
var remotePeer peer.Peer
reply, err := c.ServiceRestart(globalCtx, id, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error starting service: %s", err)
}
defaultNode := addrFromPeer(&remotePeer)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tRESPONSE")
for _, resp := range reply.Response {
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -14,7 +14,9 @@ import (
criconstants "github.com/containerd/cri/pkg/constants"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/peer"
"github.com/talos-systems/talos/api/common"
osapi "github.com/talos-systems/talos/api/os"
@ -47,21 +49,26 @@ var statsCmd = &cobra.Command{
}
md := metadata.New(make(map[string]string))
md.Set("targets", target...)
reply, err := c.Stats(metadata.NewOutgoingContext(globalCtx, md), namespace, driver)
var remotePeer peer.Peer
reply, err := c.Stats(metadata.NewOutgoingContext(globalCtx, md), namespace, driver, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error getting stats: %s", err)
}
statsRender(reply)
statsRender(&remotePeer, reply)
})
},
}
func statsRender(reply *osapi.StatsReply) {
func statsRender(remotePeer *peer.Peer, reply *osapi.StatsReply) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tNAMESPACE\tID\tMEMORY(MB)\tCPU")
defaultNode := addrFromPeer(remotePeer)
for _, rep := range reply.Response {
resp := rep
sort.Slice(resp.Stats,
@ -76,7 +83,7 @@ func statsRender(reply *osapi.StatsReply) {
display = "└─ " + display
}
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -12,6 +12,8 @@ import (
"github.com/golang/protobuf/ptypes"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/peer"
timeapi "github.com/talos-systems/talos/api/time"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
@ -30,14 +32,18 @@ var timeCmd = &cobra.Command{
helpers.Fatalf("failed to parse check flag: %w", err)
}
var reply *timeapi.TimeReply
var (
reply *timeapi.TimeReply
remotePeer peer.Peer
)
if server == "" {
reply, err = c.Time(globalCtx)
reply, err = c.Time(globalCtx, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error fetching time: %s", err)
}
} else {
reply, err = c.TimeCheck(globalCtx, server)
reply, err = c.TimeCheck(globalCtx, server, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error fetching time: %s", err)
}
@ -46,9 +52,11 @@ var timeCmd = &cobra.Command{
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tNTP-SERVER\tLOCAL-TIME\tREMOTE-TIME")
defaultNode := addrFromPeer(&remotePeer)
var localtime, remotetime time.Time
for _, resp := range reply.Response {
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -12,6 +12,8 @@ import (
"time"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/peer"
machineapi "github.com/talos-systems/talos/api/machine"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
@ -39,12 +41,13 @@ func upgrade() {
var (
err error
reply *machineapi.UpgradeReply
remotePeer peer.Peer
)
setupClient(func(c *client.Client) {
// TODO: See if we can validate version and prevent starting upgrades to
// an unknown version
reply, err = c.Upgrade(globalCtx, upgradeImage)
reply, err = c.Upgrade(globalCtx, upgradeImage, grpc.Peer(&remotePeer))
})
if err != nil {
@ -54,8 +57,10 @@ func upgrade() {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
fmt.Fprintln(w, "NODE\tACK\tSTARTED")
defaultNode := addrFromPeer(&remotePeer)
for _, resp := range reply.Response {
node := ""
node := defaultNode
if resp.Metadata != nil {
node = resp.Metadata.Hostname

View File

@ -9,6 +9,8 @@ import (
"os"
"github.com/spf13/cobra"
"google.golang.org/grpc"
"google.golang.org/grpc/peer"
"github.com/talos-systems/talos/cmd/osctl/pkg/client"
"github.com/talos-systems/talos/cmd/osctl/pkg/helpers"
@ -45,15 +47,24 @@ var versionCmd = &cobra.Command{
fmt.Println("Server:")
setupClient(func(c *client.Client) {
reply, err := c.Version(globalCtx)
var remotePeer peer.Peer
reply, err := c.Version(globalCtx, grpc.Peer(&remotePeer))
if err != nil {
helpers.Fatalf("error getting version: %s", err)
}
defaultNode := addrFromPeer(&remotePeer)
for _, resp := range reply.Response {
node := defaultNode
if resp.Metadata != nil {
fmt.Printf("\t%s: %s\n", "NODE", resp.Metadata.Hostname)
node = resp.Metadata.Hostname
}
fmt.Printf("\t%s: %s\n", "NODE", node)
version.PrintLongVersionFromExisting(resp.Version)
}
})

View File

@ -207,27 +207,34 @@ func (c *Client) Kubeconfig(ctx context.Context) ([]byte, error) {
}
// Stats implements the proto.OSClient interface.
func (c *Client) Stats(ctx context.Context, namespace string, driver common.ContainerDriver) (reply *osapi.StatsReply, err error) {
reply, err = c.client.Stats(ctx, &osapi.StatsRequest{
func (c *Client) Stats(ctx context.Context, namespace string, driver common.ContainerDriver, callOptions ...grpc.CallOption) (reply *osapi.StatsReply, err error) {
reply, err = c.client.Stats(
ctx, &osapi.StatsRequest{
Namespace: namespace,
Driver: driver,
})
},
callOptions...,
)
return
}
// Containers implements the proto.OSClient interface.
func (c *Client) Containers(ctx context.Context, namespace string, driver common.ContainerDriver) (reply *osapi.ContainersReply, err error) {
reply, err = c.client.Containers(ctx, &osapi.ContainersRequest{
func (c *Client) Containers(ctx context.Context, namespace string, driver common.ContainerDriver, callOptions ...grpc.CallOption) (reply *osapi.ContainersReply, err error) {
reply, err = c.client.Containers(
ctx,
&osapi.ContainersRequest{
Namespace: namespace,
Driver: driver,
})
},
callOptions...,
)
return
}
// Restart implements the proto.OSClient interface.
func (c *Client) Restart(ctx context.Context, namespace string, driver common.ContainerDriver, id string) (err error) {
func (c *Client) Restart(ctx context.Context, namespace string, driver common.ContainerDriver, id string, callOptions ...grpc.CallOption) (err error) {
_, err = c.client.Restart(ctx, &osapi.RestartRequest{
Id: id,
Namespace: namespace,
@ -272,33 +279,69 @@ func (c *Client) Logs(ctx context.Context, namespace string, driver common.Conta
}
// Version implements the proto.OSClient interface.
func (c *Client) Version(ctx context.Context) (*machineapi.VersionReply, error) {
return c.MachineClient.Version(ctx, &empty.Empty{})
func (c *Client) Version(ctx context.Context, callOptions ...grpc.CallOption) (reply *machineapi.VersionReply, err error) {
reply, err = c.MachineClient.Version(
ctx,
&empty.Empty{},
callOptions...,
)
return
}
// Routes implements the networkdproto.NetworkClient interface.
func (c *Client) Routes(ctx context.Context) (*networkapi.RoutesReply, error) {
return c.NetworkClient.Routes(ctx, &empty.Empty{})
func (c *Client) Routes(ctx context.Context, callOptions ...grpc.CallOption) (reply *networkapi.RoutesReply, err error) {
reply, err = c.NetworkClient.Routes(
ctx,
&empty.Empty{},
callOptions...,
)
return
}
// Interfaces implements the proto.OSClient interface.
func (c *Client) Interfaces(ctx context.Context) (*networkapi.InterfacesReply, error) {
return c.NetworkClient.Interfaces(ctx, &empty.Empty{})
func (c *Client) Interfaces(ctx context.Context, callOptions ...grpc.CallOption) (reply *networkapi.InterfacesReply, err error) {
reply, err = c.NetworkClient.Interfaces(
ctx,
&empty.Empty{},
callOptions...,
)
return
}
// Processes implements the proto.OSClient interface.
func (c *Client) Processes(ctx context.Context) (reply *osapi.ProcessesReply, err error) {
return c.client.Processes(ctx, &empty.Empty{})
func (c *Client) Processes(ctx context.Context, callOptions ...grpc.CallOption) (reply *osapi.ProcessesReply, err error) {
reply, err = c.client.Processes(
ctx,
&empty.Empty{},
callOptions...,
)
return
}
// Memory implements the proto.OSClient interface.
func (c *Client) Memory(ctx context.Context) (*osapi.MemInfoReply, error) {
return c.client.Memory(ctx, &empty.Empty{})
func (c *Client) Memory(ctx context.Context, callOptions ...grpc.CallOption) (reply *osapi.MemInfoReply, err error) {
reply, err = c.client.Memory(
ctx,
&empty.Empty{},
callOptions...,
)
return
}
// Mounts implements the proto.OSClient interface.
func (c *Client) Mounts(ctx context.Context) (*machineapi.MountsReply, error) {
return c.MachineClient.Mounts(ctx, &empty.Empty{})
func (c *Client) Mounts(ctx context.Context, callOptions ...grpc.CallOption) (reply *machineapi.MountsReply, err error) {
reply, err = c.MachineClient.Mounts(
ctx,
&empty.Empty{},
callOptions...,
)
return
}
// LS implements the proto.OSClient interface.
@ -320,46 +363,117 @@ func (c *Client) CopyOut(ctx context.Context, rootPath string) (io.Reader, <-cha
// Upgrade initiates a Talos upgrade ... and implements the proto.OSClient
// interface
func (c *Client) Upgrade(ctx context.Context, image string) (*machineapi.UpgradeReply, error) {
return c.MachineClient.Upgrade(ctx, &machineapi.UpgradeRequest{Image: image})
func (c *Client) Upgrade(ctx context.Context, image string, callOptions ...grpc.CallOption) (reply *machineapi.UpgradeReply, err error) {
reply, err = c.MachineClient.Upgrade(
ctx,
&machineapi.UpgradeRequest{Image: image},
callOptions...,
)
return
}
// ServiceList returns list of services with their state
func (c *Client) ServiceList(ctx context.Context) (*machineapi.ServiceListReply, error) {
return c.MachineClient.ServiceList(ctx, &empty.Empty{})
func (c *Client) ServiceList(ctx context.Context, callOptions ...grpc.CallOption) (reply *machineapi.ServiceListReply, err error) {
reply, err = c.MachineClient.ServiceList(
ctx,
&empty.Empty{},
callOptions...,
)
return
}
// ServiceInfo provides info about a service and node metadata
type ServiceInfo struct {
Metadata *common.ResponseMetadata
Service *machineapi.ServiceInfo
}
// ServiceInfo returns info about a single service
//
// This is implemented via service list API, as we don't have many services
// If service with given id is not registered, function returns nil
func (c *Client) ServiceInfo(ctx context.Context, id string) (*machineapi.ServiceListReply, error) {
return c.MachineClient.ServiceList(ctx, &empty.Empty{})
func (c *Client) ServiceInfo(ctx context.Context, id string, callOptions ...grpc.CallOption) (services []ServiceInfo, err error) {
var reply *machineapi.ServiceListReply
reply, err = c.MachineClient.ServiceList(
ctx,
&empty.Empty{},
callOptions...,
)
if err != nil {
return
}
for _, resp := range reply.Response {
for _, svc := range resp.Services {
if svc.Id == id {
services = append(services, ServiceInfo{
Metadata: resp.Metadata,
Service: svc,
})
}
}
}
return
}
// ServiceStart starts a service.
func (c *Client) ServiceStart(ctx context.Context, id string) (*machineapi.ServiceStartReply, error) {
return c.MachineClient.ServiceStart(ctx, &machineapi.ServiceStartRequest{Id: id})
func (c *Client) ServiceStart(ctx context.Context, id string, callOptions ...grpc.CallOption) (reply *machineapi.ServiceStartReply, err error) {
reply, err = c.MachineClient.ServiceStart(
ctx,
&machineapi.ServiceStartRequest{Id: id},
callOptions...,
)
return
}
// ServiceStop stops a service.
func (c *Client) ServiceStop(ctx context.Context, id string) (*machineapi.ServiceStopReply, error) {
return c.MachineClient.ServiceStop(ctx, &machineapi.ServiceStopRequest{Id: id})
func (c *Client) ServiceStop(ctx context.Context, id string, callOptions ...grpc.CallOption) (reply *machineapi.ServiceStopReply, err error) {
reply, err = c.MachineClient.ServiceStop(
ctx,
&machineapi.ServiceStopRequest{Id: id},
callOptions...,
)
return
}
// ServiceRestart restarts a service.
func (c *Client) ServiceRestart(ctx context.Context, id string) (*machineapi.ServiceRestartReply, error) {
return c.MachineClient.ServiceRestart(ctx, &machineapi.ServiceRestartRequest{Id: id})
func (c *Client) ServiceRestart(ctx context.Context, id string, callOptions ...grpc.CallOption) (reply *machineapi.ServiceRestartReply, err error) {
reply, err = c.MachineClient.ServiceRestart(
ctx,
&machineapi.ServiceRestartRequest{Id: id},
callOptions...,
)
return
}
// Time returns the time
func (c *Client) Time(ctx context.Context) (*timeapi.TimeReply, error) {
return c.TimeClient.Time(ctx, &empty.Empty{})
func (c *Client) Time(ctx context.Context, callOptions ...grpc.CallOption) (reply *timeapi.TimeReply, err error) {
reply, err = c.TimeClient.Time(
ctx,
&empty.Empty{},
callOptions...,
)
return
}
// TimeCheck returns the time compared to the specified ntp server
func (c *Client) TimeCheck(ctx context.Context, server string) (*timeapi.TimeReply, error) {
return c.TimeClient.TimeCheck(ctx, &timeapi.TimeRequest{Server: server})
func (c *Client) TimeCheck(ctx context.Context, server string, callOptions ...grpc.CallOption) (reply *timeapi.TimeReply, err error) {
reply, err = c.TimeClient.TimeCheck(
ctx,
&timeapi.TimeRequest{Server: server},
callOptions...,
)
return
}
// Read reads a file.