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
27 changes: 25 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/olekukonko/tablewriter"
"github.com/olekukonko/tablewriter/renderer"
Expand Down Expand Up @@ -367,9 +368,31 @@ func printStatus(cmd *cobra.Command, servicesStatus []stack.ServiceStatus) {
tablewriter.WithRenderer(renderer.NewColorized(config)),
tablewriter.WithConfig(defaultTableConfig),
)
table.Header("Service", "Version", "Status")
table.Header("Service", "Version", "Status", "Image Build Date", "VCS Ref")
for _, service := range servicesStatus {
table.Append(service.Name, service.Version, service.Status)
var buildDate, vcsRef string
if service.Labels != nil {
buildDate = formatTime(service.Labels.BuildDate)
vcsRef = truncate(service.Labels.VCSRef, 10)
}
table.Append(service.Name, service.Version, service.Status, buildDate, vcsRef)
}
table.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 @@ -49,7 +49,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 ' '
Comment on lines +52 to +57
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks good 👍

Before:

│SERVICE│VERSION│STATUS│
│elastic-agent│9.3.0-6f40f4f1-SNAPSHOT│running(healthy)│
│elasticsearch│9.3.0-6f40f4f1-SNAPSHOT│running(healthy)│
│fleet-server│9.3.0-6f40f4f1-SNAPSHOT│running(healthy)│
│kibana│9.3.0-6f40f4f1-SNAPSHOT│running(healthy)│
│package-registry│latest│running(healthy)│

Now:

|SERVICE|VERSION|STATUS|
|elastic-agent|9.3.0-6f40f4f1-SNAPSHOT|running(healthy)|
|elasticsearch|9.3.0-6f40f4f1-SNAPSHOT|running(healthy)|
|fleet-server|9.3.0-6f40f4f1-SNAPSHOT|running(healthy)|
|kibana|9.3.0-6f40f4f1-SNAPSHOT|running(healthy)|
|package-registry|latest|running(healthy)|

}

trap cleanup EXIT
Expand Down Expand Up @@ -131,20 +136,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_AGENT_VERSION} │ running (healthy) │
│ elasticsearch │ ${EXPECTED_VERSION} │ running (healthy) │
│ fleet-server │ ${EXPECTED_AGENT_VERSION} │ running (healthy) │
│ kibana │ ${EXPECTED_VERSION} │ running (healthy) │
│ package-registry │ latest │ running (healthy) │
╰──────────────────┴─────────┴───────────────────╯
╭──────────────────┬─────────────────────┬───────────────────┬───────────────────┬────────────╮
│ SERVICE │ VERSION │ STATUS │ IMAGE BUILD DATE │ VCS REF
├──────────────────┼─────────────────────┼───────────────────┼───────────────────┼────────────┤
│ elastic-agent │ ${EXPECTED_AGENT_VERSION} │ running (healthy) │ 2024-08-22T02:44Z │ b96a4ca8fa
│ elasticsearch │ ${EXPECTED_VERSION} │ running (healthy) │ 2024-08-22T13:26Z │ 1362d56865
│ fleet-server │ ${EXPECTED_AGENT_VERSION} │ running (healthy) │ 2024-08-22T02:44Z │ b96a4ca8fa
│ kibana │ ${EXPECTED_VERSION} │ running (healthy) │ 2024-08-22T11:09Z │ cdcdfddd3f
│ package-registry │ latest │ running (healthy) │ │
╰──────────────────┴─────────────────────┴───────────────────┴───────────────────┴────────────╯
EOF

NO_COLOR=true 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