Add unittests for tags
diff --git a/tests/data/create_tag.json b/tests/data/create_tag.json
new file mode 100644
index 0000000..9680fb5
--- /dev/null
+++ b/tests/data/create_tag.json
@@ -0,0 +1,16 @@
+{
+    "queryasyncjobresultresponse": {
+        "jobprocstatus": 0,
+        "created": "2014-06-01T12:00:56+0200",
+        "cmd": "org.apache.cloudstack.api.command.user.tag.CreateTagsCmd",
+        "userid": "26a772da-dc25-4f2b-b0f1-e095e3717a30",
+        "jobstatus": 1,
+        "jobid": "036bf202-6fe5-4b73-8823-d9e22cd3c63f",
+        "jobresultcode": 0,
+        "jobresulttype": "object",
+        "jobresult": {
+            "success": true
+        },
+        "accountid": "ddbdf378-e8d9-47e0-964b-661d0d8414b8"
+    }
+}
diff --git a/tests/data/delete_tag.json b/tests/data/delete_tag.json
new file mode 100644
index 0000000..2874489
--- /dev/null
+++ b/tests/data/delete_tag.json
@@ -0,0 +1,16 @@
+{
+    "queryasyncjobresultresponse": {
+        "jobprocstatus": 0,
+        "created": "2014-06-01T12:22:48+0200",
+        "cmd": "org.apache.cloudstack.api.command.user.tag.DeleteTagsCmd",
+        "userid": "26a772da-dc25-4f2b-b0f1-e095e3717a30",
+        "jobstatus": 1,
+        "jobid": "5af5c011-c708-4f36-8a99-caca51590458",
+        "jobresultcode": 0,
+        "jobresulttype": "object",
+        "jobresult": {
+            "success": true
+        },
+        "accountid": "ddbdf378-e8d9-47e0-964b-661d0d8414b8"
+    }
+}
diff --git a/tests/data/list_tags.json b/tests/data/list_tags.json
new file mode 100644
index 0000000..9076631
--- /dev/null
+++ b/tests/data/list_tags.json
@@ -0,0 +1,25 @@
+{
+    "listtagsresponse": {
+        "count": 2,
+        "tag": [
+            {
+                "account": "brogand93@darrenbrogan.ie",
+                "domainid": "42f2b0d0-3953-485f-984d-b8d67185d358",
+                "resourcetype": "UserVm",
+                "resourceid": "a0ae3a53-1f4d-42d3-bbb8-7227bb0e0d69",
+                "domain": "brogand93@darrenbrogan.ie",
+                "value": "po",
+                "key": "gjh"
+            },
+            {
+                "account": "brogand93@darrenbrogan.ie",
+                "domainid": "42f2b0d0-3953-485f-984d-b8d67185d358",
+                "resourcetype": "UserVm",
+                "resourceid": "a0ae3a53-1f4d-42d3-bbb8-7227bb0e0d69",
+                "domain": "brogand93@darrenbrogan.ie",
+                "value": "test",
+                "key": "testkey"
+            }
+        ]
+    }
+}
diff --git a/tests/settings.py b/tests/settings.py
index cf7244a..49cbbd9 100644
--- a/tests/settings.py
+++ b/tests/settings.py
@@ -8,6 +8,7 @@
 CLOUDSTACK_DEFAULT_ZONE = 'CH-GV2'
 
 INSTANCE_TYPE_MAP = {'m1.small': 'micro'}
+RESOURCE_TYPE_MAP = {'exampleresourceid': 'UserVm'}
 
 DEBUG = False
 TESTING = True
