Use libjuju for adding and removing models

libjuju supports adding and removing models so replace calls out
to subprocess with libjuju calls
This commit is contained in:
Liam Young
2018-06-06 12:28:08 +01:00
parent d1a5b67d8c
commit b21767ce52
6 changed files with 94 additions and 59 deletions

View File

@@ -4,14 +4,8 @@ import unit_tests.utils as ut_utils
class TestCharmLifecycleDestroy(ut_utils.BaseTestCase):
def test_destroy_model(self):
self.patch_object(lc_destroy.subprocess, 'check_call')
lc_destroy.destroy_model('doomed')
self.check_call.assert_called_once_with(
['juju', 'destroy-model', '--yes', 'doomed'])
def test_destroy(self):
self.patch_object(lc_destroy, 'destroy_model')
self.patch_object(lc_destroy.zaza.model, 'destroy_model')
lc_destroy.destroy('doomed')
self.destroy_model.assert_called_once_with('doomed')

View File

@@ -4,26 +4,20 @@ import unit_tests.utils as ut_utils
class TestCharmLifecyclePrepare(ut_utils.BaseTestCase):
def test_add_model(self):
self.patch_object(lc_prepare.subprocess, 'check_call')
lc_prepare.add_model('newmodel')
self.check_call.assert_called_once_with(
[
'juju', 'add-model', 'newmodel',
'--config', 'agent-stream=proposed',
'--config', 'default-series=xenial',
'--config', 'image-stream=daily',
'--config', 'test-mode=true',
'--config', 'transmit-vendor-metrics=false',
'--config', 'enable-os-upgrade=false',
'--config', 'automatically-retry-hooks=false',
'--config', 'use-default-secgroup=true'
])
def test_prepare(self):
self.patch_object(lc_prepare, 'add_model')
lc_prepare.add_model('newmodel')
self.add_model.assert_called_once_with('newmodel')
self.patch_object(lc_prepare.zaza.model, 'add_model')
lc_prepare.prepare('newmodel')
self.add_model.assert_called_once_with(
'newmodel',
config={
'agent-stream': 'proposed',
'default-series': 'xenial',
'image-stream': 'daily',
'test-mode': 'true',
'transmit-vendor-metrics': 'false',
'enable-os-upgrade': 'false',
'automatically-retry-hooks': 'false',
'use-default-secgroup': 'true'})
def test_parser(self):
args = lc_prepare.parse_args(['-m', 'newmodel'])

View File

@@ -99,6 +99,15 @@ class TestModel(ut_utils.BaseTestCase):
async def _connect():
return
async def _ctrl_connect():
return
async def _ctrl_add_model(model_name, config=None):
return
async def _ctrl_destroy_models(model_name):
return
self.Model_mock.connect.side_effect = _connect
self.Model_mock.connect_model.side_effect = _connect_model
self.Model_mock.disconnect.side_effect = _disconnect
@@ -109,6 +118,36 @@ class TestModel(ut_utils.BaseTestCase):
self.model_name = "testmodel"
self.Model_mock.info.name = self.model_name
self.Controller_mock = mock.MagicMock()
self.Controller_mock.connect.side_effect = _ctrl_connect
self.Controller_mock.add_model.side_effect = _ctrl_add_model
self.Controller_mock.destroy_models.side_effect = _ctrl_destroy_models
def test_add_model(self):
self.patch_object(model, 'Controller')
self.Controller.return_value = self.Controller_mock
model.add_model('newmodel')
self.Controller_mock.connect.assert_called_once_with()
self.Controller_mock.add_model.assert_called_once_with(
'newmodel',
config=None)
def test_add_model_config(self):
self.patch_object(model, 'Controller')
self.Controller.return_value = self.Controller_mock
model.add_model('newmodel', config={'run-faster': 'true'})
self.Controller_mock.connect.assert_called_once_with()
self.Controller_mock.add_model.assert_called_once_with(
'newmodel',
config={'run-faster': 'true'})
def test_destroy_model(self):
self.patch_object(model, 'Controller')
self.Controller.return_value = self.Controller_mock
model.destroy_model('newmodel')
self.Controller_mock.connect.assert_called_once_with()
self.Controller_mock.destroy_models.assert_called_once_with('newmodel')
def test_run_in_model(self):
self.patch_object(model, 'Model')
self.Model.return_value = self.Model_mock

View File

@@ -1,17 +1,8 @@
import argparse
import logging
import subprocess
import sys
def destroy_model(model_name):
"""Remove a model with the given name
:param model: Name of model to remove
:type bundle: str
"""
logging.info("Remove model {}".format(model_name))
subprocess.check_call(['juju', 'destroy-model', '--yes', model_name])
import zaza.model
def destroy(model_name):
@@ -20,7 +11,7 @@ def destroy(model_name):
:param model: Name of model to remove
:type bundle: str
"""
destroy_model(model_name)
zaza.model.destroy_model(model_name)
def parse_args(args):

View File

@@ -1,33 +1,23 @@
import argparse
import logging
import subprocess
import sys
import zaza.model
MODEL_DEFAULTS = [
MODEL_DEFAULTS = {
# Model defaults from charm-test-infra
# https://jujucharms.com/docs/2.1/models-config
'--config', 'agent-stream=proposed',
'--config', 'default-series=xenial',
'--config', 'image-stream=daily',
'--config', 'test-mode=true',
'--config', 'transmit-vendor-metrics=false',
'agent-stream': 'proposed',
'default-series': 'xenial',
'image-stream': 'daily',
'test-mode': 'true',
'transmit-vendor-metrics': 'false',
# https://bugs.launchpad.net/juju/+bug/1685351
# enable-os-refresh-update: false
'--config', 'enable-os-upgrade=false',
'--config', 'automatically-retry-hooks=false',
'--config', 'use-default-secgroup=true',
]
def add_model(model_name):
"""Add a model with the given name
:param model: Name of model to add
:type bundle: str
"""
logging.info("Adding model {}".format(model_name))
subprocess.check_call(['juju', 'add-model', model_name] + MODEL_DEFAULTS)
'enable-os-upgrade': 'false',
'automatically-retry-hooks': 'false',
'use-default-secgroup': 'true',
}
def prepare(model_name):
@@ -36,7 +26,7 @@ def prepare(model_name):
:param model: Name of model to add
:type bundle: str
"""
add_model(model_name)
zaza.model.add_model(model_name, config=MODEL_DEFAULTS)
def parse_args(args):

View File

@@ -8,12 +8,39 @@ import yaml
from oslo_config import cfg
from juju import loop
from juju.controller import Controller
from juju.errors import JujuError
from juju.model import Model
from zaza import sync_wrapper
async def async_add_model(model_name, config=None):
"""Add a model to the current controller
:param model_name: Name to give the new model.
:type model_name: str
:param config: Model configuration.
:type config: dict"""
controller = Controller()
await controller.connect()
await controller.add_model(model_name, config=config)
add_model = sync_wrapper(async_add_model)
async def async_destroy_model(model_name):
"""Remove a model from the current controller
:param model_name: Name of model to remove
:type model_name: str"""
controller = Controller()
await controller.connect()
await controller.destroy_models(model_name)
destroy_model = sync_wrapper(async_destroy_model)
async def deployed(filter=None):
# Create a Model instance. We need to connect our Model to a Juju api
# server before we can use it.