77from socketserver import ThreadingMixIn
88
99ENDPOINT_TYPE_MAP = {
10- 'api.ipify.org' : "IPv4" ,
11- 'api6.ipify.org' : "IPv6" ,
12- 'api64.ipify.org' : "Dual stack"
13- }
10+ 'api.ipify.org' : {
11+ 'validation_name' : "IPv4" ,
12+ 'path' : "/ipv4-test"
13+ },
14+ 'api6.ipify.org' : {
15+ 'validation_name' : "IPv6" ,
16+ 'path' : "/ipv6-test"
17+ },
18+ 'api64.ipify.org' : {
19+ 'validation_name' : "Dual stack" ,
20+ 'path' : "/dual-stack-test"
21+ }
22+ }
1423
1524DEFAULT_PORT = '8080'
1625HOST = '127.0.0.1'
1726
18- OVERALL_SUCCESS_MESSAGE = "IPv6 egress test suite passed. All tests completed successfully."
19- OVERALL_FAIL_MESSAGE = "IPv6 Egress Suite failed — investigate failed components."
20-
21- # Set up logging
2227logging .basicConfig (
2328 level = logging .INFO ,
2429 format = '%(asctime)s | %(levelname)s | %(message)s'
2732class IPv6Tester :
2833 """
2934 The `IPv6Tester` class is responsible for verifying the successful execution of
30- egress calls using IPv4, IPv6, and Dual Stack configurations, sequentially.
31- It offers logging at each step to track the progress of the calls.
32- The test execution is deemed successful if all endpoints are reached without errors.
33- Conversely, if any egress call fails, the test execution is marked as failed,
34- and the application exits with an exit code of 1 to signal the failure.
35+ egress calls using IPv4, IPv6, and Dual Stack configurations, depending on the input.
36+ It offers logging result from the call.
37+ The test execution is deemed successful if the requested endpoint is reached without errors.
38+
3539 """
3640
3741 def __init__ (self , endpoints ):
3842 self .endpoints = endpoints
39-
40- def test_all_addresses (self ):
41- results = []
42- all_successful = True
43- for endpoint in self .endpoints :
44- result = self .test_endpoint (endpoint )
45- results .append ((endpoint , result ))
46- self .print_result (endpoint , result )
47- if not result ['success' ]:
48- all_successful = False
49-
50- if all_successful :
51- logging .info (OVERALL_SUCCESS_MESSAGE )
52- else :
53- logging .error (OVERALL_FAIL_MESSAGE )
54-
55- return all_successful , results
56-
43+
44+ def test_single_address (self , endpoint ):
45+ result = self .test_endpoint (endpoint )
46+ self .print_result (endpoint , result )
47+ return result
48+
5749 def print_result (self , endpoint , result ):
58- validation_type = ENDPOINT_TYPE_MAP . get ( endpoint , "Unknown" )
50+ validation_type = ENDPOINT_TYPE_MAP [ endpoint ][ 'validation_name' ]
5951 if result ['success' ]:
6052 logging .info (f"{ validation_type } validation succeeded." )
6153 else :
6254 logging .error (f"{ validation_type } validation failed." )
63-
55+
6456 def test_endpoint (self , endpoint ):
65-
6657 try :
6758 logging .info (f"Testing endpoint: { endpoint } " )
6859 connection = http .client .HTTPConnection (endpoint , timeout = 0.20 )
@@ -83,9 +74,9 @@ def test_endpoint(self, endpoint):
8374 return {
8475 'success' : False ,
8576 'error' : str (e ),
86- 'ip_type' : 'Unknown'
77+ 'ip_type' : 'Unknown'
8778 }
88-
79+
8980 @staticmethod
9081 def determine_ip_type (ip_string ):
9182 try :
@@ -101,46 +92,46 @@ class Handler(BaseHTTPRequestHandler):
10192 to testing IPv6 egress calls, while the default path is used
10293 for testing the default Hello-Python buildpack test case.
10394 '''
95+
10496 def do_GET (self ):
105- path = self .path
106- if path == "/ipv6-test" :
107- self .handle_ipv6_test ()
97+ if self .path in [data ['path' ] for data in ENDPOINT_TYPE_MAP .values ()]:
98+ self .handle_test ()
10899 else :
109100 self .send_response (200 )
110101 self .end_headers ()
111- message = "Hello python, world!"
102+ message = "Hello python, world!"
112103 self .wfile .write (message .encode ('utf-8' ))
113104 self .wfile .write ('\n ' .encode ('utf-8' ))
114-
115- def handle_ipv6_test (self ):
116- tester = IPv6Tester (list (ENDPOINT_TYPE_MAP .keys ()))
117- all_successful , results = tester .test_all_addresses ()
118-
119- # Determine response status and message
120- response_code = 200 if all_successful else 500
121- overall_message = OVERALL_SUCCESS_MESSAGE if all_successful else OVERALL_FAIL_MESSAGE
122-
123- # Send HTTP response status
124- self .send_response (response_code )
125- self .end_headers ()
126-
127- response_messages = []
128- for endpoint , result in results :
129- endpoint_results = f"{ ENDPOINT_TYPE_MAP .get (endpoint , 'Unknown' )} validation resulted in { 'success' if result ['success' ] else 'failure' } . Detected IP type is { result .get ('ip_type' , 'unknown' )} . Error message: { result .get ('error' , 'none' )} ."
130- response_messages .append (endpoint_results )
131-
132- response_content = "\n " .join (response_messages + [overall_message ])
133-
134- # Write the detailed results and overall message to the web console
135- self .wfile .write (response_content .encode ('utf-8' ))
136- self .wfile .write ('\n ' .encode ('utf-8' ))
137-
138105
106+ def handle_test (self ):
107+ endpoint = self .get_endpoint_from_path ()
108+ if endpoint :
109+ tester = IPv6Tester ([endpoint ])
110+ result = tester .test_single_address (endpoint )
111+ response_code = 200 if result ['success' ] else 500
112+ self .send_response (response_code )
113+ self .end_headers ()
114+
115+ validation_name = ENDPOINT_TYPE_MAP [endpoint ]['validation_name' ]
116+ response_message = (f"{ validation_name } validation resulted in "
117+ f"{ 'success' if result ['success' ] else 'failure' } . Detected IP type is "
118+ f"{ result .get ('ip_type' , 'unknown' )} . Error message: { result .get ('error' , 'none' )} ." )
119+ self .wfile .write (response_message .encode ('utf-8' ))
120+ self .wfile .write ('\n ' .encode ('utf-8' ))
121+ else :
122+ self .send_response (404 )
123+ self .end_headers ()
124+ self .wfile .write (b'Endpoint not found\n ' )
125+
126+ def get_endpoint_from_path (self ):
127+ for endpoint , data in ENDPOINT_TYPE_MAP .items ():
128+ if self .path == data ['path' ]:
129+ return endpoint
130+ return None
139131
140132class ThreadedHTTPServer (ThreadingMixIn , HTTPServer ):
141133 """Handle requests in a separate thread."""
142134
143-
144135if __name__ == '__main__' :
145136 port = int (os .environ .get ('PORT' , DEFAULT_PORT ))
146137 host = os .environ .get ('VCAP_APP_HOST' , HOST )
@@ -149,4 +140,4 @@ class ThreadedHTTPServer(ThreadingMixIn, HTTPServer):
149140 server = ThreadedHTTPServer ((host , port ), Handler )
150141 print ('Starting server, use <Ctrl-C> to stop' )
151142
152- server .serve_forever ()
143+ server .serve_forever ()
0 commit comments