github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/edp/client_test.go (about)

     1  package edp
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"net/http"
     7  	"net/http/httptest"
     8  	"testing"
     9  
    10  	"github.com/kyma-project/kyma-environment-broker/internal/logger"
    11  
    12  	"github.com/gorilla/mux"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  const (
    17  	subAccountID  = "72b83910-c2dc-415b-b95d-960cc45b36abx"
    18  	environment   = "test"
    19  	testNamespace = "testNs"
    20  )
    21  
    22  func TestClient_CreateDataTenant(t *testing.T) {
    23  	// given
    24  	testServer := fixHTTPServer(t)
    25  	defer testServer.Close()
    26  
    27  	config := Config{
    28  		AdminURL:  testServer.URL,
    29  		Namespace: testNamespace,
    30  	}
    31  	client := NewClient(config, logger.NewLogDummy())
    32  	client.setHttpClient(testServer.Client())
    33  
    34  	// when
    35  	err := client.CreateDataTenant(DataTenantPayload{
    36  		Name:        subAccountID,
    37  		Environment: environment,
    38  	})
    39  
    40  	// then
    41  	assert.NoError(t, err)
    42  
    43  	response, err := testServer.Client().Get(fmt.Sprintf("%s/namespaces/%s/dataTenants/%s/%s", testServer.URL, testNamespace, subAccountID, environment))
    44  	assert.NoError(t, err)
    45  
    46  	var dt DataTenantItem
    47  	err = json.NewDecoder(response.Body).Decode(&dt)
    48  	assert.NoError(t, err)
    49  	assert.Equal(t, subAccountID, dt.Name)
    50  	assert.Equal(t, environment, dt.Environment)
    51  	assert.Equal(t, testNamespace, dt.Namespace.Name)
    52  }
    53  
    54  func TestClient_DeleteDataTenant(t *testing.T) {
    55  	// given
    56  	testServer := fixHTTPServer(t)
    57  	defer testServer.Close()
    58  
    59  	config := Config{
    60  		AdminURL:  testServer.URL,
    61  		Namespace: testNamespace,
    62  	}
    63  	client := NewClient(config, logger.NewLogDummy())
    64  	client.setHttpClient(testServer.Client())
    65  
    66  	err := client.CreateDataTenant(DataTenantPayload{
    67  		Name:        subAccountID,
    68  		Environment: environment,
    69  	})
    70  	assert.NoError(t, err)
    71  
    72  	// when
    73  	err = client.DeleteDataTenant(subAccountID, environment)
    74  
    75  	// then
    76  	assert.NoError(t, err)
    77  
    78  	response, err := testServer.Client().Get(fmt.Sprintf("%s/namespaces/%s/dataTenants/%s/%s", testServer.URL, testNamespace, subAccountID, environment))
    79  	assert.NoError(t, err)
    80  	assert.Equal(t, http.StatusNotFound, response.StatusCode)
    81  }
    82  
    83  func TestClient_CreateMetadataTenant(t *testing.T) {
    84  	// given
    85  	testServer := fixHTTPServer(t)
    86  	defer testServer.Close()
    87  
    88  	config := Config{
    89  		AdminURL:  testServer.URL,
    90  		Namespace: testNamespace,
    91  	}
    92  	client := NewClient(config, logger.NewLogDummy())
    93  	client.setHttpClient(testServer.Client())
    94  
    95  	// when
    96  	err := client.CreateMetadataTenant(subAccountID, environment, MetadataTenantPayload{Key: "tK", Value: "tV"})
    97  	assert.NoError(t, err)
    98  
    99  	err = client.CreateMetadataTenant(subAccountID, environment, MetadataTenantPayload{Key: "tK2", Value: "tV2"})
   100  	assert.NoError(t, err)
   101  
   102  	// then
   103  	assert.NoError(t, err)
   104  
   105  	data, err := client.GetMetadataTenant(subAccountID, environment)
   106  	assert.NoError(t, err)
   107  	assert.Len(t, data, 2)
   108  }
   109  
   110  func TestClient_DeleteMetadataTenant(t *testing.T) {
   111  	// given
   112  	key := "tK"
   113  	testServer := fixHTTPServer(t)
   114  	defer testServer.Close()
   115  
   116  	config := Config{
   117  		AdminURL:  testServer.URL,
   118  		Namespace: testNamespace,
   119  	}
   120  	client := NewClient(config, logger.NewLogDummy())
   121  	client.setHttpClient(testServer.Client())
   122  
   123  	err := client.CreateMetadataTenant(subAccountID, environment, MetadataTenantPayload{Key: key, Value: "tV"})
   124  	assert.NoError(t, err)
   125  
   126  	// when
   127  	err = client.DeleteMetadataTenant(subAccountID, environment, key)
   128  
   129  	// then
   130  	assert.NoError(t, err)
   131  
   132  	data, err := client.GetMetadataTenant(subAccountID, environment)
   133  	assert.NoError(t, err)
   134  	assert.Len(t, data, 0)
   135  }
   136  
   137  func fixHTTPServer(t *testing.T) *httptest.Server {
   138  	r := mux.NewRouter()
   139  	srv := newServer(t)
   140  
   141  	r.HandleFunc("/namespaces/{namespace}/dataTenants", srv.createDataTenant).Methods(http.MethodPost)
   142  	r.HandleFunc("/namespaces/{namespace}/dataTenants/{name}/{env}", srv.deleteDataTenant).Methods(http.MethodDelete)
   143  
   144  	r.HandleFunc("/namespaces/{namespace}/dataTenants/{name}/{env}/metadata", srv.createMetadata).Methods(http.MethodPost)
   145  	r.HandleFunc("/namespaces/{namespace}/dataTenants/{name}/{env}/metadata", srv.getMetadata).Methods(http.MethodGet)
   146  	r.HandleFunc("/namespaces/{namespace}/dataTenants/{name}/{env}/metadata/{key}", srv.deleteMetadata).Methods(http.MethodDelete)
   147  
   148  	// enpoints use only for test (exist in real EDP)
   149  	r.HandleFunc("/namespaces/{namespace}/dataTenants/{name}/{env}", srv.getDataTenants).Methods(http.MethodGet)
   150  
   151  	return httptest.NewServer(r)
   152  }
   153  
   154  type server struct {
   155  	t          *testing.T
   156  	metadata   []MetadataItem
   157  	dataTenant map[string][]byte
   158  }
   159  
   160  func newServer(t *testing.T) *server {
   161  	return &server{
   162  		t:          t,
   163  		metadata:   make([]MetadataItem, 0),
   164  		dataTenant: make(map[string][]byte, 0),
   165  	}
   166  }
   167  
   168  func (s *server) checkNamespace(w http.ResponseWriter, r *http.Request) (string, bool) {
   169  	namespace, ok := mux.Vars(r)["namespace"]
   170  	if !ok {
   171  		s.t.Error("key namespace doesn't exist")
   172  		w.WriteHeader(http.StatusMethodNotAllowed)
   173  		return "", false
   174  	}
   175  	if namespace != testNamespace {
   176  		s.t.Errorf("key namespace is not equal to %s", testNamespace)
   177  		w.WriteHeader(http.StatusNotFound)
   178  		return namespace, false
   179  	}
   180  
   181  	return namespace, true
   182  }
   183  
   184  func (s *server) fetchNameAndEnv(w http.ResponseWriter, r *http.Request) (string, string, bool) {
   185  	vars := mux.Vars(r)
   186  	name, okName := vars["name"]
   187  	env, okEnv := vars["env"]
   188  
   189  	if !okName || !okEnv {
   190  		s.t.Error("one of the required key doesn't exist")
   191  		w.WriteHeader(http.StatusMethodNotAllowed)
   192  		return "", "", false
   193  	}
   194  
   195  	return name, env, true
   196  }
   197  
   198  func (s *server) createDataTenant(w http.ResponseWriter, r *http.Request) {
   199  	ns, ok := s.checkNamespace(w, r)
   200  	if !ok {
   201  		return
   202  	}
   203  
   204  	var dt DataTenantPayload
   205  	err := json.NewDecoder(r.Body).Decode(&dt)
   206  	if err != nil {
   207  		s.t.Errorf("cannot read request body")
   208  		w.WriteHeader(http.StatusBadRequest)
   209  		return
   210  	}
   211  
   212  	dti := DataTenantItem{
   213  		Namespace: NamespaceItem{
   214  			Name: ns,
   215  		},
   216  		Name:        dt.Name,
   217  		Environment: dt.Environment,
   218  	}
   219  
   220  	data, err := json.Marshal(dti)
   221  	if err != nil {
   222  		s.t.Errorf("wrong request body")
   223  		w.WriteHeader(http.StatusBadRequest)
   224  		return
   225  	}
   226  
   227  	s.dataTenant[dt.Name] = data
   228  	w.WriteHeader(http.StatusCreated)
   229  }
   230  
   231  func (s *server) deleteDataTenant(w http.ResponseWriter, r *http.Request) {
   232  	if _, ok := s.checkNamespace(w, r); !ok {
   233  		return
   234  	}
   235  	name, _, ok := s.fetchNameAndEnv(w, r)
   236  	if !ok {
   237  		return
   238  	}
   239  
   240  	for dtName, _ := range s.dataTenant {
   241  		if dtName == name {
   242  			delete(s.dataTenant, dtName)
   243  			w.WriteHeader(http.StatusNoContent)
   244  			return
   245  		}
   246  	}
   247  
   248  	// EDP server return 204 if dataTenant not exist already
   249  	w.WriteHeader(http.StatusNoContent)
   250  }
   251  
   252  func (s *server) createMetadata(w http.ResponseWriter, r *http.Request) {
   253  	if _, ok := s.checkNamespace(w, r); !ok {
   254  		return
   255  	}
   256  	name, env, ok := s.fetchNameAndEnv(w, r)
   257  	if !ok {
   258  		return
   259  	}
   260  
   261  	var item MetadataItem
   262  	err := json.NewDecoder(r.Body).Decode(&item)
   263  	item.DataTenant = DataTenantItem{
   264  		Namespace: NamespaceItem{
   265  			Name: testNamespace,
   266  		},
   267  		Name:        name,
   268  		Environment: env,
   269  	}
   270  	if err != nil {
   271  		s.t.Errorf("cannot decode request body")
   272  		w.WriteHeader(http.StatusBadRequest)
   273  		return
   274  	}
   275  
   276  	s.metadata = append(s.metadata, item)
   277  	w.WriteHeader(http.StatusCreated)
   278  }
   279  
   280  func (s *server) deleteMetadata(w http.ResponseWriter, r *http.Request) {
   281  	if _, ok := s.checkNamespace(w, r); !ok {
   282  		return
   283  	}
   284  
   285  	vars := mux.Vars(r)
   286  	key, ok := vars["key"]
   287  	if !ok {
   288  		s.t.Error("key doesn't exist")
   289  		w.WriteHeader(http.StatusNotFound)
   290  		return
   291  	}
   292  
   293  	newData := make([]MetadataItem, 0)
   294  	for _, item := range s.metadata {
   295  		if item.Key == key {
   296  			continue
   297  		}
   298  		newData = append(newData, item)
   299  	}
   300  
   301  	s.metadata = newData
   302  	w.WriteHeader(http.StatusNoContent)
   303  }
   304  
   305  func (s *server) getMetadata(w http.ResponseWriter, r *http.Request) {
   306  	err := json.NewEncoder(w).Encode(s.metadata)
   307  	if err != nil {
   308  		s.t.Errorf("%s", err)
   309  		w.WriteHeader(http.StatusInternalServerError)
   310  		return
   311  	}
   312  
   313  	w.WriteHeader(http.StatusOK)
   314  }
   315  
   316  func (s *server) getDataTenants(w http.ResponseWriter, r *http.Request) {
   317  	if _, ok := s.checkNamespace(w, r); !ok {
   318  		return
   319  	}
   320  	name, _, ok := s.fetchNameAndEnv(w, r)
   321  	if !ok {
   322  		s.t.Error("cannot find name/env query parameters")
   323  		w.WriteHeader(http.StatusNotFound)
   324  		return
   325  	}
   326  
   327  	if _, ok := s.dataTenant[name]; !ok {
   328  		s.t.Logf("dataTenant with name %s not exist", name)
   329  		w.WriteHeader(http.StatusNotFound)
   330  		return
   331  	}
   332  
   333  	_, err := w.Write(s.dataTenant[name])
   334  	if err != nil {
   335  		w.WriteHeader(http.StatusInternalServerError)
   336  		return
   337  	}
   338  
   339  	w.WriteHeader(http.StatusOK)
   340  }
   341  
   342  // setHttpClient auxiliary method of testing to get rid of oAuth client wrapper
   343  func (c *Client) setHttpClient(httpClient *http.Client) {
   344  	c.httpClient = httpClient
   345  }