def test_network_get(self): network_get_out = '''{ "bind-addresses": [ { "mac-address": "", "interface-name": "", "addresses": [ { "hostname": "", "value": "192.0.2.2", "cidr": "" } ] } ], "egress-subnets": [ "192.0.2.2/32" ], "ingress-addresses": [ "192.0.2.2" ] }''' fake_script( self, 'network-get', f'''[ "$1" = deadbeef ] && echo '{network_get_out}' || exit 1''') network_info = self.backend.network_get('deadbeef') self.assertEqual(network_info, json.loads(network_get_out)) self.assertEqual(fake_script_calls(self, clear=True), [['network-get', 'deadbeef', '--format=json']]) network_info = self.backend.network_get('deadbeef', 1) self.assertEqual(network_info, json.loads(network_get_out)) self.assertEqual( fake_script_calls(self, clear=True), [['network-get', 'deadbeef', '-r', '1', '--format=json']])
def test_storage(self): # TODO: (jam) 2020-05-07 Harness doesn't yet expose storage-get issue #263 meta = ops.charm.CharmMeta() meta.storages = {'disks': None, 'data': None} model = ops.model.Model('myapp/0', meta, ops.model._ModelBackend()) fake_script(self, 'storage-list', ''' if [ "$1" = disks ]; then echo '["disks/0", "disks/1"]' else echo '[]' fi ''') fake_script(self, 'storage-get', ''' if [ "$2" = disks/0 ]; then echo '"/var/srv/disks/0"' elif [ "$2" = disks/1 ]; then echo '"/var/srv/disks/1"' else exit 2 fi ''') fake_script(self, 'storage-add', '') self.assertEqual(len(model.storages), 2) self.assertEqual(model.storages.keys(), meta.storages.keys()) self.assertIn('disks', model.storages) test_cases = { 0: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/0')}, 1: {'name': 'disks', 'location': pathlib.Path('/var/srv/disks/1')}, } for storage in model.storages['disks']: self.assertEqual(storage.name, 'disks') self.assertIn(storage.id, test_cases) self.assertEqual(storage.name, test_cases[storage.id]['name']) self.assertEqual(storage.location, test_cases[storage.id]['location']) self.assertEqual(fake_script_calls(self, clear=True), [ ['storage-list', 'disks', '--format=json'], ['storage-get', '-s', 'disks/0', 'location', '--format=json'], ['storage-get', '-s', 'disks/1', 'location', '--format=json'], ]) self.assertSequenceEqual(model.storages['data'], []) model.storages.request('data', count=3) self.assertEqual(fake_script_calls(self), [ ['storage-list', 'data', '--format=json'], ['storage-add', 'data=3'], ]) # Try to add storage not present in charm metadata. with self.assertRaises(ops.model.ModelError): model.storages.request('deadbeef') # Invalid count parameter types. for count_v in [None, False, 2.0, 'a', b'beef', object]: with self.assertRaises(TypeError): model.storages.request('data', count_v)
def test_juju_log(self): fake_script(self, 'juju-log', 'exit 0') self.backend.juju_log('WARNING', 'foo') self.assertEqual(fake_script_calls(self, clear=True), [['juju-log', '--log-level', 'WARNING', 'foo']]) with self.assertRaises(TypeError): self.backend.juju_log('DEBUG') self.assertEqual(fake_script_calls(self, clear=True), []) fake_script(self, 'juju-log', 'exit 1') with self.assertRaises(ops.model.ModelError): self.backend.juju_log('BAR', 'foo') self.assertEqual(fake_script_calls(self, clear=True), [['juju-log', '--log-level', 'BAR', 'foo']])
def test_action_get_error(self): fake_script(self, 'action-get', '') fake_script(self, 'action-get', f'echo fooerror >&2 ; exit 1') with self.assertRaises(ops.model.ModelError): self.backend.action_get() calls = [['action-get', '--format=json']] self.assertEqual(fake_script_calls(self, clear=True), calls)
def test_relation_set_fail(self): fake_script(self, 'relation-ids', """[ "$1" = db2 ] && echo '["db2:5"]' || echo '[]'""") fake_script(self, 'relation-list', """[ "$2" = 5 ] && echo '["remoteapp1/0"]' || exit 2""") fake_script( self, 'relation-get', """([ "$2" = 5 ] && [ "$4" = "myapp/0" ]) && echo '{"host": "myapp-0"}' || exit 2""" ) fake_script(self, 'relation-set', 'exit 2') rel_db2 = self.model.relations['db2'][0] # Force memory cache to be loaded. self.assertIn('host', rel_db2.data[self.model.unit]) with self.assertRaises(ops.model.ModelError): rel_db2.data[self.model.unit]['host'] = 'bar' self.assertEqual(rel_db2.data[self.model.unit]['host'], 'myapp-0') with self.assertRaises(ops.model.ModelError): del rel_db2.data[self.model.unit]['host'] self.assertIn('host', rel_db2.data[self.model.unit]) self.assertEqual( fake_script_calls(self), [['relation-ids', 'db2', '--format=json'], ['relation-list', '-r', '5', '--format=json'], [ 'relation-get', '-r', '5', '-', 'myapp/0', '--app=False', '--format=json' ], ['relation-set', '-r', '5', 'host=bar', '--app=False'], ['relation-set', '-r', '5', 'host=', '--app=False']])
def test_unit_relation_data(self): fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") fake_script( self, 'relation-get', """([ "$2" = 4 ] && [ "$4" = "remoteapp1/0" ]) && echo '{"host": "remoteapp1-0"}' || exit 2""" ) random_unit = self.model._cache.get(ops.model.Unit, 'randomunit/0') with self.assertRaises(KeyError): self.model.get_relation('db1').data[random_unit] remoteapp1_0 = next( filter(lambda u: u.name == 'remoteapp1/0', self.model.get_relation('db1').units)) self.assertEqual( self.model.get_relation('db1').data[remoteapp1_0], {'host': 'remoteapp1-0'}) self.assertEqual(fake_script_calls(self), [['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json'], [ 'relation-get', '-r', '4', '-', 'remoteapp1/0', '--app=False', '--format=json' ]])
def test_action_set_error(self): fake_script(self, 'action-get', '') fake_script(self, 'action-set', f'echo fooerror >&2 ; exit 1') with self.assertRaises(ops.model.ModelError): self.backend.action_set({'foo': 'bar', 'dead': 'beef cafe'}) calls = [["action-set", "foo=bar", "dead=beef cafe"]] self.assertEqual(fake_script_calls(self, clear=True), calls)
def test_application_version_set_invalid(self): fake_script(self, 'application-version-set', 'exit 0') with self.assertRaises(TypeError): self.backend.application_version_set(2) with self.assertRaises(TypeError): self.backend.application_version_set() self.assertEqual(fake_script_calls(self), [])
def test_relation_data_modify_remote(self): fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") fake_script( self, 'relation-get', """([ "$2" = 4 ] && [ "$4" = "remoteapp1/0" ]) && echo '{"host": "remoteapp1-0"}' || exit 2""" ) rel_db1 = self.model.get_relation('db1') remoteapp1_0 = next( filter(lambda u: u.name == 'remoteapp1/0', self.model.get_relation('db1').units)) # Force memory cache to be loaded. self.assertIn('host', rel_db1.data[remoteapp1_0]) with self.assertRaises(ops.model.RelationDataError): rel_db1.data[remoteapp1_0]['foo'] = 'bar' self.assertNotIn('foo', rel_db1.data[remoteapp1_0]) self.assertEqual(fake_script_calls(self), [['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json'], [ 'relation-get', '-r', '4', '-', 'remoteapp1/0', '--app=False', '--format=json' ]])
def test_network_get_errors(self): err_no_endpoint = 'ERROR no network config found for binding "$2"' err_no_rel = 'ERROR invalid value "$3" for option -r: relation not found' test_cases = [ ( lambda: fake_script(self, 'network-get', f'echo {err_no_endpoint} >&2 ; exit 1'), lambda: self.backend.network_get("deadbeef"), ops.model.ModelError, [['network-get', 'deadbeef', '--format=json']], ), ( lambda: fake_script(self, 'network-get', f'echo {err_no_rel} >&2 ; exit 2'), lambda: self.backend.network_get("deadbeef", 3), ops.model.RelationNotFoundError, [['network-get', 'deadbeef', '-r', '3', '--format=json']], ) ] for do_fake, run, exception, calls in test_cases: do_fake() with self.assertRaises(exception): run() self.assertEqual(fake_script_calls(self, clear=True), calls)
def test_app_relation_data_modify_local_as_minion(self): fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") fake_script( self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""" ) fake_script( self, 'relation-get', """[ "$2" = 4 ] && [ "$4" = myapp ] && echo '{"password": "******"}' || exit 2""" ) fake_script(self, 'is-leader', 'echo false') local_app = self.model.unit.app rel_db1 = self.model.get_relation('db1') self.assertEqual(rel_db1.data[local_app], {'password': '******'}) with self.assertRaises(ops.model.RelationDataError): rel_db1.data[local_app]['password'] = '******' self.assertEqual(fake_script_calls(self), [ ['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json'], [ 'relation-get', '-r', '4', '-', 'myapp', '--app=True', '--format=json' ], ['is-leader', '--format=json'], ])
def test_storage_tool_errors(self): test_cases = [( lambda: fake_script(self, 'storage-list', 'echo fooerror >&2 ; exit 1'), lambda: self.backend.storage_list('foobar'), ops.model.ModelError, [['storage-list', 'foobar', '--format=json']], ), ( lambda: fake_script(self, 'storage-get', 'echo fooerror >&2 ; exit 1'), lambda: self.backend.storage_get('foobar', 'someattr'), ops.model.ModelError, [['storage-get', '-s', 'foobar', 'someattr', '--format=json']], ), ( lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), lambda: self.backend.storage_add('foobar', count=2), ops.model.ModelError, [['storage-add', 'foobar=2']], ), ( lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), lambda: self.backend.storage_add('foobar', count=object), TypeError, [], ), ( lambda: fake_script(self, 'storage-add', 'echo fooerror >&2 ; exit 1'), lambda: self.backend.storage_add('foobar', count=True), TypeError, [], )] for do_fake, run, exception, calls in test_cases: do_fake() with self.assertRaises(exception): run() self.assertEqual(fake_script_calls(self, clear=True), calls)
def test_relation_data_del_key(self): fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") fake_script(self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0"]' || exit 2""") fake_script(self, 'relation-set', '''[ "$2" = 4 ] && exit 0 || exit 2''') fake_script( self, 'relation-get', """([ "$2" = 4 ] && [ "$4" = "myapp/0" ]) && echo '{"host": "bar"}' || exit 2""" ) rel_db1 = self.model.get_relation('db1') # Force memory cache to be loaded. self.assertIn('host', rel_db1.data[self.model.unit]) del rel_db1.data[self.model.unit]['host'] fake_script( self, 'relation-get', """([ "$2" = 4 ] && [ "$4" = "myapp/0" ]) && echo '{}' || exit 2""" ) self.assertNotIn('host', rel_db1.data[self.model.unit]) self.assertEqual( fake_script_calls(self), [['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json'], [ 'relation-get', '-r', '4', '-', 'myapp/0', '--app=False', '--format=json' ], ['relation-set', '-r', '4', 'host=', '--app=False']])
def test_remote_app_status(self): fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") fake_script( self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""" ) remoteapp1 = self.model.get_relation('db1').app # Remote application status is always unknown. self.assertIsInstance(remoteapp1.status, ops.model.UnknownStatus) test_statuses = ( ops.model.UnknownStatus(), ops.model.ActiveStatus(), ops.model.MaintenanceStatus('Upgrading software'), ops.model.BlockedStatus('Awaiting manual resolution'), ops.model.WaitingStatus('Awaiting related app updates'), ) for target_status in test_statuses: with self.assertRaises(RuntimeError): remoteapp1.status = target_status self.assertEqual(fake_script_calls(self, clear=True), [ ['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json'], ])
def test_remote_app_relation_data(self): fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") fake_script( self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""" ) fake_script( self, 'relation-get', """[ "$2" = 4 ] && [ "$4" = remoteapp1 ] && echo '{"secret": "cafedeadbeef"}' || exit 2""" ) # Try to get relation data for an invalid remote application. random_app = self.model._cache.get(ops.model.Application, 'randomapp') with self.assertRaises(KeyError): self.model.get_relation('db1').data[random_app] remoteapp1 = self.model.get_relation('db1').app self.assertEqual( self.model.get_relation('db1').data[remoteapp1], {'secret': 'cafedeadbeef'}) self.assertEqual(fake_script_calls(self), [ ['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json'], [ 'relation-get', '-r', '4', '-', 'remoteapp1', '--app=True', '--format=json' ], ])
def test_action_log_error(self): fake_script(self, 'action-get', '') fake_script(self, 'action-log', f'echo fooerror >&2 ; exit 1') with self.assertRaises(ops.model.ModelError): self.backend.action_log('log-message') calls = [["action-log", "log-message"]] self.assertEqual(fake_script_calls(self, clear=True), calls)
def test_action_get(self): fake_script(self, 'action-get', """echo '{"foo-name": "bar", "silent": false}'""") params = self.backend.action_get() self.assertEqual(params['foo-name'], 'bar') self.assertEqual(params['silent'], False) self.assertEqual(fake_script_calls(self), [['action-get', '--format=json']])
def test_pod_spec(self): # TODO: (jam) 2020-05-07 Harness doesn't yet expose pod-spec-set issue #261 meta = ops.charm.CharmMeta.from_yaml(''' name: myapp ''') model = ops.model.Model('myapp/0', meta, ops.model._ModelBackend()) fake_script(self, 'pod-spec-set', """ cat $2 > $(dirname $0)/spec.json [[ -n $4 ]] && cat $4 > $(dirname $0)/k8s_res.json || true """) fake_script(self, 'is-leader', 'echo true') spec_path = self.fake_script_path / 'spec.json' k8s_res_path = self.fake_script_path / 'k8s_res.json' def check_calls(calls): # There may 1 or 2 calls because of is-leader. self.assertLessEqual(len(fake_calls), 2) pod_spec_call = next(filter(lambda c: c[0] == 'pod-spec-set', calls)) self.assertEqual(pod_spec_call[:2], ['pod-spec-set', '--file']) # 8 bytes are used as of python 3.4.0, see Python bug #12015. # Other characters are from POSIX 3.282 (Portable Filename # Character Set) a subset of which Python's mkdtemp uses. self.assertRegex(pod_spec_call[2], '.*/tmp[A-Za-z0-9._-]{8}-pod-spec-set') model.pod.set_spec({'foo': 'bar'}) self.assertEqual(spec_path.read_text(), '{"foo": "bar"}') self.assertFalse(k8s_res_path.exists()) fake_calls = fake_script_calls(self, clear=True) check_calls(fake_calls) model.pod.set_spec({'bar': 'foo'}, {'qux': 'baz'}) self.assertEqual(spec_path.read_text(), '{"bar": "foo"}') self.assertEqual(k8s_res_path.read_text(), '{"qux": "baz"}') fake_calls = fake_script_calls(self, clear=True) check_calls(fake_calls) # Create a new model to drop is-leader caching result. self.backend = ops.model._ModelBackend() meta = ops.charm.CharmMeta() model = ops.model.Model('myapp/0', meta, self.backend) fake_script(self, 'is-leader', 'echo false') with self.assertRaises(ops.model.ModelError): model.pod.set_spec({'foo': 'bar'})
def test_binding_by_relation_name(self): fake_script(self, 'network-get', '''[ "$1" = db0 ] && echo '{}' || exit 1'''.format(self.network_get_out)) binding_name = 'db0' expected_calls = [['network-get', 'db0', '--format=json']] binding = self.model.get_binding(binding_name) self._check_binding_data(binding_name, binding) self.assertEqual(fake_script_calls(self, clear=True), expected_calls)
def test_local_set_invalid_status(self): fake_script(self, 'status-set', 'exit 1') fake_script(self, 'is-leader', 'echo true') with self.assertRaises(ops.model.ModelError): self.model.unit.status = ops.model.UnknownStatus() self.assertEqual(fake_script_calls(self, True), [ ['status-set', '--application=False', 'unknown', ''], ]) with self.assertRaises(ops.model.ModelError): self.model.app.status = ops.model.UnknownStatus() # A leadership check is needed for application status. self.assertEqual(fake_script_calls(self, True), [ ['is-leader', '--format=json'], ['status-set', '--application=True', 'unknown', ''], ])
def test_is_leader(self): def check_remote_units(): fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") fake_script( self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""" ) # Cannot determine leadership for remote units. for u in self.model.get_relation('db1').units: with self.assertRaises(RuntimeError): u.is_leader() fake_script(self, 'is-leader', 'echo true') self.assertTrue(self.model.unit.is_leader()) check_remote_units() # Create a new model and backend to drop a cached is-leader output. self.backend = ops.model.ModelBackend() meta = ops.charm.CharmMeta() meta.relations = { 'db0': RelationMeta('provides', 'db0', { 'interface': 'db0', 'scope': 'global' }), 'db1': RelationMeta('requires', 'db1', { 'interface': 'db1', 'scope': 'global' }), 'db2': RelationMeta('peers', 'db2', { 'interface': 'db2', 'scope': 'global' }), } self.model = ops.model.Model('myapp/0', meta, self.backend) fake_script(self, 'is-leader', 'echo false') self.assertFalse(self.model.unit.is_leader()) check_remote_units() self.assertEqual(fake_script_calls(self), [ ['is-leader', '--format=json'], ['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json'], ['is-leader', '--format=json'], ['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json'], ])
def test_get(self): fake_script(self, 'state-get', dedent(""" echo 'foo: "bar"' """)) backend = storage._JujuStorageBackend() value = backend.get('key') self.assertEqual(value, {'foo': 'bar'}) self.assertEqual(fake_script_calls(self, clear=True), [ ['state-get', 'key'], ])
def test_local_set_valid_unit_status(self): test_cases = [ ( ops.model.ActiveStatus('Green'), lambda: fake_script(self, 'status-set', 'exit 0'), lambda: self.assertEqual(fake_script_calls(self, True), [[ 'status-set', '--application=False', 'active', 'Green' ]]), ), ( ops.model.MaintenanceStatus('Yellow'), lambda: fake_script(self, 'status-set', 'exit 0'), lambda: self.assertEqual(fake_script_calls(self, True), [[ 'status-set', '--application=False', 'maintenance', 'Yellow' ]]), ), ( ops.model.BlockedStatus('Red'), lambda: fake_script(self, 'status-set', 'exit 0'), lambda: self.assertEqual(fake_script_calls(self, True), [[ 'status-set', '--application=False', 'blocked', 'Red' ]]), ), ( ops.model.WaitingStatus('White'), lambda: fake_script(self, 'status-set', 'exit 0'), lambda: self.assertEqual(fake_script_calls(self, True), [[ 'status-set', '--application=False', 'waiting', 'White' ]]), ) ] for target_status, setup_tools, check_tool_calls in test_cases: setup_tools() self.model.unit.status = target_status self.assertEqual(self.model.unit.status, target_status) check_tool_calls()
def test_local_set_valid_app_status(self): fake_script(self, 'is-leader', 'echo true') test_cases = [ ( ops.model.ActiveStatus(), lambda: fake_script(self, 'status-set', 'exit 0'), lambda: self.assertIn([ 'status-set', '--application=True', 'active', '' ], fake_script_calls(self, True)), ), ( ops.model.MaintenanceStatus('Yellow'), lambda: fake_script(self, 'status-set', 'exit 0'), lambda: self.assertIn([ 'status-set', '--application=True', 'maintenance', 'Yellow' ], fake_script_calls(self, True)), ), ( ops.model.BlockedStatus('Red'), lambda: fake_script(self, 'status-set', 'exit 0'), lambda: self.assertIn([ 'status-set', '--application=True', 'blocked', 'Red' ], fake_script_calls(self, True)), ), ( ops.model.WaitingStatus('White'), lambda: fake_script(self, 'status-set', 'exit 0'), lambda: self.assertIn([ 'status-set', '--application=True', 'waiting', 'White' ], fake_script_calls(self, True)), ) ] for target_status, setup_tools, check_tool_calls in test_cases: setup_tools() self.model.app.status = target_status self.assertEqual(self.model.app.status, target_status) check_tool_calls()
def test_binding_by_relation(self): fake_script(self, 'network-get', '''[ "$1" = db0 ] && echo '{}' || exit 1'''.format(self.network_get_out)) binding_name = 'db0' expected_calls = [ ['relation-ids', 'db0', '--format=json'], # The two invocations below are due to the get_relation call. ['relation-list', '-r', '4', '--format=json'], ['network-get', 'db0', '-r', '4', '--format=json'], ] binding = self.model.get_binding(self.model.get_relation(binding_name)) self._check_binding_data(binding_name, binding) self.assertEqual(fake_script_calls(self, clear=True), expected_calls)
def test_config(self): fake_script(self, 'config-get', """echo '{"foo":"foo","bar":1,"qux":true}'""") self.assertEqual(self.model.config, { 'foo': 'foo', 'bar': 1, 'qux': True, }) with self.assertRaises(TypeError): # Confirm that we cannot modify config values. self.model.config['foo'] = 'bar' self.assertEqual(fake_script_calls(self), [['config-get', '--format=json']])
def test_remote_units_is_our(self): fake_script(self, 'relation-ids', """[ "$1" = db1 ] && echo '["db1:4"]' || echo '[]'""") fake_script( self, 'relation-list', """[ "$2" = 4 ] && echo '["remoteapp1/0", "remoteapp1/1"]' || exit 2""" ) for u in self.model.get_relation('db1').units: self.assertFalse(u._is_our_unit) self.assertFalse(u.app._is_our_app) self.assertEqual(fake_script_calls(self), [['relation-ids', 'db1', '--format=json'], ['relation-list', '-r', '4', '--format=json']])
def test_valid_metrics(self): fake_script(self, 'add-metric', 'exit 0') test_cases = [( OrderedDict([('foo', 42), ('b-ar', 4.5), ('ba_-z', 4.5), ('a', 1)]), OrderedDict([('de', 'ad'), ('be', 'ef_ -')]), [['add-metric', '--labels', 'de=ad,be=ef_ -', 'foo=42', 'b-ar=4.5', 'ba_-z=4.5', 'a=1']] ), ( OrderedDict([('foo1', 0), ('b2r', 4.5)]), OrderedDict([('d3', 'aд'), ('b33f', '3_ -')]), [['add-metric', '--labels', 'd3=aд,b33f=3_ -', 'foo1=0', 'b2r=4.5']], )] for metrics, labels, expected_calls in test_cases: self.backend.add_metrics(metrics, labels) self.assertEqual(fake_script_calls(self, clear=True), expected_calls)
def test_local_set_invalid_status(self): # juju return exit code 1 if you ask to set status to 'unknown' meta = ops.charm.CharmMeta.from_yaml(''' name: myapp ''') model = ops.model.Model('myapp/0', meta, self.backend) fake_script(self, 'status-set', 'exit 1') fake_script(self, 'is-leader', 'echo true') with self.assertRaises(ops.model.ModelError): model.unit.status = ops.model.UnknownStatus() self.assertEqual(fake_script_calls(self, True), [ ['status-set', '--application=False', 'unknown', ''], ]) with self.assertRaises(ops.model.ModelError): model.app.status = ops.model.UnknownStatus() # A leadership check is needed for application status. self.assertEqual(fake_script_calls(self, True), [ ['is-leader', '--format=json'], ['status-set', '--application=True', 'unknown', ''], ])
def test_relations_keys(self): fake_script( self, 'relation-ids', """[ "$1" = db2 ] && echo '["db2:5", "db2:6"]' || echo '[]'""") fake_script( self, 'relation-list', """([ "$2" = 5 ] && echo '["remoteapp1/0", "remoteapp1/1"]') || ([ "$2" = 6 ] && echo '["remoteapp2/0"]') || exit 2""" ) for relation in self.model.relations['db2']: self.assertIn(self.model.unit, relation.data) unit_from_rel = next( filter(lambda u: u.name == 'myapp/0', relation.data.keys())) self.assertIs(self.model.unit, unit_from_rel) self.assertEqual(fake_script_calls(self), [['relation-ids', 'db2', '--format=json'], ['relation-list', '-r', '5', '--format=json'], ['relation-list', '-r', '6', '--format=json']])