blob: bae4b80730816f3994b5294f53d4ee4f9492e160 [file] [log] [blame]
Adam Israelc3e6c2e2018-03-01 09:31:50 -05001import inspect
Adam Israeldcdf82b2017-08-15 15:26:43 -04002import subprocess
3import uuid
4
Adam Israelc3e6c2e2018-03-01 09:31:50 -05005import mock
6from juju.client.jujudata import FileJujuData
Adam Israeldcdf82b2017-08-15 15:26:43 -04007from juju.controller import Controller
Adam Israelc3e6c2e2018-03-01 09:31:50 -05008
9import pytest
Adam Israeldcdf82b2017-08-15 15:26:43 -040010
11
12def is_bootstrapped():
13 result = subprocess.run(['juju', 'switch'], stdout=subprocess.PIPE)
14 return (
15 result.returncode == 0 and
16 len(result.stdout.decode().strip()) > 0)
17
Adam Israelc3e6c2e2018-03-01 09:31:50 -050018
Adam Israeldcdf82b2017-08-15 15:26:43 -040019bootstrapped = pytest.mark.skipif(
20 not is_bootstrapped(),
21 reason='bootstrapped Juju environment required')
22
Adam Israelc3e6c2e2018-03-01 09:31:50 -050023test_run_nonce = uuid.uuid4().hex[-4:]
24
Adam Israeldcdf82b2017-08-15 15:26:43 -040025
26class CleanController():
27 def __init__(self):
Adam Israelc3e6c2e2018-03-01 09:31:50 -050028 self._controller = None
Adam Israeldcdf82b2017-08-15 15:26:43 -040029
30 async def __aenter__(self):
Adam Israelc3e6c2e2018-03-01 09:31:50 -050031 self._controller = Controller()
32 await self._controller.connect()
33 return self._controller
Adam Israeldcdf82b2017-08-15 15:26:43 -040034
35 async def __aexit__(self, exc_type, exc, tb):
Adam Israelc3e6c2e2018-03-01 09:31:50 -050036 await self._controller.disconnect()
Adam Israeldcdf82b2017-08-15 15:26:43 -040037
38
39class CleanModel():
Adam Israelc3e6c2e2018-03-01 09:31:50 -050040 def __init__(self, bakery_client=None):
41 self._controller = None
42 self._model = None
43 self._model_uuid = None
44 self._bakery_client = bakery_client
Adam Israeldcdf82b2017-08-15 15:26:43 -040045
46 async def __aenter__(self):
Adam Israelc3e6c2e2018-03-01 09:31:50 -050047 model_nonce = uuid.uuid4().hex[-4:]
48 frame = inspect.stack()[1]
49 test_name = frame.function.replace('_', '-')
50 jujudata = TestJujuData()
51 self._controller = Controller(
52 jujudata=jujudata,
53 bakery_client=self._bakery_client,
54 )
55 controller_name = jujudata.current_controller()
56 user_name = jujudata.accounts()[controller_name]['user']
57 await self._controller.connect(controller_name)
Adam Israeldcdf82b2017-08-15 15:26:43 -040058
Adam Israelc3e6c2e2018-03-01 09:31:50 -050059 model_name = 'test-{}-{}-{}'.format(
60 test_run_nonce,
61 test_name,
62 model_nonce,
63 )
64 self._model = await self._controller.add_model(model_name)
65
66 # Change the JujuData instance so that it will return the new
67 # model as the current model name, so that we'll connect
68 # to it by default.
69 jujudata.set_model(
70 controller_name,
71 user_name + "/" + model_name,
72 self._model.info.uuid,
73 )
Adam Israeldcdf82b2017-08-15 15:26:43 -040074
75 # save the model UUID in case test closes model
Adam Israelc3e6c2e2018-03-01 09:31:50 -050076 self._model_uuid = self._model.info.uuid
Adam Israeldcdf82b2017-08-15 15:26:43 -040077
Adam Israelc3e6c2e2018-03-01 09:31:50 -050078 return self._model
Adam Israeldcdf82b2017-08-15 15:26:43 -040079
Adam Israel1a15d1c2017-10-23 12:00:49 -040080 def _models(self):
81 result = self._orig_models()
82 models = result[self.controller_name]['models']
83 full_model_name = '{}/{}'.format(self.user_name, self.model_name)
84 if full_model_name not in models:
85 models[full_model_name] = {'uuid': self.model_uuid}
86 return result
87
Adam Israeldcdf82b2017-08-15 15:26:43 -040088 async def __aexit__(self, exc_type, exc, tb):
Adam Israelc3e6c2e2018-03-01 09:31:50 -050089 await self._model.disconnect()
90 await self._controller.destroy_model(self._model_uuid)
91 await self._controller.disconnect()
92
93
94class TestJujuData(FileJujuData):
95 def __init__(self):
96 self.__controller_name = None
97 self.__model_name = None
98 self.__model_uuid = None
99 super().__init__()
100
101 def set_model(self, controller_name, model_name, model_uuid):
102 self.__controller_name = controller_name
103 self.__model_name = model_name
104 self.__model_uuid = model_uuid
105
106 def current_model(self, *args, **kwargs):
107 return self.__model_name or super().current_model(*args, **kwargs)
108
109 def models(self):
110 all_models = super().models()
111 if self.__model_name is None:
112 return all_models
113 all_models.setdefault(self.__controller_name, {})
114 all_models[self.__controller_name].setdefault('models', {})
115 cmodels = all_models[self.__controller_name]['models']
116 cmodels[self.__model_name] = {'uuid': self.__model_uuid}
117 return all_models
118>>>>>>> New N2VC interface + updated libjuju
Adam Israeldcdf82b2017-08-15 15:26:43 -0400119
120
121class AsyncMock(mock.MagicMock):
122 async def __call__(self, *args, **kwargs):
123 return super().__call__(*args, **kwargs)