Skip to content

Commit

Permalink
Merge pull request #12 from Cloudzero/CP-20097-capture-version-in-val…
Browse files Browse the repository at this point in the history
…idator

CP-20097 add prometheus version check
  • Loading branch information
josephbarnett authored Jul 15, 2024
2 parents 8660e46 + a50b6ca commit b1a256e
Show file tree
Hide file tree
Showing 13 changed files with 213 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
REPO_NAME ?= $(shell basename `git rev-parse --show-toplevel`)
IMAGE_NAME ?= ghcr.io/cloudzero/cloudzero-agent-validator/cloudzero-agent-validator
TAG ?= dev-$(git rev-parse --short HEAD)

# Docker is the default container tool (and buildx buildkit)
CONTAINER_TOOL ?= docker
BUILDX_CONTAINER_EXISTS := $(shell $(CONTAINER_TOOL) buildx ls --format "{{.Name}}: {{.DriverEndpoint}}" | grep -c "container:")

BUILD_TIME ?= $(shell date -u '+%Y-%m-%d_%I:%M:%S%p')
REVISION ?= $(shell git rev-parse HEAD)
TAG ?= dev-$(REVISION)

# Directories
# Colors
Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ LABEL org.opencontainers.image.title="cloudzero-agent-validator"
LABEL org.opencontainers.image.description="cloudzero-agent execution environment validation utility"
LABEL org.opencontainers.image.vendor="Cloudzero, Inc."
LABEL org.opencontainers.image.licenses="Apache-2.0"
LABEL org.opencontainers.image.source = "https://github.com/Cloudzero/cloudzero-agent-validator"
LABEL org.opencontainers.image.source="https://github.com/Cloudzero/cloudzero-agent-validator"
LABEL io.artifacthub.package.readme-url="https://raw.githubusercontent.com/Cloudzero/cloudzero-agent-validator/main/README.md"
LABEL io.artifacthub.package.license="Apache-2.0"

Expand Down
16 changes: 9 additions & 7 deletions pkg/config/diagnostics.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@ import (
)

const (
DiagnosticAPIKey string = "api_key_valid" //nolint:gosec
DiagnosticK8sVersion string = "k8s_version"
DiagnosticEgressAccess string = "egress_reachable"
DiagnosticKMS string = "kube_state_metrics_reachable"
DiagnosticNodeExporter string = "node_exporter_reachable"
DiagnosticScrapeConfig string = "scrape_cfg"
DiagnosticAPIKey string = "api_key_valid" //nolint:gosec
DiagnosticK8sVersion string = "k8s_version"
DiagnosticEgressAccess string = "egress_reachable"
DiagnosticKMS string = "kube_state_metrics_reachable"
DiagnosticNodeExporter string = "node_exporter_reachable"
DiagnosticPrometheusVersion string = "prometheus_version"
DiagnosticScrapeConfig string = "scrape_cfg"
)

