Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add environment runner for Kubernetes' kind #6522

Merged
merged 23 commits into from
May 13, 2020
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ coverage.xml
.pytest_cache/
.benchmarks/
.junit/
.kube/

# Translations
*.mo
Expand Down
8 changes: 4 additions & 4 deletions cilium/tests/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
'cilium.controllers.failing.count',
'cilium.controllers.runs_duration.seconds.count',
'cilium.controllers.runs_duration.seconds.sum',
'cilium.datapath.conntrack_gc.duration.seconds.count',
'cilium.datapath.conntrack_gc.duration.seconds.sum',
'cilium.datapath.conntrack_gc.entries',
'cilium.datapath.errors.total',
'cilium.endpoint.count',
'cilium.endpoint.regeneration_time_stats.seconds.count',
'cilium.endpoint.regeneration_time_stats.seconds.sum',
Expand Down Expand Up @@ -74,6 +70,10 @@
'cilium.datapath.conntrack_gc.runs.total',
'cilium.controllers.runs.total',
'cilium.bpf.map_ops.total',
'cilium.datapath.conntrack_gc.duration.seconds.count',
'cilium.datapath.conntrack_gc.duration.seconds.sum',
'cilium.datapath.conntrack_gc.entries',
'cilium.datapath.errors.total',
]

