示例#1
0
def test_get_deploy_group_mappings():
    fake_service = 'fake_service'
    fake_soa_dir = '/no/yes/maybe'

    fake_service_configs = [
        MarathonServiceConfig(
            service=fake_service,
            cluster='clusterA',
            instance='main',
            branch_dict={},
            config_dict={'deploy_group': 'no_thanks'},
        ),
        MarathonServiceConfig(
            service=fake_service,
            cluster='clusterB',
            instance='main',
            branch_dict={},
            config_dict={'deploy_group': 'try_me'},
        ),
    ]

    fake_remote_refs = {
        'refs/tags/paasta-try_me-20160308T053933-deploy': '123456',
        'refs/tags/paasta-clusterB.main-123-stop': '123456',
        'refs/tags/paasta-okay-20160308T053933-deploy': 'ijowarg',
        'refs/tags/paasta-no_thanks-20160308T053933-deploy': '789009',
        'refs/tags/paasta-nah-20160308T053933-deploy': 'j8yiomwer',
    }

    fake_old_mappings = ['']
    expected = {
        'fake_service:paasta-clusterA.main': {
            'docker_image': 'services-fake_service:paasta-789009',
            'desired_state': 'start',
            'force_bounce': None,
        },
        'fake_service:paasta-clusterB.main': {
            'docker_image': 'services-fake_service:paasta-123456',
            'desired_state': 'stop',
            'force_bounce': '123',
        },
    }
    with contextlib.nested(
            mock.patch(
                'paasta_tools.generate_deployments_for_service.get_instance_config_for_service',
                return_value=fake_service_configs,
                autospec=True),
            mock.patch('paasta_tools.remote_git.list_remote_refs',
                       return_value=fake_remote_refs,
                       autospec=True),
    ) as (
            get_instance_config_for_service_patch,
            list_remote_refs_patch,
    ):
        actual = generate_deployments_for_service.get_deploy_group_mappings(
            fake_soa_dir, fake_service, fake_old_mappings)
        get_instance_config_for_service_patch.assert_called_once_with(
            soa_dir=fake_soa_dir, service=fake_service)
        assert list_remote_refs_patch.call_count == 1
        assert expected == actual
示例#2
0
def test_get_cluster_instance_map_for_service():
    fake_service_configs = [
        MarathonServiceConfig(
            service='service1',
            cluster='clusterA',
            instance='main',
            branch_dict={},
            config_dict={'deploy_group': 'no_thanks'},
        ),
        MarathonServiceConfig(
            service='service1',
            cluster='clusterB',
            instance='main',
            branch_dict={},
            config_dict={'deploy_group': 'try_me'},
        ),
        MarathonServiceConfig(
            service='service1',
            cluster='clusterA',
            instance='canary',
            branch_dict={},
            config_dict={'deploy_group': 'try_me'},
        ),
    ]
    with mock.patch(
        'paasta_tools.generate_deployments_for_service.get_instance_configs_for_service',
        return_value=fake_service_configs, autospec=True,
    ):
        ret = generate_deployments_for_service.get_cluster_instance_map_for_service('/nail/blah', 'service1', 'try_me')
        expected = {'clusterA': {'instances': ['canary']}, 'clusterB': {'instances': ['main']}}
        assert ret == expected

        ret = generate_deployments_for_service.get_cluster_instance_map_for_service('/nail/blah', 'service1')
        expected = {'clusterA': {'instances': ['main', 'canary']}, 'clusterB': {'instances': ['main']}}
        assert ret == expected
示例#3
0
def test_create_marathon_dashboard(
    mock_get_services_for_cluster, mock_pscl, mock_load_system_paasta_config
):
    soa_dir = "/fake/soa/dir"
    cluster = "fake_cluster"
    mock_load_system_paasta_config.return_value = SystemPaastaConfig(
        {"dashboard_links": {}}, "fake_directory"
    )
    mock_get_services_for_cluster.return_value = [
        ("fake_service", "foo"),
        ("fake_service", "bar"),
    ]
    mock_pscl.return_value.instance_configs.return_value = [
        MarathonServiceConfig("fake_service", "fake_cluster", "foo", {}, {}, soa_dir),
        MarathonServiceConfig("fake_service", "fake_cluster", "bar", {}, {}, soa_dir),
    ]

    mock_client = mock.Mock(servers=["hi"])
    mock_clients = MarathonClients(current=[mock_client], previous=[mock_client])

    expected_output = {
        "fake_cluster": [
            {"service": "fake_service", "instance": "foo", "shard_url": "hi"},
            {"service": "fake_service", "instance": "bar", "shard_url": "hi"},
        ]
    }
    assert (
        marathon_dashboard.create_marathon_dashboard(
            cluster=cluster, soa_dir=soa_dir, marathon_clients=mock_clients
        )
        == expected_output
    )
