...

Source file src/edge-infra.dev/pkg/sds/interlock/topic/instances/instances_int_test.go

Documentation: edge-infra.dev/pkg/sds/interlock/topic/instances

     1  package instances_test
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/gin-gonic/gin"
    13  	"github.com/go-logr/logr/testr"
    14  	"github.com/spf13/afero"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  	corev1 "k8s.io/api/core/v1"
    18  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    19  	kruntime "k8s.io/apimachinery/pkg/runtime"
    20  	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
    21  	clientgoscheme "k8s.io/client-go/kubernetes/scheme"
    22  	ctrl "sigs.k8s.io/controller-runtime"
    23  	"sigs.k8s.io/controller-runtime/pkg/cache/informertest"
    24  	"sigs.k8s.io/controller-runtime/pkg/client"
    25  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    26  
    27  	"edge-infra.dev/pkg/sds/interlock/internal/config"
    28  	"edge-infra.dev/pkg/sds/interlock/topic/instances"
    29  	"edge-infra.dev/pkg/sds/interlock/websocket"
    30  	"edge-infra.dev/pkg/sds/lib/k8s/retryclient"
    31  )
    32  
    33  func init() {
    34  	gin.SetMode(gin.TestMode)
    35  	// required to prevent errors around getting InCluster configuration for k8s
    36  	// client
    37  	os.Setenv("KUBERNETES_SERVICE_HOST", "1")
    38  	os.Setenv("KUBERNETES_SERVICE_PORT", "1")
    39  }
    40  
    41  func SetupTestCtx(t *testing.T) context.Context {
    42  	logOptions := testr.Options{
    43  		LogTimestamp: true,
    44  		Verbosity:    -1,
    45  	}
    46  
    47  	ctx := ctrl.LoggerInto(context.Background(), testr.NewWithOptions(t, logOptions))
    48  	return ctx
    49  }
    50  
    51  // CreateScheme creates a new scheme, adds all types of the automatically generated
    52  // clientset, and returns it.
    53  func CreateScheme() *kruntime.Scheme {
    54  	scheme := kruntime.NewScheme()
    55  	utilruntime.Must(clientgoscheme.AddToScheme(scheme))
    56  	return scheme
    57  }
    58  
    59  // GetFakeKubeClient returns a fake client initialised with a slice of
    60  // Kubernets objects. To be used for testing purposes.
    61  func GetFakeKubeClient(initObjs ...client.Object) client.Client {
    62  	return fake.NewClientBuilder().WithScheme(CreateScheme()).WithObjects(initObjs...).Build()
    63  }
    64  
    65  // GetTestHostNode returns a Node object initialised with name and uid fields
    66  // To be used for testing purposes.
    67  func GetTestPod(name, nodeName, ip string) *corev1.Pod {
    68  	return &corev1.Pod{
    69  		ObjectMeta: metav1.ObjectMeta{
    70  			Name:      name,
    71  			Namespace: "interlock",
    72  		},
    73  		Spec: corev1.PodSpec{
    74  			NodeName: nodeName,
    75  		},
    76  		Status: corev1.PodStatus{
    77  			PodIP: ip,
    78  		},
    79  	}
    80  }
    81  
    82  // setupTestInstancesTopic returns an initialised instances topic
    83  func setupTestInstancesTopic(t *testing.T) (*instances.Instances, error) {
    84  	pod1 := GetTestPod("interlock-11111", "node1", "1.1.1.1")
    85  	pod2 := GetTestPod("interlock-22222", "node2", "2.2.2.2")
    86  	cli := GetFakeKubeClient(pod1, pod2)
    87  	cfg := &config.Config{
    88  		Fs:              afero.NewMemMapFs(),
    89  		KubeRetryClient: retryclient.New(cli, cli, retryclient.Config{}),
    90  		Cache:           &informertest.FakeInformers{},
    91  	}
    92  
    93  	wm := websocket.NewManager()
    94  
    95  	return instances.New(SetupTestCtx(t), cfg, wm)
    96  }
    97  
    98  func TestGetState(t *testing.T) {
    99  	h, err := setupTestInstancesTopic(t)
   100  	require.NoError(t, err)
   101  
   102  	r := gin.Default()
   103  	h.RegisterEndpoints(r)
   104  
   105  	w := httptest.NewRecorder()
   106  	req, err := http.NewRequest(http.MethodGet, instances.Path, nil)
   107  	require.NoError(t, err)
   108  	r.ServeHTTP(w, req)
   109  
   110  	assert.Equal(t, http.StatusOK, w.Code)
   111  
   112  	actual := &instances.State{}
   113  	require.NoError(t, json.Unmarshal(w.Body.Bytes(), actual))
   114  
   115  	expected := &instances.State{
   116  		Instances: map[string]instances.Instance{
   117  			"node1": {URL: "http://1.1.1.1:80"},
   118  			"node2": {URL: "http://2.2.2.2:80"},
   119  		},
   120  	}
   121  	assert.Equal(t, expected, actual)
   122  }
   123  
   124  func TestGetURL(t *testing.T) {
   125  	h, err := setupTestInstancesTopic(t)
   126  	require.NoError(t, err)
   127  
   128  	r := gin.Default()
   129  	h.RegisterEndpoints(r)
   130  
   131  	path := strings.Join([]string{instances.Path, "node1"}, "/")
   132  
   133  	w := httptest.NewRecorder()
   134  	req, err := http.NewRequest(http.MethodGet, path, nil)
   135  	require.NoError(t, err)
   136  	r.ServeHTTP(w, req)
   137  
   138  	assert.Equal(t, http.StatusOK, w.Code)
   139  
   140  	actual := &instances.Instance{}
   141  	require.NoError(t, json.Unmarshal(w.Body.Bytes(), actual))
   142  
   143  	expected := &instances.Instance{
   144  		URL: "http://1.1.1.1:80",
   145  	}
   146  	assert.Equal(t, expected, actual)
   147  }
   148  

View as plain text