Skip to content

Commit 0eeaa8e

Browse files
committed
enable serviceinstance adapter with refactoring
add service instance
1 parent a799fe4 commit 0eeaa8e

14 files changed

Lines changed: 424 additions & 77 deletions

File tree

cmd/importer/cmd/subcmd/import.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,11 @@ var ImportCMD = &cobra.Command{
6363
// Create adapters
6464
clientAdapter := &adapters.CFClientAdapter{}
6565
resourceAdapters := map[string]resource.ResourceAdapter{
66-
v1alpha1.Space_Kind: &adapterv1alpha1.CFSpaceAdapter{},
67-
v1alpha1.Org_Kind: &adapterv1alpha1.CFOrganizationAdapter{},
68-
v1alpha1.App_Kind: &adapterv1alpha1.CFAppAdapter{},
69-
v1alpha1.RouteKind: &adapterv1alpha1.CFRouteAdapter{},
66+
v1alpha1.Space_Kind: &adapterv1alpha1.CFSpaceAdapter{},
67+
v1alpha1.Org_Kind: &adapterv1alpha1.CFOrganizationAdapter{},
68+
v1alpha1.App_Kind: &adapterv1alpha1.CFAppAdapter{},
69+
v1alpha1.RouteKind: &adapterv1alpha1.CFRouteAdapter{},
70+
v1alpha1.ServiceInstance_Kind: &adapterv1alpha1.CFServiceInstanceAdapter{},
7071
}
7172
configParser := &adapters.CFConfigParser{}
7273

cmd/importer/config.yaml

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
resources:
22
- org:
3-
name: TodoCompany
3+
name: cf-dev
44
managementPolicies: [Observe]
55
- space:
66
name: .*
7-
orgRef: TodoCompany
7+
orgRef: cf-dev
88
managementPolicies: [Observe]
99
- app:
1010
name: .*
11-
spaceRef: Production
11+
spaceRef: my-demo-space
1212
managementPolicies: [Observe]
13-
- app:
14-
name: .*
15-
spaceRef: Testing
16-
managementPolicies: ["Observe"]
1713
- route:
1814
name: .*
19-
spaceRef: Testing
20-
domainRef: Testing
15+
spaceRef: space-app
16+
domainRef: test-domain
17+
managementPolicies: [Observe]
18+
- serviceInstance:
19+
name: .*
20+
spaceRef: my-demo-space
21+
type: managed
2122
managementPolicies: [Observe]
2223
providerConfigRef:
2324
name: default
2425
namespace: default
26+

examples/resources/org.yaml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,7 @@ metadata:
77
spec:
88
managementPolicies: ["Observe"]
99
forProvider:
10-
name: cf-dev
10+
name: complex-org-cf
1111
providerConfigRef:
1212
name: default
1313

14-
---
15-
apiVersion: cloudfoundry.crossplane.io/v1alpha1
16-
kind: Organization
17-
metadata:
18-
namespace: default
19-
name: my-org-dev
20-
annotations:
21-
crossplane.io/external-name: cf-dev
22-
spec:
23-
forProvider: {}

examples/resources/orgrole.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ metadata:
66
name: my-org-auditor-daniel
77
spec:
88
forProvider:
9-
type: "Auditor"
9+
type: "Manager"
1010
orgRef:
1111
name: my-org
12-
username: "1@example.com"
12+
username: "daniel.lou@sap.com"
1313
origin: sap.ids

internal/cli/adapters/client.go

Lines changed: 111 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"strconv"
78

89
cfv3 "github.com/cloudfoundry/go-cfclient/v3/client"
910
cfconfig "github.com/cloudfoundry/go-cfclient/v3/config"
@@ -64,6 +65,8 @@ func (c *CFClient) GetResourcesByType(ctx context.Context, resourceType string,
6465
return c.getApps(ctx, filter)
6566
case v1alpha1.RouteKind:
6667
return c.getRoutes(ctx, filter)
68+
case v1alpha1.ServiceInstance_Kind:
69+
return c.getServiceInstances(ctx, filter)
6770
default:
6871
return nil, fmt.Errorf("unsupported resource type: %s", resourceType)
6972
}
@@ -146,28 +149,43 @@ func (c *CFClient) getOrganizations(ctx context.Context, filter map[string]strin
146149
return results, nil
147150
}
148151

152+
// getSpaceReference retrieves a space reference by name
153+
func (c *CFClient) getSpaceReference(ctx context.Context, filter map[string]string) (string, error) {
154+
spaceName, ok := filter["space"]
155+
if !ok {
156+
return "", fmt.Errorf("space-reference filter is required")
157+
}
158+
159+
spaceRefFilter := cfv3.SpaceListOptions{Names: cfv3.Filter{Values: []string{spaceName}}}
160+
spaceRef, err := c.client.Spaces.ListAll(ctx, &spaceRefFilter)
161+
if err != nil {
162+
return "", fmt.Errorf("%s: %w", errGetSpaceReference, err)
163+
}
164+
165+
if len(spaceRef) == 0 || spaceRef[0].GUID == "" {
166+
return "", fmt.Errorf("%s: space %s not found", errGetSpaceReference, spaceName)
167+
}
168+
169+
return spaceRef[0].GUID, nil
170+
}
171+
149172
func (c *CFClient) getApps(ctx context.Context, filter map[string]string) ([]interface{}, error) {
173+
150174
// Get name filter
151175
name, ok := filter["name"]
152176
if !ok {
153177
return nil, fmt.Errorf("name filter is required for apps")
154178
}
155-
spaceName, ok := filter["space"]
156-
if !ok {
157-
return nil, fmt.Errorf("org-reference filter is required for apps")
158-
}
159179

160180
// get referenced space
161-
spaceRefFilter := cfv3.SpaceListOptions{Names: cfv3.Filter{Values: []string{spaceName}}}
162-
spaceRef, err := c.client.Spaces.ListAll(ctx, &spaceRefFilter)
163-
kingpin.FatalIfError(err, "%s", errGetSpaceReference)
164-
165-
if spaceRef[0].GUID == "" {
166-
kingpin.FatalIfError(fmt.Errorf("organization %s not found", spaceName), "%s", errGetOrgReference)
181+
spaceGUID, err := c.getSpaceReference(ctx, filter)
182+
if err != nil {
183+
return nil, err
167184
}
168185

186+
utils.PrintLine("Fetching apps in space:", spaceGUID, 30)
169187
// define filter-option with spaceRef for query
170-
opt := &cfv3.AppListOptions{SpaceGUIDs: cfv3.Filter{Values: []string{spaceRef[0].GUID}}}
188+
opt := &cfv3.AppListOptions{SpaceGUIDs: cfv3.Filter{Values: []string{spaceGUID}}}
171189

172190
// Get apps from CF
173191
responseCollection, err := c.client.Applications.ListAll(ctx, opt)
@@ -193,22 +211,15 @@ func (c *CFClient) getRoutes(ctx context.Context, filter map[string]string) ([]i
193211
if !ok {
194212
return nil, fmt.Errorf("host filter is required for routes")
195213
}
196-
spaceName, ok := filter["space"]
197-
if !ok {
198-
return nil, fmt.Errorf("space-reference filter is required for routes")
199-
}
200214
domainName, ok := filter["domain"]
201215
if !ok {
202216
return nil, fmt.Errorf("domain-reference filter is required for routes")
203217
}
204218

205219
// get referenced space
206-
spaceRefFilter := cfv3.SpaceListOptions{Names: cfv3.Filter{Values: []string{spaceName}}}
207-
spaceRef, err := c.client.Spaces.ListAll(ctx, &spaceRefFilter)
208-
kingpin.FatalIfError(err, "%s", errGetSpaceReference)
209-
210-
if spaceRef[0].GUID == "" {
211-
kingpin.FatalIfError(fmt.Errorf("space %s not found", spaceName), "%s", errGetSpaceReference)
220+
spaceGUID, err := c.getSpaceReference(ctx, filter)
221+
if err != nil {
222+
return nil, err
212223
}
213224

214225
// get referenced domain
@@ -222,7 +233,7 @@ func (c *CFClient) getRoutes(ctx context.Context, filter map[string]string) ([]i
222233

223234
// define filter-option with spaceRef for query
224235
opt := &cfv3.RouteListOptions{
225-
SpaceGUIDs: cfv3.Filter{Values: []string{spaceRef[0].GUID}},
236+
SpaceGUIDs: cfv3.Filter{Values: []string{spaceGUID}},
226237
DomainGUIDs: cfv3.Filter{Values: []string{domainRef[0].GUID}},
227238
}
228239

@@ -244,6 +255,84 @@ func (c *CFClient) getRoutes(ctx context.Context, filter map[string]string) ([]i
244255
return results, nil
245256
}
246257

258+
func (c *CFClient) getServiceInstances(ctx context.Context, filter map[string]string) ([]interface{}, error) {
259+
260+
// Get name filter
261+
name, ok := filter["name"]
262+
if !ok {
263+
return nil, fmt.Errorf("name filter is required for service instances")
264+
}
265+
266+
utils.PrintLine("Fetching service instances:", name, 30)
267+
// get referenced space
268+
spaceGUID, err := c.getSpaceReference(ctx, filter)
269+
if err != nil {
270+
return nil, err
271+
}
272+
utils.PrintLine("Fetching service instances in space ...", spaceGUID, 30)
273+
274+
// define filter-option with spaceRef for query
275+
opt := &cfv3.ServiceInstanceListOptions{SpaceGUIDs: cfv3.Filter{Values: []string{spaceGUID}}}
276+
277+
if serviceType, ok := filter["type"]; ok {
278+
opt.Type = serviceType
279+
}
280+
281+
// Get service instances from CF
282+
responseCollection, err := c.client.ServiceInstances.ListAll(ctx, opt)
283+
if err != nil {
284+
return nil, err
285+
}
286+
287+
utils.PrintLine("# service instances", strconv.Itoa(len(responseCollection)), 30)
288+
289+
// Filter service instances by name
290+
var results []interface{}
291+
for _, serviceInstance := range responseCollection {
292+
if utils.IsFullMatch(name, serviceInstance.Name) {
293+
results = append(results, serviceInstance)
294+
}
295+
}
296+
297+
return results, nil
298+
}
299+
300+
func (c *CFClient) GetServicePlan(ctx context.Context, guid string) (*v1alpha1.ServicePlanParameters, error) {
301+
sp, err := c.client.ServicePlans.Get(ctx, guid)
302+
if err != nil {
303+
return nil, fmt.Errorf("failed to get service plan: %w", err)
304+
}
305+
306+
// Get service offering details
307+
so, err := c.client.ServiceOfferings.Get(ctx, sp.Relationships.ServiceOffering.Data.GUID)
308+
if err != nil {
309+
return nil, fmt.Errorf("failed to get service offering: %w", err)
310+
}
311+
312+
return &v1alpha1.ServicePlanParameters{
313+
ID: &sp.GUID,
314+
Offering: &so.Name,
315+
Plan: &sp.Name,
316+
}, nil
317+
}
318+
319+
func (c *CFClient) GetServiceCredentials(ctx context.Context, guid string, serviceType string) (*json.RawMessage, error) {
320+
// Get credentials based on service type
321+
if serviceType == "managed" {
322+
params, err := c.client.ServiceInstances.GetManagedParameters(ctx, guid)
323+
if err != nil {
324+
return nil, fmt.Errorf("failed to get managed service parameters: %w", err)
325+
}
326+
return params, nil
327+
} else {
328+
creds, err := c.client.ServiceInstances.GetUserProvidedCredentials(ctx, guid)
329+
if err != nil {
330+
return nil, fmt.Errorf("failed to get user-provided service credentials: %w", err)
331+
}
332+
return creds, nil
333+
}
334+
}
335+
247336
// CFClientAdapter implements the ClientAdapter interface
248337
type CFClientAdapter struct{}
249338

internal/cli/adapters/config.go

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"gopkg.in/yaml.v2"
1010

1111
"github.com/SAP/crossplane-provider-cloudfoundry/apis/resources/v1alpha1"
12+
"github.com/SAP/crossplane-provider-cloudfoundry/internal/cli/pkg/utils"
1213
"github.com/SAP/crossplane-provider-cloudfoundry/internal/crossplaneimport/client"
1314
"github.com/SAP/crossplane-provider-cloudfoundry/internal/crossplaneimport/config"
1415
"github.com/SAP/crossplane-provider-cloudfoundry/internal/crossplaneimport/resource"
@@ -21,9 +22,10 @@ type Config struct {
2122
}
2223

2324
type Resource struct {
24-
Space Space `yaml:"space"`
25-
Organization Organization `yaml:"org"`
26-
App App `yaml:"app"`
25+
Space Space `yaml:"space"`
26+
Organization Organization `yaml:"org"`
27+
App App `yaml:"app"`
28+
ServiceInstance ServiceInstance `yaml:"serviceInstance"`
2729
// add more resources here
2830
}
2931

@@ -44,6 +46,13 @@ type App struct {
4446
ManagementPolicies []ManagementPolicy `yaml:"managementPolicies"`
4547
}
4648

49+
type ServiceInstance struct {
50+
Name string `yaml:"name"`
51+
SpaceRef string `yaml:"spaceRef"`
52+
Type string `yaml:"type"`
53+
ManagementPolicies []ManagementPolicy `yaml:"managementPolicies"`
54+
}
55+
4756
type ManagementPolicy string
4857

4958
// CFResourceFilter implements the ResourceFilter interface
@@ -52,6 +61,7 @@ type CFResourceFilter struct {
5261
Space *SpaceFilter
5362
Organization *OrganizationFilter
5463
App *AppFilter
64+
ServiceInstance *ServiceInstanceFilter
5565
ManagementPolicies []v1.ManagementAction
5666
}
5767

@@ -76,6 +86,12 @@ func (f *CFResourceFilter) GetFilterCriteria() map[string]string {
7686
criteria["space"] = f.App.SpaceRef
7787
}
7888

89+
if f.ServiceInstance != nil {
90+
criteria["name"] = f.ServiceInstance.Name
91+
criteria["space"] = f.ServiceInstance.SpaceRef
92+
criteria["type"] = f.ServiceInstance.Type
93+
}
94+
7995
return criteria
8096
}
8197

@@ -97,6 +113,12 @@ type AppFilter struct {
97113
SpaceRef string
98114
}
99115

116+
type ServiceInstanceFilter struct {
117+
Name string
118+
SpaceRef string
119+
Type string
120+
}
121+
100122
// CFConfig implements the ProviderConfig interface
101123
type CFConfig struct {
102124
Resources []Resource
@@ -123,6 +145,11 @@ func (c *CFConfig) resourceIsValid(resource Resource) bool {
123145
fmt.Println(resource.App.Name + "is not a valid app configuration")
124146
return false
125147
}
148+
// check for empty service instance names
149+
if resource.ServiceInstance.Name != "" && (resource.ServiceInstance.ManagementPolicies == nil || resource.ServiceInstance.SpaceRef == "" || resource.ServiceInstance.Type == "") {
150+
fmt.Println(resource.ServiceInstance.Name + "is not a valid service instance configuration")
151+
return false
152+
}
126153
return true
127154
}
128155

@@ -203,6 +230,7 @@ func (p *CFConfigParser) ParseConfig(configPath string) (config.ProviderConfig,
203230
}
204231

205232
if res.App.Name != "" {
233+
utils.PrintLine("add app ...", res.App.Name, 30)
206234
var policies []v1.ManagementAction
207235
for _, policy := range res.App.ManagementPolicies {
208236
policies = append(policies, v1.ManagementAction(policy))
@@ -217,6 +245,25 @@ func (p *CFConfigParser) ParseConfig(configPath string) (config.ProviderConfig,
217245
ManagementPolicies: policies,
218246
})
219247
}
248+
249+
if res.ServiceInstance.Name != "" {
250+
utils.PrintLine("add service instances ...", res.ServiceInstance.Name, 30)
251+
252+
var policies []v1.ManagementAction
253+
for _, policy := range res.ServiceInstance.ManagementPolicies {
254+
policies = append(policies, v1.ManagementAction(policy))
255+
}
256+
257+
filters = append(filters, &CFResourceFilter{
258+
Type: v1alpha1.ServiceInstance_Kind,
259+
ServiceInstance: &ServiceInstanceFilter{
260+
Name: res.ServiceInstance.Name,
261+
SpaceRef: res.ServiceInstance.SpaceRef,
262+
Type: res.ServiceInstance.Type,
263+
},
264+
ManagementPolicies: policies,
265+
})
266+
}
220267
}
221268

222269
return cfConfig, filters, nil

0 commit comments

Comments
 (0)