示例#4
0
def check_service_replication(
    instance_config: MarathonServiceConfig,
    all_tasks_or_pods: Sequence[MarathonTask],
    replication_checker: MesosSmartstackEnvoyReplicationChecker,
) -> Optional[bool]:
    """Checks a service's replication levels based on how the service's replication
    should be monitored. (smartstack/envoy or mesos)

    :param instance_config: an instance of MarathonServiceConfig
    :param replication_checker: an instance of MesosSmartstackEnvoyReplicationChecker
    """
    expected_count = instance_config.get_instances()
    log.info("Expecting %d total tasks for %s" %
             (expected_count, instance_config.job_id))
    proxy_port = get_proxy_port_for_instance(instance_config)

    registrations = instance_config.get_registrations()
    # if the primary registration does not match the service_instance name then
    # the best we can do is check marathon for replication (for now).
    if proxy_port is not None and registrations[0] == instance_config.job_id:
        is_well_replicated = monitoring_tools.check_replication_for_instance(
            instance_config=instance_config,
            expected_count=expected_count,
            replication_checker=replication_checker,
        )
        return is_well_replicated
    else:
        check_healthy_marathon_tasks_for_service_instance(
            instance_config=instance_config,
            expected_count=expected_count,
            all_tasks=all_tasks_or_pods,
        )
        return None
示例#5
0
def status_desired_state(
    service: str,
    instance: str,
    client: marathon_tools.MarathonClient,
    job_config: marathon_tools.MarathonServiceConfig,
) -> str:
    status = get_bouncing_status(service, instance, client, job_config)
    desired_state = desired_state_human(job_config.get_desired_state(), job_config.get_instances())
    return f"Desired State:      {status} and {desired_state}"
示例#6
0
def marathon_smartstack_status(
    service: str,
    instance: str,
    job_config: marathon_tools.MarathonServiceConfig,
    service_namespace_config: ServiceNamespaceConfig,
    tasks: Sequence[MarathonTask],
    should_return_individual_backends: bool = False,
) -> Mapping[str, Any]:
    registration = job_config.get_registrations()[0]
    discover_location_type = service_namespace_config.get_discover()
    monitoring_blacklist = job_config.get_monitoring_blacklist(
        system_deploy_blacklist=settings.system_paasta_config.
        get_deploy_blacklist())
    filtered_slaves = get_all_slaves_for_blacklist_whitelist(
        blacklist=monitoring_blacklist, whitelist=None)
    grouped_slaves = get_mesos_slaves_grouped_by_attribute(
        slaves=filtered_slaves, attribute=discover_location_type)

    # rebuild the dict, replacing the slave object with just their hostname
    slave_hostname_by_location = {
        attribute_value: [slave["hostname"] for slave in slaves]
        for attribute_value, slaves in grouped_slaves.items()
    }

    expected_smartstack_count = marathon_tools.get_expected_instance_count_for_namespace(
        service, instance, settings.cluster)
    expected_count_per_location = int(expected_smartstack_count /
                                      len(slave_hostname_by_location))
    smartstack_status: MutableMapping[str, Any] = {
        "registration": registration,
        "expected_backends_per_location": expected_count_per_location,
        "locations": [],
    }

    for location, hosts in slave_hostname_by_location.items():
        synapse_host = hosts[0]
        sorted_backends = sorted(
            get_backends(
                registration,
                synapse_host=synapse_host,
                synapse_port=settings.system_paasta_config.get_synapse_port(),
                synapse_haproxy_url_format=settings.system_paasta_config.
                get_synapse_haproxy_url_format(),
            ),
            key=lambda backend: backend["status"],
            reverse=True,  # put 'UP' backends above 'MAINT' backends
        )
        matched_backends_and_tasks = match_backends_and_tasks(
            sorted_backends, tasks)
        location_dict = build_smartstack_location_dict(
            location, matched_backends_and_tasks,
            should_return_individual_backends)
        smartstack_status["locations"].append(location_dict)

    return smartstack_status
