Files
troubleshoot/pkg/collect/util_test.go
Evans Mungai 53113c0170 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
2023-12-12 11:02:41 +00:00

335 lines
9.4 KiB
Go

package collect
import (
"context"
"math/rand"
"testing"
"github.com/replicatedhq/troubleshoot/internal/testutils"
"github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
troubleshootv1beta2 "github.com/replicatedhq/troubleshoot/pkg/apis/troubleshoot/v1beta2"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
testclient "k8s.io/client-go/kubernetes/fake"
)
func Test_selectorToString(t *testing.T) {
tests := []struct {
name string
selector []string
expect string
}{
{
name: "app=api",
selector: []string{"app=api"},
expect: "app-api",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := selectorToString(test.selector)
assert.Equal(t, test.expect, actual)
})
}
}
func Test_DeterministicIDForCollector(t *testing.T) {
tests := []struct {
name string
collector *troubleshootv1beta2.Collect
expect string
}{
{
name: "cluster-info",
collector: &troubleshootv1beta2.Collect{
ClusterInfo: &troubleshootv1beta2.ClusterInfo{},
},
expect: "cluster-info",
},
{
name: "cluster-resources",
collector: &troubleshootv1beta2.Collect{
ClusterResources: &troubleshootv1beta2.ClusterResources{},
},
expect: "cluster-resources",
},
{
name: "secret",
collector: &troubleshootv1beta2.Collect{
Secret: &troubleshootv1beta2.Secret{
Namespace: "top-secret",
Name: "secret-agent-woman",
},
},
expect: "secret-top-secret-secret-agent-woman",
},
{
name: "secret selector",
collector: &troubleshootv1beta2.Collect{
Secret: &troubleshootv1beta2.Secret{
Namespace: "top-secret",
Selector: []string{"this=is", "rather=long", "for=testing", "more=words", "too=many", "abcdef!=123456"},
},
},
expect: "secret-top-secret-this-is-rather-long-for-testing-more-words-to",
},
{
name: "configmap",
collector: &troubleshootv1beta2.Collect{
ConfigMap: &troubleshootv1beta2.ConfigMap{
Namespace: "top-secret",
Name: "secret-agent-woman",
},
},
expect: "configmap-top-secret-secret-agent-woman",
},
{
name: "configmap selector",
collector: &troubleshootv1beta2.Collect{
ConfigMap: &troubleshootv1beta2.ConfigMap{
Namespace: "top-secret",
Selector: []string{"this=is", "rather=long", "for=testing", "more=words", "too=many", "abcdef!=123456"},
},
},
expect: "configmap-top-secret-this-is-rather-long-for-testing-more-words",
},
{
name: "logs",
collector: &troubleshootv1beta2.Collect{
Logs: &troubleshootv1beta2.Logs{
Namespace: "top-secret",
Selector: []string{"this=is", "rather=long", "for=testing", "more=words", "too=many", "abcdef!=123456"},
},
},
expect: "logs-top-secret-this-is-rather-long-for-testing-more-words-too-",
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := DeterministicIDForCollector(test.collector)
assert.Equal(t, test.expect, actual)
})
}
}
func Test_createTLSConfig(t *testing.T) {
k8sClient := testclient.NewSimpleClientset()
tests := []struct {
name string
tlsParams v1beta2.TLSParams
caCertOnly bool
hasError bool
}{
{
name: "complete tls params creates config successfully",
tlsParams: v1beta2.TLSParams{
CACert: testutils.GetTestFixture(t, "db/ca.pem"),
ClientCert: testutils.GetTestFixture(t, "db/client.pem"),
ClientKey: testutils.GetTestFixture(t, "db/client-key.pem"),
},
},
{
name: "complete tls params in secret creates config successfully",
tlsParams: v1beta2.TLSParams{
Secret: createTLSSecret(t, k8sClient, map[string]string{
"cacert": testutils.GetTestFixture(t, "db/ca.pem"),
"clientCert": testutils.GetTestFixture(t, "db/client.pem"),
"clientKey": testutils.GetTestFixture(t, "db/client-key.pem"),
}),
},
},
{
name: "tls params with skip verify creates config successfully",
tlsParams: v1beta2.TLSParams{
SkipVerify: true,
},
},
{
name: "tls params with CA cert only in secret creates config successfully",
tlsParams: v1beta2.TLSParams{
Secret: createTLSSecret(t, k8sClient, map[string]string{
"cacert": testutils.GetTestFixture(t, "db/ca.pem"),
}),
},
caCertOnly: true,
},
{
name: "tls params with CA cert only creates config successfully",
tlsParams: v1beta2.TLSParams{
CACert: testutils.GetTestFixture(t, "db/ca.pem"),
},
caCertOnly: true,
},
{
name: "empty TLS parameters fails to create config with error",
hasError: true,
},
{
name: "missing CA cert fails to create config with error",
tlsParams: v1beta2.TLSParams{
ClientCert: testutils.GetTestFixture(t, "db/client.pem"),
ClientKey: testutils.GetTestFixture(t, "db/client-key.pem"),
},
hasError: true,
},
{
name: "missing client cert fails to create config with error",
tlsParams: v1beta2.TLSParams{
CACert: testutils.GetTestFixture(t, "db/ca.pem"),
ClientKey: testutils.GetTestFixture(t, "db/client-key.pem"),
},
hasError: true,
},
{
name: "missing client key fails to create config with error",
tlsParams: v1beta2.TLSParams{
CACert: testutils.GetTestFixture(t, "db/ca.pem"),
ClientCert: testutils.GetTestFixture(t, "db/client.pem"),
},
hasError: true,
},
{
name: "missing CA cert in secret fails to create config with error",
tlsParams: v1beta2.TLSParams{
Secret: createTLSSecret(t, k8sClient, map[string]string{
"clientCert": testutils.GetTestFixture(t, "db/client.pem"),
"clientKey": testutils.GetTestFixture(t, "db/client-key.pem"),
}),
},
hasError: true,
},
{
name: "missing client cert in secret fails to create config with error",
tlsParams: v1beta2.TLSParams{
Secret: createTLSSecret(t, k8sClient, map[string]string{
"cacert": testutils.GetTestFixture(t, "db/ca.pem"),
"clientKey": testutils.GetTestFixture(t, "db/client-key.pem"),
}),
},
hasError: true,
},
{
name: "missing client key in secret fails to create config with error",
tlsParams: v1beta2.TLSParams{
Secret: createTLSSecret(t, k8sClient, map[string]string{
"cacert": testutils.GetTestFixture(t, "db/ca.pem"),
"clientCert": testutils.GetTestFixture(t, "db/client.pem"),
}),
},
hasError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tlsCfg, err := createTLSConfig(context.Background(), k8sClient, &tt.tlsParams)
assert.Equalf(t, tt.hasError, err != nil, "createTLSConfig() error = %v, wantErr %v", err, tt.hasError)
if err == nil {
require.NotNil(t, tlsCfg)
if tt.tlsParams.SkipVerify {
assert.True(t, tlsCfg.InsecureSkipVerify)
assert.Nil(t, tlsCfg.RootCAs)
assert.Nil(t, tlsCfg.Certificates)
} else {
// TLS parameter objects are opaque. Just check if they were created.
// There is no trivial way to inspect their metadata. Trust me :)
assert.NotNil(t, tlsCfg.RootCAs)
assert.Equal(t, tt.caCertOnly, tlsCfg.Certificates == nil)
assert.False(t, tlsCfg.InsecureSkipVerify)
}
} else {
t.Log(err)
assert.Nil(t, tlsCfg)
}
})
}
}
func randStringRunes(n int) string {
runes := []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
b := make([]rune, n)
for i := range b {
b[i] = runes[rand.Intn(len(runes))]
}
return string(b)
}
// createTLSSecret create a secret in a fake client
func createTLSSecret(t *testing.T, client kubernetes.Interface, secretData map[string]string) *v1beta2.TLSSecret {
t.Helper()
// Generate unique names cause we reuse the same client
secretName := "secret-name-" + randStringRunes(20)
namespace := "namespace-" + randStringRunes(20)
_, err := client.CoreV1().Secrets(namespace).Create(
context.Background(),
&v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
},
StringData: secretData,
},
metav1.CreateOptions{},
)
require.NoError(t, err)
return &v1beta2.TLSSecret{
Namespace: namespace,
Name: secretName,
}
}
func Test_checkForExistingServiceAccount(t *testing.T) {
tests := []struct {
name string
namespace string
serviceAccountName string
mockServiceAccount *corev1.ServiceAccount
wantErr bool
}{
{
name: "Service account doesn't exist",
namespace: "test-namespace",
serviceAccountName: "test-service-account",
mockServiceAccount: nil,
wantErr: true,
},
{
name: "Service account already exists",
namespace: "test-namespace",
serviceAccountName: "test-service-account",
mockServiceAccount: &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: "test-service-account",
},
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
client := testclient.NewSimpleClientset()
if tt.mockServiceAccount != nil {
_, err := client.CoreV1().ServiceAccounts(tt.namespace).Create(ctx, tt.mockServiceAccount, metav1.CreateOptions{})
require.NoError(t, err)
err = checkForExistingServiceAccount(ctx, client, tt.namespace, tt.serviceAccountName)
assert.Equal(t, tt.wantErr, err != nil)
}
err := checkForExistingServiceAccount(ctx, client, tt.namespace, tt.serviceAccountName)
assert.Equal(t, tt.wantErr, err != nil)
})
}
}