Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stack status cmd - add columns for image build date and VCS reference #2057

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
22 changes: 20 additions & 2 deletions cmd/stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package cmd
import (
"fmt"
"strings"
"time"

"github.com/jedib0t/go-pretty/table"

Expand Down Expand Up @@ -350,11 +351,28 @@ func printStatus(cmd *cobra.Command, servicesStatus []stack.ServiceStatus) {
return
}
t := table.NewWriter()
t.AppendHeader(table.Row{"Service", "Version", "Status"})
t.AppendHeader(table.Row{"Service", "Version", "Status", "Image Build Date", "VCS Ref"})

for _, service := range servicesStatus {
t.AppendRow(table.Row{service.Name, service.Version, service.Status})
t.AppendRow(table.Row{service.Name, service.Version, service.Status, formatTime(service.Labels.BuildDate), truncate(service.Labels.VCSRef, 10)})
Copy link
Contributor

@mrodm mrodm Sep 19, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When creating a serverless project, there are no local containers at least for elasticsearch, kibana and fleet. For that scenario, service.Labels field is nil.

Here there is an example of the panic error that it is raised because of that:

 $ elastic-package stack status
2024/09/19 17:21:03  WARN Elastic Serverless provider is in technical preview
Status of Elastic stack services:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x30 pc=0x3516bd3]

goroutine 1 [running]:
github.com/elastic/elastic-package/cmd.printStatus(0xc000546c08, {0xc0008fc460, 0x4, 0x0?})
	/home/mariorodriguez/Coding/work/elastic-package-stack-status-vcs-ref/cmd/stack.go:357 +0x233
github.com/elastic/elastic-package/cmd.setupStackCommand.func6(0xc000546c08, {0x5ba26a0?, 0x0?, 0x0?})
	/home/mariorodriguez/Coding/work/elastic-package-stack-status-vcs-ref/cmd/stack.go:299 +0x167
github.com/spf13/cobra.(*Command).execute(0xc000546c08, {0x5ba26a0, 0x0, 0x0})
	/home/mariorodriguez/go/pkg/mod/github.com/spf13/[email protected]/command.go:985 +0xaca
github.com/spf13/cobra.(*Command).ExecuteC(0xc00054af08)
	/home/mariorodriguez/go/pkg/mod/github.com/spf13/[email protected]/command.go:1117 +0x3ff
github.com/spf13/cobra.(*Command).Execute(0xc000078008?)
	/home/mariorodriguez/go/pkg/mod/github.com/spf13/[email protected]/command.go:1041 +0x13
main.main()
	/home/mariorodriguez/Coding/work/elastic-package-stack-status-vcs-ref/main.go:26 +0x66

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be an example of that command with one of the latest elastic-package versions:

 $ elastic-package stack status 
2024/09/19 17:36:22  WARN Elastic Serverless provider is in technical preview
Status of Elastic stack services:
╭───────────────┬────────────────────────────┬───────────────────╮
│ SERVICE       │ VERSION                    │ STATUS            │
├───────────────┼────────────────────────────┼───────────────────┤
│ elasticsearch │ serverless (observability) │ healthy           │
│ kibana        │ serverless (observability) │ healthy           │
│ fleet         │ serverless (observability) │ healthy           │
│ elastic-agent │ 8.15.0                     │ running (healthy) │
╰───────────────┴────────────────────────────┴───────────────────╯

}
t.SetStyle(table.StyleRounded)
cmd.Println(t.Render())
}

// formatTime returns the given RFC3339 time formated as 2006-01-02T15:04Z.
// If the value is not in RFC3339 format, then it is returned as-is.
func formatTime(maybeRFC3339Time string) string {
if t, err := time.Parse(time.RFC3339, maybeRFC3339Time); err == nil {
return t.UTC().Format("2006-01-02T15:04Z")
}
return maybeRFC3339Time
}

// truncate truncates text if it is longer than maxLength.
func truncate(text string, maxLength int) string {
if len(text) > maxLength {
return text[:maxLength]
}
return text
}
4 changes: 4 additions & 0 deletions internal/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ type ConfigLabels struct {
ComposeProject string `json:"com.docker.compose.project"`
ComposeService string `json:"com.docker.compose.service"`
ComposeVersion string `json:"com.docker.compose.version"`

// http://label-schema.org/rc1/ Labels
BuildDate string `json:"org.label-schema.build-date,omitempty"` // This label contains the Date/Time the image was built. The value SHOULD be formatted according to RFC 3339.
VCSRef string `json:"org.label-schema.vcs-ref,omitempty"` // Identifier for the version of the source code from which this image was built. For example if the version control system is git this is the SHA.
}

