Skip to content

Commit

Permalink
Merge pull request #25 from SAP/migrate-to-cf-api-v3
Browse files Browse the repository at this point in the history
migrate to github.com/cloudfoundry-community/go-cfclient/v3
  • Loading branch information
cbarbian-sap authored Oct 13, 2023
2 parents ecb58f4 + 32cbaa8 commit 25edad7
Show file tree
Hide file tree
Showing 21 changed files with 241 additions and 1,146 deletions.
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/sap/cf-service-operator
go 1.21

require (
github.com/cloudfoundry-community/go-cfclient/v2 v2.0.0
github.com/cloudfoundry-community/go-cfclient/v3 v3.0.0-alpha.5
github.com/pkg/errors v0.9.1
k8s.io/api v0.28.2
k8s.io/apiextensions-apiserver v0.28.2
Expand All @@ -13,16 +13,17 @@ require (
)

require (
github.com/Masterminds/semver v1.5.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/evanphx/json-patch/v5 v5.6.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/zapr v1.2.4 // indirect
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
Expand All @@ -37,15 +38,19 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oxtoacart/bpool v0.0.0-20150712133111-4e1c5567d7c2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.16.0 // indirect
github.com/prometheus/client_model v0.4.0 // indirect
github.com/prometheus/common v0.44.0 // indirect
github.com/prometheus/procfs v0.10.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stretchr/testify v1.8.2 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.25.0 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
Expand Down
130 changes: 2 additions & 128 deletions go.sum

Large diffs are not rendered by default.

74 changes: 37 additions & 37 deletions internal/cf/binding.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ SPDX-License-Identifier: Apache-2.0
package cf

import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"

"github.com/cloudfoundry-community/go-cfclient/v2"
cfclient "github.com/cloudfoundry-community/go-cfclient/v3/client"
cfresource "github.com/cloudfoundry-community/go-cfclient/v3/resource"
"github.com/pkg/errors"

"github.com/sap/cf-service-operator/internal/facade"
"github.com/sap/cf-service-operator/pkg/cfclientext"
)

func (c *spaceClient) GetBinding(owner string) (*facade.Binding, error) {
v := url.Values{}
v.Set("label_selector", labelKeyOwner+"="+owner)
serviceBindings, err := c.client.ListV3ServiceBindingsByQuery(v)
func (c *spaceClient) GetBinding(ctx context.Context, owner string) (*facade.Binding, error) {
listOpts := cfclient.NewServiceCredentialBindingListOptions()
listOpts.LabelSelector.EqualTo(labelPrefix + "/" + labelKeyOwner + "=" + owner)
serviceBindings, err := c.client.ServiceCredentialBindings.ListAll(ctx, listOpts)
if err != nil {
return nil, err
}
Expand All @@ -34,11 +35,11 @@ func (c *spaceClient) GetBinding(owner string) (*facade.Binding, error) {

guid := serviceBinding.GUID
name := serviceBinding.Name
generation, err := strconv.ParseInt(serviceBinding.Metadata.Annotations[annotationKeyGeneration], 10, 64)
generation, err := strconv.ParseInt(*serviceBinding.Metadata.Annotations[annotationGeneration], 10, 64)
if err != nil {
return nil, errors.Wrap(err, "error parsing service binding generation")
}
parameterHash := serviceBinding.Metadata.Annotations[annotationKeyParameterHash]
parameterHash := *serviceBinding.Metadata.Annotations[annotationParameterHash]
var state facade.BindingState
switch serviceBinding.LastOperation.Type + ":" + serviceBinding.LastOperation.State {
case "create:in progress":
Expand All @@ -60,7 +61,7 @@ func (c *spaceClient) GetBinding(owner string) (*facade.Binding, error) {

var credentials map[string]interface{}
if state == facade.BindingStateReady {
details, err := c.client.GetV3ServiceBindingDetails(guid)
details, err := c.client.ServiceCredentialBindings.GetDetails(ctx, guid)
if err != nil {
return nil, errors.Wrap(err, "error getting service binding details")
}
Expand All @@ -79,38 +80,37 @@ func (c *spaceClient) GetBinding(owner string) (*facade.Binding, error) {
}, nil
}

func (c *spaceClient) CreateBinding(name string, serviceInstanceGuid string, parameters map[string]interface{}, owner string, generation int64) error {
req := cfclientext.CreateV3ServiceBindingRequest{
Name: name,
ServiceInstanceGUID: serviceInstanceGuid,
Parameters: parameters,
Metadata: &cfclient.V3Metadata{
Labels: map[string]string{
labelKeyOwner: owner,
},
Annotations: map[string]string{
annotationKeyGeneration: strconv.FormatInt(generation, 10),
annotationKeyParameterHash: facade.ObjectHash(parameters),
},
},
// Required parameters (may not be initial): name, serviceInstanceGuid, owner, generation
// Optional parameters (may be initial): parameters
func (c *spaceClient) CreateBinding(ctx context.Context, name string, serviceInstanceGuid string, parameters map[string]interface{}, owner string, generation int64) error {
req := cfresource.NewServiceCredentialBindingCreateKey(serviceInstanceGuid, name)
if parameters != nil {
jsonParameters, err := json.Marshal(parameters)
if err != nil {
return err
}
req.WithJSONParameters(string(jsonParameters))
}
_, err := c.client.CreateV3ServiceBinding(req)
req.Metadata = cfresource.NewMetadata().
WithLabel(labelPrefix, labelKeyOwner, owner).
WithAnnotation(annotationPrefix, annotationKeyGeneration, strconv.FormatInt(generation, 10)).
WithAnnotation(annotationPrefix, annotationKeyParameterHash, facade.ObjectHash(parameters))

_, _, err := c.client.ServiceCredentialBindings.Create(ctx, req)
return err
}

func (c *spaceClient) UpdateBinding(guid string, generation int64) error {
req := cfclientext.UpdateV3ServiceBindingRequest{
Metadata: &cfclient.V3Metadata{
Annotations: map[string]string{
annotationKeyGeneration: strconv.FormatInt(generation, 10),
},
},
}
_, err := c.client.UpdateV3ServiceBinding(guid, req)
// Required parameters (may not be initial): guid, generation
func (c *spaceClient) UpdateBinding(ctx context.Context, guid string, generation int64) error {
// TODO: why is there no cfresource.NewServiceCredentialBindingUpdate() method ?
req := &cfresource.ServiceCredentialBindingUpdate{}
req.Metadata = cfresource.NewMetadata().
WithAnnotation(annotationPrefix, annotationKeyGeneration, strconv.FormatInt(generation, 10))

_, err := c.client.ServiceCredentialBindings.Update(ctx, guid, req)
return err
}

func (c *spaceClient) DeleteBinding(guid string) error {
_, err := c.client.DeleteV3ServiceBinding(guid)
return err
func (c *spaceClient) DeleteBinding(ctx context.Context, guid string) error {
return c.client.ServiceCredentialBindings.Delete(ctx, guid)
}
37 changes: 20 additions & 17 deletions internal/cf/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,32 +8,37 @@ package cf
import (
"fmt"

"github.com/cloudfoundry-community/go-cfclient/v2"
cfclient "github.com/cloudfoundry-community/go-cfclient/v3/client"
cfconfig "github.com/cloudfoundry-community/go-cfclient/v3/config"

"github.com/sap/cf-service-operator/internal/facade"
"github.com/sap/cf-service-operator/pkg/cfclientext"
)

const (
labelKeyOwner = "service-operator.cf.cs.sap.com/owner"
annotationKeyGeneration = "service-operator.cf.cs.sap.com/generation"
annotationKeyParameterHash = "service-operator.cf.cs.sap.com/parameter-hash"
labelPrefix = "service-operator.cf.cs.sap.com"
labelKeyOwner = "owner"
labelOwner = labelPrefix + "/" + labelKeyOwner
annotationPrefix = "service-operator.cf.cs.sap.com"
annotationKeyGeneration = "generation"
annotationGeneration = annotationPrefix + "/" + annotationKeyGeneration
annotationKeyParameterHash = "parameter-hash"
annotationParameterHash = annotationPrefix + "/" + annotationKeyParameterHash
)

type organizationClient struct {
url string
username string
password string
organizationName string
client cfclientext.Client
client cfclient.Client
}

type spaceClient struct {
url string
username string
password string
spaceGuid string
client cfclientext.Client
client cfclient.Client
}

func newOrganizationClient(organizationName string, url string, username string, password string) (*organizationClient, error) {
Expand All @@ -49,12 +54,11 @@ func newOrganizationClient(organizationName string, url string, username string,
if password == "" {
return nil, fmt.Errorf("missing or empty password")
}
config := &cfclient.Config{
ApiAddress: url,
Username: username,
Password: password,
config, err := cfconfig.NewUserPassword(url, username, password)
if err != nil {
return nil, err
}
c, err := cfclientext.NewClient(config)
c, err := cfclient.New(config)
if err != nil {
return nil, err
}
Expand All @@ -74,12 +78,11 @@ func newSpaceClient(spaceGuid string, url string, username string, password stri
if password == "" {
return nil, fmt.Errorf("missing or empty password")
}
config := &cfclient.Config{
ApiAddress: url,
Username: username,
Password: password,
config, err := cfconfig.NewUserPassword(url, username, password)
if err != nil {
return nil, err
}
c, err := cfclientext.NewClient(config)
c, err := cfclient.New(config)
if err != nil {
return nil, err
}
Expand Down
6 changes: 4 additions & 2 deletions internal/cf/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ SPDX-License-Identifier: Apache-2.0

package cf

func (c *spaceClient) Check() error {
_, err := c.client.GetV3SpaceByGUID(c.spaceGuid)
import "context"

func (c *spaceClient) Check(ctx context.Context) error {
_, err := c.client.Spaces.Get(ctx, c.spaceGuid)
if err != nil {
return err
}
Expand Down
102 changes: 60 additions & 42 deletions internal/cf/instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,22 @@ SPDX-License-Identifier: Apache-2.0
package cf

import (
"context"
"encoding/json"
"fmt"
"net/url"
"strconv"

"github.com/cloudfoundry-community/go-cfclient/v2"
cfclient "github.com/cloudfoundry-community/go-cfclient/v3/client"
cfresource "github.com/cloudfoundry-community/go-cfclient/v3/resource"
"github.com/pkg/errors"

"github.com/sap/cf-service-operator/internal/facade"
"github.com/sap/cf-service-operator/pkg/cfclientext"
)

func (c *spaceClient) GetInstance(owner string) (*facade.Instance, error) {
v := url.Values{}
v.Set("label_selector", labelKeyOwner+"="+owner)
serviceInstances, err := c.client.ListV3ServiceInstancesByQuery(v)
func (c *spaceClient) GetInstance(ctx context.Context, owner string) (*facade.Instance, error) {
listOpts := cfclient.NewServiceInstanceListOptions()
listOpts.LabelSelector.EqualTo(labelPrefix + "/" + labelKeyOwner + "=" + owner)
serviceInstances, err := c.client.ServiceInstances.ListAll(ctx, listOpts)
if err != nil {
return nil, err
}
Expand All @@ -34,12 +35,12 @@ func (c *spaceClient) GetInstance(owner string) (*facade.Instance, error) {

guid := serviceInstance.GUID
name := serviceInstance.Name
servicePlanGuid := serviceInstance.RelationShips["service_plan"].Data.GUID
generation, err := strconv.ParseInt(serviceInstance.Metadata.Annotations[annotationKeyGeneration], 10, 64)
servicePlanGuid := serviceInstance.Relationships.ServicePlan.Data.GUID
generation, err := strconv.ParseInt(*serviceInstance.Metadata.Annotations[annotationGeneration], 10, 64)
if err != nil {
return nil, errors.Wrap(err, "error parsing service instance generation")
}
parameterHash := serviceInstance.Metadata.Annotations[annotationKeyParameterHash]
parameterHash := *serviceInstance.Metadata.Annotations[annotationParameterHash]
var state facade.InstanceState
switch serviceInstance.LastOperation.Type + ":" + serviceInstance.LastOperation.State {
case "create:in progress":
Expand Down Expand Up @@ -77,45 +78,62 @@ func (c *spaceClient) GetInstance(owner string) (*facade.Instance, error) {
}, nil
}

func (c *spaceClient) CreateInstance(name string, servicePlanGuid string, parameters map[string]interface{}, tags []string, owner string, generation int64) error {
req := cfclientext.CreateV3ServiceInstanceRequest{
Name: name,
SpaceGUID: c.spaceGuid,
ServicePlanGUID: servicePlanGuid,
Parameters: parameters,
Tags: tags,
Metadata: &cfclient.V3Metadata{
Labels: map[string]string{
labelKeyOwner: owner,
},
Annotations: map[string]string{
annotationKeyGeneration: strconv.FormatInt(generation, 10),
annotationKeyParameterHash: facade.ObjectHash(parameters),
},
},
// Required parameters (may not be initial): name, servicePlanGuid, owner, generation
// Optional parameters (may be initial): parameters, tags
func (c *spaceClient) CreateInstance(ctx context.Context, name string, servicePlanGuid string, parameters map[string]interface{}, tags []string, owner string, generation int64) error {
req := cfresource.NewServiceInstanceCreateManaged(name, c.spaceGuid, servicePlanGuid)
if parameters != nil {
jsonParameters, err := json.Marshal(parameters)
if err != nil {
return err
}
// TODO: why is there no ServiceInstanceCreate.WithJSONParamters() method (ServiceCredentialBindingCreate has such a method) ?
// or ServiceInstance.WithParameters() method (ServiceInstanceManagedUpdate has such a method)
req.Parameters = &[]json.RawMessage{json.RawMessage(jsonParameters)}[0]
}
_, err := c.client.CreateV3ServiceInstance(req)
if tags != nil {
req.Tags = tags
}
req.Metadata = cfresource.NewMetadata().
WithLabel(labelPrefix, labelKeyOwner, owner).
WithAnnotation(annotationPrefix, annotationKeyGeneration, strconv.FormatInt(generation, 10)).
WithAnnotation(annotationPrefix, annotationKeyParameterHash, facade.ObjectHash(parameters))

_, err := c.client.ServiceInstances.CreateManaged(ctx, req)
return err
}

func (c *spaceClient) UpdateInstance(guid string, name string, servicePlanGuid string, parameters map[string]interface{}, tags []string, generation int64) error {
req := cfclientext.UpdateV3ServiceInstanceRequest{
Name: name,
ServicePlanGUID: servicePlanGuid,
Parameters: parameters,
Tags: tags,
Metadata: &cfclient.V3Metadata{
Annotations: map[string]string{
annotationKeyGeneration: strconv.FormatInt(generation, 10),
annotationKeyParameterHash: facade.ObjectHash(parameters),
},
},
// Required parameters (may not be initial): guid, generation
// Optional parameters (may be initial): name, servicePlanGuid, parameters, tags
func (c *spaceClient) UpdateInstance(ctx context.Context, guid string, name string, servicePlanGuid string, parameters map[string]interface{}, tags []string, generation int64) error {
req := cfresource.NewServiceInstanceManagedUpdate()
if name != "" {
req.WithName(name)
}
if servicePlanGuid != "" {
req.WithServicePlan(servicePlanGuid)
}
if parameters != nil {
jsonParameters, err := json.Marshal(parameters)
if err != nil {
return err
}
req.WithParameters(jsonParameters)
}
_, err := c.client.UpdateV3ServiceInstance(guid, req)
if tags != nil {
req.WithTags(tags)
}
req.Metadata = cfresource.NewMetadata().
WithAnnotation(annotationPrefix, annotationKeyGeneration, strconv.FormatInt(generation, 10))
if parameters != nil {
req.Metadata.WithAnnotation(annotationPrefix, annotationKeyParameterHash, facade.ObjectHash(parameters))
}

_, _, err := c.client.ServiceInstances.UpdateManaged(ctx, guid, req)
return err
}

func (c *spaceClient) DeleteInstance(guid string) error {
_, err := c.client.DeleteV3ServiceInstance(guid)
func (c *spaceClient) DeleteInstance(ctx context.Context, guid string) error {
_, err := c.client.ServiceInstances.Delete(ctx, guid)
return err
}
Loading

0 comments on commit 25edad7

Please sign in to comment.