cloudFoundryDeleteService Service Key deletion adaptations (#5688)

This commit is contained in:
Dominik Lendle
2026-03-18 12:17:43 +01:00
committed by GitHub
parent d0684757cf
commit b8ed949fec
2 changed files with 185 additions and 30 deletions
+82 -20
View File
@@ -2,6 +2,7 @@ package cmd
import (
"bytes"
"encoding/json"
"fmt"
"strings"
@@ -70,33 +71,29 @@ func cloudFoundryDeleteServiceKeys(options *cloudFoundryDeleteServiceOptions, c
log.Entry().Info("Deleting inherent Service Keys")
var cfFindServiceKeysScript = []string{"service-keys", options.CfServiceInstance}
var serviceKeyBytes bytes.Buffer
c.Stdout(&serviceKeyBytes)
err := c.RunExecutable("cf", cfFindServiceKeysScript...)
ServiceGUID, err := cloudFoundryFindServiceGUID(options, c)
if err != nil {
return fmt.Errorf("Failed to Delete Service Key, most likely your service doesn't exist: %w", err)
return fmt.Errorf("Failed to determine Service Instance GUID: %w", err)
}
if len(serviceKeyBytes.String()) == 0 {
log.Entry().Info("No service key could be retrieved for your requested Service")
log.Entry().WithField("Service Instance GUID :", ServiceGUID).Info("ServiceGUID")
ServiceKeyNames, err := cloudFoundryFindServiceKeyNames(ServiceGUID, c)
if err != nil {
return fmt.Errorf("Failed to determine Service Key names: %w", err)
}
if len(ServiceKeyNames) == 0 {
log.Entry().Info("No service key names could be retrieved for your requested Service")
return nil
}
var lines []string = strings.Split(serviceKeyBytes.String(), "\n")
if len(lines) <= 4 {
log.Entry().Info("No Service Keys active to be deleted")
return nil
}
var numberOfLines = len(lines)
log.Entry().WithField("Number of service keys :", numberOfLines-4).Info("ServiceKey")
log.Entry().WithField("Number of service keys :", len(ServiceKeyNames)).Info("ServiceKey")
//Deleting all matched Service Keys for Service
for i := 3; i <= numberOfLines-2; i++ {
log.Entry().WithField("Deleting Service Key", lines[i]).Info("ServiceKeyDeletion")
var cfDeleteServiceKeyScript = []string{"delete-service-key", options.CfServiceInstance, lines[i], "-f"}
for _, serviceKey := range ServiceKeyNames {
log.Entry().WithField("Service key :", serviceKey).Info("ServiceKey")
log.Entry().WithField("Deleting Service Key", serviceKey).Info("ServiceKeyDeletion")
var cfDeleteServiceKeyScript = []string{"delete-service-key", options.CfServiceInstance, serviceKey, "-f"}
if !options.CfAsync {
cfDeleteServiceKeyScript = append(cfDeleteServiceKeyScript, "--wait")
}
@@ -105,10 +102,75 @@ func cloudFoundryDeleteServiceKeys(options *cloudFoundryDeleteServiceOptions, c
return fmt.Errorf("Failed to Delete Service Key: %w", err)
}
}
log.Entry().Info("ServiceKeys have been deleted!")
return nil
}
func cloudFoundryFindServiceKeyNames(ServiceGUID string, c command.ExecRunner) (ServiceKeyNames []string, err error) {
type Resource struct {
Name string `json:"name"`
Type string `json:"type"`
}
type ServiceKeysResponse struct {
Resources []Resource `json:"resources"`
}
// Retrieve list of Service Keys bound to Service Instance
var cfFindServiceKeysScript = []string{"curl", "/v3/service_credential_bindings?service_instance_guids=" + ServiceGUID}
var serviceKeyBytes bytes.Buffer
c.Stdout(&serviceKeyBytes)
err = c.RunExecutable("cf", cfFindServiceKeysScript...)
if err != nil {
return ServiceKeyNames, fmt.Errorf("Failed to find any related Service Keys for the Service Instance, most likely your service doesn't exist: %w", err)
}
if len(serviceKeyBytes.String()) == 0 {
log.Entry().Info("No service key could be retrieved for your requested Service")
return ServiceKeyNames, nil
}
var serviceKeys = serviceKeyBytes.String()
var response ServiceKeysResponse
err = json.Unmarshal([]byte(serviceKeys), &response)
if err != nil {
fmt.Println("Error parsing JSON:", err)
return
}
if len(response.Resources) == 0 {
log.Entry().Info("No service key could be retrieved for your requested Service")
return ServiceKeyNames, nil
}
for _, resource := range response.Resources {
if resource.Type == "key" {
ServiceKeyNames = append(ServiceKeyNames, resource.Name)
}
}
return ServiceKeyNames, err
}
func cloudFoundryFindServiceGUID(options *cloudFoundryDeleteServiceOptions, c command.ExecRunner) (GUID string, err error) {
// Read GUID of Cloud Foundry Instance
var cfFindServiceGUIDScript = []string{"service", options.CfServiceInstance, "--guid"}
var serviceGUIDBytes bytes.Buffer
c.Stdout(&serviceGUIDBytes)
err = c.RunExecutable("cf", cfFindServiceGUIDScript...)
if err != nil {
return GUID, fmt.Errorf("Failed to Find Service Instance GUID, most likely your service doesn't exist: %w", err)
}
if len(serviceGUIDBytes.String()) == 0 {
log.Entry().Info("No Service Instance GUID could be retrieved for your requested Service")
return GUID, nil
}
unformattedGUID := serviceGUIDBytes.String()
GUID = strings.Replace(unformattedGUID, "\n", "", 1)
return GUID, nil
}
func cloudFoundryDeleteServiceFunction(options *cloudFoundryDeleteServiceOptions, c command.ExecRunner) error {
var cfdeleteServiceScript = []string{"delete-service", options.CfServiceInstance, "-f"}
+103 -10
View File
@@ -13,6 +13,56 @@ import (
func TestCloudFoundryDeleteService(t *testing.T) {
t.Run("CF Delete Service without service keys: success case", func(t *testing.T) {
config := cloudFoundryDeleteServiceOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
Username: "testUser",
Password: "testPassword",
CfServiceInstance: "testInstance",
CfDeleteServiceKeys: false,
CfAsync: false,
}
m := make(map[string]string)
execRunner := mock.ExecMockRunner{
StdoutReturn: m,
}
cfUtils := cloudfoundry.CfUtilsMock{}
err := runCloudFoundryDeleteService(&config, &execRunner, &cfUtils)
if assert.NoError(t, err) {
assert.Equal(t, "cf", execRunner.Calls[0].Exec)
assert.Equal(t, []string{"delete-service", "testInstance", "-f", "--wait"}, execRunner.Calls[0].Params)
}
})
t.Run("CF Delete Service without service keys async: success case", func(t *testing.T) {
config := cloudFoundryDeleteServiceOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
Username: "testUser",
Password: "testPassword",
CfServiceInstance: "testInstance",
CfDeleteServiceKeys: false,
CfAsync: true,
}
m := make(map[string]string)
execRunner := mock.ExecMockRunner{
StdoutReturn: m,
}
cfUtils := cloudfoundry.CfUtilsMock{}
err := runCloudFoundryDeleteService(&config, &execRunner, &cfUtils)
if assert.NoError(t, err) {
assert.Equal(t, "cf", execRunner.Calls[0].Exec)
assert.Equal(t, []string{"delete-service", "testInstance", "-f"}, execRunner.Calls[0].Params)
}
})
t.Run("CF Delete Service : success case", func(t *testing.T) {
config := cloudFoundryDeleteServiceOptions{
CfAPIEndpoint: "https://api.endpoint.com",
@@ -25,12 +75,15 @@ func TestCloudFoundryDeleteService(t *testing.T) {
CfAsync: false,
}
m := make(map[string]string)
m["cf service-keys testInstance"] = `line1
line2
line3
myServiceKey1
myServiceKey2
`
m["cf service testInstance --guid"] = `instance-guid`
m["cf curl /v3/service_credential_bindings?service_instance_guids=instance-guid"] = `{
"resources": [
{ "name": "ExampleServiceKey1", "type": "key" },
{ "name": "ExampleServiceKey2", "type": "application" },
{ "name": "ExampleServiceKey3", "type": "key" }
]
}`
execRunner := mock.ExecMockRunner{
StdoutReturn: m,
}
@@ -42,10 +95,50 @@ myServiceKey2
assert.Equal(t, "cf", execRunner.Calls[1].Exec)
assert.Equal(t, "cf", execRunner.Calls[2].Exec)
assert.Equal(t, "cf", execRunner.Calls[3].Exec)
assert.Equal(t, []string{"service-keys", "testInstance"}, execRunner.Calls[0].Params)
assert.Equal(t, []string{"delete-service-key", "testInstance", "myServiceKey1", "-f", "--wait"}, execRunner.Calls[1].Params)
assert.Equal(t, []string{"delete-service-key", "testInstance", "myServiceKey2", "-f", "--wait"}, execRunner.Calls[2].Params)
assert.Equal(t, []string{"delete-service", "testInstance", "-f", "--wait"}, execRunner.Calls[3].Params)
assert.Equal(t, []string{"service", "testInstance", "--guid"}, execRunner.Calls[0].Params)
assert.Equal(t, []string{"curl", "/v3/service_credential_bindings?service_instance_guids=instance-guid"}, execRunner.Calls[1].Params)
assert.Equal(t, []string{"delete-service-key", "testInstance", "ExampleServiceKey1", "-f", "--wait"}, execRunner.Calls[2].Params)
assert.Equal(t, []string{"delete-service-key", "testInstance", "ExampleServiceKey3", "-f", "--wait"}, execRunner.Calls[3].Params)
assert.Equal(t, []string{"delete-service", "testInstance", "-f", "--wait"}, execRunner.Calls[4].Params)
}
})
t.Run("CF Delete Service async : success case", func(t *testing.T) {
config := cloudFoundryDeleteServiceOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
Username: "testUser",
Password: "testPassword",
CfServiceInstance: "testInstance",
CfDeleteServiceKeys: true,
CfAsync: true,
}
m := make(map[string]string)
m["cf service testInstance --guid"] = `instance-guid`
m["cf curl /v3/service_credential_bindings?service_instance_guids=instance-guid"] = `{
"resources": [
{ "name": "ExampleServiceKey1", "type": "key" },
{ "name": "ExampleServiceKey2", "type": "application" },
{ "name": "ExampleServiceKey3", "type": "key" }
]
}`
execRunner := mock.ExecMockRunner{
StdoutReturn: m,
}
cfUtils := cloudfoundry.CfUtilsMock{}
err := runCloudFoundryDeleteService(&config, &execRunner, &cfUtils)
if assert.NoError(t, err) {
assert.Equal(t, "cf", execRunner.Calls[0].Exec)
assert.Equal(t, "cf", execRunner.Calls[1].Exec)
assert.Equal(t, "cf", execRunner.Calls[2].Exec)
assert.Equal(t, "cf", execRunner.Calls[3].Exec)
assert.Equal(t, []string{"service", "testInstance", "--guid"}, execRunner.Calls[0].Params)
assert.Equal(t, []string{"curl", "/v3/service_credential_bindings?service_instance_guids=instance-guid"}, execRunner.Calls[1].Params)
assert.Equal(t, []string{"delete-service-key", "testInstance", "ExampleServiceKey1", "-f"}, execRunner.Calls[2].Params)
assert.Equal(t, []string{"delete-service-key", "testInstance", "ExampleServiceKey3", "-f"}, execRunner.Calls[3].Params)
assert.Equal(t, []string{"delete-service", "testInstance", "-f"}, execRunner.Calls[4].Params)
}
})
}