-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(e2e): add local host support bundle test (#1680)
- Loading branch information
Showing
6 changed files
with
378 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package e2e | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"slices" | ||
"strings" | ||
"testing" | ||
|
||
"sigs.k8s.io/e2e-framework/pkg/envconf" | ||
"sigs.k8s.io/e2e-framework/pkg/features" | ||
) | ||
|
||
func TestHostLocalCollector(t *testing.T) { | ||
tests := []struct { | ||
paths []string | ||
notExpectedPaths []string | ||
expectType string | ||
}{ | ||
{ | ||
paths: []string{ | ||
"cpu.json", | ||
}, | ||
notExpectedPaths: []string{ | ||
"node_list.json", | ||
}, | ||
expectType: "file", | ||
}, | ||
} | ||
|
||
feature := features.New("Preflight Host Local Collector"). | ||
Assess("check preflight catch host local collector", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context { | ||
var out bytes.Buffer | ||
var errOut bytes.Buffer | ||
preflightName := "preflightbundle" | ||
cmd := exec.CommandContext(ctx, preflightBinary(), "spec/localHostCollectors.yaml", "--interactive=false") | ||
cmd.Stdout = &out | ||
cmd.Stderr = &errOut | ||
|
||
err := cmd.Run() | ||
tarPath := GetFilename(errOut.String(), preflightName) | ||
if err != nil { | ||
if tarPath == "" { | ||
t.Error(err) | ||
} | ||
} | ||
|
||
defer func() { | ||
err := os.Remove(tarPath) | ||
if err != nil { | ||
t.Error("Error remove file:", err) | ||
} | ||
}() | ||
|
||
targetFile := fmt.Sprintf("%s/host-collectors/system/", strings.TrimSuffix(tarPath, ".tar.gz")) | ||
|
||
files, _, err := readFilesAndFoldersFromTar(tarPath, targetFile) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
for _, test := range tests { | ||
if test.expectType == "file" { | ||
for _, path := range test.paths { | ||
if !slices.Contains(files, path) { | ||
t.Errorf("Expected file %s not found in the tarball", path) | ||
} | ||
} | ||
for _, path := range test.notExpectedPaths { | ||
if slices.Contains(files, path) { | ||
t.Errorf("Unexpected file %s found in the tarball", path) | ||
} | ||
} | ||
} | ||
} | ||
return ctx | ||
}).Feature() | ||
testenv.Test(t, feature) | ||
} | ||
|
||
func GetFilename(input, prefix string) string { | ||
// Split the input into words | ||
words := strings.Fields(input) | ||
// Iterate over each word to find the one starting with the prefix | ||
for _, word := range words { | ||
if strings.HasPrefix(word, prefix) { | ||
return word | ||
} | ||
} | ||
|
||
// Return an empty string if no match is found | ||
return "" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
package e2e | ||
|
||
import ( | ||
"archive/tar" | ||
"bytes" | ||
"compress/gzip" | ||
"context" | ||
"flag" | ||
"fmt" | ||
"io" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
"testing" | ||
|
||
"k8s.io/klog/v2" | ||
"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 | ||
|
||
const ClusterName = "kind-cluster" | ||
|
||
func TestMain(m *testing.M) { | ||
// enable klog | ||
klog.InitFlags(nil) | ||
if os.Getenv("E2E_VERBOSE") == "1" { | ||
_ = flag.Set("v", "10") | ||
} | ||
|
||
testenv = env.New() | ||
namespace := envconf.RandomName("default", 16) | ||
testenv.Setup( | ||
envfuncs.CreateCluster(kind.NewProvider(), ClusterName), | ||
envfuncs.CreateNamespace(namespace), | ||
) | ||
testenv.Finish( | ||
envfuncs.DeleteNamespace(namespace), | ||
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 { | ||
return nil, nil, fmt.Errorf("Error opening file: %w", err) | ||
} | ||
defer file.Close() | ||
|
||
gzipReader, err := gzip.NewReader(file) | ||
if err != nil { | ||
return nil, nil, fmt.Errorf("Error initializing gzip reader: %w", err) | ||
} | ||
defer gzipReader.Close() | ||
|
||
tarReader := tar.NewReader(gzipReader) | ||
var files []string | ||
var folders []string | ||
|
||
for { | ||
header, err := tarReader.Next() | ||
|
||
if err == io.EOF { | ||
break | ||
} | ||
if err != nil { | ||
return nil, nil, fmt.Errorf("Error reading tar: %w", err) | ||
} | ||
|
||
if strings.HasPrefix(header.Name, targetFolder) { | ||
relativePath, err := filepath.Rel(targetFolder, header.Name) | ||
if err != nil { | ||
return nil, nil, fmt.Errorf("Error getting relative path: %w", err) | ||
} | ||
if relativePath != "" { | ||
relativeDir := filepath.Dir(relativePath) | ||
if relativeDir != "." { | ||
parentDir := strings.Split(relativeDir, "/")[0] | ||
folders = append(folders, parentDir) | ||
} else { | ||
files = append(files, relativePath) | ||
} | ||
} | ||
} | ||
} | ||
|
||
return files, folders, nil | ||
} | ||
|
||
func readFileFromTar(tarPath, targetFile string) ([]byte, error) { | ||
file, err := os.Open(tarPath) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error opening file: %w", err) | ||
} | ||
defer file.Close() | ||
|
||
gzipReader, err := gzip.NewReader(file) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error initializing gzip reader: %w", err) | ||
} | ||
defer gzipReader.Close() | ||
|
||
tarReader := tar.NewReader(gzipReader) | ||
|
||
for { | ||
header, err := tarReader.Next() | ||
|
||
if err == io.EOF { | ||
break | ||
} | ||
if err != nil { | ||
return nil, fmt.Errorf("Error reading tar: %w", err) | ||
} | ||
|
||
if header.Name == targetFile { | ||
buf := new(bytes.Buffer) | ||
_, err = io.Copy(buf, tarReader) | ||
if err != nil { | ||
return nil, fmt.Errorf("Error copying data: %w", err) | ||
} | ||
return buf.Bytes(), nil | ||
} | ||
} | ||
return nil, fmt.Errorf("File not found: %q", targetFile) | ||
} | ||
|
||
func preflightBinary() string { | ||
return "../../../bin/preflight" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
apiVersion: troubleshoot.sh/v1beta2 | ||
kind: HostPreflight | ||
metadata: | ||
name: ec-cluster-preflight | ||
spec: | ||
collectors: | ||
- cpu: {} | ||
analyzers: | ||
- cpu: | ||
checkName: "Number of CPUs" | ||
outcomes: | ||
- pass: | ||
when: "count < 2" | ||
message: At least 2 CPU cores are required, and 4 CPU cores are recommended | ||
- warn: | ||
when: "count < 4" | ||
message: At least 4 CPU cores are recommended | ||
- pass: | ||
message: This server has at least 4 CPU cores |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package e2e | ||
|
||
import ( | ||
"bytes" | ||
"context" | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"testing" | ||
|
||
"golang.org/x/exp/slices" | ||
"sigs.k8s.io/e2e-framework/pkg/envconf" | ||
"sigs.k8s.io/e2e-framework/pkg/features" | ||
) | ||
|
||
func TestHostLocalCollector(t *testing.T) { | ||
tests := []struct { | ||
paths []string | ||
notExpectedPaths []string | ||
expectType string | ||
}{ | ||
{ | ||
paths: []string{ | ||
"cpu.json", | ||
"hostos_info.json", | ||
"ipv4Interfaces.json", | ||
"memory.json", | ||
}, | ||
notExpectedPaths: []string{ | ||
"node_list.json", | ||
}, | ||
expectType: "file", | ||
}, | ||
} | ||
feature := features.New("Host Local Collector"). | ||
Assess("check support bundle catch host local collector", func(ctx context.Context, t *testing.T, c *envconf.Config) context.Context { | ||
var out bytes.Buffer | ||
supportbundleName := "host-local-collector" | ||
tarPath := fmt.Sprintf("%s.tar.gz", supportbundleName) | ||
targetFile := fmt.Sprintf("%s/host-collectors/system/", supportbundleName) | ||
cmd := exec.CommandContext(ctx, sbBinary(), "spec/localHostCollectors.yaml", "--interactive=false", fmt.Sprintf("-o=%s", supportbundleName)) | ||
cmd.Stdout = &out | ||
err := cmd.Run() | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
defer func() { | ||
err := os.Remove(fmt.Sprintf("%s.tar.gz", supportbundleName)) | ||
if err != nil { | ||
t.Error("Error remove file:", err) | ||
} | ||
}() | ||
|
||
files, _, err := readFilesAndFoldersFromTar(tarPath, targetFile) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
for _, test := range tests { | ||
if test.expectType == "file" { | ||
for _, path := range test.notExpectedPaths { | ||
if slices.Contains(files, path) { | ||
t.Fatalf("Unexpected file %s found", path) | ||
} | ||
} | ||
for _, path := range test.paths { | ||
if !slices.Contains(files, path) { | ||
t.Fatalf("Expected file %s not found", path) | ||
} | ||
} | ||
} | ||
} | ||
|
||
return ctx | ||
}).Feature() | ||
testenv.Test(t, feature) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
apiVersion: troubleshoot.sh/v1beta2 | ||
kind: SupportBundle | ||
metadata: | ||
name: "remote-host-collectors" | ||
spec: | ||
hostCollectors: | ||
- ipv4Interfaces: {} | ||
- hostServices: {} | ||
- cpu: {} | ||
- hostOS: {} | ||
- memory: {} | ||
- blockDevices: {} | ||
- kernelConfigs: {} | ||
- copy: | ||
collectorName: etc-resolv | ||
path: /etc/resolv.conf | ||
- dns: | ||
collectorName: replicated-app-resolve | ||
hostnames: | ||
- replicated.app | ||
- diskUsage: | ||
collectorName: root-disk-usage | ||
path: / | ||
- diskUsage: | ||
collectorName: tmp | ||
path: /tmp | ||
- http: | ||
collectorName: get-replicated-app | ||
get: | ||
url: https://replicated.app | ||
- run: | ||
collectorName: uptime | ||
command: uptime |