示例#7
0
def setup_service(
    service: str,
    instance: str,
    clients: marathon_tools.MarathonClients,
    job_config: marathon_tools.MarathonServiceConfig,
    marathon_apps_with_clients: Sequence[Tuple[MarathonApp, MarathonClient]],
    soa_dir: str,
) -> Tuple[int, str, Optional[float]]:
    """Setup the service instance given and attempt to deploy it, if possible.
    Doesn't do anything if the service is already in Marathon and hasn't changed.
    If it's not, attempt to find old instances of the service and bounce them.

    :param service: The service name to setup
    :param instance: The instance of the service to setup
    :param clients: A MarathonClients object
    :param job_config: The service instance's configuration dict
    :returns: A tuple of (status, output, bounce_in_seconds) to be used with send_sensu_event"""

    log.info("Setting up instance %s for service %s", instance, service)
    try:
        marathon_app_dict = job_config.format_marathon_app_dict()
    except NoDockerImageError:
        error_msg = (
            "Docker image for {0}.{1} not in deployments.json. Exiting. Has Jenkins deployed it?\n"
        ).format(
            service,
            instance,
        )
        log.error(error_msg)
        return (1, error_msg, None)

    full_id = marathon_app_dict['id']
    service_namespace_config = marathon_tools.load_service_namespace_config(
        service=service,
        namespace=job_config.get_nerve_namespace(),
        soa_dir=soa_dir,
    )

    log.info("Desired Marathon instance id: %s", full_id)
    return deploy_service(
        service=service,
        instance=instance,
        marathon_jobid=full_id,
        config=marathon_app_dict,
        clients=clients,
        marathon_apps_with_clients=marathon_apps_with_clients,
        bounce_method=job_config.get_bounce_method(),
        drain_method_name=job_config.get_drain_method(
            service_namespace_config),
        drain_method_params=job_config.get_drain_method_params(
            service_namespace_config),
        nerve_ns=job_config.get_nerve_namespace(),
        registrations=job_config.get_registrations(),
        bounce_health_params=job_config.get_bounce_health_params(
            service_namespace_config),
        soa_dir=soa_dir,
        job_config=job_config,
        bounce_margin_factor=job_config.get_bounce_margin_factor(),
    )
示例#8
0
def test_paasta_rollback_mark_for_deployment_no_deploy_group_arg(
    mock_mark_for_deployment,
    mock_get_git_url,
    mock_figure_out_service_name,
    mock_get_instance_config,
):

    fake_args = Mock(
        commit='123456',
        deploy_groups='',
    )

    mock_get_git_url.return_value = 'git://git.repo'
    mock_figure_out_service_name.return_value = 'fakeservice'

    mock_get_instance_config.return_value = [
        MarathonServiceConfig(
            service=mock_figure_out_service_name.return_value,
            cluster='',
            instance='',
            config_dict={'deploy_group': 'fake_deploy_group'},
            branch_dict={},
        ),
        MarathonServiceConfig(
            service=mock_figure_out_service_name.return_value,
            cluster='fake_cluster',
            instance='fake_instance',
            config_dict={},
            branch_dict={},
        ),
    ]

    mock_mark_for_deployment.return_value = 0
    assert paasta_rollback(fake_args) == 0

    expected = [
        call(
            git_url=mock_get_git_url.return_value,
            service=mock_figure_out_service_name.return_value,
            commit=fake_args.commit,
            deploy_group='fake_cluster.fake_instance',
        ),
        call(
            git_url=mock_get_git_url.return_value,
            service=mock_figure_out_service_name.return_value,
            commit=fake_args.commit,
            deploy_group='fake_deploy_group',
        ),
    ]

    assert all([x in expected for x in mock_mark_for_deployment.mock_calls])
    assert len(expected) == len(mock_mark_for_deployment.mock_calls)
    assert mock_mark_for_deployment.call_count == 2
