Skip to content

Commit 7f1781b

Browse files
Project: Images Service Gen2 (#560)
* new: Add support for Images Gen. 2 (#526) * WIP oops * Add unit test case * Drop go.work.sum from source tree * oops * Add tags to ImageUploadOptions * Separate ImageStatus from ImageRegionStatus * Fix tests; add WaitForImageRegionStatus * image replication test with upload image; use getRegionsWithCaps when available * modified replication tests to use uploaded image; use random regions when available * fix fixtures * clean up * sanitize fixture * revert ipv6 pool fixture change --------- Co-authored-by: Lena Garber <[email protected]>
1 parent a405118 commit 7f1781b

File tree

76 files changed

+11919
-8108
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+11919
-8108
lines changed

images.go

+82-37
Original file line numberDiff line numberDiff line change
@@ -20,37 +20,69 @@ const (
2020
ImageStatusAvailable ImageStatus = "available"
2121
)
2222

23+
// ImageRegionStatus represents the status of an Image's replica.
24+
type ImageRegionStatus string
25+
26+
// ImageRegionStatus options start with ImageRegionStatus and
27+
// include all Image replica statuses
28+
const (
29+
ImageRegionStatusAvailable ImageRegionStatus = "available"
30+
ImageRegionStatusCreating ImageRegionStatus = "creating"
31+
ImageRegionStatusPending ImageRegionStatus = "pending"
32+
ImageRegionStatusPendingReplication ImageRegionStatus = "pending replication"
33+
ImageRegionStatusPendingDeletion ImageRegionStatus = "pending deletion"
34+
ImageRegionStatusReplicating ImageRegionStatus = "replicating"
35+
)
36+
37+
// ImageRegion represents the status of an Image object in a given Region.
38+
type ImageRegion struct {
39+
Region string `json:"region"`
40+
Status ImageRegionStatus `json:"status"`
41+
}
42+
2343
// Image represents a deployable Image object for use with Linode Instances
2444
type Image struct {
25-
ID string `json:"id"`
26-
CreatedBy string `json:"created_by"`
27-
Capabilities []string `json:"capabilities"`
28-
Label string `json:"label"`
29-
Description string `json:"description"`
30-
Type string `json:"type"`
31-
Vendor string `json:"vendor"`
32-
Status ImageStatus `json:"status"`
33-
Size int `json:"size"`
34-
IsPublic bool `json:"is_public"`
35-
Deprecated bool `json:"deprecated"`
36-
Updated *time.Time `json:"-"`
37-
Created *time.Time `json:"-"`
38-
Expiry *time.Time `json:"-"`
39-
EOL *time.Time `json:"-"`
45+
ID string `json:"id"`
46+
CreatedBy string `json:"created_by"`
47+
Capabilities []string `json:"capabilities"`
48+
Label string `json:"label"`
49+
Description string `json:"description"`
50+
Type string `json:"type"`
51+
Vendor string `json:"vendor"`
52+
Status ImageStatus `json:"status"`
53+
Size int `json:"size"`
54+
TotalSize int `json:"total_size"`
55+
IsPublic bool `json:"is_public"`
56+
Deprecated bool `json:"deprecated"`
57+
Regions []ImageRegion `json:"regions"`
58+
Tags []string `json:"tags"`
59+
60+
Updated *time.Time `json:"-"`
61+
Created *time.Time `json:"-"`
62+
Expiry *time.Time `json:"-"`
63+
EOL *time.Time `json:"-"`
4064
}
4165

4266
// ImageCreateOptions fields are those accepted by CreateImage
4367
type ImageCreateOptions struct {
44-
DiskID int `json:"disk_id"`
45-
Label string `json:"label"`
46-
Description string `json:"description,omitempty"`
47-
CloudInit bool `json:"cloud_init,omitempty"`
68+
DiskID int `json:"disk_id"`
69+
Label string `json:"label"`
70+
Description string `json:"description,omitempty"`
71+
CloudInit bool `json:"cloud_init,omitempty"`
72+
Tags *[]string `json:"tags,omitempty"`
4873
}
4974

5075
// ImageUpdateOptions fields are those accepted by UpdateImage
5176
type ImageUpdateOptions struct {
52-
Label string `json:"label,omitempty"`
53-
Description *string `json:"description,omitempty"`
77+
Label string `json:"label,omitempty"`
78+
Description *string `json:"description,omitempty"`
79+
Tags *[]string `json:"tags,omitempty"`
80+
}
81+
82+
// ImageReplicateOptions represents the options accepted by the
83+
// ReplicateImage(...) function.
84+
type ImageReplicateOptions struct {
85+
Regions []string `json:"regions"`
5486
}
5587

5688
// ImageCreateUploadResponse fields are those returned by CreateImageUpload
@@ -61,18 +93,20 @@ type ImageCreateUploadResponse struct {
6193

6294
// ImageCreateUploadOptions fields are those accepted by CreateImageUpload
6395
type ImageCreateUploadOptions struct {
64-
Region string `json:"region"`
65-
Label string `json:"label"`
66-
Description string `json:"description,omitempty"`
67-
CloudInit bool `json:"cloud_init,omitempty"`
96+
Region string `json:"region"`
97+
Label string `json:"label"`
98+
Description string `json:"description,omitempty"`
99+
CloudInit bool `json:"cloud_init,omitempty"`
100+
Tags *[]string `json:"tags,omitempty"`
68101
}
69102

70103
// ImageUploadOptions fields are those accepted by UploadImage
71104
type ImageUploadOptions struct {
72-
Region string `json:"region"`
73-
Label string `json:"label"`
74-
Description string `json:"description,omitempty"`
75-
CloudInit bool `json:"cloud_init"`
105+
Region string `json:"region"`
106+
Label string `json:"label"`
107+
Description string `json:"description,omitempty"`
108+
CloudInit bool `json:"cloud_init"`
109+
Tags *[]string `json:"tags,omitempty"`
76110
Image io.Reader
77111
}
78112

@@ -109,7 +143,7 @@ func (i Image) GetUpdateOptions() (iu ImageUpdateOptions) {
109143
return
110144
}
111145

112-
// ListImages lists Images
146+
// ListImages lists Images.
113147
func (c *Client) ListImages(ctx context.Context, opts *ListOptions) ([]Image, error) {
114148
return getPaginatedResults[Image](
115149
ctx,
@@ -119,7 +153,7 @@ func (c *Client) ListImages(ctx context.Context, opts *ListOptions) ([]Image, er
119153
)
120154
}
121155

122-
// GetImage gets the Image with the provided ID
156+
// GetImage gets the Image with the provided ID.
123157
func (c *Client) GetImage(ctx context.Context, imageID string) (*Image, error) {
124158
return doGETRequest[Image](
125159
ctx,
@@ -128,7 +162,7 @@ func (c *Client) GetImage(ctx context.Context, imageID string) (*Image, error) {
128162
)
129163
}
130164

131-
// CreateImage creates an Image
165+
// CreateImage creates an Image.
132166
func (c *Client) CreateImage(ctx context.Context, opts ImageCreateOptions) (*Image, error) {
133167
return doPOSTRequest[Image](
134168
ctx,
@@ -138,7 +172,7 @@ func (c *Client) CreateImage(ctx context.Context, opts ImageCreateOptions) (*Ima
138172
)
139173
}
140174

141-
// UpdateImage updates the Image with the specified id
175+
// UpdateImage updates the Image with the specified id.
142176
func (c *Client) UpdateImage(ctx context.Context, imageID string, opts ImageUpdateOptions) (*Image, error) {
143177
return doPUTRequest[Image](
144178
ctx,
@@ -148,7 +182,17 @@ func (c *Client) UpdateImage(ctx context.Context, imageID string, opts ImageUpda
148182
)
149183
}
150184

151-
// DeleteImage deletes the Image with the specified id
185+
// ReplicateImage replicates an image to a given set of regions.
186+
func (c *Client) ReplicateImage(ctx context.Context, imageID string, opts ImageReplicateOptions) (*Image, error) {
187+
return doPOSTRequest[Image](
188+
ctx,
189+
c,
190+
formatAPIPath("images/%s/regions", imageID),
191+
opts,
192+
)
193+
}
194+
195+
// DeleteImage deletes the Image with the specified id.
152196
func (c *Client) DeleteImage(ctx context.Context, imageID string) error {
153197
return doDELETERequest(
154198
ctx,
@@ -157,7 +201,7 @@ func (c *Client) DeleteImage(ctx context.Context, imageID string) error {
157201
)
158202
}
159203

160-
// CreateImageUpload creates an Image and an upload URL
204+
// CreateImageUpload creates an Image and an upload URL.
161205
func (c *Client) CreateImageUpload(ctx context.Context, opts ImageCreateUploadOptions) (*Image, string, error) {
162206
result, err := doPOSTRequest[ImageCreateUploadResponse](
163207
ctx,
@@ -172,7 +216,7 @@ func (c *Client) CreateImageUpload(ctx context.Context, opts ImageCreateUploadOp
172216
return result.Image, result.UploadTo, nil
173217
}
174218

175-
// UploadImageToURL uploads the given image to the given upload URL
219+
// UploadImageToURL uploads the given image to the given upload URL.
176220
func (c *Client) UploadImageToURL(ctx context.Context, uploadURL string, image io.Reader) error {
177221
// Linode-specific headers do not need to be sent to this endpoint
178222
req := resty.New().SetDebug(c.resty.Debug).R().
@@ -187,13 +231,14 @@ func (c *Client) UploadImageToURL(ctx context.Context, uploadURL string, image i
187231
return err
188232
}
189233

190-
// UploadImage creates and uploads an image
234+
// UploadImage creates and uploads an image.
191235
func (c *Client) UploadImage(ctx context.Context, opts ImageUploadOptions) (*Image, error) {
192236
image, uploadURL, err := c.CreateImageUpload(ctx, ImageCreateUploadOptions{
193237
Label: opts.Label,
194238
Region: opts.Region,
195239
Description: opts.Description,
196240
CloudInit: opts.CloudInit,
241+
Tags: opts.Tags,
197242
})
198243
if err != nil {
199244
return nil, err

test/integration/fixtures/TestAccountAvailability_Get.yaml

+7-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ interactions:
2727
- '*'
2828
Access-Control-Expose-Headers:
2929
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
30+
Akamai-Internal-Account:
31+
- '*'
3032
Cache-Control:
3133
- max-age=0, no-cache, no-store
3234
Connection:
@@ -38,7 +40,7 @@ interactions:
3840
Content-Type:
3941
- application/json
4042
Expires:
41-
- Mon, 17 Jun 2024 15:46:53 GMT
43+
- Thu, 25 Jul 2024 17:44:02 GMT
4244
Pragma:
4345
- no-cache
4446
Strict-Transport-Security:
@@ -54,7 +56,10 @@ interactions:
5456
- DENY
5557
- DENY
5658
X-Oauth-Scopes:
57-
- '*'
59+
- account:read_write databases:read_write domains:read_write events:read_write
60+
firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write
61+
longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write
62+
volumes:read_write vpc:read_write
5863
X-Ratelimit-Limit:
5964
- "400"
6065
X-Xss-Protection:

test/integration/fixtures/TestAccountAvailability_List.yaml

+24-8
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ interactions:
3131
["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"], "unavailable":
3232
[]}, {"region": "ap-southeast", "available": ["Linodes", "NodeBalancers", "Block
3333
Storage", "Kubernetes"], "unavailable": []}, {"region": "us-iad", "available":
34-
["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"], "unavailable":
35-
[]}, {"region": "us-ord", "available": ["Linodes", "NodeBalancers", "Block Storage",
34+
["Linodes", "NodeBalancers", "Block Storage"], "unavailable": ["Kubernetes"]},
35+
{"region": "us-ord", "available": ["Linodes", "NodeBalancers", "Block Storage",
3636
"Kubernetes"], "unavailable": []}, {"region": "fr-par", "available": ["Linodes",
3737
"NodeBalancers", "Block Storage", "Kubernetes"], "unavailable": []}, {"region":
3838
"us-sea", "available": ["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"],
@@ -50,10 +50,21 @@ interactions:
5050
"Kubernetes"], "unavailable": []}, {"region": "id-cgk", "available": ["Linodes",
5151
"NodeBalancers", "Block Storage", "Kubernetes"], "unavailable": []}, {"region":
5252
"us-lax", "available": ["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"],
53-
"unavailable": []}, {"region": "gb-lon", "available": ["Linodes", "NodeBalancers",
54-
"Block Storage", "Kubernetes"], "unavailable": []}, {"region": "au-mel", "available":
55-
["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"], "unavailable":
56-
[]}], "page": 1, "pages": 1, "results": 27}'
53+
"unavailable": []}, {"region": "us-den-edge-1", "available": ["Linodes"], "unavailable":
54+
["NodeBalancers", "Block Storage", "Kubernetes"]}, {"region": "de-ham-edge-1",
55+
"available": ["Linodes"], "unavailable": ["NodeBalancers", "Block Storage",
56+
"Kubernetes"]}, {"region": "fr-mrs-edge-1", "available": ["Linodes"], "unavailable":
57+
["NodeBalancers", "Block Storage", "Kubernetes"]}, {"region": "za-jnb-edge-1",
58+
"available": ["Linodes"], "unavailable": ["NodeBalancers", "Block Storage",
59+
"Kubernetes"]}, {"region": "my-kul-edge-1", "available": ["Linodes"], "unavailable":
60+
["NodeBalancers", "Block Storage", "Kubernetes"]}, {"region": "co-bog-edge-1",
61+
"available": ["Linodes"], "unavailable": ["NodeBalancers", "Block Storage",
62+
"Kubernetes"]}, {"region": "mx-qro-edge-1", "available": ["Linodes"], "unavailable":
63+
["NodeBalancers", "Block Storage", "Kubernetes"]}, {"region": "us-hou-edge-1",
64+
"available": ["Linodes"], "unavailable": ["NodeBalancers", "Block Storage",
65+
"Kubernetes"]}, {"region": "cl-scl-edge-1", "available": ["Linodes"], "unavailable":
66+
["NodeBalancers", "Block Storage", "Kubernetes"]}], "page": 1, "pages": 1, "results":
67+
34}'
5768
headers:
5869
Access-Control-Allow-Credentials:
5970
- "true"
@@ -65,6 +76,8 @@ interactions:
6576
- '*'
6677
Access-Control-Expose-Headers:
6778
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
79+
Akamai-Internal-Account:
80+
- '*'
6881
Cache-Control:
6982
- max-age=0, no-cache, no-store
7083
Connection:
@@ -74,7 +87,7 @@ interactions:
7487
Content-Type:
7588
- application/json
7689
Expires:
77-
- Mon, 17 Jun 2024 15:46:53 GMT
90+
- Thu, 25 Jul 2024 17:44:02 GMT
7891
Pragma:
7992
- no-cache
8093
Strict-Transport-Security:
@@ -91,7 +104,10 @@ interactions:
91104
- DENY
92105
- DENY
93106
X-Oauth-Scopes:
94-
- '*'
107+
- account:read_write databases:read_write domains:read_write events:read_write
108+
firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write
109+
longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write
110+
volumes:read_write vpc:read_write
95111
X-Ratelimit-Limit:
96112
- "400"
97113
X-Xss-Protection:

0 commit comments

Comments
 (0)