def test_tryUpdate_writes_nginx_config_reloads_nginx(self): self.useFixture(MAASRootFixture()) rpc_service, _ = yield prepareRegion(self) region_ips = self.extract_regions(rpc_service) resource_root = self.make_dir() + "/" service = self.make_startable_RackHTTPService(resource_root, rpc_service, reactor) # Mock service_monitor to catch reloadService. mock_reloadService = self.patch(http.service_monitor, "reloadService") mock_reloadService.return_value = always_succeed_with(None) yield service.startService() self.addCleanup((yield service.stopService)) yield service._orig_tryUpdate() # Verify the contents of the written config. target_path = http.compose_http_config_path("rackd.nginx.conf") self.assertThat( target_path, FileContains(matcher=Contains("alias %s;" % resource_root)), ) for region_ip in region_ips: self.assertThat( target_path, FileContains(matcher=Contains("server %s:5240;" % region_ip)), ) self.assertThat( target_path, FileContains( matcher=Contains("proxy_pass http://maas-regions/MAAS/;")), ) self.assertThat(mock_reloadService, MockCalledOnceWith("http")) # If the configuration has not changed then a second call to # `_tryUpdate` does not result in another call to `_configure`. yield service._orig_tryUpdate() self.assertThat(mock_reloadService, MockCalledOnceWith("http"))
def test__calls_are_made_to_all_clusters(self): rpc_fixture = self.prepare_live_rpc() rack_controllers = [factory.make_RackController() for _ in range(3)] protocols = [] rack_creds = [] for rack in rack_controllers: tokens = list(get_auth_tokens(rack.owner)) if len(tokens) > 0: # Use the latest token. token = tokens[-1] else: token = create_auth_token(rack.owner) creds = convert_tuple_to_string(get_creds_tuple(token)) rack_creds.append(creds) protocol = rpc_fixture.makeCluster(rack, EvaluateTag) protocol.EvaluateTag.side_effect = always_succeed_with({}) protocols.append(protocol) tag = factory.make_Tag(populate=False) [d] = populate_tags(tag) # `d` is a testing-only convenience. We must wait for it to fire, and # we must do that from the reactor thread. wait_for_populate = asynchronous(lambda: d) wait_for_populate().wait(10) for rack, protocol, creds in zip(rack_controllers, protocols, rack_creds): self.expectThat( protocol.EvaluateTag, MockCalledOnceWith(protocol, tag_name=tag.name, tag_definition=tag.definition, system_id=rack.system_id, tag_nsmap=ANY, credentials=creds, nodes=ANY))
def test_render_GET_500_server_error(self): path = factory.make_name("path") ip = factory.make_ip_address() request = DummyRequest([path.encode("utf-8")]) request.requestHeaders = Headers({ "X-Server-Addr": ["192.168.1.1"], "X-Server-Port": ["5248"], "X-Forwarded-For": [ip], "X-Forwarded-Port": ["%s" % factory.pick_port()], }) self.patch(http.log, "info") mock_deferLater = self.patch(http, "deferLater") mock_deferLater.side_effect = always_succeed_with(None) exc = factory.make_exception("internal error") self.tftp.backend.get_reader.return_value = fail(exc) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertEqual(500, request.responseCode) self.assertEqual(str(exc).encode("utf-8"), b"".join(request.written))
def test_tryUpdate_logs_errors_from_broken_method(self): service = ntp.RegionNetworkTimeProtocolService(reactor) broken_method = self.patch_autospec(service, self.method) broken_method.side_effect = factory.make_exception() # Ensure that we never actually execute against systemd or write an # actual configuration file. self.patch_autospec( ntp, "deferToThread").side_effect = always_succeed_with(None) self.patch_autospec(service_monitor, "restartService") with TwistedLoggerFixture() as logger: yield service._tryUpdate() self.assertThat( logger.output, DocTestMatches(""" Failed to update NTP configuration. Traceback (most recent call last): ... maastesting.factory.TestException#... """), )
def test_render_GET_400_when_no_local_addr(self): path = factory.make_name("path") ip = factory.make_ip_address() request = DummyRequest([path.encode("utf-8")]) request.requestHeaders = Headers( { "X-Forwarded-For": [ip], "X-Forwarded-Port": ["%s" % factory.pick_port()], } ) self.patch(http.log, "info") mock_deferLater = self.patch(http, "deferLater") mock_deferLater.side_effect = always_succeed_with(None) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertEquals(400, request.responseCode) self.assertEquals( b"Missing X-Server-Addr and X-Forwarded-For HTTP headers.", b"".join(request.written), )
def test_render_GET_500_server_error(self): path = factory.make_name('path') ip = factory.make_ip_address() request = DummyRequest([path.encode('utf-8')]) request.requestHeaders = Headers({ 'X-Server-Addr': ['192.168.1.1'], 'X-Server-Port': ['5248'], 'X-Forwarded-For': [ip], 'X-Forwarded-Port': ['%s' % factory.pick_port()], }) self.patch(http.log, 'info') mock_deferLater = self.patch(http, 'deferLater') mock_deferLater.side_effect = always_succeed_with(None) exc = factory.make_exception("internal error") self.tftp.backend.get_reader.return_value = fail(exc) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertEquals(500, request.responseCode) self.assertEquals(str(exc).encode('utf-8'), b''.join(request.written))
def makeEventLoop(self, *commands): """Make and add a new stub event-loop for the given `commands`. See `make_amp_protocol_factory` for details. """ if region.Identify not in commands: commands = commands + (region.Identify,) if region.Authenticate not in commands: commands = commands + (region.Authenticate,) if region.RegisterRackController not in commands: commands = commands + (region.RegisterRackController,) if amp.StartTLS not in commands: commands = commands + (amp.StartTLS,) protocol_factory = make_amp_protocol_factory(*commands) protocol = protocol_factory() eventloop = self.getEventLoopName(protocol) protocol.Identify.return_value = {"ident": eventloop} protocol.Authenticate.side_effect = self._authenticate_with_cluster_key protocol.RegisterRackController.side_effect = always_succeed_with( {"system_id": ""} ) protocol.StartTLS.return_value = get_tls_parameters_for_region() return protocol, self.addEventLoop(protocol)
def test_render_GET_logs_node_event_with_original_path_ip(self): path = factory.make_name("path") ip = factory.make_ip_address() request = DummyRequest([path.encode("utf-8")]) request.requestHeaders = Headers({ "X-Server-Addr": ["192.168.1.1"], "X-Server-Port": ["5248"], "X-Forwarded-For": [ip], "X-Forwarded-Port": ["%s" % factory.pick_port()], }) log_info = self.patch(http.log, "info") mock_deferLater = self.patch(http, "deferLater") mock_deferLater.side_effect = always_succeed_with(None) self.tftp.backend.get_reader.return_value = fail(AccessViolation()) resource = http.HTTPBootResource() yield self.render_GET(resource, request) self.assertThat( log_info, MockCalledOnceWith("{path} requested by {remoteHost}", path=path, remoteHost=ip), ) self.assertThat( mock_deferLater, MockCalledOnceWith( ANY, 0, http.send_node_event_ip_address, event_type=EVENT_TYPES.NODE_HTTP_REQUEST, ip_address=ip, description=path, ), )
def patch_methods_using_rpc(self): pcs = self.patch_autospec(power, "power_change_starting") pcs.return_value = always_succeed_with(None) cps = self.patch_autospec(power, "change_power_state") cps.return_value = always_succeed_with(None)
def patch_authenticate_for_failure(self, client): authenticate = self.patch_autospec(client, "authenticateCluster") authenticate.side_effect = always_succeed_with(False)
def prepareRegion( test, *, is_region=False, is_rack=True, servers=None, peers=None, trusted_networks=None, proxy_enabled=True, proxy_port=8000, proxy_allowed_cidrs=None, proxy_prefer_v4_proxy=False, syslog_port=5247 ): """Set up a mock region controller. It responds to `GetControllerType`, `GetTimeConfiguration`, `GetDNSConfiguration`, `GetProxyConfiguration`, and `GetSyslogConfiguration`. :return: The running RPC service, and the protocol instance. """ fixture = test.useFixture(MockLiveClusterToRegionRPCFixture()) protocol, connecting = fixture.makeEventLoop( region.GetControllerType, region.GetTimeConfiguration, region.GetDNSConfiguration, region.GetProxyConfiguration, region.GetSyslogConfiguration, ) protocol.RegisterRackController.side_effect = always_succeed_with( {"system_id": factory.make_name("maas-id")} ) protocol.GetControllerType.side_effect = always_succeed_with( {"is_region": is_region, "is_rack": is_rack} ) protocol.GetTimeConfiguration.side_effect = always_succeed_with( { "servers": [] if servers is None else servers, "peers": [] if peers is None else peers, } ) protocol.GetDNSConfiguration.side_effect = always_succeed_with( { "trusted_networks": ( [] if trusted_networks is None else trusted_networks ) } ) if proxy_allowed_cidrs is None: proxy_allowed_cidrs = [] protocol.GetProxyConfiguration.side_effect = always_succeed_with( { "enabled": proxy_enabled, "port": proxy_port, "allowed_cidrs": proxy_allowed_cidrs, "prefer_v4_proxy": proxy_prefer_v4_proxy, } ) protocol.GetSyslogConfiguration.side_effect = always_succeed_with( {"port": syslog_port} ) def connected(teardown): test.addCleanup(teardown) return services.getServiceNamed("rpc"), protocol return connecting.addCallback(connected)
def make_startable_RackExternalService(test, *args, **kwargs): service = external.RackExternalService(*args, **kwargs) service._orig_tryUpdate = service._tryUpdate test.patch(service, "_tryUpdate").return_value = always_succeed_with(None) service.call = (service._tryUpdate, tuple(), {}) return service