示例#9
0
def test_paasta_rollback_mark_for_deployment_multiple_instance_args(
    mock_mark_for_deployment,
    mock_get_git_url,
    mock_figure_out_service_name,
    mock_get_instance_config_for_service,
):

    fake_args = Mock(
        deploy_groups='cluster.instance1,cluster.instance2',
        commit='123456',
    )

    mock_get_git_url.return_value = 'git://git.repo'
    mock_figure_out_service_name.return_value = 'fakeservice'

    mock_get_instance_config_for_service.return_value = [
        MarathonServiceConfig(
            instance='instance1',
            cluster='cluster',
            service=mock_figure_out_service_name.return_value,
            config_dict={},
            branch_dict={},
        ),
        MarathonServiceConfig(
            instance='instance2',
            cluster='cluster',
            service=mock_figure_out_service_name.return_value,
            config_dict={},
            branch_dict={},
        ),
    ]

    mock_mark_for_deployment.return_value = 0
    assert paasta_rollback(fake_args) == 0

    expected = [
        call(
            git_url=mock_get_git_url.return_value,
            service=mock_figure_out_service_name.return_value,
            commit=fake_args.commit,
            deploy_group='cluster.instance1',
        ),
        call(
            git_url=mock_get_git_url.return_value,
            service=mock_figure_out_service_name.return_value,
            commit=fake_args.commit,
            deploy_group='cluster.instance2',
        ),
    ]

    mock_mark_for_deployment.assert_has_calls(expected, any_order=True)
    assert mock_mark_for_deployment.call_count == 2
示例#10
0
def _record_autoscaling_decision(
    marathon_service_config: MarathonServiceConfig,
    autoscaling_params: AutoscalingParamsDict,
    utilization: float,
    log_utilization_data: Mapping[str, str],
    error: float,
    current_instances: int,
    num_healthy_instances: int,
    new_instance_count: int,
    safe_downscaling_threshold: int,
    task_data_insufficient: bool,
) -> None:
    """
    Based on the calculations made, perform observability side effects.
    Log messages, generate time series, send any alerts, etc.
    """
    write_to_log(
        config=marathon_service_config,
        line=json.dumps(
            dict(
                timestamp=time.time(),
                paasta_cluster=marathon_service_config.get_cluster(),
                paasta_service=marathon_service_config.get_service(),
                paasta_instance=marathon_service_config.get_instance(),
                autoscaling_params=autoscaling_params,
                utilization=utilization,
                error=error,
                current_instances=current_instances,
                num_healthy_instances=num_healthy_instances,
                new_instance_count=new_instance_count,
                safe_downscaling_threshold=safe_downscaling_threshold,
                task_data_insufficient=task_data_insufficient,
            )),
        level="debug",
    )
    meteorite_dims = {
        "paasta_service": marathon_service_config.service,
        "paasta_cluster": marathon_service_config.cluster,
        "paasta_instance": marathon_service_config.instance,
        "decision_policy":
        autoscaling_params[DECISION_POLICY_KEY],  # type: ignore
    }
    if yelp_meteorite:
        gauge = yelp_meteorite.create_gauge("paasta.service.instances",
                                            meteorite_dims)
        gauge.set(new_instance_count)
        gauge = yelp_meteorite.create_gauge("paasta.service.max_instances",
                                            meteorite_dims)
        gauge.set(marathon_service_config.get_max_instances())
        gauge = yelp_meteorite.create_gauge("paasta.service.min_instances",
                                            meteorite_dims)
        gauge.set(marathon_service_config.get_min_instances())
示例#11
0
def test_list_previously_deployed_shas():
    fake_refs = {
        'refs/tags/paasta-test.deploy.group-00000000T000000-deploy':
        'SHA_IN_OUTPUT',
        'refs/tags/paasta-other.deploy.group-00000000T000000-deploy':
        'NOT_IN_OUTPUT',
    }
    fake_configs = [
        MarathonServiceConfig(
            service='fake_service',
            instance='fake_instance',
            cluster='fake_cluster',
            config_dict={'deploy_group': 'test.deploy.group'},
            branch_dict={},
        )
    ]
    with contextlib.nested(
            patch('paasta_tools.cli.cmds.rollback.list_remote_refs',
                  autospec=True,
                  return_value=fake_refs),
            patch(
                'paasta_tools.cli.cmds.rollback.get_instance_config_for_service',
                autospec=True,
                return_value=fake_configs),
    ) as (
            _,
            _,
    ):
        fake_args = Mock(
            service='fake_service',
            deploy_groups='test.deploy.group,nonexistant.deploy.group',
            soa_dir='/fake/soa/dir',
        )
        assert set(
            list_previously_deployed_shas(fake_args)) == {'SHA_IN_OUTPUT'}
