Improve test coverage, clean operations
diff --git a/gstack/__init__.py b/gstack/__init__.py
index c4e0c6e..0624553 100644
--- a/gstack/__init__.py
+++ b/gstack/__init__.py
@@ -75,6 +75,7 @@
def configure_app(settings=None):
app.config['DATA'] = os.path.abspath(os.path.dirname(__file__)) + '/data'
+ app.config['PATH'] = 'compute/v1/projects/'
db.init_app(app)
diff --git a/gstack/configure.py b/gstack/configure.py
index d67cf73..242e901 100644
--- a/gstack/configure.py
+++ b/gstack/configure.py
@@ -19,16 +19,16 @@
import os
import argparse
-import ConfigParser
from alembic import command
+from ConfigParser import SafeConfigParser
from alembic.config import Config as AlembicConfig
def main():
config_folder = _create_config_folder()
- _create_config_file(config_folder)
_create_database()
+ _create_config_file(config_folder)
def _create_config_folder():
@@ -66,7 +66,7 @@
def _modify_config_profile(config_file, profile):
- config = ConfigParser.SafeConfigParser()
+ config = SafeConfigParser()
config.read(config_file)
if not config.has_section(profile):
diff --git a/gstack/controllers/instances.py b/gstack/controllers/instances.py
index 7ea1139..4694b14 100755
--- a/gstack/controllers/instances.py
+++ b/gstack/controllers/instances.py
@@ -184,13 +184,11 @@
return errors.resource_not_found(func_route)
else:
- populated_response = operations.create_response(
+ return helpers.create_response(operations.create_async_response(
projectid=projectid,
operationid=deployment_result['deployvirtualmachineresponse']['jobid'],
authorization=authorization
- )
-
- return helpers.create_response(data=populated_response)
+ ))
@app.route('/compute/v1/projects/<projectid>/zones/<zone>/instances/<instance>', methods=['DELETE'])
@@ -209,10 +207,8 @@
authorization.client_secret
)
- populated_response = operations.create_response(
+ return helpers.create_response(operations.create_async_response(
projectid=projectid,
operationid=deletion_result['destroyvirtualmachineresponse']['jobid'],
authorization=authorization
- )
-
- return helpers.create_response(data=populated_response)
+ ))
diff --git a/gstack/controllers/operations.py b/gstack/controllers/operations.py
index 048595d..361c277 100644
--- a/gstack/controllers/operations.py
+++ b/gstack/controllers/operations.py
@@ -38,34 +38,35 @@
return cloudstack_response
-def _delete_instance_response(async_result, projectid):
- populated_response = {
- 'kind': 'compute#operation',
- 'insertTime': async_result['created'],
- 'operationType': 'delete',
- 'name': async_result['jobid'],
- 'startTime': async_result['created'],
- 'selfLink': urllib.unquote_plus(helpers.get_root_url() + url_for(
+def _get_instance_async_response(async_result, projectid, type):
+ response = {}
+ response['kind'] = 'compute#operation'
+ response['id'] = async_result['jobid']
+ response['operationType'] = type
+ response['name'] = async_result['jobid']
+ response['insertTime'] = async_result['created']
+ response['startTime'] = async_result['created']
+ response['selfLink'] = urllib.unquote_plus(
+ helpers.get_root_url() + url_for(
'getoperations',
projectid=projectid,
operationid=async_result['jobid']
))
- }
if async_result['jobstatus'] is 0:
- populated_response['targetLink'] = ''
- populated_response['status'] = 'PENDING'
- populated_response['progress'] = 0
+ response['targetLink'] = ''
+ response['status'] = 'PENDING'
+ response['progress'] = 0
elif async_result['jobstatus'] is 1:
- populated_response['status'] = 'DONE'
- populated_response['zone'] = urllib.unquote_plus(
+ response['status'] = 'DONE'
+ response['zone'] = urllib.unquote_plus(
helpers.get_root_url() +
url_for(
'getzone',
projectid=projectid,
zone=async_result['jobresult']['virtualmachine']['zonename'],
))
- populated_response['targetLink'] = urllib.unquote_plus(
+ response['targetLink'] = urllib.unquote_plus(
helpers.get_root_url() +
url_for(
'getinstance',
@@ -73,6 +74,26 @@
zone=async_result['jobresult']['virtualmachine']['zonename'],
instance=async_result['jobresult']['virtualmachine']['name']))
+ return response
+
+
+def _delete_instance_response(async_result, projectid):
+ populated_response = _get_instance_async_response(async_result, projectid, 'delete')
+ return populated_response
+
+
+def _create_instance_response(async_result, projectid, authorization):
+ populated_response = _get_instance_async_response(async_result, projectid, 'insert')
+ populated_response['user'] = async_result['userid']
+
+ if async_result['jobstatus'] is 1:
+ _add_sshkey_metadata(
+ authorization=authorization,
+ publickey=publickey_storage[projectid],
+ instanceid=async_result['jobresult']['virtualmachine']['id']
+ )
+ print populated_response
+
return populated_response
@@ -82,7 +103,6 @@
split_publickey = [l[i:i + n] for i in range(0, len(l), n)]
i = 0
for datasegment in split_publickey:
- print datasegment
_add_sshkey_metadata_segment(
authorization, str(i) + '-sshkey-segment', datasegment, instanceid)
i = i + 1
@@ -105,55 +125,7 @@
)
-def _create_instance_response(async_result, projectid, authorization):
- populated_response = {
- 'kind': 'compute#operation',
- 'id': async_result['jobid'],
- 'operationType': 'insert',
- 'name': async_result['jobid'],
- 'user': async_result['userid'],
- 'insertTime': async_result['created'],
- 'startTime': async_result['created'],
- 'selfLink': urllib.unquote_plus(helpers.get_root_url() + url_for(
- 'getoperations',
- projectid=projectid,
- operationid=async_result['jobid']
- ))
- }
-
- if async_result['jobstatus'] is 0:
- # handle pending case
- populated_response['targetLink'] = ''
- populated_response['status'] = 'PENDING'
- populated_response['progress'] = 0
- elif async_result['jobstatus'] is 1:
- # handle successful case
- populated_response['status'] = 'DONE'
- populated_response['id'] = async_result['jobid']
- populated_response['zone'] = urllib.unquote_plus(
- helpers.get_root_url() +
- url_for(
- 'getzone',
- projectid=projectid,
- zone=async_result['jobresult']['virtualmachine']['zonename'],
- ))
- populated_response['targetLink'] = urllib.unquote_plus(
- helpers.get_root_url() +
- url_for(
- 'getinstance',
- projectid=projectid,
- zone=async_result['jobresult']['virtualmachine']['zonename'],
- instance=async_result['jobresult']['virtualmachine']['name']))
- _add_sshkey_metadata(
- authorization=authorization,
- publickey=publickey_storage[projectid],
- instanceid=async_result['jobresult']['virtualmachine']['id']
- )
-
- return populated_response
-
-
-def create_response(authorization, projectid, operationid):
+def create_async_response(authorization, projectid, operationid):
async_result = _get_async_result(
authorization=authorization,
args={'jobId': operationid}
@@ -184,7 +156,7 @@
@app.route('/compute/v1/projects/<projectid>/global/operations/<operationid>', methods=['GET'])
@authentication.required
def getoperations(authorization, operationid, projectid):
- return helpers.create_response(create_response(
+ return helpers.create_response(create_async_response(
authorization=authorization,
operationid=operationid,
projectid=projectid
diff --git a/setup.py b/setup.py
index 13600cf..770e70d 100755
--- a/setup.py
+++ b/setup.py
@@ -36,27 +36,32 @@
return open(os.path.join(os.path.dirname(__file__), fname)).read().strip()
setup(
- name="gstack",
+ name='gstack',
version=VERSION,
- description="A GCE interface to Apache CloudStack",
- author="Ian Duffy, Darren Brogan, Sebastien Goasguen",
- author_email="ian@ianduffy.ie, brogand93@darrenbrogan.ie, runseb@gmail.com",
- long_description="A Google Compute Engine compliant interface to the Apache CloudStack API",
- url="https://github.com/NOPping/gstack",
- platforms=("Any"),
- license="LICENSE.txt",
- package_data={'': ['LICENSE.txt', 'data/*'],
- 'ec2stack': ['templates/*.json']},
+ description='A GCE interface to Apache CloudStack',
+ author='Ian Duffy, Darren Brogan, Sebastien Goasguen',
+ author_email='ian@ianduffy.ie, brogand93@darrenbrogan.ie, runseb@gmail.com',
+ long_description='A Google Compute Engine compliant interface to the Apache CloudStack API',
+ url='https://github.com/NOPping/gstack',
+ platforms=('Any'),
+ license='LICENSE.txt',
+ package_data={'': ['LICENSE.txt', 'data/*', 'migrations/*']},
packages=[
- "gstack", "gstack.controllers", "gstack.models",
- "gstack.services", "gstack.data", "pyoauth2"],
+ 'gstack',
+ 'gstack.controllers',
+ 'gstack.models',
+ 'gstack.services',
+ 'gstack.data',
+ 'pyoauth2',
+ 'migrations'],
+ include_package_data=True,
install_requires=[
- "requests==0.14",
- "pycrypto==2.6",
- "pyopenssl",
- "Flask-SQLAlchemy",
- "flask",
- "alembic"
+ 'requests==0.14',
+ 'pycrypto==2.6',
+ 'pyopenssl',
+ 'Flask-SQLAlchemy',
+ 'flask',
+ 'alembic'
],
classifiers=[
'Development Status :: 3 - Alpha',
diff --git a/tests/data/destroy_vm_async_pending.json b/tests/data/destroy_vm_async_pending.json
new file mode 100644
index 0000000..65ec50c
--- /dev/null
+++ b/tests/data/destroy_vm_async_pending.json
@@ -0,0 +1,14 @@
+{
+ "queryasyncjobresultresponse": {
+ "jobprocstatus": 0,
+ "created": "2014-06-23T22:24:21+0200",
+ "cmd": "org.apache.cloudstack.api.command.user.vm.DestroyVMCmd",
+ "userid": "26a772da-dc25-4f2b-b0f1-e095e3717a30",
+ "jobstatus": 0,
+ "jobid": "678bbff2-3e45-4c6a-af5c-0859b8ab8170",
+ "jobresultcode": 0,
+ "jobinstanceid": "35de6b8f-8155-4843-bd84-dec137ff784e",
+ "jobinstancetype": "VirtualMachine",
+ "accountid": "ddbdf378-e8d9-47e0-964b-661d0d8414b8"
+ }
+}
diff --git a/tests/operations_tests.py b/tests/operations_tests.py
new file mode 100644
index 0000000..ac6ccb1
--- /dev/null
+++ b/tests/operations_tests.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+import mock
+
+from gstack.helpers import read_file
+from . import GStackAppTestCase
+
+class OperationsTestCase(GStackAppTestCase):
+
+ def test_query_operation(self):
+ get = mock.Mock()
+ get.return_value.text = read_file('tests/data/destroy_vm_async_pending.json')
+ get.return_value.status_code = 200
+
+ with mock.patch('requests.get', get):
+ headers = {'authorization': 'Bearer ' + str(GStackAppTestCase.access_token)}
+ response = self.get('/compute/v1/projects/exampleproject/global/operations/exampleoperation', headers=headers)
+
+ self.assert_ok(response)
\ No newline at end of file
diff --git a/tests/settings.py b/tests/settings.py
index 278c50d..e6f93ed 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -1,4 +1,3 @@
-PATH = 'compute/v1/projects/'
GSTACK_BIND_ADDRESS = 'localhost'
GSTACK_PORT = '5000'
CLOUDSTACK_HOST = 'api.exoscale.ch'