@@ -31,7 +31,7 @@ func ResourceProjectAPIKey() *schema.Resource {
31
31
Schema : map [string ]* schema.Schema {
32
32
"project_id" : {
33
33
Type : schema .TypeString ,
34
- Required : true ,
34
+ Optional : true ,
35
35
},
36
36
"api_key_id" : {
37
37
Type : schema .TypeString ,
@@ -79,42 +79,41 @@ type APIProjectAssignmentKeyInput struct {
79
79
RoleNames []string `json:"roles,omitempty"`
80
80
}
81
81
82
+ const errorNoProjectAssignmentDefined = "could not obtain a project id as no assignments are defined"
83
+
82
84
func resourceMongoDBAtlasProjectAPIKeyCreate (ctx context.Context , d * schema.ResourceData , meta any ) diag.Diagnostics {
83
85
conn := meta .(* config.MongoDBClient ).Atlas
84
- projectID := d .Get ("project_id" ).(string )
85
- createRequest := new (matlas.APIKeyInput )
86
86
87
87
var apiKey * matlas.APIKey
88
88
var err error
89
89
var resp * matlas.Response
90
90
91
+ createRequest := new (matlas.APIKeyInput )
91
92
createRequest .Desc = d .Get ("description" ).(string )
92
93
if projectAssignments , ok := d .GetOk ("project_assignment" ); ok {
93
94
projectAssignmentList := ExpandProjectAssignmentSet (projectAssignments .(* schema.Set ))
94
- for _ , apiKeyList := range projectAssignmentList {
95
- if apiKeyList .ProjectID == projectID {
96
- createRequest .Roles = apiKeyList .RoleNames
97
- apiKey , resp , err = conn .ProjectAPIKeys .Create (ctx , projectID , createRequest )
98
- if err != nil {
99
- if resp != nil && resp .StatusCode == http .StatusNotFound {
100
- d .SetId ("" )
101
- return nil
102
- }
103
- }
95
+
96
+ // creates api key using project id of first defined project assignment
97
+ firstAssignment := projectAssignmentList [0 ]
98
+ createRequest .Roles = firstAssignment .RoleNames
99
+ apiKey , resp , err = conn .ProjectAPIKeys .Create (ctx , firstAssignment .ProjectID , createRequest )
100
+ if err != nil {
101
+ if resp != nil && resp .StatusCode == http .StatusNotFound {
102
+ d .SetId ("" )
103
+ return nil
104
104
}
105
105
}
106
106
107
- for _ , apiKeyList := range projectAssignmentList {
108
- if apiKeyList .ProjectID != projectID {
109
- createRequest .Roles = apiKeyList .RoleNames
110
- _ , err := conn .ProjectAPIKeys .Assign (ctx , apiKeyList .ProjectID , apiKey .ID , & matlas.AssignAPIKey {
111
- Roles : createRequest .Roles ,
112
- })
113
- if err != nil {
114
- if resp != nil && resp .StatusCode == http .StatusNotFound {
115
- d .SetId ("" )
116
- return nil
117
- }
107
+ // assign created api key to remaining project assignments
108
+ for _ , apiKeyList := range projectAssignmentList [1 :] {
109
+ createRequest .Roles = apiKeyList .RoleNames
110
+ _ , err := conn .ProjectAPIKeys .Assign (ctx , apiKeyList .ProjectID , apiKey .ID , & matlas.AssignAPIKey {
111
+ Roles : createRequest .Roles ,
112
+ })
113
+ if err != nil {
114
+ if resp != nil && resp .StatusCode == http .StatusNotFound {
115
+ d .SetId ("" )
116
+ return nil
118
117
}
119
118
}
120
119
}
@@ -128,8 +127,12 @@ func resourceMongoDBAtlasProjectAPIKeyCreate(ctx context.Context, d *schema.Reso
128
127
return diag .FromErr (fmt .Errorf ("error setting `private_key`: %s" , err ))
129
128
}
130
129
130
+ firstProjectID , err := getFirstProjectIDFromAssignments (d )
131
+ if err != nil {
132
+ return diag .FromErr (fmt .Errorf ("could not obtain a project id from state: %s" , err ))
133
+ }
131
134
d .SetId (conversion .EncodeStateID (map [string ]string {
132
- "project_id" : projectID ,
135
+ "project_id" : * firstProjectID , // defined to avoid breaking changes (preserve id format), can be removed when root project_id is removed.
133
136
"api_key_id" : apiKey .ID ,
134
137
}))
135
138
@@ -140,10 +143,14 @@ func resourceMongoDBAtlasProjectAPIKeyRead(ctx context.Context, d *schema.Resour
140
143
// Get client connection.
141
144
conn := meta .(* config.MongoDBClient ).Atlas
142
145
ids := conversion .DecodeStateID (d .Id ())
143
- projectID := ids ["project_id" ]
144
146
apiKeyID := ids ["api_key_id" ]
145
147
146
- projectAPIKeys , _ , err := conn .ProjectAPIKeys .List (ctx , projectID , nil )
148
+ firstProjectID , err := getFirstProjectIDFromAssignments (d )
149
+ if err != nil {
150
+ return diag .FromErr (fmt .Errorf ("could not obtain a project id from state: %s" , err ))
151
+ }
152
+
153
+ projectAPIKeys , _ , err := conn .ProjectAPIKeys .List (ctx , * firstProjectID , nil )
147
154
if err != nil {
148
155
return diag .FromErr (fmt .Errorf ("error getting api key information: %s" , err ))
149
156
}
@@ -168,7 +175,7 @@ func resourceMongoDBAtlasProjectAPIKeyRead(ctx context.Context, d *schema.Resour
168
175
169
176
if projectAssignments , err := newProjectAssignment (ctx , conn , apiKeyID ); err == nil {
170
177
if err := d .Set ("project_assignment" , projectAssignments ); err != nil {
171
- return diag .Errorf (ErrorProjectSetting , `created` , projectID , err )
178
+ return diag .Errorf ("error setting `project_assignment` : %s" , err )
172
179
}
173
180
}
174
181
}
@@ -178,15 +185,6 @@ func resourceMongoDBAtlasProjectAPIKeyRead(ctx context.Context, d *schema.Resour
178
185
return nil
179
186
}
180
187
181
- if err := d .Set ("project_id" , projectID ); err != nil {
182
- return diag .FromErr (fmt .Errorf ("error setting `project_id`: %s" , err ))
183
- }
184
-
185
- d .SetId (conversion .EncodeStateID (map [string ]string {
186
- "project_id" : projectID ,
187
- "api_key_id" : apiKeyID ,
188
- }))
189
-
190
188
return nil
191
189
}
192
190
@@ -195,7 +193,6 @@ func resourceMongoDBAtlasProjectAPIKeyUpdate(ctx context.Context, d *schema.Reso
195
193
connV2 := meta .(* config.MongoDBClient ).AtlasV2
196
194
197
195
ids := conversion .DecodeStateID (d .Id ())
198
- projectID := ids ["project_id" ]
199
196
apiKeyID := ids ["api_key_id" ]
200
197
201
198
if d .HasChange ("project_assignment" ) {
@@ -241,9 +238,14 @@ func resourceMongoDBAtlasProjectAPIKeyUpdate(ctx context.Context, d *schema.Reso
241
238
}
242
239
}
243
240
241
+ firstProjectID , err := getFirstProjectIDFromAssignments (d )
242
+ if err != nil {
243
+ return diag .FromErr (fmt .Errorf ("could not obtain a project id from state: %s" , err ))
244
+ }
245
+
244
246
if d .HasChange ("description" ) {
245
247
newDescription := d .Get ("description" ).(string )
246
- if _ , _ , err := connV2 .ProgrammaticAPIKeysApi .UpdateApiKeyRoles (ctx , projectID , apiKeyID , & admin.UpdateAtlasProjectApiKey {
248
+ if _ , _ , err := connV2 .ProgrammaticAPIKeysApi .UpdateApiKeyRoles (ctx , * firstProjectID , apiKeyID , & admin.UpdateAtlasProjectApiKey {
247
249
Desc : & newDescription ,
248
250
}).Execute (); err != nil {
249
251
return diag .Errorf ("error updating description in api key(%s): %s" , apiKeyID , err )
@@ -256,11 +258,15 @@ func resourceMongoDBAtlasProjectAPIKeyUpdate(ctx context.Context, d *schema.Reso
256
258
func resourceMongoDBAtlasProjectAPIKeyDelete (ctx context.Context , d * schema.ResourceData , meta any ) diag.Diagnostics {
257
259
conn := meta .(* config.MongoDBClient ).Atlas
258
260
ids := conversion .DecodeStateID (d .Id ())
259
- projectID := ids ["project_id" ]
260
261
apiKeyID := ids ["api_key_id" ]
261
262
var orgID string
262
263
263
- projectAPIKeys , _ , err := conn .ProjectAPIKeys .List (ctx , projectID , nil )
264
+ firstProjectID , err := getFirstProjectIDFromAssignments (d )
265
+ if err != nil {
266
+ return diag .FromErr (fmt .Errorf ("could not obtain a project id from state: %s" , err ))
267
+ }
268
+
269
+ projectAPIKeys , _ , err := conn .ProjectAPIKeys .List (ctx , * firstProjectID , nil )
264
270
if err != nil {
265
271
return diag .FromErr (fmt .Errorf ("error getting api key information: %s" , err ))
266
272
}
@@ -275,28 +281,20 @@ func resourceMongoDBAtlasProjectAPIKeyDelete(ctx context.Context, d *schema.Reso
275
281
}
276
282
}
277
283
278
- _ , roleOk := d .GetOk ("role_names" )
279
- if ! roleOk {
280
- options := & matlas.ListOptions {}
284
+ options := & matlas.ListOptions {}
281
285
282
- apiKeyOrgList , _ , err := conn .Root .List (ctx , options )
283
- if err != nil {
284
- return diag .FromErr (fmt .Errorf ("error getting api key information: %s" , err ))
285
- }
286
+ apiKeyOrgList , _ , err := conn .Root .List (ctx , options )
287
+ if err != nil {
288
+ return diag .FromErr (fmt .Errorf ("error getting api key information: %s" , err ))
289
+ }
286
290
287
- projectAssignments , err := getAPIProjectAssignments (ctx , conn , apiKeyOrgList , apiKeyID )
288
- if err != nil {
289
- return diag .FromErr (fmt .Errorf ("error getting api key information: %s" , err ))
290
- }
291
+ projectAssignments , err := getAPIProjectAssignments (ctx , conn , apiKeyOrgList , apiKeyID )
292
+ if err != nil {
293
+ return diag .FromErr (fmt .Errorf ("error getting api key information: %s" , err ))
294
+ }
291
295
292
- for _ , apiKey := range projectAssignments {
293
- _ , err = conn .ProjectAPIKeys .Unassign (ctx , apiKey .ProjectID , apiKeyID )
294
- if err != nil {
295
- return diag .FromErr (fmt .Errorf ("error deleting project api key: %s" , err ))
296
- }
297
- }
298
- } else {
299
- _ , err = conn .ProjectAPIKeys .Unassign (ctx , projectID , apiKeyID )
296
+ for _ , apiKey := range projectAssignments {
297
+ _ , err = conn .ProjectAPIKeys .Unassign (ctx , apiKey .ProjectID , apiKeyID )
300
298
if err != nil {
301
299
return diag .FromErr (fmt .Errorf ("error deleting project api key: %s" , err ))
302
300
}
@@ -316,7 +314,7 @@ func resourceMongoDBAtlasProjectAPIKeyImportState(ctx context.Context, d *schema
316
314
317
315
parts := strings .SplitN (d .Id (), "-" , 2 )
318
316
if len (parts ) != 2 {
319
- return nil , errors .New ("import format error: to import a api key use the format {org_id }-{api_key_id}" )
317
+ return nil , errors .New ("import format error: to import a api key use the format {project_id }-{api_key_id}" )
320
318
}
321
319
322
320
projectID := parts [0 ]
@@ -336,6 +334,12 @@ func resourceMongoDBAtlasProjectAPIKeyImportState(ctx context.Context, d *schema
336
334
return nil , fmt .Errorf ("error setting `public_key`: %s" , err )
337
335
}
338
336
337
+ if projectAssignments , err := newProjectAssignment (ctx , conn , apiKeyID ); err == nil {
338
+ if err := d .Set ("project_assignment" , projectAssignments ); err != nil {
339
+ return nil , fmt .Errorf ("error setting `project_assignment`: %s" , err )
340
+ }
341
+ }
342
+
339
343
d .SetId (conversion .EncodeStateID (map [string ]string {
340
344
"project_id" : projectID ,
341
345
"api_key_id" : val .ID ,
@@ -345,6 +349,17 @@ func resourceMongoDBAtlasProjectAPIKeyImportState(ctx context.Context, d *schema
345
349
return []* schema.ResourceData {d }, nil
346
350
}
347
351
352
+ func getFirstProjectIDFromAssignments (d * schema.ResourceData ) (* string , error ) {
353
+ if projectAssignments , ok := d .GetOk ("project_assignment" ); ok {
354
+ projectAssignmentList := ExpandProjectAssignmentSet (projectAssignments .(* schema.Set ))
355
+ if len (projectAssignmentList ) < 1 {
356
+ return nil , errors .New (errorNoProjectAssignmentDefined )
357
+ }
358
+ return admin .PtrString (projectAssignmentList [0 ].ProjectID ), nil // can safely assume at least one assigment is defined because of schema definition
359
+ }
360
+ return nil , errors .New (errorNoProjectAssignmentDefined )
361
+ }
362
+
348
363
func flattenProjectAPIKeyRoles (projectID string , apiKeyRoles []matlas.AtlasRole ) []string {
349
364
if len (apiKeyRoles ) == 0 {
350
365
return nil
0 commit comments