Skip to content

Commit 40136ab

Browse files
author
Clark Perkins
committed
Finshed merge of upstream/master
2 parents fd4fb39 + 08fdc7b commit 40136ab

File tree

11 files changed

+607
-359
lines changed

11 files changed

+607
-359
lines changed

stackdio/client/__init__.py

Lines changed: 21 additions & 332 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,27 @@
11
import json
22
import logging
3-
import os
43

5-
from .http import HttpMixin, use_admin_auth, endpoint
6-
from .exceptions import StackException
4+
from .http import use_admin_auth, endpoint
5+
from .exceptions import BlueprintException, StackException
6+
7+
from .blueprint import BlueprintMixin
8+
from .formula import FormulaMixin
9+
from .profile import ProfileMixin
10+
from .provider import ProviderMixin
11+
from .region import RegionMixin
12+
from .settings import SettingsMixin
13+
from .stack import StackMixin
14+
15+
from .version import _parse_version_string
716

817
logger = logging.getLogger(__name__)
918

1019

11-
class StackdIO(HttpMixin):
20+
class StackdIO(BlueprintMixin, FormulaMixin, ProfileMixin,
21+
ProviderMixin, RegionMixin, StackMixin, SettingsMixin):
1222

13-
def __init__(self,
14-
protocol="https",
15-
host="localhost",
16-
port=443,
17-
base_url=None,
18-
auth=None,
19-
auth_admin=None,
23+
def __init__(self, protocol="https", host="localhost", port=443,
24+
base_url=None, auth=None, auth_admin=None,
2025
verify=False):
2126
"""auth_admin is optional, only needed for creating provider, profile,
2227
and base security groups"""
@@ -33,112 +38,16 @@ def __init__(self,
3338
self.auth = auth
3439
self.auth_admin = auth_admin
3540

41+
_, self.version = _parse_version_string(self.get_version())
42+
3643
@endpoint("")
3744
def get_root(self):
3845
"""Get the api root"""
3946
return self._get(endpoint, jsonify=True)
4047

41-
42-
@use_admin_auth
43-
@endpoint("providers/")
44-
def create_provider(self, **kwargs):
45-
"""Create a provider"""
46-
47-
form_data = {
48-
"title": None,
49-
"account_id": None,
50-
"provider_type": None,
51-
"access_key_id": None,
52-
"secret_access_key": None,
53-
"keypair": None,
54-
"security_groups": None,
55-
"route53_domain": None,
56-
"default_availability_zone": None,
57-
"private_key": None
58-
}
59-
60-
for key in form_data.keys():
61-
form_data[key] = kwargs.get(key)
62-
63-
return self._post(endpoint, data=json.dumps(form_data), jsonify=True)
64-
65-
66-
@endpoint("providers/")
67-
def get_provider(self, title, provider_name):
68-
"""Look for and return a provider"""
69-
70-
result = self._get(endpoint, jsonify=True)
71-
for provider in result['results']:
72-
if provider.get("title") == title and \
73-
provider.get("provider_type_name") == provider_name:
74-
75-
return provider
76-
77-
raise StackException("Provider %s not found" % title)
78-
79-
80-
@use_admin_auth
81-
@endpoint("providers/")
82-
def create_profile(self, title, image_id, ssh_user, cloud_provider,
83-
default_instance_size=None):
84-
"""Create a profile"""
85-
data = {
86-
"title": title,
87-
"image_id": image_id,
88-
"ssh_user": ssh_user,
89-
"cloud_provider": cloud_provider,
90-
"default_instance_size": default_instance_size
91-
}
92-
return self._post(endpoint, data=json.dumps(data), jsonify=True)
93-
94-
95-
@endpoint("profiles/")
96-
def get_profile(self, title, cloud_provider):
97-
"""Look for and return a profile"""
98-
99-
result = self._get(endpoint, jsonify=True)
100-
101-
for profile in result['results']:
102-
if profile.get("title") == title and \
103-
profile.get("cloud_provider") == cloud_provider:
104-
return profile
105-
106-
return None
107-
108-
109-
@endpoint("formulas/")
110-
def import_formula(self, formula_uri, public=True):
111-
"""Import a formula"""
112-
data = {
113-
"uri": formula_uri,
114-
"public": public,
115-
}
116-
return self._post(endpoint, data=json.dumps(data), jsonify=True)
117-
118-
119-
@endpoint("blueprints/")
120-
def create_blueprint(self, blueprint, provider="ec2"):
121-
"""Create a blueprint"""
122-
123-
# check the provided blueprint to see if we need to look up any ids
124-
for host in blueprint["hosts"]:
125-
if isinstance(host["size"], str):
126-
host["size"] = self.get_instance_id(host["size"], provider)
127-
128-
if isinstance(host["zone"], str):
129-
host["zone"] = self.get_zone(host["zone"], provider)
130-
131-
if isinstance(host["cloud_profile"], str):
132-
host["cloud_profile"] = self.get_profile_id(host["cloud_profile"])
133-
134-
for component in host["formula_components"]:
135-
if isinstance(component["id"], (tuple, list)):
136-
component["id"] = self.get_component_id(
137-
self.get_formula(component["id"][0]),
138-
component["id"][1])
139-
140-
return self._post(endpoint, data=json.dumps(blueprint), jsonify=True)
141-
48+
@endpoint("version/")
49+
def get_version(self):
50+
return self._get(endpoint, jsonify=True)['version']
14251

14352
@endpoint("blueprints/{blueprint_id}/")
14453
def delete_blueprint(self, blueprint_id):
@@ -161,7 +70,6 @@ def create_security_group(self, name, description, cloud_provider, is_default=Tr
16170
}
16271
return self._post(endpoint, data=json.dumps(data), jsonify=True)
16372

164-
16573
@endpoint("settings/")
16674
def get_public_key(self):
16775
"""Get the public key for the logged in uesr"""
@@ -182,140 +90,6 @@ def set_public_key(self, public_key):
18290
}
18391
return self._put(endpoint, data=json.dumps(data), jsonify=True)
18492

185-
186-
@endpoint("formulas/")
187-
def get_formulas(self):
188-
"""Return all formulas"""
189-
return self._get(endpoint, jsonify=True)['results']
190-
191-
192-
def get_formula(self, title):
193-
"""Get a formula that matches title"""
194-
195-
for formula in self.get_formulas():
196-
if formula.get("title") == title:
197-
return formula
198-
199-
raise StackException("Formula %s not found" % title)
200-
201-
202-
def get_formula_id(self, title):
203-
"""Get the id for a formula that matches title. If component_title is
204-
provided, find and return the component id"""
205-
206-
formula = self.get_formula(title)
207-
return formula.get("id")
208-
209-
210-
def get_component_id(self, formula, component_title):
211-
"""Get the id for a component from formula_id that matches title"""
212-
213-
for component in formula.get("components"):
214-
if component.get("title") == component_title:
215-
return component.get("id")
216-
217-
raise StackException("Component %s not found for formula %s" %
218-
(component_title, formula.get("title")))
219-
220-
221-
@endpoint("providers/")
222-
def get_provider_id(self, slug, title=False):
223-
"""Get the id for a provider that matches slug. If title is True will
224-
look at title instead."""
225-
226-
result = self._get(endpoint, jsonify=True)
227-
228-
for provider in result['results']:
229-
if provider.get("slug" if not title else "title") == slug:
230-
return provider.get("id")
231-
232-
raise StackException("Provider %s not found" % slug)
233-
234-
235-
@endpoint("profiles/")
236-
def get_profile_id(self, slug, title=False):
237-
"""Get the id for a profile that matches slug. If title is True will look
238-
at title instead."""
239-
240-
result = self._get(endpoint, jsonify=True)
241-
242-
for profile in result['results']:
243-
if profile.get("slug" if not title else "title") == slug:
244-
return profile.get("id")
245-
246-
return StackException("Provider %s not found" % slug)
247-
248-
249-
@endpoint("stacks/")
250-
def get_stacks(self):
251-
"""Return a list of all stacks"""
252-
return self._get(endpoint, jsonify=True)['results']
253-
254-
255-
@endpoint("stacks/{stack_id}/")
256-
def get_stack(self, stack_id):
257-
"""Get stack info"""
258-
result = self._get(endpoint, none_on_404=True, jsonify=True)
259-
if result is None:
260-
raise StackException("Stack %s not found" % stack_id)
261-
else:
262-
return result
263-
264-
265-
@endpoint("stacks/{stack_id}/history/")
266-
def get_stack_history(self, stack_id):
267-
"""Get stack info"""
268-
result = self._get(endpoint, none_on_404=True, jsonify=True)
269-
if result is None:
270-
raise StackException("Stack %s not found" % stack_id)
271-
else:
272-
return result
273-
274-
275-
@endpoint("stacks/")
276-
def get_stack_id(self, title):
277-
"""Find a stack id"""
278-
279-
result = self._get(endpoint, jsonify=True)
280-
try:
281-
for stack in result['results']:
282-
if stack.get("title") == title:
283-
return stack.get("id")
284-
except TypeError, e:
285-
logger.error("Error querying stacks: %s", e)
286-
287-
raise StackException("Stack %s not found" % title)
288-
289-
290-
@endpoint("stacks/{stack_id}/hosts/")
291-
def get_stack_hosts(self, stack_id):
292-
"""Get a list of all stack hosts"""
293-
return self._get(endpoint, jsonify=True)['results']
294-
295-
296-
@endpoint("blueprints/")
297-
def get_blueprints(self):
298-
"""Returns all the blueprints"""
299-
return self._get(endpoint, jsonify=True)['results']
300-
301-
302-
@endpoint("blueprints/{blueprint_id}/")
303-
def get_blueprint(self, blueprint_id):
304-
"""Return info for a specific blueprint_id"""
305-
return self._get(endpoint, jsonify=True)
306-
307-
308-
@endpoint("blueprints/")
309-
def get_blueprint_id(self, title):
310-
"""Get the id for a blueprint that matches title"""
311-
result = self._get(endpoint, params={"title": title}, jsonify=True)
312-
313-
if not result.get('count') == 1:
314-
raise StackException("Blueprint %s not found" % title)
315-
316-
return result['results'][0]['id']
317-
318-
31993
@endpoint("instance_sizes/")
32094
def get_instance_id(self, instance_id, provider_type="ec2"):
32195
"""Get the id for an instance_id. The instance_id parameter is the
@@ -330,88 +104,3 @@ def get_instance_id(self, instance_id, provider_type="ec2"):
330104

331105
raise StackException("Instance type %s from provider %s not found" %
332106
(instance_id, provider_type))
333-
334-
335-
@endpoint("provider_types/")
336-
def get_provider_type(self, type_name):
337-
"""Get the id for the provider specified by type_name"""
338-
339-
result = self._get(endpoint, jsonify=True)
340-
for provider_type in result['results']:
341-
if provider_type.get("type_name") == type_name:
342-
return provider_type.get("id")
343-
344-
raise StackException("Provider type %s not found" % type_name)
345-
346-
347-
@endpoint("zones/")
348-
def get_zone(self, title, type_name="ec2"):
349-
"""Get a zone id for title"""
350-
351-
provider_type = self.get_provider_type(type_name)
352-
result = self._get(endpoint, jsonify=True)
353-
for zone in result['results']:
354-
if zone.get("title") == title and \
355-
zone.get("provider_type") == provider_type:
356-
return zone.get("id")
357-
358-
raise StackException("Zone %s not found for %s" % (title, type_name))
359-
360-
361-
@endpoint("stacks/")
362-
def launch_stack(self, stack_data):
363-
"""Launch a stack as described by stack_data"""
364-
return self._post(endpoint, data=json.dumps(stack_data), jsonify=True)
365-
366-
367-
@endpoint("stacks/{stack_id}/hosts/")
368-
def describe_hosts(self, stack_id, key="fqdn", ec2=False):
369-
"""Retrieve a list of info about a stack. Defaults to the id for each
370-
host, but you can specify any available key. Setting ec2=True will
371-
force it to inspect the ec2_metadata field."""
372-
373-
EC2 = "ec2_metadata"
374-
result = self._get(endpoint, jsonify=True)
375-
376-
stack_details = []
377-
378-
for host in result['results']:
379-
if not ec2:
380-
host_details = host.get(key)
381-
else:
382-
host_details = host.get(EC2).get(key)
383-
384-
if host_details:
385-
stack_details.append(host_details)
386-
387-
if stack_details:
388-
return stack_details
389-
390-
raise StackException("Key %s for stack %s not available" % (key, stack_id))
391-
392-
393-
@endpoint("stacks/{stack_id}/")
394-
def delete_stack(self, stack_id):
395-
"""Destructively delete a stack forever."""
396-
# make sure the stack exists
397-
self.get_stack(stack_id)
398-
return self._delete(endpoint, jsonify=True)
399-
400-
401-
@endpoint("stacks/{stack_id}/action/")
402-
def get_valid_actions(self, stack_id):
403-
return self._get(endpoint, jsonify=True)['available_actions']
404-
405-
406-
@endpoint("stacks/{stack_id}/action/")
407-
def do_action(self, stack_id, action):
408-
"""Execute an action on a stack"""
409-
valid_actions = self.get_valid_actions(stack_id)
410-
411-
if action not in valid_actions:
412-
raise StackException("Invalid action, must be one of %s" %
413-
", ".join(valid_actions))
414-
415-
data = {"action": action}
416-
417-
return self._post(endpoint, data=json.dumps(data), jsonify=True)

0 commit comments

Comments
 (0)