cloudflare/cloudflared

Public

mirrored from https://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
2021.11.0

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

component-tests/setup.py

165lines · modeblame

9d3a7bd0Nuno Diegues5 years ago1#!/usr/bin/env python
2import argparse
3import base64
4import json
5import os
6import subprocess
7import uuid
8
9import CloudFlare
10import yaml
11from retrying import retry
12
13from constants import MAX_RETRIES, BACKOFF_SECS
14from util import LOGGER
15
16
17def get_config_from_env():
18config_content = base64.b64decode(get_env("COMPONENT_TESTS_CONFIG_CONTENT")).decode('utf-8')
19return yaml.safe_load(config_content)
20
21
22def get_config_from_file():
23config_path = get_env("COMPONENT_TESTS_CONFIG")
24with open(config_path, 'r') as infile:
25return yaml.safe_load(infile)
26
27
28def persist_config(config):
29config_path = get_env("COMPONENT_TESTS_CONFIG")
30with open(config_path, 'w') as outfile:
31yaml.safe_dump(config, outfile)
32
33
34def persist_origin_cert(config):
35origincert = get_env("COMPONENT_TESTS_ORIGINCERT")
36path = config["origincert"]
37with open(path, 'w') as outfile:
38outfile.write(origincert)
39return path
40
41
42@retry(stop_max_attempt_number=MAX_RETRIES, wait_fixed=BACKOFF_SECS * 1000)
43def create_tunnel(config, origincert_path, random_uuid):
44# Delete any previous existing credentials file. If the agent keeps files around (that's the case in Windows) then
45# cloudflared tunnel create will refuse to create the tunnel because it does not want to overwrite credentials
46# files.
47credentials_path = config["credentials_file"]
48try:
49os.remove(credentials_path)
50except OSError:
51pass
52
53tunnel_name = "cfd_component_test-" + random_uuid
54create_cmd = [config["cloudflared_binary"], "tunnel", "--origincert", origincert_path, "create",
55"--credentials-file", credentials_path, tunnel_name]
56LOGGER.info(f"Creating tunnel with {create_cmd}")
57subprocess.run(create_cmd, check=True)
58
59list_cmd = [config["cloudflared_binary"], "tunnel", "--origincert", origincert_path, "list", "--name",
60tunnel_name, "--output", "json"]
61LOGGER.info(f"Listing tunnel with {list_cmd}")
62cloudflared = subprocess.run(list_cmd, check=True, capture_output=True)
63return json.loads(cloudflared.stdout)[0]["id"]
64
65
66@retry(stop_max_attempt_number=MAX_RETRIES, wait_fixed=BACKOFF_SECS * 1000)
67def delete_tunnel(config):
68credentials_path = config["credentials_file"]
69delete_cmd = [config["cloudflared_binary"], "tunnel", "--origincert", config["origincert"], "delete",
70"--credentials-file", credentials_path, "-f", config["tunnel"]]
71LOGGER.info(f"Deleting tunnel with {delete_cmd}")
72subprocess.run(delete_cmd, check=True)
73
74
75@retry(stop_max_attempt_number=MAX_RETRIES, wait_fixed=BACKOFF_SECS * 1000)
76def create_dns(config, hostname, type, content):
77cf = CloudFlare.CloudFlare(debug=True, token=get_env("DNS_API_TOKEN"))
78cf.zones.dns_records.post(
79config["zone_tag"],
80data={'name': hostname, 'type': type, 'content': content, 'proxied': True}
81)
82
83
84def create_classic_dns(config, random_uuid):
85classic_hostname = "classic-" + random_uuid + "." + config["zone_domain"]
86create_dns(config, classic_hostname, "AAAA", "fd10:aec2:5dae::")
87return classic_hostname
88
89
90def create_named_dns(config, random_uuid):
91hostname = "named-" + random_uuid + "." + config["zone_domain"]
92create_dns(config, hostname, "CNAME", config["tunnel"] + ".cfargotunnel.com")
93return hostname
94
95
96@retry(stop_max_attempt_number=MAX_RETRIES, wait_fixed=BACKOFF_SECS * 1000)
97def delete_dns(config, hostname):
98cf = CloudFlare.CloudFlare(debug=True, token=get_env("DNS_API_TOKEN"))
99zone_tag = config["zone_tag"]
100dns_records = cf.zones.dns_records.get(zone_tag, params={'name': hostname})
101if len(dns_records) > 0:
102cf.zones.dns_records.delete(zone_tag, dns_records[0]['id'])
103
104
105def write_file(content, path):
106with open(path, 'w') as outfile:
107outfile.write(content)
108
109
110def get_env(env_name):
111val = os.getenv(env_name)
112if val is None:
113raise Exception(f"{env_name} is not set")
114return val
115
116
117def create():
118"""
119Creates the necessary resources for the components test to run.
120- Creates a named tunnel with a random name.
121- Creates a random CNAME DNS entry for that tunnel.
122- Creates a random AAAA DNS entry for a classic tunnel.
123
124Those created resources are added to the config (obtained from an environment variable).
125The resulting configuration is persisted for the tests to use.
126"""
127config = get_config_from_env()
128origincert_path = persist_origin_cert(config)
129
130random_uuid = str(uuid.uuid4())
131config["tunnel"] = create_tunnel(config, origincert_path, random_uuid)
132config["classic_hostname"] = create_classic_dns(config, random_uuid)
133config["ingress"] = [
134{
135"hostname": create_named_dns(config, random_uuid),
136"service": "hello_world"
137},
138{
139"service": "http_status:404"
140}
141]
142
143persist_config(config)
144
145
146def cleanup():
147"""
148Reads the persisted configuration that was created previously.
149Deletes the resources that were created there.
150"""
151config = get_config_from_file()
152delete_tunnel(config)
153delete_dns(config, config["classic_hostname"])
154delete_dns(config, config["ingress"][0]["hostname"])
155
156
157if __name__ == '__main__':
158parser = argparse.ArgumentParser(description='setup component tests')
159parser.add_argument('--type', choices=['create', 'cleanup'], default='create')
160args = parser.parse_args()
161
162if args.type == 'create':
163create()
164else:
165cleanup()