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 }