@@ -6,6 +6,7 @@ package sagemaker
6
6
import (
7
7
"context"
8
8
"log"
9
+ "strconv"
9
10
10
11
"github.com/YakDriver/regexache"
11
12
"github.com/aws/aws-sdk-go-v2/aws"
@@ -20,21 +21,34 @@ import (
20
21
"github.com/hashicorp/terraform-provider-aws/internal/enum"
21
22
"github.com/hashicorp/terraform-provider-aws/internal/errs"
22
23
"github.com/hashicorp/terraform-provider-aws/internal/errs/sdkdiag"
24
+ "github.com/hashicorp/terraform-provider-aws/internal/flex"
23
25
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
24
26
"github.com/hashicorp/terraform-provider-aws/names"
25
27
)
26
28
29
+ const imageVersionResourcePartCount = 2
30
+
27
31
// @SDKResource("aws_sagemaker_image_version", name="Image Version")
28
32
func resourceImageVersion () * schema.Resource {
29
33
return & schema.Resource {
30
34
CreateWithoutTimeout : resourceImageVersionCreate ,
31
35
ReadWithoutTimeout : resourceImageVersionRead ,
32
36
UpdateWithoutTimeout : resourceImageVersionUpdate ,
33
37
DeleteWithoutTimeout : resourceImageVersionDelete ,
38
+
34
39
Importer : & schema.ResourceImporter {
35
40
StateContext : schema .ImportStatePassthroughContext ,
36
41
},
37
42
43
+ StateUpgraders : []schema.StateUpgrader {
44
+ {
45
+ Type : resourceImageVersionV0 ().CoreConfigSchema ().ImpliedType (),
46
+ Upgrade : imageVersionStateUpgradeV0 ,
47
+ Version : 0 ,
48
+ },
49
+ },
50
+
51
+ SchemaVersion : 1 ,
38
52
Schema : map [string ]* schema.Schema {
39
53
names .AttrARN : {
40
54
Type : schema .TypeString ,
@@ -105,7 +119,7 @@ func resourceImageVersionCreate(ctx context.Context, d *schema.ResourceData, met
105
119
conn := meta .(* conns.AWSClient ).SageMakerClient (ctx )
106
120
107
121
name := d .Get ("image_name" ).(string )
108
- input := & sagemaker.CreateImageVersionInput {
122
+ input := sagemaker.CreateImageVersionInput {
109
123
ImageName : aws .String (name ),
110
124
BaseImage : aws .String (d .Get ("base_image" ).(string )),
111
125
ClientToken : aws .String (id .UniqueId ()),
@@ -139,25 +153,37 @@ func resourceImageVersionCreate(ctx context.Context, d *schema.ResourceData, met
139
153
input .ProgrammingLang = aws .String (v .(string ))
140
154
}
141
155
142
- _ , err := conn .CreateImageVersion (ctx , input )
143
- if err != nil {
156
+ if _ , err := conn .CreateImageVersion (ctx , & input ); err != nil {
144
157
return sdkdiag .AppendErrorf (diags , "creating SageMaker AI Image Version %s: %s" , name , err )
145
158
}
146
159
147
- d .SetId (name )
148
-
149
- if _ , err := waitImageVersionCreated (ctx , conn , d .Id ()); err != nil {
160
+ out , err := waitImageVersionCreated (ctx , conn , name )
161
+ if err != nil {
150
162
return sdkdiag .AppendErrorf (diags , "waiting for SageMaker AI Image Version (%s) to be created: %s" , d .Id (), err )
151
163
}
152
164
165
+ parts := []string {name , strconv .Itoa (int (aws .ToInt32 (out .Version )))}
166
+ id , err := flex .FlattenResourceId (parts , imageVersionResourcePartCount , false )
167
+ if err != nil {
168
+ return sdkdiag .AppendErrorf (diags , "creating SageMaker AI Image Version %s: %s" , name , err )
169
+ }
170
+
171
+ d .SetId (id )
172
+
153
173
return append (diags , resourceImageVersionRead (ctx , d , meta )... )
154
174
}
155
175
156
176
func resourceImageVersionRead (ctx context.Context , d * schema.ResourceData , meta any ) diag.Diagnostics {
157
177
var diags diag.Diagnostics
158
178
conn := meta .(* conns.AWSClient ).SageMakerClient (ctx )
159
179
160
- image , err := findImageVersionByName (ctx , conn , d .Id ())
180
+ name , version , err := expandImageVersionResourceID (d .Id ())
181
+ if err != nil {
182
+ return sdkdiag .AppendErrorf (diags , "reading SageMaker AI Image Version (%s): %s" , d .Id (), err )
183
+ }
184
+ d .Set ("image_name" , name ) // to support import
185
+
186
+ image , err := findImageVersionByTwoPartKey (ctx , conn , name , version )
161
187
162
188
if ! d .IsNewResource () && tfresource .NotFound (err ) {
163
189
d .SetId ("" )
@@ -174,7 +200,6 @@ func resourceImageVersionRead(ctx context.Context, d *schema.ResourceData, meta
174
200
d .Set ("image_arn" , image .ImageArn )
175
201
d .Set ("container_image" , image .ContainerImage )
176
202
d .Set (names .AttrVersion , image .Version )
177
- d .Set ("image_name" , d .Id ())
178
203
d .Set ("horovod" , image .Horovod )
179
204
d .Set ("job_type" , image .JobType )
180
205
d .Set ("processor" , image .Processor )
@@ -190,9 +215,12 @@ func resourceImageVersionUpdate(ctx context.Context, d *schema.ResourceData, met
190
215
var diags diag.Diagnostics
191
216
conn := meta .(* conns.AWSClient ).SageMakerClient (ctx )
192
217
193
- input := & sagemaker.UpdateImageVersionInput {
194
- ImageName : aws .String (d .Id ()),
195
- Version : aws .Int32 (int32 (d .Get (names .AttrVersion ).(int ))),
218
+ name := d .Get ("image_name" ).(string )
219
+ version := d .Get (names .AttrVersion ).(int )
220
+
221
+ input := sagemaker.UpdateImageVersionInput {
222
+ ImageName : aws .String (name ),
223
+ Version : aws .Int32 (int32 (version )),
196
224
}
197
225
198
226
if d .HasChange ("horovod" ) {
@@ -223,7 +251,7 @@ func resourceImageVersionUpdate(ctx context.Context, d *schema.ResourceData, met
223
251
input .ProgrammingLang = aws .String (d .Get ("programming_lang" ).(string ))
224
252
}
225
253
226
- if _ , err := conn .UpdateImageVersion (ctx , input ); err != nil {
254
+ if _ , err := conn .UpdateImageVersion (ctx , & input ); err != nil {
227
255
return sdkdiag .AppendErrorf (diags , "updating SageMaker AI Image Version (%s): %s" , d .Id (), err )
228
256
}
229
257
@@ -234,9 +262,12 @@ func resourceImageVersionDelete(ctx context.Context, d *schema.ResourceData, met
234
262
var diags diag.Diagnostics
235
263
conn := meta .(* conns.AWSClient ).SageMakerClient (ctx )
236
264
265
+ name := d .Get ("image_name" ).(string )
266
+ version := d .Get (names .AttrVersion ).(int )
267
+
237
268
input := & sagemaker.DeleteImageVersionInput {
238
- ImageName : aws .String (d . Id () ),
239
- Version : aws .Int32 (int32 (d . Get ( names . AttrVersion ).( int ) )),
269
+ ImageName : aws .String (name ),
270
+ Version : aws .Int32 (int32 (version )),
240
271
}
241
272
242
273
if _ , err := conn .DeleteImageVersion (ctx , input ); err != nil {
@@ -246,19 +277,24 @@ func resourceImageVersionDelete(ctx context.Context, d *schema.ResourceData, met
246
277
return sdkdiag .AppendErrorf (diags , "deleting SageMaker AI Image Version (%s): %s" , d .Id (), err )
247
278
}
248
279
249
- if _ , err := waitImageVersionDeleted (ctx , conn , d . Id () ); err != nil {
250
- return sdkdiag .AppendErrorf (diags , "waiting for SageMaker AI Image Version (%s) to delete : %s" , d .Id (), err )
280
+ if _ , err := waitImageVersionDeleted (ctx , conn , name , version ); err != nil {
281
+ return sdkdiag .AppendErrorf (diags , "waiting for SageMaker AI Image Version (%s) deletion : %s" , d .Id (), err )
251
282
}
252
283
253
284
return diags
254
285
}
255
286
287
+ // findImageVersionByName is used immediately after creation to poll for status of
288
+ // the most recently created image version
289
+ //
290
+ // findImageVersionByTwoPartKey should be used for all subsequent operations once the
291
+ // version number is assigned.
256
292
func findImageVersionByName (ctx context.Context , conn * sagemaker.Client , name string ) (* sagemaker.DescribeImageVersionOutput , error ) {
257
- input := & sagemaker.DescribeImageVersionInput {
293
+ input := sagemaker.DescribeImageVersionInput {
258
294
ImageName : aws .String (name ),
259
295
}
260
296
261
- output , err := conn .DescribeImageVersion (ctx , input )
297
+ output , err := conn .DescribeImageVersion (ctx , & input )
262
298
263
299
if errs .IsAErrorMessageContains [* awstypes.ResourceNotFound ](err , "does not exist" ) {
264
300
return nil , & retry.NotFoundError {
@@ -277,3 +313,48 @@ func findImageVersionByName(ctx context.Context, conn *sagemaker.Client, name st
277
313
278
314
return output , nil
279
315
}
316
+
317
+ // findImageVersionByTwoPartKey is used to fetch a specific version once a version number
318
+ // is assigned
319
+ func findImageVersionByTwoPartKey (ctx context.Context , conn * sagemaker.Client , name string , version int ) (* sagemaker.DescribeImageVersionOutput , error ) {
320
+ input := sagemaker.DescribeImageVersionInput {
321
+ ImageName : aws .String (name ),
322
+ Version : aws .Int32 (int32 (version )),
323
+ }
324
+
325
+ output , err := conn .DescribeImageVersion (ctx , & input )
326
+
327
+ if errs .IsAErrorMessageContains [* awstypes.ResourceNotFound ](err , "does not exist" ) {
328
+ return nil , & retry.NotFoundError {
329
+ LastError : err ,
330
+ LastRequest : input ,
331
+ }
332
+ }
333
+
334
+ if err != nil {
335
+ return nil , err
336
+ }
337
+
338
+ if output == nil {
339
+ return nil , tfresource .NewEmptyResultError (input )
340
+ }
341
+
342
+ return output , nil
343
+ }
344
+
345
+ // expandImageVersionResourceID wraps flex.ExpandResourceId and handles conversion
346
+ // of the version portion to an integer
347
+ func expandImageVersionResourceID (id string ) (string , int , error ) {
348
+ parts , err := flex .ExpandResourceId (id , imageVersionResourcePartCount , false )
349
+ if err != nil {
350
+ return "" , 0 , err
351
+ }
352
+
353
+ name := parts [0 ]
354
+ version , err := strconv .Atoi (parts [1 ])
355
+ if err != nil {
356
+ return name , version , err
357
+ }
358
+
359
+ return name , version , nil
360
+ }
0 commit comments