示例#12
0
def test_instance_config(
    mock_read_extra_service_information,
    mock_load_deployments_json,
):
    mock_read_extra_service_information.return_value = marathon_cluster_config(
    )
    mock_load_deployments_json.return_value = deployment_json()
    expected_instance_config = MarathonServiceConfig(
        service=TEST_SERVICE_NAME,
        cluster=TEST_CLUSTER_NAME,
        instance='main',
        config_dict={
            'port': None,
            'vip': None,
            'lb_extras': {},
            'monitoring': {},
            'deploy': {},
            'data': {},
            'smartstack': {},
            'dependencies': {},
            'instances': 3,
            'deploy_group': 'fake.non_canary',
            'cpus': 0.1,
            'mem': 1000,
        },
        branch_dict={
            'docker_image': 'some_image',
            'desired_state': 'start',
            'force_bounce': None,
        },
        soa_dir=TEST_SOA_DIR,
    )
    s = create_test_service()
    instance_config = s.instance_config(TEST_CLUSTER_NAME, 'main')
    assert instance_config == expected_instance_config
示例#13
0
def test_simulate_healthcheck_on_service_enabled_honors_grace_period(
    mock_run_healthcheck_on_container,
    mock_time,
    mock_sleep,
    capsys,
):
    # change time to make sure we are sufficiently past grace period
    mock_time.side_effect = [0, 1, 5]
    mock_docker_client = mock.MagicMock(spec_set=docker.Client)
    mock_service_manifest = MarathonServiceConfig(
        service='fake_name',
        cluster='fake_cluster',
        instance='fake_instance',
        config_dict={
            # only one healthcheck will be performed silently
            'healthcheck_grace_period_seconds': 2,
        },
        branch_dict={},
    )

    fake_container_id = 'fake_container_id'
    fake_mode = 'http'
    fake_url = 'http://fake_host/fake_status_path'
    assert simulate_healthcheck_on_service(
        mock_service_manifest, mock_docker_client, fake_container_id, fake_mode, fake_url, True)
    assert mock_sleep.call_count == 2
    assert mock_run_healthcheck_on_container.call_count == 3
    out, _ = capsys.readouterr()
    assert out.count('Healthcheck failed! (disregarded due to grace period)') == 1
    assert out.count('Healthcheck failed! (Attempt') == 1
    assert out.count('Healthcheck succeeded!') == 1
示例#14
0
def test_simulate_healthcheck_on_service_enabled_during_grace_period(
    mock_run_healthcheck_on_container,
    mock_time,
    mock_sleep
):
    # prevent grace period from ending
    mock_time.side_effect = [0, 0]
    mock_docker_client = mock.MagicMock(spec_set=docker.Client)
    mock_service_manifest = MarathonServiceConfig(
        service='fake_name',
        cluster='fake_cluster',
        instance='fake_instance',
        config_dict={
            'healthcheck_grace_period_seconds': 1,
        },
        branch_dict={},
    )

    fake_container_id = 'fake_container_id'
    fake_mode = 'http'
    fake_url = 'http://fake_host/fake_status_path'
    assert simulate_healthcheck_on_service(
        mock_service_manifest, mock_docker_client, fake_container_id, fake_mode, fake_url, True)
    assert mock_sleep.call_count == 0
    assert mock_run_healthcheck_on_container.call_count == 1
示例#15
0
def test_simulate_healthcheck_on_service_dead_container_exits_immediately(
        capsys):
    with mock.patch(
            'time.sleep',
            side_effect=AssertionError('sleep should not have been called'),
    ):
        mock_client = mock.MagicMock(spec_set=docker.Client)
        mock_client.inspect_container.return_value = {
            'State': {
                'Running': False,
                'ExitCode': 127
            },
        }
        fake_service_manifest = MarathonServiceConfig(
            service='fake_name',
            cluster='fake_cluster',
            instance='fake_instance',
            config_dict={},
            branch_dict={},
        )
        ret = simulate_healthcheck_on_service(
            fake_service_manifest,
            mock_client,
            mock.sentinel.container_id,
            'http',
            'http://fake_host/status',
            True,
        )
        assert ret == (False, 'Aborted by the user')
        out, _ = capsys.readouterr()
        assert out.count('Container exited with code 127') == 1
示例#16
0
def test_simulate_healthcheck_on_service_enabled_partial_failure(
        mock_run_healthcheck_on_container, mock_sleep):
    mock_run_healthcheck_on_container.side_effect = iter([(False, ""),
                                                          (False, ""),
                                                          (False, ""),
                                                          (False, ""),
                                                          (True, "")])
    mock_docker_client = mock.MagicMock(spec_set=docker.Client)
    mock_service_manifest = MarathonServiceConfig(
        service='fake_name',
        cluster='fake_cluster',
        instance='fake_instance',
        config_dict={
            'healthcheck_grace_period_seconds': 0,
        },
        branch_dict={},
    )

    fake_container_id = 'fake_container_id'
    fake_mode = 'http'
    fake_url = 'http://fake_host/fake_status_path'
    assert simulate_healthcheck_on_service(mock_service_manifest,
                                           mock_docker_client,
                                           fake_container_id, fake_mode,
                                           fake_url, True)
    # First run_healthcheck_on_container call happens silently
    assert mock_run_healthcheck_on_container.call_count == 5
    assert mock_sleep.call_count == 4
