github.com/verrazzano/verrazzano@v1.7.0/tools/vz/pkg/helpers/vzcapture_test.go (about)

     1  // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package helpers
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/common"
    10  	"os"
    11  	"path/filepath"
    12  	"regexp"
    13  	"testing"
    14  
    15  	v1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
    16  	"github.com/crossplane/oam-kubernetes-runtime/apis/core"
    17  	"github.com/stretchr/testify/assert"
    18  	appv1alpha1 "github.com/verrazzano/verrazzano/application-operator/apis/app/v1alpha1"
    19  	appclusterv1alpha1 "github.com/verrazzano/verrazzano/application-operator/apis/clusters/v1alpha1"
    20  	appoamv1alpha1 "github.com/verrazzano/verrazzano/application-operator/apis/oam/v1alpha1"
    21  	clusterv1alpha1 "github.com/verrazzano/verrazzano/cluster-operator/apis/clusters/v1alpha1"
    22  	"github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1beta1"
    23  	"github.com/verrazzano/verrazzano/tools/vz/pkg/constants"
    24  	testhelpers "github.com/verrazzano/verrazzano/tools/vz/test/helpers"
    25  	corev1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/cli-runtime/pkg/genericclioptions"
    28  	fakedynamic "k8s.io/client-go/dynamic/fake"
    29  	k8sfake "k8s.io/client-go/kubernetes/fake"
    30  	k8scheme "k8s.io/client-go/kubernetes/scheme"
    31  	"sigs.k8s.io/controller-runtime/pkg/client"
    32  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    33  )
    34  
    35  const dummyIP1 = "0.0.0.0"
    36  const dummyIP2 = "5.6.x.x"
    37  
    38  // TestCreateReportArchive
    39  // GIVEN a directory containing some files
    40  //
    41  //	WHEN I call function CreateReportArchive with a report file
    42  //	THEN expect it to create the report file
    43  func TestCreateReportArchive(t *testing.T) {
    44  	tmpDir, _ := os.MkdirTemp("", "bug-report")
    45  	defer cleanupTempDir(t, tmpDir)
    46  
    47  	captureDir := tmpDir + string(os.PathSeparator) + "test-report"
    48  	if err := os.Mkdir(captureDir, os.ModePerm); err != nil {
    49  		assert.Error(t, err)
    50  	}
    51  
    52  	// Create some files inside bugReport
    53  	_, err := os.Create(captureDir + string(os.PathSeparator) + "f1.txt")
    54  	if err != nil {
    55  		assert.Error(t, err)
    56  	}
    57  
    58  	_, err = os.Create(captureDir + string(os.PathSeparator) + "f2.txt")
    59  	if err != nil {
    60  		assert.Error(t, err)
    61  	}
    62  
    63  	_, err = os.Create(captureDir + string(os.PathSeparator) + "f3.txt")
    64  	if err != nil {
    65  		assert.Error(t, err)
    66  	}
    67  
    68  	bugReportFile, err := os.Create(tmpDir + string(os.PathSeparator) + "bug.tar.gz")
    69  	if err != nil {
    70  		assert.Error(t, err)
    71  	}
    72  	err = CreateReportArchive(captureDir, bugReportFile)
    73  	if err != nil {
    74  		assert.Error(t, err)
    75  	}
    76  
    77  	// Check file exists
    78  	assert.FileExists(t, bugReportFile.Name())
    79  }
    80  
    81  // TestRemoveDuplicates
    82  // GIVEN a string slice containing duplicates
    83  //
    84  //	WHEN I call function RemoveDuplicate
    85  //	THEN expect it to remove the duplicate elements
    86  func TestRemoveDuplicates(t *testing.T) {
    87  	testSlice := []string{"abc", "def", "abc"}
    88  	result := RemoveDuplicate(testSlice)
    89  	assert.True(t, true, len(result) == 2)
    90  }
    91  
    92  // TestGroupVersionResource
    93  //
    94  //	WHEN I call functions to get the config schemes
    95  //	THEN expect it to return the expected resource
    96  func TestGroupVersionResource(t *testing.T) {
    97  	assert.True(t, true, GetAppConfigScheme().Resource == constants.OAMAppConfigurations)
    98  	assert.True(t, true, GetComponentConfigScheme().Resource == constants.OAMComponents)
    99  	assert.True(t, true, GetMetricsTraitConfigScheme().Resource == constants.OAMMetricsTraits)
   100  	assert.True(t, true, GetIngressTraitConfigScheme().Resource == constants.OAMIngressTraits)
   101  	assert.True(t, true, GetMCComponentScheme().Resource == constants.OAMMCCompConfigurations)
   102  	assert.True(t, true, GetMCAppConfigScheme().Resource == constants.OAMMCAppConfigurations)
   103  	assert.True(t, true, GetVzProjectsConfigScheme().Resource == constants.OAMProjects)
   104  	assert.True(t, true, GetManagedClusterConfigScheme().Resource == constants.OAMManagedClusters)
   105  }
   106  
   107  // TestCaptureK8SResources
   108  //
   109  //	WHEN I call functions to capture k8s resource
   110  //	THEN expect it to not throw any error
   111  func TestCaptureK8SResources(t *testing.T) {
   112  	schemeForClient := k8scheme.Scheme
   113  	err := v1.AddToScheme(schemeForClient)
   114  	assert.NoError(t, err)
   115  	k8sClient := k8sfake.NewSimpleClientset()
   116  	scheme := k8scheme.Scheme
   117  	AddCapiToScheme(scheme)
   118  	dynamicClient := fakedynamic.NewSimpleDynamicClient(scheme)
   119  	client := fake.NewClientBuilder().WithScheme(schemeForClient).Build()
   120  	captureDir, err := os.MkdirTemp("", "testcapture")
   121  	defer cleanupTempDir(t, captureDir)
   122  	assert.NoError(t, err)
   123  	buf := new(bytes.Buffer)
   124  	errBuf := new(bytes.Buffer)
   125  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   126  	err = CaptureK8SResources(client, k8sClient, dynamicClient, constants.VerrazzanoInstall, captureDir, rc)
   127  	assert.NoError(t, err)
   128  }
   129  
   130  // TestCaptureMultiClusterResources tests the functionality to capture the multi cluster related resources
   131  //
   132  //	WHEN I call functions to capture Verrazzano multi cluster resources
   133  //	THEN expect it to not throw any error
   134  func TestCaptureMultiClusterResources(t *testing.T) {
   135  	scheme := k8scheme.Scheme
   136  	_ = v1beta1.AddToScheme(scheme)
   137  	_ = clusterv1alpha1.AddToScheme(scheme)
   138  	_ = appclusterv1alpha1.AddToScheme(scheme)
   139  
   140  	dynamicClient := fakedynamic.NewSimpleDynamicClient(scheme)
   141  	captureDir, err := os.MkdirTemp("", "testcapture")
   142  	defer cleanupTempDir(t, captureDir)
   143  	assert.NoError(t, err)
   144  	buf := new(bytes.Buffer)
   145  	errBuf := new(bytes.Buffer)
   146  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   147  	assert.NoError(t, CaptureMultiClusterOAMResources(dynamicClient, []string{constants.VerrazzanoInstall}, captureDir, rc))
   148  }
   149  
   150  // TestCaptureOAMResources tests the functionality to capture the OAM resources in the cluster
   151  //
   152  //	WHEN I call functions to capture Verrazzano OAM resources
   153  //	THEN expect it to not throw any error
   154  func TestCaptureOAMResources(t *testing.T) {
   155  	scheme := k8scheme.Scheme
   156  	_ = v1beta1.AddToScheme(scheme)
   157  	_ = clusterv1alpha1.AddToScheme(scheme)
   158  	_ = appclusterv1alpha1.AddToScheme(scheme)
   159  	_ = appv1alpha1.AddToScheme(scheme)
   160  	_ = appoamv1alpha1.AddToScheme(scheme)
   161  	_ = core.AddToScheme(scheme)
   162  
   163  	dynamicClient := fakedynamic.NewSimpleDynamicClient(scheme)
   164  	captureDir, err := os.MkdirTemp("", "testcapture")
   165  	defer cleanupTempDir(t, captureDir)
   166  	assert.NoError(t, err)
   167  	buf := new(bytes.Buffer)
   168  	errBuf := new(bytes.Buffer)
   169  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   170  	assert.NoError(t, CaptureOAMResources(dynamicClient, []string{constants.VerrazzanoInstall}, captureDir, rc))
   171  }
   172  
   173  // TestCapturePodLog tests the functionality to capture the logs of a given pod.
   174  func TestCapturePodLog(t *testing.T) {
   175  	k8sClient := k8sfake.NewSimpleClientset()
   176  	captureDir, err := os.MkdirTemp("", "testcapture")
   177  	defer cleanupTempDir(t, captureDir)
   178  	assert.NoError(t, err)
   179  	buf := new(bytes.Buffer)
   180  	errBuf := new(bytes.Buffer)
   181  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   182  	err = CapturePodLog(k8sClient, corev1.Pod{}, constants.VerrazzanoInstall, captureDir, rc, 0)
   183  	assert.NoError(t, err)
   184  
   185  	//  GIVENT and empty k8s cluster,
   186  	//	WHEN I call functions to capture VPO pod logs,
   187  	//	THEN expect it to not throw any error.
   188  	err = CapturePodLog(k8sClient, corev1.Pod{ObjectMeta: metav1.ObjectMeta{
   189  		Name:      constants.VerrazzanoPlatformOperator,
   190  		Namespace: constants.VerrazzanoInstall,
   191  	}}, constants.VerrazzanoInstall, captureDir, rc, 0)
   192  	assert.NoError(t, err)
   193  
   194  	//  GIVENT a k8s cluster with a VPO pod,
   195  	//	WHEN I call functions to capture VPO pod logs,
   196  	//	THEN expect it to not throw any error.
   197  	k8sClient = k8sfake.NewSimpleClientset(&corev1.Pod{ObjectMeta: metav1.ObjectMeta{
   198  		Name:      constants.VerrazzanoPlatformOperator,
   199  		Namespace: constants.VerrazzanoInstall,
   200  	}, Spec: corev1.PodSpec{
   201  		Containers: []corev1.Container{
   202  			{
   203  				Name:  "testcontainer",
   204  				Image: "dummimage:notag",
   205  			},
   206  		},
   207  	}})
   208  	err = CapturePodLog(k8sClient, corev1.Pod{ObjectMeta: metav1.ObjectMeta{
   209  		Name:      constants.VerrazzanoPlatformOperator,
   210  		Namespace: constants.VerrazzanoInstall,
   211  	}, Spec: corev1.PodSpec{
   212  		Containers: []corev1.Container{
   213  			{
   214  				Name:  "testcontainer",
   215  				Image: "dummimage:notag",
   216  			},
   217  		},
   218  	}}, constants.VerrazzanoInstall, captureDir, rc, 300)
   219  	assert.NoError(t, err)
   220  }
   221  
   222  // TestGetPodList tests the functionality to return the list of pods with the given label
   223  func TestGetPodList(t *testing.T) {
   224  	//  GIVEN a k8s cluster with no VPO pods,
   225  	//	WHEN I call functions to get the list of pods in the k8s cluster,
   226  	//	THEN expect it to be an empty list.
   227  	pods, err := GetPodList(fake.NewClientBuilder().Build(), "app", constants.VerrazzanoPlatformOperator, constants.VerrazzanoInstall)
   228  	assert.NoError(t, err)
   229  	assert.Empty(t, pods)
   230  
   231  	//  GIVEN a k8s cluster with a VPO pod,
   232  	//	WHEN I call functions to get the list of pods in the k8s cluster,
   233  	//	THEN expect it to be an empty list.
   234  	pods, err = GetPodList(fake.NewClientBuilder().WithObjects(&corev1.Pod{
   235  		ObjectMeta: metav1.ObjectMeta{
   236  			Name:      constants.VerrazzanoPlatformOperator,
   237  			Namespace: constants.VerrazzanoInstall,
   238  			Labels:    map[string]string{"app": constants.VerrazzanoPlatformOperator},
   239  		},
   240  	}).Build(), "app", constants.VerrazzanoPlatformOperator, constants.VerrazzanoInstall)
   241  	assert.NoError(t, err)
   242  	assert.NotEmpty(t, pods)
   243  }
   244  
   245  // TestCaptureVZResource tests the functionality to capture the Verrazzano resource.
   246  func TestCaptureVZResource(t *testing.T) {
   247  	captureDir, err := os.MkdirTemp("", "testcapture")
   248  	defer cleanupTempDir(t, captureDir)
   249  	assert.NoError(t, err)
   250  	buf := new(bytes.Buffer)
   251  	errBuf := new(bytes.Buffer)
   252  
   253  	//  GIVEN a k8s cluster with a user provided Verrazzano CR,
   254  	//	WHEN I call functions to capture the Verrazzano CR,
   255  	//	THEN expect the file to contain the JSON output of the Verrazzano CR.
   256  	vz := &v1beta1.Verrazzano{
   257  		ObjectMeta: metav1.ObjectMeta{
   258  			Namespace: "default",
   259  			Name:      "myverrazzano",
   260  		},
   261  		Spec: v1beta1.VerrazzanoSpec{
   262  			Profile: v1beta1.Dev,
   263  		},
   264  	}
   265  	tempFile, err := os.CreateTemp("", "testfile")
   266  	defer cleanupFile(t, tempFile)
   267  	assert.NoError(t, err)
   268  	SetMultiWriterOut(buf, tempFile)
   269  	SetMultiWriterErr(errBuf, tempFile)
   270  	SetVerboseOutput(true)
   271  	SetIsLiveCluster()
   272  	err = CaptureVZResource(captureDir, vz)
   273  	assert.NoError(t, err)
   274  	assert.NotNil(t, GetMultiWriterOut())
   275  	assert.NotNil(t, GetMultiWriterErr())
   276  	assert.True(t, GetIsLiveCluster())
   277  }
   278  
   279  // TestDoesNamespaceExist tests the functionality to check if a given namespace exists.
   280  func TestDoesNamespaceExist(t *testing.T) {
   281  	buf := new(bytes.Buffer)
   282  	errBuf := new(bytes.Buffer)
   283  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   284  	tempFile, _ := os.CreateTemp("", "testfile")
   285  	defer cleanupFile(t, tempFile)
   286  	SetMultiWriterOut(buf, tempFile)
   287  	SetMultiWriterErr(errBuf, tempFile)
   288  	SetVerboseOutput(true)
   289  
   290  	//  GIVEN a k8s cluster with no namespaces,
   291  	//	WHEN I call functions to check if a namespace with empty string exists,
   292  	//	THEN expect it to return false and no error.
   293  	exists, err := DoesNamespaceExist(k8sfake.NewSimpleClientset(), "", rc)
   294  	assert.NoError(t, err)
   295  	assert.False(t, exists)
   296  
   297  	//  GIVEN a k8s cluster with no namespaces,
   298  	//	WHEN I call functions to check if a namespace verrazzano-install exists,
   299  	//	THEN expect it to return false and an error.
   300  	exists, err = DoesNamespaceExist(k8sfake.NewSimpleClientset(), constants.VerrazzanoInstall, rc)
   301  	assert.Error(t, err)
   302  	assert.False(t, exists)
   303  
   304  	//  GIVEN a k8s cluster with the required verrazzano-install namespace,
   305  	//	WHEN I call functions to check if a namespace verrazzano-install exists,
   306  	//	THEN expect it to return true and no error.
   307  	exists, err = DoesNamespaceExist(k8sfake.NewSimpleClientset(&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{
   308  		Name: constants.VerrazzanoInstall,
   309  	}}), constants.VerrazzanoInstall, rc)
   310  	assert.NoError(t, err)
   311  	assert.True(t, exists)
   312  }
   313  
   314  // TestGetVZManagedNamespaces tests the functionality to return all namespaces managed by verrazzano
   315  func TestGetVZManagedNamespaces(t *testing.T) {
   316  	namespaces := GetVZManagedNamespaces(k8sfake.NewSimpleClientset())
   317  	assert.Empty(t, namespaces)
   318  
   319  	//  GIVEN a k8s cluster with the required verrazzano-install namespace with label verrazzano-managed=true,
   320  	//	WHEN I call functions to list the namespaces that are managed by Verrazzano,
   321  	//	THEN expect it to return a single namespace verrazzano-install
   322  	namespaces = GetVZManagedNamespaces(k8sfake.NewSimpleClientset(&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{
   323  		Name:   constants.VerrazzanoInstall,
   324  		Labels: map[string]string{"verrazzano-managed": "true"},
   325  	}}))
   326  	assert.NotEmpty(t, namespaces)
   327  	assert.Equal(t, 1, len(namespaces))
   328  	assert.Equal(t, constants.VerrazzanoInstall, namespaces[0])
   329  }
   330  
   331  // TestIsErrorReported tests the functionality to see if an error had been reported when capturing the k8s resources.
   332  func TestIsErrorReported(t *testing.T) {
   333  	assert.False(t, IsErrorReported())
   334  	LogError("dummy error msg")
   335  	assert.True(t, IsErrorReported())
   336  }
   337  
   338  // TestCreateFile tests the functionality to create a file containing the Verrazzano Resource
   339  func TestCreateFile(t *testing.T) {
   340  	//  GIVEN a k8s cluster with a VPO pod,
   341  	//	WHEN I call functions to create a JSON file for the pod,
   342  	//	THEN expect it to write to the provided resource file, the JSON contents of the pod and no error should be returned.
   343  	captureDir, err := os.MkdirTemp("", "testcapture")
   344  	defer cleanupTempDir(t, captureDir)
   345  	assert.NoError(t, err)
   346  	defer cleanupTempDir(t, captureDir)
   347  	buf := new(bytes.Buffer)
   348  	errBuf := new(bytes.Buffer)
   349  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   350  	err = createFile(corev1.Pod{ObjectMeta: metav1.ObjectMeta{
   351  		Name:      constants.VerrazzanoPlatformOperator,
   352  		Namespace: constants.VerrazzanoInstall,
   353  	}}, constants.VerrazzanoInstall, "test-file", captureDir, rc)
   354  	assert.NoError(t, err)
   355  }
   356  
   357  // cleanupTempDir cleans up the given temp directory after the test run
   358  func cleanupTempDir(t *testing.T, dirName string) {
   359  	if err := os.RemoveAll(dirName); err != nil {
   360  		t.Fatalf("RemoveAll failed: %v", err)
   361  	}
   362  }
   363  
   364  // cleanupTempDir cleans up the given temp file after the test run
   365  func cleanupFile(t *testing.T, file *os.File) {
   366  	if err := file.Close(); err != nil {
   367  		t.Fatalf("RemoveAll failed: %v", err)
   368  	}
   369  }
   370  
   371  // TestGetPodListAll tests the functionality to return the list of all pods
   372  func TestGetPodListAll(t *testing.T) {
   373  	nsName := "test"
   374  	podLength := 5
   375  	var podList []client.Object
   376  	for i := 0; i < podLength; i++ {
   377  		podList = append(podList, &corev1.Pod{
   378  			ObjectMeta: metav1.ObjectMeta{
   379  				Name:      nsName + fmt.Sprint(i),
   380  				Namespace: nsName,
   381  				Labels:    map[string]string{"name": "myapp"},
   382  			},
   383  		})
   384  	}
   385  	//  GIVEN a k8s cluster with no pods,
   386  	//	WHEN I call functions to get the list of pods in the k8s cluster,
   387  	//	THEN expect it to be an empty list.
   388  	pods, err := GetPodListAll(fake.NewClientBuilder().Build(), nsName)
   389  	assert.NoError(t, err)
   390  	assert.Empty(t, pods)
   391  
   392  	//  GIVEN a k8s cluster with 5 pods,
   393  	//	WHEN I call functions to get the list of pods in the k8s cluster without label,
   394  	//	THEN expect it to be list all pods.
   395  	pods, err = GetPodListAll(fake.NewClientBuilder().WithObjects(podList...).Build(), nsName)
   396  	assert.NoError(t, err)
   397  	assert.Equal(t, podLength, len(pods))
   398  }
   399  
   400  //		TestCreateCertificateFile tests that a certificate file titled certificates.json can be successfully written
   401  //	 	GIVEN a k8s cluster with certificates present in a namespace  ,
   402  //		WHEN I call functions to create a list of certificates for the namespace,
   403  //		THEN expect it to write to the provided resource file and no error should be returned.
   404  func TestCreateCertificateFile(t *testing.T) {
   405  	schemeForClient := k8scheme.Scheme
   406  	err := v1.AddToScheme(schemeForClient)
   407  	assert.NoError(t, err)
   408  	sampleCert := v1.Certificate{
   409  		ObjectMeta: metav1.ObjectMeta{Name: "testcertificate", Namespace: "cattle-system"},
   410  		Spec: v1.CertificateSpec{
   411  			DNSNames:    []string{"example.com", "www.example.com", "api.example.com"},
   412  			IPAddresses: []string{dummyIP1, dummyIP2},
   413  		},
   414  	}
   415  	client := fake.NewClientBuilder().WithScheme(schemeForClient).WithObjects(&sampleCert).Build()
   416  	captureDir, err := os.MkdirTemp("", "testcaptureforcertificates")
   417  	assert.NoError(t, err)
   418  	t.Log(captureDir)
   419  	defer cleanupTempDir(t, captureDir)
   420  	buf := new(bytes.Buffer)
   421  	errBuf := new(bytes.Buffer)
   422  	tempFile, err := os.CreateTemp(captureDir, "temporary-log-file-for-test")
   423  	assert.NoError(t, err)
   424  	SetMultiWriterOut(buf, tempFile)
   425  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   426  	err = captureCertificates(client, "cattle-system", captureDir, rc)
   427  	assert.NoError(t, err)
   428  }
   429  
   430  // TestCreateCaCrtInfoFile tests that a caCrtInfo file titled caCrtInfo.json can be successfully written
   431  // GIVEN a k8s cluster with secrets containing caCrtInfo present in a namespace  ,
   432  // WHEN I call functions to create a list of caCrt for the namespace,
   433  // THEN expect it to write to the provided resource file and no error should be returned.
   434  func TestCreateCaCrtJsonFile(t *testing.T) {
   435  	schemeForClient := k8scheme.Scheme
   436  	err := v1.AddToScheme(schemeForClient)
   437  	assert.NoError(t, err)
   438  	certificateListForTest := v1.CertificateList{}
   439  	sampleCert := v1.Certificate{
   440  		ObjectMeta: metav1.ObjectMeta{Name: "test-certificate-caCrt.json", Namespace: "cattle-system"},
   441  		Spec: v1.CertificateSpec{
   442  			DNSNames:    []string{"example.com", "www.example.com", "api.example.com"},
   443  			IPAddresses: []string{dummyIP1, dummyIP2},
   444  			SecretName:  "test-secret-name",
   445  		},
   446  	}
   447  	certificateListForTest.Items = append(certificateListForTest.Items, sampleCert)
   448  	sampleSecret := corev1.Secret{
   449  		ObjectMeta: metav1.ObjectMeta{Name: "test-secret-name", Namespace: "cattle-system"},
   450  		Data: map[string][]byte{
   451  			"ca.crt": []byte("-----BEGIN CERTIFICATE-----\nMIIDvTCCAqWgAwIBAgIUJUr+YG3UuQJh6g4MKuRpZPnTVO0wDQYJKoZIhvcNAQEL\nBQAwbTELMAkGA1UEBhMCUEExDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3Qx\nDTALBgNVBAoMBFRlc3QxDTALBgNVBAsMBFRlc3QxDTALBgNVBAMMBFRlc3QxEzAR\nBgkqhkiG9w0BCQEWBFRlc3QwIBcNMjMwODMwMTkxMjE4WhgPMzAyMjEyMzExOTEy\nMThaMG0xCzAJBgNVBAYTAlBBMQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0\nMQ0wCwYDVQQKDARUZXN0MQ0wCwYDVQQLDARUZXN0MQ0wCwYDVQQDDARUZXN0MRMw\nEQYJKoZIhvcNAQkBFgRUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEA5R5EAPbPhrfRnpGtC49OX9q4XDVP11C/nHZ13z4QMPQn3eD+S5DODjo95wVD\nbZlmOUdGhas037W/G4rsEr+fg2DF3tNV3bNtDU5NG+PjRDcmFDKup0q7Lh7Yf2FP\naNxi6wlIgmm8Yi4lQmaBSN5LZalIbTO+tk7PRa1FY2LCIKDzzY9ipc0h9nDQWXIz\nEUtjQdQuZsdcv+br2L6b891Pu/fiZgJg1Vzx8N9bBbxMl3usI/CT8qmJy4E9fh4q\n0LQMFcOXeVSR4dhGLpctXP82AH2wgz0mLmgXlYe3koX+TlOxGIG3tUKBndvII8wm\nO03wILuk63XhXg30EFjpj0qZiQIDAQABo1MwUTAdBgNVHQ4EFgQUxkWW0nvivNEy\nLAPMJYgNwpSHQ5IwHwYDVR0jBBgwFoAUxkWW0nvivNEyLAPMJYgNwpSHQ5IwDwYD\nVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAtUjYhkDzJoFNx84Y9KXJ\nVM5BRtiI7YuvrKujwFmct1uCDEDXxZivwDf7khbUlI/GDg13LXsHQbxRaZNotcju\nibG9DNwInlBDpJ/grjlz/KG/LCmYrQE5RAnuqxVe812pc2ndSkTOGvcds7n7Gir/\n1S6zn2d5g2KeYtaMEYV1jArjzsFIdZ4M2R0ZTAsArcJy2ZGZ655j54Df7yzviNpD\nTz6nQQv1DHEpdogys+rOUTXrVhSpnsTacwztp/lvQsZl231THlCJcsySHRgMKmB+\nRKLLMfDfIaGeiZWRvEPEdurMWYkwWdYz9d+iEo3YTpWKy2QeCOEFZKMX5B2MXkdd\nNA==\n-----END CERTIFICATE-----\n"),
   452  		},
   453  	}
   454  	client := fake.NewClientBuilder().WithScheme(schemeForClient).WithObjects(&sampleCert, &sampleSecret).Build()
   455  	captureDir, err := os.MkdirTemp("", "testcaptureforcaCrt.json")
   456  	assert.NoError(t, err)
   457  	t.Log(captureDir)
   458  	defer cleanupTempDir(t, captureDir)
   459  	buf := new(bytes.Buffer)
   460  	errBuf := new(bytes.Buffer)
   461  	tempFile, err := os.CreateTemp(captureDir, "temporary-log-file-for-ca-crt-test")
   462  	assert.NoError(t, err)
   463  	SetMultiWriterOut(buf, tempFile)
   464  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   465  	err = captureCaCrtExpirationInfo(client, certificateListForTest, "cattle-system", captureDir, rc)
   466  	assert.NoError(t, err)
   467  }
   468  
   469  // TestRedactHostNamesForCertificates tests the captureCertificates function
   470  // GIVEN when sample cert with DNSNames and IPAddresses which are sensitive information
   471  // WHEN captureCertificates is called on certain namespace
   472  // THEN it should obfuscate the known hostnames with hashed value
   473  // AND the output certificates.json file should NOT contain any of the sensitive information from KnownHostNames
   474  func TestRedactHostNamesForCertificates(t *testing.T) {
   475  	sampleCert := &v1.Certificate{
   476  		ObjectMeta: metav1.ObjectMeta{
   477  			Name:      "test-certificate",
   478  			Namespace: "cattle-system",
   479  		},
   480  		Spec: v1.CertificateSpec{
   481  			DNSNames:    []string{"example.com", "www.example.com", "api.example.com"},
   482  			IPAddresses: []string{dummyIP1, dummyIP2},
   483  		},
   484  	}
   485  
   486  	schemeForClient := k8scheme.Scheme
   487  	err := v1.AddToScheme(schemeForClient)
   488  	assert.NoError(t, err)
   489  	client := fake.NewClientBuilder().WithScheme(schemeForClient).WithObjects(sampleCert).Build()
   490  	captureDir, err := os.MkdirTemp("", "testcaptureforcertificates")
   491  	assert.NoError(t, err)
   492  	t.Log(captureDir)
   493  	defer cleanupTempDir(t, captureDir)
   494  	buf := new(bytes.Buffer)
   495  	errBuf := new(bytes.Buffer)
   496  	tempFile, err := os.CreateTemp(captureDir, "temporary-log-file-for-test")
   497  	assert.NoError(t, err)
   498  	SetMultiWriterOut(buf, tempFile)
   499  	rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf})
   500  
   501  	err = captureCertificates(client, common.CattleSystem, captureDir, rc)
   502  	assert.NoError(t, err)
   503  
   504  	// Check if the file is Sanitized as expected
   505  	certLocation := filepath.Join(captureDir, common.CattleSystem, constants.CertificatesJSON)
   506  	f, err := os.ReadFile(certLocation)
   507  	assert.NoError(t, err, "Should not error reading certificates.json file")
   508  	for k := range KnownHostNames {
   509  		keyMatch, err := regexp.Match(k, f)
   510  		assert.NoError(t, err, "Error while regex matching")
   511  		assert.Falsef(t, keyMatch, "%s should be obfuscated from certificates.json file %s", k, string(f))
   512  	}
   513  }