github.com/verrazzano/verrazzano@v1.7.1/pkg/rancherutil/rancher_config_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 rancherutil
     5  
     6  import (
     7  	"bytes"
     8  	"io"
     9  	"net/http"
    10  	"os"
    11  	"strings"
    12  	"testing"
    13  	"time"
    14  
    15  	"github.com/verrazzano/verrazzano/pkg/nginxutil"
    16  
    17  	"github.com/golang/mock/gomock"
    18  	"github.com/stretchr/testify/assert"
    19  	pkgconst "github.com/verrazzano/verrazzano/pkg/constants"
    20  	"github.com/verrazzano/verrazzano/pkg/log/vzlog"
    21  	"github.com/verrazzano/verrazzano/pkg/test/mockmatchers"
    22  	"github.com/verrazzano/verrazzano/platform-operator/mocks"
    23  	corev1 "k8s.io/api/core/v1"
    24  	networkv1 "k8s.io/api/networking/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/util/wait"
    27  	"sigs.k8s.io/controller-runtime/pkg/client"
    28  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    29  )
    30  
    31  var (
    32  	testToken = "test"
    33  	userID    = "usertest"
    34  )
    35  
    36  // TestCreateRancherRequest tests the creation of a Rancher request sender to make sure that
    37  // HTTP requests are properly constructed and sent to Rancher
    38  func TestCreateRancherRequest(t *testing.T) {
    39  	DeleteStoredTokens()
    40  	cli := createTestObjects()
    41  	log := vzlog.DefaultLogger()
    42  
    43  	testPath := "test/path"
    44  	testBody := "test-body"
    45  
    46  	savedRancherHTTPClient := RancherHTTPClient
    47  	defer func() {
    48  		RancherHTTPClient = savedRancherHTTPClient
    49  	}()
    50  
    51  	savedRetry := DefaultRetry
    52  	defer func() {
    53  		DefaultRetry = savedRetry
    54  	}()
    55  	DefaultRetry = wait.Backoff{
    56  		Steps:    1,
    57  		Duration: 1 * time.Millisecond,
    58  		Factor:   1.0,
    59  		Jitter:   0.1,
    60  	}
    61  
    62  	mocker := gomock.NewController(t)
    63  	httpMock := mocks.NewMockRequestSender(mocker)
    64  	httpMock = expectHTTPRequests(httpMock, testPath, testBody)
    65  	RancherHTTPClient = httpMock
    66  
    67  	// Test with the Verrazzano cluster user
    68  	rc, err := NewVerrazzanoClusterRancherConfig(cli, DefaultRancherIngressHostPrefix+nginxutil.IngressNGINXNamespace(), log)
    69  	assert.NoError(t, err)
    70  
    71  	response, body, err := SendRequest(http.MethodGet, testPath, map[string]string{}, "", rc, log)
    72  	assert.NoError(t, err)
    73  	assert.Equal(t, testBody, body)
    74  	assert.Equal(t, http.StatusOK, response.StatusCode)
    75  
    76  	// Test with the admin user
    77  	rc, err = NewAdminRancherConfig(cli, DefaultRancherIngressHostPrefix+nginxutil.IngressNGINXNamespace(), log)
    78  	assert.NoError(t, err)
    79  
    80  	response, body, err = SendRequest(http.MethodGet, testPath, map[string]string{}, "", rc, log)
    81  	assert.NoError(t, err)
    82  	assert.Equal(t, testBody, body)
    83  	assert.Equal(t, http.StatusOK, response.StatusCode)
    84  
    85  	response, _, err = SendRequest(http.MethodPost, tokensPath, map[string]string{}, "", rc, log)
    86  	assert.NoError(t, err)
    87  
    88  	response, _, err = SendRequest(http.MethodGet, tokensPath+testToken, map[string]string{}, "", rc, log)
    89  	assert.NoError(t, err)
    90  }
    91  
    92  func createTestObjects() client.WithWatch {
    93  	return fake.NewClientBuilder().WithRuntimeObjects(
    94  		&networkv1.Ingress{
    95  			ObjectMeta: metav1.ObjectMeta{
    96  				Namespace: rancherNamespace,
    97  				Name:      rancherIngressName,
    98  			},
    99  			Spec: networkv1.IngressSpec{
   100  				Rules: []networkv1.IngressRule{
   101  					{
   102  						Host: "test-rancher.com",
   103  					},
   104  				},
   105  			},
   106  		},
   107  		&corev1.Secret{
   108  			ObjectMeta: metav1.ObjectMeta{
   109  				Namespace: pkgconst.VerrazzanoMultiClusterNamespace,
   110  				Name:      pkgconst.VerrazzanoClusterRancherName,
   111  			},
   112  			Data: map[string][]byte{
   113  				"password": []byte(""),
   114  			},
   115  		},
   116  		&corev1.Secret{
   117  			ObjectMeta: metav1.ObjectMeta{
   118  				Namespace: rancherNamespace,
   119  				Name:      rancherAdminSecret,
   120  			},
   121  			Data: map[string][]byte{
   122  				"password": []byte(""),
   123  			},
   124  		}).Build()
   125  }
   126  
   127  func expectHTTPRequests(httpMock *mocks.MockRequestSender, testPath, testBody string) *mocks.MockRequestSender {
   128  	loginURLParts := strings.Split(loginPath, "?")
   129  	loginURIPath := loginURLParts[0]
   130  	httpMock.EXPECT().
   131  		Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(tokensPath+testToken)).
   132  		DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) {
   133  			var resp *http.Response
   134  			r := io.NopCloser(bytes.NewReader([]byte(testBody)))
   135  			resp = &http.Response{
   136  				StatusCode: http.StatusOK,
   137  				Body:       r,
   138  			}
   139  			return resp, nil
   140  		})
   141  	httpMock.EXPECT().
   142  		Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(tokensPath)).
   143  		DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) {
   144  			var resp *http.Response
   145  			r := io.NopCloser(bytes.NewReader([]byte(testBody)))
   146  			resp = &http.Response{
   147  				StatusCode: http.StatusCreated,
   148  				Body:       r,
   149  			}
   150  			return resp, nil
   151  		}).Times(1)
   152  	httpMock.EXPECT().
   153  		Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(testPath)).
   154  		DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) {
   155  			var resp *http.Response
   156  			r := io.NopCloser(bytes.NewReader([]byte(testBody)))
   157  			resp = &http.Response{
   158  				StatusCode: http.StatusOK,
   159  				Body:       r,
   160  			}
   161  			return resp, nil
   162  		}).Times(2)
   163  	httpMock.EXPECT().
   164  		Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(loginURIPath)).
   165  		DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) {
   166  			r := io.NopCloser(bytes.NewReader([]byte(`{"token":"unit-test-token"}`)))
   167  			resp := &http.Response{
   168  				StatusCode: http.StatusCreated,
   169  				Body:       r,
   170  				Request:    &http.Request{Method: http.MethodPost},
   171  			}
   172  			return resp, nil
   173  		}).Times(2)
   174  	return httpMock
   175  }
   176  func TestGetTokenWithFilter(t *testing.T) {
   177  	clusterIDForTest := "clusteridfortest"
   178  	DeleteStoredTokens()
   179  	cli := createTestObjects()
   180  	log := vzlog.DefaultLogger()
   181  	loginURLParts := strings.Split(loginPath, "?")
   182  	loginURIPath := loginURLParts[0]
   183  	testBodyForTokens, _ := os.Open("testdata/bodyfortokentest.json")
   184  	arrayBytes, _ := io.ReadAll(testBodyForTokens)
   185  	savedRancherHTTPClient := RancherHTTPClient
   186  	defer func() {
   187  		RancherHTTPClient = savedRancherHTTPClient
   188  	}()
   189  
   190  	savedRetry := DefaultRetry
   191  	defer func() {
   192  		DefaultRetry = savedRetry
   193  	}()
   194  
   195  	DefaultRetry = wait.Backoff{
   196  		Steps:    1,
   197  		Duration: 1 * time.Millisecond,
   198  		Factor:   1.0,
   199  		Jitter:   0.1,
   200  	}
   201  
   202  	mocker := gomock.NewController(t)
   203  	httpMock := mocks.NewMockRequestSender(mocker)
   204  	httpMock.EXPECT().
   205  		Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(loginURIPath)).
   206  		DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) {
   207  			r := io.NopCloser(bytes.NewReader([]byte(`{"token":"unit-test-token"}`)))
   208  			resp := &http.Response{
   209  				StatusCode: http.StatusCreated,
   210  				Body:       r,
   211  				Request:    &http.Request{Method: http.MethodPost},
   212  			}
   213  			return resp, nil
   214  		}).Times(1)
   215  	httpMock.EXPECT().
   216  		Do(gomock.Not(gomock.Nil()), mockmatchers.MatchesURI(tokensPath)).
   217  		DoAndReturn(func(httpClient *http.Client, req *http.Request) (*http.Response, error) {
   218  			var resp *http.Response
   219  			r := io.NopCloser(bytes.NewReader([]byte(arrayBytes)))
   220  			resp = &http.Response{
   221  				StatusCode: http.StatusOK,
   222  				Body:       r,
   223  			}
   224  			return resp, nil
   225  		}).Times(1)
   226  	RancherHTTPClient = httpMock
   227  	rc, err := NewAdminRancherConfig(cli, DefaultRancherIngressHostPrefix+nginxutil.IngressNGINXNamespace(), log)
   228  	assert.NoError(t, err)
   229  	createdTimeAsString, _, err := GetTokenWithFilter(rc, log, userID, clusterIDForTest)
   230  	assert.NoError(t, err)
   231  	assert.Equal(t, createdTimeAsString, "2023-07-13T19:32:38Z")
   232  }