// String function dumps string representation of the container description.
Expand Down
2 changes: 2 additions & 0 deletions internal/stack/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ type ServiceStatus struct {
Name string
Status string
Version string
Labels *docker.ConfigLabels // Container labels.
}

const readyServicesSuffix = "is_ready"
Expand Down Expand Up @@ -214,6 +215,7 @@ func newServiceStatus(description *docker.ContainerDescription) (*ServiceStatus,
Name: description.Config.Labels.ComposeService,
Status: description.State.Status,
Version: getVersionFromDockerImage(description.Config.Image),
Labels: &description.Config.Labels,
}
if description.State.Status == "running" {
healthStatus := "unknown health"
Expand Down
3 changes: 3 additions & 0 deletions internal/stack/compose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ func TestNewServiceStatus(t *testing.T) {
Name: "myservice",
Status: "running (healthy)",
Version: "1.42.0",
Labels: &docker.ConfigLabels{ComposeService: "myservice"},
},
},
{
Expand Down Expand Up @@ -112,6 +113,7 @@ func TestNewServiceStatus(t *testing.T) {
Name: "myservice",
Status: "exited (128)",
Version: "1.42.0",
Labels: &docker.ConfigLabels{ComposeService: "myservice"},
},
},
{
Expand Down Expand Up @@ -155,6 +157,7 @@ func TestNewServiceStatus(t *testing.T) {
Name: "myservice",
Status: "running (starting)",
Version: "1.42.0",
Labels: &docker.ConfigLabels{ComposeService: "myservice"},
},
},
}
Expand Down
27 changes: 16 additions & 11 deletions scripts/test-stack-command.sh
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,12 @@ default_version() {

clean_status_output() {
local output_file="$1"
cat "${output_file}" | grep "│" | tr -d ' '
# This removes the 'IMAGE BUILD DATE" and 'VCS REF' columns and
# removes the whitespace between columns.
grep "│" "${output_file}" \
| sed 's/│/|/g' \
| cut -d '|' -f 1-4,7- \
| tr -d ' '
}

trap cleanup EXIT
Expand Down Expand Up @@ -90,20 +95,20 @@ curl --cacert "${ELASTIC_PACKAGE_CA_CERT}" -f "${ELASTIC_PACKAGE_KIBANA_HOST}/lo
# Check status with running services
cat <<EOF > "${OUTPUT_PATH_STATUS}/expected_running.txt"
Status of Elastic stack services:
╭──────────────────┬─────────┬───────────────────╮
│ SERVICE │ VERSION │ STATUS │
├──────────────────┼─────────┼───────────────────┤
│ elastic-agent │ ${EXPECTED_VERSION} │ running (healthy) │
│ elasticsearch │ ${EXPECTED_VERSION} │ running (healthy) │
│ fleet-server │ ${EXPECTED_VERSION} │ running (healthy) │
│ kibana │ ${EXPECTED_VERSION} │ running (healthy) │
│ package-registry │ latest │ running (healthy) │
╰──────────────────┴─────────┴───────────────────╯
╭──────────────────┬─────────────────────┬───────────────────┬───────────────────┬────────────╮
│ SERVICE │ VERSION │ STATUS │ IMAGE BUILD DATE │ VCS REF
├──────────────────┼─────────────────────┼───────────────────┼───────────────────┼────────────┤
│ elastic-agent │ ${EXPECTED_VERSION} │ running (healthy) │ 2024-08-22T02:44Z │ b96a4ca8fa
│ elasticsearch │ ${EXPECTED_VERSION} │ running (healthy) │ 2024-08-22T13:26Z │ 1362d56865
│ fleet-server │ ${EXPECTED_VERSION} │ running (healthy) │ 2024-08-22T02:44Z │ b96a4ca8fa
│ kibana │ ${EXPECTED_VERSION} │ running (healthy) │ 2024-08-22T11:09Z │ cdcdfddd3f
│ package-registry │ latest │ running (healthy) │ │
╰──────────────────┴─────────────────────┴───────────────────┴───────────────────┴────────────╯
EOF

elastic-package stack status -v 2> "${OUTPUT_PATH_STATUS}/running.txt"

# Remove spaces to avoid issues with spaces between columns
# Remove dates, commit IDs, and spaces to avoid issues.
clean_status_output "${OUTPUT_PATH_STATUS}/expected_running.txt" > "${OUTPUT_PATH_STATUS}/expected_no_spaces.txt"
clean_status_output "${OUTPUT_PATH_STATUS}/running.txt" > "${OUTPUT_PATH_STATUS}/running_no_spaces.txt"

Expand Down