const (
Expand All @@ -26,7 +27,8 @@ func IsValidDiagnostic(d string) bool {
d = strings.ToLower(strings.TrimSpace(d))
switch d {
case DiagnosticAPIKey, DiagnosticK8sVersion, DiagnosticEgressAccess,
DiagnosticKMS, DiagnosticNodeExporter, DiagnosticScrapeConfig:
DiagnosticKMS, DiagnosticNodeExporter, DiagnosticScrapeConfig,
DiagnosticPrometheusVersion:
return true
}
return false
Expand Down
1 change: 1 addition & 0 deletions pkg/config/prometheus.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
)

type Prometheus struct {
Executable string `yaml:"executable" default:"/bin/prometheus" env:"PROMETHEUS_EXECUTABLE" env-description:"Prometheus Executable Path"`
KubeStateMetricsServiceEndpoint string `yaml:"kube_state_metrics_service_endpoint" env:"KMS_EP_URL" required:"true" env-description:"Kube State Metrics Service Endpoint"`
PrometheusNodeExporterServiceEndpoint string `yaml:"prometheus_node_exporter_service_endpoint" env:"NODE_EXPORTER_EP_URL" required:"true" env-description:"Prometheus Node Exporter Service Endpoint"`
Configurations []string `yaml:"configurations"`
Expand Down
6 changes: 4 additions & 2 deletions pkg/diagnostic/catalog/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (
"github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/k8s"
"github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/kms"
"github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/pne"
"github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/prom"
promcfg "github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/prom/config"
promver "github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/prom/version"
"github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/stage"
"github.com/cloudzero/cloudzero-agent-validator/pkg/status"
)
Expand Down Expand Up @@ -42,7 +43,8 @@ func NewCatalog(ctx context.Context, c *config.Settings) Registry {
r.add(config.DiagnosticK8sVersion, false, k8s.NewProvider(ctx, c))
r.add(config.DiagnosticKMS, false, kms.NewProvider(ctx, c))
r.add(config.DiagnosticNodeExporter, false, pne.NewProvider(ctx, c))
r.add(config.DiagnosticScrapeConfig, false, prom.NewProvider(ctx, c))
r.add(config.DiagnosticScrapeConfig, false, promcfg.NewProvider(ctx, c))
r.add(config.DiagnosticPrometheusVersion, false, promver.NewProvider(ctx, c))

// Internal diagnostics emitted based on stage
r.add(config.DiagnosticInternalInitStart, true, stage.NewProvider(ctx, c, status.StatusType_STATUS_TYPE_INIT_STARTED))
Expand Down
2 changes: 1 addition & 1 deletion pkg/diagnostic/catalog/catalog_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,5 @@ func TestRegistry_List(t *testing.T) {

// Test listing providers
providers := r.List()
assert.Len(t, providers, 6)
assert.Len(t, providers, 7)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package prom
package config

import (
"context"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package prom_test
package config_test

import (
"context"
Expand All @@ -8,7 +8,7 @@ import (
"github.com/stretchr/testify/assert"

"github.com/cloudzero/cloudzero-agent-validator/pkg/config"
"github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/prom"
promcfg "github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/prom/config"
"github.com/cloudzero/cloudzero-agent-validator/pkg/status"
)

Expand All @@ -26,7 +26,7 @@ func TestChecker_CheckOK(t *testing.T) {
Configurations: []string{scrapeConfigFile},
},
}
provider := prom.NewProvider(context.Background(), cfg)
provider := promcfg.NewProvider(context.Background(), cfg)

accessor := makeReport()

Expand Down Expand Up @@ -65,7 +65,7 @@ func TestChecker_NotSet(t *testing.T) {

for _, tc := range tcase {
t.Run(tc.name, func(t *testing.T) {
provider := prom.NewProvider(context.Background(), tc.cfg)
provider := promcfg.NewProvider(context.Background(), tc.cfg)
accessor := makeReport()
err := provider.Check(context.Background(), nil, accessor)
assert.NoError(t, err)
Expand Down
File renamed without changes.
108 changes: 108 additions & 0 deletions pkg/diagnostic/prom/version/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package version

import (
"bytes"
"context"
"fmt"
net "net/http"
"os"
"os/exec"

"github.com/cloudzero/cloudzero-agent-validator/pkg/config"
"github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic"
"github.com/cloudzero/cloudzero-agent-validator/pkg/logging"
"github.com/cloudzero/cloudzero-agent-validator/pkg/status"
"github.com/sirupsen/logrus"
)

const DiagnosticPrometheusVersion = config.DiagnosticPrometheusVersion

type checker struct {
cfg *config.Settings
logger *logrus.Entry
}

func NewProvider(ctx context.Context, cfg *config.Settings) diagnostic.Provider {
return &checker{
cfg: cfg,
logger: logging.NewLogger().
WithContext(ctx).WithField(logging.OpField, "prom"),
}
}

func (c *checker) Check(ctx context.Context, _ *net.Client, accessor status.Accessor) error {
if len(c.cfg.Prometheus.Executable) == 0 {
accessor.AddCheck(&status.StatusCheck{
Name: DiagnosticPrometheusVersion,
Error: "no prometheus binary available at configured location",
})
return nil
}

versionData, err := c.GetVersion(ctx)
if err != nil {
accessor.AddCheck(
&status.StatusCheck{
Name: DiagnosticPrometheusVersion,
Error: err.Error(),
})
return nil
}

accessor.WriteToReport(func(s *status.ClusterStatus) {
s.AgentVersion = string(versionData)
s.Checks = append(s.Checks, &status.StatusCheck{Name: DiagnosticPrometheusVersion, Passing: true})
})
return nil
}

func (c *checker) GetVersion(ctx context.Context) ([]byte, error) {
executable := c.cfg.Prometheus.Executable
if len(executable) == 0 {
return nil, fmt.Errorf("no prometheus binary available at configured location")
}

fi, err := os.Stat(executable)
if os.IsNotExist(err) {
return nil, fmt.Errorf("prometheus executable not found: %w", err)
}
if fi.Mode()&0111 == 0 {
return nil, fmt.Errorf("prometheus executable is not executable: %s", executable)
}

// create the raw output fle
rawOutput, err := os.CreateTemp(os.TempDir(), ".promver.*")
if err != nil {
return nil, fmt.Errorf("failed to create raw prometheus version output file: %w", err)
}
defer func() {
_ = rawOutput.Close()
_ = os.Remove(rawOutput.Name())
}()

// Build the command and Exec the scanner
cmd := exec.CommandContext(ctx, executable, "--version")

// capture the output
var stderr bytes.Buffer
cmd.Stderr = &stderr
cmd.Stdout = rawOutput

// Now run the app
if err := cmd.Run(); err != nil {
return nil, fmt.Errorf("failed to run prometheus: %w", err)
}

// make sure all bytes are written from the standard output
if err := rawOutput.Sync(); err != nil {
return nil, fmt.Errorf("failed to sync raw prometheus output file: %w", err)
}

// seek to the beginning of the file for reading.
if _, err := rawOutput.Seek(0, 0); err != nil {
return nil, fmt.Errorf("failed to seek to the beginning of the raw prometheus output file: %w", err)
}

// read the results into a byte slice
return os.ReadFile(rawOutput.Name())
}
74 changes: 74 additions & 0 deletions pkg/diagnostic/prom/version/check_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package version_test

import (
"context"
"os"
"testing"

"github.com/stretchr/testify/assert"

"github.com/cloudzero/cloudzero-agent-validator/pkg/config"
"github.com/cloudzero/cloudzero-agent-validator/pkg/diagnostic/prom/version"
"github.com/cloudzero/cloudzero-agent-validator/pkg/status"
)

func makeReport() status.Accessor {
return status.NewAccessor(&status.ClusterStatus{})
}

func TestChecker_GetVersion(t *testing.T) {
tests := []struct {
name string
executable string
expected bool
}{
{
name: "ExecutableNotFound",
executable: "/path/to/nonexistent/prometheus",
expected: false,
},
{
name: "ExecutableEmpty",
executable: "",
expected: false,
},
{
name: "Success",
executable: getPromExecutablePath(),
expected: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := &config.Settings{
Prometheus: config.Prometheus{
Executable: tt.executable,
},
}
provider := version.NewProvider(context.Background(), cfg)
accessor := makeReport()

err := provider.Check(context.Background(), nil, accessor)
assert.NoError(t, err)

accessor.ReadFromReport(func(s *status.ClusterStatus) {
assert.Len(t, s.Checks, 1)
for _, c := range s.Checks {
assert.Equal(t, tt.expected, c.Passing)
}
if tt.expected {
assert.NotEmpty(t, s.AgentVersion)
}
})
})
}
}

func getPromExecutablePath() string {
wd, err := os.Getwd()
if err != nil {
panic(err)
}
return wd + "/testdata/prometheus"
}
8 changes: 8 additions & 0 deletions pkg/diagnostic/prom/version/testdata/prometheus
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/bin/sh

echo " prometheus, version 2.50.1 (branch: HEAD, revision: 8c9b0285360a0b6288d76214a75ce3025bce4050)"
echo " build user: root@6213bb3ee580"
echo " build date: 20240226-11:38:47"
echo " go version: go1.21.7"
echo " platform: linux/arm64"
echo " tags: netgo,builtinassets,stringlabels"
1 change: 1 addition & 0 deletions pkg/diagnostic/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func (r *runner) Run(ctx context.Context) (status.Accessor, error) {
cs.Region = r.cfg.Deployment.Region
cs.Name = r.cfg.Deployment.ClusterName
cs.ValidatorVersion = build.GetVersion()
cs.ChartVersion = r.cfg.Versions.ChartVersion
})

// Pre steps sequentially
Expand Down

0 comments on commit b1a256e

Please sign in to comment.