示例#17
0
def test_paasta_rollback_mark_for_deployment_simple_invocation(
    mock_mark_for_deployment,
    mock_get_git_url,
    mock_figure_out_service_name,
    mock_get_instance_config,
):

    fake_args = Mock(deploy_groups='fake_deploy_groups', commit='123456')

    mock_get_git_url.return_value = 'git://git.repo'
    mock_figure_out_service_name.return_value = 'fakeservice'

    mock_get_instance_config.return_value = [
        MarathonServiceConfig(
            service='',
            cluster='',
            instance='',
            branch_dict={},
            config_dict={'deploy_group': 'fake_deploy_groups'},
        )
    ]

    mock_mark_for_deployment.return_value = 0
    assert paasta_rollback(fake_args) == 0

    mock_mark_for_deployment.assert_called_once_with(
        git_url=mock_get_git_url.return_value,
        deploy_group=fake_args.deploy_groups,
        service=mock_figure_out_service_name.return_value,
        commit=fake_args.commit)

    assert mock_mark_for_deployment.call_count == 1
示例#18
0
def test_simulate_healthcheck_on_service_enabled_honors_grace_period(
        mock_run_healthcheck_on_container, mock_time, mock_sleep):
    # change time to make sure we are sufficiently past grace period
    mock_time.side_effect = [0, 2]
    mock_docker_client = mock.MagicMock(spec_set=docker.Client)
    mock_service_manifest = MarathonServiceConfig(
        service='fake_name',
        cluster='fake_cluster',
        instance='fake_instance',
        config_dict={
            # only one healthcheck will be performed silently
            'healthcheck_grace_period_seconds': 1,
        },
        branch_dict={},
    )

    fake_container_id = 'fake_container_id'
    fake_mode = 'http'
    fake_url = 'http://fake_host/fake_status_path'
    assert simulate_healthcheck_on_service(mock_service_manifest,
                                           mock_docker_client,
                                           fake_container_id, fake_mode,
                                           fake_url, True)
    assert mock_sleep.call_count == 0
    assert mock_run_healthcheck_on_container.call_count == 2
示例#19
0
def test_paasta_rollback_mark_for_deployment_wrong_deploy_group_args(
    mock_mark_for_deployment,
    mock_get_git_url,
    mock_figure_out_service_name,
    mock_get_instance_config_for_service,
):

    fake_args = Mock(
        commit='123456',
        deploy_groups='test_group,fake_deploy.group',
    )

    mock_get_git_url.return_value = 'git://git.repo'
    mock_figure_out_service_name.return_value = 'fakeservice'

    mock_get_instance_config_for_service.return_value = [
        MarathonServiceConfig(
            instance='some_other_instance',
            cluster='some_other_cluster',
            service=mock_figure_out_service_name.return_value,
            config_dict={},
            branch_dict={},
        ),
    ]

    assert paasta_rollback(fake_args) == 1
    assert mock_mark_for_deployment.call_count == 0
示例#20
0
def test_make_mutate_refs_func():
    mutate_refs = start_stop_restart.make_mutate_refs_func(
        service_config=MarathonServiceConfig(
            cluster='fake_cluster',
            instance='fake_instance',
            service='fake_service',
            config_dict={'deploy_group': 'a'},
            branch_dict=None,
        ),
        force_bounce='FORCEBOUNCE',
        desired_state='stop',
    )

    old_refs = {
        'refs/tags/paasta-a-20160308T053933-deploy': 'hash_for_a',
        'refs/tags/paasta-b-20160308T053933-deploy': 'hash_for_b',
        'refs/tags/paasta-c-20160308T053933-deploy': 'hash_for_c',
        'refs/tags/paasta-d-20160308T053933-deploy': 'hash_for_d',
    }

    expected = dict(old_refs)
    expected.update({
        'refs/tags/paasta-fake_cluster.fake_instance-FORCEBOUNCE-stop':
        'hash_for_a',
    })

    actual = mutate_refs(old_refs)
    assert actual == expected
