← Back to team overview

cloud-init-dev team mailing list archive

[Merge] ~chad.smith/cloud-init:tests/preserve-ci-instances into cloud-init:master

 

Chad Smith has proposed merging ~chad.smith/cloud-init:tests/preserve-ci-instances into cloud-init:master.

Commit message:
test: add optional --preserve-instance arg to integraiton tests

By default, integration tests destroy the test instances after each
test run. To aid debug and development of integration tests, support a
--preserve-instance argument which will leave the modified test instance
in a stopped state for further debug.

Requested reviews:
  cloud-init commiters (cloud-init-dev)

For more details, see:
https://code.launchpad.net/~chad.smith/cloud-init/+git/cloud-init/+merge/347716

to test:
  make deb;
  tox -e citest -- run --verbose --platform lxd --os-name artful --test modules/ntp_chrony --deb <YOUR_DEBNAME> -d results --preserve-data --preserve-instance
-- 
Your team cloud-init commiters is requested to review the proposed merge of ~chad.smith/cloud-init:tests/preserve-ci-instances into cloud-init:master.
diff --git a/doc/rtd/topics/tests.rst b/doc/rtd/topics/tests.rst
index cac4a6e..b83bd89 100644
--- a/doc/rtd/topics/tests.rst
+++ b/doc/rtd/topics/tests.rst
@@ -58,7 +58,8 @@ explaining how to run one or the other independently.
     $ tox -e citest -- run --verbose \
         --os-name stretch --os-name xenial \
         --deb cloud-init_0.7.8~my_patch_all.deb \
-        --preserve-data --data-dir ~/collection
+        --preserve-data --data-dir ~/collection \
+        --preserve-instance
 
 The above command will do the following:
 
@@ -76,6 +77,10 @@ The above command will do the following:
 * ``--preserve-data`` always preserve collected data, do not remove data
   after successful test run
 
+* ``--preserve-instance`` do not destroy the instance after test to allow
+  for debugging the stopped instance during integration test development. By
+  default, test instances are destroyed after the test completes.
+
 * ``--data-dir ~/collection`` write collected data into `~/collection`,
   rather than using a temporary directory
 
diff --git a/tests/cloud_tests/args.py b/tests/cloud_tests/args.py
index c6c1877..ab34549 100644
--- a/tests/cloud_tests/args.py
+++ b/tests/cloud_tests/args.py
@@ -62,6 +62,9 @@ ARG_SETS = {
         (('-d', '--data-dir'),
          {'help': 'directory to store test data in',
           'action': 'store', 'metavar': 'DIR', 'required': False}),
+        (('--preserve-instance',),
+         {'help': 'do not destroy the instance under test',
+          'action': 'store_true', 'default': False, 'required': False}),
         (('--preserve-data',),
          {'help': 'do not remove collected data after successful run',
           'action': 'store_true', 'default': False, 'required': False}),),
diff --git a/tests/cloud_tests/collect.py b/tests/cloud_tests/collect.py
index 78263bf..75b5061 100644
--- a/tests/cloud_tests/collect.py
+++ b/tests/cloud_tests/collect.py
@@ -93,7 +93,8 @@ def collect_test_data(args, snapshot, os_name, test_name):
     # create test instance
     component = PlatformComponent(
         partial(platforms.get_instance, snapshot, user_data,
-                block=True, start=False, use_desc=test_name))
+                block=True, start=False, use_desc=test_name),
+        preserve_instance=args.preserve_instance)
 
     LOG.info('collecting test data for test: %s', test_name)
     with component as instance:
diff --git a/tests/cloud_tests/stage.py b/tests/cloud_tests/stage.py
index 74a7d46..35f506f 100644
--- a/tests/cloud_tests/stage.py
+++ b/tests/cloud_tests/stage.py
@@ -12,9 +12,15 @@ from tests.cloud_tests import LOG
 class PlatformComponent(object):
     """Context manager to safely handle platform components."""
 
-    def __init__(self, get_func):
-        """Store get_<platform component> function as partial with no args."""
+    def __init__(self, get_func, preserve_instance=False):
+        """Store get_<platform component> function as partial with no args.
+        
+        @param get_func: Callable returning an instance from the platform.
+        @param preserve_instance: Boolean, when True, do not destroy instance
+            after test. Used for test development.
+        """
         self.get_func = get_func
+        self.preserve_instance = preserve_instance
 
     def __enter__(self):
         """Create instance of platform component."""
@@ -24,7 +30,10 @@ class PlatformComponent(object):
     def __exit__(self, etype, value, trace):
         """Destroy instance."""
         if self.instance is not None:
-            self.instance.destroy()
+            if self.preserve_instance:
+                LOG.info('Preserving test instance %s', self.instance.name)
+            else:
+                self.instance.destroy()
 
 
 def run_single(name, call):

Follow ups