{"id":24278371,"url":"https://github.com/rapter1990/flightsearchapi","last_synced_at":"2025-03-05T11:44:12.572Z","repository":{"id":271021728,"uuid":"912166080","full_name":"Rapter1990/flightsearchapi","owner":"Rapter1990","description":"Case Study - Flight Search Api (Java 21, Spring Boot, Mongodb, JUnit, Spring Security, JWT, Docker, AOP, Kubernetes, Prometheus, Grafana, Github Actions (CI/CD), Jenkins)","archived":false,"fork":false,"pushed_at":"2025-02-02T18:51:52.000Z","size":272,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-02T19:34:17.904Z","etag":null,"topics":["aop","ci-cd","docker","docker-compose","github-actions","grafana","integration-test","jacoco","java","jenkins","junit","jwt","kubernetes","maven","mongodb","nosql","openapi","prometheus","spring-boot","spring-security"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Rapter1990.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-01-04T19:38:59.000Z","updated_at":"2025-01-29T20:58:59.000Z","dependencies_parsed_at":"2025-01-19T16:27:54.392Z","dependency_job_id":"4463ac3e-5c2b-45fe-a77a-4c579da27a56","html_url":"https://github.com/Rapter1990/flightsearchapi","commit_stats":null,"previous_names":["rapter1990/flightsearchapi"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rapter1990%2Fflightsearchapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rapter1990%2Fflightsearchapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rapter1990%2Fflightsearchapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Rapter1990%2Fflightsearchapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Rapter1990","download_url":"https://codeload.github.com/Rapter1990/flightsearchapi/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242023222,"owners_count":20059296,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aop","ci-cd","docker","docker-compose","github-actions","grafana","integration-test","jacoco","java","jenkins","junit","jwt","kubernetes","maven","mongodb","nosql","openapi","prometheus","spring-boot","spring-security"],"created_at":"2025-01-16T00:43:13.270Z","updated_at":"2025-03-05T11:44:12.554Z","avatar_url":"https://github.com/Rapter1990.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Case Study - Flight Search Api \n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"screenshots/main_screenshot.png\" alt=\"Main Information\" width=\"800\" height=\"700\"\u003e\n\u003c/p\u003e\n\n### 📖 Information\n\n\u003cul style=\"list-style-type:disc\"\u003e\n  \u003cli\u003e\n    This project provides a Spring Boot API for managing user authentication,\n    airport management, flight management, and flight search functionalities. It\n    includes advanced logging and security features.\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003cb\u003eUser Authentication:\u003c/b\u003e\n    \u003cul\u003e\n      \u003cli\u003e\n        \u003cb\u003eUser Registration:\u003c/b\u003e Register users with an email and password.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eUser Login:\u003c/b\u003e Authenticate users with email and password, generating\n        access and refresh tokens.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eToken Refresh:\u003c/b\u003e Refresh expired access tokens using refresh tokens.\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eUser Logout:\u003c/b\u003e Invalidate tokens to log users out.\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003cb\u003eAirport Management:\u003c/b\u003e\n    \u003cul\u003e\n      \u003cli\u003e\n        \u003cb\u003eCreate Airports:\u003c/b\u003e Accessible only to \u003ci\u003eADMIN\u003c/i\u003e users.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eRetrieve Airports:\u003c/b\u003e Paginated airport list retrieval, accessible to both\n        \u003ci\u003eADMIN\u003c/i\u003e and \u003ci\u003eUSER\u003c/i\u003e roles.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eRetrieve Specific Airport:\u003c/b\u003e Search by airport ID, accessible to both\n        \u003ci\u003eADMIN\u003c/i\u003e and \u003ci\u003eUSER\u003c/i\u003e roles.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eUpdate Airports:\u003c/b\u003e Modify an existing airport by ID, accessible only to\n        \u003ci\u003eADMIN\u003c/i\u003e users.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eDelete Airports:\u003c/b\u003e Remove airports by ID, accessible only to \u003ci\u003eADMIN\u003c/i\u003e\n        users.\n      \u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003cb\u003eFlight Management:\u003c/b\u003e\n    \u003cul\u003e\n      \u003cli\u003e\n        \u003cb\u003eCreate Flights:\u003c/b\u003e Accessible only to \u003ci\u003eADMIN\u003c/i\u003e users.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eRetrieve Flights:\u003c/b\u003e Paginated flight list retrieval, accessible to both\n        \u003ci\u003eADMIN\u003c/i\u003e and \u003ci\u003eUSER\u003c/i\u003e roles.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eRetrieve Specific Flight:\u003c/b\u003e Search by flight ID, accessible to both\n        \u003ci\u003eADMIN\u003c/i\u003e and \u003ci\u003eUSER\u003c/i\u003e roles.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eUpdate Flights:\u003c/b\u003e Modify an existing flight by ID, accessible only to\n        \u003ci\u003eADMIN\u003c/i\u003e users.\n      \u003c/li\u003e\n      \u003cli\u003e\n        \u003cb\u003eDelete Flights:\u003c/b\u003e Remove flights by ID, accessible only to \u003ci\u003eADMIN\u003c/i\u003e\n        users.\n      \u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003cb\u003eFlight Search:\u003c/b\u003e\n    \u003cul\u003e\n      \u003cli\u003e\n        \u003cb\u003eSearch Flights:\u003c/b\u003e Search for flights based on departure, arrival airports,\n        and departure date. Accessible to both \u003ci\u003eADMIN\u003c/i\u003e and \u003ci\u003eUSER\u003c/i\u003e\n        roles. (One Way - Round-Trip)\n      \u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003cb\u003eSecurity:\u003c/b\u003e\n    \u003cul\u003e\n      \u003cli\u003e\n        \u003cb\u003eUser Roles:\u003c/b\u003e ADMIN and USER roles implemented using Spring Security.\n      \u003c/li\u003e\n      \u003cli\u003e\u003cb\u003eJWT Authentication:\u003c/b\u003e Secure endpoints with JSON Web Tokens.\u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n  \u003cli\u003e\n    \u003cb\u003eLogging:\u003c/b\u003e\n    \u003cul\u003e\n      \u003cli\u003e\n        \u003cb\u003eCustom Logging Aspect:\u003c/b\u003e Logs details of REST controller method calls and\n        exceptions, including HTTP request and response details.\n      \u003c/li\u003e\n    \u003c/ul\u003e\n  \u003c/li\u003e\n\u003c/ul\u003e\n\n\n### Explore Rest APIs\n\nEndpoints Summary\n\u003ctable style=\"width:100%;\"\u003e\n    \u003ctr\u003e\n        \u003cth\u003eMethod\u003c/th\u003e\n        \u003cth\u003eUrl\u003c/th\u003e\n        \u003cth\u003eDescription\u003c/th\u003e\n        \u003cth\u003eRequest Body\u003c/th\u003e\n        \u003cth\u003ePath Variable\u003c/th\u003e\n        \u003cth\u003eResponse\u003c/th\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePOST\u003c/td\u003e\n        \u003ctd\u003e/api/v1/authentication/user/register\u003c/td\u003e\n        \u003ctd\u003eRegister for Admin or User\u003c/td\u003e\n        \u003ctd\u003eRegisterRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;Void\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePOST\u003c/td\u003e\n        \u003ctd\u003e/api/v1/authentication/user/login\u003c/td\u003e\n        \u003ctd\u003eLogin for Admin or User\u003c/td\u003e\n        \u003ctd\u003eLoginRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;TokenResponse\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePOST\u003c/td\u003e\n        \u003ctd\u003e/api/v1/authentication/user/refresh-token\u003c/td\u003e\n        \u003ctd\u003eRefresh Token for Admin or User\u003c/td\u003e\n        \u003ctd\u003eTokenRefreshRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;TokenResponse\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePOST\u003c/td\u003e\n        \u003ctd\u003e/api/v1/authentication/user/logout\u003c/td\u003e\n        \u003ctd\u003eLogout for Admin or User\u003c/td\u003e\n        \u003ctd\u003eTokenInvalidateRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;Void\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePOST\u003c/td\u003e\n        \u003ctd\u003e/api/v1/airports\u003c/td\u003e\n        \u003ctd\u003eCreate a new Airport\u003c/td\u003e\n        \u003ctd\u003eCreateAirportRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;String\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eGET\u003c/td\u003e\n        \u003ctd\u003e/api/v1/airports\u003c/td\u003e\n        \u003ctd\u003eGet all Airports\u003c/td\u003e\n        \u003ctd\u003eAirportPagingRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;CustomPagingResponse\u0026lt;AirportResponse\u0026gt;\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eGET\u003c/td\u003e\n        \u003ctd\u003e/api/v1/airports/{id}\u003c/td\u003e\n        \u003ctd\u003eGet Airport by ID\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eUUID\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;AirportResponse\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePUT\u003c/td\u003e\n        \u003ctd\u003e/api/v1/airports/{id}\u003c/td\u003e\n        \u003ctd\u003eUpdate an Airport\u003c/td\u003e\n        \u003ctd\u003eUpdateAirportRequest\u003c/td\u003e\n        \u003ctd\u003eUUID\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;AirportResponse\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eDELETE\u003c/td\u003e\n        \u003ctd\u003e/api/v1/airports/{id}\u003c/td\u003e\n        \u003ctd\u003eDelete an Airport\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eUUID\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;String\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePOST\u003c/td\u003e\n        \u003ctd\u003e/api/v1/flights\u003c/td\u003e\n        \u003ctd\u003eCreate a new Flight\u003c/td\u003e\n        \u003ctd\u003eCreateFlightRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;String\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eGET\u003c/td\u003e\n        \u003ctd\u003e/api/v1/flights\u003c/td\u003e\n        \u003ctd\u003eGet all Flights\u003c/td\u003e\n        \u003ctd\u003eAirportPagingRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;CustomPagingResponse\u0026lt;FlightResponse\u0026gt;\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eGET\u003c/td\u003e\n        \u003ctd\u003e/api/v1/flights/{id}\u003c/td\u003e\n        \u003ctd\u003eGet Flight by ID\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eUUID\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;FlightResponse\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePUT\u003c/td\u003e\n        \u003ctd\u003e/api/v1/flights/{id}\u003c/td\u003e\n        \u003ctd\u003eUpdate a Flight\u003c/td\u003e\n        \u003ctd\u003eUpdateFlightRequest\u003c/td\u003e\n        \u003ctd\u003eUUID\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;FlightResponse\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003eDELETE\u003c/td\u003e\n        \u003ctd\u003e/api/v1/flights/{id}\u003c/td\u003e\n        \u003ctd\u003eDelete a Flight\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eUUID\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;String\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd\u003ePOST\u003c/td\u003e\n        \u003ctd\u003e/api/v1/flights/search\u003c/td\u003e\n        \u003ctd\u003eSearch for Flights\u003c/td\u003e\n        \u003ctd\u003eSearchFlightRequest\u003c/td\u003e\n        \u003ctd\u003e\u003c/td\u003e\n        \u003ctd\u003eCustomResponse\u0026lt;CustomPagingResponse\u0026lt;FlightResponse\u0026gt;\u0026gt;\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\n\n### Technologies\n\n---\n- Java 21\n- Spring Boot 3.0\n- Restful API\n- Mapstruct\n- Open Api (Swagger)\n- Maven\n- Junit5\n- Mockito\n- Integration Tests\n- Docker\n- Docker Compose\n- CI/CD (Github Actions - Jenkins)\n- Postman\n- TestContainer\n- Mongo\n- Prometheus\n- Grafana\n- Kubernetes\n- JaCoCo (Test Report)\n\n### Postman\n\n```\nImport postman collection under postman_collection folder\n```\n\n\n### Prerequisites\n\n#### Define Variable in .env file\n\n```\nMONGO_DB_NAME=flightdatabase\nMONGO_DB_HOST=localhost\nMONGO_DB_PORT=27017\n```\n\n### Open Api (Swagger)\n\n```\nhttp://localhost:1133/swagger-ui/index.html\n```\n\n---\n\n### JaCoCo (Test Report)\n\nAfter the command named `mvn clean install` completes, the JaCoCo report will be available at:\n```\ntarget/site/jacoco/index.html\n```\nNavigate to the `target/site/jacoco/` directory.\n\nOpen the `index.html` file in your browser to view the detailed coverage report.\n\n---\n\n### Maven, Docker and Kubernetes Running Process\n\n\n### Maven Run\nTo build and run the application with `Maven`, please follow the directions shown below;\n\n```sh\n$ cd flightsearchapi\n$ mvn clean install\n$ mvn spring-boot:run\n```\n\n---\n\n### Docker Run\nThe application can be built and run by the `Docker` engine. The `Dockerfile` has multistage build, so you do not need to build and run separately.\n\nPlease follow directions shown below in order to build and run the application with Docker Compose file;\n\n```sh\n$ cd flightsearchapi\n$ docker-compose up -d\n```\n\nIf you change anything in the project and run it on Docker, you can also use this command shown below\n\n```sh\n$ cd flightsearchapi\n$ docker-compose up --build\n```\n\nTo monitor the application, you can use the following tools:\n\n- **Prometheus**:  \n  Open in your browser at [http://localhost:9090](http://localhost:9090)  \n  Prometheus collects and stores application metrics.\n\n- **Grafana**:  \n  Open in your browser at [http://localhost:3000](http://localhost:3000)  \n  Grafana provides a dashboard for visualizing the metrics.  \n  **Default credentials**:\n    - Username: `admin`\n    - Password: `admin`\n\n- Define prometheus data source url, use this link shown below\n\n```\nhttp://prometheus:9090\n```\n\n---\n\n\n### Kubernetes Run\nTo build and run the application with `Maven`, please follow the directions shown below;\n\n- Start Minikube\n\n```sh\n$ minikube start\n```\n\n- Open Minikube Dashboard\n\n```sh\n$ minikube dashboard\n```\n\n- To deploy the application on Kubernetes, apply the Kubernetes configuration file underneath k8s folder\n\n```sh\n$ kubectl apply -f k8s\n```\n\n- To open Prometheus, click tunnel url link provided by the command shown below to reach out Prometheus\n\n```sh\nminikube service prometheus-service\n```\n\n\n- To open Grafana, click tunnel url link provided by the command shown below to reach out Prometheus\n\n```sh\nminikube service grafana-service\n```\n\n- Define prometheus data source url, use this link shown below\n\n```\nhttp://prometheus-service.default.svc.cluster.local:9090\n```\n\n\n---\n### Docker Image Location\n\n```\nhttps://hub.docker.com/repository/docker/noyandocker/flightsearchapi/general\nhttps://hub.docker.com/repository/docker/noyandocker/flightsearchapi-jenkins/general\n```\n\n### Jenkins\n\n- Go to `jenkins` folder\n- Run `docker-compose up -d`\n- Open Jenkins in the browser via `localhost:8080`\n- Go to pipeline named `flightsearchapi`\n- Run Pipeline\n- Show `Pipeline Step` to verify if it succeeded or failed\n\n\n### Screenshots\n\n\u003cdetails\u003e\n\u003csummary\u003eClick here to show the screenshots of project\u003c/summary\u003e\n    \u003cp\u003e Figure 1 \u003c/p\u003e\n    \u003cimg src =\"screenshots/postman_1.PNG\"\u003e\n    \u003cp\u003e Figure 2 \u003c/p\u003e\n    \u003cimg src =\"screenshots/postman_2.PNG\"\u003e\n    \u003cp\u003e Figure 3 \u003c/p\u003e\n    \u003cimg src =\"screenshots/jacoco_report.PNG\"\u003e\n    \u003cp\u003e Figure 4 \u003c/p\u003e\n    \u003cimg src =\"screenshots/docker_result.PNG\"\u003e\n    \u003cp\u003e Figure 5 \u003c/p\u003e\n    \u003cimg src =\"screenshots/docker_prometheus.PNG\"\u003e\n    \u003cp\u003e Figure 6 \u003c/p\u003e\n    \u003cimg src =\"screenshots/docker_grafana_1.PNG\"\u003e\n    \u003cp\u003e Figure 7 \u003c/p\u003e\n    \u003cimg src =\"screenshots/docker_grafana_2.PNG\"\u003e\n    \u003cp\u003e Figure 8 \u003c/p\u003e\n    \u003cimg src =\"screenshots/docker_grafana_3.PNG\"\u003e\n    \u003cp\u003e Figure 9 \u003c/p\u003e\n    \u003cimg src =\"screenshots/docker_grafana_4.PNG\"\u003e\n    \u003cp\u003e Figure 10 \u003c/p\u003e\n    \u003cimg src =\"screenshots/docker_grafana_5.PNG\"\u003e\n    \u003cp\u003e Figure 11 \u003c/p\u003e\n    \u003cimg src =\"screenshots/docker_grafana_6.PNG\"\u003e\n    \u003cp\u003e Figure 12 \u003c/p\u003e\n    \u003cimg src =\"screenshots/minikube_1.PNG\"\u003e\n    \u003cp\u003e Figure 13 \u003c/p\u003e\n    \u003cimg src =\"screenshots/minikube_2.PNG\"\u003e\n    \u003cp\u003e Figure 14 \u003c/p\u003e\n    \u003cimg src =\"screenshots/minikube_3.PNG\"\u003e\n    \u003cp\u003e Figure 15 \u003c/p\u003e\n    \u003cimg src =\"screenshots/minikube_prometheus.PNG\"\u003e\n    \u003cp\u003e Figure 16 \u003c/p\u003e\n    \u003cimg src =\"screenshots/minikube_grafana_1.PNG\"\u003e\n    \u003cp\u003e Figure 17 \u003c/p\u003e\n    \u003cimg src =\"screenshots/minikube_grafana_2.PNG\"\u003e\n    \u003cp\u003e Figure 18 \u003c/p\u003e\n    \u003cimg src =\"screenshots/minikube_grafana_3.PNG\"\u003e\n    \u003cp\u003e Figure 19 \u003c/p\u003e\n    \u003cimg src =\"screenshots/minikube_grafana_4.PNG\"\u003e\n    \u003cp\u003e Figure 20 \u003c/p\u003e\n    \u003cimg src =\"screenshots/jenkins_credential_docker_1.PNG\"\u003e\n    \u003cp\u003e Figure 21 \u003c/p\u003e\n    \u003cimg src =\"screenshots/jenkins_credential_docker_2.PNG\"\u003e\n    \u003cp\u003e Figure 22 \u003c/p\u003e\n    \u003cimg src =\"screenshots/jenkins_credential_docker_3.PNG\"\u003e\n    \u003cp\u003e Figure 23 \u003c/p\u003e\n    \u003cimg src =\"screenshots/jenkins_pipeline_1.PNG\"\u003e\n    \u003cp\u003e Figure 24 \u003c/p\u003e\n    \u003cimg src =\"screenshots/jenkins_pipeline_2.PNG\"\u003e\n\u003c/details\u003e\n\n\n### Contributors\n\n- [Sercan Noyan Germiyanoğlu](https://github.com/Rapter1990)\n- [Furkan Tarık Göçmen](https://github.com/furkantarikgocmen)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frapter1990%2Fflightsearchapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frapter1990%2Fflightsearchapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frapter1990%2Fflightsearchapi/lists"}