Skip to content

Commit

Permalink
Handle Service Bindings in SM client and get Service Instances in API (
Browse files Browse the repository at this point in the history
…#735)

* wip

* wip

* wip

* Rebase and sort imports

* wip

* Fix fetching structs fields

* Fix ServiceBinding struct

* GET Service Instances in API

* CRUD Service Bindings

* GET Service Plan by ID in SM client

* GET Service Instance by ID in API

* Revert temp changes

---------

Co-authored-by: Marcin Szwed <[email protected]>
Co-authored-by: Ksawery Zietara <[email protected]>
  • Loading branch information
3 people committed Aug 21, 2024
1 parent 1578c07 commit 6cec48e
Show file tree
Hide file tree
Showing 14 changed files with 849 additions and 31 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ go 1.22.5

require (
github.com/go-logr/logr v1.4.2
github.com/google/uuid v1.6.0
github.com/onsi/ginkgo/v2 v2.20.0
github.com/onsi/gomega v1.34.1
github.com/prometheus/client_golang v1.20.1
Expand Down Expand Up @@ -40,7 +41,6 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20240727154555-813a5fbdbec8 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
Expand Down
12 changes: 10 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
Expand Down Expand Up @@ -58,6 +59,8 @@ github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
Expand All @@ -71,6 +74,7 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo/v2 v2.20.0 h1:PE84V2mHqoT1sglvHc8ZdQtPcwmvvt29WLEEO3xmdZw=
github.com/onsi/ginkgo/v2 v2.20.0/go.mod h1:lG9ey2Z29hR41WMVthyJBGUBcBhGOtoPF2VFMvBXFCI=
github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k=
Expand All @@ -94,12 +98,13 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/vrischmann/envconfig v1.3.0 h1:4XIvQTXznxmWMnjouj0ST5lFo/WAYf5Exgl3x82crEk=
github.com/vrischmann/envconfig v1.3.0/go.mod h1:bbvxFYJdRSpXrhS63mBFtKJzkDiNkyArOLXtY6q0kuI=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
Expand Down Expand Up @@ -154,6 +159,7 @@ gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuB
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4=
Expand All @@ -163,6 +169,8 @@ gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.31.0 h1:b9LiSjR2ym/SzTOlfMHm1tr7/21aD7fSkqgD/CVJBCo=
Expand Down
70 changes: 58 additions & 12 deletions internal/api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ import (
"strings"
"time"

"github.com/kyma-project/btp-manager/internal/api/vm"
"github.com/kyma-project/btp-manager/internal/service-manager/types"

"github.com/kyma-project/btp-manager/internal/api/responses"

clusterobject "github.com/kyma-project/btp-manager/internal/cluster-object"
servicemanager "github.com/kyma-project/btp-manager/internal/service-manager"
)
Expand All @@ -24,7 +27,7 @@ type Config struct {

type API struct {
server *http.Server
serviceManager *servicemanager.Client
smClient *servicemanager.Client
secretProvider *clusterobject.SecretProvider
frontendFS http.FileSystem
logger *slog.Logger
Expand All @@ -39,7 +42,7 @@ func NewAPI(cfg Config, serviceManager *servicemanager.Client, secretProvider *c
}
return &API{
server: srv,
serviceManager: serviceManager,
smClient: serviceManager,
secretProvider: secretProvider,
frontendFS: fs,
logger: slog.Default()}
Expand All @@ -53,40 +56,42 @@ func (a *API) Start() {
mux.HandleFunc("GET /api/service-instance/{id}", a.GetServiceInstance)
mux.HandleFunc("GET /api/service-offerings/{namespace}/{name}", a.ListServiceOfferings)
mux.HandleFunc("GET /api/service-offering/{id}", a.GetServiceOffering)
mux.HandleFunc("POST /api/service-bindings", a.CreateServiceBindings)
mux.HandleFunc("GET /api/service-binding/{id}", a.GetServiceBinding)
mux.Handle("GET /", http.FileServer(a.frontendFS))
a.server.Handler = mux

log.Fatal(a.server.ListenAndServe())
}

func (a *API) CreateServiceInstance(writer http.ResponseWriter, request *http.Request) {
return
a.setupCors(writer, request)
}

func (a *API) GetServiceOffering(writer http.ResponseWriter, request *http.Request) {
a.setupCors(writer, request)
id := request.PathValue("id")
details, err := a.serviceManager.ServiceOfferingDetails(id)
details, err := a.smClient.ServiceOfferingDetails(id)
if returnError(writer, err) {
return
}
response, err := json.Marshal(vm.ToServiceOfferingDetailsVM(details))
response, err := json.Marshal(responses.ToServiceOfferingDetailsVM(details))
returnResponse(writer, response, err)
}

func (a *API) ListServiceOfferings(writer http.ResponseWriter, request *http.Request) {
a.setupCors(writer, request)
namespace := request.PathValue("namespace")
name := request.PathValue("name")
err := a.serviceManager.SetForGivenSecret(context.Background(), name, namespace)
err := a.smClient.SetForGivenSecret(context.Background(), name, namespace)
if returnError(writer, err) {
return
}
offerings, err := a.serviceManager.ServiceOfferings()
offerings, err := a.smClient.ServiceOfferings()
if returnError(writer, err) {
return
}
response, err := json.Marshal(vm.ToServiceOfferingsVM(offerings))
response, err := json.Marshal(responses.ToServiceOfferingsVM(offerings))
returnResponse(writer, response, err)
}

Expand All @@ -96,21 +101,62 @@ func (a *API) ListSecrets(writer http.ResponseWriter, request *http.Request) {
if returnError(writer, err) {
return
}
response, err := json.Marshal(vm.ToSecretVM(*secrets))
response, err := json.Marshal(responses.ToSecretVM(*secrets))
returnResponse(writer, response, err)
}

func (a *API) GetServiceInstance(writer http.ResponseWriter, request *http.Request) {
a.setupCors(writer, request)
// not implemented in SM
id := request.PathValue("id")
si, err := a.smClient.ServiceInstance(id)
if returnError(writer, err) {
return
}
plan, err := a.smClient.ServicePlan(si.ServicePlanID)
if returnError(writer, err) {
return
}
response, err := json.Marshal(responses.ToServiceInstanceVM(si, plan))
returnResponse(writer, response, err)
}

func (a *API) ListServiceInstances(writer http.ResponseWriter, request *http.Request) {
a.setupCors(writer, request)
// will be taken from SM
sis, err := a.smClient.ServiceInstances()
if returnError(writer, err) {
return
}
response, err := json.Marshal(responses.ToServiceInstancesVM(sis))
returnResponse(writer, response, err)
}

func (a *API) CreateServiceBindings(writer http.ResponseWriter, request *http.Request) {
a.setupCors(writer, request)
var sb types.ServiceBinding
err := json.NewDecoder(request.Body).Decode(&sb)
if returnError(writer, err) {
return
}
_, err = a.smClient.CreateServiceBinding(&sb)
if returnError(writer, err) {
return
}
returnResponse(writer, []byte{}, err)
}

func (a *API) GetServiceBinding(writer http.ResponseWriter, request *http.Request) {
a.setupCors(writer, request)
id := request.PathValue("id")
details, err := a.smClient.ServiceBinding(id)
if returnError(writer, err) {
return
}
response, err := json.Marshal(responses.ToServiceBindingVM(details))
returnResponse(writer, response, err)
}

func (a *API) setupCors(writer http.ResponseWriter, request *http.Request) {
a.logger.Info(fmt.Sprintf("api call to -> %s as: %s", request.RequestURI, request.Method))
origin := request.Header.Get("Origin")
origin = strings.ReplaceAll(origin, "\r", "")
origin = strings.ReplaceAll(origin, "\n", "")
Expand Down
18 changes: 18 additions & 0 deletions internal/api/requests/converters.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package requests

import (
"github.com/kyma-project/btp-manager/internal/service-manager/types/requests"
)

func CreateServiceBindingVM(request CreateServiceBinding) requests.CreateServiceBindingRequestPayload {
payload := requests.CreateServiceBindingRequestPayload{
Name: request.Name,
ServiceInstanceID: request.ServiceInstanceId,
Parameters: []byte(request.Parameters),
Labels: map[string][]string{},
}
payload.Labels["_clusterid"] = append(payload.Labels["_clusterid"], payload.Name)
payload.Labels["_namespace"] = append(payload.Labels["_namespace"], request.Namespace)
payload.Labels["_k8sname"] = append(payload.Labels["_k8sname"], request.Name)
return payload
}
8 changes: 8 additions & 0 deletions internal/api/requests/requests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package requests

type CreateServiceBinding struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
ServiceInstanceId string `json:"serviceInstanceId"`
Parameters string `json:"parameters"`
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vm
package responses

import (
"github.com/kyma-project/btp-manager/internal/service-manager/types"
Expand Down Expand Up @@ -64,3 +64,58 @@ func ToServiceOfferingDetailsVM(details *types.ServiceOfferingDetails) ServiceOf

return toReturn
}

func ToServiceInstancesVM(instances *types.ServiceInstances) ServiceInstances {
toReturn := ServiceInstances{
NumItems: len(instances.Items),
Items: []ServiceInstance{},
}

for _, instance := range instances.Items {
namespace, _ := instance.ContextValueByFieldName(types.ServiceInstanceNamespace)
subaccountID, _ := instance.ContextValueByFieldName(types.ServiceInstanceSubaccountID)
clusterID, _ := instance.ContextValueByFieldName(types.ServiceInstanceClusterID)
instance := ServiceInstance{
ID: instance.ID,
Name: instance.Name,
Namespace: namespace,
SubaccountID: subaccountID,
ClusterID: clusterID,
}
toReturn.Items = append(toReturn.Items, instance)
}
return toReturn
}

func ToServiceInstanceVM(instance *types.ServiceInstance, plan *types.ServicePlan) ServiceInstance {
namespace, _ := instance.ContextValueByFieldName(types.ServiceInstanceNamespace)
subaccountID, _ := instance.ContextValueByFieldName(types.ServiceInstanceSubaccountID)
clusterID, _ := instance.ContextValueByFieldName(types.ServiceInstanceClusterID)

return ServiceInstance{
ID: instance.ID,
Name: instance.Name,
Namespace: namespace,
ServicePlanID: instance.ServicePlanID,
ServicePlanName: plan.Name,
SubaccountID: subaccountID,
ClusterID: clusterID,
}
}

func ToServiceBindingsVM(bindings *types.ServiceBindings) ServiceBindings {
toReturn := ServiceBindings{
Items: []ServiceBinding{},
}

for _, _ = range bindings.Items {
n := ServiceBinding{}
toReturn.Items = append(toReturn.Items, n)
}

return toReturn
}

func ToServiceBindingVM(binding *types.ServiceBinding) ServiceBindings {
return ServiceBindings{}
}
23 changes: 19 additions & 4 deletions internal/api/vm/vm.go → internal/api/responses/responses.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package vm
package responses

type Secrets struct {
Items []Secret `json:"items"`
Expand Down Expand Up @@ -30,12 +30,18 @@ type ServiceOfferingMetadata struct {
}

type ServiceInstances struct {
Items []ServiceInstance `json:"items"`
NumItems int `json:"numItems"`
Items []ServiceInstance `json:"items"`
}

type ServiceInstance struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
ID string `json:"id"`
Name string `json:"name"`
Namespace string `json:"namespace"`
ServicePlanID string `json:"servicePlanID"`
ServicePlanName string `json:"servicePlanName"`
SubaccountID string `json:"subaccountID"`
ClusterID string `json:"clusterID"`
}

type ServiceOfferingDetails struct {
Expand All @@ -47,3 +53,12 @@ type ServiceOfferingPlan struct {
Name string `json:"name"`
Description string `json:"description"`
}

type ServiceBinding struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
}

type ServiceBindings struct {
Items []ServiceBinding `json:"items"`
}
20 changes: 20 additions & 0 deletions internal/cluster-object/secret_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import (
"fmt"
"log/slog"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/kyma-project/btp-manager/controllers"
corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
Expand All @@ -19,6 +21,7 @@ const (

type SecretProvider struct {
client.Reader
client.Writer
namespaceProvider *NamespaceProvider
serviceInstanceProvider *ServiceInstanceProvider
logger *slog.Logger
Expand Down Expand Up @@ -158,3 +161,20 @@ func (p *SecretProvider) GetByNameAndNamespace(ctx context.Context, name, namesp

return secret, nil
}

func (p *SecretProvider) CreateSecret(ctx context.Context, name, namespace string) (*corev1.Secret, error) {
p.logger.Info(fmt.Sprintf("creating \"%s\" secret in \"%s\" namespace", btpServiceOperatorSecretName, namespace))
secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
}

if err := p.Writer.Create(ctx, secret); err != nil {
p.logger.Error(fmt.Sprintf("failed to create \"%s\" secret in \"%s\" namespace", btpServiceOperatorSecretName, namespace), "error", err)
return nil, err
}

return secret, nil
}
Loading

0 comments on commit 6cec48e

Please sign in to comment.