def assertRaises(self, excClass, callableObj, *args, **kwargs): """Fail unless an exception of class excClass is thrown by callableObj when invoked with arguments args and keyword arguments kwargs. If a different type of exception is thrown, it will not be caught, and the test case will be deemed to have suffered an error, exactly as for an unexpected exception. """ class ReRaiseOtherTypes: def match(self, matchee): if not issubclass(matchee[0], excClass): reraise(*matchee) class CaptureMatchee: def match(self, matchee): self.matchee = matchee[1] capture = CaptureMatchee() matcher = Raises( MatchesAll(ReRaiseOtherTypes(), MatchesException(excClass), capture)) our_callable = Nullary(callableObj, *args, **kwargs) self.assertThat(our_callable, matcher) return capture.matchee
def test_start_up_binds_first_of_real_endpoint_options(self): service = RegionService(sentinel.ipcWorker) # endpoint_1.listen(...) will bind to a random high-numbered port. endpoint_1 = TCP4ServerEndpoint(reactor, 0) # endpoint_2.listen(...), if attempted, will crash because only root # (or a user with explicit capabilities) can do stuff like that. It's # a reasonable assumption that the user running these tests is not # root, but we'll check the port number later too to be sure. endpoint_2 = TCP4ServerEndpoint(reactor, 1) service.endpoints = [[endpoint_1, endpoint_2]] yield service.startService() self.addCleanup(wait_for_reactor(service.stopService)) # A single port has been bound. self.assertThat(service.ports, MatchesAll( HasLength(1), AllMatch(IsInstance(tcp.Port)))) # The port is not listening on port 1; i.e. a belt-n-braces check that # endpoint_2 was not used. [port] = service.ports self.assertThat(port.getHost().port, Not(Equals(1)))
def test_get_ports_archive_overrides_to_package_repository(self): PackageRepository.objects.all().delete() ports_url = factory.make_url(scheme='http') factory.make_PackageRepository(url=ports_url, default=True, arches=['arm64', 'armhf', 'powerpc']) response = self.client.get(reverse('maas_handler'), { "op": "get_config", "name": "ports_archive", }) self.assertThat( response, MatchesAll( # An HTTP 200 response, MatchesStructure(status_code=Equals(http.client.OK)), # with a JSON body, AfterPreprocessing(itemgetter("Content-Type"), Equals("application/json")), # containing the main_archive setting. AfterPreprocessing( lambda response: json.loads( response.content.decode(settings.DEFAULT_CHARSET)), Equals(ports_url)), ))
def test_get_reader_install(self): # Given the right configuration options, the PXE configuration is # correctly rendered. method = S390XBootMethod() params = make_kernel_parameters(self, arch="s390x", purpose="xinstall") output = method.get_reader(backend=None, kernel_params=params) # The output is a BytesReader. self.assertThat(output, IsInstance(BytesReader)) output = output.read(10000).decode("utf-8") # The template has rendered without error. PXELINUX configurations # typically start with a DEFAULT line. self.assertThat(output, StartsWith("DEFAULT ")) # The PXE parameters are all set according to the options. image_dir = compose_image_path( osystem=params.osystem, arch=params.arch, subarch=params.subarch, release=params.release, label=params.label, ) self.assertThat( output, MatchesAll( MatchesRegex( r".*^\s+KERNEL %s/%s$" % (re.escape(image_dir), params.kernel), re.MULTILINE | re.DOTALL, ), MatchesRegex( r".*^\s+INITRD %s/%s$" % (re.escape(image_dir), params.initrd), re.MULTILINE | re.DOTALL, ), MatchesRegex(r".*^\s+APPEND .+?$", re.MULTILINE | re.DOTALL), ), )
def test__saving_tag_schedules_node_population(self): clock = self.patch(tag_module, "reactor", Clock()) with post_commit_hooks: # Make a Tag by hand to trigger normal node population handling # behaviour rather than the (generally more convenient) default # behaviour in the factory. tag = Tag(name=factory.make_name("tag"), definition='true()') tag.save() # A call has been scheduled to populate tags. calls = clock.getDelayedCalls() self.assertThat(calls, HasLength(1)) [call] = calls self.assertThat( call, MatchesAll( IsInstance(DelayedCall), MatchesStructure.byEquality(time=0, func=deferToDatabase, args=(populate_tags, tag), kw={}), first_only=True, ))
def test_sets_interfaces(self): # Interfaces are set on new rack controllers. interfaces = { factory.make_name("eth0"): { "type": "physical", "mac_address": factory.make_mac_address(), "parents": [], "links": [], "enabled": True, } } rack_registered = register(interfaces=interfaces) self.assertThat( rack_registered.interface_set.all(), MatchesSetwise(*(MatchesAll( IsInstance(PhysicalInterface), MatchesStructure.byEquality( name=name, mac_address=interface["mac_address"], enabled=interface["enabled"], ), first_only=True, ) for name, interface in interfaces.items())), )
def test_get_config_ntp_server_alias_for_ntp_servers(self): ntp_servers = factory.make_hostname() + " " + factory.make_hostname() Config.objects.set_config("ntp_servers", ntp_servers) response = self.client.get( reverse("maas_handler"), {"op": "get_config", "name": "ntp_server"} ) self.assertThat( response, MatchesAll( # An HTTP 200 response, MatchesStructure(status_code=Equals(http.client.OK)), # with a JSON body, AfterPreprocessing( itemgetter("Content-Type"), Equals("application/json") ), # containing the ntp_servers setting. AfterPreprocessing( lambda response: json.loads( response.content.decode(settings.DEFAULT_CHARSET) ), Equals(ntp_servers), ), ), )
def test_responder_resource_child(self): """ When a GET request is made to the ACME challenge path, and the responder resource has a child resource at the correct path, the value of the resource should be returned. """ self.responder_resource.putChild(b'foo', Data(b'bar', 'text/plain')) response = self.client.get( 'http://localhost/.well-known/acme-challenge/foo') assert_that( response, succeeded( MatchesAll( MatchesStructure(code=Equals(200), headers=HasHeader('Content-Type', ['text/plain'])), After(methodcaller('content'), succeeded(Equals(b'bar')))))) # Sanity check that a request to a different subpath does not succeed response = self.client.get( 'http://localhost/.well-known/acme-challenge/baz') assert_that(response, succeeded(MatchesStructure(code=Equals(404))))
def test_signal_usr1(self): """ When a client calls the ``/mlb_signal/usr1`` endpoint, the correct response should be returned and the ``signalled_usr1`` flag set True. """ assert_that(self.marathon_lb.check_signalled_usr1(), Equals(False)) response = self.client.get('http://localhost/_mlb_signal/usr1') assert_that( response, succeeded( MatchesAll( MatchesStructure(code=Equals(200), headers=HasHeader('content-type', ['text/plain'])), After( methodcaller('text'), succeeded( Equals('Sent SIGUSR1 signal to marathon-lb')))))) assert_that(self.marathon_lb.check_signalled_usr1(), Equals(True)) # Signalled flag should be reset to false after it is checked assert_that(self.marathon_lb.check_signalled_usr1(), Equals(False))
def test__sets_up_fields_based_on_pod(self): request = MagicMock() pod = make_pod_with_hints() form = ComposeMachineForm(request=request, pod=pod) self.assertThat( form.fields['cores'], MatchesStructure( required=Equals(False), validators=MatchesSetwise( MatchesAll( IsInstance(MaxValueValidator), MatchesStructure(limit_value=Equals(pod.hints.cores))), MatchesAll(IsInstance(MinValueValidator), MatchesStructure(limit_value=Equals(1)))))) self.assertThat( form.fields['memory'], MatchesStructure( required=Equals(False), validators=MatchesSetwise( MatchesAll( IsInstance(MaxValueValidator), MatchesStructure( limit_value=Equals(pod.hints.memory))), MatchesAll(IsInstance(MinValueValidator), MatchesStructure(limit_value=Equals(1024)))))) self.assertThat( form.fields['architecture'], MatchesStructure(required=Equals(False), choices=MatchesSetwise(*[ Equals((architecture, architecture)) for architecture in pod.architectures ]))) self.assertThat( form.fields['cpu_speed'], MatchesStructure( required=Equals(False), validators=MatchesSetwise( MatchesAll( IsInstance(MaxValueValidator), MatchesStructure( limit_value=Equals(pod.hints.cpu_speed))), MatchesAll(IsInstance(MinValueValidator), MatchesStructure(limit_value=Equals(300))))))
assert_that(domains, Equals(['example.com', 'example2.com'])) def test_multiple_domains_whitespace(self): """ When the domain label contains multiple comma-separated domains with whitespace inbetween, the domains should be parsed into a list of domains without the whitespace. """ domains = parse_domain_label(' example.com, example2.com ') assert_that(domains, Equals(['example.com', 'example2.com'])) is_marathon_lb_sigusr_response = MatchesListwise([ # Per marathon-lb instance MatchesAll( MatchesStructure(code=Equals(200)), AfterPreprocessing( lambda r: r.text(), succeeded(Equals('Sent SIGUSR1 signal to marathon-lb')))) ]) class FailableTxacmeClient(FakeClient): """ A fake txacme client that raises an error during the CSR issuance phase if the 'error' attribute has been set. Used to very *very* roughly simulate an error while issuing a certificate. """ def __init__(self, *args, **kwargs): super(FailableTxacmeClient, self).__init__(*args, **kwargs) # Patch on support for HTTP challenge types self._challenge_types.append(challenges.HTTP01)
def test__interface_links_create_STATIC(self): origin = make_origin() Interface, Subnet = origin.Interface, origin.Subnet system_id = make_string_without_spaces() interface_data = { "system_id": system_id, "id": random.randint(0, 100), "name": make_string_without_spaces(), "type": InterfaceType.PHYSICAL.value, "links": [{ "id": random.randint(0, 100), "mode": LinkMode.LINK_UP.value, "subnet": { "id": random.randint(0, 100) }, }], } interface = Interface(interface_data) updated_data = dict(interface_data) link_id = random.randint(100, 200) subnet_id = random.randint(1, 100) updated_data["links"] = [{ "id": link_id, "mode": LinkMode.STATIC.value, "ip_address": "192.168.122.10", "subnet": { "id": subnet_id }, }] Interface._handler.link_subnet.return_value = updated_data interface.links.create( LinkMode.STATIC, subnet=Subnet(subnet_id), ip_address="192.168.122.10", default_gateway=True, force=True, ) Interface._handler.link_subnet.assert_called_once_with( system_id=interface.node.system_id, id=interface.id, mode=LinkMode.STATIC.value, subnet=subnet_id, ip_address="192.168.122.10", force=True, default_gateway=True, ) self.assertThat( interface.links, MatchesSetwise( MatchesStructure( id=Equals(link_id), mode=Equals(LinkMode.STATIC), ip_address=Equals("192.168.122.10"), subnet=MatchesAll(IsInstance(Subnet), MatchesStructure(id=Equals(subnet_id))), )), )
def test_delegates_to_agent_for_location(self, agent): """ When a request is made using the agent, the added agents are delegated to based on the URI location/authority. """ agent.add_agent(b'foo:8080', DummyAgent()) agent.add_agent(b'bar:8080', FailingAgent(RuntimeError('bar'))) agent.add_agent(b'foo:9090', FailingAgent(RuntimeError('9090'))) d = agent.request(b'GET', b'http://foo:8080') assert_that( d, succeeded( MatchesListwise([ MatchesListwise( [Equals(b'GET'), Equals(b'http://foo:8080')]), MatchesDict({ 'headers': Is(None), 'bodyProducer': Is(None) }) ]))) # Scheme doesn't matter d = agent.request(b'GET', b'https://foo:8080') assert_that( d, succeeded( MatchesListwise([ MatchesListwise( [Equals(b'GET'), Equals(b'https://foo:8080')]), MatchesDict({ 'headers': Is(None), 'bodyProducer': Is(None) }) ]))) # Path doesn't matter d = agent.request(b'GET', b'http://foo:8080/bar/baz') assert_that( d, succeeded( MatchesListwise([ MatchesListwise( [Equals(b'GET'), Equals(b'http://foo:8080/bar/baz')]), MatchesDict({ 'headers': Is(None), 'bodyProducer': Is(None) }) ]))) # Hostname *does* matter d = agent.request(b'GET', b'http://bar:8080') assert_that( d, failed( MatchesStructure( value=MatchesAll(IsInstance(RuntimeError), MatchesPredicate(str, Equals('bar')))))) # Port *does* matter d = agent.request(b'GET', b'http://foo:9090') assert_that( d, failed( MatchesStructure( value=MatchesAll(IsInstance(RuntimeError), MatchesPredicate(str, Equals('9090')))))) # Other args passed through d = agent.request(b'GET', b'http://foo:8080', 'bar', 'baz') assert_that( d, succeeded( MatchesListwise([ MatchesListwise( [Equals(b'GET'), Equals(b'http://foo:8080')]), MatchesDict({ 'headers': Equals('bar'), 'bodyProducer': Equals('baz') }) ])))
def test_that_it_works_eh(self): nowish = datetime(2014, 0o3, 24, 16, 0o7, tzinfo=UTC) security_datetime = self.patch(security, "datetime") # Make security.datetime() work like regular datetime. security_datetime.side_effect = datetime # Make security.datetime.now() return a fixed value. security_datetime.now.return_value = nowish self.assertEqual(69005220, security.get_serial()) is_valid_region_certificate = MatchesAll( IsInstance(ssl.PrivateCertificate), AfterPreprocessing( lambda cert: cert.getSubject(), Equals({"commonName": b"MAAS Region"}) ), AfterPreprocessing( lambda cert: cert.getPublicKey().original.bits(), Equals(2048) ), AfterPreprocessing( lambda cert: cert.privateKey.original.bits(), Equals(2048) ), ) class TestCertificateFunctions(MAASServerTestCase): def patch_serial(self): serial = self.getUniqueInteger() self.patch(security, "get_serial").return_value = serial return serial def test_generate_region_certificate(self): serial = self.patch_serial()
def test_compose_multiple_interface_constraints(self): pod_id = factory.make_name("pod_id") context = self.make_parameters_context() request = make_requested_machine() request.interfaces = [ RequestedMachineInterface( ifname=factory.make_name("ifname"), attach_name=factory.make_name("bridge_name"), attach_type="bridge", attach_options=None, ) for _ in range(3) ] # LXD uses 'bridged' while MAAS uses 'bridge' so convert # the nictype as this is what we expect from LXDPodDriver.compose. expected_interfaces = [{ "name": request.interfaces[i].ifname, "parent": request.interfaces[i].attach_name, "nictype": "bridged", "type": "nic", } for i in range(3)] expected_interfaces[0]["boot.priority"] = "1" driver = lxd_module.LXDPodDriver() Client = self.patch(driver, "get_client") client = Client.return_value mock_profile = Mock() mock_profile.name = random.choice(["maas", "default"]) profile_devices = { "eth0": { "name": "eth0", "nictype": "bridged", "parent": "lxdbr0", "type": "nic", }, "eth1": { "boot.priority": "1", "name": "eth1", "nictype": "bridged", "parent": "virbr1", "type": "nic", }, "root": { "boot.priority": "0", "path": "/", "pool": "default", "type": "disk", "size": "20GB", }, } mock_profile.devices = profile_devices client.profiles.get.return_value = mock_profile mock_storage_pools = Mock() client.storage_pools.all.return_value = mock_storage_pools mock_get_usable_storage_pool = self.patch(driver, "get_usable_storage_pool") usable_pool = factory.make_name("pool") mock_get_usable_storage_pool.return_value = usable_pool mock_get_best_nic_from_profile = self.patch( driver, "get_best_nic_from_profile") mock_get_best_nic_from_profile.return_value = ( "eth1", profile_devices["eth1"], ) mock_machine = Mock() client.virtual_machines.create.return_value = mock_machine mock_get_discovered_machine = self.patch(driver, "get_discovered_machine") mock_get_discovered_machine.side_effect = async_succeed( sentinel.discovered_machine) definition = { "name": request.hostname, "architecture": debian_to_kernel_architecture(request.architecture), "config": { "limits.cpu": str(request.cores), "limits.memory": str(request.memory * 1024**2), "security.secureboot": "false", }, "profiles": [mock_profile.name], "source": { "type": "none" }, "devices": { "root": { "path": "/", "type": "disk", "pool": usable_pool, "size": str(request.block_devices[0].size), "boot.priority": "0", }, expected_interfaces[0]["name"]: expected_interfaces[0], expected_interfaces[1]["name"]: expected_interfaces[1], expected_interfaces[2]["name"]: expected_interfaces[2], "eth1": { "type": "none" }, "eth0": { "type": "none" }, }, } discovered_machine, empty_hints = yield driver.compose( pod_id, context, request) self.assertThat( client.virtual_machines.create, MockCalledOnceWith(definition, wait=True), ) self.assertEquals(sentinel.discovered_machine, discovered_machine) self.assertThat( empty_hints, MatchesAll( IsInstance(DiscoveredPodHints), MatchesStructure( cores=Equals(-1), cpu_speed=Equals(-1), memory=Equals(-1), local_storage=Equals(-1), local_disks=Equals(-1), iscsi_storage=Equals(-1), ), ), )
def matches_pod(pod): return MatchesAll(matches_metadata(pod.metadata), )
def MatchesUnselectableScript(what, *selectors): return MatchesAll(IsInstance(parallel.TestScriptUnselectable), MatchesStructure.byEquality(script=what), first_only=True)
def test_make_name_does_not_include_weird_characters(self): self.assertThat( factory.make_name(size=100), MatchesAll(*[Not(Contains(char)) for char in "/ \t\n\r\\"]), )
from maasserver.utils.django_urls import reverse from provisioningserver.utils.testing import MAASIDFixture from testtools.matchers import ( Equals, GreaterThan, IsInstance, KeysEqual, LessThan, MatchesAll, MatchesDict, MatchesListwise, MatchesSetwise, ) from twisted.internet.defer import inlineCallbacks is_valid_port = MatchesAll(IsInstance(int), GreaterThan(0), LessThan(2**16)) class RPCViewTest(MAASTransactionServerTestCase): def setUp(self): super(RPCViewTest, self).setUp() self.maas_id = None def set_maas_id(maas_id): self.maas_id = maas_id self.set_maas_id = self.patch(regionservice, "set_maas_id") self.set_maas_id.side_effect = set_maas_id def get_maas_id(): return self.maas_id
# ordinarily get squashed. return Failure( amp.UnknownRemoteError( "%s: %s" % (reflect.qual(error.type), reflect.safe_str(error.value)))) d.addErrback(eb_massage_error) return d are_valid_tls_parameters = MatchesDict({ "tls_localCertificate": IsInstance(ssl.PrivateCertificate), "tls_verifyAuthorities": MatchesAll(IsInstance(Sequence), AllMatch(IsInstance(ssl.Certificate))), }) class MockClusterToRegionRPCFixtureBase(fixtures.Fixture, metaclass=ABCMeta): """Patch in a stub region RPC implementation to enable end-to-end testing. This is an abstract base class. Derive concrete fixtures from this by implementing the `connect` method. """ starting = None stopping = None def __init__(self, maas_url=None): self.maas_url = maas_url
def MatchesSelectableScript(what, *selectors): return MatchesAll(IsInstance(parallel.TestScriptSelectable), MatchesStructure.byEquality(script="bin/test.%s" % what, selectors=selectors), first_only=True)
b = str(observed).splitlines(keepends=False) b = list(line + "\n" for line in b) yield "--- expected\n" yield "+++ observed\n" yield from ndiff(a, b) # The matchee is a non-empty string. In addition a string containing only # whitespace will not match. IsNonEmptyString = MatchesAll( MatchesPredicate( (lambda observed: isinstance(observed, str)), "%r is not a string"), MatchesPredicate( (lambda observed: len(observed) != 0), "%r is empty"), MatchesPredicate( (lambda observed: not observed.isspace()), "%r is whitespace"), first_only=True) class ContainedBy(Matcher): """Test if the matchee is in the given container.""" def __init__(self, haystack): super(ContainedBy, self).__init__() self.haystack = haystack def __str__(self):
def test_get_bind_config_dir_defaults_to_etc_bind_maas(self): self.useFixture(EnvironmentVariable("MAAS_BIND_CONFIG_DIR")) self.assertThat( config.get_bind_config_dir(), MatchesAll(SamePath(locate_config("../bind")), IsInstance(str)), )
def match(self, something): return MatchesAll( HasAttribute("return_value"), HasAttribute("side_effect"), IsCallable(), ).match(something)
def matches_replicaset(replicaset): return MatchesAll(matches_metadata(replicaset.metadata), )
return Failure( amp.UnknownRemoteError( "%s: %s" % (reflect.qual(error.type), reflect.safe_str(error.value)))) d.addErrback(eb_massage_error) return d are_valid_tls_parameters = MatchesDict({ "tls_localCertificate": IsInstance(ssl.PrivateCertificate), "tls_verifyAuthorities": MatchesAll( IsInstance(collections.Sequence), AllMatch(IsInstance(ssl.Certificate)), ), }) class MockClusterToRegionRPCFixtureBase(fixtures.Fixture, metaclass=ABCMeta): """Patch in a stub region RPC implementation to enable end-to-end testing. This is an abstract base class. Derive concrete fixtures from this by implementing the `connect` method. """ starting = None stopping = None def __init__(self, maas_url=None):
def test__decodes_byte_strings(self): string = factory.make_string().encode("utf-8") self.expectThat( describe_canonical(string), MatchesAll( IsInstance(str), Not(Is(string)), Equals(string.decode("utf-8"))))
def test_full_jitter(self, values): jittered = list(full_jitter(values)) self.assertThat(jittered, AllMatch(IsInstance(float))) self.assertThat(jittered, AllMatch(MatchesAll( GreaterThanOrEqual(0.0), LessThan(10000.0))))
def test_pod_fromdict(self): hostname = factory.make_name("hostname") cores = random.randint(1, 8) cpu_speed = random.randint(1000, 2000) memory = random.randint(4096, 8192) local_storage = random.randint(4096, 8192) iscsi_storage = random.randint(4096, 8192) hints = dict( cores=random.randint(1, 8), cpu_speed=random.randint(1000, 2000), memory=random.randint(4096, 8192), local_storage=random.randint(4096, 8192), iscsi_storage=random.randint(4096, 8192), ) machines_data = [] for _ in range(3): cores = random.randint(1, 8) cpu_speed = random.randint(1000, 2000) memory = random.randint(4096, 8192) interfaces = [ dict(mac_address=factory.make_mac_address()) for _ in range(3) ] block_devices = [ dict( model=factory.make_name("model"), serial=factory.make_name("serial"), size=random.randint(512, 1024), ) for _ in range(3) ] for _ in range(3): block_devices.append( dict( model=None, serial=None, size=random.randint(512, 1024), type=BlockDeviceType.ISCSI, iscsi_target=self.make_iscsi_target(), )) machines_data.append( dict( hostname=hostname, architecture="amd64/generic", cores=cores, cpu_speed=cpu_speed, memory=memory, interfaces=interfaces, block_devices=block_devices, )) pod_data = dict( architectures=["amd64/generic"], cores=cores, cpu_speed=cpu_speed, memory=memory, local_storage=local_storage, iscsi_storage=iscsi_storage, hints=hints, machines=machines_data, ) pod = DiscoveredPod.fromdict(pod_data) self.assertThat(pod, IsInstance(DiscoveredPod)) self.assertThat( pod, MatchesStructure( architectures=Equals(["amd64/generic"]), cores=Equals(cores), cpu_speed=Equals(cpu_speed), memory=Equals(memory), local_storage=Equals(local_storage), iscsi_storage=Equals(iscsi_storage), hints=MatchesAll( IsInstance(DiscoveredPodHints), MatchesStructure( cores=Equals(hints["cores"]), cpu_speed=Equals(hints["cpu_speed"]), memory=Equals(hints["memory"]), local_storage=Equals(hints["local_storage"]), iscsi_storage=Equals(hints["iscsi_storage"]), ), ), machines=MatchesListwise([ MatchesAll( IsInstance(DiscoveredMachine), MatchesStructure( architecture=Equals("amd64/generic"), cores=Equals(machine["cores"]), cpu_speed=Equals(machine["cpu_speed"]), memory=Equals(machine["memory"]), interfaces=MatchesListwise([ MatchesAll( IsInstance(DiscoveredMachineInterface), MatchesStructure( mac_address=Equals( interface["mac_address"]), vid=Equals(-1), tags=Equals([]), ), ) for interface in machine["interfaces"] ]), block_devices=MatchesListwise([ MatchesAll( IsInstance(DiscoveredMachineBlockDevice), MatchesStructure( model=Equals(block_device["model"]), serial=Equals(block_device["serial"]), size=Equals(block_device["size"]), block_size=Equals(512), tags=Equals([]), type=Equals(BlockDeviceType.PHYSICAL), ), ) for block_device in machine["block_devices"] if "type" not in block_device ] + [ MatchesAll( IsInstance(DiscoveredMachineBlockDevice), MatchesStructure( model=Is(None), serial=Is(None), size=Equals(block_device["size"]), block_size=Equals(512), tags=Equals([]), type=Equals(BlockDeviceType.ISCSI), iscsi_target=Equals( block_device["iscsi_target"]), ), ) for block_device in machine["block_devices"] if "type" in block_device ]), ), ) for machine in machines_data ]), ), )
def EnterStage(matcher, context=empty_context): """ """ return MatchesAll( IsInstance(Interceptor), After(lambda interceptor: interceptor.enter(context), matcher))