Skip to content

Commit

Permalink
Merge pull request #86 from StackVista/stac-21470
Browse files Browse the repository at this point in the history
STAC-21470: Add agent list command
  • Loading branch information
craffit authored Aug 1, 2024
2 parents 9013c47 + 5370190 commit b302df8
Show file tree
Hide file tree
Showing 76 changed files with 10,491 additions and 1,747 deletions.
18 changes: 18 additions & 0 deletions cmd/agent.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cmd

import (
"github.com/spf13/cobra"
"github.com/stackvista/stackstate-cli/cmd/agent"
"github.com/stackvista/stackstate-cli/internal/di"
)

func AgentCommand(deps *di.Deps) *cobra.Command {
cmd := &cobra.Command{
Use: "agent",
Short: "Manage the StackState agents",
Long: "Manage the StackState agents.",
}

cmd.AddCommand(agent.ListCommand(deps))
return cmd
}
96 changes: 96 additions & 0 deletions cmd/agent/agent_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package agent

import (
"cmp"
"fmt"
"slices"
"time"

"github.com/spf13/cobra"
"github.com/stackvista/stackstate-cli/generated/stackstate_api"
"github.com/stackvista/stackstate-cli/internal/common"
"github.com/stackvista/stackstate-cli/internal/di"
"github.com/stackvista/stackstate-cli/internal/printer"
)

func ListCommand(deps *di.Deps) *cobra.Command {
cmd := &cobra.Command{
Use: "list",
Short: "List all registered agents",
Long: "List all registered agents.",
RunE: deps.CmdRunEWithApi(RunListCommand),
}

return cmd
}

const toMB = 1024 * 1024

func RunListCommand(cmd *cobra.Command, cli *di.Deps, api *stackstate_api.APIClient, serverInfo *stackstate_api.ServerInfo) common.CLIError {
agents, resp, err := api.AgentRegistrationsApi.AllAgentRegistrations(cli.Context).Execute()

if err != nil {
return common.NewResponseError(err, resp)
}

agentList := agents.Agents

slices.SortFunc(agentList, func(a, b stackstate_api.AgentRegistration) int {
if n := cmp.Compare(a.Lease, b.Lease); n != 0 {
return n
}
// If leases are equal, order by registration moment
return cmp.Compare(a.RegisteredEpochMs, b.RegisteredEpochMs)
})

var active = 0
var limited = 0
var stale = 0

for _, agent := range agentList {
switch agent.Lease {
case stackstate_api.AGENTLEASE_ACTIVE:
active++
case stackstate_api.AGENTLEASE_LIMITED:
limited++
case stackstate_api.AGENTLEASE_STALE:
stale++
default:
}
}

if cli.IsJson() {
cli.Printer.PrintJson(map[string]interface{}{
"agents": agentList,
})
} else {
data := make([][]interface{}, len(agentList))

for i, agent := range agentList {
var info = agent.AgentData
if info == nil {
info = &stackstate_api.AgentData{Platform: "", CoreCount: 0, MemoryBytes: 0, KernelVersion: ""}
}

data[i] = []interface{}{
agent.AgentId,
agent.Lease,
time.UnixMilli(agent.RegisteredEpochMs).Format("2006-01-02 15:04:05 MST"),
time.UnixMilli(agent.LeaseUntilEpochMs).Format("2006-01-02 15:04:05 MST"),
fmt.Sprintf("%v", info.CoreCount),
fmt.Sprintf("%vMB", info.MemoryBytes/toMB),
info.Platform,
info.KernelVersion,
}
}
cli.Printer.Table(printer.TableData{
Header: []string{"Host", "Lease", "Registered", "Last Lease", "CPUS", "Memory", "Platform", "Kernel"},
Data: data,
})

cli.Printer.PrintLn("")
cli.Printer.PrintLn(fmt.Sprintf("Totals: %d active, %d limited, %d stale", active, limited, stale))
}

return nil
}
73 changes: 73 additions & 0 deletions cmd/agent/agent_list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package agent

import (
"testing"
"time"

"github.com/stackvista/stackstate-cli/generated/stackstate_api"
"github.com/stackvista/stackstate-cli/internal/di"
"github.com/stackvista/stackstate-cli/internal/printer"
"github.com/stretchr/testify/assert"
)

var (
SomeAgentRegistrations = []stackstate_api.AgentRegistration{
{
AgentId: "id1",
Lease: stackstate_api.AGENTLEASE_ACTIVE,
LeaseUntilEpochMs: 0,
RegisteredEpochMs: 0,
AgentData: &stackstate_api.AgentData{
Platform: "platform",
CoreCount: 4,
MemoryBytes: 16 * 1024 * 1024,
KernelVersion: "5.15",
},
}, {
AgentId: "id2",
Lease: stackstate_api.AGENTLEASE_LIMITED,
LeaseUntilEpochMs: 0,
RegisteredEpochMs: 0,
AgentData: nil,
},
}
)

