1
0
Fork 0
mirror of https://github.com/external-secrets/external-secrets.git synced 2024-12-14 11:57:59 +00:00

IBM provider: remove deprecated code for fetching secret by name (#3078)

* remove deprecated code for fetching secret by name

Signed-off-by: shanti.gundumalla@ibm.com <shanti.gundumalla@ibm.com>

* update the documentation

Signed-off-by: shanti.gundumalla@ibm.com <shanti.gundumalla@ibm.com>

* fix linting

Signed-off-by: shanti.gundumalla@ibm.com <shanti.gundumalla@ibm.com>

---------

Signed-off-by: shanti.gundumalla@ibm.com <shanti.gundumalla@ibm.com>
Co-authored-by: shanti.gundumalla@ibm.com <shanti.gundumalla@ibm.com>
This commit is contained in:
Shanti G 2024-01-26 22:16:24 +05:30 committed by GitHub
parent 01f6be8e6e
commit 5f8d24000a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 21 additions and 415 deletions

View file

@ -238,12 +238,6 @@ Alternatively, the secret name along with its secret group name can be specified
{% include 'ibm-external-secret-by-name.yaml' %}
```
Please note that the below mechanism to get the secret by name is deprecated and not supported.
```yaml
{% include 'ibm-external-secret-by-name-deprecated.yaml' %}
```
### Getting the Kubernetes secret
The operator will fetch the IBM Secret Manager secret and inject it as a `Kind=Secret`
```

View file

@ -1,22 +0,0 @@
# NOTE: Below way of fetching the secret by name is deprecated and not supported.
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: database-credentials
spec:
refreshInterval: 60m
secretStoreRef:
name: ibm-store
kind: SecretStore
target:
name: database-credentials
creationPolicy: Owner
data:
- secretKey: username
remoteRef:
key: username_password/<SECRET_NAME>
property: username
- secretKey: password
remoteRef:
key: username_password/<SECRET_NAME>
property: password

2
go.mod
View file

@ -163,7 +163,7 @@ require (
github.com/goccy/go-json v0.10.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect

View file

@ -1,72 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ibm
import (
"time"
"github.com/golang/groupcache/lru"
)
type (
cacheIntf interface {
GetData(key string) (bool, []byte)
PutData(key string, value []byte)
DeleteData(key string)
}
lruCache struct {
lru *lru.Cache
ttl time.Duration
}
cacheObject struct {
timeExpires time.Time
value []byte
}
)
func NewCache(maxEntries int, ttl time.Duration) cacheIntf {
lruCache := &lruCache{
lru: lru.New(maxEntries),
ttl: ttl,
}
return lruCache
}
func (c *lruCache) GetData(key string) (bool, []byte) {
v, ok := c.lru.Get(key)
if !ok {
return false, nil
}
returnedObj := v.(cacheObject)
if time.Now().After(returnedObj.timeExpires) && c.ttl > 0 {
c.DeleteData(key)
return false, nil
}
return true, returnedObj.value
}
func (c *lruCache) PutData(key string, value []byte) {
obj := cacheObject{
timeExpires: time.Now().Add(c.ttl),
value: value,
}
c.lru.Add(key, obj)
}
func (c *lruCache) DeleteData(key string) {
c.lru.Remove(key)
}

View file

@ -1,92 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ibm
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
const maxEntries = 10
func dataCache(t *testing.T, ttl time.Duration, maxEntries int) cacheIntf {
t.Helper()
return NewCache(maxEntries, ttl)
}
func TestGetData(t *testing.T) {
tests := []struct {
name string
ttl time.Duration
key string
value []byte
wantValue []byte
wantFound bool
}{
{
name: "object exists in cache and has not expired",
ttl: 30 * time.Second,
key: "testObject",
value: []byte("testValue"),
wantValue: []byte("testValue"),
wantFound: true,
},
{
name: "object exists in cache and will never expire",
ttl: 0 * time.Second,
key: "testObject",
value: []byte("testValue"),
wantValue: []byte("testValue"),
wantFound: true,
},
{
name: "object exists in cache but has expired",
ttl: 1 * time.Nanosecond,
key: "testObject",
value: []byte("testValue"),
wantFound: false,
},
{
name: "object not in cache",
ttl: 30 * time.Second,
key: "testObject",
wantFound: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := NewCache(10, tt.ttl)
if tt.value != nil {
c.PutData(tt.key, tt.value)
}
gotFound, gotValue := c.GetData(tt.key)
assert.Equal(t, tt.wantFound, gotFound)
assert.Equal(t, string(gotValue), string(tt.wantValue))
})
}
}
func TestPutData(t *testing.T) {
t.Parallel()
d := dataCache(t, time.Minute, maxEntries)
d.PutData("test-key", []byte("test-value"))
}
func TestDeleteData(t *testing.T) {
t.Parallel()
d := dataCache(t, time.Minute, maxEntries)
d.DeleteData("test-key")
}

View file

@ -25,7 +25,6 @@ import (
type IBMMockClient struct {
getSecretWithContext func(ctx context.Context, getSecretOptions *sm.GetSecretOptions) (result sm.SecretIntf, response *core.DetailedResponse, err error)
listSecretsWithContext func(ctx context.Context, listSecretsOptions *sm.ListSecretsOptions) (result *sm.SecretMetadataPaginatedCollection, response *core.DetailedResponse, err error)
getSecretByNameTypeWithContext func(ctx context.Context, getSecretByNameTypeOptions *sm.GetSecretByNameTypeOptions) (result sm.SecretIntf, response *core.DetailedResponse, err error)
}
@ -33,9 +32,6 @@ type IBMMockClientParams struct {
GetSecretOptions *sm.GetSecretOptions
GetSecretOutput sm.SecretIntf
GetSecretErr error
ListSecretsOptions *sm.ListSecretsOptions
ListSecretsOutput *sm.SecretMetadataPaginatedCollection
ListSecretsErr error
GetSecretByNameOptions *sm.GetSecretByNameTypeOptions
GetSecretByNameOutput sm.SecretIntf
GetSecretByNameErr error
@ -45,10 +41,6 @@ func (mc *IBMMockClient) GetSecretWithContext(ctx context.Context, getSecretOpti
return mc.getSecretWithContext(ctx, getSecretOptions)
}
func (mc *IBMMockClient) ListSecretsWithContext(ctx context.Context, listSecretsOptions *sm.ListSecretsOptions) (result *sm.SecretMetadataPaginatedCollection, response *core.DetailedResponse, err error) {
return mc.listSecretsWithContext(ctx, listSecretsOptions)
}
func (mc *IBMMockClient) GetSecretByNameTypeWithContext(ctx context.Context, getSecretByNameTypeOptions *sm.GetSecretByNameTypeOptions) (result sm.SecretIntf, response *core.DetailedResponse, err error) {
return mc.getSecretByNameTypeWithContext(ctx, getSecretByNameTypeOptions)
}
@ -63,14 +55,6 @@ func (mc *IBMMockClient) WithValue(params IBMMockClientParams) {
}
return params.GetSecretOutput, nil, params.GetSecretErr
}
mc.listSecretsWithContext = func(ctx context.Context, paramReq *sm.ListSecretsOptions) (result *sm.SecretMetadataPaginatedCollection, response *core.DetailedResponse, err error) {
// type secretmanagerpb.AccessSecretVersionRequest contains unexported fields
// use cmpopts.IgnoreUnexported to ignore all the unexported fields in the cmp.
if !cmp.Equal(paramReq, params.ListSecretsOptions, cmpopts.IgnoreUnexported(sm.SecretMetadataPaginatedCollection{})) {
return nil, nil, fmt.Errorf("unexpected test argument for ListSecrets: %s, %s", *paramReq.Search, *params.ListSecretsOptions.Search)
}
return params.ListSecretsOutput, nil, params.ListSecretsErr
}
mc.getSecretByNameTypeWithContext = func(ctx context.Context, paramReq *sm.GetSecretByNameTypeOptions) (sm.SecretIntf, *core.DetailedResponse, error) {
// type secretmanagerpb.AccessSecretVersionRequest contains unexported fields
// use cmpopts.IgnoreUnexported to ignore all the unexported fields in the cmp.

View file

@ -1,82 +0,0 @@
/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ibm
import (
"fmt"
sm "github.com/IBM/secrets-manager-go-sdk/v2/secretsmanagerv2"
)
func extractSecretMetadata(response sm.SecretMetadataIntf, givenName *string, secretType string) (*string, *string, error) {
switch secretType {
case sm.Secret_SecretType_Arbitrary:
metadata, ok := response.(*sm.ArbitrarySecretMetadata)
if !ok {
return nil, nil, fmt.Errorf(errExtractingSecret, *givenName, sm.Secret_SecretType_Arbitrary, "extractSecretMetadata")
}
return metadata.ID, metadata.Name, nil
case sm.Secret_SecretType_UsernamePassword:
metadata, ok := response.(*sm.UsernamePasswordSecretMetadata)
if !ok {
return nil, nil, fmt.Errorf(errExtractingSecret, *givenName, sm.Secret_SecretType_UsernamePassword, "extractSecretMetadata")
}
return metadata.ID, metadata.Name, nil
case sm.Secret_SecretType_IamCredentials:
metadata, ok := response.(*sm.IAMCredentialsSecretMetadata)
if !ok {
return nil, nil, fmt.Errorf(errExtractingSecret, *givenName, sm.Secret_SecretType_IamCredentials, "extractSecretMetadata")
}
return metadata.ID, metadata.Name, nil
case sm.Secret_SecretType_ServiceCredentials:
metadata, ok := response.(*sm.ServiceCredentialsSecretMetadata)
if !ok {
return nil, nil, fmt.Errorf(errExtractingSecret, *givenName, sm.Secret_SecretType_ServiceCredentials, "extractSecretMetadata")
}
return metadata.ID, metadata.Name, nil
case sm.Secret_SecretType_ImportedCert:
metadata, ok := response.(*sm.ImportedCertificateMetadata)
if !ok {
return nil, nil, fmt.Errorf(errExtractingSecret, *givenName, sm.Secret_SecretType_ImportedCert, "extractSecretMetadata")
}
return metadata.ID, metadata.Name, nil
case sm.Secret_SecretType_PublicCert:
metadata, ok := response.(*sm.PublicCertificateMetadata)
if !ok {
return nil, nil, fmt.Errorf(errExtractingSecret, *givenName, sm.Secret_SecretType_PublicCert, "extractSecretMetadata")
}
return metadata.ID, metadata.Name, nil
case sm.Secret_SecretType_PrivateCert:
metadata, ok := response.(*sm.PrivateCertificateMetadata)
if !ok {
return nil, nil, fmt.Errorf(errExtractingSecret, *givenName, sm.Secret_SecretType_PrivateCert, "extractSecretMetadata")
}
return metadata.ID, metadata.Name, nil
case sm.Secret_SecretType_Kv:
metadata, ok := response.(*sm.KVSecretMetadata)
if !ok {
return nil, nil, fmt.Errorf(errExtractingSecret, *givenName, sm.Secret_SecretType_Kv, "extractSecretMetadata")
}
return metadata.ID, metadata.Name, nil
default:
return nil, nil, fmt.Errorf("unknown secret type %s", secretType)
}
}

View file

@ -59,9 +59,6 @@ const (
errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
errJSONSecretMarshal = "unable to marshal secret: %w"
errExtractingSecret = "unable to extract the fetched secret %s of type %s while performing %s"
defaultCacheSize = 100
defaultCacheExpiry = 1 * time.Hour
)
var contextTimeout = time.Minute * 2
@ -74,13 +71,11 @@ var (
type SecretManagerClient interface {
GetSecretWithContext(ctx context.Context, getSecretOptions *sm.GetSecretOptions) (result sm.SecretIntf, response *core.DetailedResponse, err error)
ListSecretsWithContext(ctx context.Context, listSecretsOptions *sm.ListSecretsOptions) (result *sm.SecretMetadataPaginatedCollection, response *core.DetailedResponse, err error)
GetSecretByNameTypeWithContext(ctx context.Context, getSecretByNameTypeOptions *sm.GetSecretByNameTypeOptions) (result sm.SecretIntf, response *core.DetailedResponse, err error)
}
type providerIBM struct {
IBMClient SecretManagerClient
cache cacheIntf
}
type client struct {
@ -355,31 +350,16 @@ func getKVSecret(ref esv1beta1.ExternalSecretDataRemoteRef, secret *sm.KVSecret)
}
func getSecretData(ibm *providerIBM, secretName *string, secretType, secretGroupName string) (sm.SecretIntf, error) {
var givenName *string
var cachedKey string
_, err := uuid.Parse(*secretName)
if err != nil {
// secret name has been provided instead of id
if secretGroupName == "" {
// secret group name is not provided, follow the existing mechanism
// once this mechanism is deprecated, this flow will not be supported, and error will be thrown instead
givenName = secretName
cachedKey = fmt.Sprintf("%s/%s", secretType, *givenName)
isCached, cacheData := ibm.cache.GetData(cachedKey)
tmp := string(cacheData)
cachedName := &tmp
if isCached && *cachedName != "" {
secretName = cachedName
} else {
secretName, err = findSecretByName(ibm, givenName, secretType)
if err != nil {
return nil, err
// secret group name is not provided
return nil, fmt.Errorf("failed to fetch the secret, secret group name is missing")
}
ibm.cache.PutData(cachedKey, []byte(*secretName))
}
} else {
// secret group name is provided along with secret name, follow the new mechanism by calling GetSecretByNameTypeWithContext
// secret group name is provided along with secret name,
// follow the new mechanism by calling GetSecretByNameTypeWithContext
ctx, cancel := context.WithTimeout(context.Background(), contextTimeout)
defer cancel()
response, _, err := ibm.IBMClient.GetSecretByNameTypeWithContext(
@ -395,7 +375,6 @@ func getSecretData(ibm *providerIBM, secretName *string, secretType, secretGroup
}
return response, nil
}
}
ctx, cancel := context.WithTimeout(context.Background(), contextTimeout)
defer cancel()
@ -411,38 +390,6 @@ func getSecretData(ibm *providerIBM, secretName *string, secretType, secretGroup
return response, nil
}
func findSecretByName(ibm *providerIBM, secretName *string, secretType string) (*string, error) {
var secretID *string
ctx, cancel := context.WithTimeout(context.Background(), contextTimeout)
defer cancel()
response, _, err := ibm.IBMClient.ListSecretsWithContext(ctx,
&sm.ListSecretsOptions{
Search: secretName,
})
metrics.ObserveAPICall(constants.ProviderIBMSM, constants.CallIBMSMListSecrets, err)
if err != nil {
return nil, err
}
found := 0
for _, r := range response.Secrets {
foundsecretID, foundSecretName, err := extractSecretMetadata(r, secretName, secretType)
if err == nil {
if *foundSecretName == *secretName {
found++
secretID = foundsecretID
}
}
}
if found == 0 {
return nil, fmt.Errorf("failed to find a secret for the given secretName %s", *secretName)
}
if found > 1 {
return nil, fmt.Errorf("found more than one secret matching for the given secretName %s, cannot proceed further", *secretName)
}
return secretID, nil
}
func (ibm *providerIBM) GetSecretMap(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
if utils.IsNil(ibm.IBMClient) {
return nil, fmt.Errorf(errUninitalizedIBMProvider)
@ -731,7 +678,6 @@ func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericSt
}
ibm.IBMClient = secretsManager
ibm.cache = NewCache(defaultCacheSize, defaultCacheExpiry)
return ibm, nil
}

View file

@ -21,7 +21,6 @@ import (
"strconv"
"strings"
"testing"
"time"
"github.com/IBM/go-sdk-core/v5/core"
sm "github.com/IBM/secrets-manager-go-sdk/v2/secretsmanagerv2"
@ -48,9 +47,6 @@ type secretManagerTestCase struct {
mockClient *fakesm.IBMMockClient
apiInput *sm.GetSecretOptions
apiOutput sm.SecretIntf
listInput *sm.ListSecretsOptions
listOutput *sm.SecretMetadataPaginatedCollection
listError error
getByNameInput *sm.GetSecretByNameTypeOptions
getByNameOutput sm.SecretIntf
getByNameError error
@ -69,9 +65,6 @@ func makeValidSecretManagerTestCase() *secretManagerTestCase {
apiInput: makeValidAPIInput(),
ref: makeValidRef(),
apiOutput: makeValidAPIOutput(),
listInput: makeValidListInput(),
listOutput: makeValidListSecretsOutput(),
listError: nil,
getByNameInput: makeValidGetByNameInput(),
getByNameOutput: makeValidGetByNameOutput(),
getByNameError: nil,
@ -85,9 +78,6 @@ func makeValidSecretManagerTestCase() *secretManagerTestCase {
GetSecretOptions: smtc.apiInput,
GetSecretOutput: smtc.apiOutput,
GetSecretErr: smtc.apiErr,
ListSecretsOptions: smtc.listInput,
ListSecretsOutput: smtc.listOutput,
ListSecretsErr: smtc.listError,
GetSecretByNameOptions: smtc.getByNameInput,
GetSecretByNameOutput: smtc.getByNameOutput,
GetSecretByNameErr: smtc.getByNameError,
@ -133,16 +123,6 @@ func makeValidGetByNameOutput() sm.SecretIntf {
return i
}
func makeValidListSecretsOutput() *sm.SecretMetadataPaginatedCollection {
list := sm.SecretMetadataPaginatedCollection{}
return &list
}
func makeValidListInput() *sm.ListSecretsOptions {
listOpt := sm.ListSecretsOptions{}
return &listOpt
}
func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTestCase)) *secretManagerTestCase {
smtc := makeValidSecretManagerTestCase()
for _, fn := range tweaks {
@ -152,9 +132,6 @@ func makeValidSecretManagerTestCaseCustom(tweaks ...func(smtc *secretManagerTest
GetSecretOptions: smtc.apiInput,
GetSecretOutput: smtc.apiOutput,
GetSecretErr: smtc.apiErr,
ListSecretsOptions: smtc.listInput,
ListSecretsOutput: smtc.listOutput,
ListSecretsErr: smtc.listError,
GetSecretByNameOptions: smtc.getByNameInput,
GetSecretByNameOutput: smtc.getByNameOutput,
GetSecretByNameErr: smtc.apiErr,
@ -317,16 +294,9 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
Username: &secretUsername,
Password: &secretPassword,
}
secretMetadata := &sm.UsernamePasswordSecretMetadata{
Name: utilpointer.To("testyname"),
ID: utilpointer.To(secretUUID),
}
smtc.name = name
smtc.apiInput.ID = utilpointer.To(secretUUID)
smtc.apiOutput = secret
smtc.listInput.Search = utilpointer.To("testyname")
smtc.listOutput.Secrets = make([]sm.SecretMetadataIntf, 1)
smtc.listOutput.Secrets[0] = secretMetadata
smtc.ref.Key = "username_password/" + secretName
smtc.ref.Property = property
if property == "username" {
@ -337,8 +307,6 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
}
}
setSecretUserPassByID := funcSetUserPass(secretUUID, "username", "good case: username_password type - get username by ID")
setSecretUserPassUsername := funcSetUserPass("testyname", "username", "good case: username_password type - get username by secret name")
setSecretUserPassPassword := funcSetUserPass("testyname", "password", "good case: username_password type - get password by secret name")
// good case: iam_credentials type
funcSetSecretIam := func(secretName, name string) func(*secretManagerTestCase) {
@ -349,24 +317,17 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
ID: utilpointer.To(secretUUID),
ApiKey: utilpointer.To(secretAPIKey),
}
secretMetadata := &sm.IAMCredentialsSecretMetadata{
Name: utilpointer.To("testyname"),
ID: utilpointer.To(secretUUID),
}
smtc.apiInput.ID = utilpointer.To(secretUUID)
smtc.name = name
smtc.apiOutput = secret
smtc.listInput.Search = utilpointer.To("testyname")
smtc.listOutput.Secrets = make([]sm.SecretMetadataIntf, 1)
smtc.listOutput.Secrets[0] = secretMetadata
smtc.ref.Key = iamCredentialsSecret + secretName
smtc.expectedSecret = secretAPIKey
}
}
setSecretIamByID := funcSetSecretIam(secretUUID, "good case: iam_credenatials type - get API Key by ID")
setSecretIamByName := funcSetSecretIam("testyname", "good case: iam_credenatials type - get API Key by name")
// good case: iam_credentials type - get API Key by name, providing the secret group ID
funcSetSecretIamNew := func(secretName, groupName, name string) func(*secretManagerTestCase) {
return func(smtc *secretManagerTestCase) {
secret := &sm.IAMCredentialsSecret{
@ -400,16 +361,9 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
ID: utilpointer.To(secretUUID),
Credentials: dummySrvCreds,
}
secretMetadata := &sm.ServiceCredentialsSecretMetadata{
Name: utilpointer.To("testyname"),
ID: utilpointer.To(secretUUID),
}
smtc.apiInput.ID = utilpointer.To(secretUUID)
smtc.name = name
smtc.apiOutput = secret
smtc.listInput.Search = utilpointer.To("testyname")
smtc.listOutput.Secrets = make([]sm.SecretMetadataIntf, 1)
smtc.listOutput.Secrets[0] = secretMetadata
smtc.ref.Key = "service_credentials/" + secretName
smtc.expectedSecret = "{\"apikey\":\"01234567890\"}"
}
@ -601,10 +555,7 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
makeValidSecretManagerTestCaseCustom(setNilMockClient),
makeValidSecretManagerTestCaseCustom(badSecretUserPass),
makeValidSecretManagerTestCaseCustom(setSecretUserPassByID),
makeValidSecretManagerTestCaseCustom(setSecretUserPassUsername),
makeValidSecretManagerTestCaseCustom(setSecretUserPassPassword),
makeValidSecretManagerTestCaseCustom(setSecretIamByID),
makeValidSecretManagerTestCaseCustom(setSecretIamByName),
makeValidSecretManagerTestCaseCustom(setSecretCert),
makeValidSecretManagerTestCaseCustom(setSecretKV),
makeValidSecretManagerTestCaseCustom(setSecretKVWithKey),
@ -626,7 +577,6 @@ func TestIBMSecretManagerGetSecret(t *testing.T) {
for _, v := range successCases {
t.Run(v.name, func(t *testing.T) {
sm.IBMClient = v.mockClient
sm.cache = NewCache(10, 1*time.Minute)
out, err := sm.GetSecret(context.Background(), *v.ref)
if !ErrorContains(err, v.expectError) {
t.Errorf("unexpected error:\n%s, expected:\n'%s'", err.Error(), v.expectError)