@@ -18,7 +18,8 @@ import (
1818
1919// Define test error constants.
2020var (
21- ErrInternalError = errors .New ("internal error" )
21+ ErrInternalError = errors .New ("internal error" )
22+ ErrTransientError = errors .New ("transient error" )
2223)
2324
2425// MockGSMClient is a mock implementation of GSMClient.
@@ -76,6 +77,45 @@ func newGSMStoreWithClient(client GSMClient, options GSMStoreOptions) *GSMStore
7677 return store
7778}
7879
80+ func gsmClientSecretCreationMock (parent string , secretId string , secretPayload string , err error ) func (m * MockGSMClient ) {
81+ return func (m * MockGSMClient ) {
82+ m .On ("CreateSecret" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.CreateSecretRequest ) bool {
83+ expectedReq := & secretmanagerpb.CreateSecretRequest {
84+ Parent : parent ,
85+ SecretId : secretId ,
86+ Secret : & secretmanagerpb.Secret {
87+ Replication : & secretmanagerpb.Replication {
88+ Replication : & secretmanagerpb.Replication_Automatic_ {
89+ Automatic : & secretmanagerpb.Replication_Automatic {},
90+ },
91+ },
92+ },
93+ }
94+ return req .Parent == expectedReq .Parent &&
95+ req .SecretId == expectedReq .SecretId &&
96+ req .Secret .GetReplication ().GetAutomatic () != nil
97+ })).Return (& secretmanagerpb.Secret {
98+ Name : fmt .Sprintf ("%s/secrets/%s" , parent , secretId ),
99+ }, nil )
100+
101+ var ret * secretmanagerpb.SecretVersion
102+ if err == nil {
103+ ret = & secretmanagerpb.SecretVersion {}
104+ }
105+
106+ m .On ("AddSecretVersion" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.AddSecretVersionRequest ) bool {
107+ expectedReq := & secretmanagerpb.AddSecretVersionRequest {
108+ Parent : fmt .Sprintf ("%s/secrets/%s" , parent , secretId ),
109+ Payload : & secretmanagerpb.SecretPayload {
110+ Data : []byte (secretPayload ),
111+ },
112+ }
113+ return req .Parent == expectedReq .Parent &&
114+ string (req .Payload .Data ) == string (expectedReq .Payload .Data )
115+ })).Return (ret , err )
116+ }
117+ }
118+
79119func TestGSMStore_Set (t * testing.T ) {
80120 testPrefix := "test-prefix"
81121 testDelimiter := "-"
@@ -95,37 +135,12 @@ func TestGSMStore_Set(t *testing.T) {
95135 component : "app/service" ,
96136 key : "config-key" ,
97137 value : "test-value" ,
98- mockFn : func (m * MockGSMClient ) {
99- m .On ("CreateSecret" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.CreateSecretRequest ) bool {
100- expectedReq := & secretmanagerpb.CreateSecretRequest {
101- Parent : "projects/test-project" ,
102- SecretId : "test-prefix_dev_usw2_app_service_config-key" ,
103- Secret : & secretmanagerpb.Secret {
104- Replication : & secretmanagerpb.Replication {
105- Replication : & secretmanagerpb.Replication_Automatic_ {
106- Automatic : & secretmanagerpb.Replication_Automatic {},
107- },
108- },
109- },
110- }
111- return req .Parent == expectedReq .Parent &&
112- req .SecretId == expectedReq .SecretId &&
113- req .Secret .GetReplication ().GetAutomatic () != nil
114- })).Return (& secretmanagerpb.Secret {
115- Name : "projects/test-project/secrets/test-prefix_dev_usw2_app_service_config-key" ,
116- }, nil )
117-
118- m .On ("AddSecretVersion" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.AddSecretVersionRequest ) bool {
119- expectedReq := & secretmanagerpb.AddSecretVersionRequest {
120- Parent : "projects/test-project/secrets/test-prefix_dev_usw2_app_service_config-key" ,
121- Payload : & secretmanagerpb.SecretPayload {
122- Data : []byte ("test-value" ),
123- },
124- }
125- return req .Parent == expectedReq .Parent &&
126- string (req .Payload .Data ) == string (expectedReq .Payload .Data )
127- })).Return (& secretmanagerpb.SecretVersion {}, nil )
128- },
138+ mockFn : gsmClientSecretCreationMock (
139+ "projects/test-project" ,
140+ "test-prefix_dev_usw2_app_service_config-key" ,
141+ `"test-value"` ,
142+ nil ,
143+ ),
129144 wantErr : false ,
130145 },
131146 {
@@ -134,35 +149,12 @@ func TestGSMStore_Set(t *testing.T) {
134149 component : "app/service" ,
135150 key : "config-key" ,
136151 value : "test-value" ,
137- mockFn : func (m * MockGSMClient ) {
138- m .On ("CreateSecret" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.CreateSecretRequest ) bool {
139- expectedReq := & secretmanagerpb.CreateSecretRequest {
140- Parent : "projects/test-project" ,
141- SecretId : "test-prefix_dev_usw2_app_service_config-key" ,
142- Secret : & secretmanagerpb.Secret {
143- Replication : & secretmanagerpb.Replication {
144- Replication : & secretmanagerpb.Replication_Automatic_ {
145- Automatic : & secretmanagerpb.Replication_Automatic {},
146- },
147- },
148- },
149- }
150- return req .Parent == expectedReq .Parent &&
151- req .SecretId == expectedReq .SecretId &&
152- req .Secret .GetReplication ().GetAutomatic () != nil
153- })).Return (nil , status .Error (codes .AlreadyExists , "secret already exists" ))
154-
155- m .On ("AddSecretVersion" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.AddSecretVersionRequest ) bool {
156- expectedReq := & secretmanagerpb.AddSecretVersionRequest {
157- Parent : "projects/test-project/secrets/test-prefix_dev_usw2_app_service_config-key" ,
158- Payload : & secretmanagerpb.SecretPayload {
159- Data : []byte ("test-value" ),
160- },
161- }
162- return req .Parent == expectedReq .Parent &&
163- string (req .Payload .Data ) == string (expectedReq .Payload .Data )
164- })).Return (& secretmanagerpb.SecretVersion {}, nil )
165- },
152+ mockFn : gsmClientSecretCreationMock (
153+ "projects/test-project" ,
154+ "test-prefix_dev_usw2_app_service_config-key" ,
155+ `"test-value"` ,
156+ nil ,
157+ ),
166158 wantErr : false ,
167159 },
168160 {
@@ -171,24 +163,26 @@ func TestGSMStore_Set(t *testing.T) {
171163 component : "app/service" ,
172164 key : "config-key" ,
173165 value : "test-value" ,
174- mockFn : func (m * MockGSMClient ) {
175- m .On ("CreateSecret" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.CreateSecretRequest ) bool {
176- expectedReq := & secretmanagerpb.CreateSecretRequest {
177- Parent : "projects/test-project" ,
178- SecretId : "test-prefix_dev_usw2_app_service_config-key" ,
179- Secret : & secretmanagerpb.Secret {
180- Replication : & secretmanagerpb.Replication {
181- Replication : & secretmanagerpb.Replication_Automatic_ {
182- Automatic : & secretmanagerpb.Replication_Automatic {},
183- },
184- },
185- },
186- }
187- return req .Parent == expectedReq .Parent &&
188- req .SecretId == expectedReq .SecretId &&
189- req .Secret .GetReplication ().GetAutomatic () != nil
190- })).Return (nil , fmt .Errorf ("internal error: %w" , ErrInternalError ))
191- },
166+ mockFn : gsmClientSecretCreationMock (
167+ "projects/test-project" ,
168+ "test-prefix_dev_usw2_app_service_config-key" ,
169+ `"test-value"` ,
170+ fmt .Errorf ("internal error: %w" , ErrInternalError )),
171+ wantErr : true ,
172+ },
173+
174+ {
175+ name : "create secret - transient error" ,
176+ stack : "dev-usw2" ,
177+ component : "app/service" ,
178+ key : "config-key" ,
179+ value : "test-value" ,
180+ mockFn : gsmClientSecretCreationMock (
181+ "projects/test-project" ,
182+ "test-prefix_dev_usw2_app_service_config-key" ,
183+ `"test-value"` ,
184+ fmt .Errorf ("transient error: %w" , ErrTransientError ),
185+ ),
192186 wantErr : true ,
193187 },
194188 {
@@ -197,47 +191,54 @@ func TestGSMStore_Set(t *testing.T) {
197191 component : "app/service" ,
198192 key : "config-key" ,
199193 value : "test-value" ,
200- mockFn : func (m * MockGSMClient ) {
201- m .On ("CreateSecret" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.CreateSecretRequest ) bool {
202- expectedReq := & secretmanagerpb.CreateSecretRequest {
203- Parent : "projects/test-project" ,
204- SecretId : "test-prefix_dev_usw2_app_service_config-key" ,
205- Secret : & secretmanagerpb.Secret {
206- Replication : & secretmanagerpb.Replication {
207- Replication : & secretmanagerpb.Replication_Automatic_ {
208- Automatic : & secretmanagerpb.Replication_Automatic {},
209- },
210- },
211- },
212- }
213- return req .Parent == expectedReq .Parent &&
214- req .SecretId == expectedReq .SecretId &&
215- req .Secret .GetReplication ().GetAutomatic () != nil
216- })).Return (& secretmanagerpb.Secret {
217- Name : "projects/test-project/secrets/test-prefix_dev_usw2_app_service_config-key" ,
218- }, nil )
219-
220- m .On ("AddSecretVersion" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.AddSecretVersionRequest ) bool {
221- expectedReq := & secretmanagerpb.AddSecretVersionRequest {
222- Parent : "projects/test-project/secrets/test-prefix_dev_usw2_app_service_config-key" ,
223- Payload : & secretmanagerpb.SecretPayload {
224- Data : []byte ("test-value" ),
225- },
226- }
227- return req .Parent == expectedReq .Parent &&
228- string (req .Payload .Data ) == string (expectedReq .Payload .Data )
229- })).Return (nil , fmt .Errorf ("internal error: %w" , ErrInternalError ))
230- },
194+ mockFn : gsmClientSecretCreationMock (
195+ "projects/test-project" ,
196+ "test-prefix_dev_usw2_app_service_config-key" ,
197+ `"test-value"` ,
198+ fmt .Errorf ("internal error: %w" , ErrInternalError ),
199+ ),
231200 wantErr : true ,
232201 },
233202 {
234- name : "invalid value type " ,
203+ name : "successful set with int " ,
235204 stack : "dev-usw2" ,
236205 component : "app/service" ,
237206 key : "config-key" ,
238- value : 123 , // Not a string
239- mockFn : func (m * MockGSMClient ) {},
240- wantErr : true ,
207+ value : 123 ,
208+ mockFn : gsmClientSecretCreationMock (
209+ "projects/test-project" ,
210+ "test-prefix_dev_usw2_app_service_config-key" ,
211+ `123` ,
212+ nil ,
213+ ),
214+ wantErr : false ,
215+ },
216+ {
217+ name : "successful_set_with_slice" ,
218+ stack : "dev_usw2" ,
219+ component : "app/service" ,
220+ key : "slice-key" ,
221+ value : []string {"value1" , "value2" , "value3" },
222+ mockFn : gsmClientSecretCreationMock (
223+ "projects/test-project" ,
224+ "test-prefix_dev_usw2_app_service_slice-key" ,
225+ `["value1","value2","value3"]` ,
226+ nil ,
227+ ),
228+ },
229+ {
230+ name : "successful_set_with_map" ,
231+ stack : "dev_usw2" ,
232+ component : "app/service" ,
233+ key : "map-key" ,
234+ value : map [string ]interface {}{"key1" : "value1" , "key2" : 42 , "key3" : true },
235+
236+ mockFn : gsmClientSecretCreationMock (
237+ "projects/test-project" ,
238+ "test-prefix_dev_usw2_app_service_map-key" ,
239+ `{"key1":"value1","key2":42,"key3":true}` ,
240+ nil ,
241+ ),
241242 },
242243 {
243244 name : "empty stack" ,
@@ -319,7 +320,27 @@ func TestGSMStore_Get(t *testing.T) {
319320 return req .Name == expectedReq .Name
320321 })).Return (& secretmanagerpb.AccessSecretVersionResponse {
321322 Payload : & secretmanagerpb.SecretPayload {
322- Data : []byte ("test-value" ),
323+ Data : []byte (`"test-value"` ),
324+ },
325+ }, nil )
326+ },
327+ want : "test-value" ,
328+ wantErr : false ,
329+ },
330+ {
331+ name : "successful get - legacy value without json" ,
332+ stack : "dev-usw2" ,
333+ component : "app/service" ,
334+ key : "config-key" ,
335+ mockFn : func (m * MockGSMClient ) {
336+ m .On ("AccessSecretVersion" , mock .Anything , mock .MatchedBy (func (req * secretmanagerpb.AccessSecretVersionRequest ) bool {
337+ expectedReq := & secretmanagerpb.AccessSecretVersionRequest {
338+ Name : "projects/test-project/secrets/test-prefix_dev_usw2_app_service_config-key/versions/latest" ,
339+ }
340+ return req .Name == expectedReq .Name
341+ })).Return (& secretmanagerpb.AccessSecretVersionResponse {
342+ Payload : & secretmanagerpb.SecretPayload {
343+ Data : []byte (`test-value` ),
323344 },
324345 }, nil )
325346 },
0 commit comments