Пример #1
0
def test_bad_config():
    with pytest.raises(Exception):
        KubeletCheck('kubelet', None, {}, [{}, {}])
Пример #2
0
def test_parse_quantity():
    for raw, res in iteritems(QUANTITIES):
        assert KubeletCheck.parse_quantity(raw) == res
Пример #3
0
def test_report_container_state_metrics(monkeypatch, tagger):
    check = KubeletCheck('kubelet', None, {}, [{}])
    check.pod_list_url = "dummyurl"
    monkeypatch.setattr(
        check, 'perform_kubelet_query',
        mock.Mock(return_value=MockStreamResponse('pods_crashed.json')))
    monkeypatch.setattr(check, '_compute_pod_expiration_datetime',
                        mock.Mock(return_value=None))
    monkeypatch.setattr(check, 'gauge', mock.Mock())

    attrs = {'is_excluded.return_value': False}
    check.pod_list_utils = mock.Mock(**attrs)

    pod_list = check.retrieve_pod_list()

    instance_tags = ["one:1", "two:2"]
    check._report_container_state_metrics(pod_list, instance_tags)

    calls = [
        mock.call(
            'kubernetes.containers.last_state.terminated',
            1,
            [
                'kube_container_name:fluentd-gcp',
                'kube_deployment:fluentd-gcp-v2.0.10'
            ] + instance_tags + ['reason:OOMKilled'],
        ),
        mock.call(
            'kubernetes.containers.state.waiting',
            1,
            [
                'kube_container_name:prometheus-to-sd-exporter',
                'kube_deployment:fluentd-gcp-v2.0.10'
            ] + instance_tags + ['reason:CrashLoopBackOff'],
        ),
        mock.call(
            'kubernetes.containers.restarts',
            1,
            [
                'kube_container_name:fluentd-gcp',
                'kube_deployment:fluentd-gcp-v2.0.10'
            ] + instance_tags,
        ),
        mock.call(
            'kubernetes.containers.restarts',
            0,
            [
                'kube_container_name:prometheus-to-sd-exporter',
                'kube_deployment:fluentd-gcp-v2.0.10'
            ] + instance_tags,
        ),
        mock.call('kubernetes.containers.restarts', 0,
                  ['kube_container_name:datadog-agent'] + instance_tags),
        mock.call('kubernetes.containers.restarts', 0,
                  ['kube_container_name:datadog-agent'] + instance_tags),
    ]
    check.gauge.assert_has_calls(calls, any_order=True)

    container_state_gauges = [
        x[0][2] for x in check.gauge.call_args_list
        if x[0][0].startswith('kubernetes.containers.state')
    ]
    if any(map(lambda e: 'reason:TransientReason' in e,
               container_state_gauges)):
        raise AssertionError(
            'kubernetes.containers.state.* was submitted with a transient reason'
        )
    if any(
            map(lambda e: not any(x for x in e if x.startswith('reason:')),
                container_state_gauges)):
        raise AssertionError(
            'kubernetes.containers.state.* was submitted without a reason')
Пример #4
0
def mock_kubelet_check(monkeypatch,
                       instances,
                       kube_version=KUBE_1_14,
                       stats_summary_fail=False):
    """
    Returns a check that uses mocked data for responses from prometheus endpoints, pod list,
    and node spec.
    """
    check = KubeletCheck('kubelet', None, {}, instances)
    monkeypatch.setattr(
        check, 'retrieve_pod_list',
        mock.Mock(return_value=json.loads(mock_from_file('pods.json'))))
    monkeypatch.setattr(check, '_retrieve_node_spec',
                        mock.Mock(return_value=NODE_SPEC))
    if stats_summary_fail:
        monkeypatch.setattr(check, '_retrieve_stats',
                            mock.Mock(return_value={}))
    else:
        monkeypatch.setattr(
            check, '_retrieve_stats',
            mock.Mock(
                return_value=json.loads(mock_from_file('stats_summary.json'))))
    monkeypatch.setattr(check, '_perform_kubelet_check',
                        mock.Mock(return_value=None))
    monkeypatch.setattr(check, '_compute_pod_expiration_datetime',
                        mock.Mock(return_value=None))

    def mocked_poll(cadvisor_response, kubelet_response):
        def _mocked_poll(*args, **kwargs):
            scraper_config = args[0]
            prometheus_url = scraper_config['prometheus_url']

            if prometheus_url.endswith('/metrics/cadvisor'):
                # Mock response for "/metrics/cadvisor"
                content = mock_from_file(cadvisor_response)
            elif prometheus_url.endswith('/metrics'):
                # Mock response for "/metrics"
                content = mock_from_file(kubelet_response)
            else:
                raise Exception("Must be a valid endpoint")

            attrs = {
                'close.return_value': True,
                'iter_lines.return_value': content.split('\n'),
                'content': content
            }
            return mock.Mock(headers={'Content-Type': 'text/plain'}, **attrs)

        return _mocked_poll

    if kube_version == KUBE_POST_1_16:
        monkeypatch.setattr(
            check,
            'poll',
            mock.Mock(side_effect=mocked_poll(
                cadvisor_response='cadvisor_metrics_post_1_16.txt',
                kubelet_response='kubelet_metrics_1_14.txt')),
        )
    elif kube_version == KUBE_1_14:
        monkeypatch.setattr(
            check,
            'poll',
            mock.Mock(side_effect=mocked_poll(
                cadvisor_response='cadvisor_metrics_pre_1_16.txt',
                kubelet_response='kubelet_metrics_1_14.txt',
            )),
        )
    elif kube_version == KUBE_PRE_1_14:
        monkeypatch.setattr(
            check,
            'poll',
            mock.Mock(side_effect=mocked_poll(
                cadvisor_response='cadvisor_metrics_pre_1_16.txt',
                kubelet_response='kubelet_metrics.txt')),
        )

    return check