Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project: Images Service Gen2 #560

Merged
merged 11 commits into from
Aug 9, 2024
119 changes: 82 additions & 37 deletions images.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,37 +20,69 @@ const (
ImageStatusAvailable ImageStatus = "available"
)

// ImageRegionStatus represents the status of an Image's replica.
type ImageRegionStatus string

// ImageRegionStatus options start with ImageRegionStatus and
// include all Image replica statuses
const (
ImageRegionStatusAvailable ImageRegionStatus = "available"
ImageRegionStatusCreating ImageRegionStatus = "creating"
ImageRegionStatusPending ImageRegionStatus = "pending"
ImageRegionStatusPendingReplication ImageRegionStatus = "pending replication"
ImageRegionStatusPendingDeletion ImageRegionStatus = "pending deletion"
ImageRegionStatusReplicating ImageRegionStatus = "replicating"
)

// ImageRegion represents the status of an Image object in a given Region.
type ImageRegion struct {
Region string `json:"region"`
Status ImageRegionStatus `json:"status"`
}

// Image represents a deployable Image object for use with Linode Instances
type Image struct {
ID string `json:"id"`
CreatedBy string `json:"created_by"`
Capabilities []string `json:"capabilities"`
Label string `json:"label"`
Description string `json:"description"`
Type string `json:"type"`
Vendor string `json:"vendor"`
Status ImageStatus `json:"status"`
Size int `json:"size"`
IsPublic bool `json:"is_public"`
Deprecated bool `json:"deprecated"`
Updated *time.Time `json:"-"`
Created *time.Time `json:"-"`
Expiry *time.Time `json:"-"`
EOL *time.Time `json:"-"`
ID string `json:"id"`
CreatedBy string `json:"created_by"`
Capabilities []string `json:"capabilities"`
Label string `json:"label"`
Description string `json:"description"`
Type string `json:"type"`
Vendor string `json:"vendor"`
Status ImageStatus `json:"status"`
Size int `json:"size"`
TotalSize int `json:"total_size"`
IsPublic bool `json:"is_public"`
Deprecated bool `json:"deprecated"`
Regions []ImageRegion `json:"regions"`
Tags []string `json:"tags"`

Updated *time.Time `json:"-"`
Created *time.Time `json:"-"`
Expiry *time.Time `json:"-"`
EOL *time.Time `json:"-"`
}

// ImageCreateOptions fields are those accepted by CreateImage
type ImageCreateOptions struct {
DiskID int `json:"disk_id"`
Label string `json:"label"`
Description string `json:"description,omitempty"`
CloudInit bool `json:"cloud_init,omitempty"`
DiskID int `json:"disk_id"`
Label string `json:"label"`
Description string `json:"description,omitempty"`
CloudInit bool `json:"cloud_init,omitempty"`
Tags *[]string `json:"tags,omitempty"`
}

// ImageUpdateOptions fields are those accepted by UpdateImage
type ImageUpdateOptions struct {
Label string `json:"label,omitempty"`
Description *string `json:"description,omitempty"`
Label string `json:"label,omitempty"`
Description *string `json:"description,omitempty"`
Tags *[]string `json:"tags,omitempty"`
}

// ImageReplicateOptions represents the options accepted by the
// ReplicateImage(...) function.
type ImageReplicateOptions struct {
Regions []string `json:"regions"`
}

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

// ImageCreateUploadOptions fields are those accepted by CreateImageUpload
type ImageCreateUploadOptions struct {
Region string `json:"region"`
Label string `json:"label"`
Description string `json:"description,omitempty"`
CloudInit bool `json:"cloud_init,omitempty"`
Region string `json:"region"`
Label string `json:"label"`
Description string `json:"description,omitempty"`
CloudInit bool `json:"cloud_init,omitempty"`
Tags *[]string `json:"tags,omitempty"`
}

// ImageUploadOptions fields are those accepted by UploadImage
type ImageUploadOptions struct {
Region string `json:"region"`
Label string `json:"label"`
Description string `json:"description,omitempty"`
CloudInit bool `json:"cloud_init"`
Region string `json:"region"`
Label string `json:"label"`
Description string `json:"description,omitempty"`
CloudInit bool `json:"cloud_init"`
Tags *[]string `json:"tags,omitempty"`
Image io.Reader
}