OPERATOR_METRICS = [
Expand Down
52 changes: 33 additions & 19 deletions cilium/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@
import pytest

from datadog_checks.base.utils.common import get_docker_hostname
from datadog_checks.dev import run_command
from datadog_checks.dev.kind import kind_run
from datadog_checks.dev.kube_port_forward import port_forward
from datadog_checks.dev.terraform import terraform_run

from .common import ADDL_AGENT_METRICS, AGENT_DEFAULT_METRICS, OPERATOR_AWS_METRICS, OPERATOR_METRICS

try:
from contextlib import ExitStack
except ImportError:
from contextlib2 import ExitStack


HERE = os.path.dirname(os.path.abspath(__file__))
HOST = get_docker_hostname()
AGENT_PORT = 9090
Expand All @@ -27,29 +27,43 @@
PORTS = [AGENT_PORT, OPERATOR_PORT]


def setup_cilium():
config = os.path.join(HERE, 'kind', 'cilium.yaml')
run_command(
[
"kubectl",
"create",
"clusterrolebinding",
"cluster-admin-binding",
"--clusterrole",
"cluster-admin",
"--user",
"[email protected]",
]
)
run_command(["kubectl", "create", "ns", "cilium"])
run_command(["kubectl", "create", "-f", config])
run_command(
["kubectl", "wait", "deployments", "--all", "--for=condition=Available", "-n", "cilium", "--timeout=300s"]
)
run_command(["kubectl", "wait", "pods", "-n", "cilium", "--all", "--for=condition=Ready", "--timeout=300s"])


@pytest.fixture(scope='session')
def dd_environment():
with terraform_run(os.path.join(HERE, 'terraform')) as outputs:
kubeconfig = outputs['kubeconfig']['value']
with kind_run(HERE, conditions=[setup_cilium]) as kubeconfig:
with ExitStack() as stack:
ip_ports = [
stack.enter_context(port_forward(kubeconfig, 'cilium', 'cilium-operator', port)) for port in PORTS
]
instances = {
'instances': [
{'agent_endpoint': 'http://{}:{}/metrics'.format(*ip_ports[0])},
{'operator_endpoint': 'http://{}:{}/metrics'.format(*ip_ports[1])},
]
}

instances = {
'instances': [
{
'agent_endpoint': 'http://{}:{}/metrics'.format(*ip_ports[0]),
'metrics': ADDL_AGENT_METRICS + AGENT_DEFAULT_METRICS,
},
{
'operator_endpoint': 'http://{}:{}/metrics'.format(*ip_ports[1]),
'metrics': OPERATOR_METRICS + OPERATOR_AWS_METRICS,
},
]
}

yield instances
yield instances


@pytest.fixture(scope="session")
Expand Down
File renamed without changes.
23 changes: 0 additions & 23 deletions cilium/tests/terraform/kubeconfig-template.yaml

This file was deleted.

42 changes: 0 additions & 42 deletions cilium/tests/terraform/main.tf

This file was deleted.

34 changes: 0 additions & 34 deletions cilium/tests/terraform/script.py

This file was deleted.

3 changes: 1 addition & 2 deletions cilium/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ envlist =
[testenv]
dd_check_style = true
description =
py{27,38}: e2e ready if TF_VAR_account_json
py{27,38}: e2e ready
usedevelop = true
platform = linux|darwin|win32
deps =
Expand All @@ -17,7 +17,6 @@ deps =
passenv =
DOCKER*
COMPOSE*
TF_VAR*
commands =
pip install -r requirements.in
pytest -v {posargs}
Expand Down
91 changes: 91 additions & 0 deletions datadog_checks_dev/datadog_checks/dev/kind.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# (C) Datadog, Inc. 2019-present
# All rights reserved
# Licensed under a 3-clause BSD style license (see LICENSE)
import os
from contextlib import contextmanager

import pytest
from six import PY3

from .env import environment_run
from .structures import LazyFunction
from .subprocess import run_command
from .utils import find_check_root, get_check_name, get_here, get_tox_env, path_join

if PY3:
from shutil import which
else:
from shutilwhich import which


@contextmanager
def kind_run(directory, sleep=None, endpoints=None, conditions=None, env_vars=None, wrappers=None):
"""This utility provides a convenient way to safely set up and tear down Kind environments.

:param directory: A path containing Kind files.
:type directory: ``str``
:param sleep: Number of seconds to wait before yielding.
:type sleep: ``float``
:param endpoints: Endpoints to verify access for before yielding. Shorthand for adding
``conditions.CheckEndpoints(endpoints)`` to the ``conditions`` argument.
:type endpoints: ``list`` of ``str``, or a single ``str``
:param conditions: A list of callable objects that will be executed before yielding to check for errors.
:type conditions: ``callable``
:param env_vars: A dictionary to update ``os.environ`` with during execution.
:type env_vars: ``dict``
:param wrappers: A list of context managers to use during execution.
"""
if not which('kind'):
pytest.skip('Kind not available')

get_here()
set_up = KindUp(directory)
tear_down = KindDown(directory)

with environment_run(
up=set_up,
down=tear_down,
sleep=sleep,
endpoints=endpoints,
conditions=conditions,
env_vars=env_vars,
wrappers=wrappers,
) as result:
yield result


class KindUp(LazyFunction):
"""Create the kind cluster and use its context, calling
`kind create cluster --name <integration>-cluster`

It also returns the kubeconfig path as a `str`.
"""

def __init__(self, directory):
self.directory = directory
self.check_root = find_check_root(depth=3)
self.check_name = get_check_name(self.directory)
self.cluster_name = '{}-{}-cluster'.format(self.check_name, get_tox_env())

def __call__(self):
kube_path = path_join(self.check_root, '.kube', 'config')
env = os.environ.copy()
env['KUBECONFIG'] = kube_path
# Create cluster
run_command(['kind', 'create', 'cluster', '--name', self.cluster_name], check=True, env=env)
mgarabed marked this conversation as resolved.
Show resolved Hide resolved
# Connect to cluster
run_command(['kind', 'export', 'kubeconfig', '--name', self.cluster_name], check=True, env=env)

return kube_path


class KindDown(LazyFunction):
"""Delete the kind cluster, calling `delete cluster`."""

def __init__(self, directory):
self.directory = directory
self.check_name = get_check_name(self.directory)
self.cluster_name = '{}-{}-cluster'.format(self.check_name, get_tox_env())

def __call__(self):
return run_command(['kind', 'delete', 'cluster', '--name', self.cluster_name], check=True)
21 changes: 21 additions & 0 deletions datadog_checks_dev/datadog_checks/dev/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
ON_LINUX = not (ON_MACOS or ON_WINDOWS)


def get_tox_env():
return os.environ['TOX_ENV_NAME']


def get_ci_env_vars():
return ('AGENT_OS', 'SYSTEM_TEAMFOUNDATIONCOLLECTIONURI')

Expand Down Expand Up @@ -246,6 +250,23 @@ def find_check_root(depth=0):
return root


def get_check_name(root):
"""
Get check name from path
"""
while True:
if os.path.isfile(os.path.join(root, 'setup.py')):
check = os.path.basename(root)
break

new_root = os.path.dirname(root)
if new_root == root:
raise OSError('No Datadog Agent check found')

root = new_root
return check


@contextmanager
def temp_dir():
# TODO: On Python 3.5+ just use `with TemporaryDirectory() as d:`.
Expand Down