async def connect_juju(ctrl_name=None, model_name=None, endpoint=None, username=None, password=None, cacert=None): controller = Controller(max_frame_size=MAX_FRAME_SIZE) # noqa if endpoint: await controller.connect(endpoint=endpoint, username=username, password=password, cacert=cacert) else: await controller.connect(ctrl_name) if endpoint: model = Model(max_frame_size=MAX_FRAME_SIZE) await model.connect(uuid=model_name, endpoint=endpoint, username=username, password=password, cacert=cacert) elif model_name: model = await controller.get_model(model_name) else: model = Model(max_frame_size=MAX_FRAME_SIZE) # noqa await model.connect() # HACK low unsettable timeout in the model model.charmstore._cs = CharmStore(timeout=60) return controller, model
def test_apply_delta(self): from juju.model import Model from juju.application import Application model = Model() model._connector = mock.MagicMock() delta = _make_delta('application', 'add', dict(name='foo')) # test add prev, new = model.state.apply_delta(delta) self.assertEqual( len(model.state.state[delta.entity][delta.get_id()]), 1) self.assertIsNone(prev) self.assertIsInstance(new, Application) # test remove delta.type = 'remove' prev, new = model.state.apply_delta(delta) # length of the entity history deque is now 3: # - 1 for the first delta # - 1 for the second delta # - 1 for the None sentinel appended after the 'remove' self.assertEqual( len(model.state.state[delta.entity][delta.get_id()]), 3) self.assertIsInstance(new, Application) # new object is falsy because its data is None self.assertFalse(new) self.assertIsInstance(prev, Application) self.assertTrue(prev)
async def main(): model = Model() # connect to current model with current user, per Juju CLI await model.connect() goal_state = Model.from_yaml('bundle-like-thing') ubuntu_app = await model.deploy( 'ubuntu-0', application_name='ubuntu', series='trusty', channel='stable', ) ubuntu_app.on_unit_added(callback=lambda unit: True) await model.deploy( 'nrpe-11', application_name='nrpe', series='trusty', channel='stable', num_units=0, ) await model.add_relation( 'ubuntu', 'nrpe', ) result, ok = await model.block_until( lambda: model.matches(goal_state), timeout=600 )
async def main(): model = Model() await model.connect() await model.reset(force=True) goal_state = Model.from_yaml('bundle-like-thing') ubuntu_app = await model.deploy( 'ubuntu-0', application_name='ubuntu', series='trusty', channel='stable', ) ubuntu_app.on_unit_added(callback=lambda unit: True) await model.deploy( 'nrpe-11', application_name='nrpe', series='trusty', channel='stable', num_units=0, ) await model.add_relation( 'ubuntu', 'nrpe', ) result, ok = await model.block_until(lambda: model.matches(goal_state), timeout=600)
async def main(): model = Model() try: await model.connect_current() print('There are {} applications'.format(len(model.applications))) finally: if model.is_connected(): print('Disconnecting from model') await model.disconnect()
async def watch(): model = Model() await model.connect() allwatcher = client.AllWatcherFacade.from_connection(model.connection()) while True: change = await allwatcher.Next() for delta in change.deltas: print(delta.deltas)
def test_relation_does_not_match_anything(self): model = Model() model._connector = mock.MagicMock() delta = _make_delta('relation', 'bar', dict(id="uuid-1234", name='foo', endpoints=[{"application-name": "foo"}])) model.state.apply_delta(delta) rel = Relation("uuid-1234", model) self.assertFalse(rel.matches(["xxx"]))
async def main(): model = Model() try: # connect to the current model with the current user, per the Juju CLI await model.connect() print('There are {} applications'.format(len(model.applications))) finally: if model.is_connected(): print('Disconnecting from model') await model.disconnect()
async def destroy(): model = Model() controller = Controller() await controller.connect(controller_endpoint, username, password, cacert) await model.connect_current() import ipdb ipdb.set_trace() await controller.destroy_model(model.info.uuid) model.disconnect() controller.disconnect()
async def main(): model = Model() # connect to current model with current user, per Juju CLI await model.connect() try: model.add_observer(MyRemoveObserver()) await model.reset(force=True) model.add_observer(MyModelObserver()) ubuntu_app = await model.deploy( 'ubuntu', application_name='ubuntu', series='trusty', channel='stable', ) ubuntu_app.on_change(asyncio.coroutine( lambda delta, old_app, new_app, model: print('App changed: {}'.format(new_app.entity_id)) )) ubuntu_app.on_remove(asyncio.coroutine( lambda delta, old_app, new_app, model: print('App removed: {}'.format(old_app.entity_id)) )) ubuntu_app.on_unit_add(asyncio.coroutine( lambda delta, old_unit, new_unit, model: print('Unit added: {}'.format(new_unit.entity_id)) )) ubuntu_app.on_unit_remove(asyncio.coroutine( lambda delta, old_unit, new_unit, model: print('Unit removed: {}'.format(old_unit.entity_id)) )) unit_a, unit_b = await ubuntu_app.add_units(count=2) unit_a.on_change(asyncio.coroutine( lambda delta, old_unit, new_unit, model: print('Unit changed: {}'.format(new_unit.entity_id)) )) await model.deploy( 'nrpe', application_name='nrpe', series='trusty', channel='stable', # subordinates must be deployed without units num_units=0, ) my_relation = await model.add_relation( 'ubuntu', 'nrpe', ) my_relation.on_remove(asyncio.coroutine( lambda delta, old_rel, new_rel, model: print('Relation removed: {}'.format(old_rel.endpoints)) )) finally: await model.disconnect()
async def set_controller_acc(c_name, access, user, username, password, url, port): try: controllers = redis.StrictRedis(host=url, port=port, charset="utf-8", decode_responses=True, db=10) users = redis.StrictRedis(host=url, port=port, charset="utf-8", decode_responses=True, db=11) con = json.loads(controllers.get(c_name)) usr = json.loads(users.get(user)) logger.info('Connecting to controller %s', c_name) controller = Controller() await controller.connect(con['endpoints'][0], username, password, con['ca-cert']) logger.info('Connected to controller %s ', c_name) await controller.grant(user, acl=access) exists = False for contr in usr['controllers']: if contr['name'] == c_name: contr['access'] = access exists = True break if not exists: usr['controllers'].append({'name': c_name, 'access': access}) logger.info('Controller access set for %s ', c_name) if access == 'superuser': model = Model() models = [] for mod in con['models']: logger.info('Setting up connection for model: %s', mod['name']) await model.connect(con['endpoints'][0], mod['uuid'], username, password, con['ca-cert']) await model.grant(user, acl='admin') models.append({'name': mod['name'], 'access': 'admin'}) logger.info('Admin Access granted for for %s:%s', c_name, mod['name']) for key in usr['ssh-keys']: await model.add_ssh_key(user, key) model.disconnect() for contro in usr['controllers']: if contro['name'] == c_name: contro['models'] = models users.set(user, json.dumps(usr)) controller.disconnect() except Exception: exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) for l in lines: logger.error(l)
async def main(): model = Model() try: # connect to the current model with the current user, per the Juju CLI await model.connect() charm = await model.charmhub.info("mattermost") print(charm) finally: if model.is_connected(): print('Disconnecting from model') await model.disconnect()
async def run(): model = Model() await model.connect_current() await model.reset(force=True) model.add_observer(MyModelObserver()) await model.deploy( 'ubuntu-0', service_name='ubuntu', series='trusty', channel='stable', )
async def test_hostname(mock_cf): model = Model() model._connector = mock.MagicMock() model.state = mock.MagicMock() # Calling hostname() when no information is available (e.g. targeting # an older controller, agent not started yet etc.) should return None model.state.entity_data = mock.MagicMock(return_value={}) mach = Machine('test', model) assert mach.hostname is None model.state.entity_data = mock.MagicMock(return_value={ 'hostname': 'thundering-herds', }) assert mach.hostname == 'thundering-herds'
async def main(): model = Model() try: # connect to the current model with the current user, per the Juju CLI await model.connect() print('There are {} applications'.format(len(model.applications))) machine = model.machines['0'] # This roughly expands to the following: # scp -i ~/.local/share/juju/ssh/juju_id_rsa -o StrictHostKeyChecking=no -q -B [email protected]:/home/ubuntu/.profile /tmp/profile await machine.scp_from("/home/ubuntu/.profile", "/tmp/profile") finally: if model.is_connected(): print('Disconnecting from model') await model.disconnect()
async def run_in_model(model_name, f, add_model_arg=False, awaitable=True): """Run the given function in the model matching the model_name :param model_name: Name of model to run function in :type model_name: str :param f: Function to run with given moel in focus :type f: functools.partial :param add_model_arg: Whether to add kwarg pointing at model to the given function before running it :type add_model_arg: boolean :param awaitable: Whether f is awaitable :type awaitable: boolean :returns: Output of f :rtype: Unknown, depends on the passed in function """ model = Model() await model.connect_model(model_name) output = None try: if add_model_arg: f.keywords.update(model=model) if awaitable: output = await f() else: output = f() finally: # Disconnect from the api server and cleanup. await model.disconnect() return output
async def test_deploy(): # Get env variables CHARM_NAME = os.environ.get('CHARM_NAME') CHARM_PATH = os.path.join(os.environ.get('CHARM_BUILD_DIR'), CHARM_NAME) model = Model() print('Connecting to model') await model.connect_current() print('Resetting model') await model.reset(force=True) try: print('Deploying {} from {}'.format(CHARM_NAME, CHARM_PATH)) application = await model.deploy(entity_url=CHARM_PATH, application_name=CHARM_NAME) print('Waiting for active') await model.block_until( lambda: all(unit.workload_status == 'blocked' for unit in application.units)) print('Removing {}'.format(CHARM_NAME)) await application.remove() finally: print('Disconnecting from model') await model.disconnect()
async def main(): model = Model() print('Connecting to model') # Connect to current model with current user, per Juju CLI await model.connect() try: print('Deploying trusted bundle application ubuntu') applications = await model.deploy( 'cs:~juju-qa/bundle/basic-trusted-1', channel='beta', trust=True, ) print('Waiting for active') await model.block_until( lambda: all(unit.workload_status == 'active' for application in applications for unit in application.units)) print("Successfully deployed!") print('Removing bundle') for application in applications: await application.remove() finally: print('Disconnecting from model') await model.disconnect()
async def scaleDownWorkersOnMachineId(controller, machineId): if not ScalerDbConnector.isRemovable(machineId): return ("Cannot remove machine: " + machineId + " because it is marked as non removable") else: defaultModel = await controller.get_model("default") await defaultModel.get_status() model = Model() await model.connect() for units in defaultModel.units.items(): if units[1].machine is not None: if units[1].machine.entity_id == machineId: unitName = units[1].entity_id machineName = units[1].machine.entity_id machineToRemove = units[1].machine await units[1].remove() await machineToRemove.remove() ScalerDbConnector.deleteMachine(machineId) await model.disconnect() await controller.disconnect() return "Removed unit: " + unitName + " and machine: " + machineName await model.disconnect() await controller.disconnect() return "fail"
async def model(request, tools): model = Model() await model.connect(tools.connection) if request.config.getoption("--is-upgrade"): upgrade_snap_channel = request.config.getoption( "--upgrade-snap-channel") upgrade_charm_channel = request.config.getoption( "--upgrade-charm-channel") if not upgrade_snap_channel and upgrade_charm_channel: raise Exception( "Must have both snap and charm upgrade " "channels set to perform upgrade prior to validation test.") print("Upgrading charms") await upgrade_charms(model, upgrade_charm_channel, tools) print("Upgrading snaps") await upgrade_snaps(model, upgrade_snap_channel, tools) if request.config.getoption("--snapd-upgrade"): snapd_channel = request.config.getoption("--snapd-channel") await log_snap_versions(model, prefix="Before") for unit in model.units.values(): if unit.dead: continue await unit.run(f"sudo snap refresh core --{snapd_channel}") await unit.run(f"sudo snap refresh snapd --{snapd_channel}") await log_snap_versions(model, prefix="After") yield model await model.disconnect()
async def main(): model = Model() print('Connecting to model') # connect to current model with current user, per Juju CLI await model.connect() try: print('Deploying local-charm') base_dir = Path(__file__).absolute().parent.parent charm_path = '{}/tests/integration/oci-image-charm'.format(base_dir) resources = {"oci-image": "ubuntu/latest"} application = await model.deploy( charm_path, resources=resources, ) print('Waiting for active') await model.block_until( lambda: all(unit.workload_status == 'active' for unit in application.units), timeout=120, ) print('Removing Charm') await application.remove() finally: print('Disconnecting from model') await model.disconnect()
async def test_expose_with_exposed_endpoints_as_raw_dict(self, mock_conn): mock_facade_version = mock.MagicMock(return_value=13) mock_facade = mock.MagicMock(name="application_facade") mock_facade().Expose.return_value = asyncio.Future() mock_facade().Expose.return_value.set_result([]) app = Application(entity_id="app-id", model=Model()) app.name = "panther" app._facade = mock_facade app._facade_version = mock_facade_version # Check that if we pass a dict as would be the case when processing an # expose change, it gets correctly converted to ExposedEndpoint values, # validated and converted to a dictionary with the right format before # it gets passed to the facade. await app.expose(exposed_endpoints={ "": { "expose-to-spaces": ["alpha"], "expose-to-cidrs": ["0.0.0.0/0"] } }) mock_facade().Expose.assert_called_once_with( application="panther", exposed_endpoints={ "": { "expose-to-spaces": ["alpha"], "expose-to-cidrs": ["0.0.0.0/0"] } })
async def main(): model = Model() # connect to current model with current user, per Juju CLI await model.connect() ubuntu_app = await model.deploy( 'cs:mysql', application_name='mysql', series='trusty', channel='stable', config={ 'tuning-level': 'safest', }, constraints={ 'mem': 256 * MB, }, ) # update and check app config await ubuntu_app.set_config({'tuning-level': 'fast'}) config = await ubuntu_app.get_config() assert(config['tuning-level']['value'] == 'fast') # update and check app constraints await ubuntu_app.set_constraints({'mem': 512 * MB}) constraints = await ubuntu_app.get_constraints() assert(constraints['mem'] == 512 * MB) await model.disconnect()
async def main(): model = Model() print('Connecting to model') # connect to current model with current user, per Juju CLI await model.connect() try: print('Deploying ubuntu') application = await model.deploy( 'cs:ubuntu-10', application_name='ubuntu', series='trusty', channel='stable', ) print('Waiting for active') await model.block_until( lambda: all(unit.workload_status == 'active' for unit in application.units)) print('Removing ubuntu') await application.remove() finally: print('Disconnecting from model') await model.disconnect()
async def test_wait_for_active_status(self): # create a custom apps mock from types import SimpleNamespace apps = {"dummy_app": SimpleNamespace( status="active", units=[SimpleNamespace( name="mockunit/0", workload_status="active", workload_status_message="workload_status_message", machine=None, agent_status="idle", )], )} with patch.object(Model, 'applications', new_callable=PropertyMock) as mock_apps: mock_apps.return_value = apps m = Model() # pass "active" via `status` (str) await m.wait_for_idle(apps=["dummy_app"], status="active") # pass "active" via `wait_for_active` (bool; deprecated) await m.wait_for_idle(apps=["dummy_app"], wait_for_active=True) # use both `status` and `wait_for_active` - `wait_for_active` takes precedence await m.wait_for_idle(apps=["dummy_app"], wait_for_active=True, status="doesn't matter") mock_apps.assert_called_with()
async def test_normal_use(self, mock_connect, mock_disconnect): async with Model() as model: self.assertTrue(isinstance(model, Model)) self.assertTrue(mock_connect.called) self.assertTrue(mock_disconnect.called)
async def remove_ssh_key(usr, pwd, ssh_key, url, port, username): try: controllers = redis.StrictRedis(host=url, port=port, charset="utf-8", decode_responses=True, db=10) users = redis.StrictRedis(host=url, port=port, charset="utf-8", decode_responses=True, db=11) user = json.loads(users.get(username)) if ssh_key in user['ssh-keys']: user['ssh-keys'].remove(ssh_key) users.set(username, json.dumps(user)) for con in user['controllers']: for mod in con['models']: controller = json.loads(controllers.get(con['name'])) for modl in controller['models']: if modl['name'] == mod['name']: model = Model() logger.info( 'Setting up Modelconnection for model: %s', mod['name']) await model.connect(controller['endpoints'][0], modl['uuid'], usr, pwd, controller['ca-cert']) await model.remove_ssh_key(username, ssh_key) await model.disconnect() except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) for l in lines: logger.error(l)
async def run(): model = Model() await model.connect_current() await model.reset(force=True) ubuntu_app = await model.deploy( 'mysql', service_name='mysql', series='trusty', channel='stable', config={ 'tuning-level': 'safest', }, constraints={ 'mem': 256 * MB, }, ) # update and check app config await ubuntu_app.set_config({'tuning-level': 'fast'}) config = await ubuntu_app.get_config() assert(config['tuning-level']['value'] == 'fast') # update and check app constraints await ubuntu_app.set_constraints({'mem': 512 * MB}) constraints = await ubuntu_app.get_constraints() assert(constraints['mem'] == 512 * MB) await model.disconnect() model.loop.stop()
async def add_unit(c_name, m_name, usr, pwd, url, port, app_name, amount, target): try: controllers = redis.StrictRedis(host=url, port=port, charset="utf-8", decode_responses=True, db=10) controller = json.loads(controllers.get(c_name)) model = Model() logger.info('Setting up Model connection for %s:%s', c_name, m_name) for mod in controller['models']: if mod['name'] == m_name: await model.connect(controller['endpoints'][0], mod['uuid'], usr, pwd, controller['ca-cert']) for app, entity in model.state.applications.items(): if app == app_name: logger.info('Adding units to %s', app_name) if target == 'None': target = None await entity.add_unit(count=int(amount), to=target) logger.info('Units added to %s', app_name) except Exception as e: exc_type, exc_value, exc_traceback = sys.exc_info() lines = traceback.format_exception(exc_type, exc_value, exc_traceback) for l in lines: logger.error(l) finally: if 'model' in locals(): await model.disconnect()
async def model(controller): """Return the model for the test.""" model_name = os.getenv("PYTEST_MODEL") if model_name: # Reuse existing model _model = Model() full_name = "{}:{}".format(controller.controller_name, os.getenv("PYTEST_MODEL")) try: await _model.connect(full_name) except JujuConnectionError: # Let's create it since it's missing _model = await controller.add_model( model_name, cloud_name=os.getenv("PYTEST_CLOUD_NAME"), region=os.getenv("PYTEST_CLOUD_REGION"), ) else: # Create a new random model model_name = "functest-{}".format(str(uuid.uuid4())[-12:]) _model = await controller.add_model( model_name, cloud_name=os.getenv("PYTEST_CLOUD_NAME"), region=os.getenv("PYTEST_CLOUD_REGION"), ) # https://github.com/juju/python-libjuju/issues/267 subprocess.check_call(["juju", "models"]) while model_name not in await controller.list_models(): await asyncio.sleep(1) yield _model await _model.disconnect() if not os.getenv("PYTEST_KEEP_MODEL"): await controller.destroy_model(model_name) while model_name in await controller.list_models(): await asyncio.sleep(1)
async def model(request, event_loop, connection_name): event_loop.set_exception_handler(lambda l, _: l.stop()) model = Model(event_loop) await model.connect(connection_name) if request.config.getoption("--is-upgrade"): upgrade_snap_channel = request.config.getoption( "--upgrade-snap-channel") upgrade_charm_channel = request.config.getoption( "--upgrade-charm-channel") if not upgrade_snap_channel and upgrade_charm_channel: raise Exception( "Must have both snap and charm upgrade channels set to perform upgrade prior to validation test." ) print("Upgrading charms") await upgrade_charms(model, upgrade_charm_channel) print("Upgrading snaps") await upgrade_snaps(model, upgrade_snap_channel) if request.config.getoption("--snapd-upgrade"): snapd_channel = request.config.getoption("--snapd-channel") cmd = f"sudo snap refresh core --{snapd_channel}" cloudinit_userdata = {"postruncmd": [cmd]} cloudinit_userdata_str = yaml.dump(cloudinit_userdata) await model.set_config({"cloudinit-userdata": cloudinit_userdata_str}) await model.deploy("cs:~containers/charmed-kubernetes") await log_snap_versions(model, prefix="Before") await asyncify(_juju_wait)() await log_snap_versions(model, prefix="After") yield model await model.disconnect()
async def main(): model = Model() try: # connect to the current model with the current user, per the Juju CLI await model.connect() # do a partial query so that we get more results. charms = await model.charmhub.find("kuber") print("Bundle\tName") for resp in charms.result: print("{}\t{}".format("N" if resp.type_ == "charm" else "Y", resp.name)) finally: if model.is_connected(): print('Disconnecting from model') await model.disconnect()
def test_get_series(): from juju.model import Model model = Model() entity = { 'Meta': { 'supported-series': { 'SupportedSeries': [ 'xenial', 'trusty', ], }, }, } assert model._get_series('cs:trusty/ubuntu', entity) == 'trusty' assert model._get_series('xenial/ubuntu', entity) == 'xenial' assert model._get_series('~foo/xenial/ubuntu', entity) == 'xenial' assert model._get_series('~foo/ubuntu', entity) == 'xenial' assert model._get_series('ubuntu', entity) == 'xenial' assert model._get_series('cs:ubuntu', entity) == 'xenial'
async def watch_model(): model = Model() # connect to current model with current user, per Juju CLI await model.connect() model.add_observer(on_model_change)