func TestAgentList(t *testing.T) {
cli := di.NewMockDeps(t)
cmd := ListCommand(&cli.Deps)

cli.MockClient.ApiMocks.AgentRegistrationsApi.AllAgentRegistrationsResponse.Result = stackstate_api.AgentRegistrations{
Agents: SomeAgentRegistrations,
}

di.ExecuteCommandWithContextUnsafe(&cli.Deps, cmd)

assert.Len(t, *cli.MockClient.ApiMocks.AgentRegistrationsApi.AllAgentRegistrationsCalls, 1)

nulTime := time.UnixMilli(0).Format("2006-01-02 15:04:05 MST")

expectedTable := []printer.TableData{
{
Header: []string{"Host", "Lease", "Registered", "Last Lease", "CPUS", "Memory", "Platform", "Kernel"},
Data: [][]interface{}{
{"id1", stackstate_api.AGENTLEASE_ACTIVE, nulTime, nulTime, "4", "16MB", "platform", "5.15"},
{"id2", stackstate_api.AGENTLEASE_LIMITED, nulTime, nulTime, "0", "0MB", "", ""},
},
},
}

assert.Equal(t, expectedTable, *cli.MockPrinter.TableCalls)

di.ExecuteCommandWithContextUnsafe(&cli.Deps, cmd, "-o", "json")

assert.Len(t, *cli.MockClient.ApiMocks.AgentRegistrationsApi.AllAgentRegistrationsCalls, 2)

expectedJson := []map[string]interface{}{
{
"agents": SomeAgentRegistrations,
},
}

assert.Equal(t, expectedJson, *cli.MockPrinter.PrintJsonCalls)
}
1 change: 1 addition & 0 deletions cmd/sts.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ func STSCommand(cli *di.Deps) *cobra.Command {
cmd.AddCommand(TopicCommand(cli))
cmd.AddCommand(TopologySyncCommand(cli))
cmd.AddCommand(IngestionApiKeyCommand(cli))
cmd.AddCommand(AgentCommand(cli))

return cmd
}
42 changes: 42 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

111 changes: 111 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{
description = "StackState CLI";

nixConfig.bash-prompt = "STS CLI 2 $ ";

inputs = {
nixpkgs.url = "github:nixos/nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; overlays = [ ]; };
pkgs-linux = import nixpkgs { system = "x86_64-linux"; overlays = [ ]; };

# Dependencies used for both development and CI/CD
sharedDeps = pkgs: (with pkgs; [
bash
go_1_19
gotools
diffutils # Required for golangci-lint
golangci-lint
openapi-generator-cli
]);

# Dependencies used only by CI/CD
ciDeps = pkgs: (with pkgs; [
git
cacert
gcc
coreutils-full
goreleaser
awscli
docker
]);

darwinDevShellExtraDeps = pkgs: pkgs.lib.optionals pkgs.stdenv.isDarwin (with pkgs.darwin.apple_sdk_11_0; [
Libsystem
IOKit
]);
in {

devShells = {
dev = pkgs.mkShell {
buildInputs = sharedDeps(pkgs) ++ darwinDevShellExtraDeps(pkgs);
};

ci = pkgs.mkShell {
buildInputs = sharedDeps(pkgs) ++ ciDeps(pkgs);
};
};

devShell = self.devShells."${system}".dev;

packages = {
sts = pkgs.buildGo119Module {
pname = "sts";
version = "2.0.0";

src = ./.;

# This hash locks the dependencies of this package.
# Change it to the provided when the go dependencies change.
# See https://www.tweag.io/blog/2021-03-04-gomod2nix/ for details.
#
# NOTE In case if your build fails due to incosistency in vendor modules
# Comment out the real hash and uncomment the fake one then on next `nix build .` run
# you will get a new real hash which can be used here.
#
# vendorSha256 = pkgs.lib.fakeSha256;
vendorSha256 = "sha256-aXTDHT1N+4Qpkuxb8vvBvP2VPyS5ofCgX6XFhJ5smUQ=";

postInstall = ''
mv $out/bin/stackstate-cli2 $out/bin/sts
'';
};

ci-image = pkgs.dockerTools.buildImage {
name = "stackstate-cli2-ci";
tag = "latest";
created = "now";

contents = sharedDeps(pkgs-linux) ++ ciDeps(pkgs-linux);

config = {
Env = [
"GIT_SSL_CAINFO=/etc/ssl/certs/ca-bundle.crt"
"SSL_CERT_FILE=/etc/ssl/certs/ca-bundle.crt"
];

# Required to make golangci-lint work.
Volumes = {
"/tmp" = {};
};
};
};

default = self.packages."${system}".sts;
};

apps = {
sts = {
type = "app";
program = "${self.packages."${system}".sts}/bin/sts";
};

default = self.apps."${system}".sts;
};
});
}
Loading

0 comments on commit b302df8

Please sign in to comment.