cloudflare/cloudflared

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
9018ee5d5ed771a2aef8d4daadc9875c0605fb02

Branches

Tags

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

Clone

HTTPS

Download ZIP

component-tests/test_service.py

139lines · modecode

1#!/usr/bin/env python
2import os
3import platform
4import subprocess
5from contextlib import contextmanager
6from pathlib import Path
7
8import pytest
9
10import test_logging
11from util import start_cloudflared, wait_tunnel_ready
12
13
14def select_platform(plat):
15 return pytest.mark.skipif(
16 platform.system() != plat, reason=f"Only runs on {plat}")
17
18
19def default_config_dir():
20 return os.path.join(Path.home(), ".cloudflared")
21
22
23def default_config_file():
24 return os.path.join(default_config_dir(), "config.yml")
25
26
27class TestServiceMode:
28 @select_platform("Darwin")
29 @pytest.mark.skipif(os.path.exists(default_config_file()), reason=f"There is already a config file in default path")
30 def test_launchd_service_log_to_file(self, tmp_path, component_tests_config):
31 log_file = tmp_path / test_logging.default_log_file
32 additional_config = {
33 # On Darwin cloudflared service defaults to run classic tunnel command
34 "hello-world": True,
35 "logfile": str(log_file),
36 }
37 config = component_tests_config(additional_config=additional_config, named_tunnel=False)
38
39 def assert_log_file():
40 test_logging.assert_log_in_file(log_file)
41 test_logging.assert_json_log(log_file)
42
43 self.launchd_service_scenario(config, assert_log_file)
44
45 @select_platform("Darwin")
46 @pytest.mark.skipif(os.path.exists(default_config_file()), reason=f"There is already a config file in default path")
47 def test_launchd_service_rotating_log(self, tmp_path, component_tests_config):
48 log_dir = tmp_path / "logs"
49 additional_config = {
50 # On Darwin cloudflared service defaults to run classic tunnel command
51 "hello-world": True,
52 "loglevel": "debug",
53 "log-directory": str(log_dir),
54 }
55 config = component_tests_config(additional_config=additional_config, named_tunnel=False)
56
57 def assert_rotating_log():
58 test_logging.assert_log_to_dir(config, log_dir)
59
60 self.launchd_service_scenario(config, assert_rotating_log)
61
62 def launchd_service_scenario(self, config, extra_assertions):
63 with self.run_service(Path(default_config_dir()), config):
64 self.launchctl_cmd("list")
65 self.launchctl_cmd("start")
66 wait_tunnel_ready(tunnel_url=config.get_url())
67 extra_assertions()
68 self.launchctl_cmd("stop")
69
70 os.remove(default_config_file())
71 self.launchctl_cmd("list", success=False)
72
73 @select_platform("Linux")
74 @pytest.mark.skipif(os.path.exists("/etc/cloudflared/config.yml"),
75 reason=f"There is already a config file in default path")
76 def test_sysv_service_log_to_file(self, tmp_path, component_tests_config):
77 log_file = tmp_path / test_logging.default_log_file
78 additional_config = {
79 "logfile": str(log_file),
80 }
81 config = component_tests_config(additional_config=additional_config)
82
83 def assert_log_file():
84 test_logging.assert_log_in_file(log_file)
85 test_logging.assert_json_log(log_file)
86
87 self.sysv_service_scenario(config, tmp_path, assert_log_file)
88
89 @select_platform("Linux")
90 @pytest.mark.skipif(os.path.exists("/etc/cloudflared/config.yml"),
91 reason=f"There is already a config file in default path")
92 def test_sysv_service_rotating_log(self, tmp_path, component_tests_config):
93 log_dir = tmp_path / "logs"
94 additional_config = {
95 "loglevel": "debug",
96 "log-directory": str(log_dir),
97 }
98 config = component_tests_config(additional_config=additional_config)
99
100 def assert_rotating_log():
101 # We need the folder to have executable permissions for the "stat" command in the assertions to work.
102 subprocess.check_call(['sudo', 'chmod', 'o+x', log_dir])
103 test_logging.assert_log_to_dir(config, log_dir)
104
105 self.sysv_service_scenario(config, tmp_path, assert_rotating_log)
106
107 def sysv_service_scenario(self, config, tmp_path, extra_assertions):
108 with self.run_service(tmp_path, config, root=True):
109 self.sysv_cmd("start")
110 self.sysv_cmd("status")
111 wait_tunnel_ready(tunnel_url=config.get_url())
112 extra_assertions()
113 self.sysv_cmd("stop")
114
115 # Service install copies config file to /etc/cloudflared/config.yml
116 subprocess.run(["sudo", "rm", "/etc/cloudflared/config.yml"])
117 self.sysv_cmd("status", success=False)
118
119 @contextmanager
120 def run_service(self, tmp_path, config, root=False):
121 try:
122 service = start_cloudflared(
123 tmp_path, config, cfd_args=["service", "install"], cfd_pre_args=[], capture_output=False, root=root)
124 yield service
125 finally:
126 start_cloudflared(
127 tmp_path, config, cfd_args=["service", "uninstall"], cfd_pre_args=[], capture_output=False, root=root)
128
129 def launchctl_cmd(self, action, success=True):
130 cmd = subprocess.run(
131 ["launchctl", action, "com.cloudflare.cloudflared"], check=success)
132 if not success:
133 assert cmd.returncode != 0, f"Expect {cmd.args} to fail, but it succeed"
134
135 def sysv_cmd(self, action, success=True):
136 cmd = subprocess.run(
137 ["sudo", "service", "cloudflared", action], check=success)
138 if not success:
139 assert cmd.returncode != 0, f"Expect {cmd.args} to fail, but it succeed"
140