Skip to content

Commit 930367f

Browse files
authored
Merge pull request #256 from andrewsomething/asb/custom-images
Add support of importing custom images.
2 parents 9ff1137 + ddbdce6 commit 930367f

3 files changed

Lines changed: 113 additions & 0 deletions

File tree

digitalocean/Image.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,46 @@
11
# -*- coding: utf-8 -*-
22
from .baseapi import BaseAPI, POST, DELETE, PUT, NotFoundError
33

4+
45
class Image(BaseAPI):
6+
"""
7+
An object representing an DigitalOcean Image.
8+
9+
Attributes accepted at creation time:
10+
11+
Args:
12+
name (str): The name to be given to an image.
13+
url (str): A URL from which the virtual machine image may be retrieved.
14+
region (str): The slug of the region where the image will be available.
15+
distribution (str, optional): The name of the image's distribution.
16+
description (str, optional): Free-form text field to describe an image.
17+
tags (obj:`list` of `str`, optional): List of tag names to apply to
18+
the image.
19+
20+
Attributes returned by API:
21+
22+
id (int): A unique number to identify and reference a image.
23+
name (str): The display name given to an image.
24+
type (str): The kind of image. This will be either "snapshot",
25+
"backup", or "custom".
26+
distribution (str): The name of the image's distribution.
27+
slug (str): A uniquely identifying string that is associated with each
28+
of the DigitalOcean-provided public images.
29+
public (bool): Indicates whether the image is public or not.
30+
regions (obj:`list` of `str`): A list of the slugs of the regions where
31+
the image is available for use.
32+
created_at (str): A time value given in ISO8601 combined date and time
33+
format that represents when the image was created.
34+
min_disk_size (int): The minimum disk size in GB required for a Droplet
35+
to use this image.
36+
size_gigabytes (int): The size of the image in gigabytes.
37+
description (str): Free-form text field to describing an image.
38+
tags (obj:`list` of `str`): List of tag names to applied to the image.
39+
status (str): Indicates the state of a custom image. This may be "NEW",
40+
"available", "pending", or "deleted".
41+
error_message (str): Information about errors that may occur when
42+
importing a custom image.
43+
"""
544
def __init__(self, *args, **kwargs):
645
self.id = None
746
self.name = None
@@ -12,6 +51,12 @@ def __init__(self, *args, **kwargs):
1251
self.regions = []
1352
self.created_at = None
1453
self.size_gigabytes = None
54+
self.description = None
55+
self.status = None
56+
self.tags = []
57+
self.error_message = None
58+
self.url = None
59+
self.region = None
1560

1661
super(Image, self).__init__(*args, **kwargs)
1762

@@ -45,6 +90,26 @@ def _is_string(value):
4590
else:
4691
return None
4792

93+
def create(self):
94+
"""
95+
Creates a new custom DigitalOcean Image from the Linux virtual machine
96+
image located at the provided `url`.
97+
"""
98+
params = {'name': self.name,
99+
'region': self.region,
100+
'url': self.url,
101+
'distribution': self.distribution,
102+
'description': self.description,
103+
'tags': self.tags}
104+
105+
data = self.get_data('images', type=POST, params=params)
106+
107+
if data:
108+
for attr in data['image'].keys():
109+
setattr(self, attr, data['image'][attr])
110+
111+
return self
112+
48113
def load(self, use_slug=False):
49114
"""
50115
Load slug.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"image": {
3+
"created_at": "2018-09-20T19:28:00Z",
4+
"description": "Cloud-optimized image",
5+
"distribution": "Ubuntu",
6+
"error_message": "",
7+
"id": 38413969,
8+
"name": "ubuntu-18.04-minimal",
9+
"regions": [
10+
11+
],
12+
"type": "custom",
13+
"tags": [
14+
"base-image",
15+
"prod"
16+
],
17+
"status": "NEW"
18+
}
19+
}

digitalocean/tests/test_image.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,35 @@ def test_load_by_slug(self):
6464
self.assertEqual(self.image_with_slug.size_gigabytes, 2.34)
6565
self.assertEqual(self.image_with_slug.min_disk_size, 30)
6666

67+
@responses.activate
68+
def test_create(self):
69+
data = self.load_from_file('images/create.json')
70+
url = self.base_url + "images"
71+
72+
responses.add(responses.POST,
73+
url,
74+
body=data,
75+
status=202,
76+
content_type='application/json')
77+
78+
image = digitalocean.Image(name='ubuntu-18.04-minimal',
79+
url='https://www.example.com/cloud.img',
80+
distribution='Ubuntu',
81+
region='nyc3',
82+
description='Cloud-optimized image',
83+
tags=['base-image', 'prod'],
84+
token=self.token)
85+
image.create()
86+
87+
self.assertEqual(image.id, 38413969)
88+
self.assertEqual(image.name, 'ubuntu-18.04-minimal')
89+
self.assertEqual(image.distribution, 'Ubuntu')
90+
self.assertEqual(image.type, 'custom')
91+
self.assertEqual(image.status, 'NEW')
92+
self.assertEqual(image.description, 'Cloud-optimized image')
93+
self.assertEqual(image.tags, ['base-image', 'prod'])
94+
self.assertEqual(image.created_at, '2018-09-20T19:28:00Z')
95+
6796
@responses.activate
6897
def test_destroy(self):
6998
responses.add(responses.DELETE,

0 commit comments

Comments
 (0)