summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorChris Conway <clconway@google.com>2014-03-29 17:27:48 -0700
committerChris Conway <clconway@google.com>2014-04-13 18:38:30 -0700
commit2cc4a372c5b65f37e2c4e24d293714c2d851136c (patch)
tree17878a7088e8af4dced97ab5a5d67c155cf27ac4 /test
parentb0556ab1fbc0652147b86a809cf8b69d4c3cd188 (diff)
downloadansible-2cc4a372c5b65f37e2c4e24d293714c2d851136c.tar.gz
Adds integration tests for gce module.
Diffstat (limited to 'test')
-rw-r--r--test/integration/Makefile9
-rw-r--r--test/integration/cleanup_gce.py102
-rw-r--r--test/integration/credentials.template5
-rw-r--r--test/integration/gce.yml5
-rw-r--r--test/integration/roles/test_gce/defaults/main.yml6
-rw-r--r--test/integration/roles/test_gce/tasks/main.yml97
6 files changed, 224 insertions, 0 deletions
diff --git a/test/integration/Makefile b/test/integration/Makefile
index da2758c140..d8ca0a10c2 100644
--- a/test/integration/Makefile
+++ b/test/integration/Makefile
@@ -39,6 +39,9 @@ cloud_cleanup: amazon_cleanup rackspace_cleanup
amazon_cleanup:
python cleanup_ec2.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
+gce_cleanup:
+ python cleanup_gce.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
+
rackspace_cleanup:
@echo "FIXME - cleanup_rax.py not yet implemented"
@# python cleanup_rax.py -y --match="^$(CLOUD_RESOURCE_PREFIX)"
@@ -53,6 +56,12 @@ amazon: $(CREDENTIALS_FILE)
CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make amazon_cleanup ; \
exit $$RC;
+gce: $(CREDENTIALS_FILE)
+ ansible-playbook gce.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
+ RC=$$? ; \
+ CLOUD_RESOURCE_PREFIX="$(CLOUD_RESOURCE_PREFIX)" make gce_cleanup ; \
+ exit $$RC;
+
rackspace: $(CREDENTIALS_FILE)
ansible-playbook rackspace.yml -i $(INVENTORY) -e @$(VARS_FILE) $(CREDENTIALS_ARG) -e "resource_prefix=$(CLOUD_RESOURCE_PREFIX)" -v $(TEST_FLAGS) ; \
RC=$$? ; \
diff --git a/test/integration/cleanup_gce.py b/test/integration/cleanup_gce.py
new file mode 100644
index 0000000000..9b1645e93e
--- /dev/null
+++ b/test/integration/cleanup_gce.py
@@ -0,0 +1,102 @@
+'''
+Find and delete GCE resources matching the provided --match string. Unless
+--yes|-y is provided, the prompt for confirmation prior to deleting resources.
+Please use caution, you can easily delete your *ENTIRE* GCE infrastructure.
+'''
+
+import os
+import re
+import sys
+import optparse
+import yaml
+
+try:
+ from libcloud.compute.types import Provider
+ from libcloud.compute.providers import get_driver
+ from libcloud.common.google import GoogleBaseError, QuotaExceededError, \
+ ResourceExistsError, ResourceInUseError, ResourceNotFoundError
+ _ = Provider.GCE
+except ImportError:
+ print("failed=True " + \
+ "msg='libcloud with GCE support (0.13.3+) required for this module'")
+ sys.exit(1)
+
+
+def delete_gce_resources(get_func, attr, opts):
+ for item in get_func():
+ val = getattr(item, attr)
+ if re.search(opts.match_re, val, re.IGNORECASE):
+ prompt_and_delete(item, "Delete matching %s? [y/n]: " % (item,), opts.assumeyes)
+
+def prompt_and_delete(item, prompt, assumeyes):
+ if not assumeyes:
+ assumeyes = raw_input(prompt).lower() == 'y'
+ assert hasattr(item, 'destroy'), "Class <%s> has no delete attribute" % item.__class__
+ if assumeyes:
+ item.destroy()
+ print ("Deleted %s" % item)
+
+def parse_args():
+ default_service_account_email = None
+ default_pem_file = None
+ default_project_id = None
+
+ # Load details from credentials.yml
+ if os.path.isfile('credentials.yml'):
+ credentials = yaml.load(open('credentials.yml', 'r'))
+
+ if default_service_account_email is None:
+ default_service_account_email = credentials['gce_service_account_email']
+ if default_pem_file is None:
+ default_pem_file = credentials['gce_pem_file']
+ if default_project_id is None:
+ default_project_id = credentials['gce_project_id']
+
+ parser = optparse.OptionParser(usage="%s [options]" % (sys.argv[0],),
+ description=__doc__)
+ parser.add_option("--service_account_email",
+ action="store", dest="service_account_email",
+ default=default_service_account_email,
+ help="GCE service account email. Default is loaded from credentials.yml.")
+ parser.add_option("--pem_file",
+ action="store", dest="pem_file",
+ default=default_pem_file,
+ help="GCE client key. Default is loaded from credentials.yml.")
+ parser.add_option("--project_id",
+ action="store", dest="project_id",
+ default=default_project_id,
+ help="Google Cloud project ID. Default is loaded from credentials.yml.")
+ parser.add_option("--credentials", "-c",
+ action="store", dest="credential_file",
+ default="credentials.yml",
+ help="YAML file to read cloud credentials (default: %default)")
+ parser.add_option("--yes", "-y",
+ action="store_true", dest="assumeyes",
+ default=False,
+ help="Don't prompt for confirmation")
+ parser.add_option("--match",
+ action="store", dest="match_re",
+ default="^ansible-testing-",
+ help="Regular expression used to find GCE resources (default: %default)")
+
+ (opts, args) = parser.parse_args()
+ for required in ['service_account_email', 'pem_file', 'project_id']:
+ if getattr(opts, required) is None:
+ parser.error("Missing required parameter: --%s" % required)
+
+ return (opts, args)
+
+if __name__ == '__main__':
+
+ (opts, args) = parse_args()
+
+ # Connect to GCE
+ gce_cls = get_driver(Provider.GCE)
+ gce = gce_cls(
+ opts.service_account_email, opts.pem_file, project=opts.project_id)
+
+ try:
+ # Delete matching instances
+ delete_gce_resources(gce.list_nodes, 'name', opts)
+ except KeyboardInterrupt, e:
+ print "\nExiting on user command."
diff --git a/test/integration/credentials.template b/test/integration/credentials.template
index f21100405f..12316254bb 100644
--- a/test/integration/credentials.template
+++ b/test/integration/credentials.template
@@ -3,5 +3,10 @@
ec2_access_key:
ec2_secret_key:
+# GCE Credentials
+service_account_email:
+pem_file:
+project_id:
+
# GITHUB SSH private key - a path to a SSH private key for use with github.com
github_ssh_private_key: "{{ lookup('env','HOME') }}/.ssh/id_rsa"
diff --git a/test/integration/gce.yml b/test/integration/gce.yml
new file mode 100644
index 0000000000..75287abab1
--- /dev/null
+++ b/test/integration/gce.yml
@@ -0,0 +1,5 @@
+- hosts: testhost
+ gather_facts: true
+ roles:
+ - { role: test_gce, tags: test_gce }
+ # TODO: tests for gce_net, gce_pd, etc.
diff --git a/test/integration/roles/test_gce/defaults/main.yml b/test/integration/roles/test_gce/defaults/main.yml
new file mode 100644
index 0000000000..1564808d79
--- /dev/null
+++ b/test/integration/roles/test_gce/defaults/main.yml
@@ -0,0 +1,6 @@
+---
+# defaults file for test_gce
+instance_name: "{{ resource_prefix|lower }}"
+service_account_email: "{{ gce_service_account_email }}"
+pem_file: "{{ gce_pem_file }}"
+project_id: "{{ gce_project_id }}"
diff --git a/test/integration/roles/test_gce/tasks/main.yml b/test/integration/roles/test_gce/tasks/main.yml
new file mode 100644
index 0000000000..8791c281a5
--- /dev/null
+++ b/test/integration/roles/test_gce/tasks/main.yml
@@ -0,0 +1,97 @@
+# TODO: lots of attributes not covered: machine_type, zone, metadata, tags, etc.
+#
+# ============================================================
+- name: test with no parameters
+ gce:
+ register: result
+ ignore_errors: true
+
+- name: assert failure when called with no parameters
+ assert:
+ that:
+ - 'result.failed'
+ - 'result.msg == "Missing GCE connection parameters in libcloud secrets file."'
+
+# ============================================================
+- name: test missing name
+ gce:
+ service_account_email: "{{ service_account_email }}"
+ pem_file: "{{ pem_file }}"
+ project_id: "{{ project_id }}"
+ register: result
+ ignore_errors: true
+
+- name: assert failure when called with no parameters
+ assert:
+ that:
+ - 'result.failed'
+ - 'result.msg == "Must specify a \"name\" or \"instance_names\""'
+
+# ============================================================
+- name: test state=present (expected changed=true)
+ gce:
+ name: "{{ instance_name }}"
+ service_account_email: "{{ service_account_email }}"
+ pem_file: "{{ pem_file }}"
+ project_id: "{{ project_id }}"
+ state: present
+ register: result
+
+- name: assert state=present (expected changed=true)
+ assert:
+ that:
+ - 'result.changed'
+ - 'result.name == "{{ instance_name }}"'
+ - 'result.state == "present"'
+
+# ============================================================
+- name: test state=present (expected changed=false)
+ gce:
+ name: "{{ instance_name }}"
+ service_account_email: "{{ service_account_email }}"
+ pem_file: "{{ pem_file }}"
+ project_id: "{{ project_id }}"
+ state: present
+ register: result
+
+- name: assert state=present (expected changed=false)
+ assert:
+ that:
+ - 'not result.changed'
+ - 'result.name == "{{ instance_name }}"'
+ - 'result.state == "present"'
+
+# ============================================================
+- name: test state=absent (expected changed=true)
+ gce:
+ name: "{{ instance_name }}"
+ service_account_email: "{{ service_account_email }}"
+ pem_file: "{{ pem_file }}"
+ project_id: "{{ project_id }}"
+ state: absent
+ register: result
+
+- name: assert state=absent (expected changed=true)
+ assert:
+ that:
+ - 'result.changed'
+ - 'result.name == "{{ instance_name }}"'
+ - 'result.state == "absent"'
+
+# ============================================================
+- name: test state=absent (expected changed=false)
+ gce:
+ name: "{{ instance_name }}"
+ service_account_email: "{{ service_account_email }}"
+ pem_file: "{{ pem_file }}"
+ project_id: "{{ project_id }}"
+ state: absent
+ register: result
+
+- name: assert state=absent (expected changed=false)
+ assert:
+ that:
+ - 'not result.changed'
+ - 'result.name == "{{ instance_name }}"'
+ - 'result.state == "absent"'
+