def test_log_event():
    with contextlib.nested(
        mock.patch('paasta_tools.utils.get_username', autospec=True, return_value='fake_user'),
        mock.patch('socket.getfqdn', autospec=True, return_value='fake_fqdn'),
        mock.patch('paasta_tools.utils._log', autospec=True),
    ) as (
        mock_get_username,
        mock_getfqdn,
        mock_log,
    ):
        service_config = MarathonServiceConfig(
            cluster='fake_cluster',
            instance='fake_instance',
            service='fake_service',
            config_dict={'deploy_group': 'fake_deploy_group'},
            branch_dict={},
        )
        start_stop_restart.log_event(service_config, 'stopped')
        mock_log.assert_called_once_with(
            instance='fake_instance',
            service='fake_service',
            level='event',
            component='deploy',
            cluster='fake_cluster',
            line=("Issued request to change state of fake_instance (an instance of "
                  "fake_service) to 'stopped' by fake_user@fake_fqdn")
        )
示例#22
0
def test_issue_state_change_for_service(mock_log_event, get_transport_and_path,
                                        get_git_url):
    fake_git_url = 'BLOORGRGRGRGR'
    fake_path = 'somepath'

    get_git_url.return_value = fake_git_url

    mock_git_client = mock.Mock()
    get_transport_and_path.return_value = (mock_git_client, fake_path)

    start_stop_restart.issue_state_change_for_service(
        MarathonServiceConfig(
            cluster='fake_cluster',
            instance='fake_instance',
            service='fake_service',
            config_dict={},
            branch_dict=None,
        ),
        '0',
        'stop',
    )

    get_transport_and_path.assert_called_once_with(fake_git_url)
    mock_git_client.send_pack.assert_called_once_with(
        fake_path,
        mock.ANY,
        mock.ANY,
    )
    assert mock_log_event.call_count == 1
示例#23
0
def test_issue_state_change_for_service(
    mock_log_event,
    get_transport_and_path,
    get_git_url,
    mock_trigger_deploys,
):
    fake_git_url = "BLOORGRGRGRGR.yelpcorp.com"
    fake_path = "somepath"

    get_git_url.return_value = fake_git_url

    mock_git_client = mock.Mock()
    get_transport_and_path.return_value = (mock_git_client, fake_path)

    start_stop_restart.issue_state_change_for_service(
        MarathonServiceConfig(
            cluster="fake_cluster",
            instance="fake_instance",
            service="fake_service",
            config_dict={},
            branch_dict=None,
        ),
        "0",
        "stop",
    )

    get_transport_and_path.assert_called_once_with(fake_git_url)
    mock_git_client.send_pack.assert_called_once_with(fake_path, mock.ANY, mock.ANY)
    assert mock_log_event.call_count == 1
    mock_trigger_deploys.assert_called_once_with("fake_service")
def test_make_mutate_refs_func():
    mutate_refs = start_stop_restart.make_mutate_refs_func(
        service_config=MarathonServiceConfig(
            cluster="fake_cluster",
            instance="fake_instance",
            service="fake_service",
            config_dict={"deploy_group": "a"},
            branch_dict=None,
        ),
        force_bounce="FORCEBOUNCE",
        desired_state="stop",
    )

    old_refs = {
        "refs/tags/paasta-a-20160308T053933-deploy": "hash_for_a",
        "refs/tags/paasta-b-20160308T053933-deploy": "hash_for_b",
        "refs/tags/paasta-c-20160308T053933-deploy": "hash_for_c",
        "refs/tags/paasta-d-20160308T053933-deploy": "hash_for_d",
    }

    expected = dict(old_refs)
    expected.update(
        {"refs/tags/paasta-fake_cluster.fake_instance-FORCEBOUNCE-stop": "hash_for_a"}
    )

    actual = mutate_refs(old_refs)
    assert actual == expected
def test_start_or_stop_bad_refs(
    mock_list_clusters,
    mock_list_remote_refs,
    mock_get_instance_config,
    mock_apply_args_filters,
    capfd,
):
    args, _ = parse_args([
        'restart', '-s', 'fake_service', '-i', 'fake_instance',
        '-c', 'fake_cluster1,fake_cluster2', '-d', '/fake/soa/dir',
    ])
    mock_list_clusters.return_value = ['fake_cluster1', 'fake_cluster2']

    mock_get_instance_config.return_value = MarathonServiceConfig(
        cluster='fake_cluster1',
        instance='fake_instance',
        service='fake_service',
        config_dict={},
        branch_dict={},
    )
    mock_list_remote_refs.return_value = {
        "refs/tags/paasta-deliberatelyinvalidref-20160304T053919-deploy": "70f7245ccf039d778c7e527af04eac00d261d783",
    }
    mock_apply_args_filters.return_value = {
        'fake_cluster1': {'fake_service': ['fake_instance']},
        'fake_cluster2': {'fake_service': ['fake_instance']},
    }
    assert args.command(args) == 1
    assert "No branches found for" in capfd.readouterr()[0]
