cloudflare/cloudflared

Public

mirrored fromhttps://github.com/cloudflare/cloudflaredAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
31f45fb5056bef48efae27fdc5b74bbd26fdf8a3

Branches

Tags

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

Clone

HTTPS

Download ZIP

component-tests/setup.py

156lines · modecode

1#!/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():
18 config_content = base64.b64decode(get_env("COMPONENT_TESTS_CONFIG_CONTENT")).decode('utf-8')
19 return yaml.safe_load(config_content)
20
21
22def get_config_from_file():
23 config_path = get_env("COMPONENT_TESTS_CONFIG")
24 with open(config_path, 'r') as infile:
25 return yaml.safe_load(infile)
26
27
28def persist_config(config):
29 config_path = get_env("COMPONENT_TESTS_CONFIG")
30 with open(config_path, 'w') as outfile:
31 yaml.safe_dump(config, outfile)
32
33
34def persist_origin_cert(config):
35 origincert = get_env("COMPONENT_TESTS_ORIGINCERT")
36 path = config["origincert"]
37 with open(path, 'w') as outfile:
38 outfile.write(origincert)
39 return 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.
47 credentials_path = config["credentials_file"]
48 try:
49 os.remove(credentials_path)
50 except OSError:
51 pass
52
53 tunnel_name = "cfd_component_test-" + random_uuid
54 create_cmd = [config["cloudflared_binary"], "tunnel", "--origincert", origincert_path, "create",
55 "--credentials-file", credentials_path, tunnel_name]
56 LOGGER.info(f"Creating tunnel with {create_cmd}")
57 subprocess.run(create_cmd, check=True)
58
59 list_cmd = [config["cloudflared_binary"], "tunnel", "--origincert", origincert_path, "list", "--name",
60 tunnel_name, "--output", "json"]
61 LOGGER.info(f"Listing tunnel with {list_cmd}")
62 cloudflared = subprocess.run(list_cmd, check=True, capture_output=True)
63 return 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):
68 credentials_path = config["credentials_file"]
69 delete_cmd = [config["cloudflared_binary"], "tunnel", "--origincert", config["origincert"], "delete",
70 "--credentials-file", credentials_path, "-f", config["tunnel"]]
71 LOGGER.info(f"Deleting tunnel with {delete_cmd}")
72 subprocess.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):
77 cf = CloudFlare.CloudFlare(debug=False, token=get_env("DNS_API_TOKEN"))
78 cf.zones.dns_records.post(
79 config["zone_tag"],
80 data={'name': hostname, 'type': type, 'content': content, 'proxied': True}
81 )
82
83
84def create_named_dns(config, random_uuid):
85 hostname = "named-" + random_uuid + "." + config["zone_domain"]
86 create_dns(config, hostname, "CNAME", config["tunnel"] + ".cfargotunnel.com")
87 return hostname
88
89
90@retry(stop_max_attempt_number=MAX_RETRIES, wait_fixed=BACKOFF_SECS * 1000)
91def delete_dns(config, hostname):
92 cf = CloudFlare.CloudFlare(debug=False, token=get_env("DNS_API_TOKEN"))
93 zone_tag = config["zone_tag"]
94 dns_records = cf.zones.dns_records.get(zone_tag, params={'name': hostname})
95 if len(dns_records) > 0:
96 cf.zones.dns_records.delete(zone_tag, dns_records[0]['id'])
97
98
99def write_file(content, path):
100 with open(path, 'w') as outfile:
101 outfile.write(content)
102
103
104def get_env(env_name):
105 val = os.getenv(env_name)
106 if val is None:
107 raise Exception(f"{env_name} is not set")
108 return val
109
110
111def create():
112 """
113 Creates the necessary resources for the components test to run.
114 - Creates a named tunnel with a random name.
115 - Creates a random CNAME DNS entry for that tunnel.
116
117 Those created resources are added to the config (obtained from an environment variable).
118 The resulting configuration is persisted for the tests to use.
119 """
120 config = get_config_from_env()
121 origincert_path = persist_origin_cert(config)
122
123 random_uuid = str(uuid.uuid4())
124 config["tunnel"] = create_tunnel(config, origincert_path, random_uuid)
125 config["ingress"] = [
126 {
127 "hostname": create_named_dns(config, random_uuid),
128 "service": "hello_world"
129 },
130 {
131 "service": "http_status:404"
132 }
133 ]
134
135 persist_config(config)
136
137
138def cleanup():
139 """
140 Reads the persisted configuration that was created previously.
141 Deletes the resources that were created there.
142 """
143 config = get_config_from_file()
144 delete_tunnel(config)
145 delete_dns(config, config["ingress"][0]["hostname"])
146
147
148if __name__ == '__main__':
149 parser = argparse.ArgumentParser(description='setup component tests')
150 parser.add_argument('--type', choices=['create', 'cleanup'], default='create')
151 args = parser.parse_args()
152
153 if args.type == 'create':
154 create()
155 else:
156 cleanup()
157