Skip to content

Commit

Permalink
Service Manager client ServiceOfferings test (#703)
Browse files Browse the repository at this point in the history
Add unit test for Service Manager client and ServiceOfferings endpoint
  • Loading branch information
szwedm authored May 17, 2024
1 parent 0e8db25 commit 20b4f47
Show file tree
Hide file tree
Showing 3 changed files with 285 additions and 0 deletions.
4 changes: 4 additions & 0 deletions internal/service-manager/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ func (c *Client) SetHTTPClient(httpClient *http.Client) {
c.httpClient = httpClient
}

func (c *Client) SetSMURL(smURL string) {
c.smURL = smURL
}

func (c *Client) ServiceOfferings() (*types.ServiceOfferings, error) {
req, err := http.NewRequest(http.MethodGet, c.smURL+ServiceOfferingsPath, nil)
if err != nil {
Expand Down
170 changes: 170 additions & 0 deletions internal/service-manager/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
package servicemanager_test

import (
"context"
"encoding/json"
"fmt"
"log"
"log/slog"
"net/http"
"net/http/httptest"
"os"
"testing"

servicemanager "github.com/kyma-project/btp-manager/internal/service-manager"
"github.com/kyma-project/btp-manager/internal/service-manager/types"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
serviceOfferingsJSONPath = "testdata/service_offerings.json"
)

func TestClient(t *testing.T) {
// given
secretProvider := newFakeSecretProvider()
srv, err := initFakeServer()
require.NoError(t, err)

srv.Start()
defer srv.Close()
httpClient := srv.Client()
url := srv.URL

t.Run("should get service offerings available for the default credentials", func(t *testing.T) {
// given
ctx := context.TODO()
secretProvider.AddSecret(defaultSecret())
smClient := servicemanager.NewClient(ctx, slog.Default(), secretProvider)

var expectedServiceOfferings types.ServiceOfferings
soJSON, err := getResourcesFromJSONFile(serviceOfferingsJSONPath)
require.NoError(t, err)

soBytes, err := json.Marshal(soJSON)
require.NoError(t, err)

err = json.Unmarshal(soBytes, &expectedServiceOfferings)
require.NoError(t, err)

// when
err = smClient.Defaults(ctx)

// then
require.NoError(t, err)

// given
smClient.SetHTTPClient(httpClient)
smClient.SetSMURL(url)

// when
so, err := smClient.ServiceOfferings()

// then
require.NoError(t, err)
assert.Len(t, so.ServiceOfferings, 4)
assert.ElementsMatch(t, expectedServiceOfferings.ServiceOfferings, so.ServiceOfferings)
})
}

func initFakeServer() (*httptest.Server, error) {
smHandler, err := newFakeSMHandler()
if err != nil {
return nil, fmt.Errorf("while creating new fake SM handler: %w", err)
}

mux := http.NewServeMux()
mux.HandleFunc("GET /v1/service_offerings", smHandler.getServiceOfferings)

srv := httptest.NewUnstartedServer(mux)

return srv, nil
}

type fakeSMHandler struct {
serviceOfferings map[string]interface{}
}

func newFakeSMHandler() (*fakeSMHandler, error) {
so, err := getResourcesFromJSONFile(serviceOfferingsJSONPath)
if err != nil {
return nil, fmt.Errorf("while getting service offerings from JSON file: %w", err)
}

return &fakeSMHandler{serviceOfferings: so}, nil
}

func getResourcesFromJSONFile(jsonFilePath string) (map[string]interface{}, error) {
var buf map[string]interface{}
f, err := os.Open(jsonFilePath)
defer f.Close()
if err != nil {
return nil, fmt.Errorf("while reading resources from JSON file: %w", err)
}

d := json.NewDecoder(f)
if err := d.Decode(&buf); err != nil {
return nil, fmt.Errorf("while decoding resources JSON: %w", err)
}
return buf, nil
}

func (h *fakeSMHandler) getServiceOfferings(w http.ResponseWriter, r *http.Request) {
data, err := json.Marshal(h.serviceOfferings)
if err != nil {
log.Println("error while marshalling service offerings data: %w", err)
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(http.StatusOK)
if _, err = w.Write(data); err != nil {
w.WriteHeader(http.StatusBadRequest)
log.Println("error while writing service offerings data: %w", err)
return
}
}

type fakeSecretProvider struct {
secrets []*corev1.Secret
}

func newFakeSecretProvider() *fakeSecretProvider {
return &fakeSecretProvider{secrets: make([]*corev1.Secret, 0)}
}

func (p *fakeSecretProvider) AddSecret(secret *corev1.Secret) {
p.secrets = append(p.secrets, secret)
}

func (p *fakeSecretProvider) GetByNameAndNamespace(ctx context.Context, name, namespace string) (*corev1.Secret, error) {
for _, secret := range p.secrets {
if secret.Name == name && secret.Namespace == namespace {
return secret, nil
}
}
return nil, fmt.Errorf("secret not found")
}

func (p *fakeSecretProvider) clean() {
p.secrets = make([]*corev1.Secret, 0)
}

func defaultSecret() *corev1.Secret {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: "sap-btp-service-operator",
Namespace: "kyma-system",
},
StringData: map[string]string{
"clientid": "default-client-id",
"clientsecret": "default-client-secret",
"sm_url": "https://default-sm-url.local",
"tokenurl": "https://default-token-url.local",
"tokenurlsuffix": "/oauth/token",
},
}
}
111 changes: 111 additions & 0 deletions internal/service-manager/testdata/service_offerings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
{
"num_items": 4,
"items": [
{
"id": "fc26622b-aeb2-4f3c-95da-8eb337a26883",
"ready": true,
"name": "service1",
"description": "Service 1 description",
"bindable": true,
"instances_retrievable": false,
"bindings_retrievable": false,
"plan_updateable": false,
"allow_context_updates": false,
"metadata": {
"createBindingDocumentationUrl": "https://service1-test.local/create-binding.html",
"discoveryCenterUrl": "https://discovery-center.local/serviceCatalog/service1",
"displayName": "Service 1",
"documentationUrl": "https://service1-test.local/documentation.html",
"imageUrl": "data:image/svg+xml;base64,c2VydmljZTEK",
"longDescription": "Service 1 long description",
"serviceInventoryId": "SERVICE-1",
"shareable": true,
"supportUrl": "https://service1-test.local/support.html"
},
"broker_id": "9352e325-d62b-4cc9-bf73-b2db77a343aa",
"catalog_id": "a5b7679a-36e6-4c85-8f4f-ab7a1ab1ac16",
"catalog_name": "service1",
"created_at": "2024-01-11T01:01:00",
"updated_at": "2024-01-12T02:02:00"
},
{
"id": "1d87e6e3-12b4-4a04-82bb-ddf7299d52c9",
"ready": true,
"name": "service2",
"description": "Service 2 description",
"bindable": true,
"instances_retrievable": false,
"bindings_retrievable": false,
"plan_updateable": true,
"allow_context_updates": false,
"tags": [
"service",
"two"
],
"metadata": {
"shareable": false,
"displayName": "Service 2"
},
"broker_id": "c208c628-4600-4bfc-b92c-dc1e2bd8632b",
"catalog_id": "fb4035a9-75ec-4049-9b5f-b9f19af48e9a",
"catalog_name": "service2",
"created_at": "2024-02-11T02:02:00",
"updated_at": "2024-02-12T03:03:00"
},
{
"id": "7df0a7a5-3bda-4af4-9fdf-763ad4c01bb7",
"ready": true,
"name": "service3",
"description": "Service 3 description",
"bindable": true,
"instances_retrievable": true,
"bindings_retrievable": false,
"plan_updateable": false,
"allow_context_updates": false,
"tags": [
"service-three"
],
"metadata": {
"documentationUrl": "https://service3-test.local/documentation.html",
"serviceInventoryId": "SERVICE-3",
"displayName": "Service 3",
"imageUrl": "data:image/png;base64,c2VydmljZTMK"
},
"broker_id": "f5ccc8b2-9723-4ae9-834a-46c00d177df7",
"catalog_id": "service3-service-broker",
"catalog_name": "service3",
"created_at": "2024-03-11T03:03:00",
"updated_at": "2024-03-12T04:04:00"
},
{
"id": "69e313ac-6633-4fa9-a9d5-8aaf569bc966",
"ready": true,
"name": "service4",
"description": "Service 4 description",
"bindable": true,
"instances_retrievable": false,
"bindings_retrievable": false,
"plan_updateable": false,
"allow_context_updates": false,
"tags": [
"service",
"four",
"foursvc"
],
"metadata": {
"longDescription": "Service 4 long description",
"documentationUrl": "https://service4-test.local/documentation.html",
"providerDisplayName": "GREAT COMPANY",
"serviceInventoryId": "SERVICE-4",
"displayName": "Service 4",
"imageUrl": "data:image/svg+xml;base64,c2VydmljZTQK",
"supportUrl": "https://service4-test.local/support.html"
},
"broker_id": "c94651ef-9997-485c-aa65-5ef5ed64e619",
"catalog_id": "1277f478-9670-4d62-a068-039329ff086b",
"catalog_name": "service4",
"created_at": "2024-04-11T04:04:00",
"updated_at": "2024-04-12T05:05:00"
}
]
}

0 comments on commit 20b4f47

Please sign in to comment.