| 1 | import click |
| 2 | import asyncio |
| 3 | import sys |
| 4 | import pathlib |
| 5 | import dagger |
| 6 | import uuid |
| 7 | import httpx |
| 8 | |
| 9 | from nd import Distribution, NetdataInstaller, FeatureFlags, Endpoint, AgentContext |
| 10 | |
| 11 | |
| 12 | def run_async(func): |
| 13 | def wrapper(*args, **kwargs): |
| 14 | return asyncio.run(func(*args, **kwargs)) |
| 15 | |
| 16 | return wrapper |
| 17 | |
| 18 | |
| 19 | @run_async |
| 20 | async def simple_test(): |
| 21 | config = dagger.Config(log_output=sys.stdout) |
| 22 | |
| 23 | async with dagger.Connection(config) as client: |
| 24 | platform = dagger.Platform("linux/x86_64") |
| 25 | distro = Distribution("debian10") |
| 26 | |
| 27 | repo_root = pathlib.Path("/netdata") |
| 28 | prefix_path = pathlib.Path("/opt/netdata") |
| 29 | installer = NetdataInstaller( |
| 30 | platform, distro, repo_root, prefix_path, FeatureFlags.DBEngine |
| 31 | ) |
| 32 | |
| 33 | api_key = uuid.uuid4() |
| 34 | |
| 35 | # |
| 36 | # parent |
| 37 | # |
| 38 | parent_endpoint = Endpoint("parent1", 22000) |
| 39 | parent_ctx = AgentContext( |
| 40 | client, platform, distro, installer, parent_endpoint, api_key, True |
| 41 | ) |
| 42 | parent_cmd = installer.prefix / "usr/sbin/netdata" |
| 43 | parent_args = [ |
| 44 | parent_cmd.as_posix(), |
| 45 | "-D", |
| 46 | "-i", |
| 47 | "0.0.0.0", |
| 48 | "-p", |
| 49 | str(parent_endpoint.port), |
| 50 | ] |
| 51 | |
| 52 | parent_ctr = parent_ctx.build_container() |
| 53 | parent_ctr = parent_ctr.with_exec(parent_args) |
| 54 | parent_svc = parent_ctr.as_service() |
| 55 | |
| 56 | # |
| 57 | # child |
| 58 | # |
| 59 | child_endpoint = Endpoint("child1", 21000) |
| 60 | child_ctx = AgentContext( |
| 61 | client, platform, distro, installer, child_endpoint, api_key, False |
| 62 | ) |
| 63 | child_ctx.add_parent(parent_ctx) |
| 64 | child_cmd = installer.prefix / "usr/sbin/netdata" |
| 65 | child_args = [ |
| 66 | child_cmd.as_posix(), |
| 67 | "-D", |
| 68 | "-i", |
| 69 | "0.0.0.0", |
| 70 | "-p", |
| 71 | str(child_endpoint.port), |
| 72 | ] |
| 73 | |
| 74 | child_ctr = child_ctx.build_container() |
| 75 | child_ctr = child_ctr.with_service_binding(parent_endpoint.hostname, parent_svc) |
| 76 | child_ctr = child_ctr.with_exec(child_args) |
| 77 | child_svc = child_ctr.as_service() |
| 78 | |
| 79 | # |
| 80 | # endpoints |
| 81 | # |
| 82 | parent_tunnel, child_tunnel = await asyncio.gather( |
| 83 | client.host().tunnel(parent_svc, native=True).start(), |
| 84 | client.host().tunnel(child_svc, native=True).start(), |
| 85 | ) |
| 86 | |
| 87 | parent_endpoint, child_endpoint = await asyncio.gather( |
| 88 | parent_tunnel.endpoint(), |
| 89 | child_tunnel.endpoint(), |
| 90 | ) |
| 91 | |
| 92 | await asyncio.sleep(10) |
| 93 | |
| 94 | # |
| 95 | # run tests |
| 96 | # |
| 97 | |
| 98 | async with httpx.AsyncClient() as http: |
| 99 | resp = await http.get(f"http://{parent_endpoint}/api/v1/info") |
| 100 | |
| 101 | # |
| 102 | # Check that the child was connected |
| 103 | # |
| 104 | jd = resp.json() |
| 105 | assert ( |
| 106 | "hosts-available" in jd |
| 107 | ), "Could not find 'host-available' key in api/v1/info" |
| 108 | assert jd["hosts-available"] == 2, "Child did not connect to parent" |
| 109 | |
| 110 | # |
| 111 | # Check bearer protection |
| 112 | # |
| 113 | forbidden_urls = [ |
| 114 | f"http://{parent_endpoint}/api/v2/bearer_protection", |
| 115 | f"http://{parent_endpoint}/api/v2/bearer_get_token", |
| 116 | ] |
| 117 | |
| 118 | for url in forbidden_urls: |
| 119 | async with httpx.AsyncClient() as http: |
| 120 | resp = await http.get(url) |
| 121 | assert ( |
| 122 | resp.status_code == httpx.codes.UNAVAILABLE_FOR_LEGAL_REASONS |
| 123 | ), "Bearer protection is broken" |
| 124 | |
| 125 | |
| 126 | @click.command(help="Run a simple parent/child test") |
| 127 | def test(): |
| 128 | simple_test() |