Coverage for tests / test_ordering.py: 100%

16 statements  

« prev     ^ index     » next       coverage.py v7.13.2, created at 2026-01-29 02:37 +0000

1import pytest 

2from unittest.mock import MagicMock 

3from stepclient_traefik.config import settings 

4from stepclient_traefik.discovery import DockerDiscovery 

5 

6CASES = [ 

7 { 

8 "id": "host-explicit", 

9 "labels": { 

10 "traefik.enable": "true", 

11 "traefik.http.routers.example.rule": "Host(`main.example.com`,`sub1.example.com`,`sub2.example.com`,`sub3.example.com`)", 

12 "traefik.http.routers.example.entrypoints": "websecure", 

13 "traefik.http.routers.example.tls": "true" 

14 }, 

15 "expected": { 

16 "rule_domains": ["main.example.com", "sub1.example.com", "sub2.example.com", "sub3.example.com"], 

17 "tls_domains": [] 

18 } 

19 }, 

20 { 

21 "id": "hostsni-explicit", 

22 "labels": { 

23 "traefik.enable": "true", 

24 "traefik.http.routers.example.rule": "HostSNI(`main.example.com`,`sub1.example.com`,`sub2.example.com`,`sub3.example.com`)", 

25 "traefik.http.routers.example.entrypoints": "websecure", 

26 "traefik.http.routers.example.tls": "true" 

27 }, 

28 "expected": { 

29 "rule_domains": ["main.example.com", "sub1.example.com", "sub2.example.com", "sub3.example.com"], 

30 "tls_domains": [] 

31 } 

32 }, 

33 { 

34 "id": "hostregexp-pipe-group", 

35 "labels": { 

36 "traefik.enable": "true", 

37 "traefik.http.routers.example.rule": "HostRegexp(`{sub:(main|sub1|sub2|sub3)}.example.com`)", 

38 "traefik.http.routers.example.entrypoints": "websecure", 

39 "traefik.http.routers.example.tls": "true" 

40 }, 

41 "expected": { 

42 "rule_domains": ["main.example.com", "sub1.example.com", "sub2.example.com", "sub3.example.com"], 

43 "tls_domains": [] 

44 } 

45 }, 

46 { 

47 "id": "tls-domains-main-and-sans", 

48 "labels": { 

49 "traefik.enable": "true", 

50 "traefik.http.routers.example.rule": "Host(`main.example.com`)", 

51 "traefik.http.routers.example.entrypoints": "websecure", 

52 "traefik.http.routers.example.tls": "true", 

53 "traefik.http.routers.example.tls.domains[0].main": "main.example.com", 

54 "traefik.http.routers.example.tls.domains[0].sans": "sub1.example.com,sub2.example.com,sub3.example.com" 

55 }, 

56 "expected": { 

57 "rule_domains": ["main.example.com"], 

58 "tls_domains": ["main.example.com", "sub1.example.com", "sub2.example.com", "sub3.example.com"] 

59 } 

60 }, 

61 { 

62 "id": "tls-domains-multiple-certs", 

63 "labels": { 

64 "traefik.enable": "true", 

65 "traefik.http.routers.example.rule": "Host(`main.example.com`,`sub1.example.com`,`sub2.example.com`,`sub3.example.com`)", 

66 "traefik.http.routers.example.entrypoints": "websecure", 

67 "traefik.http.routers.example.tls": "true", 

68 "traefik.http.routers.example.tls.domains[0].main": "main.example.com", 

69 "traefik.http.routers.example.tls.domains[1].main": "sub1.example.com", 

70 "traefik.http.routers.example.tls.domains[2].main": "sub2.example.com", 

71 "traefik.http.routers.example.tls.domains[3].main": "sub3.example.com" 

72 }, 

73 "expected": { 

74 "rule_domains": ["main.example.com", "sub1.example.com", "sub2.example.com", "sub3.example.com"], 

75 "tls_domains": ["main.example.com", "sub1.example.com", "sub2.example.com", "sub3.example.com"] 

76 } 

77 }, 

78 { 

79 "id": "hostregexp-plus-tls-domains", 

80 "labels": { 

81 "traefik.enable": "true", 

82 "traefik.http.routers.example.rule": "HostRegexp(`{sub:(main|sub1|sub2|sub3)}.example.com`)", 

83 "traefik.http.routers.example.entrypoints": "websecure", 

84 "traefik.http.routers.example.tls": "true", 

85 "traefik.http.routers.example.tls.domains[0].main": "main.example.com", 

86 "traefik.http.routers.example.tls.domains[0].sans": "sub1.example.com,sub2.example.com,sub3.example.com" 

87 }, 

88 "expected": { 

89 "rule_domains": ["main.example.com", "sub1.example.com", "sub2.example.com", "sub3.example.com"], 

90 "tls_domains": ["main.example.com", "sub1.example.com", "sub2.example.com", "sub3.example.com"] 

91 } 

92 }, 

93 { 

94 "id": "host-or-chaining", 

95 "labels": { 

96 "traefik.enable": "true", 

97 "traefik.http.routers.example.rule": "Host(`main.example.com`) || Host(`sub1.example.com`) || Host(`sub2.example.com`)", 

98 "traefik.http.routers.example.entrypoints": "websecure", 

99 "traefik.http.routers.example.tls": "true" 

100 }, 

101 "expected": { 

102 "rule_domains": ["main.example.com", "sub1.example.com", "sub2.example.com"], 

103 "tls_domains": [] 

104 } 

105 } 

106] 

107 

108 

109@pytest.mark.parametrize("case", CASES, ids=lambda c: c["id"]) 

110def test_discovery_ordering(case): 

111 d = DockerDiscovery() 

112 # Mock return from get_services so we don't need real docker socket 

113 d.get_services = MagicMock(return_value=[ 

114 {"Spec": {"Labels": case["labels"]}} 

115 ]) 

116 

117 routers, warnings = d.extract_routers() 

118 assert "example" in routers, f"Router 'example' not found in case {case['id']}" 

119 

120 meta = routers["example"] 

121 

122 # 1. Check Rule Extraction Ordering 

123 rule_domains, _ = d.extract_from_rules(meta.get("rule", "")) 

124 

125 # Convert to list to check order if it isn't already (current implementation returns set) 

126 # But we want to fail if it's unordered. 

127 # We assertion verifies strict equality with list. 

128 assert list(rule_domains) == case["expected"]["rule_domains"], f"Rule domains order mismatch for {case['id']}" 

129 

130 # 2. Check TLS Domains Extraction Ordering 

131 # Note: Flatten logic for tls_domains matches how we expect them to be accumulated 

132 # The 'expected' in test case implies the aggregate of all tls.domains definitions 

133 extracted_tls = meta.get("tls_domains") or [] 

134 assert list(extracted_tls) == case["expected"]["tls_domains"], f"TLS domains order mismatch for {case['id']}"