示例#26
0
def test_start_or_stop_bad_refs(mock_list_clusters, mock_list_all_instances,
                                mock_list_remote_refs,
                                mock_get_instance_config,
                                mock_figure_out_service_name, mock_stdout):

    args = mock.Mock()
    # To suppress any messages due to Mock making everything truthy
    args.clusters = 'fake_cluster1,fake_cluster2'
    args.soa_dir = '/fake/soa/dir'
    args.instances = 'fake_instance'

    mock_list_clusters.return_value = ['fake_cluster1', 'fake_cluster2']

    mock_figure_out_service_name.return_value = 'fake_service'
    mock_get_instance_config.return_value = MarathonServiceConfig(
        cluster='fake_cluster1',
        instance='fake_instance',
        service='fake_service',
        config_dict={},
        branch_dict={},
    )
    mock_list_remote_refs.return_value = {
        "refs/tags/paasta-deliberatelyinvalidref-20160304T053919-deploy":
        "70f7245ccf039d778c7e527af04eac00d261d783"
    }
    mock_list_all_instances.return_value = {args.instances}
    assert start_stop_restart.paasta_start_or_stop(args, 'restart') == 1
    assert "No branches found for" in mock_stdout.getvalue()
示例#27
0
def mock_marathon_instance_config(fake_name) -> "MarathonServiceConfig":
    return MarathonServiceConfig(
        service='fake_service',
        cluster='fake_cluster',
        instance=fake_name,
        config_dict={'deploy_group': 'fake_deploy_group'},
        branch_dict={},
        soa_dir='fake_soa_dir',
    )
def mock_marathon_instance_config(fake_name) -> "MarathonServiceConfig":
    return MarathonServiceConfig(
        service="fake_service",
        cluster="fake_cluster",
        instance=fake_name,
        config_dict={"deploy_group": "fake_deploy_group"},
        branch_dict=None,
        soa_dir="fake_soa_dir",
    )
示例#29
0
def test_create_marathon_dashboard(mock_get_services_for_cluster, mock_pscl,
                                   mock_load_system_paasta_config):
    soa_dir = '/fake/soa/dir'
    cluster = 'fake_cluster'
    mock_load_system_paasta_config.return_value = SystemPaastaConfig(
        {
            'dashboard_links': {},
        },
        'fake_directory',
    )
    mock_get_services_for_cluster.return_value = [
        ('fake_service', 'foo'),
        ('fake_service', 'bar'),
    ]
    mock_pscl.return_value.instance_configs.return_value = [
        MarathonServiceConfig('fake_service', 'fake_cluster', 'foo', {}, {},
                              soa_dir),
        MarathonServiceConfig('fake_service', 'fake_cluster', 'bar', {}, {},
                              soa_dir),
    ]

    mock_client = mock.Mock(servers=['hi'])
    mock_clients = MarathonClients(current=[mock_client],
                                   previous=[mock_client])

    expected_output = {
        'fake_cluster': [
            {
                'service': 'fake_service',
                'instance': 'foo',
                'shard_url': 'hi',
            },
            {
                'service': 'fake_service',
                'instance': 'bar',
                'shard_url': 'hi',
            },
        ],
    }
    assert marathon_dashboard.create_marathon_dashboard(
        cluster=cluster,
        soa_dir=soa_dir,
        marathon_clients=mock_clients,
    ) == expected_output
示例#30
0
def test_list_deploy_groups_parses_configs(
    mock_get_instance_configs_for_service, ):
    mock_get_instance_configs_for_service.return_value = [
        MarathonServiceConfig(
            service='foo',
            cluster='',
            instance='',
            config_dict={'deploy_group': 'fake_deploy_group'},
            branch_dict=None,
        ),
        MarathonServiceConfig(
            service='foo',
            cluster='fake_cluster',
            instance='fake_instance',
            config_dict={},
            branch_dict=None,
        ),
    ]
    actual = utils.list_deploy_groups(service="foo")
    assert actual == {'fake_deploy_group', 'fake_cluster.fake_instance'}