def test_get_paasta_native_services_running_here_for_nerve(): cluster = 'edelweiss' soa_dir = 'the_sound_of_music' fake_marathon_services = [ ('no_test', 'left_behind', 1111), ('no_docstrings', 'forever_abandoned', 2222), ] registrations = [ ['no_docstrings.dos'], ['no_test.uno'], ] nerve_dicts = [ long_running_service_tools.ServiceNamespaceConfig({ 'binary': 1, 'proxy_port': 6666 }), long_running_service_tools.ServiceNamespaceConfig({ 'clock': 0, 'proxy_port': 6666 }), ] expected = [ ('no_test.uno', { 'clock': 0, 'port': 1111, 'proxy_port': 6666 }), ('no_docstrings.dos', { 'binary': 1, 'port': 2222, 'proxy_port': 6666 }), ] with mock.patch( 'paasta_tools.native_mesos_scheduler.paasta_native_services_running_here', autospec=True, return_value=fake_marathon_services, ) as pnsrh_patch, mock.patch( 'paasta_tools.native_mesos_scheduler.read_all_registrations_for_service_instance', autospec=True, side_effect=lambda *args, **kwargs: registrations.pop(), ) as get_namespace_patch, mock.patch( 'paasta_tools.native_mesos_scheduler.load_service_namespace_config', autospec=True, side_effect=lambda *args, **kwargs: nerve_dicts.pop(), ) as read_ns_config_patch: actual = native_mesos_scheduler.get_paasta_native_services_running_here_for_nerve( cluster, soa_dir) assert expected == actual pnsrh_patch.assert_called_once_with(hostname=None) get_namespace_patch.assert_any_call('no_test', 'left_behind', cluster, soa_dir) get_namespace_patch.assert_any_call('no_docstrings', 'forever_abandoned', cluster, soa_dir) assert get_namespace_patch.call_count == 2 read_ns_config_patch.assert_any_call('no_test', 'uno', soa_dir) read_ns_config_patch.assert_any_call('no_docstrings', 'dos', soa_dir) assert read_ns_config_patch.call_count == 2
def test_get_paasta_native_services_running_here_for_nerve_when_not_in_smartstack(): cluster = "edelweiss" soa_dir = "the_sound_of_music" fake_marathon_services = [ ("no_test", "left_behind", 1111), ("no_docstrings", "forever_abandoned", 2222), ] registrations = [["no_docstrings.dos"], ["no_test.uno"]] nerve_dicts = [ long_running_service_tools.ServiceNamespaceConfig({"binary": 1}), long_running_service_tools.ServiceNamespaceConfig( {"clock": 0, "proxy_port": 6666} ), ] expected = [("no_test.uno", {"clock": 0, "port": 1111, "proxy_port": 6666})] with mock.patch( "paasta_tools.native_mesos_scheduler.paasta_native_services_running_here", autospec=True, return_value=fake_marathon_services, ) as pnsrh_patch, mock.patch( "paasta_tools.native_mesos_scheduler.load_paasta_native_job_config", autospec=True, ) as mock_load_paasta_native_job_config, mock.patch( "paasta_tools.native_mesos_scheduler.load_service_namespace_config", autospec=True, side_effect=lambda *args, **kwargs: nerve_dicts.pop(), ) as read_ns_config_patch: def mock_registrations_side_effect(*args, **kwargs): return registrations.pop() mock_load_paasta_native_job_config.return_value.get_registrations.side_effect = ( mock_registrations_side_effect ) actual = ( native_mesos_scheduler.get_paasta_native_services_running_here_for_nerve( cluster, soa_dir ) ) assert expected == actual pnsrh_patch.assert_called_once_with(hostname=None) mock_load_paasta_native_job_config.assert_any_call( service="no_test", instance="left_behind", cluster=cluster, load_deployments=False, soa_dir=soa_dir, ) mock_load_paasta_native_job_config.assert_any_call( service="no_docstrings", instance="forever_abandoned", cluster=cluster, load_deployments=False, soa_dir=soa_dir, ) assert mock_load_paasta_native_job_config.call_count == 2 read_ns_config_patch.assert_any_call("no_test", "uno", soa_dir) read_ns_config_patch.assert_any_call("no_docstrings", "dos", soa_dir) assert read_ns_config_patch.call_count == 2
def test_get_paasta_native_services_running_here_for_nerve_when_get_cluster_raises_other_exception( ): cluster = None soa_dir = 'the_sound_of_music' with mock.patch( 'paasta_tools.native_mesos_scheduler.load_system_paasta_config', autospec=True, ) as load_system_paasta_config_patch, mock.patch( 'paasta_tools.native_mesos_scheduler.paasta_native_services_running_here', autospec=True, return_value=[], ): load_system_paasta_config_patch.return_value.get_cluster = mock.Mock( side_effect=Exception) with pytest.raises(Exception): native_mesos_scheduler.get_paasta_native_services_running_here_for_nerve( cluster, soa_dir)
def test_get_paasta_native_services_running_here_for_nerve_when_paasta_not_configured( ): cluster = None soa_dir = 'the_sound_of_music' with mock.patch( 'paasta_tools.native_mesos_scheduler.load_system_paasta_config', autospec=True, ) as load_system_paasta_config_patch, mock.patch( 'paasta_tools.native_mesos_scheduler.paasta_native_services_running_here', autospec=True, return_value=[], ): load_system_paasta_config_patch.return_value \ = mock.Mock(side_effect=native_mesos_scheduler.PaastaNotConfiguredError) actual = native_mesos_scheduler.get_paasta_native_services_running_here_for_nerve( cluster, soa_dir) assert actual == []
def test_get_paasta_native_services_running_here_for_nerve_when_get_cluster_raises_custom_exception(): cluster = None soa_dir = "the_sound_of_music" with mock.patch( "paasta_tools.native_mesos_scheduler.load_system_paasta_config", autospec=True ) as load_system_paasta_config_patch, mock.patch( "paasta_tools.native_mesos_scheduler.paasta_native_services_running_here", autospec=True, return_value=[], ): load_system_paasta_config_patch.return_value = mock.Mock( side_effect=native_mesos_scheduler.PaastaNotConfiguredError ) actual = native_mesos_scheduler.get_paasta_native_services_running_here_for_nerve( cluster, soa_dir ) assert actual == []
def main() -> None: opts = parse_args(sys.argv[1:]) new_config = generate_configuration( paasta_services=( get_marathon_services_running_here_for_nerve( # type: ignore cluster=None, soa_dir=DEFAULT_SOA_DIR, ) + get_paasta_native_services_running_here_for_nerve( cluster=None, soa_dir=DEFAULT_SOA_DIR, ) + get_kubernetes_services_running_here_for_nerve( cluster=None, soa_dir=DEFAULT_SOA_DIR, )), puppet_services=get_puppet_services_running_here_for_nerve( soa_dir=DEFAULT_SOA_DIR, ), heartbeat_path=opts.heartbeat_path, hacheck_port=opts.hacheck_port, weight=opts.weight, zk_topology_dir=opts.zk_topology_dir, zk_location_type=opts.zk_location_type, zk_cluster_type=opts.zk_cluster_type, labels_dir=opts.labels_dir, envoy_listeners=get_envoy_listeners(opts.envoy_admin_port), ) # Must use os.rename on files in the same filesystem to ensure that # config is swapped atomically, so we need to create the temp file in # the same directory as the config file new_config_path = '{0}.tmp'.format(opts.nerve_config_path) with open(new_config_path, 'w') as fp: json.dump(new_config, fp, sort_keys=True, indent=4, separators=(',', ': ')) # Match the permissions that puppet expects os.chmod(new_config_path, 0o644) # Restart/reload nerve if the config files differ # Always force a restart if the heartbeat file is old should_reload = not filecmp.cmp(new_config_path, opts.nerve_config_path) should_restart = file_not_modified_since(opts.heartbeat_path, opts.heartbeat_threshold) # Always swap new config file into place, even if we're not going to # restart nerve. Our monitoring system checks the opts.nerve_config_path # file age to ensure that this script is functioning correctly. try: # Verify the new config is _valid_ command = [opts.nerve_executable_path] command.extend(['-c', new_config_path, '-k']) subprocess.check_call(command) # Move the config over shutil.move(new_config_path, opts.nerve_config_path) except subprocess.CalledProcessError: # Nerve config is invalid!, bail out **without restarting** # so staleness monitoring can trigger and alert us of a problem return # If we can reload with SIGHUP, use that, otherwise use the normal # graceful method if should_reload and opts.reload_with_sighup: try: with open(opts.nerve_pid_path) as f: pid = int(f.read().strip()) os.kill(pid, signal.SIGHUP) except (OSError, ValueError, IOError): # invalid pid file, time to restart should_restart = True else: # Always try to stop the backup process subprocess.call(opts.nerve_backup_command + ['stop']) else: should_restart |= should_reload if should_restart: # Try to do a graceful restart by starting up the backup nerve # prior to restarting the main nerve. Then once the main nerve # is restarted, stop the backup nerve. try: subprocess.call(opts.nerve_backup_command + ['start']) time.sleep(opts.nerve_registration_delay_s) subprocess.check_call(opts.nerve_command + ['stop']) subprocess.check_call(opts.nerve_command + ['start']) time.sleep(opts.nerve_registration_delay_s) finally: # Always try to stop the backup process subprocess.call(opts.nerve_backup_command + ['stop'])
def test_get_paasta_native_services_running_here_for_nerve_multiple_namespaces( ): cluster = 'edelweiss' soa_dir = 'the_sound_of_music' fake_marathon_services = [ ('no_test', 'left_behind', 1111), ('no_docstrings', 'forever_abandoned', 2222), ] namespaces = [ ['no_docstrings.quatro'], ['no_test.uno', 'no_test.dos', 'no_test.tres'], ] nerve_dicts = { ('no_test', 'uno'): long_running_service_tools.ServiceNamespaceConfig({'proxy_port': 6666}), ('no_test', 'dos'): long_running_service_tools.ServiceNamespaceConfig({'proxy_port': 6667}), ('no_test', 'tres'): long_running_service_tools.ServiceNamespaceConfig({'proxy_port': 6668}), ('no_docstrings', 'quatro'): long_running_service_tools.ServiceNamespaceConfig({'proxy_port': 6669}), } expected = [ ('no_test.uno', { 'port': 1111, 'proxy_port': 6666 }), ('no_test.dos', { 'port': 1111, 'proxy_port': 6667 }), ('no_test.tres', { 'port': 1111, 'proxy_port': 6668 }), ('no_docstrings.quatro', { 'port': 2222, 'proxy_port': 6669 }), ] with mock.patch( 'paasta_tools.native_mesos_scheduler.paasta_native_services_running_here', autospec=True, return_value=fake_marathon_services, ) as pnsrh_patch, mock.patch( 'paasta_tools.native_mesos_scheduler.load_paasta_native_job_config', autospec=True, ) as mock_load_paasta_native_job_config, mock.patch( 'paasta_tools.native_mesos_scheduler.load_service_namespace_config', autospec=True, side_effect=lambda service, namespace, soa_dir: nerve_dicts.pop( (service, namespace)), ) as read_ns_config_patch: def mock_registrations_side_effect(*args, **kwargs): return namespaces.pop() mock_load_paasta_native_job_config.return_value.get_registrations.side_effect = mock_registrations_side_effect actual = native_mesos_scheduler.get_paasta_native_services_running_here_for_nerve( cluster, soa_dir) assert expected == actual pnsrh_patch.assert_called_once_with(hostname=None) mock_load_paasta_native_job_config.assert_any_call( service='no_test', instance='left_behind', cluster=cluster, load_deployments=False, soa_dir=soa_dir, ) mock_load_paasta_native_job_config.assert_any_call( service='no_docstrings', instance='forever_abandoned', cluster=cluster, load_deployments=False, soa_dir=soa_dir, ) assert mock_load_paasta_native_job_config.call_count == 2 read_ns_config_patch.assert_any_call('no_test', 'uno', soa_dir) read_ns_config_patch.assert_any_call('no_test', 'dos', soa_dir) read_ns_config_patch.assert_any_call('no_test', 'tres', soa_dir) read_ns_config_patch.assert_any_call('no_docstrings', 'quatro', soa_dir) assert read_ns_config_patch.call_count == 4