feat: goldpinger collector and analyser (#1398)

* feat: goldpinger analyser

Analyser to generate a report from goldpinger results

* Add goldpinger testdata

* Goldpinger collector

* Improvements after running tests

* More minor updates after further testing

* Better error message if a container fails to start

* A few more updates

* Add goldpinger e2e test

* Update schemas

* Clean up help installs in e2e tests

* Add resource limits to goldpinger pods

* Some minor improvements

* Some more changes noted when writing docs

* Update schemas

* A few more updates when testing with kURL

* Log goldpinger tests

* Tests before exit code
This commit is contained in:
Evans Mungai
2023-12-12 11:02:41 +00:00
committed by GitHub
parent b0907d7139
commit 53113c0170
33 changed files with 1657 additions and 39 deletions

View File

@@ -42,7 +42,7 @@ func TestDeploymentPod(t *testing.T) {
tarPath := fmt.Sprintf("%s.tar.gz", supportBundleName)
targetFile := fmt.Sprintf("%s/analysis.json", supportBundleName)
cmd := exec.Command("../../../bin/support-bundle", "spec/pod.yaml", "--interactive=false", fmt.Sprintf("-o=%s", supportBundleName))
cmd := exec.CommandContext(ctx, sbBinary(), "spec/pod.yaml", "--interactive=false", fmt.Sprintf("-o=%s", supportBundleName))
cmd.Stdout = &out
err := cmd.Run()
if err != nil {

View File

@@ -69,7 +69,7 @@ func TestClusterResources(t *testing.T) {
supportBundleName := "cluster-resources"
tarPath := fmt.Sprintf("%s.tar.gz", supportBundleName)
targetFolder := fmt.Sprintf("%s/cluster-resources/", supportBundleName)
cmd := exec.Command("../../../bin/support-bundle", "spec/clusterResources.yaml", "--interactive=false", fmt.Sprintf("-o=%s", supportBundleName))
cmd := exec.CommandContext(ctx, sbBinary(), "spec/clusterResources.yaml", "--interactive=false", fmt.Sprintf("-o=%s", supportBundleName))
cmd.Stdout = &out
err := cmd.Run()
if err != nil {

View File

@@ -0,0 +1,95 @@
package e2e
import (
"bytes"
"context"
"encoding/json"
"fmt"
"os"
"os/exec"
"path/filepath"
"strings"
"testing"
"github.com/replicatedhq/troubleshoot/internal/testutils"
"github.com/replicatedhq/troubleshoot/pkg/convert"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/e2e-framework/pkg/envconf"
"sigs.k8s.io/e2e-framework/pkg/features"
"sigs.k8s.io/e2e-framework/third_party/helm"
)
var specTemplate = `
apiVersion: troubleshoot.sh/v1beta2
kind: SupportBundle
metadata:
name: goldpinger
spec:
collectors:
- goldpinger:
namespace: $NAMESPACE
analyzers:
- goldpinger: {}
`
func Test_GoldpingerCollector(t *testing.T) {
releaseName := "goldpinger"
feature := features.New("Goldpinger collector and analyser").
Setup(func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
cluster := getClusterFromContext(t, ctx, ClusterName)
manager := helm.New(cluster.GetKubeconfig())
err := manager.RunInstall(
helm.WithName(releaseName),
helm.WithNamespace(c.Namespace()),
helm.WithChart(testutils.TestFixtureFilePath(t, "charts/goldpinger-6.0.1.tgz")),
helm.WithWait(),
helm.WithTimeout("1m"),
)
require.NoError(t, err)
return ctx
}).
Assess("collect and analyse goldpinger pings", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
var out bytes.Buffer
namespace := c.Namespace()
supportBundleName := "goldpinger-test"
spec := strings.ReplaceAll(specTemplate, "$NAMESPACE", namespace)
specPath := filepath.Join(t.TempDir(), "goldpinger.yaml")
err := os.WriteFile(specPath, []byte(spec), 0644)
require.NoError(t, err)
tarPath := filepath.Join(t.TempDir(), fmt.Sprintf("%s.tar.gz", supportBundleName))
cmd := exec.CommandContext(ctx, sbBinary(), specPath, "--interactive=false", "-v=2", fmt.Sprintf("-o=%s", tarPath))
cmd.Stdout = &out
err = cmd.Run()
t.Log(out.String())
require.NoError(t, err)
analysisJSON, err := readFileFromTar(tarPath, fmt.Sprintf("%s/analysis.json", supportBundleName))
require.NoError(t, err)
var analysisResults []convert.Result
err = json.Unmarshal(analysisJSON, &analysisResults)
require.NoError(t, err)
// Check that we analysed collected goldpinger results.
// There won't be any ping results because goldpinger would not have run yet.
// The test is fine since this checks that we query the goldpinger results correctly
// and the analyser is working.
require.Equal(t, 1, len(analysisResults))
assert.True(t, strings.HasPrefix(analysisResults[0].Name, "missing.ping.results.for.goldpinger."))
assert.Equal(t, convert.SeverityWarn, analysisResults[0].Severity)
return ctx
}).
Teardown(func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
cluster := getClusterFromContext(t, ctx, ClusterName)
manager := helm.New(cluster.GetKubeconfig())
manager.RunUninstall(helm.WithName(releaseName), helm.WithNamespace(c.Namespace()))
return ctx
}).
Feature()
testenv.Test(t, feature)
}

View File

@@ -11,7 +11,6 @@ import (
"testing"
"sigs.k8s.io/e2e-framework/pkg/envconf"
"sigs.k8s.io/e2e-framework/pkg/envfuncs"
"sigs.k8s.io/e2e-framework/pkg/features"
"sigs.k8s.io/e2e-framework/third_party/helm"
@@ -26,10 +25,7 @@ func Test_HelmCollector(t *testing.T) {
feature := features.New("Collector Helm Release").
Setup(func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
cluster, ok := envfuncs.GetKindClusterFromContext(ctx, ClusterName)
if !ok {
t.Fatalf("Failed to extract kind cluster %s from context", ClusterName)
}
cluster := getClusterFromContext(t, ctx, ClusterName)
manager := helm.New(cluster.GetKubeconfig())
manager.RunInstall(helm.WithName(releaseName), helm.WithNamespace(c.Namespace()), helm.WithChart(filepath.Join(curDir, "testdata/charts/nginx-15.2.0.tgz")), helm.WithWait(), helm.WithTimeout("1m"))
//ignore error to allow test to speed up, helm collector will catch the pending or deployed helm release status
@@ -43,7 +39,7 @@ func Test_HelmCollector(t *testing.T) {
namespace := c.Namespace()
tarPath := fmt.Sprintf("%s.tar.gz", supportBundleName)
targetFile := fmt.Sprintf("%s/helm/%s.json", supportBundleName, namespace)
cmd := exec.Command("../../../bin/support-bundle", "spec/helm.yaml", "--interactive=false", fmt.Sprintf("-o=%s", supportBundleName))
cmd := exec.CommandContext(ctx, sbBinary(), "spec/helm.yaml", "--interactive=false", fmt.Sprintf("-o=%s", supportBundleName))
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
@@ -72,6 +68,12 @@ func Test_HelmCollector(t *testing.T) {
assert.Equal(t, "nginx", results[0].Chart)
return ctx
}).
Teardown(func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context {
cluster := getClusterFromContext(t, ctx, ClusterName)
manager := helm.New(cluster.GetKubeconfig())
manager.RunUninstall(helm.WithName(releaseName), helm.WithNamespace(c.Namespace()))
return ctx
}).
Feature()
testenv.Test(t, feature)
}

View File

@@ -4,6 +4,7 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
"context"
"fmt"
"io"
"os"
@@ -14,6 +15,7 @@ import (
"sigs.k8s.io/e2e-framework/pkg/env"
"sigs.k8s.io/e2e-framework/pkg/envconf"
"sigs.k8s.io/e2e-framework/pkg/envfuncs"
"sigs.k8s.io/e2e-framework/support/kind"
)
var testenv env.Environment
@@ -24,16 +26,29 @@ func TestMain(m *testing.M) {
testenv = env.New()
namespace := envconf.RandomName("default", 16)
testenv.Setup(
envfuncs.CreateKindCluster(ClusterName),
envfuncs.CreateCluster(kind.NewProvider(), ClusterName),
envfuncs.CreateNamespace(namespace),
)
testenv.Finish(
envfuncs.DeleteNamespace(namespace),
envfuncs.DestroyKindCluster(ClusterName),
envfuncs.DestroyCluster(ClusterName),
)
os.Exit(testenv.Run(m))
}
func getClusterFromContext(t *testing.T, ctx context.Context, clusterName string) *kind.Cluster {
provider, ok := envfuncs.GetClusterFromContext(ctx, ClusterName)
if !ok {
t.Fatalf("Failed to extract kind cluster %s from context", ClusterName)
}
cluster, ok := provider.(*kind.Cluster)
if !ok {
t.Fatalf("Failed to cast kind cluster %s from provider", ClusterName)
}
return cluster
}
func readFilesAndFoldersFromTar(tarPath, targetFolder string) ([]string, []string, error) {
file, err := os.Open(tarPath)
if err != nil {
@@ -112,5 +127,9 @@ func readFileFromTar(tarPath, targetFile string) ([]byte, error) {
return buf.Bytes(), nil
}
}
return nil, fmt.Errorf("File not found: %s", targetFile)
return nil, fmt.Errorf("File not found: %q", targetFile)
}
func sbBinary() string {
return "../../../bin/support-bundle"
}