{
    "elems": [
        {
            "id": 0,
            "name": "PodAvailability",
            "description": "The pod 'example-pod' must be running and available to serve traffic for the service to function correctly.",
            "command": {
                "tool": "k8s",
                "cmd": "kubectl get pod example-pod -n chaos-eater -o jsonpath='{.status.phase}'"
            },
            "inspection_result": "Running",
            "threshold": {
                "threshold": "Running",
                "reason": "The current state of the pod 'example-pod' is 'Running', which indicates that the pod is operational and able to serve traffic. Setting the threshold to 'Running' ensures that the pod is available and functioning correctly, which is necessary for the service to operate as expected. This threshold is satisfied in the current state, ensuring that the system is in a steady state."
            },
            "unittest": {
                "file_path": "unittest_podavailability.py",
                "code": "import unittest\nimport os\nfrom kubernetes import client, config\n\nclass TestPodAvailability(unittest.TestCase):\n    def setUp(self):\n        # Load Kubernetes configuration based on the environment\n        if os.getenv('KUBERNETES_SERVICE_HOST'):\n            config.load_incluster_config()\n        else:\n            config.load_kube_config()\n        \n        # Create a Kubernetes API client\n        self.v1 = client.CoreV1Api()\n\n    def test_pod_running(self):\n        # Define the namespace and pod name\n        namespace = 'chaos-eater'\n        pod_name = 'example-pod'\n\n        # Get the pod details\n        pod = self.v1.read_namespaced_pod(name=pod_name, namespace=namespace)\n\n        # Check if the pod is in the 'Running' state\n        self.assertEqual(pod.status.phase, 'Running', f\"Pod {pod_name} is not in 'Running' state\")\n\nif __name__ == '__main__':\n    unittest.main()"
            }
        },
        {
            "id": 1,
            "name": "ServiceEndpointResolution",
            "description": "The 'example-service' must correctly resolve to the IP address of the 'example-pod' to route traffic properly.",
            "command": {
                "tool": "k8s",
                "cmd": "kubectl get endpoints example-service -n chaos-eater -o jsonpath='{.subsets[*].addresses[*].ip}'"
            },
            "inspection_result": "10.244.0.114",
            "threshold": {
                "threshold": "The 'example-service' must resolve to the IP address '10.244.0.114'.",
                "reason": "The current state shows that the 'example-service' resolves to the IP address '10.244.0.114', which indicates that the service is correctly routing traffic to the 'example-pod'. Setting the threshold to this IP address ensures that the service continues to function as expected, maintaining the correct routing to the pod."
            },
            "unittest": {
                "file_path": "unittest_serviceendpointresolution.py",
                "code": "import unittest\nimport os\nfrom kubernetes import client, config\n\nclass TestServiceEndpointResolution(unittest.TestCase):\n    def setUp(self):\n        # Load Kubernetes configuration based on the environment\n        if os.getenv('KUBERNETES_SERVICE_HOST'):\n            config.load_incluster_config()\n        else:\n            config.load_kube_config()\n        \n        # Initialize the Kubernetes API client\n        self.v1 = client.CoreV1Api()\n\n    def test_service_endpoint_resolution(self):\n        # Define the expected IP address for the service endpoint\n        expected_ip = '10.244.0.114'\n        \n        # Retrieve the endpoints for the 'example-service' in the 'chaos-eater' namespace\n        endpoints = self.v1.read_namespaced_endpoints(name='example-service', namespace='chaos-eater')\n        \n        # Extract the IP addresses from the endpoints\n        actual_ips = [addr.ip for subset in endpoints.subsets for addr in subset.addresses]\n        \n        # Check if the expected IP address is in the list of actual IP addresses\n        self.assertIn(expected_ip, actual_ips, f\"The service endpoint does not resolve to the expected IP {expected_ip}.\")\n\nif __name__ == '__main__':\n    unittest.main()"
            }
        },
        {
            "id": 2,
            "name": "HTTPResponseSuccessRate",
            "description": "The Nginx server should return successful HTTP responses (e.g., 200 OK) to ensure the web server is functioning as expected.",
            "command": {
                "tool": "k6",
                "cmd": {
                    "file_path": "k6_httpresponsesuccessrate.js",
                    "code": "import http from 'k6/http';\nimport { check } from 'k6';\n\nexport default function () {\n  const res = http.get('http://example-service.chaos-eater.svc.cluster.local');\n  check(res, {\n    'status is 200': (r) => r.status === 200,\n  });\n}"
                }
            },
            "inspection_result": [
                "\n     \u2713 status is 200\n\n     checks.........................: 100.00% \u2713 1          \u2717 0\n     data_received..................: 850 B   276 kB/s\n     data_sent......................: 111 B   36 kB/s\n     http_req_blocked...............: avg=2.13ms   min=2.13ms   med=2.13ms   max=2.13ms   p(90)=2.13ms   p(95)=2.13ms  \n     http_req_connecting............: avg=132.2\u00b5s  min=132.2\u00b5s  med=132.2\u00b5s  max=132.2\u00b5s  p(90)=132.2\u00b5s  p(95)=132.2\u00b5s \n     http_req_duration..............: avg=338.6\u00b5s  min=338.6\u00b5s  med=338.6\u00b5s  max=338.6\u00b5s  p(90)=338.6\u00b5s  p(95)=338.6\u00b5s \n       { expected_response:true }...: avg=338.6\u00b5s  min=338.6\u00b5s  med=338.6\u00b5s  max=338.6\u00b5s  p(90)=338.6\u00b5s  p(95)=338.6\u00b5s \n     http_req_failed................: 0.00%   \u2713 0          \u2717 1\n     http_req_receiving.............: avg=109.36\u00b5s min=109.36\u00b5s med=109.36\u00b5s max=109.36\u00b5s p(90)=109.36\u00b5s p(95)=109.36\u00b5s\n     http_req_sending...............: avg=97.39\u00b5s  min=97.39\u00b5s  med=97.39\u00b5s  max=97.39\u00b5s  p(90)=97.39\u00b5s  p(95)=97.39\u00b5s \n     http_req_tls_handshaking.......: avg=0s       min=0s       med=0s       max=0s       p(90)=0s       p(95)=0s      \n     http_req_waiting...............: avg=131.84\u00b5s min=131.84\u00b5s med=131.84\u00b5s max=131.84\u00b5s p(90)=131.84\u00b5s p(95)=131.84\u00b5s\n     http_reqs......................: 1       325.153659/s\n     iteration_duration.............: avg=2.93ms   min=2.93ms   med=2.93ms   max=2.93ms   p(90)=2.93ms   p(95)=2.93ms  \n     iterations.....................: 1       325.153659/s\n\n",
                {
                    "file_path": "k6_httpresponsesuccessrate_result.json",
                    "code": "{\"root_group\": {\"groups\": {}, \"checks\": {\"status is 200\": {\"name\": \"status is 200\", \"path\": \"::status is 200\", \"id\": \"6210a8cd14cd70477eba5c5e4cb3fb5f\", \"passes\": 1, \"fails\": 0}}, \"name\": \"\", \"path\": \"\", \"id\": \"d41d8cd98f00b204e9800998ecf8427e\"}, \"metrics\": {\"http_reqs\": {\"count\": 1, \"rate\": 325.1536594906338}, \"http_req_waiting\": {\"p(95)\": 0.131848, \"avg\": 0.131848, \"min\": 0.131848, \"med\": 0.131848, \"max\": 0.131848, \"p(90)\": 0.131848}, \"iterations\": {\"count\": 1, \"rate\": 325.1536594906338}, \"data_received\": {\"count\": 850, \"rate\": 276380.6105670387}, \"checks\": {\"passes\": 1, \"fails\": 0, \"value\": 1}, \"iteration_duration\": {\"med\": 2.932321, \"max\": 2.932321, \"p(90)\": 2.932321, \"p(95)\": 2.932321, \"avg\": 2.932321, \"min\": 2.932321}, \"http_req_tls_handshaking\": {\"p(95)\": 0, \"avg\": 0, \"min\": 0, \"med\": 0, \"max\": 0, \"p(90)\": 0}, \"http_req_sending\": {\"avg\": 0.097393, \"min\": 0.097393, \"med\": 0.097393, \"max\": 0.097393, \"p(90)\": 0.097393, \"p(95)\": 0.097393}, \"data_sent\": {\"count\": 111, \"rate\": 36092.05620346035}, \"http_req_duration{expected_response:true}\": {\"p(95)\": 0.338606, \"avg\": 0.338606, \"min\": 0.338606, \"med\": 0.338606, \"max\": 0.338606, \"p(90)\": 0.338606}, \"http_req_connecting\": {\"avg\": 0.132208, \"min\": 0.132208, \"med\": 0.132208, \"max\": 0.132208, \"p(90)\": 0.132208, \"p(95)\": 0.132208}, \"http_req_failed\": {\"passes\": 0, \"fails\": 1, \"value\": 0}, \"http_req_blocked\": {\"avg\": 2.139644, \"min\": 2.139644, \"med\": 2.139644, \"max\": 2.139644, \"p(90)\": 2.139644, \"p(95)\": 2.139644}, \"http_req_receiving\": {\"avg\": 0.109365, \"min\": 0.109365, \"med\": 0.109365, \"max\": 0.109365, \"p(90)\": 0.109365, \"p(95)\": 0.109365}, \"http_req_duration\": {\"avg\": 0.338606, \"min\": 0.338606, \"med\": 0.338606, \"max\": 0.338606, \"p(90)\": 0.338606, \"p(95)\": 0.338606}}}"
                }
            ],
            "threshold": {
                "threshold": "HTTPResponseSuccessRate >= 99.9%",
                "reason": "The current state shows a 100% success rate for HTTP responses, indicating that the Nginx server is functioning correctly. Setting a threshold of 99.9% allows for a small margin of error while ensuring high reliability and performance of the web server."
            },
            "unittest": {
                "file_path": "unittest_httpresponsesuccessrate.py",
                "code": "import unittest\nimport json\nimport argparse\n\nclass TestHTTPResponseSuccessRate(unittest.TestCase):\n    def test_http_response_success_rate(self):\n        # Load the JSON file containing the inspection summary\n        with open(args.path, 'r') as file:\n            data = json.load(file)\n\n        # Extract the 'status is 200' metric from the loaded JSON\n        status_200_check = data['root_group']['checks']['status is 200']\n        passes = status_200_check['passes']\n        fails = status_200_check['fails']\n\n        # Calculate the success rate\n        total_requests = passes + fails\n        success_rate = (passes / total_requests) * 100\n\n        # Define the threshold\n        threshold = 99.9\n\n        # Assert that the success rate is greater than or equal to the threshold\n        self.assertGreaterEqual(success_rate, threshold, f\"HTTP response success rate is below threshold: {success_rate}%\")\n\nif __name__ == '__main__':\n    # Set up argument parser to dynamically input the JSON file path\n    parser = argparse.ArgumentParser(description='Test HTTP Response Success Rate')\n    parser.add_argument('--path', type=str, required=True, help='Path to the JSON file')\n    args = parser.parse_args()\n\n    # Run the unit test\n    unittest.main(argv=['first-arg-is-ignored'], exit=False)"
            }
        }
    ]
}