Expand Down Expand Up @@ -109,7 +143,7 @@ func (i Image) GetUpdateOptions() (iu ImageUpdateOptions) {
return
}

// ListImages lists Images
// ListImages lists Images.
func (c *Client) ListImages(ctx context.Context, opts *ListOptions) ([]Image, error) {
return getPaginatedResults[Image](
ctx,
Expand All @@ -119,7 +153,7 @@ func (c *Client) ListImages(ctx context.Context, opts *ListOptions) ([]Image, er
)
}

// GetImage gets the Image with the provided ID
// GetImage gets the Image with the provided ID.
func (c *Client) GetImage(ctx context.Context, imageID string) (*Image, error) {
return doGETRequest[Image](
ctx,
Expand All @@ -128,7 +162,7 @@ func (c *Client) GetImage(ctx context.Context, imageID string) (*Image, error) {
)
}

// CreateImage creates an Image
// CreateImage creates an Image.
func (c *Client) CreateImage(ctx context.Context, opts ImageCreateOptions) (*Image, error) {
return doPOSTRequest[Image](
ctx,
Expand All @@ -138,7 +172,7 @@ func (c *Client) CreateImage(ctx context.Context, opts ImageCreateOptions) (*Ima
)
}

// UpdateImage updates the Image with the specified id
// UpdateImage updates the Image with the specified id.
func (c *Client) UpdateImage(ctx context.Context, imageID string, opts ImageUpdateOptions) (*Image, error) {
return doPUTRequest[Image](
ctx,
Expand All @@ -148,7 +182,17 @@ func (c *Client) UpdateImage(ctx context.Context, imageID string, opts ImageUpda
)
}

// DeleteImage deletes the Image with the specified id
// ReplicateImage replicates an image to a given set of regions.
func (c *Client) ReplicateImage(ctx context.Context, imageID string, opts ImageReplicateOptions) (*Image, error) {
return doPOSTRequest[Image](
ctx,
c,
formatAPIPath("images/%s/regions", imageID),
opts,
)
}

// DeleteImage deletes the Image with the specified id.
func (c *Client) DeleteImage(ctx context.Context, imageID string) error {
return doDELETERequest(
ctx,
Expand All @@ -157,7 +201,7 @@ func (c *Client) DeleteImage(ctx context.Context, imageID string) error {
)
}

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

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

// UploadImage creates and uploads an image
// UploadImage creates and uploads an image.
func (c *Client) UploadImage(ctx context.Context, opts ImageUploadOptions) (*Image, error) {
image, uploadURL, err := c.CreateImageUpload(ctx, ImageCreateUploadOptions{
Label: opts.Label,
Region: opts.Region,
Description: opts.Description,
CloudInit: opts.CloudInit,
Tags: opts.Tags,
})
if err != nil {
return nil, err
Expand Down
9 changes: 7 additions & 2 deletions test/integration/fixtures/TestAccountAvailability_Get.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ interactions:
- '*'
Access-Control-Expose-Headers:
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
Akamai-Internal-Account:
- '*'
Cache-Control:
- max-age=0, no-cache, no-store
Connection:
Expand All @@ -38,7 +40,7 @@ interactions:
Content-Type:
- application/json
Expires:
- Mon, 17 Jun 2024 15:46:53 GMT
- Thu, 25 Jul 2024 17:44:02 GMT
Pragma:
- no-cache
Strict-Transport-Security:
Expand All @@ -54,7 +56,10 @@ interactions:
- DENY
- DENY
X-Oauth-Scopes:
- '*'
- account:read_write databases:read_write domains:read_write events:read_write
firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write
longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write
volumes:read_write vpc:read_write
X-Ratelimit-Limit:
- "400"
X-Xss-Protection:
Expand Down
32 changes: 24 additions & 8 deletions test/integration/fixtures/TestAccountAvailability_List.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ interactions:
["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"], "unavailable":
[]}, {"region": "ap-southeast", "available": ["Linodes", "NodeBalancers", "Block
Storage", "Kubernetes"], "unavailable": []}, {"region": "us-iad", "available":
["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"], "unavailable":
[]}, {"region": "us-ord", "available": ["Linodes", "NodeBalancers", "Block Storage",
["Linodes", "NodeBalancers", "Block Storage"], "unavailable": ["Kubernetes"]},
{"region": "us-ord", "available": ["Linodes", "NodeBalancers", "Block Storage",
"Kubernetes"], "unavailable": []}, {"region": "fr-par", "available": ["Linodes",
"NodeBalancers", "Block Storage", "Kubernetes"], "unavailable": []}, {"region":
"us-sea", "available": ["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"],
Expand All @@ -50,10 +50,21 @@ interactions:
"Kubernetes"], "unavailable": []}, {"region": "id-cgk", "available": ["Linodes",
"NodeBalancers", "Block Storage", "Kubernetes"], "unavailable": []}, {"region":
"us-lax", "available": ["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"],
"unavailable": []}, {"region": "gb-lon", "available": ["Linodes", "NodeBalancers",
"Block Storage", "Kubernetes"], "unavailable": []}, {"region": "au-mel", "available":
["Linodes", "NodeBalancers", "Block Storage", "Kubernetes"], "unavailable":
[]}], "page": 1, "pages": 1, "results": 27}'
"unavailable": []}, {"region": "us-den-edge-1", "available": ["Linodes"], "unavailable":
["NodeBalancers", "Block Storage", "Kubernetes"]}, {"region": "de-ham-edge-1",
"available": ["Linodes"], "unavailable": ["NodeBalancers", "Block Storage",
"Kubernetes"]}, {"region": "fr-mrs-edge-1", "available": ["Linodes"], "unavailable":
["NodeBalancers", "Block Storage", "Kubernetes"]}, {"region": "za-jnb-edge-1",
"available": ["Linodes"], "unavailable": ["NodeBalancers", "Block Storage",
"Kubernetes"]}, {"region": "my-kul-edge-1", "available": ["Linodes"], "unavailable":
["NodeBalancers", "Block Storage", "Kubernetes"]}, {"region": "co-bog-edge-1",
"available": ["Linodes"], "unavailable": ["NodeBalancers", "Block Storage",
"Kubernetes"]}, {"region": "mx-qro-edge-1", "available": ["Linodes"], "unavailable":
["NodeBalancers", "Block Storage", "Kubernetes"]}, {"region": "us-hou-edge-1",
"available": ["Linodes"], "unavailable": ["NodeBalancers", "Block Storage",
"Kubernetes"]}, {"region": "cl-scl-edge-1", "available": ["Linodes"], "unavailable":
["NodeBalancers", "Block Storage", "Kubernetes"]}], "page": 1, "pages": 1, "results":
34}'
headers:
Access-Control-Allow-Credentials:
- "true"
Expand All @@ -65,6 +76,8 @@ interactions:
- '*'
Access-Control-Expose-Headers:
- X-OAuth-Scopes, X-Accepted-OAuth-Scopes, X-Status
Akamai-Internal-Account:
- '*'
Cache-Control:
- max-age=0, no-cache, no-store
Connection:
Expand All @@ -74,7 +87,7 @@ interactions:
Content-Type:
- application/json
Expires:
- Mon, 17 Jun 2024 15:46:53 GMT
- Thu, 25 Jul 2024 17:44:02 GMT
Pragma:
- no-cache
Strict-Transport-Security:
Expand All @@ -91,7 +104,10 @@ interactions:
- DENY
- DENY
X-Oauth-Scopes:
- '*'
- account:read_write databases:read_write domains:read_write events:read_write
firewall:read_write images:read_write ips:read_write linodes:read_write lke:read_write
longview:read_write nodebalancers:read_write object_storage:read_write stackscripts:read_write
volumes:read_write vpc:read_write
X-Ratelimit-Limit:
- "400"
X-Xss-Protection:
Expand Down
Loading