1import ./make-test-python.nix (
2 { pkgs, lib, ... }:
3
4 let
5 user = "alice"; # from ./common/user-account.nix
6 password = "foobar"; # from ./common/user-account.nix
7 in {
8 name = "cockpit";
9 meta = {
10 maintainers = with lib.maintainers; [ lucasew ];
11 };
12 nodes = {
13 server = { config, ... }: {
14 imports = [ ./common/user-account.nix ];
15 security.polkit.enable = true;
16 users.users.${user} = {
17 extraGroups = [ "wheel" ];
18 };
19 services.cockpit = {
20 enable = true;
21 openFirewall = true;
22 settings = {
23 WebService = {
24 Origins = "https://server:9090";
25 };
26 };
27 };
28 };
29 client = { config, ... }: {
30 imports = [ ./common/user-account.nix ];
31 environment.systemPackages = let
32 seleniumScript = pkgs.writers.writePython3Bin "selenium-script" {
33 libraries = with pkgs.python3Packages; [ selenium ];
34 } ''
35 from selenium import webdriver
36 from selenium.webdriver.common.by import By
37 from selenium.webdriver.firefox.options import Options
38 from selenium.webdriver.support.ui import WebDriverWait
39 from selenium.webdriver.support import expected_conditions as EC
40 from time import sleep
41
42
43 def log(msg):
44 from sys import stderr
45 print(f"[*] {msg}", file=stderr)
46
47
48 log("Initializing")
49
50 options = Options()
51 options.add_argument("--headless")
52
53 service = webdriver.FirefoxService(executable_path="${lib.getExe pkgs.geckodriver}") # noqa: E501
54 driver = webdriver.Firefox(options=options, service=service)
55
56 driver.implicitly_wait(10)
57
58 log("Opening homepage")
59 driver.get("https://server:9090")
60
61 wait = WebDriverWait(driver, 60)
62
63
64 def wait_elem(by, query):
65 wait.until(EC.presence_of_element_located((by, query)))
66
67
68 def wait_title_contains(title):
69 wait.until(EC.title_contains(title))
70
71
72 def find_element(by, query):
73 return driver.find_element(by, query)
74
75
76 def set_value(elem, value):
77 script = 'arguments[0].value = arguments[1]'
78 return driver.execute_script(script, elem, value)
79
80
81 log("Waiting for the homepage to load")
82
83 # cockpit sets initial title as hostname
84 wait_title_contains("server")
85 wait_elem(By.CSS_SELECTOR, 'input#login-user-input')
86
87 log("Homepage loaded!")
88
89 log("Filling out username")
90 login_input = find_element(By.CSS_SELECTOR, 'input#login-user-input')
91 set_value(login_input, "${user}")
92
93 log("Filling out password")
94 password_input = find_element(By.CSS_SELECTOR, 'input#login-password-input')
95 set_value(password_input, "${password}")
96
97 log("Submitting credentials for login")
98 driver.find_element(By.CSS_SELECTOR, 'button#login-button').click()
99
100 # driver.implicitly_wait(1)
101 # driver.get("https://server:9090/system")
102
103 log("Waiting dashboard to load")
104 wait_title_contains("${user}@server")
105
106 log("Waiting for the frontend to initialize")
107 sleep(1)
108
109 log("Looking for that banner that tells about limited access")
110 container_iframe = find_element(By.CSS_SELECTOR, 'iframe.container-frame')
111 driver.switch_to.frame(container_iframe)
112
113 assert "Web console is running in limited access mode" in driver.page_source
114
115 driver.close()
116 '';
117 in with pkgs; [ firefox-unwrapped geckodriver seleniumScript ];
118 };
119 };
120
121 testScript = ''
122 start_all()
123
124 server.wait_for_open_port(9090)
125 server.wait_for_unit("network.target")
126 server.wait_for_unit("multi-user.target")
127 server.systemctl("start", "polkit")
128
129 client.wait_for_unit("multi-user.target")
130
131 client.succeed("curl -k https://server:9090 -o /dev/stderr")
132 print(client.succeed("whoami"))
133 client.succeed('PYTHONUNBUFFERED=1 selenium-script')
134 '';
135 }
136)