Browse files

0.1.1 [Thu Mar 15 19:27:47 EET 2012]

* [TEST] Added basic unittests
  • Loading branch information...
1 parent 0dd20be commit 1165afccf8bcecec2bd00c632bbd6c05b2b42aeb Nikita Savin committed Mar 15, 2012
Showing with 321 additions and 6 deletions.
  1. +1 −0 TODO
  2. +8 −1 doc/source/quickstart.rst
  3. +2 −2 etc/nova-dns/dns-api-paste.ini
  4. +1 −1 nova-dns.spec
  5. +1 −1 nova_dns/__init__.py
  6. +1 −1 nova_dns/dns.py
  7. +36 −0 tests/__init__.py
  8. +127 −0 tests/test_amqp.py
  9. +18 −0 tests/test_auth.py
  10. +126 −0 tests/test_dns.py
View
1 TODO
@@ -1,4 +1,5 @@
* check rpm deps - nova, keystone, ...
+* rename README in README.md
* DNS API
** rest tests
** DNS api docs
View
9 doc/source/quickstart.rst
@@ -103,7 +103,14 @@ setup ns servers:
.. code-block:: bash
LOCALDNS=`perl -e '$ns=1; print join(",", map {sprintf "ns%d:%s", $ns++, $_} split /\s*,\s*/,$ARGV[0])' "$LOCALIP"
- echo "--dns_ns=$LOCALIP" >> $NOVA
+ echo "--dns_ns=$LOCALDNS" >> $NOVA
+
+add service in keystone
+
+.. code-block:: bash
+
+ keystone-manage service add nova_dns nova_dns "DNS for OpenStack"
+ keystone-manage endpointTemplates add RegionOne nova_dns http://$LOCALIP:15353 http://$LOCALIP:15353 http://$LOCALIP:15353 1 1
start service:
View
4 etc/nova-dns/dns-api-paste.ini
@@ -3,8 +3,8 @@ use = egg:Paste#urlmap
/: dns_api001
[pipeline:dns_api001]
-#pipeline = version authtoken dns_app001
-pipeline = version dns_app001
+pipeline = version authtoken dns_app001
+#pipeline = version dns_app001
[app:dns_app001]
paste.app_factory = nova_dns.dns:App.factory
View
2 nova-dns.spec
@@ -5,7 +5,7 @@
%define mod_name nova_dns
Name: nova-dns
-Version: 0.1.0
+Version: 0.1.1
Release: 1
Summary: REST API for DNS configuration and service to add records for fixed ips
License: GNU LGPL v2.1
View
2 nova_dns/__init__.py
@@ -1,5 +1,5 @@
-__version__ = "0.1.0"
+__version__ = "0.1.1"
try:
from nova import flags
View
2 nova_dns/dns.py
@@ -171,7 +171,7 @@ def __init__(self):
GET /zone
return list of all zones
GET /zone/name
- return SSON for SOA if zone exists
+ return JSON for SOA if zone exists
PUT /zone/name[?soa_params]
create new zone. if no params for SOA provided, backend
_has_to_ use reasonable defaults. Return 'ok' on success
View
36 tests/__init__.py
@@ -0,0 +1,36 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Nova Billing
+# Copyright (C) GridDynamics Openstack Core Team, GridDynamics
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+"""
+Base class for Nova Billing unit tests.
+"""
+
+import unittest
+import stubout
+
+
+class TestCase(unittest.TestCase):
+ def setUp(self):
+ """Run before each test method to initialize test environment."""
+ super(TestCase, self).setUp()
+ self.stubs = stubout.StubOutForTesting()
+
+ def tearDown(self):
+ """Runs after each test method to tear down test environment."""
+ self.stubs.UnsetAll()
+ self.stubs.SmartUnsetAll()
View
127 tests/test_amqp.py
@@ -0,0 +1,127 @@
+
+import os
+import sys
+import json
+import datetime
+import unittest
+import stubout
+
+from nova_dns import amqp
+from nova import flags
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+import tests
+
+FLAGS = flags.FLAGS
+
+class TestListener():
+ def event(self, e):
+ self.event = e
+
+class TestCase(tests.TestCase):
+ run_instance_body = {
+ "_context_roles": [
+ "projectmanager"
+ ],
+ "_context_request_id": "29615116-ddd0-4a20-8018-ef5f90f8bdf3",
+ "args": {
+ "request_spec": {
+ "num_instances": 1,
+ "image": {
+ "status": "active",
+ "deleted": False,
+ "container_format": "ami",
+ "updated_at": "2011-12-05 12:15:26.659439",
+ "is_public": True,
+ "deleted_at": None,
+ "properties": {
+ "kernel_id": "2",
+ "owner": None,
+ "min_ram": "0",
+ "ramdisk_id": "1",
+ "min_disk": "0"
+ },
+ "size": 216858624,
+ "name": "SL61",
+ "checksum": "ecd1d23a8039b72812db4fee5a11a547",
+ "created_at": "2011-12-05 12:15:25.541042",
+ "disk_format": "ami",
+ "id": 4,
+ "location": "file:///var/lib/glance/images/4"
+ },
+ "filter": None,
+ "instance_type": {
+ "rxtx_quota": 0,
+ "deleted": False,
+ "updated_at": None,
+ "extra_specs": {},
+ "flavorid": 2,
+ "id": 5,
+ "local_gb": 20,
+ "deleted_at": None,
+ "name": "m1.small",
+ "created_at": None,
+ "memory_mb": 2048,
+ "vcpus": 1,
+ "rxtx_cap": 0,
+ "swap": 0
+ },
+ "blob": None,
+ "instance_properties": {
+ "vm_state": "building",
+ "availability_zone": None,
+ "ramdisk_id": "1",
+ "instance_type_id": 5,
+ "user_data": "",
+ "vm_mode": None,
+ "reservation_id": "r-851pambx",
+ "root_device_name": None,
+ "user_id": "admin",
+ "display_description": None,
+ "key_data": None,
+ "power_state": 0,
+ "project_id": "systenant",
+ "metadata": {},
+ "access_ip_v6": None,
+ "access_ip_v4": None,
+ "kernel_id": "2",
+ "key_name": None,
+ "display_name": None,
+ "config_drive_id": "",
+ "local_gb": 20,
+ "locked": False,
+ "launch_time": "2011-12-06T19:12:57Z",
+ "memory_mb": 2048,
+ "vcpus": 1,
+ "image_ref": 4,
+ "architecture": None,
+ "os_type": None,
+ "config_drive": ""
+ }
+ },
+ "requested_networks": None,
+ "availability_zone": None,
+ "instance_id": 16,
+ "admin_password": None,
+ "injected_files": None
+ },
+ "_context_auth_token": None,
+ "_context_user_id": "admin",
+ "_context_read_deleted": False,
+ "_context_strategy": "noauth",
+ "_context_is_admin": True,
+ "_context_project_id": "systenant",
+ "_context_timestamp": "2011-12-06T19:12:57.805503",
+ "method": "run_instance",
+ "_context_remote_address": "128.107.79.131"
+ }
+
+ def test_process_event(self):
+ FLAGS.dns_listener = "tests.test_amqp.TestListener"
+ service = amqp.Service()
+ service.process_event(self.run_instance_body, None)
+ self.assertEqual(self.run_instance_body, service.listener.event)
+
+ #TODO test work with actuall rabbit server - start private one for this needs
+
View
18 tests/test_auth.py
@@ -0,0 +1,18 @@
+
+import os
+import sys
+import json
+import datetime
+import unittest
+import stubout
+
+from nova_dns import auth
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+import tests
+
+class TestCase(tests.TestCase):
+ pass
+ #TODO to be done after changing auth model to acl
+
View
126 tests/test_dns.py
@@ -0,0 +1,126 @@
+import os
+import sys
+import json
+import unittest
+
+import webob
+import urllib
+
+from nova_dns import dns
+
+from nova import flags
+FLAGS = flags.FLAGS
+
+sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+import tests
+
+zones = ['test']
+soa = dict(retry="1", primary="ns.localhost", refresh="3", expire="4", ttl="5",
+ hostmaster="me@localhost", serial="5")
+add = dict(content="1", ttl=2, priority=3)
+
+class TestManager():
+ def list(self):
+ return zones
+
+ def add(self, zone_name, soa):
+ if zone_name == 'error':
+ raise Exception('test error')
+ return (zone_name, soa)
+
+ def drop(self, zone_name, force=False):
+ return [zone_name, force]
+
+ def get(self, zone_name):
+ return TestZone(zone_name)
+
+
+class TestZone():
+ def __init__(self, zone_name):
+ self.zone_name = zone_name
+ def drop(self):
+ pass
+ def add(self, v):
+ return [self.zone_name, v.__dict__]
+ def get(self, name, type=None):
+ self.name = name
+ self.type = type
+ return [self]
+ def set(self, name, type, content, priority, ttl):
+ return [self.zone_name, name, type, content, priority, ttl]
+ def delete(self, name, type):
+ return [self.zone_name, name, type]
+
+class TestAuth():
+ read = False
+ write = False
+ def can(self, req, zone_name):
+ return {"read": self.read, "write": self.write}
+
+class TestCase(tests.TestCase):
+ def req(self, path, status=200, error=None, method='GET', params=None):
+ #FIXME - hardcoded api-paste chain
+ query = "%s?%s" % (path, urllib.urlencode(params)) if params else path
+ print query
+ request = webob.Request.blank(query)
+ request.method = method
+ res = request.get_response(dns.VersionFilter(dns.App()))
+ self.assertEqual(res.status_int, status, "path %s: status %d != %d" %
+ (path, res.status_int, status))
+ #special case for version
+ if path == '/':
+ return res.body
+ if res.status_int != 200:
+ return
+ res = json.loads(res.body)
+ self.assertEqual(error, res['error'])
+ return res['result']
+
+ def test_app(self):
+ FLAGS.dns_manager = "tests.test_dns.TestManager"
+ AUTH = TestAuth()
+ dns.AUTH = AUTH
+
+ self.req('/')
+ self.req('/incorrect_path', status=404)
+
+ AUTH.read = False
+ self.req('/zone/', error='unauthorized')
+ AUTH.read = True
+ self.assertEqual(self.req('/zone/'), zones)
+
+ #TODO add more tests with AUTH - delayed with this as auth model
+ #will change
+ AUTH.write = True
+
+ self.assertEqual(self.req('/zone/testadd', method='PUT', params=soa), ['testadd', soa])
+ self.req('/zone/error', method='PUT', error="test error")
+
+ self.assertEqual(self.req('/zone/testdel', method='DELETE', params={"force": True}),
+ ['testdel', 'True'])
+ self.assertEqual(self.req('/zone/testdel', method='DELETE'), ['testdel', None])
+
+ self.assertEqual(self.req('/record/testzone', params={'type':'A', 'name': '@'}),
+ [dict(zone_name='testzone', type='A', name='')])
+ self.assertEqual(self.req('/record/testzone'),
+ [dict(zone_name='testzone', type=None, name=None)])
+
+ self.assertEqual(self.req('/record/testzone/@/A', method='POST', params=add),
+ ['testzone', '', 'A', add['content'], str(add['priority']), str(add['ttl'])])
+
+ self.assertEqual(self.req('/record/testzone/some/MX/'+add['content'], method='PUT',
+ params=add), ['testzone', dict(add.items(), name='some', type='MX')])
+ self.assertEqual(self.req('/record/testzone/@/A/'+add['content'], method='PUT',
+ params=add), ['testzone', dict(add.items(), name='', type='A')])
+ self.assertEqual(self.req('/record/testzone/@/A/'+add['content'], method='PUT'),
+ ['testzone', dict(name='', type='A', content=add['content'],
+ priority=0, ttl=7200)])
+ self.req('/record/testzone/@/INCORRECT/'+add['content'], method='PUT',
+ params=add, error='Incorrect type: INCORRECT')
+
+ self.assertEqual(self.req('/record/testzone/@/A', method='DELETE'),
+ ['testzone', '', 'A'])
+ self.assertEqual(self.req('/record/testzone/some/MX', method='DELETE'),
+ ['testzone', 'some', 'MX'])
+
+

0 comments on commit 1165afc

Please sign in to comment.