diff --git a/tests/tags_tests.py b/tests/tags_tests.py
new file mode 100644
index 0000000..3ab6568
--- /dev/null
+++ b/tests/tags_tests.py
@@ -0,0 +1,153 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+from base64 import b64encode
+
+import mock
+
+from ec2stack.helpers import read_file, generate_signature
+from . import Ec2StackAppTestCase
+
+
+class TagsTestCase(Ec2StackAppTestCase):
+
+    def test_create_tag(self):
+        data = self.get_example_data()
+        data['Action'] = 'CreateTags'
+        data['Tag.1.Key'] = 'examplekey'
+        data['Tag.1.value'] = 'examplevalue'
+        data['ResourceId.1'] = 'exampleresourceid'
+
+
+        data['Signature'] = generate_signature(data, 'POST', 'localhost', '/')
+
+        get = mock.Mock()
+        get.return_value.text = read_file(
+            'tests/data/create_tag.json'
+        )
+        get.return_value.status_code = 200
+
+        with mock.patch('requests.get', get):
+            response = self.post(
+                '/',
+                data=data
+            )
+
+        self.assert_ok(response)
+        assert 'CreateTagsResponse' in response.data
+
+    def test_create_tag_resource_id_not_in_config(self):
+        data = self.get_example_data()
+        data['Action'] = 'CreateTags'
+        data['Tag.1.Key'] = 'examplekey'
+        data['Tag.1.value'] = 'examplevalue'
+        data['ResourceId.1'] = 'exampleunconfigredresourceid'
+
+
+        data['Signature'] = generate_signature(data, 'POST', 'localhost', '/')
+
+        get = mock.Mock()
+        get.return_value.text = read_file(
+            'tests/data/create_tag.json'
+        )
+        get.return_value.status_code = 200
+
+        with mock.patch('requests.get', get):
+            response = self.post(
+                '/',
+                data=data
+            )
+
+        self.assert_bad_request(response)
+        assert ' not found in configuration' in response.data
+
+    def test_delete_tag(self):
+        data = self.get_example_data()
+        data['Action'] = 'DeleteTags'
+        data['Tag.1.Key'] = 'examplekey'
+        data['ResourceId.1'] = 'exampleresourceid'
+
+
+        data['Signature'] = generate_signature(data, 'POST', 'localhost', '/')
+
+        get = mock.Mock()
+        get.return_value.text = read_file(
+            'tests/data/delete_tag.json'
+        )
+        get.return_value.status_code = 200
+
+        with mock.patch('requests.get', get):
+            response = self.post(
+                '/',
+                data=data
+            )
+
+        self.assert_ok(response)
+        assert 'DeleteTagsResponse' in response.data
+
+    def test_delete_tag_resource_id_not_in_config(self):
+        data = self.get_example_data()
+        data['Action'] = 'DeleteTags'
+        data['Tag.1.Key'] = 'examplekey'
+        data['ResourceId.1'] = 'exampleunconfigredresourceid'
+
+
+        data['Signature'] = generate_signature(data, 'POST', 'localhost', '/')
+
+        get = mock.Mock()
+        get.return_value.text = read_file(
+            'tests/data/delete_tag.json'
+        )
+        get.return_value.status_code = 200
+
+        with mock.patch('requests.get', get):
+            response = self.post(
+                '/',
+                data=data
+            )
+
+        self.assert_bad_request(response)
+        assert ' not found in configuration' in response.data
+
+    def test_delete_keypair(self):
+        data = self.get_example_data()
+        data['Action'] = 'DeleteKeyPair'
+        data['KeyName'] = 'Test'
+        data['Signature'] = generate_signature(data, 'POST', 'localhost', '/')
+
+        get = mock.Mock()
+        get.return_value.text = read_file(
+            'tests/data/delete_keypair.json'
+        )
+        get.return_value.status_code = 200
+
+        with mock.patch('requests.get', get):
+            response = self.post(
+                '/',
+                data=data
+            )
+
+        self.assert_ok(response)
+        assert 'DeleteKeyPairResponse' in response.data
+
+    def test_describe_tags(self):
+        data = self.get_example_data()
+        data['Action'] = 'DescribeTags'
+        data['Signature'] = generate_signature(data, 'POST', 'localhost', '/')
+
+        get = mock.Mock()
+        get.return_value.text = read_file(
+            'tests/data/list_tags.json'
+        )
+        get.return_value.status_code = 200
+
+        with mock.patch('requests.get', get):
+            response = self.post(
+                '/',
+                data=data
+            )
+
+        self.assert_ok(response)
+        assert 'DescribeTagsResponse' in response.data
+
+