diff --git a/.gitignore b/.gitignore index 9a67eb9e8232931038aa89dd32d0ebc9fc685fff..c27c6be3e887423403f0be2a726fa4ef7edaa134 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ __pycache__/ *.crt *.zip *.srl +*.log services/nginx/certs/sign_req_body.json services/easy_rsa/certs/pki services/easy_rsa/certs/*EasyRSA* @@ -29,9 +30,10 @@ monitoring/tempo/tempo-data/* docs/testing_with_postman/*node_modules* +docs/testing_with_postman/Responses docs/testing_with_postman/package-lock.json results helm/capif/*.lock -helm/capif/charts \ No newline at end of file +helm/capif/charts/tempo* diff --git a/README.md b/README.md index 577a12d15416e9625e5a89ffa647c10596548e72..358015bd2513a0447ed036ce9d59f1247457f5e3 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,45 @@ # Common API Framework (CAPIF) - [Common API Framework (CAPIF)](#common-api-framework-capif) -- [Repository structure](#repository-structure) - [CAPIF\_API\_Services](#capif_api_services) +- [Documentation](#documentation) - [How to run CAPIF services in this Repository](#how-to-run-capif-services-in-this-repository) - [Run All CAPIF Services locally with Docker images](#run-all-capif-services-locally-with-docker-images) - [Run All CAPIF Services locally with Docker images and deploy monitoring stack](#run-all-capif-services-locally-with-docker-images-and-deploy-monitoring-stack) - [Run each service using Docker](#run-each-service-using-docker) - [Run each service using Python](#run-each-service-using-python) -- [How to test CAPIF APIs](#how-to-test-capif-apis) - - [Test Plan Documentation](#test-plan-documentation) - - [Robot Framework](#robot-framework) - - [Using Curl](#using-curl) - - [Using PostMan](#using-postman) - [Important urls:](#important-urls) - [Mongo CAPIF's DB Dashboard](#mongo-capifs-db-dashboard) - [Mongo Register's DB Dashboard](#mongo-registers-db-dashboard) - [FAQ Documentation](#faq-documentation) -- [CAPIF Release 0](#capif-release-0) -# Repository structure - -``` -CAPIF_API_Services -└───docs -│ └───test_plan -│ └───testing_with_postman -└───services -└───tests -└───tools - └───robot - └───open_api_script -``` -* **services**: Services developed following CAPIF API specifications. Also, other complementary services (e.g., NGINX and JWTauth services for the authentication of API consuming entities). -* **tools**: Auxiliary tools. Robot Framework related code and OpenAPI scripts. -* **test**: Tests developed using Robot Framework. - -* **docs**: Documents related to the code in the repository. - * images: images used in the repository - * test_plan: test plan descriptions for each API service referring to the test that are executed with the Robot Framework. - * testing_with_postman: auxiliary JSON file needed for the Postman-based examples. # CAPIF_API_Services This repository has the python-flask Mockup servers created with openapi-generator related with CAPIF APIS defined here: [Open API Descriptions of 3GPP 5G APIs] +# Documentation + +Please refer to [OCF Documentation] for more detailed information. + + +# Install and Run +### (to be added in Getting Started section of Documentation) +``` +mkdir OpenCAPIF + +cd OpenCAPIF + +# The link must be changed when finally merged with the default branch and be permanent +wget https://labs.etsi.org/rep/ocf/capif/-/raw/OCF19-local-installation-of-capif-downloading-script/deploy.sh + +chmod +x deploy.sh + +# ./deploy.sh [branch to fetch] [true or false (default) to install monitoring stack or not] +./deploy.sh staging +``` + ## How to run CAPIF services in this Repository Capif services are developed under /service/ folder. @@ -147,29 +141,6 @@ pip3 install -r requirements.txt python3 -m ``` -# How to test CAPIF APIs -The above APIs can be tested either with "curl" command, POSTMAN tool or running developed tests with Robot Framework. -## Test Plan Documentation - -Complete documentation of tests is here: [Test Plan Directory] -## Robot Framework - -In order to ensure modifications over CAPIF services still accomplish the required functionality, Robot Framework test suite must be success. - -Test suite implemented accomplish requirements described under test plan at [Test Plan Directory] folder. - -Please go to [Testing with Robot Framework] Section - -## Using Curl - -Please go to [Testing Using Curl] section. - -## Using PostMan -You can test the CAPIF flow using the Postman tool. To do this, we have created a collection with some examples of CAPIF requests with everything necessary to carry them out. - -For more information on how to test the APIs with POSTMAN, follow this [Document](docs/testing_with_postman/README.md). -Also you have here the [POSTMAN Collection](docs/testing_with_postman/CAPIF.postman_collection.json) - # Important urls: ## Mongo CAPIF's DB Dashboard @@ -194,24 +165,11 @@ http://:8083/ (if accessed from another host) Frequently asked questions can be found here: [FAQ Directory] -# CAPIF Release 0 - -The APIs included in release 0 are: -- JWT Authentication APIs -- CAPIF Invoker Management API -- CAPIF Publish API -- CAPIF Discover API -- CAPIF Security API -- CAPIF Events API -- CAPIF Provider Management API - -Testing Suite of all services with robot. -Also Postman suite to a simple test. - - [Open API Descriptions of 3GPP 5G APIs]: https://forge.3gpp.org/rep/all/5G_APIs "Open API Descriptions of 3GPP 5G APIs" [Test Plan Directory]: ./docs/test_plan/README.md "Test Plan Directory" [Testing Using Curl]: ./docs/testing_with_curl/README.md "Testing Using Curl" [Testing with Robot Framework]: ./docs/testing_with_robot/README.md "Testing with Robot Framework" -[FAQ Directory]: ./FAQ.md "FAQ directory" \ No newline at end of file +[FAQ Directory]: https://ocf.etsi.org/documentation/latest/FAQ/ "FAQ Url" +[OCF Documentation]: https://ocf.etsi.org/documentation/latest/ "OCF Documentation" + diff --git a/deploy.sh b/deploy.sh new file mode 100644 index 0000000000000000000000000000000000000000..5b483bd72628228beb6b7b5a381e61ac42bf9b37 --- /dev/null +++ b/deploy.sh @@ -0,0 +1,32 @@ +#!/bin/sh + +dirlocation=`pwd`/. +# If no argument is provided, use "main" as the default value +default_branch="main" +default_mon="false" +branch="${1:-$default_branch}" +monitoring="${2:-default_mon}" + +echo "Selected branch: $branch" +echo "We're working with $dirlocation" +cd $dirlocation + + +updaterepo(){ + cd $dirlocation + echo "Build " $1 + if [ ! -d $1 ]; then + git clone https://labs.etsi.org/rep/ocf/$1.git + fi + + cd $1/ + git checkout $branch + git pull +} + +updaterepo capif + +cd $dirlocation +cd capif/services + +./run.sh -m $monitoring \ No newline at end of file diff --git a/docs/images/flows/01 - Register of AEF.png b/docs/images/flows/01 - Register of AEF.png deleted file mode 100644 index 391cb43fe8657f9965c66391f716cfc06a5e9eb0..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/01 - Register of AEF.png and /dev/null differ diff --git a/docs/images/flows/01a - Register (Only) AEF.png b/docs/images/flows/01a - Register (Only) AEF.png deleted file mode 100644 index 5b6d17b181408b74fb3e15bc8276d79bf1290c39..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/01a - Register (Only) AEF.png and /dev/null differ diff --git a/docs/images/flows/01b - Register of AEF GetAuth.png b/docs/images/flows/01b - Register of AEF GetAuth.png deleted file mode 100644 index 8cb5cb75839e340aeedf3349c8032fcae1fc3ce4..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/01b - Register of AEF GetAuth.png and /dev/null differ diff --git a/docs/images/flows/02 - AEF API Provider registration.png b/docs/images/flows/02 - AEF API Provider registration.png deleted file mode 100644 index 3b42e21185ae36c97f3c6504624757a80e282ef6..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/02 - AEF API Provider registration.png and /dev/null differ diff --git a/docs/images/flows/03 - AEF Publish.png b/docs/images/flows/03 - AEF Publish.png deleted file mode 100644 index dfe3a3e09ff3183fa93eab95e1df107a2dfa9638..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/03 - AEF Publish.png and /dev/null differ diff --git a/docs/images/flows/04 - Invoker Register.png b/docs/images/flows/04 - Invoker Register.png deleted file mode 100644 index 571f2af8098ba390a31cf5676ba0cd180b55d983..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/04 - Invoker Register.png and /dev/null differ diff --git a/docs/images/flows/04a - Invoker (Only) Register.png b/docs/images/flows/04a - Invoker (Only) Register.png deleted file mode 100644 index 535d8b5baf23f43060231d20ca82c077e0959bab..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/04a - Invoker (Only) Register.png and /dev/null differ diff --git a/docs/images/flows/04b - Invoker Register GetAuth.png b/docs/images/flows/04b - Invoker Register GetAuth.png deleted file mode 100644 index 2cb2349e0378c18f874da9442852ca1eb79deb6b..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/04b - Invoker Register GetAuth.png and /dev/null differ diff --git a/docs/images/flows/05 - Invoker Onboarding.png b/docs/images/flows/05 - Invoker Onboarding.png deleted file mode 100644 index 9cd4b2d9fc99daa0f285a0f9e5cf77d9c51ea17c..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/05 - Invoker Onboarding.png and /dev/null differ diff --git a/docs/images/flows/06 - Invoker Discover AEF.png b/docs/images/flows/06 - Invoker Discover AEF.png deleted file mode 100644 index 20b2f04f94444833bbea04832620434593f89bc0..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/06 - Invoker Discover AEF.png and /dev/null differ diff --git a/docs/images/flows/07 - Invoker Create Security Context.png b/docs/images/flows/07 - Invoker Create Security Context.png deleted file mode 100644 index bb655e0e38e8394b3aaa024ada0f13c2f21c2b4c..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/07 - Invoker Create Security Context.png and /dev/null differ diff --git a/docs/images/flows/08 - Invoker Get Token.png b/docs/images/flows/08 - Invoker Get Token.png deleted file mode 100644 index 2e39f52a3d12efa8c19ea3032957e9f48d890d0e..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/08 - Invoker Get Token.png and /dev/null differ diff --git a/docs/images/flows/09 - Invoker Send Request to AEF Service API.png b/docs/images/flows/09 - Invoker Send Request to AEF Service API.png deleted file mode 100644 index 1e4a87c54b04d2d6524da2617fa615dab7318dc7..0000000000000000000000000000000000000000 Binary files a/docs/images/flows/09 - Invoker Send Request to AEF Service API.png and /dev/null differ diff --git a/docs/images/robot_log_example.png b/docs/images/robot_log_example.png deleted file mode 100644 index 6c15a031e26eae47fed53b21a1e69e2f7bfa89db..0000000000000000000000000000000000000000 Binary files a/docs/images/robot_log_example.png and /dev/null differ diff --git a/docs/images/robot_report_example.png b/docs/images/robot_report_example.png deleted file mode 100644 index 1cf36d8766753d08938be73c87e958f4c8d56068..0000000000000000000000000000000000000000 Binary files a/docs/images/robot_report_example.png and /dev/null differ diff --git a/docs/test_plan/README.md b/docs/test_plan/README.md deleted file mode 100644 index d25099756a27c799848098e6e343564298a2f0c2..0000000000000000000000000000000000000000 --- a/docs/test_plan/README.md +++ /dev/null @@ -1,16 +0,0 @@ -[**[Return To Main]**] - -# Testplans -List of Common API Services implemented: -* [Api Invoker Management](./api_invoker_management/README.md) -* [Api Provider Management](./api_provider_management/README.md) -* [Api Publish Service](./api_publish_service/README.md) -* [Api Discover Service](./api_discover_service/README.md) -* [Api Events Service](./api_events_service/README.md) -* [Api Security Service](./api_security_service/README.md) -* [Api Logging Service](./api_logging_service/README.md) -* [Api Auditing Service](./api_auditing_service/README.md) -* [Api Access Control Policy](./api_access_control_policy/README.md) - - - [Return To Main]: ../../README.md#test-plan-documentation \ No newline at end of file diff --git a/docs/test_plan/api_access_control_policy/README.md b/docs/test_plan/api_access_control_policy/README.md deleted file mode 100644 index 05a9e63227702c7972790a6ea248d6f9a1dea864..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_access_control_policy/README.md +++ /dev/null @@ -1,813 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Api Access Control Policy](#test-plan-for-capif-api-access-control-policy) -- [Tests](#tests) - - [Test Case 1: Retrieve ACL](#test-case-1-retrieve-acl) - - [Test Case 2: Retrieve ACL with 2 Service APIs published](#test-case-2-retrieve-acl-with-2-service-apis-published) - - [Test Case 3: Retrieve ACL with security context created by two different Invokers](#test-case-3-retrieve-acl-with-security-context-created-by-two-different-invokers) - - [Test Case 4: Retrieve ACL filtered by api-invoker-id](#test-case-4-retrieve-acl-filtered-by-api-invoker-id) - - [Test Case 5: Retrieve ACL filtered by supported-features](#test-case-5-retrieve-acl-filtered-by-supported-features) - - [Test Case 6: Retrieve ACL with aef-id not valid](#test-case-6-retrieve-acl-with-aef-id-not-valid) - - [Test Case 7: Retrieve ACL with service-id not valid](#test-case-7-retrieve-acl-with-service-id-not-valid) - - [Test Case 8: Retrieve ACL with service-api-id and aef-id not valid](#test-case-8-retrieve-acl-with-service-api-id-and-aef-id-not-valid) - - [Test Case 9: Retrieve ACL without SecurityContext created previously by Invoker](#test-case-9-retrieve-acl-without-securitycontext-created-previously-by-invoker) - - [Test Case 10: Retrieve ACL filtered by api-invoker-id not present](#test-case-10-retrieve-acl-filtered-by-api-invoker-id-not-present) - - [Test Case 11: Retrieve ACL with APF Certificate](#test-case-11-retrieve-acl-with-apf-certificate) - - [Test Case 12: Retrieve ACL with AMF Certificate](#test-case-12-retrieve-acl-with-amf-certificate) - - [Test Case 13: Retrieve ACL with Invoker Certificate](#test-case-13-retrieve-acl-with-invoker-certificate) - - [Test Case 14: No ACL for invoker after be removed](#test-case-14-no-acl-for-invoker-after-be-removed) - - - - -# Test Plan for CAPIF Api Access Control Policy -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Retrieve ACL -* **Test ID**: ***capif_api_acl-1*** -* **Description**: - - This test case will check that an API Provider can retrieve ACL from CAPIF -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* - * Use *serviceApiId* and *aefId* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. ACL Response: - 1. **200 OK** Response. - 2. body returned must accomplish **AccessControlPolicyList** data structure. - 3. apiInvokerPolicies must: - 1. contain only one object. - 2. apiInvokerId must match apiInvokerId registered previously. - - -## Test Case 2: Retrieve ACL with 2 Service APIs published -* **Test ID**: ***capif_api_acl-2*** -* **Description**: - - This test case will check that an API Provider can retrieve ACL from CAPIF for 2 different serviceApis published. -* **Pre-Conditions**: - - * API Provider had two Service API Published on CAPIF - * API Invoker had a Security Context for both Service APIs published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_2 - * Store *serviceApiId* - * Use APF Certificate - - 4. Perform [Invoker Onboarding] store apiInvokerId - 5. Discover published APIs - 6. Create Security Context for this Invoker for both published APIs - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 7. Provider Retrieve ACL for serviceApiId1 - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}* - * Use *serviceApiId* and *aefId* - * Use AEF Provider Certificate - - 8. Provider Retrieve ACL for serviceApiId2 - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId2}?aef-id=${aef_id}* - * Use *serviceApiId* and *aefId* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 and service_2 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information for service_1. - 7. Provider Get ACL information for service_2. - -* **Expected Result**: - - 1. ACL Response: - 1. **200 OK** Response. - 2. body returned must accomplish **AccessControlPolicyList** data structure. - 3. apiInvokerPolicies must: - 1. contain one object. - 2. apiInvokerId must match apiInvokerId registered previously. - -## Test Case 3: Retrieve ACL with security context created by two different Invokers -* **Test ID**: ***capif_api_acl-3*** -* **Description**: - - This test case will check that an API Provider can retrieve ACL from CAPIF containing 2 objects. -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * Two API Invokers had a Security Context for same Service API published by provider. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker for both published APIs - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Repeat previous 3 steps in order to have a new Invoker. - - 7. Provider Retrieve ACL for serviceApiId - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}* - * Use *serviceApiId* and *aefId* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 and service_2 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. ACL Response: - 1. **200 OK** Response. - 2. body returned must accomplish **AccessControlPolicyList** data structure. - 3. apiInvokerPolicies must: - 1. Contain two objects. - 2. One object must match with apiInvokerId1 and the other one with apiInvokerId2 an registered previously. - -## Test Case 4: Retrieve ACL filtered by api-invoker-id -* **Test ID**: ***capif_api_acl-4*** -* **Description**: - - This test case will check that an API Provider can retrieve ACL filtering by apiInvokerId from CAPIF containing 1 objects. -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * Two API Invokers had a Security Context for same Service API published by provider. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 4. Perform [Invoker Onboarding] store apiInvokerId - 6. Discover published APIs - 7. Create Security Context for this Invoker for both published APIs - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 8. Repeat previous 3 steps in order to have a new Invoker. - - 9. Provider Retrieve ACL for serviceApiId - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&api-invoker-id={apiInvokerId1}* - * Use *serviceApiId*, *aefId* and apiInvokerId1 - * Use AEF Provider Certificate - - 10. Provider Retrieve ACL for serviceApiId - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&api-invoker-id={apiInvokerId2}* - * Use *serviceApiId*, *aefId* and apiInvokerId2 - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 and service_2 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information with query parameter indicating first api-invoker-id. - 7. Provider Get ACL information with query parameter indicating second api-invoker-id. - -* **Expected Result**: - - 1. ACL Response: - 1. **200 OK** Response. - 2. body returned must accomplish **AccessControlPolicyList** data structure. - 3. apiInvokerPolicies must: - 1. Contain one objects. - 2. Object must match with apiInvokerId1. - - 2. ACL Response: - 1. **200 OK** Response. - 2. body returned must accomplish **AccessControlPolicyList** data structure. - 3. apiInvokerPolicies must: - 1. Contain one objects. - 2. Object must match with apiInvokerId2. - -## Test Case 5: Retrieve ACL filtered by supported-features -* **Test ID**: ***capif_api_acl-5*** -* **Description**: - **CURRENTLY NOT SUPPORTED FEATURE** - - This test case will check that an API Provider can retrieve ACL filtering by supportedFeatures from CAPIF containing 1 objects. - -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * Two API Invokers had a Security Context for same Service API published by provider. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker for both published APIs - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Repeat previous 3 steps in order to have a new Invoker. - - 7. Provider Retrieve ACL for serviceApiId - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&supported-features={apiInvokerId1}* - * Use *serviceApiId*, *aefId* and apiInvokerId1 - * Use AEF Provider Certificate - - 8. Provider Retrieve ACL for serviceApiId - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId1}?aef-id=${aef_id}&supported-features={apiInvokerId2}* - * Use *serviceApiId*, *aefId* and apiInvokerId2 - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 and service_2 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information with query parameter indicating first supported-features. - 7. Provider Get ACL information with query parameter indicating second supported-features. - -* **Expected Result**: - - 1. ACL Response: - 1. **200 OK** Response. - 2. body returned must accomplish **AccessControlPolicyList** data structure. - 3. apiInvokerPolicies must: - 1. Contain one objects. - 2. Object must match with supportedFeatures1. - - 2. ACL Response: - 1. **200 OK** Response. - 2. body returned must accomplish **AccessControlPolicyList** data structure. - 3. apiInvokerPolicies must: - 1. Contain one objects. - 2. Object must match with supportedFeatures1. - - -## Test Case 6: Retrieve ACL with aef-id not valid -* **Test ID**: ***capif_api_acl-6*** -* **Description**: - - This test case will check that an API Provider can't retrieve ACL from CAPIF if aef-id is not valid -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${AEF_ID_NOT_VALID}* - * Use *serviceApiId* and *AEF_ID_NOT_VALID* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. ACL Response: - 1. **404 Not Found** Response. - 2. body returned must accomplish **Problem Details** data structure. - 3. apiInvokerPolicies must: - * status **404** - * title with message "Not Found" - * detail with message "No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". - * cause with message "Wrong id". - - -## Test Case 7: Retrieve ACL with service-id not valid -* **Test ID**: ***capif_api_acl-7*** -* **Description**: - - This test case will check that an API Provider can't retrieve ACL from CAPIF if service-api-id is not valid -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${NOT_VALID_SERVICE_API_ID}?aef-id=${aef_id}* - * Use *NOT_VALID_SERVICE_API_ID* and *aef_id* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. ACL Response: - 1. **404 Not Found** Response. - 2. body returned must accomplish **Problem Details** data structure. - 3. apiInvokerPolicies must: - * status **404** - * title with message "Not Found" - * detail with message "No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". - * cause with message "Wrong id". - -## Test Case 8: Retrieve ACL with service-api-id and aef-id not valid -* **Test ID**: ***capif_api_acl-8*** -* **Description**: - - This test case will check that an API Provider can't retrieve ACL from CAPIF if service-api-id and aef-id are not valid -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${NOT_VALID_SERVICE_API_ID}?aef-id=${AEF_ID_NOT_VALID}* - * Use *NOT_VALID_SERVICE_API_ID* and *aef_id* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. ACL Response: - 1. **404 Not Found** Response. - 2. body returned must accomplish **Problem Details** data structure. - 3. apiInvokerPolicies must: - * status **404** - * title with message "Not Found" - * detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". - * cause with message "Wrong id". - - -## Test Case 9: Retrieve ACL without SecurityContext created previously by Invoker -* **Test ID**: ***capif_api_acl-9*** -* **Description**: - - This test case will check that an API Provider can't retrieve ACL if no invoker had requested Security Context to CAPIF -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker created but no Security Context for Service API published had been requested. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - - 5. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* - * Use *serviceApiId* and *aefId* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. ACL Response: - 1. **404 Not Found** Response. - 2. body returned must accomplish **Problem Details** data structure. - 3. apiInvokerPolicies must: - * status **404** - * title with message "Not Found" - * detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". - * cause with message "Wrong id". - -## Test Case 10: Retrieve ACL filtered by api-invoker-id not present -* **Test ID**: ***capif_api_acl-10*** -* **Description**: - - This test case will check that an API Provider get not found response if filter by not valid api-invoker-id doesn't match any registered ACL. -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&api-invoker-id={NOT_VALID_API_INVOKER_ID}* - * Use *serviceApiId*, *aefId* and *NOT_VALID_API_INVOKER_ID* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. ACL Response: - 1. **404 Not Found** Response. - 2. body returned must accomplish **Problem Details** data structure. - 3. apiInvokerPolicies must: - * status **404** - * title with message "Not Found" - * detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}". - * cause with message "Wrong id". - -## Test Case 11: Retrieve ACL with APF Certificate -* **Test ID**: ***capif_api_acl-11*** -* **Description**: - - This test case will check that an API Provider can't retrieve ACL from CAPIF using APF Certificate -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* - * Use *serviceApiId* and *aefId* - * Use APF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. Response to Logging Service must accomplish: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 401 - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "Certificate not authorized". - -## Test Case 12: Retrieve ACL with AMF Certificate -* **Test ID**: ***capif_api_acl-12*** -* **Description**: - - This test case will check that an API Provider can't retrieve ACL from CAPIF using AMF Certificate -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* - * Use *serviceApiId* and *aefId* - * Use AMF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. Response to Logging Service must accomplish: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 401 - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "Certificate not authorized". - -## Test Case 13: Retrieve ACL with Invoker Certificate -* **Test ID**: ***capif_api_acl-13*** -* **Description**: - - This test case will check that an API Provider can't retrieve ACL from CAPIF using Invoker Certificate -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}* - * Use *serviceApiId* and *aefId* - * Use Invoker Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information. - -* **Expected Result**: - - 1. Response to Logging Service must accomplish: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 401 - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "Certificate not authorized". - -## Test Case 14: No ACL for invoker after be removed -* **Test ID**: ***capif_api_acl-14*** -* **Description**: - - This test case will check that ACLs are removed after invoker is removed. -* **Pre-Conditions**: - - * API Provider had a Service API Published on CAPIF - * API Invoker had a Security Context for Service API published and ACL is present - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Store *serviceApiId* - * Use APF Certificate - - 3. Perform [Invoker Onboarding] store apiInvokerId - 4. Discover published APIs - 5. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - - 6. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&api-invoker-id={api-invoker-id}* - * Use *serviceApiId*, *aefId* and *api-invoker-id* - * Use AEF Provider Certificate - 7. Remove Invoker from CAPIF - 8. Provider Retrieve ACL - * Send GET *https://{CAPIF_HOSTNAME}/access-control-policy/v1/accessControlPolicyList/${serviceApiId}?aef-id=${aef_id}&api-invoker-id={api-invoker-id}* - * Use *serviceApiId*, *aefId* and *api-invoker-id* - * Use AEF Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Provider at CCF. - 2. Publish a provider API with name service_1 - 3. Register and onboard Invoker at CCF - 4. Store signed Certificate - 5. Create Security Context - 6. Provider Get ACL information of invoker. - 7. Remove Invoker from CAPIF. - 8. Provider Get ACL information of invoker. - -* **Expected Result**: - 1. ACL Response: - 1. **200 OK** Response. - 2. body returned must accomplish **AccessControlPolicyList** data structure. - 3. apiInvokerPolicies must: - 1. contain only one object. - 2. apiInvokerId must match apiInvokerId registered previously. - - 2. ACL Response: - 1. **404 Not Found** Response. - 2. body returned must accomplish **Problem Details** data structure. - 3. apiInvokerPolicies must: - * status **404** - * title with message "Not Found" - * detail with message "No ACLs found for the requested service: {NOT_VALID_SERVICE_API_ID}, aef_id: {AEF_ID_NOT_VALID}, invoker: None and supportedFeatures: None". - * cause with message "Wrong id". - - - -[Return To All Test Plans]: ../README.md - -[service api description]: ../api_publish_service/service_api_description_post_example.json "Service API Description Request" -[publisher register body]: ../api_publish_service/publisher_register_body.json "Publish register Body" -[service security body]: ./service_security.json "Service Security Request" -[security notification body]: ./security_notification.json "Security Notification Request" -[access token req body]: ./access_token_req.json "Access Token Request" -[example]: ./access_token_req.json "Access Token Request Example" -[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" -[provider registration]: ../common_operations/README.md#register-a-provider "Provider Registration" diff --git a/docs/test_plan/api_access_control_policy/service_api_description_post_example.json b/docs/test_plan/api_access_control_policy/service_api_description_post_example.json deleted file mode 100644 index b725b428629509bf39a79c030f1bf93f4b6f18f6..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_access_control_policy/service_api_description_post_example.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "apiName": "service_1", - "aefProfiles": [ - { - "aefId": "string", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "string", - "commType": "REQUEST_RESPONSE", - "uri": "string", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - } - ] - }, - { - "aefId": "string", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "string", - "commType": "REQUEST_RESPONSE", - "uri": "string", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - } - ] - } - ], - "description": "string", - "supportedFeatures": "fffff", - "shareableInfo": { - "isShareable": true, - "capifProvDoms": [ - "string" - ] - }, - "serviceAPICategory": "string", - "apiSuppFeats": "fffff", - "pubApiPath": { - "ccfIds": [ - "string" - ] - }, - "ccfId": "string" -} \ No newline at end of file diff --git a/docs/test_plan/api_auditing_service/README.md b/docs/test_plan/api_auditing_service/README.md deleted file mode 100644 index bd3204c0aa3cc0eeb63b3f85f6f6629914957aa4..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_auditing_service/README.md +++ /dev/null @@ -1,244 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Api Auditing Service](#test-plan-for-capif-api-auditing-service) -- [Tests](#tests) - - [Test Case 1: Get a CAPIF Log Entry.](#test-case-1-creates-a-new-individual-capif-log-entry) - - -# Test Plan for CAPIF Api Auditing Service -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Get CAPIF Log Entry. -* Test ID: ***capif_api_auditing-1*** -* Description: - - This test case will check that a CAPIF AMF can get log entry to Logging Service -* Pre-Conditions: - - * CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority) - * Service exist in CAPIF - * Invoker exist in CAPIF - * Log Entry exist in CAPIF - -* Information of Test: - - 1. Perform [provider onboarding], [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Create Log Entry: - - Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* - - body [log entry request body] - - Use AEF Certificate - - 4. Get Log: - 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&api-invoker-id={api-invoker-id}* - 2. Use AMF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - 4. Get Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **200 OK** - 2. Response Body must follow **InvocationLog** data structure with: - * aefId - * apiInvokerId - * logs - -## Test Case 2: Get CAPIF Log Entry With no Log entry in CAPIF. -* Test ID: ***capif_api_auditing-2*** -* Description: - - This test case will check that a CAPIF AEF can create log entry to Logging Service -* Pre-Conditions: - - * CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority) - * Service exist in CAPIF - * Invoker exist in CAPIF - - -* Information of Test: - - 1. Perform [provider onboarding], [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 4. Get Log: - 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&api-invoker-id={api-invoker-id}* - 2. Use AMF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Get Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found Log Entry in CAPIF". - * cause with message "Not Exist Logs with the filters applied". - - -## Test Case 3: Get CAPIF Log Entry without aef-id and api-invoker-id. -* Test ID: ***capif_api_auditing-3*** -* Description: - - This test case will check that a CAPIF AEF can create log entry to Logging Service -* Pre-Conditions: - - * CAPIF provider is no pre-authorised (has no valid AMF cert from CAPIF Authority) - * Service exist in CAPIF - * Invoker exist in CAPIF - * Log Entry exist in CAPIF - -* Information of Test: - - 1. Perform [provider onboarding], [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Create Log Entry: - - Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* - - body [log entry request body] - - Use AEF Certificate - - 4. Get Log: - 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs - 2. Use AMF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - 4. Get Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **400 Bad Request** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 400 - * title with message "Bad Request" - * detail with message "aef_id and api_invoker_id parameters are mandatory". - * cause with message "Mandatory parameters missing". - - -## Test Case 4: Get CAPIF Log Entry with filtter api-version. -* Test ID: ***capif_api_auditing-4*** -* Description: - - This test case will check that a CAPIF AMF can get log entry to Logging Service -* Pre-Conditions: - - * CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority) - * Service exist in CAPIF - * Invoker exist in CAPIF - * Log Entry exist in CAPIF - -* Information of Test: - - 1. Perform [provider onboarding], [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Create Log Entry: - - Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* - - body [log entry request body] - - Use AEF Certificate - - 4. Get Log: - 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&api-invoker-id={api-invoker-id}&api-version={v1}* - 2. Use AMF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - 4. Get Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **200 OK** - 2. Response Body must follow **InvocationLog** data structure with: - * aefId - * apiInvokerId - * logs - - -## Test Case 5: Get CAPIF Log Entry with filter api-version but not exist in log entry. -* Test ID: ***capif_api_auditing-4*** -* Description: - - This test case will check that a CAPIF AMF can get log entry to Logging Service -* Pre-Conditions: - - * CAPIF provider is pre-authorised (has valid AMF cert from CAPIF Authority) - * Service exist in CAPIF - * Invoker exist in CAPIF - * Log Entry exist in CAPIF - -* Information of Test: - - 1. Perform [provider onboarding], [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Create Log Entry: - - Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* - - body [log entry request body] - - Use AEF Certificate - - 4. Get Log: - 1. Send GET to *https://{CAPIF_HOSTNAME}/logs/v1/apiInvocationLogs?aef-id={aefId}&api-invoker-id={api-invoker-id}&api-version={v58}* - 2. Use AMF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - 4. Get Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * detail with message "Parameters do not match any log entry" - * cause with message "No logs found". - - - -[log entry request body]: ../api_logging_service/invocation_log.json "Log Request Body" - -[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" - -[provider onboarding]: ../common_operations/README.md#register-a-provider "Provider Onboarding" - -[Return To All Test Plans]: ../README.md \ No newline at end of file diff --git a/docs/test_plan/api_discover_service/README.md b/docs/test_plan/api_discover_service/README.md deleted file mode 100644 index 3125c888c96eadcbda6a7b6a688aa721f2714000..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_discover_service/README.md +++ /dev/null @@ -1,336 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Discover Service](#test-plan-for-capif-discover-service) -- [Tests](#tests) - - [Test Case 1: Discover Published service APIs by Authorised API Invoker](#test-case-1-discover-published-service-apis-by-authorised-api-invoker) - - [Test Case 2: Discover Published service APIs by Non Authorised API Invoker](#test-case-2-discover-published-service-apis-by-non-authorised-api-invoker) - - [Test Case 3: Discover Published service APIs by not registered API Invoker](#test-case-3-discover-published-service-apis-by-not-registered-api-invoker) - - [Test Case 4: Discover Published service APIs by registered API Invoker with 1 result filtered](#test-case-4-discover-published-service-apis-by-registered-api-invoker-with-1-result-filtered) - - [Test Case 5: Discover Published service APIs by registered API Invoker filtered with no match](#test-case-5-discover-published-service-apis-by-registered-api-invoker-filtered-with-no-match) - - [Test Case 6: Discover Published service APIs by registered API Invoker not filtered](#test-case-6-discover-published-service-apis-by-registered-api-invoker-not-filtered) - - -# Test Plan for CAPIF Discover Service -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Discover Published service APIs by Authorised API Invoker -* **Test ID**: ***capif_api_discover_service-1*** -* **Description**: - - This test case will check if NetApp (Invoker) can discover published service APIs. -* **Pre-Conditions**: - * Service APIs are published. - * NetApp was registered previously - * NetApp was onboarded previously with {onboardingId} - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Use APF Certificate - 3. Request Discover Published APIs: - * Send GET to *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Use Invoker Certificate - -* **Execution Steps**: - - 1. Register Provider at CCF, store certificates and Publish Service API at CCF - 2. Register Invoker and Onboard Invoker at CCF - 3. Discover Service APIs by Invoker - -* **Expected Result**: - - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - - 2. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - 3. Response to Discover Request By Invoker: - 1. **200 OK** response. - 2. Response body must follow **DiscoveredAPIs** data structure: - * Check if DiscoveredAPIs contains the API Published previously - - -## Test Case 2: Discover Published service APIs by Non Authorised API Invoker -* **Test ID**: ***capif_api_discover_service-2*** -* **Description**: - - This test case will check that an API Publisher can't discover published APIs because is not authorized. - -* **Pre-Conditions**: - * Service APIs are published. - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Use APF Certificate - 3. Request Discover Published APIs by no invoker entity: - * Send GET to *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Use not Invoker Certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API at CCF - 2. Register Invoker and Onboard Invoker at CCF - 3. Discover Service APIs by no invoker entity - -* **Expected Result**: - - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - - 2. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - 3. Response to Discover Request By no invoker entity: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 401 - * title with message "Unauthorized" - * detail with message "User not authorized". - * cause with message "Certificate not authorized". - - -## Test Case 3: Discover Published service APIs by not registered API Invoker -* **Test ID**: ***capif_api_discover_service-3*** -* **Description**: - - This test case will check that a not registered invoker is forbidden to discover published APIs. - -* **Pre-Conditions**: - * Service APIs are published. - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Use APF Certificate - 3. Request Discover Published APIs with not valid apiInvoker: - * Send GET to *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={INVOKER_NOT_REGISTERED}* - * Param api-invoker-id is mandatory - * Using invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API at CCF - 2. Register Invoker and Onboard Invoker at CCF - 3. Discover Service APIs by Publisher - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - - 2. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - 3. Response to Discover Request By Invoker: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "API Invoker does not exist". - * cause with message "API Invoker id not found". - - -## Test Case 4: Discover Published service APIs by registered API Invoker with 1 result filtered -* **Test ID**: ***capif_api_discover_service-4*** -* **Description**: - - This test case will check if NetApp (Invoker) can discover published service APIs. -* **Pre-Conditions**: - * At least 2 Service APIs are published. - * NetApp was registered previously - * NetApp was onboarded previously with {onboardingId} - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Use APF Certificate - 3. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_2 - * Use APF Certificate - 4. Request Discover Published APIs filtering by api-name: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}&api-name=service_1* - * Param api-invoker-id is mandatory - * Using invoker certificate - * filter by api-name service_1 - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF - 2. Register Invoker and Onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Discover filtered by api-name service_1 Service APIs by Invoker - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - 2. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - 3. Response to Discover Request By Invoker: - 1. **200 OK** response. - 2. Response body must follow **DiscoveredAPIs** data structure: - * Check if DiscoveredAPIs contains previously registered Service APIs published. - 4. Response to Discover Request By Invoker: - 1. **200 OK** response. - 2. Response body must follow **DiscoveredAPIs** data structure: - * Check if DiscoveredAPIs contains only Service API published with api-name service_1 - - -## Test Case 5: Discover Published service APIs by registered API Invoker filtered with no match -* **Test ID**: ***capif_api_discover_service-5*** -* **Description**: - This test case will check if NetApp (Invoker) can discover published service APIs. -* **Pre-Conditions**: - * At least 2 Service APIs are published. - * NetApp was registered previously - * NetApp was onboarded previously with {onboardingId} - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Use APF Certificate - 3. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_2 - * Use APF Certificate - 4. Request Discover Published APIs filtering by api-name not published: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}&api-name=NOT_VALID_NAME* - * Param api-invoker-id is mandatory - * Using invoker certificate - * filter by api-name NOT_VALID_NAME - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF - 2. Register Invoker and Onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Discover filtered by api-name not published Service APIs by Invoker - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - 2. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - 3. Response to Discover Request By Invoker: - 1. **200 OK** response. - 2. Response body must follow **DiscoveredAPIs** data structure: - * Check if DiscoveredAPIs contains previously registered Service APIs published. - 4. Response to Discover Request By Invoker: - 1. **404 Not Found** response. - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "API Invoker {api_invoker_id} has no API Published that accomplish filter conditions". - * cause with message "No API Published accomplish filter conditions". - - -## Test Case 6: Discover Published service APIs by registered API Invoker not filtered -* **Test ID**: ***capif_api_discover_service-6*** -* **Description**: - - This test case will check if NetApp (Invoker) can discover published service APIs. -* **Pre-Conditions**: - * 2 Service APIs are published. - * NetApp was registered previously - * NetApp was onboarded previously with {onboardingId} - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Use APF Certificate - 3. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_2 - * Use APF Certificate - 4. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 and service_2 at CCF - 2. Register Invoker and Onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Discover without filter by Invoker - -* **Expected Result**: - - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - - 2. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - 3. Response to Discover Request By Invoker: - 1. **200 OK** response. - 2. Response body must follow **DiscoveredAPIs** data structure: - * Check if DiscoveredAPIs contains the 2 previously registered Service APIs published. - - - - [service api description]: ./api_publish_service/service_api_description_post_example.json "Service API **Description** Request" - [publisher register body]: ./api_publish_service/publisher_register_body.json "Publish register Body" - [invoker onboarding body]: ../api_invoker_management/invoker_details_post_example.json "API Invoker Request" - [invoker register body]: ../api_invoker_management/invoker_register_body.json "Invoker Register Body" - [provider request body]: ../api_provider_management/provider_details_post_example.json "API Provider Enrolment Request" - [provider request patch body]: ../api_provider_management/provider_details_enrolment_details_patch_example.json "API Provider Enrolment Patch Request" - [provider getauth body]: ../api_provider_management/provider_getauth_example.json "Get Auth Example" - [invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" - [provider registration]: ../common_operations/README.md#register-a-provider "Provider Registration" - - -[Return To All Test Plans]: ../README.md diff --git a/docs/test_plan/api_events_service/README.md b/docs/test_plan/api_events_service/README.md deleted file mode 100644 index 417c1aa623671fde54b4e894b8e359ee03dd9d36..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_events_service/README.md +++ /dev/null @@ -1,265 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Api Events Service](#test-plan-for-capif-api-events-service) -- [Tests](#tests) - - [Test Case 1: Creates a new individual CAPIF Event Subscription.](#test-case-1-creates-a-new-individual-capif-event-subscription) - - [Test Case 2: Creates a new individual CAPIF Event Subscription with Invalid SubscriberId](#test-case-2-creates-a-new-individual-capif-event-subscription-with-invalid-subscriberid) - - [Test Case 3: Deletes an individual CAPIF Event Subscription](#test-case-3-deletes-an-individual-capif-event-subscription) - - [Test Case 4: Deletes an individual CAPIF Event Subscription with invalid SubscriberId](#test-case-4-deletes-an-individual-capif-event-subscription-with-invalid-subscriberid) - - [Test Case 5: Deletes an individual CAPIF Event Subscription with invalid SubscriptionId](#test-case-5-deletes-an-individual-capif-event-subscription-with-invalid-subscriptionid) - - - -# Test Plan for CAPIF Api Events Service -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Creates a new individual CAPIF Event Subscription. -* Test ID: ***capif_api_events-1*** -* Description: - - This test case will check that a CAPIF subscriber (Invoker or Publisher) can Subscribe to Events -* Pre-Conditions: - - * CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority) - -* Information of Test: - - 1. Perform [Invoker Onboarding] - - 2. Event Subscription: - 1. Send POST to *https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions* - 2. body [event subscription request body] - 3. Use Invoker Certificate - -* Execution Steps: - - 1. Register Invoker and Onboard Invoker at CCF - 2. Subscribe to Events - 3. Retrieve {subscriberId} and {subscriptionId} from Location Header - -* Expected Result: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - 2. Response to Event Subscription must accomplish: - 1. **201 Created** - 2. The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: *{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId} - 3. Response Body must follow **EventSubscription** data structure. - - 3. Event Subscriptions are stored in CAPIF Database - - -## Test Case 2: Creates a new individual CAPIF Event Subscription with Invalid SubscriberId -* Test ID: ***capif_api_events-2*** -* Description: - - This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Subscribe to Events without valid SubcriberId -* Pre-Conditions: - - * CAPIF subscriber is not pre-authorised (has invalid InvokerId or apfId) - -* Information of Test: - - 1. Perform [Invoker Onboarding] - - 2. Event Subscription: - 1. Send POST to *https://{CAPIF_HOSTNAME}/capif-events/v1/{SUBSCRIBER_NOT_REGISTERED}/subscriptions* - 2. body [event subscription request body] - 3. Use Invoker Certificate - -* Execution Steps: - - 1. Register Invoker and Onboard Invoker at CCF - 2. Subscribe to Events - -* Expected Result: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - 2. Response to Event Subscription must accomplish: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Invoker or APF or AEF or AMF Not found". - * cause with message "Subscriber Not Found". - - 3. Event Subscriptions are not stored in CAPIF Database - - -## Test Case 3: Deletes an individual CAPIF Event Subscription -* Test ID: ***capif_api_events-3*** -* Description: - - This test case will check that a CAPIF subscriber (Invoker or Publisher) can Delete an Event Subscription -* Pre-Conditions: - - * CAPIF subscriber is pre-authorised (has valid InvokerId or apfId from CAPIF Authority) - -* Information of Test: - - 1. Perform [Invoker Onboarding] - - 2. Event Subscription: - 1. Send POST to *https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions* - 2. body [event subscription request body] - 3. Use Invoker Certificate - - 3. Remove Event Subscription: - 1. Send DELETE to *https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions* - 2. Use Invoker Certificate - -* Execution Steps: - - 1. Register Invoker and Onboard Invoker at CCF - 2. Subscribe to Events - 3. Retrieve {subscriberId} and {subscriptionId} from Location Header - 4. Remove Event Subscription - -* Expected Result: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - 2. Response to Event Subscription must accomplish: - 1. **201 Created** - 2. The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: *{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId} - 3. Response Body must follow **EventSubscription** data structure. - - 3. Event Subscriptions are stored in CAPIF Database - 4. Remove Event Subscription: - 1. **204 No Content** - - 5. Event Subscription is not present at CAPIF Database. - - -## Test Case 4: Deletes an individual CAPIF Event Subscription with invalid SubscriberId -* Test ID: ***capif_api_events-4*** -* Description: - - This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Delete to Events without valid SubcriberId -* Pre-Conditions: - - * CAPIF subscriber is pre-authorised (has valid InvokerId or apfId). - * CAPIF subscriber is subscribed to Events. - -* Information of Test: - - 1. Perform [Invoker Onboarding] - - 2. Event Subscription: - 1. Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions - 2. body [event subscription request body] - 3. Use Invoker Certificate - - 3. Remove Event Subcription with not valid subscriber: - 1. Send DELETE to to https://{CAPIF_HOSTNAME}/capif-events/v1/{SUBSCRIBER_ID_NOT_VALID}/subscriptions/{subcriptionId} - 2. Use Invoker Certificate - -* Execution Steps: - - 1. Register Invoker and Onboard Invoker at CCF - 2. Subscribe to Events - 3. Retrieve Location Header with subscriptionId. - 4. Remove Event Subscribed with not valid Subscriber. - -* Expected Result: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - 2. Response to Event Subscription must accomplish: - 1. 201 Created - 2. The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: *{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId} - 3. Response Body must follow **EventSubscription** data structure. - - 3. Event Subscriptions are stored in CAPIF Database - 4. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Invoker or APF or AEF or AMF Not found". - * cause with message "Subscriber Not Found". - - -## Test Case 5: Deletes an individual CAPIF Event Subscription with invalid SubscriptionId -* Test ID: ***capif_api_events-5*** -* Description: - - This test case will check that a CAPIF subscriber (Invoker or Publisher) cannot Delete an Event Subscription without valid SubscriptionId -* Pre-Conditions: - - * CAPIF subscriber is pre-authorised (has invalid InvokerId or apfId). - * CAPIF subscriber is subscribed to Events. - -* Information of Test: - - 1. Perform [Invoker Onboarding] - - 2. Event Subscription: - 1. Send POST to https://{CAPIF_HOSTNAME}/capif-events/v1/{subscriberId}/subscriptions - 2. body [event subscription request body] - 3. Use Invoker Certificate - - 3. Remove Event Subcription with not valid subscriber: - 1. Send DELETE to to https://{CAPIF_HOSTNAME}/capif-events/v1/{subcriberId}/subscriptions/{SUBSCRIPTION_ID_NOT_VALID} - 2. Use Invoker Certificate - -* Execution Steps: - - 1. Register Invoker and Onboard Invoker at CCF - 2. Subscribe to Events - 3. Retrieve Location Header with subscriptionId. - 4. Remove Event Subscribed with not valid Subscriber. - -* Expected Result: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - 2. Response to Event Subscription must accomplish: - 1. **201 Created** - 2. The URI of the created resource shall be returned in the "Location" HTTP header, following this structure: *{apiRoot}/capif-events/{apiVersion}/{subscriberId}/subscriptions/{subscriptionId} - 3. Response Body must follow **EventSubscription** data structure. - - 3. Event Subscriptions are stored in CAPIF Database - 4. Remove Event Subscription with not valid subscriber: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * detail with message "Service API not existing". - * cause with message "Event API subscription id not found". - - - - -[invoker register body]: ../api_invoker_management/invoker_register_body.json "Invoker Register Body" -[invoker onboard request body]: ../api_invoker_management/invoker_details_post_example.json "API Invoker Request" -[event subscription request body]: ./event_subscription.json "Event Subscription Request" -[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" - - -[Return To All Test Plans]: ../README.md diff --git a/docs/test_plan/api_events_service/event_subscription.json b/docs/test_plan/api_events_service/event_subscription.json deleted file mode 100644 index 40dc09bb1ca5236fa9cb23ff1a25ad5dccd28844..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_events_service/event_subscription.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "eventFilters": [ - { - "aefIds": ["aefIds", "aefIds"], - "apiIds": ["apiIds", "apiIds"], - "apiInvokerIds": ["apiInvokerIds", "apiInvokerIds"] - }, - { - "aefIds": ["aefIds", "aefIds"], - "apiIds": ["apiIds", "apiIds"], - "apiInvokerIds": ["apiInvokerIds", "apiInvokerIds"] - } - ], - "eventReq": { - "grpRepTime": 5, - "immRep": true, - "maxReportNbr": 0, - "monDur": "2000-01-23T04:56:07+00:00", - "partitionCriteria": ["string1", "string2"], - "repPeriod": 6, - "sampRatio": 15 - }, - "events": ["SERVICE_API_AVAILABLE", "API_INVOKER_ONBOARDED"], - "notificationDestination": "http://robot.testing", - "requestTestNotification": true, - "supportedFeatures": "aaa", - "websockNotifConfig": { - "requestWebsocketUri": true, - "websocketUri": "websocketUri" - } -} diff --git a/docs/test_plan/api_invoker_management/README.md b/docs/test_plan/api_invoker_management/README.md deleted file mode 100644 index 9846c960d9e8fda5d84676a2242f820aa54f53cf..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_invoker_management/README.md +++ /dev/null @@ -1,306 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Api Invoker Management](#test-plan-for-capif-api-invoker-management) -- [Tests](#tests) - - [Test Case 1: Onboard NetApp](#test-case-1-onboard-netapp) - - [Test Case 2: Onboard NetApp Already onboarded](#test-case-2-onboard-netapp-already-onboarded) - - [Test Case 3: Update Onboarded NetApp](#test-case-3-update-onboarded-netapp) - - [Test Case 4: Update Not Onboarded NetApp](#test-case-4-update-not-onboarded-netapp) - - [Test Case 5: Offboard NetApp](#test-case-5-offboard-netapp) - - [Test Case 6: Offboard Not previsouly Onboarded NetApp](#test-case-6-offboard-not-previsouly-onboarded-netapp) - - [Test Case 7: Update Onboarded NetApp Certificate](#test-case-7-update-onboarded-netapp-certificate) - - -# Test Plan for CAPIF Api Invoker Management -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Onboard NetApp -* **Test ID**: ***capif_api_invoker_management-1*** -* **Description**: - - This test will try to register new NetApp at CAPIF Core. -* **Pre-Conditions**: - - * NetApp was not registered previously - * NetApp was not onboarded previously - -* **Information of Test**: - - 1. Create public and private key at invoker - - 2. Register of Invoker at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [invoker register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [invoker getauth body] - - 4. Onboard Invoker: - * Send POST to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers* - * Reference Request Body: [invoker onboarding body] - * "onboardingInformation"->"apiInvokerPublicKey": must contain public key generated by Invoker. - * Send at Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token}) - -* **Execution Steps**: - 1. Register Invoker at CCF - 2. Onboard Invoker at CCF - 3. Store signed Certificate - -* **Expected Result**: - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - -## Test Case 2: Onboard NetApp Already onboarded - -* **Test ID**: ***capif_api_invoker_management-2*** -* **Description**: - - This test will check second onboard of same NetApp is not allowed. - -* **Pre-Conditions**: - - * NetApp was registered previously - * NetApp was onboarded previously - -* **Information of Test**: - - 1. Perform [Invoker Onboarding] - - 2. Repeat Onboard Invoker: - * Send POST to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers* - * Reference Request Body: [invoker onboarding body] - * "onboardingInformation"->"apiInvokerPublicKey": must contain public key generated by Invoker. - * Send at Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token}) - -* **Execution Steps**: - 1. Register NetApp at CCF - 2. Onboard NetApp at CCF - 3. Store signed Certificate at NetApp - 4. Onboard Again the NetApp at CCF - -* **Expected Result**: - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - 2. Response to Second Onboard of NetApp must accomplish: - 1. **403 Forbidden** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 403 - * title with message "Forbidden" - * detail with message "Invoker Already registered". - * cause with message "Identical invoker public key". - - -## Test Case 3: Update Onboarded NetApp -* **Test ID**: ***capif_api_invoker_management-3*** -* **Description**: - - This test will try to update information of previous onboard NetApp at CAPIF Core. -* **Pre-Conditions**: - - * NetApp was registered previously - * NetApp was onboarded previously with {onboardingId} - -* **Information of Test**: - - 1. Perform [Invoker Onboarding] - - 2. Update information of previously onboarded Invoker: - * Send PUT to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}* - * Reference Request Body is: [put invoker onboarding body] - * "notificationDestination": "*http://host.docker.internal:8086/netapp_new_callback*", - -* **Execution Steps**: - - 1. Register Invoker at CCF - 2. Onboard Invoker at CCF - 3. Store signed Certificate - 4. Update Onboarding Information at CCF with a minor change on "notificationDestination" - -* **Expected Result**: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - 2. Response to Update Request (PUT) with minor change must contain: - 1. **200 OK** response. - 2. notificationDestination on response must contain the new value - - -## Test Case 4: Update Not Onboarded NetApp -* **Test ID**: ***capif_api_invoker_management-4*** -* **Description**: - - This test will try to update information of not onboarded NetApp at CAPIF Core. -* **Pre-Conditions**: - - * NetApp was registered previously - * NetApp was not onboarded previously - -* **Information of Test**: - - 1. Perform [Invoker Onboarding] - - 2. Update information of not onboarded Invoker: - * Send PUT to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{INVOKER_NOT_REGISTERED}* - * Reference Request Body is: [put invoker onboarding body] - -* **Execution Steps**: - - 1. Register Invoker at CCF - 2. Onboard Invoker at CCF - 3. Update Onboarding Information at CCF of not onboarded - -* **Expected Result**: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response to Update Request (PUT) must contain: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Please provide an existing Netapp ID". - * cause with message "Not exist NetappID". - - - -## Test Case 5: Offboard NetApp -* **Test ID**: ***capif_api_invoker_management-5*** -* **Description**: - - This test case will check that a Registered NetApp can be deleted. -* **Pre-Conditions**: - - * NetApp was registered previously - * NetApp was onboarded previously - -* **Information of Test**: - - 1. Perform [Invoker Onboarding] - - 2. Offboard: - * Send Delete to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}* - -* **Execution Steps**: - - 1. Register Invoker at CCF - 2. Onboard Invoker at CCF - 3. Offboard Invoker at CCF - -* **Expected Result**: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response to Offboard Request (DELETE) must contain: - 1. **204 No Content** - - -## Test Case 6: Offboard Not previsouly Onboarded NetApp -* **Test ID**: ***capif_api_invoker_management-6*** -* **Description**: - - This test case will check that a Non-Registered NetApp cannot be deleted -* **Pre-Conditions**: - - * NetApp was registered previously - * NetApp was not onboarded previously - -* **Information of Test**: - - 1. Perform [Invoker Onboarding] - - 2. Offboard: - * Send Delete to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{INVOKER_NOT_REGISTERED}* - -* **Execution Steps**: - - 1. Register Invoker at CCF - 2. Offboard Invoker at CCF - -* **Expected Result**: - - 1. Response to Offboard Request (DELETE) must contain: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Please provide an existing Netapp ID". - * cause with message "Not exist NetappID". - -## Test Case 7: Update Onboarded NetApp Certificate -* **Test ID**: ***capif_api_invoker_management-7*** -* **Description**: - - This test will try to update public key and get a new signed certificate by CAPIF Core. -* **Pre-Conditions**: - - * NetApp was registered previously - * NetApp was onboarded previously with {onboardingId} and {public_key_1} - -* **Information of Test**: - - 1. Perform [Invoker Onboarding] with public_key_1. - - 2. Create {public_key_2} - - 3. Update information of previously onboarded Invoker: - * Send PUT to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}* - * Reference Request Body is: [put invoker onboarding body] - * ["onboardingInformation"]["apiInvokerPublicKey"]: {public_key_2}, - * Store new certificate. - - 4. Update information of previously onboarded Invoker Using new certificate: - * Send PUT to *https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers/{onboardingId}* - * Reference Request Body is: [put invoker onboarding body] - * "notificationDestination": "*http://host.docker.internal:8086/netapp_new_callback*", - * Use new invoker certificate - -* **Execution Steps**: - - 1. Register Invoker at CCF - 2. Onboard Invoker at CCF - 3. Store signed Certificate - 4. Update Onboarding Information at CCF with new public key - 5. Update Onboarding Information at CCF with minor change - -* **Expected Result**: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - 2. Response to Update Request (PUT) with new public key: - 1. **200 OK** response. - 2. apiInvokerCertificate with new certificate on response -> store to use. - 3. Response to Update Request (PUT) with minor change must contain: - 1. **200 OK** response. - 2. notificationDestination on response must contain the new value - - - - -[invoker onboarding body]: ./invoker_details_post_example.json "API Invoker Request" -[invoker register body]: ./invoker_register_body.json "Invoker Register Body" -[put register body]: ./invoker_details_put_example.json "API Invoker Update Request" -[invoker getauth body]: ./invoker_getauth_example.json "Get Auth Example" - -[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" - -[Return To All Test Plans]: ../README.md \ No newline at end of file diff --git a/docs/test_plan/api_invoker_management/invoker_details_post_example.json b/docs/test_plan/api_invoker_management/invoker_details_post_example.json deleted file mode 100644 index c306a17e2d04f55da35a5b3638775af9d63e769f..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_invoker_management/invoker_details_post_example.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "notificationDestination": "http://host.docker.internal:8086/netapp_callback", - "supportedFeatures": "fffffff", - "apiInvokerInformation": "ROBOT_TESTING_INVOKER", - "websockNotifConfig": { - "requestWebsocketUri": true, - "websocketUri": "websocketUri" - }, - "onboardingInformation": { - "apiInvokerPublicKey": "{PUBLIC_KEY}", - "onboardingSecret": "onboardingSecret", - "apiInvokerCertificate": "apiInvokerCertificate" - }, - "requestTestNotification": true -} diff --git a/docs/test_plan/api_invoker_management/invoker_details_put_example.json b/docs/test_plan/api_invoker_management/invoker_details_put_example.json deleted file mode 100644 index 37a1eefbb05a2df1058b20429477cbf17f412cb8..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_invoker_management/invoker_details_put_example.json +++ /dev/null @@ -1,393 +0,0 @@ -{ - "notificationDestination": "http://host.docker.internal:8086/netapp_new_callback", - "supportedFeatures": "fffffff", - "apiInvokerInformation": "ROBOT_TESTING_INVOKER", - "websockNotifConfig": { - "requestWebsocketUri": true, - "websocketUri": "websocketUri" - }, - "onboardingInformation": { - "apiInvokerPublicKey": "{PUBLIC_KEY}", - "onboardingSecret": "onboardingSecret", - "apiInvokerCertificate": "apiInvokerCertificate" - }, - "requestTestNotification": true, - "apiList": [ - { - "serviceAPICategory": "serviceAPICategory", - "ccfId": "ccfId", - "apiName": "apiName", - "shareableInfo": { - "capifProvDoms": ["capifProvDoms", "capifProvDoms"], - "isShareable": true - }, - "supportedFeatures": "fffffff", - "description": "description", - "apiSuppFeats": "fffffff", - "apiId": "apiId", - "aefProfiles": [ - { - "securityMethods": ["PSK"], - "versions": [ - { - "apiVersion": "apiVersion", - "resources": [ - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - } - ], - "custOperations": [ - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - } - ], - "expiry": "2000-01-23T04:56:07.000+00:00" - }, - { - "apiVersion": "apiVersion", - "resources": [ - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - } - ], - "custOperations": [ - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - } - ], - "expiry": "2000-01-23T04:56:07.000+00:00" - } - ], - "aefId": "aefId", - "interfaceDescriptions": [ - { - "securityMethods": ["PSK"], - "port": 5248, - "ipv4Addr": "ipv4Addr" - }, - { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" } - ] - }, - { - "securityMethods": ["PSK"], - "versions": [ - { - "apiVersion": "apiVersion", - "resources": [ - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - } - ], - "custOperations": [ - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - } - ], - "expiry": "2000-01-23T04:56:07.000+00:00" - }, - { - "apiVersion": "apiVersion", - "resources": [ - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - } - ], - "custOperations": [ - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - } - ], - "expiry": "2000-01-23T04:56:07.000+00:00" - } - ], - "aefId": "aefId", - "interfaceDescriptions": [ - { - "securityMethods": ["PSK"], - "port": 5248, - "ipv4Addr": "ipv4Addr" - }, - { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" } - ] - } - ], - "pubApiPath": { "ccfIds": ["ccfIds", "ccfIds"] } - }, - { - "serviceAPICategory": "serviceAPICategory", - "ccfId": "ccfId", - "apiName": "apiName2", - "shareableInfo": { - "capifProvDoms": ["capifProvDoms", "capifProvDoms"], - "isShareable": true - }, - "supportedFeatures": "fffffff", - "description": "description", - "apiSuppFeats": "fffffff", - "apiId": "apiId", - "aefProfiles": [ - { - "securityMethods": ["PSK"], - "versions": [ - { - "apiVersion": "apiVersion", - "resources": [ - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - } - ], - "custOperations": [ - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - } - ], - "expiry": "2000-01-23T04:56:07.000+00:00" - }, - { - "apiVersion": "apiVersion", - "resources": [ - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - } - ], - "custOperations": [ - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - } - ], - "expiry": "2000-01-23T04:56:07.000+00:00" - } - ], - "aefId": "aefId", - "interfaceDescriptions": [ - { - "securityMethods": ["PSK"], - "port": 5248, - "ipv4Addr": "ipv4Addr" - }, - { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" } - ] - }, - { - "securityMethods": ["PSK"], - "versions": [ - { - "apiVersion": "apiVersion", - "resources": [ - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - } - ], - "custOperations": [ - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - } - ], - "expiry": "2000-01-23T04:56:07.000+00:00" - }, - { - "apiVersion": "apiVersion", - "resources": [ - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "resourceName": "resourceName", - "custOpName": "custOpName", - "uri": "uri", - "commType": "REQUEST_RESPONSE" - } - ], - "custOperations": [ - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - }, - { - "operations": ["GET"], - "description": "description", - "custOpName": "custOpName", - "commType": "REQUEST_RESPONSE" - } - ], - "expiry": "2000-01-23T04:56:07.000+00:00" - } - ], - "aefId": "aefId", - "interfaceDescriptions": [ - { - "securityMethods": ["PSK"], - "port": 5248, - "ipv4Addr": "ipv4Addr" - }, - { "securityMethods": ["PSK"], "port": 5248, "ipv4Addr": "ipv4Addr" } - ] - } - ], - "pubApiPath": { "ccfIds": ["ccfIds", "ccfIds"] } - } - ] -} diff --git a/docs/test_plan/api_invoker_management/invoker_getauth_example.json b/docs/test_plan/api_invoker_management/invoker_getauth_example.json deleted file mode 100644 index a66dad58adb1894b70b802193164301a429abdc1..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_invoker_management/invoker_getauth_example.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "username": "ROBOT_TESTING_INVOKER", - "password": "password" -} diff --git a/docs/test_plan/api_invoker_management/invoker_register_body.json b/docs/test_plan/api_invoker_management/invoker_register_body.json deleted file mode 100644 index e5bf1fc5b89682c56416c62530a95a5a86037885..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_invoker_management/invoker_register_body.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "password": "password", - "username": "ROBOT_TESTING_INVOKER", - "role": "invoker", - "description": "Testing", - "cn": "ROBOT_TESTING_INVOKER" -} diff --git a/docs/test_plan/api_logging_service/README.md b/docs/test_plan/api_logging_service/README.md deleted file mode 100644 index 913a652ba779bc66dcae07c64502a5312bf3fdce..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_logging_service/README.md +++ /dev/null @@ -1,241 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Api Logging Service](#test-plan-for-capif-api-logging-service) -- [Tests](#tests) - - [Test Case 1: Creates a new individual CAPIF Log Entry.](#test-case-1-creates-a-new-individual-capif-log-entry) - - [Test Case 2: Creates a new individual CAPIF Log Entry with Invalid aefID](#test-case-2-creates-a-new-individual-capif-log-entry-with-invalid-aefid) - - [Test Case 3: Creates a new individual CAPIF Log Entry with Invalid serviceAPI](#test-case-3-creates-a-new-individual-capif-log-entry-with-invalid-serviceapi) - - [Test Case 4: Creates a new individual CAPIF Log Entry with Invalid apiInvokerId](#test-case-4-creates-a-new-individual-capif-log-entry-with-invalid-apiinvokerid) - - - [Test Case 5: Creates a new individual CAPIF Log Entry with differnted aef_id in body and request](#test-case-5-creates-a-new-individual-capif-log-entry-with-invalid-aefid-in-body) - - -# Test Plan for CAPIF Api Logging Service -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Creates a new individual CAPIF Log Entry. -* Test ID: ***capif_api_logging-1*** -* Description: - - This test case will check that a CAPIF AEF can create log entry to Logging Service -* Pre-Conditions: - - * CAPIF provider is pre-authorised (has valid aefId from CAPIF Authority) - * Service exist in CAPIF - * Invoker exist in CAPIF - -* Information of Test: - - 1. Perform [provider onboarding] and [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Log Entry: - 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* - 2. body [log entry request body] - 3. Use AEF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **201 Created** - 2. Response Body must follow **InvocationLog** data structure with: - * aefId - * apiInvokerId - * logs - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invocation-logs/v1/{aefId}/logs/{logId}* - - - - -## Test Case 2: Creates a new individual CAPIF Log Entry with Invalid aefId -* Test ID: ***capif_api_logging-2*** -* Description: - - This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId -* Pre-Conditions: - - * CAPIF provider is not pre-authorised (has not valid aefId from CAPIF Authority) - * Service exist in CAPIF - * Invoker exist in CAPIF - -* Information of Test: - - 1. Perform [provider onboarding] and [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Log Entry: - 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{not-valid-aefId}/logs* - 2. body [log entry request body] - 3. Use AEF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Exposer not exist". - * cause with message "Exposer id not found". - -## Test Case 3: Creates a new individual CAPIF Log Entry with Invalid serviceAPI -* Test ID: ***capif_api_logging-3*** -* Description: - - This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId -* Pre-Conditions: - - * CAPIF subscriber is pre-authorised (has valid aefId from CAPIF Authority) - -* Information of Test: - - 1. Perform [provider onboarding] and [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Log Entry: - 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* - 2. body [log entry request body with serviceAPI apiName apiId not valid] - 3. Use AEF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Invoker not exist". - * cause with message "Invoker id not found". - - - -## Test Case 4: Creates a new individual CAPIF Log Entry with Invalid apiInvokerId -* Test ID: ***capif_api_logging-4*** -* Description: - - This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId -* Pre-Conditions: - - * CAPIF subscriber is pre-authorised (has valid aefId from CAPIF Authority) - -* Information of Test: - - 1. Perform [provider onboarding] and [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Log Entry: - 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* - 2. body [log entry request body with invokerId not valid] - 3. Use AEF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - -* Expected Result: - - 1. Response to Onboard request must accomplish: - 1. **201 Created** response. - 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure. - 3. For each **apiProvFuncs**, we must check: - 1. **apiProvFuncId** is set - 2. **apiProvCert** under **regInfo** is set properly - 5. Location Header must contain the new resource URL *{apiRoot}/api-provider-management/v1/registrations/{registrationId}* - - 2. Response to Logging Service must accomplish: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Invoker not exist". - * cause with message "Invoker id not found". - - 3. Log Entry are not stored in CAPIF Database - - -## Test Case 5: Creates a new individual CAPIF Log Entry with Invalid aefId in body -* Test ID: ***capif_api_logging-5*** -* Description: - - This test case will check that a CAPIF subscriber (AEF) cannot create Log Entry without valid aefId in body -* Pre-Conditions: - - * CAPIF provider is pre-authorised (has valid apfId from CAPIF Authority) - * Service exist in CAPIF - * Invoker exist in CAPIF - -* Information of Test: - - 1. Perform [provider onboarding] and [invoker onboarding] - - 2. Publish Service API at CCF: - - Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - - body [service api description] with apiName service_1 - - Use APF Certificate - - 3. Log Entry: - 1. Send POST to *https://{CAPIF_HOSTNAME}/api-invocation-logs/v1/{aefId}/logs* - 2. body [log entry request body with bad aefId] - 3. Use AEF Certificate - -* Execution Steps: - 1. Register Provider and Invoker CCF - 2. Publish Service - 3. Create Log Entry - -* Expected Result: - - 1. Response to Logging Service must accomplish: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 401 - * title with message "Unauthorized" - * detail with message "AEF id not matching in request and body". - * cause with message "Not identical AEF id". - - - - - - -[log entry request body]: ./invocation_log.json "Log Request Body" - -[invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" - -[provider onboarding]: ../common_operations/README.md#register-a-provider "Provider Onboarding" - -[Return To All Test Plans]: ../README.md diff --git a/docs/test_plan/api_logging_service/invocation_log.json b/docs/test_plan/api_logging_service/invocation_log.json deleted file mode 100644 index ceabcf02016e116566cd2b13c99a87a6adcef5d3..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_logging_service/invocation_log.json +++ /dev/null @@ -1,45 +0,0 @@ -{ - "aefId": "aefId", - "apiInvokerId": "apiInvokerId", - "logs": [ - { - "apiId": "apiId", - "apiName": "apiName", - "apiVersion": "string", - "resourceName": "string", - "uri": "string", - "protocol": "HTTP_1_1", - "operation": "GET", - "result": "string", - "invocationTime": "2023-03-30T10:30:21.404Z", - "invocationLatency": 0, - "inputParameters": "string", - "outputParameters": "string", - "srcInterface": { - "ipv4Addr": "string", - "ipv6Addr": "string", - "fqdn": "string", - "port": 65535, - "apiPrefix": "string", - "securityMethods": [ - "PSK", - "Oauth" - ] - }, - "destInterface": { - "ipv4Addr": "string", - "ipv6Addr": "string", - "fqdn": "string", - "port": 65535, - "apiPrefix": "string", - "securityMethods": [ - "PSK", - "string" - ] - }, - "fwdInterface": "string" - } - ], - "supportedFeatures": "string" - } - \ No newline at end of file diff --git a/docs/test_plan/api_provider_management/README.md b/docs/test_plan/api_provider_management/README.md deleted file mode 100644 index 547d654d69308c7dbbcc2b89f168df911e9e75dc..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_provider_management/README.md +++ /dev/null @@ -1,398 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Api Provider Management](#test-plan-for-capif-api-provider-management) -- [Tests](#tests) - - [Test Case 1: Register Api Provider](#test-case-1-register-api-provider) - - [Test Case 2: Register Api Provider Already registered](#test-case-2-register-api-provider-already-registered) - - [Test Case 3: Update Registered Api Provider](#test-case-3-update-registered-api-provider) - - [Test Case 4: Update Not Registered Api Provider](#test-case-4-update-not-registered-api-provider) - - [Test Case 5: Partially Update Registered Api Provider](#test-case-5-partially-update-registered-api-provider) - - [Test Case 6: Partially Update Not Registered Api Provider](#test-case-6-partially-update-not-registered-api-provider) - - [Test Case 7: Delete Registered Api Provider](#test-case-7-delete-registered-api-provider) - - [Test Case 8: Delete Not Registered Api Provider](#test-case-8-delete-not-registered-api-provider) - - -# Test Plan for CAPIF Api Provider Management -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Register Api Provider -* **Test ID**: ***capif_api_provider_management-1*** -* **Description**: - - This test case will check that Api Provider can be registered con CCF -* **Pre-Conditions**: - - * Provider is pre-authorised (has valid certificate from CAPIF Authority) - -* **Information of Test**: - - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Authentication Bearer with access_token - * Store each cert in a file with according name. - -* **Execution Steps**: - - 1. Create private and public key for provider and each function to register. - 2. Register Provider. - -* **Expected Result**: - - 1. Register Provider at Provider Management: - 1. **201 Created** response. - 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure. - 3. For each **apiProvFuncs**, we must check: - 1. **apiProvFuncId** is set - 2. **apiProvCert** under **regInfo** is set properly - 5. Location Header must contain the new resource URL *{apiRoot}/api-provider-management/v1/registrations/{registrationId}* - -## Test Case 2: Register Api Provider Already registered -* **Test ID**: ***capif_api_provider_management-2*** -* **Description**: - - This test case will check that a Api Provider previously registered cannot be re-registered -* **Pre-Conditions**: - - * Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB - -* **Information of Test**: - - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Authentication Bearer with access_token - * Store each cert in a file with according name. - - 5. Re-Register Provider: - * Same regSec than Previous registration - -* **Execution Steps**: - - 1. Create private and public key for provider and each function to register. - 2. Register Provider. - 3. Re-Register Provider. - -* **Expected Result**: - - 1. Re-Register Provider: - 1. **403 Forbidden** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status 403 - * title with message "Forbidden" - * detail with message "Provider already registered". - * cause with message "Identical provider reg sec". - -## Test Case 3: Update Registered Api Provider -* **Test ID**: ***capif_api_provider_management-3*** -* **Description**: - - This test case will check that a Registered Api Provider can be updated -* **Pre-Conditions**: - - * Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB - -* **Information of Test**: - - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Authentication Bearer with access_token - * Get Resource URL from Location - - 5. Update Provider: - * Send PUT to Resource URL returned at registration *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}* - * body [provider request body] with apiProvDomInfo set to ROBOT_TESTING_MOD - * Use AMF Certificate. - - -* **Execution Steps**: - - 1. Create private and public key for provider and each function to register. - 2. Register Provider - 3. Update Provider - -* **Expected Result**: - 1. Register Provider: - 1. **201 Created** response. - 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure. - 3. Location Header must contain the new resource URL *{apiRoot}/api-provider-management/v1/registrations/{registrationId}* - - - 2. Update Provider: - 1. **200 OK** response. - 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure, with: - * apiProvDomInfo set to ROBOT_TESTING_MOD - - -## Test Case 4: Update Not Registered Api Provider -* **Test ID**: ***capif_api_provider_management-4*** -* **Description**: - - This test case will check that a Non-Registered Api Provider cannot be updated -* **Pre-Conditions**: - - * Api Provider was not registered previously - -* **Information of Test**: - - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Authentication Bearer with access_token - * Store each cert in a file with according name. - - 5. Update Not Registered Provider: - * Send PUT *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_PROVIDER_NOT_REGISTERED}* - * body [provider request body] - * Use AMF Certificate. - -* **Execution Steps**: - - 1. Register Provider at CCF - 3. Update Not Registered Provider - -* **Expected Result**: - - 1. Update Not Registered Provider: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status 404 - * title with message "Not Found" - * detail with message "Not Exist Provider Enrolment Details". - * cause with message "Not found registrations to send this api provider details". - -## Test Case 5: Partially Update Registered Api Provider -* **Test ID**: ***capif_api_provider_management-5*** -* **Description**: - - This test case will check that a Registered Api Provider can be partially updated -* **Pre-Conditions**: - - * Api Provider was registered previously and there is a {registerId} for his Api Provider in the DB - -* **Information of Test**: - - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Authentication Bearer with access_token - * Store each cert in a file with according name. - - 5. Partial update provider: - * Send PATCH *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}* - * body [provider request patch body] - * Use AMF Certificate. - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Register Provider - 3. Partial update provider - -* **Expected Result**: - - 1. Partial update provider at Provider Management: - 1. **200 OK** response. - 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure, with: - * apiProvDomInfo with "ROBOT_TESTING_MOD" - -## Test Case 6: Partially Update Not Registered Api Provider -* **Test ID**: ***capif_api_provider_management-6*** -* **Description**: - - This test case will check that a Non-Registered Api Provider cannot be partially updated - -* **Pre-Conditions**: - - * Api Provider was not registered previously - -* **Information of Test**: - - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Authentication Bearer with access_token - * Store each cert in a file with according name. - - 5. Partial update Provider: - * Send PATCH *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_API_PROVIDER_NOT_REGISTERED}* - * body [provider request patch body] - * Use AMF Certificate. - - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Register Provider - 3. Partial update provider - -* **Expected Result**: - - 1. Partial update provider: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status 404 - * title with message "Not Found" - * detail with message "Not Exist Provider Enrolment Details". - * cause with message "Not found registrations to send this api provider details". - -## Test Case 7: Delete Registered Api Provider -* **Test ID**: ***capif_api_provider_management-7*** -* **Description**: - - This test case will check that a Registered Api Provider can be deleted -* **Pre-Conditions**: - - * Api Provider was registered previously - -* **Information of Test**: - - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Authentication Bearer with access_token - * Store each cert in a file with according name. - - 5. Delete registered provider: - * Send DELETE *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{registrationId}* - * Use AMF Certificate. - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Register Provider - 3. Delete Provider - -* **Expected Result**: - - 1. Delete Provider: - 1. **204 No Content** response. - -## Test Case 8: Delete Not Registered Api Provider -* **Test ID**: ***capif_api_provider_management-8*** -* **Description**: - - This test case will check that a Non-Registered Api Provider cannot be deleted -* **Pre-Conditions**: - - * Api Provider was not registered previously - -* **Information of Test**: - - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Authentication Bearer with access_token - * Store each cert in a file with according name. - - 5. Delete registered provider at Provider Management: - * Send DELETE *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations/{API_PROVIDER_NOT_REGISTERED}* - * Use AMF Certificate. - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Delete Provider - -* **Expected Result**: - - 1. Delete Provider: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status 404 - * title with message "Not Found" - * detail with message "Not Exist Provider Enrolment Details". - * cause with message "Not found registrations to send this api provider details". - -[provider register body]: ./provider_details_post_example.json "API Provider Enrolment Request" - -[provider request body]: ./provider_details_post_example.json "API Provider Enrolment Request" - -[provider request patch body]: ./provider_details_enrolment_details_patch_example.json "API Provider Enrolment Patch Request" - -[provider getauth body]: ./provider_getauth_example.json "Get Auth Example" - -[Return To All Test Plans]: ../README.md diff --git a/docs/test_plan/api_provider_management/provider_details_enrolment_details_patch_example.json b/docs/test_plan/api_provider_management/provider_details_enrolment_details_patch_example.json deleted file mode 100644 index 4dac4f409eccfc7201c4eaf615b55f70c38b54e4..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_provider_management/provider_details_enrolment_details_patch_example.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "regSec": "", - "apiProvFuncs": [ - { - "regInfo": { - "apiProvPubKey": "" - }, - "apiProvFuncRole": "APF", - "apiProvFuncInfo": "APF_ROBOT_TESTING_PROVIDER" - }, - { - "regInfo": { - "apiProvPubKey": "" - }, - "apiProvFuncRole": "AEF", - "apiProvFuncInfo": "AEF_ROBOT_TESTING_PROVIDER" - }, - { - "regInfo": { - "apiProvPubKey": "" - }, - "apiProvFuncRole": "AMF", - "apiProvFuncInfo": "AMF_ROBOT_TESTING_PROVIDER" - } - ], - "apiProvDomInfo": "ROBOT_TESTING", - "suppFeat": "string", - "failReason": "string" -} \ No newline at end of file diff --git a/docs/test_plan/api_provider_management/provider_details_post_example.json b/docs/test_plan/api_provider_management/provider_details_post_example.json deleted file mode 100644 index 48e91bacf24899e55221babf610598b9d4132b61..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_provider_management/provider_details_post_example.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "regSec": "string", - "apiProvFuncs": [ - { - "apiProvFuncId": "string", - "regInfo": { - "apiProvPubKey": "string", - "apiProvCert": "string" - }, - "apiProvFuncRole": "AEF", - "apiProvFuncInfo": "string" - } - ], - "apiProvDomInfo": "string", - "suppFeat": "string", - "failReason": "string" -} \ No newline at end of file diff --git a/docs/test_plan/api_provider_management/provider_getauth_example.json b/docs/test_plan/api_provider_management/provider_getauth_example.json deleted file mode 100644 index 8fc82aeebfc9531651fa746bf10be11c6aa347f3..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_provider_management/provider_getauth_example.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "username": "ROBOT_TESTING_PROVIDER", - "password": "password" -} diff --git a/docs/test_plan/api_provider_management/provider_register_body.json b/docs/test_plan/api_provider_management/provider_register_body.json deleted file mode 100644 index fc26db2141eab904b1f2f8d96e963f2ec0efcbe1..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_provider_management/provider_register_body.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "password": "password", - "username": "ROBOT_TESTING_PUBLISHER", - "role": "provider", - "description": "Testing", - "cn": "ROBOT_TESTING_PUBLISHER" -} diff --git a/docs/test_plan/api_publish_service/README.md b/docs/test_plan/api_publish_service/README.md deleted file mode 100644 index 8487f5d5cc582ab65c393c5e437267e51b23a089..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_publish_service/README.md +++ /dev/null @@ -1,599 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Api Publish Service](#test-plan-for-capif-api-publish-service) -- [Tests](#tests) - - [Test Case 1: Publish API by Authorised API Publisher](#test-case-1-publish-api-by-authorised-api-publisher) - - [Test Case 2: Publish API by NON Authorised API Publisher](#test-case-2-publish-api-by-non-authorised-api-publisher) - - [Test Case 3: Retrieve all APIs Published by Authorised apfId](#test-case-3-retrieve-all-apis-published-by-authorised-apfid) - - [Test Case 4: Retrieve all APIs Published by NON Authorised apfId](#test-case-4-retrieve-all-apis-published-by-non-authorised-apfid) - - [Test Case 5: Retrieve single APIs Published by Authorised apfId](#test-case-5-retrieve-single-apis-published-by-authorised-apfid) - - [Test Case 6: Retrieve single APIs non Published by Authorised apfId](#test-case-6-retrieve-single-apis-non-published-by-authorised-apfid) - - [Test Case 7: Retrieve single APIs Published by NON Authorised apfId](#test-case-7-retrieve-single-apis-published-by-non-authorised-apfid) - - [Test Case 8: Update API Published by Authorised apfId with valid serviceApiId](#test-case-8-update-api-published-by-authorised-apfid-with-valid-serviceapiid) - - [Test Case 9: Update APIs Published by Authorised apfId with invalid serviceApiId](#test-case-9-update-apis-published-by-authorised-apfid-with-invalid-serviceapiid) - - [Test Case 10: Update APIs Published by NON Authorised apfId](#test-case-10-update-apis-published-by-non-authorised-apfid) - - [Test Case 11: Delete API Published by Authorised apfId with valid serviceApiId](#test-case-11-delete-api-published-by-authorised-apfid-with-valid-serviceapiid) - - [Test Case 12: Delete APIs Published by Authorised apfId with invalid serviceApiId](#test-case-12-delete-apis-published-by-authorised-apfid-with-invalid-serviceapiid) - - [Test Case 13: Delete APIs Published by NON Authorised apfId](#test-case-13-delete-apis-published-by-non-authorised-apfid) - - -# Test Plan for CAPIF Api Publish Service -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Publish API by Authorised API Publisher -* **Test ID**: ***capif_api_publish_service-1*** -* **Description**: - - This test case will check that an API Publisher can Publish an API -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Publish Service API - 3. Retrieve {apiId} from body and Location header with new resource created from response - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - - 2. Published Service API is stored in CAPIF Database - -## Test Case 2: Publish API by NON Authorised API Publisher -* **Test ID**: ***capif_api_publish_service-2*** -* **Description**: - - This test case will check that an API Publisher cannot Publish an API withot valid apfId -* **Pre-Conditions**: - - * CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority) - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Publish Service API with invalid APF ID at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{APF_ID_NOT_VALID}/service-apis* - * body [service api description] with apiName service_1 - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Publish Service API with invalid APF ID - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status **401** - * title with message "Unauthorized" - * detail with message "Publisher not existing". - * cause with message "Publisher id not found". - - 2. Service API is NOT stored in CAPIF Database - - -## Test Case 3: Retrieve all APIs Published by Authorised apfId -* **Test ID**: ***capif_api_publish_service-3*** -* **Description**: - - This test case will check that an API Publisher can Retrieve all API published -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) - * At least 2 service APIs are published. - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Get apiId - * Use APF Certificate - - 3. Publish Other Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_2 - * Get apiId - * Use APF Certificate - - 4. Retrieve all published APIs: - * Send Get to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Publish Service API service_1 - 3. Retrieve {apiId1} from body and Location header with new resource created from response - 4. Publish Service API service_2 - 5. Retrieve {apiId2} from body and Location header with new resource created from response - 6. Retrieve All published APIs and check if both are present. - -* **Expected Result**: - 1. Response to service 1 Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId1}* - - 2. Response to service 2 Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId2}* - - 3. Published Service APIs are stored in CAPIF Database - - 4. Response to Retrieve all published APIs: - 1. **200 OK** - 2. Response body must return an array of **ServiceAPIDescription** data. - 3. Array must contain all previously published APIs. - -## Test Case 4: Retrieve all APIs Published by NON Authorised apfId -* **Test ID**: ***capif_api_publish_service-4*** -* **Description**: - - This test case will check that an API Publisher cannot Retrieve API published when apfId is not authorised -* **Pre-Conditions**: - - * CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority) - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Retrieve all published APIs: - * Send Get to *https://{CAPIF_HOSTNAME}/published-apis/v1/{APF_ID_NOT_VALID}/service-apis* - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Retrieve All published APIs - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **401 Non Authorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status **401** - * title with message "Unauthorized" - * detail with message "Provider not existing". - * cause with message "Provider id not found". - - 2. Service API is NOT stored in CAPIF Database - -## Test Case 5: Retrieve single APIs Published by Authorised apfId -* **Test ID**: ***capif_api_publish_service-5*** -* **Description**: - - This test case will check that an API Publisher can Retrieve API published one by one -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) - * At least 2 service APIs are published. - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Get apiId - * Use APF Certificate - - 3. Publish Other Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_2 - * Get apiId - * Use APF Certificate - - 4. Retrieve service_1 published APIs detail: - * Send Get to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{apiId1}* - * Use APF Certificate - - 5. Retrieve service_2 published APIs detail: - * Send Get to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{apiId2}* - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Publish Service API service_1. - 3. Retrieve {apiId1} from body and Location header with new resource created from response. - 4. Publish Service API service_2. - 5. Retrieve {apiId2} from body and Location header with new resource created from response. - 6. Retrieve service_1 API Detail. - 7. Retrieve service_2 API Detail. - -* **Expected Result**: - 1. Response to service 1 Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId1}* - - 2. Response to service 2 Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId2}* - - 3. Published Service APIs are stored in CAPIF Database - - 4. Response to Retrieve service_1 published API using apiId1: - 1. **200 OK** - 2. Response body must return a **ServiceAPIDescription** data. - 3. Array must contain same information than service_1 published registration response. - - 5. Response to Retrieve service_2 published API using apiId2: - 1. **200 OK** - 2. Response body must return a **ServiceAPIDescription** data. - 3. Array must contain same information than service_2 published registration response. - - -## Test Case 6: Retrieve single APIs non Published by Authorised apfId -* **Test ID**: ***capif_api_publish_service-6*** -* **Description**: - - This test case will check that an API Publisher try to get detail of not published api. -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) - * No published api - -* **Information of Test**: - 1. Perform [Provider Registration] - 2. Retrieve not published APIs detail: - * Send Get to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}* - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Retrieve not published API Detail. - -* **Expected Result**: - 1. Response to Retrieve for NOT published API must accomplish: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status **404** - * title with message "Not Found" - * detail with message "Service API not found". - * cause with message "No Service with specific credentials exists". - - -## Test Case 7: Retrieve single APIs Published by NON Authorised apfId -* **Test ID**: ***capif_api_publish_service-7*** -* **Description**: - - This test case will check that an API Publisher cannot Retrieve detailed API published when apfId is not authorised -* **Pre-Conditions**: - - * CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority) - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Get apiId - * Use APF Certificate - - 3. Retrieve detailed published APIs: - * Send Get to *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/${apiId}* - * Use Invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Publish Service API at CCF - 3. Retrieve {apiId} from body and Location header with new resource created from response. - 4. Register and onboard Invoker at CCF - 5. Store signed Invoker Certificate - 6. Retrieve detailed published API acting as Invoker - -* **Expected Result**: - 1. Response to Retrieve Detailed published API acting as Invoker must accomplish: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status **401** - * title with message "Unauthorized" - * detail with message "User not authorized". - * cause with message "Certificate not authorized". - - 2. Service API is NOT stored in CAPIF Database - - -## Test Case 8: Update API Published by Authorised apfId with valid serviceApiId -* **Test ID**: ***capif_api_publish_service-8*** -* **Description**: - - This test case will check that an API Publisher can Update published API with a valid serviceApiId -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) - * A service APIs is published. - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Get apiId - * get resource url from location Header. - * Use APF Certificate - - 3. Update published API at CCF: - * Send PUT to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}* - * body [service api description] with overrided apiName to service_1_modified - * Use APF Certificate - - 4. Retrieve detail of service API: - * Send Get to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}* - * check apiName is service_1_modified - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Publish Service API - 3. Retrieve {apiId} from body and Location header with new resource url created from response - 4. Update published Service API. - 5. Retrieve detail of Service API - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - - 2. Response to Update Published Service API: - 1. **200 OK** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiName service_1_modified - - 3. Response to Retrieve detail of Service API: - 1. **200 OK** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiName service_1_modified. - - -## Test Case 9: Update APIs Published by Authorised apfId with invalid serviceApiId -* **Test ID**: ***capif_api_publish_service-9*** -* **Description**: - - This test case will check that an API Publisher cannot Update published API with a invalid serviceApiId -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority) - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Get apiId - * Use APF Certificate - - 3. Update published API at CCF: - * Send PUT to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}* - * body [service api description] with overrided apiName to ***service_1_modified*** - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Update published Service API. - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - - 2. Response to Update Published Service API: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status **404** - * title with message "Not Found" - * detail with message "Service API not found". - * cause with message "Service API id not found". - - ## Test Case 10: Update APIs Published by NON Authorised apfId -* **Test ID**: ***capif_api_publish_service-10*** -* **Description**: - - This test case will check that an API Publisher cannot Update API published when apfId is not authorised -* **Pre-Conditions**: - - * CAPIF subscriber is NOT pre-authorised (has invalid apfId from CAPIF Authority) - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Get apiId - * Use APF Certificate - - 3. Update published API at CCF: - * Send PUT to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - * body [service api description] with overrided apiName to ***service_1_modified*** - * Use invoker certificate - - 4. Retrieve detail of service API: - * Send Get to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}* - * check apiName is service_1 - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Publish Service API at CCF - 3. Retrieve {apiId} from body and Location header with new resource created from response. - 4. Register and onboard Invoker at CCF - 5. Store signed Invoker Certificate - 6. Update published API at CCF as Invoker - 7. Retrieve detail of Service API as publisher - -* **Expected Result**: - 1. Response to Update published API acting as Invoker must accomplish: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status **401** - * title with message "Unauthorized" - * detail with message "User not authorized". - * cause with message "Certificate not authorized". - - 2. Response to Retrieve Detail of Service API: - 1. **200 OK** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiName service_1. - - -## Test Case 11: Delete API Published by Authorised apfId with valid serviceApiId -* **Test ID**: ***capif_api_publish_service-11*** -* **Description**: - - This test case will check that an API Publisher can Delete published API with a valid serviceApiId -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority). - * A service APIs is published. - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Get apiId - * Use APF Certificate - - 3. Remove published Service API at CCF: - * Send DELETE to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - * Use APF Certificate - 4. Retrieve detail of service API: - * Send Get to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{serivceApiId}* - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Publish Service API - 3. Retrieve {apiId} from body and Location header with new resource created from response - 4. Remove published API at CCF - 5. Try to retreive deleted service API from CCF - -* **Expected Result**: - 1. Response to Publish request must accomplish: - 1. **201 Created** - 2. Response Body must follow **ServiceAPIDescription** data structure with: - * apiId - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/published-apis/v1/{apfId}/service-apis/{serviceApiId}* - - 2. Published Service API is stored in CAPIF Database - - 3. Response to Remove published Service API at CCF: - 1. **204 No Content** - - 4. Response to Retrieve for DELETED published API must accomplish: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Service API not found". - * cause with message "No Service with specific credentials exists". - - -## Test Case 12: Delete APIs Published by Authorised apfId with invalid serviceApiId -* **Test ID**: ***capif_api_publish_service-12*** -* **Description**: - - This test case will check that an API Publisher cannot Delete with invalid serviceApiId -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority). - -* **Information of Test**: - 1. Perform [Provider Registration] - - 2. Remove published Service API at CCF with invalid serviceId: - * Send DELETE to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}* - * Use APF Certificate - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Remove published API at CCF with invalid serviceId - -* **Expected Result**: - 1. Response to Remove published Service API at CCF: - 1. **404 Not Found** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status 404 - * title with message "Not Found" - * detail with message "Service API not found". - * cause with message "Service API id not found". - - -## Test Case 13: Delete APIs Published by NON Authorised apfId -* **Test ID**: ***capif_api_publish_service-12*** -* **Description**: - - This test case will check that an API Publisher cannot Delete API published when apfId is not authorised -* **Pre-Conditions**: - - * CAPIF subscriber is pre-authorised (has valid apfId from CAPIF Authority). - -* **Information of Test**: - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis* - * body [service api description] with apiName service_1 - * Get apiId - * Use APF Certificate - - 3. Remove published Service API at CCF with invalid serviceId as Invoker: - * Send DELETE to resource URL *https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis/{SERVICE_API_ID_NOT_VALID}* - * Use invoker certificate. - -* **Execution Steps**: - 1. Register Provider at CCF and store certificates. - 2. Register Invoker and onboard Invoker at CCF - 3. Remove published API at CCF with invalid serviceId as Invoker - -* **Expected Result**: - 1. Response to Remove published Service API at CCF: - 1. **401 Unauthorized** - 2. Error Response Body must accomplish with **ProblemDetails** data structure with: - * status **401** - * title with message "Unauthorized" - * detail with message "User not authorized". - * cause with message "Certificate not authorized". - - - [service api description]: ./service_api_description_post_example.json "Service API Description Request" - [publisher register body]: ./publisher_register_body.json "Publish register Body" - [invoker onboarding body]: ../api_invoker_management/invoker_details_post_example.json "API Invoker Request" - [invoker register body]: ../api_invoker_management/invoker_register_body.json "Invoker Register Body" - [provider request body]: ../api_provider_management/provider_details_post_example.json "API Provider Enrolment Request" - [provider request patch body]: ../api_provider_management/provider_details_enrolment_details_patch_example.json "API Provider Enrolment Patch Request" - [provider getauth body]: ../api_provider_management/provider_getauth_example.json "Get Auth Example" - - [invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" - [provider registration]: ../common_operations/README.md#register-a-provider "Provider Registration" - - - [Return To All Test Plans]: ../README.md \ No newline at end of file diff --git a/docs/test_plan/api_publish_service/publisher_register_body.json b/docs/test_plan/api_publish_service/publisher_register_body.json deleted file mode 100644 index fc26db2141eab904b1f2f8d96e963f2ec0efcbe1..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_publish_service/publisher_register_body.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "password": "password", - "username": "ROBOT_TESTING_PUBLISHER", - "role": "provider", - "description": "Testing", - "cn": "ROBOT_TESTING_PUBLISHER" -} diff --git a/docs/test_plan/api_publish_service/service_api_description_post_example.json b/docs/test_plan/api_publish_service/service_api_description_post_example.json deleted file mode 100644 index b725b428629509bf39a79c030f1bf93f4b6f18f6..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_publish_service/service_api_description_post_example.json +++ /dev/null @@ -1,113 +0,0 @@ -{ - "apiName": "service_1", - "aefProfiles": [ - { - "aefId": "string", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "string", - "commType": "REQUEST_RESPONSE", - "uri": "string", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - } - ] - }, - { - "aefId": "string", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "string", - "commType": "REQUEST_RESPONSE", - "uri": "string", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - } - ] - } - ], - "description": "string", - "supportedFeatures": "fffff", - "shareableInfo": { - "isShareable": true, - "capifProvDoms": [ - "string" - ] - }, - "serviceAPICategory": "string", - "apiSuppFeats": "fffff", - "pubApiPath": { - "ccfIds": [ - "string" - ] - }, - "ccfId": "string" -} \ No newline at end of file diff --git a/docs/test_plan/api_security_service/README.md b/docs/test_plan/api_security_service/README.md deleted file mode 100644 index c0d3e71b06da6e40e9fdaeff50064ad230b76c57..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_security_service/README.md +++ /dev/null @@ -1,1244 +0,0 @@ -[**[Return To All Test Plans]**] - -- [Test Plan for CAPIF Api Security Service](#test-plan-for-capif-api-security-service) -- [Tests](#tests) - - [Test Case 1: Create a security context for an API invoker](#test-case-1-create-a-security-context-for-an-api-invoker) - - [Test Case 2: Create a security context for an API invoker with Provider role](#test-case-2-create-a-security-context-for-an-api-invoker-with-provider-role) - - [Test Case 3: Create a security context for an API invoker with Provider entity role and invalid apiInvokerId](#test-case-3-create-a-security-context-for-an-api-invoker-with-provider-entity-role-and-invalid-apiinvokerid) - - [Test Case 4: Create a security context for an API invoker with Invoker entity role and invalid apiInvokerId](#test-case-4-create-a-security-context-for-an-api-invoker-with-invoker-entity-role-and-invalid-apiinvokerid) - - [Test Case 5: Retrieve the Security Context of an API Invoker](#test-case-5-retrieve-the-security-context-of-an-api-invoker) - - [Test Case 6: Retrieve the Security Context of an API Invoker with invalid apiInvokerID](#test-case-6-retrieve-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid) - - [Test Case 7: Retrieve the Security Context of an API Invoker with invalid apfId](#test-case-7-retrieve-the-security-context-of-an-api-invoker-with-invalid-apfid) - - [Test Case 8: Delete the Security Context of an API Invoker](#test-case-8-delete-the-security-context-of-an-api-invoker) - - [Test Case 9: Delete the Security Context of an API Invoker with Invoker entity role](#test-case-9-delete-the-security-context-of-an-api-invoker-with-invoker-entity-role) - - [Test Case 10: Delete the Security Context of an API Invoker with Invoker entity role and invalid apiInvokerID](#test-case-10-delete-the-security-context-of-an-api-invoker-with-invoker-entity-role-and-invalid-apiinvokerid) - - [Test Case 11: Delete the Security Context of an API Invoker with invalid apiInvokerID](#test-case-11-delete-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid) - - [Test Case 12: Update the Security Context of an API Invoker](#test-case-12-update-the-security-context-of-an-api-invoker) - - [Test Case 13: Update the Security Context of an API Invoker with Provider entity role](#test-case-13-update-the-security-context-of-an-api-invoker-with-provider-entity-role) - - [Test Case 14: Update the Security Context of an API Invoker with AEF entity role and invalid apiInvokerId](#test-case-14-update-the-security-context-of-an-api-invoker-with-aef-entity-role-and-invalid-apiinvokerid) - - [Test Case 15: Update the Security Context of an API Invoker with invalid apiInvokerID](#test-case-15-update-the-security-context-of-an-api-invoker-with-invalid-apiinvokerid) - - [Test Case 16: Revoke the authorization of the API invoker for APIs.](#test-case-16-revoke-the-authorization-of-the-api-invoker-for-apis) - - [Test Case 17: Revoke the authorization of the API invoker for APIs without valid apfID.](#test-case-17-revoke-the-authorization-of-the-api-invoker-for-apis-without-valid-apfid) - - [Test Case 18: Revoke the authorization of the API invoker for APIs with invalid apiInvokerId.](#test-case-18-revoke-the-authorization-of-the-api-invoker-for-apis-with-invalid-apiinvokerid) - - [Test Case 19: Retrieve access token](#test-case-19-retrieve-access-token) - - [Test Case 20: Retrieve access token by Provider](#test-case-20-retrieve-access-token-by-provider) - - [Test Case 21: Retrieve access token by Provider with invalid apiInvokerId](#test-case-21-retrieve-access-token-by-provider-with-invalid-apiinvokerid) - - [Test Case 22: Retrieve access token with invalid apiInvokerId](#test-case-22-retrieve-access-token-with-invalid-apiinvokerid) - - [Test Case 23: Retrieve access token with invalid client\_id](#test-case-23-retrieve-access-token-with-invalid-client_id) - - [Test Case 24: Retrieve access token with unsupported grant\_type](#test-case-24-retrieve-access-token-with-unsupported-grant_type) - - [Test Case 25: Retrieve access token with invalid scope](#test-case-25-retrieve-access-token-with-invalid-scope) - - [Test Case 26: Retrieve access token with invalid aefid at scope](#test-case-26-retrieve-access-token-with-invalid-aefid-at-scope) - - [Test Case 27: Retrieve access token with invalid apiName at scope](#test-case-27-retrieve-access-token-with-invalid-apiname-at-scope) - - - -# Test Plan for CAPIF Api Security Service -At this documentation you will have all information and related files and examples of test plan for this API. - -# Tests - -## Test Case 1: Create a security context for an API invoker -* **Test ID**: ***capif_security_api-1*** -* **Description**: - - This test case will check that an API Invoker can create a Security context -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) - -* **Information of Test**: - 1. Perform [Invoker Onboarding] - 2. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Use Invoker Certificate - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Store signed Certificate - 3. Create Security Context - -* **Expected Result**: - - 1. Create security context: - 1. **201 Created** response. - 2. body returned must accomplish **ServiceSecurity** data structure. - 3. Location Header must contain the new resource URL *{apiRoot}/capif-security/v1/trustedInvokers/{apiInvokerId}* - - -## Test Case 2: Create a security context for an API invoker with Provider role -* **Test ID**: ***capif_security_api-2*** -* **Description**: - - This test case will check that an Provider cannot create a Security context with valid apiInvokerId. -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with Provider role - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker but using Provider certificate. - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using AEF certificate - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Register Provider at CCF - 3. Create Security Context using Provider certificate - -* **Expected Result**: - - 1. Create security context using Provider certificate: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **401** - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "User role must be invoker". - - 2. No context stored at DB - -## Test Case 3: Create a security context for an API invoker with Provider entity role and invalid apiInvokerId -* **Test ID**: ***capif_security_api-3*** -* **Description**: - - This test case will check that an Provider cannot create a Security context with invalid apiInvokerID. -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with Provider role - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Create Security Context for this not valid apiInvokerId and using Provider certificate. - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* - * body [service security body] - * Using AEF certificate - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Create Security Context using Provider certificate - -* **Expected Result**: - - 1. Create security context using Provider certificate: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **401** - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "User role must be invoker". - 2. No context stored at DB - -## Test Case 4: Create a security context for an API invoker with Invoker entity role and invalid apiInvokerId -* **Test ID**: ***capif_security_api-4*** -* **Description**: - - This test case will check that an Invoker cannot create a Security context with valid apiInvokerId. -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID), but user that create Security Context with invalid apiInvokerId - -* **Information of Test**: - 1. Perform [Invoker Onboarding] - - 2. Create Security Context for this Invoker: - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* - * body [service security body] - * Use Invoker Certificate - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Create Security Context using Provider certificate - -* **Expected Result**: - - 1. Create security context using Provider certificate: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **404** - * title with message "Not Found" - * detail with message "Invoker not found". - * cause with message "API Invoker not exists or invalid ID". - - 2. No context stored at DB - - -## Test Case 5: Retrieve the Security Context of an API Invoker -* **Test ID**: ***capif_security_api-5*** -* **Description**: - - This test case will check that an provider can retrieve the Security context of an API Invoker -* **Pre-Conditions**: - - * Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker. - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker certificate - - 3. Retrieve Security Context of Invoker by Provider: - * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * Using AEF Certificate - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Register Provider at CCF - 3. Create Security Context using Provider certificate - 4. Retrieve Security Context by Provider - -* **Expected Result**: - 1. Retrieve security context: - 1. **200 OK** response. - 2. body returned must accomplish **ServiceSecurity** data structure. - - -## Test Case 6: Retrieve the Security Context of an API Invoker with invalid apiInvokerID -* **Test ID**: ***capif_security_api-6*** -* **Description**: - - This test case will check that an provider can retrieve the Security context of an API Invoker -* **Pre-Conditions**: - - * Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Retrieve Security Context of invalid Invoker by Provider: - * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* - * Using AEF Certificate. - -* **Execution Steps**: - - 2. Register Provider at CCF - 3. Create Security Context using Provider certificate - 4. Retrieve Security Context by Provider of invalid invoker - -* **Expected Result**: - 1. Retrieve security context: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **404** - * title with message "Not Found" - * detail with message "Invoker not found". - * cause with message "API Invoker not exists or invalid ID". - - -## Test Case 7: Retrieve the Security Context of an API Invoker with invalid apfId -* **Test ID**: ***capif_security_api-7*** -* **Description**: - - This test case will check that an Provider cannot retrieve the Security context of an API Invoker without valid apfId -* **Pre-Conditions**: - - * API Exposure Function is not pre-authorised (has invalid apfId) - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate - - 3. Retrieve Security Context as Invoker role: - * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * Using Invoker Certificate - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Store signed Certificate - 3. Create Security Context - 4. Retrieve Security Context as Provider. - -* **Expected Result**: - - 1. Create security context: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **401** - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "User role must be aef". - - -## Test Case 8: Delete the Security Context of an API Invoker -* **Test ID**: ***capif_security_api-8*** -* **Description**: - - This test case will check that an Provider can delete a Security context -* **Pre-Conditions**: - - * Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker but using Provider certificate. - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using AEF certificate - - 3. Delete Security Context of Invoker by Provider: - * Send DELETE *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * Use AEF certificate - - 4. Retrieve Security Context of Invoker by Provider: - * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * Using AEF Certificate - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Register Provider at CCF - 3. Create Security Context using Provider certificate - 4. Delete Security Context by Provider - -* **Expected Result**: - - 1. Delete security context: - 1. **204 No Content** response. - - 2. Retrieve security context: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **404** - * title with message "Not Found" - * detail with message "Security context not found". - * cause with message "API Invoker not exists or invalid ID". - - -## Test Case 9: Delete the Security Context of an API Invoker with Invoker entity role -* **Test ID**: ***capif_security_api-9*** -* **Description**: - - This test case will check that an Invoker cannot delete a Security context -* **Pre-Conditions**: - - * Provider is pre-authorised (has valid apfId from CAPIF Authority) and API Invoker has created a valid Security Context - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker: - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker certificate - - 3. Delete Security Context of Invoker: - * Send DELETE *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * Use Invoker certificate - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Create Security Context using Provider certificate - 3. Delete Security Context by Invoker - -* **Expected Result**: - - 1. Delete security context: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **401** - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "User role must be aef". - - -## Test Case 10: Delete the Security Context of an API Invoker with Invoker entity role and invalid apiInvokerID -* **Test ID**: ***capif_security_api-10*** -* **Description**: - - This test case will check that an Invoker cannot delete a Security context with invalid -* **Pre-Conditions**: - - * Invoker is pre-authorised. - -* **Information of Test**: - - 1. Perform [Invoker Onboarding] - - 2. Delete Security Context of Invoker: - * Send DELETE *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* - * Use Invoker certificate - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Delete Security Context by invoker - -* **Expected Result**: - - 1. Delete security context: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **401** - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "User role must be aef". - - -## Test Case 11: Delete the Security Context of an API Invoker with invalid apiInvokerID -* **Test ID**: ***capif_security_api-11*** -* **Description**: - - This test case will check that an Provider cannot delete a Security context of invalid apiInvokerId -* **Pre-Conditions**: - - * Provider is pre-authorised (has valid apfId from CAPIF Authority). - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 2. Delete Security Context of Invoker by Provider: - * Send DELETE *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}* - * Use AEF certificate - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Delete Security Context by provider - -* **Expected Result**: - - 1. Retrieve security context: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **404** - * title with message "Not Found" - * detail with message "Invoker not found". - * cause with message "API Invoker not exists or invalid ID". - - -## Test Case 12: Update the Security Context of an API Invoker -* **Test ID**: ***capif_security_api-12*** -* **Description**: - - This test case will check that an API Invoker can update a Security context -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker: - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - - 3. Update Security Context of Invoker: - * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/update* - * body [service security body] but with notification destination modified to http://robot.testing2 - * Using Invoker Certificate. - - 4. Retrieve Security Context of Invoker by Provider: - * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * Using AEF Certificate. - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Register Provider at CCF - 3. Create Security Context By Invoker - 4. Update Security Context By Invoker - 5. Retrieve Security Context By Provider - -* **Expected Result**: - - 1. Update security context: - 1. **200 OK** response. - 2. body returned must accomplish **ServiceSecurity** data structure. - - 2. Retrieve security context: - 1. **200 OK** response. - 2. body returned must accomplish **ServiceSecurity** data structure. - 1. Check is this returned object match with modified one. - - -## Test Case 13: Update the Security Context of an API Invoker with Provider entity role -* **Test ID**: ***capif_security_api-13*** -* **Description**: - - This test case will check that an Provider cannot update a Security context - -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized. - * Invoker has created the Security Context previously. - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker: - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - - 3. Update Security Context of Invoker by Provider: - * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/update* - * body [service security body] but with notification destination modified to http://robot.testing2 - * Using AEF Certificate - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Register Provider at CCF - 3. Create Security Context - 4. Update Security Context as Provider - -* **Expected Result**: - - 1. Update security context: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **401** - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "User role must be invoker". - - -## Test Case 14: Update the Security Context of an API Invoker with AEF entity role and invalid apiInvokerId -* **Test ID**: ***capif_security_api-14*** -* **Description**: - - This test case will check that an Provider cannot update a Security context of invalid apiInvokerId - -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized. - * Invoker has created the Security Context previously. - -* **Information of Test**: - - 1. Perform [Provider Registration] - - 4. Update Security Context of Invoker by Provider: - * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/update* - * body [service security body] - * Using AEF Certificate - -* **Execution Steps**: - - 1. Register Provider at CCF - 2. Update Security Context as Provider - -* **Expected Result**: - - 1. Update security context: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **401** - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "User role must be invoker". - - -## Test Case 15: Update the Security Context of an API Invoker with invalid apiInvokerID -* **Test ID**: ***capif_security_api-15*** -* **Description**: - - This test case will check that an API Invoker cannot update a Security context not valid apiInvokerId -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Update Security Context of Invoker: - * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/update* - * body [service security body] - * Using Invoker Certificate. - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Update Security Context - -* **Expected Result**: - -1. Retrieve security context: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **404** - * title with message "Not Found" - * detail with message "Invoker not found". - * cause with message "API Invoker not exists or invalid ID". - - -## Test Case 16: Revoke the authorization of the API invoker for APIs. -* **Test ID**: ***capif_security_api-16*** -* **Description**: - - This test case will check that a Provider can revoke the authorization for APIs - -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context By Invoker: - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate - - 3. Revoke Authorization by Provider: - * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete* - * body [security notification body] - * Using AEF Certificate. - - 4. Retrieve Security Context by Provider: - * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * Using AEF Certificate. - - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Register Provider at CCF - 3. Create Security Context by Invoker - 4. Revoke Security Context by Provider - 5. Retrieve Security Context by Provider - -* **Expected Result**: - - 1. Revoke Authorization: - 1. **204 No Content** response. - - 2. Retrieve security context: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **404** - * title with message "Not Found" - * detail with message "Security context not found". - * cause with message "API Invoker has no security context". - - -## Test Case 17: Revoke the authorization of the API invoker for APIs without valid apfID. -* **Test ID**: ***capif_security_api-17*** -* **Description**: - - This test case will check that an Invoker can't revoke the authorization for APIs - -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker: - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - - 3. Revoke Authorization by invoker: - * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}/delete* - * body [security notification body] - * Using Invoker Certificate - - 4. Retrieve Security Context of Invoker by Provider: - * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * Using Provider Certificate - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Register Provider at CCF - 3. Create Security Context - 4. Revoke Security Context by invoker - 5. Retrieve Security Context - -* **Expected Result**: - - 1. Revoke Security Context by invoker: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **401** - * title with message "Unauthorized" - * detail with message "Role not authorized for this API route". - * cause with message "User role must be provider". - - 3. Retrieve security context: - 1. **200 OK** response. - 2. body returned must accomplish **ServiceSecurity** data structure. - 1. Check is this returned object match with created one. - - -## Test Case 18: Revoke the authorization of the API invoker for APIs with invalid apiInvokerId. -* **Test ID**: ***capif_security_api-18*** -* **Description**: - - This test case will check that an API Exposure Function cannot revoke the authorization for APIs for invalid apiInvokerId - -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Create Security Context for this Invoker: - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - - 3. Revoke Authorization by Provider: - * Send POST *https://{CAPIF_HOSTNAME}/trustedInvokers/{API_INVOKER_NOT_VALID}/delete* - * body [security notification body] - * Using AEF Certificate. - - 4. Retrieve Security Context of Invoker by Provider: - * Send GET *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}?authenticationInfo=true&authorizationInfo=true* - * This request will ask with parameter to retrieve authenticationInfo and authorizationInfo - * Using AEF Certificate. - -* **Execution Steps**: - - 1. Register and onboard Invoker at CCF - 2. Register Provider at CCF - 3. Create Security Context - 4. Revoke Security Context by Provider - 5. Retrieve Security Context - -* **Expected Result**: - - 1. Revoke Security Context by invoker: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails** data structure, with: - * status **404** - * title with message "Not Found" - * detail with message "Invoker not found". - * cause with message "API Invoker not exists or invalid ID". - - 3. Retrieve security context: - 1. **200 OK** response. - 2. body returned must accomplish **ServiceSecurity** data structure. - 1. Check is this return one object that match with created one. - - -## Test Case 19: Retrieve access token -* **Test ID**: ***capif_security_api-19*** -* **Description**: - - This test case will check that an API Invoker can retrieve a security access token OAuth 2.0. -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerId) - * Service API of Provider is published - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - - 5. Request Access Token by invoker: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*: - * body [access token req body] and example [example] - * ***securityId*** is apiInvokerId. - * ***grant_type=client_credentials***. - * Create Scope properly for request: ***3gpp#{aef_id}:{api_name}*** - * Using Invoker Certificate. - -* **Execution Steps**: - - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **200 OK** - 2. body must follow **AccessTokenRsp** with: - 1. access_token present - 2. token_type=Bearer - -## Test Case 20: Retrieve access token by Provider -* **Test ID**: ***capif_security_api-20*** -* **Description**: - - This test case will check that an API Exposure Function cannot revoke the authorization for APIs for invalid apiInvokerId - -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerID from CAPIF Authority) and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - - 5. Request Access Token by provider: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*: - * body [access token req body] - * ***securityId*** is apiInvokerId - * ***grant_type=client_credentials*** - * Using AEF certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token by Provider - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **AccessTokenErr** data structure, with: - * error unauthorized_client - * error_description=Role not authorized for this API route - -## Test Case 21: Retrieve access token by Provider with invalid apiInvokerId -* **Test ID**: ***capif_security_api-21*** -* **Description**: - - This test case will check that an API Exposure Function cannot retrieve a security access token without valid apiInvokerId - -* **Pre-Conditions**: - - * API Invoker is pre-authorised and Provider is also authorized - - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - - 5. Request Access Token by provider: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{API_INVOKER_NOT_VALID}/token*. - * body [access token req body] - * ***securityId*** is apiInvokerId - * ***grant_type=client_credentials*** - * Using AEF certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token by Provider - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **401 Unauthorized** response. - 2. body returned must accomplish **AccessTokenErr** data structure, with: - * error unauthorized_client - * error_description=Role not authorized for this API route - - -## Test Case 22: Retrieve access token with invalid apiInvokerId -* **Test ID**: ***capif_security_api-22*** -* **Description**: - - This test case will check that an API Invoker can't retrieve a security access token without valid apiInvokerId - -* **Pre-Conditions**: - - * API Invoker is pre-authorised (has valid apiInvokerId) - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - 5. Request Access Token by invoker: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{API_INVOKER_NOT_VALID}/token*. - * body [access token req body] - * ***securityId*** is apiInvokerId - * ***grant_type=client_credentials*** - * Using Invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token by Invoker - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **404 Not Found** response. - 2. body returned must accomplish **ProblemDetails29571** data structure, with: - * status 404 - * title Not Found - * detail Security context not found - * cause API Invoker has no security context - - -**NOTE: ProblemDetails29571 is the definition present for this request at swagger of ProblemDetails, and this is different from definition of ProblemDetails across other CAPIF Services** - -## Test Case 23: Retrieve access token with invalid client_id -* **Test ID**: ***capif_security_api-23*** -* **Description**: - - This test case will check that an API Exposure Function cannot retrieve a security access token without valid client_id at body - -* **Pre-Conditions**: - - * API Invoker is pre-authorised and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - - 5. Request Access Token by invoker: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. - * body [access token req body] - * ***securityId*** is apiInvokerId - * ***grant_type=client_credentials*** - * **client_id is not-valid** - * Using Invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token by Invoker - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **400 Bad Request** response. - 2. body returned must accomplish **AccessTokenErr** data structure, with: - * error invalid_client - * error_description=Client Id not found - - -## Test Case 24: Retrieve access token with unsupported grant_type -* **Test ID**: ***capif_security_api-24*** -* **Description**: - - This test case will check that an API Exposure Function cannot retrieve a security access token with unsupported grant_type - -* **Pre-Conditions**: - - * API Invoker is pre-authorised and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - - 5. Request Access Token by invoker: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. - * body [access token req body] - * ***securityId*** is apiInvokerId - * ***grant_type=not_valid*** - * Using Invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token by Invoker - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **400 Bad Request** response. - 2. body returned must accomplish **AccessTokenErr** data structure, with: - * error unsupported_grant_type - * error_description=Invalid value for `grant_type` \\(${grant_type}\\), must be one of \\['client_credentials'\\] - 'grant_type' - -## Test Case 25: Retrieve access token with invalid scope -* **Test ID**: ***capif_security_api-25*** -* **Description**: - - This test case will check that an API Exposure Function cannot retrieve a security access token with complete invalid scope - -* **Pre-Conditions**: - - * API Invoker is pre-authorised and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - - 5. Request Access Token by invoker: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. - * body [access token req body] - * ***securityId*** is apiInvokerId - * ***grant_type=client_credentials*** - * ***scope=not-valid-scope*** - * Using Invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token by Invoker - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **400 Bad Request** response. - 2. body returned must accomplish **AccessTokenErr** data structure, with: - * error invalid_scope - * error_description=The first characters must be '3gpp' - - -## Test Case 26: Retrieve access token with invalid aefid at scope -* **Test ID**: ***capif_security_api-26*** -* **Description**: - - This test case will check that an API Exposure Function cannot retrieve a security access token with invalid aefId at scope - -* **Pre-Conditions**: - - * API Invoker is pre-authorised and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - - 5. Request Access Token by invoker: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. - * body [access token req body] - * ***securityId*** is apiInvokerId - * ***grant_type=client_credentials*** - * ***scope=3gpp#1234:service_1*** - * Using Invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token by Invoker - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **400 Bad Request** response. - 2. body returned must accomplish **AccessTokenErr** data structure, with: - * error invalid_scope - * error_description=One of aef_id not belongs of your security context - - -## Test Case 27: Retrieve access token with invalid apiName at scope -* **Test ID**: ***capif_security_api-27*** -* **Description**: - - This test case will check that an API Exposure Function cannot retrieve a security access token with invalid apiName at scope - -* **Pre-Conditions**: - - * API Invoker is pre-authorised and Provider is also authorized - -* **Information of Test**: - - 1. Perform [Provider Registration] and [Invoker Onboarding] - - 2. Publish Service API at CCF: - * Send Post to ccf_publish_url https://{CAPIF_HOSTNAME}/published-apis/v1/{apfId}/service-apis - * body [service api description] with apiName service_1 - * Use APF Certificate - - 3. Request Discover Published APIs not filtered: - * Send GET to ccf_discover_url *https://{CAPIF_HOSTNAME}/service-apis/v1/allServiceAPIs?api-invoker-id={apiInvokerId}* - * Param api-invoker-id is mandatory - * Using invoker certificate - - 4. Create Security Context for this Invoker - * Send PUT *https://{CAPIF_HOSTNAME}/trustedInvokers/{apiInvokerId}* - * body [service security body] - * Using Invoker Certificate. - * Create Security Information Body with one **securityInfo** for each aef present at each serviceAPIDescription present at Discover. - - 5. Request Access Token by invoker: - * Sent POST *https://{CAPIF_HOSTNAME}/securities/{securityId}/token*. - * body [access token req body] - * ***securityId*** is apiInvokerId - * ***grant_type=client_credentials*** - * ***scope=3gpp#{aef_id}:not-valid*** - * Using Invoker certificate - -* **Execution Steps**: - 1. Register Provider at CCF, store certificates and Publish Service API service_1 at CCF - 2. Register and onboard Invoker at CCF - 3. Discover Service APIs by Invoker. - 4. Create Security Context According to Service APIs discovered. - 5. Request Access Token by Invoker - -* **Expected Result**: - - 1. Response to Request of Access Token: - 1. **400 Bad Request** response. - 2. body returned must accomplish **AccessTokenErr** data structure, with: - * error invalid_scope - * error_description=One of the api names does not exist or is not associated with the aef id provided - - - [Return To All Test Plans]: ../README.md - - - - [service security body]: ./service_security.json "Service Security Request" - [security notification body]: ./security_notification.json "Security Notification Request" - [access token req body]: ./access_token_req.json "Access Token Request" - [example]: ./access_token_req.json "Access Token Request Example" - - [invoker onboarding]: ../common_operations/README.md#register-an-invoker "Invoker Onboarding" - [provider registration]: ../common_operations/README.md#register-a-provider "Provider Registration" - - diff --git a/docs/test_plan/api_security_service/access_token_req.json b/docs/test_plan/api_security_service/access_token_req.json deleted file mode 100644 index 8504736e1fb40d49c3bcb4c6a8bca4dbb6d9f855..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_security_service/access_token_req.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "client_id": "client_id", - "client_secret": "client_secret", - "grant_type": "client_credentials", - "scope": "scope" -} \ No newline at end of file diff --git a/docs/test_plan/api_security_service/access_token_req_example.json b/docs/test_plan/api_security_service/access_token_req_example.json deleted file mode 100644 index 070a717db975b76a80792117b50957ce4267cf6b..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_security_service/access_token_req_example.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "client_id": "bb260b4d0b3a0f954fa23f42d979ca", - "grant_type": "client_credentials", - "scope": "3gpp#af7e4cf70063814770e7b00b87273e:service_1" -} diff --git a/docs/test_plan/api_security_service/security_notification.json b/docs/test_plan/api_security_service/security_notification.json deleted file mode 100644 index 6b94eb5497ed8b6bde547dda6a4abc71783bc998..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_security_service/security_notification.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "aefId": "aefId", - "apiIds": [ - "apiIds", - "apiIds" - ], - "apiInvokerId": "api_invoker_id", - "cause": "OVERLIMIT_USAGE" -} \ No newline at end of file diff --git a/docs/test_plan/api_security_service/service_security.json b/docs/test_plan/api_security_service/service_security.json deleted file mode 100644 index ad7bc1ad5c64f6dc979a294044b5b44f5f43c68a..0000000000000000000000000000000000000000 --- a/docs/test_plan/api_security_service/service_security.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "notificationDestination": "http://robot.testing", - "supportedFeatures": "fffffff", - "securityInfo": [{ - "authenticationInfo": "authenticationInfo", - "authorizationInfo": "authorizationInfo", - "interfaceDetails": { - "ipv4Addr": "127.0.0.1", - "securityMethods": ["PSK"], - "port": 5248 - }, - "prefSecurityMethods": ["PSK", "PKI", "OAUTH"], - }, - { - "authenticationInfo": "authenticationInfo", - "authorizationInfo": "authorizationInfo", - "prefSecurityMethods": ["PSK", "PKI", "OAUTH"], - "aefId": "aefId" - }], - "websockNotifConfig": { - "requestWebsocketUri": true, - "websocketUri": "websocketUri" - }, - "requestTestNotification": true -} diff --git a/docs/test_plan/common_operations/README.md b/docs/test_plan/common_operations/README.md deleted file mode 100644 index ff39d943278ac7760f370dac2810fde776a28d5d..0000000000000000000000000000000000000000 --- a/docs/test_plan/common_operations/README.md +++ /dev/null @@ -1,86 +0,0 @@ - -# Register an Invoker - -## Steps to perform operation - 1. Create public and private key at invoker - 2. Register of Invoker at CCF: - * Send POST to http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register - * Body [invoker register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [invoker getauth body] - - 4. Onboard Invoker: - * Send POST to https://{CAPIF_HOSTNAME}/api-invoker-management/v1/onboardedInvokers - * Reference Request Body: [invoker onboarding body] - * "onboardingInformation"->"apiInvokerPublicKey": must contain public key generated by Invoker. - * Send at Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token}) - -## Checks to ensure onboarding - 1. Response to Register: - 1. **201 Created** - - 2. Response to Get Auth: - 1. **200 OK** - 2. ***access_token*** returned. - - 3. Response to Onboard request must accomplish: - 1. **201 Created** - 2. Response Body must follow **APIInvokerEnrolmentDetails** data structure with: - * apiInvokerId - * onboardingInformation->apiInvokerCertificate must contain the public key signed. - 3. Response Header **Location** must be received with URI to new resource created, following this structure: *{apiRoot}/api-invoker-management/{apiVersion}/onboardedInvokers/{onboardingId}* - - -# Register a Provider - -## Steps to Perform operation - 1. Create public and private key at provider for provider itself and each function (apf, aef and amf) - 2. Register of Provider at CCF: - * Send POST to *http://{CAPIF_HOSTNAME}:{CAPIF_HTTP_PORT}/register* - * body [provider register body] - - 3. Obtain Access Token: - * Send POST to *http://{CAPIF_HOSTNAME}/getauth* - * Body [provider getauth body] - - 4. Register Provider: - * Send POST *https://{CAPIF_HOSTNAME}/api-provider-management/v1/registrations* - * body [provider request body] - * Send at Authorization Header the Bearer access_token obtained previously (Authorization:Bearer ${access_token}) - * Store each cert in a file with according name. - -## Checks to ensure provider registration - 1. Response to Register: - 1. **201 Created** - - 2. Response to Get Auth: - 1. **200 OK** - 2. ***access_token*** returned. - - 3. Register Provider at Provider Management: - 1. **201 Created** response. - 2. body returned must accomplish **APIProviderEnrolmentDetails** data structure. - 3. For each **apiProvFuncs**, we must check: - 1. **apiProvFuncId** is set - 2. **apiProvCert** under **regInfo** is set properly - 4. Location Header must contain the new resource URL *{apiRoot}/api-provider-management/v1/registrations/{registrationId}* - - - - - -[invoker register body]: ../api_invoker_management/invoker_register_body.json "Invoker Register Body" -[invoker onboarding body]: ../api_invoker_management/invoker_details_post_example.json "API Invoker Request" -[invoker getauth body]: ../api_invoker_management/invoker_getauth_example.json "Get Auth Example" - -[provider register body]: ../api_provider_management/provider_register_body.json "Provider Register Body" -[provider request body]: ../api_provider_management/provider_details_post_example.json "API Provider Enrolment Request" -[provider getauth body]: ../api_provider_management/provider_getauth_example.json "Get Auth Example" - - - - - -[Return To All Test Plans]: ../README.md diff --git a/docs/testing_with_curl/README.md b/docs/testing_with_curl/README.md deleted file mode 100644 index 0903b8ba0f1dbac8703517160bee96752ecc857d..0000000000000000000000000000000000000000 --- a/docs/testing_with_curl/README.md +++ /dev/null @@ -1,369 +0,0 @@ -[**[Return To Main]**] -# Testing Using Curl - -- [Testing Using Curl](#testing-using-curl) - - [cURL scripts (TLS supported)](#curl-scripts-tls-supported) - - [cURL manual execution](#curl-manual-execution) - - [Authentication](#authentication) - - [Invoker](#invoker) - - [Provider](#provider) - - [JWT Authentication APIs](#jwt-authentication-apis) - - [Register an entity](#register-an-entity) - - [Get access token for an existing entity](#get-access-token-for-an-existing-entity) - - [Retrieve and store CA certificate](#retrieve-and-store-ca-certificate) - - [Sign provider certificate](#sign-provider-certificate) - - [Invoker Management APIs](#invoker-management-apis) - - [Onboard an Invoker](#onboard-an-invoker) - - [Update Invoker Details](#update-invoker-details) - - [Offboard an Invoker](#offboard-an-invoker) - - [Publish APIs](#publish-apis) - - [Publish a new API.](#publish-a-new-api) - - [Update a published service API.](#update-a-published-service-api) - - [Unpublish a published service API.](#unpublish-a-published-service-api) - - [Retrieve all published APIs](#retrieve-all-published-apis) - - [Retrieve a published service API.](#retrieve-a-published-service-api) - - [Discover API](#discover-api) - - [Discover published service APIs and retrieve a collection of APIs according to certain filter criteria.](#discover-published-service-apis-and-retrieve-a-collection-of-apis-according-to-certain-filter-criteria) - -## cURL scripts (TLS supported) -Also you can follow the instructions and run the commands of the bash scripts: -* [provider](./capif_tls_curls_exposer.sh) to test CAPIF as provider with TLS support. -* [invoker](./capif_tls_curls_invoker.sh) to test CAPIF as invoker with TLS support. - -## cURL manual execution - -### Authentication -This version will use TLS communication, for that purpose we have 2 different scenarios, according to role: -* Invoker -* Provider - -#### Invoker -To authenticate an invoker user, we must perform next steps: -- Retrieve CA certificate from platform. [Retrieve and store CA certificate](#retrieve-and-store-ca-certificate) -- Register on the CAPIF with invoker role. [Register an entity](#register-an-entity) -- Get a Json Web Token (JWT) in order to request onboarding [Get access token for an existing entity](#get-access-token-for-an-existing-entity) -- Request onboarding adding public key to request. [Onboard an Invoker](#onboard-an-invoker) -- Store certificate signed by CAPIF platform to allow TLS onwards. - -**Flow:** - -![Flow](../images/flows/04%20-%20Invoker%20Register.png) -![Flow](../images/flows/05%20-%20Invoker%20Onboarding.png) - -#### Provider -To authenticate an provider user, we must perform next steps: -- Retrieve CA certificate from platform. [Retrieve and store CA certificate](#retrieve-and-store-ca-certificate) -- Register on the CAPIF with provider role. [Register an entity](#register-an-entity) -- Request sign the public key to CAPIF including beared with JWT. [Sign provider certificate](#sign-provider-certificate) -- Store certificate signed by CAPIF platform to allow TLS onwards. - -**Flow:** - -![Flow](../images/flows/01%20-%20Register%20of%20AEF.png) -![Flow](../images/flows/02%20-%20AEF%20API%20Provider%20registration.png) -![Flow](../images/flows/03%20-%20AEF%20Publish.png) - -### JWT Authentication APIs -These APIs are triggered by an entity (Invoker or Provider for release 1.0) to: -- register on the CAPIF Framework -- get a Json Web Token (JWT) in order to be authorized to call CAPIF APIs - -#### Register an entity -Request -```shell -curl --request POST 'http://:/register' --header 'Content-Type: application/json' --data '{ - "username":"...", - "password":"...", - "role":"...", - "description":"...", - "cn":"..." -}' -``` - -* Role: invoker or publisher -* cn: common name - -Response body -```json -{ - "id": "Entity ID", - "message": "Informative message" -} -``` - -#### Get access token for an existing entity -Request -```shell -curl --request POST 'http://:/gettoken' --header 'Content-Type: application/json' --data '{ - "username":"...", - "password":"...", - "role":"..." -}' -``` - -Response body -```json -{ - "access_token": "JSON Web Token for CAPIF APIs", - "message": "Informative message" -} -``` - -#### Retrieve and store CA certificate -```shell -curl --request GET 'http://:/ca-root' 2>/dev/null | jq -r '.certificate' -j > -``` - -#### Sign provider certificate -```shell -curl --request POST 'http:///sign-csr' --header 'Authorization: Bearer ' --header 'Content-Type: application/json' --data-raw '{ - "csr": "RAW PUBLIC KEY CREATED BY PUBLISHER", - "mode": "client", - "filename": provider -}' -``` -Response -``` json -{ - "certificate": "PUBLISHER CERTIFICATE" -} -``` -PUBLISHER CERTIFICATE value must be stored by Provider entity to next request to CAPIF (provider.crt for example) - -### Invoker Management APIs - -These APIs are triggered by a NetApp (i.e. Invoker) - -#### Onboard an Invoker - -```shell -curl --cacert --request POST 'https:///api-invoker-management/v1/onboardedInvokers' --header 'Authorization: Bearer ' --header 'Content-Type: application/json' --data-raw '{ - "notificationDestination" : "http://X:Y/netapp_callback", - "supportedFeatures" : "fffffff", - "apiInvokerInformation" : , - "websockNotifConfig" : { - "requestWebsocketUri" : true, - "websocketUri" : "websocketUri" - }, - "onboardingInformation" : { - "apiInvokerPublicKey" : - }, - "requestTestNotification" : true -}' -``` - -Response Body - -``` json -{ - "apiInvokerId": "7da0a8d4172d7d86c536c0fbc9c372", - "onboardingInformation": { - "apiInvokerPublicKey": "RAW PUBLIC KEY CREATED BY INVOKER", - "apiInvokerCertificate": "INVOKER CERTIFICATE", - "onboardingSecret": "onboardingSecret" - }, - "notificationDestination": "http://host.docker.internal:8086/netapp_callback", - "requestTestNotification": true, - ... -} -``` - -INVOKER CERTIFICATE value must be stored by Invoker entity to next request to CAPIF (invoker.crt for example) - -#### Update Invoker Details - -```shell -curl --location --request PUT 'https:///api-invoker-management/v1/onboardedInvokers/' --cert --key --cacert --header 'Content-Type: application/json' --data '{ - "notificationDestination" : "http://X:Y/netapp_callback2", - "supportedFeatures" : "fffffff", - "apiInvokerInformation" : , - "websockNotifConfig" : { - "requestWebsocketUri" : true, - "websocketUri" : "websocketUri2" - }, - "onboardingInformation" : { - "apiInvokerPublicKey" : - }, - "requestTestNotification" : true -}' -``` - -#### Offboard an Invoker - -```shell -curl --cert --key --cacert --request DELETE 'https:///api-invoker-management/v1/onboardedInvokers/' -``` - -### Publish APIs - -These APIs are triggered by the API Publishing Function (APF) of an Provider - -#### Publish a new API. -```shell -curl --cert --key --cacert --request POST 'https:///published-apis/v1//service-apis' --header 'Content-Type: application/json' --data '{ - "apiName": "3gpp-monitoring-event", - "aefProfiles": [ - { - "aefId": "string", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "string", - "commType": "REQUEST_RESPONSE", - "uri": "string", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - } - ] - } - ], - "description": "string", - "supportedFeatures": "fffff", - "shareableInfo": { - "isShareable": true, - "capifProvDoms": [ - "string" - ] - }, - "serviceAPICategory": "string", - "apiSuppFeats": "fffff", - "pubApiPath": { - "ccfIds": [ - "string" - ] - }, - "ccfId": "string" -}' -``` - -#### Update a published service API. -```shell -curl --cert --key --cacert --request PUT 'https:///published-apis/v1//service-apis/' --header 'Content-Type: application/json' --data '{ - "apiName": "3gpp-monitoring-event", - "aefProfiles": [ - { - "aefId": "string1", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "string", - "commType": "REQUEST_RESPONSE", - "uri": "string", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - } - ] - } - ], - "description": "string", - "supportedFeatures": "fffff", - "shareableInfo": { - "isShareable": true, - "capifProvDoms": [ - "string" - ] - }, - "serviceAPICategory": "string", - "apiSuppFeats": "fffff", - "pubApiPath": { - "ccfIds": [ - "string" - ] - }, - "ccfId": "string" -}' -``` - -#### Unpublish a published service API. -```shell -curl --cert --key --cacert --request DELETE 'https:///published-apis/v1//service-apis/' -``` - -#### Retrieve all published APIs -```shell -curl --cert --key --cacert --request GET 'https:///published-apis/v1//service-apis' -``` - -#### Retrieve a published service API. -```shell -curl --cert --key --cacert --request GET 'https:///published-apis/v1//service-apis/' -``` - -### Discover API - -This API is triggered by a NetApp (or Invoker) - -#### Discover published service APIs and retrieve a collection of APIs according to certain filter criteria. -```shell -curl --cert --key --cacert --request GET 'https:///service-apis/v1/allServiceAPIs?api-invoker-id=&api-name=&api-version=&aef-id=&api-cat=&supported-features=&api-supported-features=' -``` - - - -[Return To Main]: ../../README.md#using-curl \ No newline at end of file diff --git a/docs/testing_with_curl/capif_tls_curls_exposer.sh b/docs/testing_with_curl/capif_tls_curls_exposer.sh deleted file mode 100755 index 5b81712eeebf75965dc0fd6e4b38f1f6a89a1ef7..0000000000000000000000000000000000000000 --- a/docs/testing_with_curl/capif_tls_curls_exposer.sh +++ /dev/null @@ -1,205 +0,0 @@ -##### Execute Exposer curls locally - -##### Configure machine - -##### Add in /etc/hosts: 127.0.0.1 capifcore - - -##### Set environment variables -capifhost="capifcore" -capifhttpport="8080" - -exposerpk="-----BEGIN CERTIFICATE REQUEST-----\nMIIC0TCCAbkCAQAwgYsxEDAOBgNVBAMMB2V4cG9zZXIxFzAVBgNVBAoMDlRlbGVm\nb25pY2EgSStEMRMwEQYDVQQLDApJbm5vdmF0aW9uMQ8wDQYDVQQHDAZNYWRyaWQx\nDzANBgNVBAgMBk1hZHJpZDELMAkGA1UEBhMCRVMxGjAYBgkqhkiG9w0BCQEWC2lu\nbm9AdGlkLmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAkpJ7FzAI\nkzFYxLKbW54lIsQBNIQz5zQIvRZDFcrO4QLR2jQUps9giBWEDih++47JiBJyM+z1\nWkEh7b+moZhQThj7L9PKgJHRhU1oeHpSE1x/r7479J5F+CFRqFo5v9dC+2zGfP4E\nsSrNfp3MK/KQHsHhMzSt881xAHs+p2/bcM+sd/BlXC4J6E1y6Hk3ogI7kq443fcY\noUHZx9ClUSboOvXa1ZSPVxdCV6xKRraUdAKfhMGn+pYtJDsNp8Gg/BN8NXmYUzl9\ntDhjeuIxr4N38LgW3gRHLNIa8acO9eBctWw9AD20JWzFAXvvmsboBPc2wsOVcsml\ncCbisMRKX4JyKQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAIxZ1Sec9ATbqjhi\nRz4rvhX8+myXhyfEw2MQ62jz5tpH4qIVZFtn+cZvU/ULySY10WHaBijGgx8fTaMh\nvjQbc+p3PXmgtnmt1QmoOGjDTFa6vghqpxPLSUjjCUe8yj5y24gkOImY6Cv5rzzQ\nlnTMkNvnGgpDgUeiqWcQNbwwge3zkzp9bVRgogTT+EDxiFnjTTF6iUG80sRtXMGr\nD6sygLsF2zijGGfWoKRo/7aZTQxuCiCixceVFXegMfr+eACkOjV25Kso7hYBoEdP\nkgUf5PNpl5uK3/rmPIrl/TeE0SnGGfCYP7QajE9ELRsBVmVDZJb7ZxUl1A4YydFY\ni0QOM3Y=\n-----END CERTIFICATE REQUEST-----\n" - - -##### Retrieve and store CA certificate - -curl --request GET "http://$capifhost:$capifhttpport/ca-root" 2>/dev/null | jq -r '.certificate' -j > ca.crt - - -##### Register an entity - -exposerid=$(curl --request POST "http://$capifhost:$capifhttpport/register" --header 'Content-Type: application/json' --data '{ - "username":"exposer", - "password":"exposer", - "role":"exposer", - "description":"Exposer", - "cn":"exposer" -}' 2>/dev/null | jq -r '.id' -j) - - -##### Get access token - -exposertoken=$(curl --request POST "http://$capifhost:$capifhttpport/gettoken" --header 'Content-Type: application/json' --data '{ - "username":"exposer", - "password":"exposer", - "role":"exposer" -}' 2>/dev/null | jq -r '.access_token' -j) - - -##### Sign exposer certificate - -curl --request POST "http://$capifhost:$capifhttpport/sign-csr" --header "Authorization: Bearer $exposertoken" --header 'Content-Type: application/json' --data-raw "{ - \"csr\": \"$exposerpk\", - \"mode\": \"client\", - \"filename\": \"exposer\" -}" 2>/dev/null | jq -r '.certificate' -j > exposer.crt - - -##### Publish service -curl --cert exposer.crt --key exposer.key --cacert ca.crt --request POST "https://$capifhost/published-apis/v1/$exposerid/service-apis" --header 'Content-Type: application/json' --data '{ - "apiName": "3gpp-monitoring-event", - "aefProfiles": [ - { - "aefId": "string", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "string", - "commType": "REQUEST_RESPONSE", - "uri": "string", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - } - ] - } - ], - "description": "string", - "supportedFeatures": "fffff", - "shareableInfo": { - "isShareable": true, - "capifProvDoms": [ - "string" - ] - }, - "serviceAPICategory": "string", - "apiSuppFeats": "fffff", - "pubApiPath": { - "ccfIds": [ - "string" - ] - }, - "ccfId": "string" -}' > response.json - -apiserviceid=$(cat response.json | jq -r '.apiId' -j) - - -##### Update a published service API -curl --cert exposer.crt --key exposer.key --cacert ca.crt --request PUT "https://$capifhost/published-apis/v1/$exposerid/service-apis/$apiserviceid" --header 'Content-Type: application/json' --data '{ - "apiName": "3gpp-monitoring-event", - "aefProfiles": [ - { - "aefId": "string1", - "versions": [ - { - "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004Z", - "resources": [ - { - "resourceName": "string", - "commType": "REQUEST_RESPONSE", - "uri": "string", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] - } - ], - "protocol": "HTTP_1_1", - "dataFormat": "JSON", - "securityMethods": ["PSK"], - "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - } - ] - } - ], - "description": "string", - "supportedFeatures": "fffff", - "shareableInfo": { - "isShareable": true, - "capifProvDoms": [ - "string" - ] - }, - "serviceAPICategory": "string", - "apiSuppFeats": "fffff", - "pubApiPath": { - "ccfIds": [ - "string" - ] - }, - "ccfId": "string" -}' - - -##### Retrieve all published APIs - -curl --cert exposer.crt --key exposer.key --cacert ca.crt --request GET "https://$capifhost/published-apis/v1/$exposerid/service-apis" - - -##### Retrieve a published service API - -curl --cert exposer.crt --key exposer.key --cacert ca.crt --request GET "https://$capifhost/published-apis/v1/$exposerid/service-apis/$apiserviceid" - - -##### Unpublish a published service API - -curl --cert exposer.crt --key exposer.key --cacert ca.crt --request DELETE "https://$capifhost/published-apis/v1/$exposerid/service-apis/$apiserviceid" - - diff --git a/docs/testing_with_curl/capif_tls_curls_invoker.sh b/docs/testing_with_curl/capif_tls_curls_invoker.sh deleted file mode 100755 index d6c287a91ee27891cf652c65e6d5b25f8ca84a63..0000000000000000000000000000000000000000 --- a/docs/testing_with_curl/capif_tls_curls_invoker.sh +++ /dev/null @@ -1,86 +0,0 @@ -##### Execute Invoker curls locally - -##### Configure machine - -##### Add in /etc/hosts: 127.0.0.1 capifcore - - -##### Set environment variables - -capifhost="capifcore" -capifhttpport="8080" - -invokerpk="-----BEGIN CERTIFICATE REQUEST-----\nMIIC0TCCAbkCAQAwgYsxEDAOBgNVBAMMB2ludm9rZXIxFzAVBgNVBAoMDlRlbGVm\nb25pY2EgSStEMRMwEQYDVQQLDApJbm5vdmF0aW9uMQ8wDQYDVQQHDAZNYWRyaWQx\nDzANBgNVBAgMBk1hZHJpZDELMAkGA1UEBhMCRVMxGjAYBgkqhkiG9w0BCQEWC2lu\nbm9AdGlkLmVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArfITEb3/\nJ5KDt7ia2WsQrd8iSrlH8kh6D9YNPEF+KaIGQ9w8QhmOW416uvIAASzOaCKMNqgb\nCI0NqsbVF9lfaiBgB71vcwX0yKatjACn3Nl3Lnubi+tH4Jb5zGQQXOuxpMHMmgyn\nNTsSc/MeMzX3iUWqLmmhnTC31Mu1ESUPTBa+CitQAj2wYMvBS970WICKrDlxWkR8\nZZBkRBZaxMfqY21VWmREtR+Kl6GCMBtUCUBH6uWjFiOpxYbCxdygxxrA4a3IzmiO\ntXOyLs7iuOP/CLSYfk71MHX2qKlpAyjdRK2W0w0GioV90Hk4uT/YUYy9zjWWN+mm\nrQ9GBy8iRZm7YwIDAQABoAAwDQYJKoZIhvcNAQELBQADggEBAI0btA7KDMvkY4Ib\n0eMteeeT40bm11Yw8/6V48IaIPi9EpZMI+jWyCebw8PBFUs3l3ImWeO8Gma96gyf\np0WB/64MRkUSdOxUWOWGMPIMEF+BH3eiHthx+EbAETtJ0D4KzmH6raxl14qvwLS5\nwxtxPGxu/R5ue5RVJpAzzJ6OX36p05GYSzL+pTotVPpowSdoeNsV+xPgPA0diV8a\nB7Zn/ujwMpsh7IjQPKpOEkhQdxc478Si8dmRbzXkVar1Oa8/QSJ8ZAaFI4VGowjR\nmtxps7AvS5OG9iMPtFQHpqxHVO50CJU5cbsXsYdu9EipGhgIKJDKewBX7tCKk0Ot\nBLU03CY=\n-----END CERTIFICATE REQUEST-----\n" - - -##### Retrieve and store CA certificate - -curl --request GET "http://$capifhost:$capifhttpport/ca-root" 2>/dev/null | jq -r '.certificate' -j > ca.crt - - -##### Register an entity - -invokerid=$(curl --request POST "http://$capifhost:$capifhttpport/register" --header 'Content-Type: application/json' --data '{ - "username":"invoker", - "password":"invoker", - "role":"invoker", - "description":"Invoker", - "cn":"invoker" -}' 2>/dev/null | jq -r '.id' -j) - - -##### Get access token - -invokertoken=$(curl --request POST "http://$capifhost:$capifhttpport/gettoken" --header 'Content-Type: application/json' --data '{ - "username":"invoker", - "password":"invoker", - "role":"invoker" -}' 2>/dev/null | jq -r '.access_token' -j) - - -##### Onboard an Invoker - -curl --cacert ca.crt --request POST "https://$capifhost/api-invoker-management/v1/onboardedInvokers" --header "Authorization: Bearer $invokertoken" --header 'Content-Type: application/json' --data-raw "{ - \"notificationDestination\" : \"http://X:Y/netapp_callback\", - \"supportedFeatures\" : \"fffffff\", - \"apiInvokerInformation\" : \"invoker\", - \"websockNotifConfig\" : { - \"requestWebsocketUri\" : true, - \"websocketUri\" : \"websocketUri\" - }, - \"onboardingInformation\" : { - \"apiInvokerPublicKey\" : \"$invokerpk\" - }, - \"requestTestNotification\" : true -}" > response.json - -cat response.json | jq -r '.onboardingInformation.apiInvokerCertificate' -j > invoker.crt -apiinvokerid=$(cat response.json | jq -r '.apiInvokerId' -j) - - -##### Update Invoker Details - -curl --location --request PUT "https://$capifhost/api-invoker-management/v1/onboardedInvokers/$apiinvokerid" --cert invoker.crt --key invoker.key --cacert ca.crt --header 'Content-Type: application/json' --data "{ - \"notificationDestination\" : \"http://X:Y/netapp_callback2\", - \"supportedFeatures\" : \"fffffff\", - \"apiInvokerInformation\" : \"test\", - \"websockNotifConfig\" : { - \"requestWebsocketUri\" : true, - \"websocketUri\" : \"websocketUri2\" - }, - \"onboardingInformation\" : { - \"apiInvokerPublicKey\" : \"$invokerpk\" - }, - \"requestTestNotification\" : true -}" - - -##### Discover API - -curl --cert invoker.crt --key invoker.key --cacert ca.crt --request GET "https://$capifhost/service-apis/v1/allServiceAPIs?api-invoker-id=$apiinvokerid" - - -##### Offboard an Invoker - -curl --cert invoker.crt --key invoker.key --cacert ca.crt --request DELETE "https://$capifhost/api-invoker-management/v1/onboardedInvokers/$apiinvokerid" - diff --git a/docs/testing_with_curl/exposer.key b/docs/testing_with_curl/exposer.key deleted file mode 100644 index e84c8c4c2796860f0a3a1b0937d5b444a68692e2..0000000000000000000000000000000000000000 --- a/docs/testing_with_curl/exposer.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCSknsXMAiTMVjE -sptbniUixAE0hDPnNAi9FkMVys7hAtHaNBSmz2CIFYQOKH77jsmIEnIz7PVaQSHt -v6ahmFBOGPsv08qAkdGFTWh4elITXH+vvjv0nkX4IVGoWjm/10L7bMZ8/gSxKs1+ -ncwr8pAeweEzNK3zzXEAez6nb9twz6x38GVcLgnoTXLoeTeiAjuSrjjd9xihQdnH -0KVRJug69drVlI9XF0JXrEpGtpR0Ap+Ewaf6li0kOw2nwaD8E3w1eZhTOX20OGN6 -4jGvg3fwuBbeBEcs0hrxpw714Fy1bD0APbQlbMUBe++axugE9zbCw5VyyaVwJuKw -xEpfgnIpAgMBAAECggEACs11TqlcIG5qd/N1Ts8ni9noACpe4ZiXV578lRkW8++E -xEZtX+P4iIm+wK+3DYGhvyp430naGsD30rF62FMaVr8xmCijC/nIoutTGqS38t8G -Ns+C/2Lrjj+fvemJyGasSaKOjdIc9L/OWG7MiE/+05LU2bTKvfrIwXvT4NGg2ei1 -NDO8vS5fRHYZ1LyCyrCDetP2aYrTlPao20hmU4IDyh4N17wLuPgijC+AuqR2Xic0 -Mk4ofZ/6Y3oN0rrov2yG7IXjMJQI469IQ6TJLlyFc8tQIF5Y3CMMCMuVMq5m33bq -/6bow4/VYFG8mPzy7lQLQ8YeEPsgDKL0pB4zqDr7ZwKBgQDJRJoG2PSaEOt6DIKV -84to73oD9x9lOSrmaH2/NzL3mwLXP2Is4nmLzEDQvA0UhTZe9c0n6OoE3uRZ1gAu -JIe3zXTJSK4/ysmePUZL1js5bKtuHBrcSCOupWRuJXbaXK5uqISDHUgHiRw3bq8y -g8SZY/JOBPyJhVlKhmhNCYMi9wKBgQC6bjJ//tLpH6EG4ux0O2StzUoHrvV2cyUj -RRxGvAt92sdsZaVKmIW/SlLy8tv5HJqblfn6m7aY/vUYbN3AfMJ4teLZz5Y//CH3 -jPchHyk/uhh7gxufiD65i5bfVyRt54tDbyVDc2/1prUyD5W4q4UNOmvhXym5saIc -U5WNCnSr3wKBgQCs8MaM5bVgAPPlfoRixs9ejo/AgoK2nqWvL9AFEzA3NDn/rJX2 -TW/1YL+83Ck9Ha33cKwlA+y53LBIRSsIexknJWKZZltbsysFTk9t8JoZILg5N+sY -puAKPFGMl6KFxSeZLDIY23s+BmF5fCEMfc7botbclUpN/IgaEl3i/C5zRwKBgHsx -lKdmEaNBZlwxmgTYtpfvH2tiXwwN3M2ovp2zZ3icGMn1hTt8/GzCxXuLpnbAQx5r -BcxoF0qUuAuS7RpklvHDZ4t9FJFloGCAQ1Ic0FovNDxyD8/k7WYY6vLdF9KUfj9q -c9pVrvdKWVQiXlKw7PQn1eAQzXbK/g/v39Raw2xLAoGBAILTLY3sGBNkFCVhJlyZ -DaIwkbtnpCBT2T7DUupw51aLhh4rnuJ5wA3uGdRqoKVYSc9DuOwB/yNFGuQDElxQ -jfKlX0X5xItaxZ5FR4EvGCnqBJl6JM3QekzhXtq5VdY5zIf/HHqFYebcMFrkEicZ -uuAZd4wa+jn9SR9mUYtS+Lq+ ------END PRIVATE KEY----- diff --git a/docs/testing_with_curl/invoker.key b/docs/testing_with_curl/invoker.key deleted file mode 100644 index 15b96bbd0d00ef4ee73a5557e79b42c4b6d6598f..0000000000000000000000000000000000000000 --- a/docs/testing_with_curl/invoker.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCt8hMRvf8nkoO3 -uJrZaxCt3yJKuUfySHoP1g08QX4pogZD3DxCGY5bjXq68gABLM5oIow2qBsIjQ2q -xtUX2V9qIGAHvW9zBfTIpq2MAKfc2Xcue5uL60fglvnMZBBc67GkwcyaDKc1OxJz -8x4zNfeJRaouaaGdMLfUy7URJQ9MFr4KK1ACPbBgy8FL3vRYgIqsOXFaRHxlkGRE -FlrEx+pjbVVaZES1H4qXoYIwG1QJQEfq5aMWI6nFhsLF3KDHGsDhrcjOaI61c7Iu -zuK44/8ItJh+TvUwdfaoqWkDKN1ErZbTDQaKhX3QeTi5P9hRjL3ONZY36aatD0YH -LyJFmbtjAgMBAAECggEAAyR5OxdJ1W5jnSD9kBCvO6jDMIUuIcU+SAZUfGaxYybn -EeNCtBiPGV8tWWLHJJ0bL6iKpAv+gOKeSpKOmwU7XkHZEWVlRAfpiNfen2bcTCiw -fg3D4bgRMmDwwyMH368QFlJ56UFMCuqb0x+oCeMRIdNjwfbcPVCpZDYNGwTDBzoy -72Aj5TssEu+Ft5VVGwhsvq0v6bd6OWmW34PI9SHzXzRlRw4b4ZtZekW8o/QpO1gO -F+ARbCGE2qjqHWRU/vzINMmAucqhDM6/f7Un5XXr+Zm+8u4PGa5eLWkebJHhfwKX -Ag0WToD/FmDPRqlnjZdzraJlhuXLGdhRAlzdnIQNRQKBgQDvhiVewu7CTzgB66dA -cdrJkXVJPZUGvUYmXkwPaSju7hjDc87pNz+szH2QP+Qm+pD1mV9OswIim4Oi7C1l -lEe423QGjtsn5txzcRk+ZzyX/Z2ltcnXi8N/MNeOZ2qFAgP/IIOTcgowKftuUT6w -2A1DQFj6xxu6vrzxOqIL6tXy7wKBgQC56SM80udTqyb9+wk/KuDSgym3bSaZ8i5q -dNVV5wOxCotLGG9Any61TVOIP/SUjar4f4+FznLZjJYXIZvpbS32PUOtlnKtOmp6 -OBKIpEXq2zq0u/o/i8EyOb6laNqehfffRYqqYU9mJXVjiTUNcOVqfLljeeui1r1P -txSRBlTuzQKBgQDUgB/hbXHjw+J9mbM9soUXtUvn2ZHAc+Wrnpc+SN6+80/W/4R/ -VbvRM27mrjhc+InoytRKfvgS+gOUZJJ1/1KOR2wtcUovoVrNtHZf7blNYv0dCiXz -bBTaX9uthER1km83RoJVKqStTGG74qqKvHMvygPnIQSR7iy0m38usX500wKBgGeM -koLzWcOBhhNa+tiDMnwucFLpaeG/QdkrwBO7u5OlstYeAwF0aFi1fDxcmwcPLVaB -/lfiGJhRtNunbacDl+EaWJLcRH12Fw6CItiW3xakCzvVo9o3JmGqRiTtlS9MoTZs -DoM99jKH1K2fI7yb0DySwdPFedjWUNWQvNTWOQJVAoGAYr9Kuo7s83Qe9CaHQW/Y -PPL0dYBA63guuw2mNQjBL5LuqMZPz6vVB0hIVlYb5Xgw48OWUThHksJ0qltJK7kR -OPRyOxiWpJVo5rZPVzS0Ofbmau9z1VYr358RqR2N2EqG5KDr5QZT9nQq7k8EJvrF -NM/zMhxmgtNYez417Q/3U+M= ------END PRIVATE KEY----- diff --git a/docs/testing_with_postman/CAPIF.postman_collection.json b/docs/testing_with_postman/CAPIF.postman_collection.json deleted file mode 100644 index e65c826994c986b46367eeb223d65444a38cebf9..0000000000000000000000000000000000000000 --- a/docs/testing_with_postman/CAPIF.postman_collection.json +++ /dev/null @@ -1,982 +0,0 @@ -{ - "info": { - "_postman_id": "5cfdf0d7-3b3c-4961-9cb9-84c2bf85056c", - "name": "CAPIF", - "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json", - "_exporter_id": "31608242", - "_collection_link": "https://red-comet-993867.postman.co/workspace/Team-Workspace~bfc7c442-a60c-4bb1-8730-fdabc2df89b9/collection/31608242-5cfdf0d7-3b3c-4961-9cb9-84c2bf85056c?action=share&source=collection_link&creator=31608242" - }, - "item": [ - { - "name": "01-register_user_provider", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var res = JSON.parse(responseBody);", - "pm.environment.set('ONBOARDING_URL', res.ccf_api_onboarding_url);", - "pm.environment.set('PUBLISH_URL', res.ccf_publish_url);", - "pm.environment.set('USER_ID', res.id);", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME}}\",\n\"description\": \"provider\",\n\"role\": \"provider\",\n\"cn\": \"provider\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/register", - "protocol": "https", - "host": [ - "{{REGISTER_HOSTNAME}}" - ], - "port": "{{REGISTER_PORT}}", - "path": [ - "register" - ] - } - }, - "response": [] - }, - { - "name": "02-getauth_provider", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var res = JSON.parse(responseBody);", - "", - "pm.environment.set('CA_ROOT', res.ca_root);", - "pm.environment.set('ACCESS_TOKEN', res.access_token);", - "", - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/write_ca',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: res", - " }", - " }, function (err, res) {", - " console.log(res);", - " });", - " }, 5000);" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/getauth", - "protocol": "https", - "host": [ - "{{REGISTER_HOSTNAME}}" - ], - "port": "{{REGISTER_PORT}}", - "path": [ - "getauth" - ] - } - }, - "response": [] - }, - { - "name": "03-onboard_provider", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var res = JSON.parse(responseBody);", - "if (pm.response.code == 201){", - " ", - " pm.environment.set('PROVIDER_ID', res.apiProvDomId);", - "", - " const roleVariableMapping = {", - " \"AEF\": { id: 'AEF_ID', cert: 'AEF_CERT' },", - " \"APF\": { id: 'APF_ID', cert: 'APF_CERT' },", - " \"AMF\": { id: 'AMF_ID', cert: 'AMF_CERT' }", - " };", - "", - " res.apiProvFuncs.forEach(function(elemento) {", - " const role = elemento.apiProvFuncRole;", - " if (roleVariableMapping.hasOwnProperty(role)) {", - " const variables = roleVariableMapping[role];", - " pm.environment.set(variables.id, elemento.apiProvFuncId);", - " pm.environment.set(variables.cert, elemento.regInfo.apiProvCert);", - "", - " }", - " });", - "", - "}", - "", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "", - "var res = JSON.parse(pm.request.body.raw);", - "", - "res.apiProvFuncs.forEach(function(elemento) {", - "", - " setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/generate_csr',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: elemento", - " }", - " }, function (err, response) {", - " j_file = JSON.parse(response.text());", - " elemento.regInfo.apiProvPubKey = j_file.csr;", - " pm.environment.set(elemento.apiProvFuncRole+'_KEY', j_file.key);", - " });", - " }, 5000);", - "", - "});", - "", - "pm.request.body.raw = res;" - ], - "type": "text/javascript" - } - } - ], - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{ACCESS_TOKEN}}", - "type": "string" - } - ] - }, - "method": "POST", - "header": [ - { - "key": "", - "value": "", - "type": "text", - "disabled": true - } - ], - "body": { - "mode": "raw", - "raw": "{\n\"apiProvFuncs\": [\n {\n \"regInfo\": {\n \"apiProvPubKey\": \"\"\n },\n \"apiProvFuncRole\": \"AEF\",\n \"apiProvFuncInfo\": \"dummy_aef\"\n },\n {\n \"regInfo\": {\n \"apiProvPubKey\": \"\"\n },\n \"apiProvFuncRole\": \"APF\",\n \"apiProvFuncInfo\": \"dummy_apf\"\n },\n {\n \"regInfo\": {\n \"apiProvPubKey\": \"\"\n },\n \"apiProvFuncRole\": \"AMF\",\n \"apiProvFuncInfo\": \"dummy_amf\"\n }\n],\n\"apiProvDomInfo\": \"This is provider\",\n\"suppFeat\": \"fff\",\n\"failReason\": \"string\",\n\"regSec\": \"{{ACCESS_TOKEN}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL}}", - "protocol": "https", - "host": [ - "{{CAPIF_HOSTNAME}}" - ], - "path": [ - "{{ONBOARDING_URL}}" - ] - } - }, - "response": [] - }, - { - "name": "04-publish_api", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/write_cert',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: {cert: pm.environment.get('APF_CERT'), key:pm.environment.get('APF_KEY')}", - " }", - " }, function (err, response) {", - " console.log(response)", - " });", - " }, 5000);", - "", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "strictSSL": true - }, - "request": { - "auth": { - "type": "noauth" - }, - "method": "POST", - "header": [ - { - "key": "", - "value": "", - "type": "text", - "disabled": true - } - ], - "body": { - "mode": "raw", - "raw": "\n{\n \"apiName\": \"hello_api_demo_v2\",\n \"aefProfiles\": [\n {\n \"aefId\": \"{{AEF_ID}}\",\n \"versions\": [\n {\n \"apiVersion\": \"v1\",\n \"expiry\": \"2021-11-30T10:32:02.004Z\",\n \"resources\": [\n {\n \"resourceName\": \"hello-endpoint\",\n \"commType\": \"REQUEST_RESPONSE\",\n \"uri\": \"/hello\",\n \"custOpName\": \"string\",\n \"operations\": [\n \"POST\"\n ],\n \"description\": \"Endpoint to receive a welcome message\"\n }\n ],\n \"custOperations\": [\n {\n \"commType\": \"REQUEST_RESPONSE\",\n \"custOpName\": \"string\",\n \"operations\": [\n \"POST\"\n ],\n \"description\": \"string\"\n }\n ]\n }\n ],\n \"protocol\": \"HTTP_1_1\",\n \"dataFormat\": \"JSON\",\n \"securityMethods\": [\"Oauth\"],\n \"interfaceDescriptions\": [\n {\n \"ipv4Addr\": \"localhost\",\n \"port\": 8088,\n \"securityMethods\": [\"Oauth\"]\n }\n ]\n }\n ],\n \"description\": \"Hello api services\",\n \"supportedFeatures\": \"fffff\",\n \"shareableInfo\": {\n \"isShareable\": true,\n \"capifProvDoms\": [\n \"string\"\n ]\n },\n \"serviceAPICategory\": \"string\",\n \"apiSuppFeats\": \"fffff\",\n \"pubApiPath\": {\n \"ccfIds\": [\n \"string\"\n ]\n },\n \"ccfId\": \"string\"\n }", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{CAPIF_HOSTNAME}}/published-apis/v1/{{APF_ID}}/service-apis", - "protocol": "https", - "host": [ - "{{CAPIF_HOSTNAME}}" - ], - "path": [ - "published-apis", - "v1", - "{{APF_ID}}", - "service-apis" - ] - } - }, - "response": [] - }, - { - "name": "05-register_user_invoker", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var res = JSON.parse(responseBody);", - "pm.environment.set('ONBOARDING_URL_INVOKER', res.ccf_onboarding_url);", - "pm.environment.set('DISCOVER_URL', res.ccf_discover_url);", - "pm.environment.set('USER_INVOKER_ID', res.id);", - "" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME_INVOKER}}\",\n\"description\": \"invoker\",\n\"role\": \"invoker\",\n\"cn\": \"invoker\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/register", - "protocol": "https", - "host": [ - "{{REGISTER_HOSTNAME}}" - ], - "port": "{{REGISTER_PORT}}", - "path": [ - "register" - ] - } - }, - "response": [] - }, - { - "name": "06-getauth_invoker", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var res = JSON.parse(responseBody);", - "", - "pm.environment.set('CA_ROOT', res.ca_root);", - "pm.environment.set('ACCESS_TOKEN_INVOKER', res.access_token);", - "", - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/write_ca',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: res", - " }", - " }, function (err, res) {", - " console.log(res);", - " });", - " }, 5000);" - ], - "type": "text/javascript" - } - } - ], - "request": { - "method": "POST", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME_INVOKER}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/getauth", - "protocol": "https", - "host": [ - "{{REGISTER_HOSTNAME}}" - ], - "port": "{{REGISTER_PORT}}", - "path": [ - "getauth" - ] - } - }, - "response": [] - }, - { - "name": "07-onboard_invoker", - "event": [ - { - "listen": "test", - "script": { - "exec": [ - "var res = JSON.parse(responseBody);", - "if (pm.response.code == 201){", - " ", - " pm.environment.set('INVOKER_ID', res.apiInvokerId);", - " pm.environment.set('INVOKER_CERT', res.onboardingInformation.apiInvokerCertificate);", - "}", - "", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "prerequest", - "script": { - "exec": [ - "", - "var res = JSON.parse(pm.request.body.raw);", - "", - "", - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/generate_csr_invoker',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: {}", - " }", - " }, function (err, response) {", - " j_file = JSON.parse(response.text());", - " res.onboardingInformation.apiInvokerPublicKey = j_file.csr;", - " pm.environment.set('INVOKER_KEY', j_file.key);", - " });", - " }, 5000);", - "", - "", - "pm.request.body.raw = res;" - ], - "type": "text/javascript" - } - } - ], - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{ACCESS_TOKEN_INVOKER}}", - "type": "string" - } - ] - }, - "method": "POST", - "header": [ - { - "key": "", - "value": "", - "type": "text", - "disabled": true - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"notificationDestination\" : \"http://host.docker.internal:8086/netapp_callback\",\n \"supportedFeatures\" : \"fffffff\",\n \"apiInvokerInformation\" : \"dummy\",\n \"websockNotifConfig\" : {\n \"requestWebsocketUri\" : true,\n \"websocketUri\" : \"websocketUri\"\n },\n \"onboardingInformation\" : {\n \"apiInvokerPublicKey\" : \"\"\n },\n \"requestTestNotification\" : true\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL_INVOKER}}", - "protocol": "https", - "host": [ - "{{CAPIF_HOSTNAME}}" - ], - "path": [ - "{{ONBOARDING_URL_INVOKER}}" - ] - } - }, - "response": [] - }, - { - "name": "08-discover", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/write_cert',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}", - " }", - " }, function (err, response) {", - " console.log(response)", - " });", - " }, 5000);", - "", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "var res = JSON.parse(responseBody);", - "if (pm.response.code == 200){", - "", - " res.serviceAPIDescriptions.forEach(function(api) {", - " pm.environment.set('API_SERVICE_ID', api.apiId);", - " pm.environment.set('API_NAME', api.apiName);", - " pm.environment.set('API_AEF_ID', api.aefProfiles[0].aefId);", - " pm.environment.set('IPV4ADDR', api.aefProfiles[0].interfaceDescriptions[0].ipv4Addr);", - " pm.environment.set('PORT', api.aefProfiles[0].interfaceDescriptions[0].port);", - " pm.environment.set('URI', api.aefProfiles[0].versions[0].resources[0].uri);", - " });", - "}" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "disableBodyPruning": true, - "strictSSL": true - }, - "request": { - "auth": { - "type": "noauth" - }, - "method": "GET", - "header": [ - { - "key": "", - "value": "", - "type": "text", - "disabled": true - } - ], - "body": { - "mode": "raw", - "raw": "", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{CAPIF_HOSTNAME}}/{{DISCOVER_URL}}{{INVOKER_ID}}", - "protocol": "https", - "host": [ - "{{CAPIF_HOSTNAME}}" - ], - "path": [ - "{{DISCOVER_URL}}{{INVOKER_ID}}" - ] - } - }, - "response": [] - }, - { - "name": "09-security_context", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/write_cert',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}", - " }", - " }, function (err, response) {", - " console.log(response)", - " });", - " }, 5000);", - "", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "strictSSL": true - }, - "request": { - "auth": { - "type": "noauth" - }, - "method": "PUT", - "header": [ - { - "key": "", - "value": "", - "type": "text", - "disabled": true - } - ], - "body": { - "mode": "raw", - "raw": "{\n \"securityInfo\": [\n {\n \"prefSecurityMethods\": [\n \"Oauth\"\n ],\n \"authenticationInfo\": \"string\",\n \"authorizationInfo\": \"string\",\n \"aefId\": \"{{API_AEF_ID}}\",\n \"apiId\": \"{{API_SERVICE_ID}}\"\n }\n ],\n \"notificationDestination\": \"https://mynotificationdest.com\",\n \"requestTestNotification\": true,\n \"websockNotifConfig\": {\n \"websocketUri\": \"string\",\n \"requestWebsocketUri\": true\n },\n \"supportedFeatures\": \"fff\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{CAPIF_HOSTNAME}}/capif-security/v1/trustedInvokers/{{INVOKER_ID}}", - "protocol": "https", - "host": [ - "{{CAPIF_HOSTNAME}}" - ], - "path": [ - "capif-security", - "v1", - "trustedInvokers", - "{{INVOKER_ID}}" - ] - } - }, - "response": [] - }, - { - "name": "10-get_token", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/write_cert',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}", - " }", - " }, function (err, response) {", - " console.log(response)", - " });", - " }, 5000);", - "", - "", - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "var res = JSON.parse(responseBody);", - "if (pm.response.code == 200){", - " pm.environment.set('NETAPP_SERVICE_TOKEN', res.access_token);", - "}" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "strictSSL": true, - "disabledSystemHeaders": {} - }, - "request": { - "auth": { - "type": "noauth" - }, - "method": "POST", - "header": [ - { - "key": "", - "value": "", - "type": "text", - "disabled": true - } - ], - "body": { - "mode": "urlencoded", - "urlencoded": [ - { - "key": "client_id", - "value": "{{INVOKER_ID}}", - "type": "text" - }, - { - "key": "grant_type", - "value": "client_credentials", - "type": "text" - }, - { - "key": "client_secret", - "value": "string", - "type": "text" - }, - { - "key": "scope", - "value": "3gpp#{{API_AEF_ID}}:{{API_NAME}}", - "type": "text" - } - ] - }, - "url": { - "raw": "https://{{CAPIF_HOSTNAME}}/capif-security/v1/securities/{{INVOKER_ID}}/token", - "protocol": "https", - "host": [ - "{{CAPIF_HOSTNAME}}" - ], - "path": [ - "capif-security", - "v1", - "securities", - "{{INVOKER_ID}}", - "token" - ] - } - }, - "response": [] - }, - { - "name": "11-call_service", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - }, - { - "listen": "test", - "script": { - "exec": [ - "" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "strictSSL": false - }, - "request": { - "auth": { - "type": "bearer", - "bearer": [ - { - "key": "token", - "value": "{{NETAPP_SERVICE_TOKEN}}", - "type": "string" - } - ] - }, - "method": "POST", - "header": [ - { - "key": "", - "value": "", - "type": "text", - "disabled": true - } - ], - "body": { - "mode": "raw", - "raw": "{\n\"name\": {{USERNAME_INVOKER}}\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "http://{{IPV4ADDR}}:{{PORT}}{{URI}}", - "protocol": "http", - "host": [ - "{{IPV4ADDR}}" - ], - "port": "{{PORT}}{{URI}}" - } - }, - "response": [] - }, - { - "name": "offboard_provider", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/write_cert',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: {cert: pm.environment.get('AMF_CERT'), key:pm.environment.get('AMF_KEY')}", - " }", - " }, function (err, response) {", - " console.log(response)", - " });", - " }, 5000);" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "strictSSL": true - }, - "request": { - "auth": { - "type": "noauth" - }, - "method": "DELETE", - "header": [], - "url": { - "raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL}}/{{PROVIDER_ID}}", - "protocol": "https", - "host": [ - "{{CAPIF_HOSTNAME}}" - ], - "path": [ - "{{ONBOARDING_URL}}", - "{{PROVIDER_ID}}" - ] - } - }, - "response": [] - }, - { - "name": "offboard_invoker", - "event": [ - { - "listen": "prerequest", - "script": { - "exec": [ - "setTimeout(() => {", - " pm.sendRequest({", - " url: 'http://localhost:3000/write_cert',", - " method: 'POST',", - " header: 'Content-Type:application/json',", - " encoding: 'binary',", - " body: {", - " mode: 'raw',", - " raw: {cert: pm.environment.get('INVOKER_CERT'), key:pm.environment.get('INVOKER_KEY')}", - " }", - " }, function (err, response) {", - " console.log(response)", - " });", - " }, 5000);" - ], - "type": "text/javascript" - } - } - ], - "protocolProfileBehavior": { - "strictSSL": true - }, - "request": { - "auth": { - "type": "noauth" - }, - "method": "DELETE", - "header": [], - "url": { - "raw": "https://{{CAPIF_HOSTNAME}}/{{ONBOARDING_URL_INVOKER}}/{{INVOKER_ID}}", - "protocol": "https", - "host": [ - "{{CAPIF_HOSTNAME}}" - ], - "path": [ - "{{ONBOARDING_URL_INVOKER}}", - "{{INVOKER_ID}}" - ] - } - }, - "response": [] - }, - { - "name": "remove_user_invoker", - "request": { - "method": "DELETE", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME_INVOKER}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/remove", - "protocol": "https", - "host": [ - "{{REGISTER_HOSTNAME}}" - ], - "port": "{{REGISTER_PORT}}", - "path": [ - "remove" - ] - } - }, - "response": [] - }, - { - "name": "remove_user_provider", - "request": { - "method": "DELETE", - "header": [], - "body": { - "mode": "raw", - "raw": "{\n\"password\": \"{{PASSWORD}}\",\n\"username\": \"{{USERNAME}}\"\n}", - "options": { - "raw": { - "language": "json" - } - } - }, - "url": { - "raw": "https://{{REGISTER_HOSTNAME}}:{{REGISTER_PORT}}/remove", - "protocol": "https", - "host": [ - "{{REGISTER_HOSTNAME}}" - ], - "port": "{{REGISTER_PORT}}", - "path": [ - "remove" - ] - } - }, - "response": [] - } - ] -} \ No newline at end of file diff --git a/docs/testing_with_postman/CAPIF.postman_environment.json b/docs/testing_with_postman/CAPIF.postman_environment.json deleted file mode 100644 index ab3839e9e78b498312a14db675316a76455747b0..0000000000000000000000000000000000000000 --- a/docs/testing_with_postman/CAPIF.postman_environment.json +++ /dev/null @@ -1,237 +0,0 @@ -{ - "id": "f2daf431-63c4-4275-8755-4cc5de2e566d", - "name": "CAPIF", - "values": [ - { - "key": "CAPIF_HOSTNAME", - "value": "capifcore", - "type": "default", - "enabled": true - }, - { - "key": "CAPIF_PORT", - "value": "8080", - "type": "default", - "enabled": true - }, - { - "key": "REGISTER_HOSTNAME", - "value": "localhost", - "type": "default", - "enabled": true - }, - { - "key": "REGISTER_PORT", - "value": "8084", - "type": "default", - "enabled": true - }, - { - "key": "USERNAME", - "value": "ProviderONE", - "type": "default", - "enabled": true - }, - { - "key": "PASSWORD", - "value": "pass", - "type": "default", - "enabled": true - }, - { - "key": "CALLBACK_IP", - "value": "host.docker.internal", - "type": "default", - "enabled": true - }, - { - "key": "CALLBACK_PORT", - "value": "8087", - "type": "default", - "enabled": true - }, - { - "key": "ONBOARDING_URL", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "PUBLISH_URL", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "USER_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "CA_ROOT", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "ACCESS_TOKEN", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "APF_KEY", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "AMF_KEY", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "AEF_KEY", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "PROVIDER_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "AEF_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "AEF_CERT", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "APF_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "APF_CERT", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "AMF_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "AMF_CERT", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "ONBOARDING_URL_INVOKER", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "DISCOVER_URL", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "USER_INVOKER_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "ACCESS_TOKEN_INVOKER", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "INVOKER_KEY", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "INVOKER_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "INVOKER_CERT", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "API_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "API_NAME", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "IPV4ADDR", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "PORT", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "URI", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "API_SERVICE_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "API_AEF_ID", - "value": "", - "type": "any", - "enabled": true - }, - { - "key": "NETAPP_SERVICE_TOKEN", - "value": "", - "type": "any", - "enabled": true - } - ], - "_postman_variable_scope": "environment", - "_postman_exported_at": "2023-12-20T10:47:32.128Z", - "_postman_exported_using": "Postman/10.21.4" -} \ No newline at end of file diff --git a/docs/testing_with_postman/README.md b/docs/testing_with_postman/README.md deleted file mode 100644 index b6c75832265d5b61f797f4d38ac2ad3d090fd216..0000000000000000000000000000000000000000 --- a/docs/testing_with_postman/README.md +++ /dev/null @@ -1,160 +0,0 @@ -[**[Return To Main]**] - -- [CAPIF in Postman](#capif-in-postman) - - [Requisites](#requisites) - - [First steps](#first-steps) - - [Not Local CAPIF](#not-local-capif) -- [CAPIF Flows](#capif-flows) - - [Publication of an API](#publication-of-an-api) - - [**01-register\_user\_provider**](#01-register_user_provider) - - [**02-getauth\_provider**](#02-getauth_provider) - - [**03-onboard\_provider**](#03-onboard_provider) - - [**04-publish\_api**](#04-publish_api) - - [Calling the API](#calling-the-api) - - [**05-register\_user\_invoker**](#05-register_user_invoker) - - [**06-getauth\_invoker**](#06-getauth_invoker) - - [**07-onboard\_invoker**](#07-onboard_invoker) - - [**08-discover**](#08-discover) - - [**09-security\_context**](#09-security_context) - - [**10-get\_token**](#10-get_token) - - [**11-call\_service**](#11-call_service) - - [Other requests](#other-requests) -- [Notes](#notes) - - -# CAPIF in Postman -In this section we can use Postman to publish an API as a provider and use it as an invoker. - -## Requisites - -- We will need to have Node.js installed since we will use a small script to create the CSRs of the certificates. -- An instance of CAPIF (If it is not local, certain variables would have to be modified both in the Node.js script and in the Postman environment variables). - -## First steps - -1. Install the Node dependencies to run the script with: - -``` -npm i -``` - -2. Run the script.js with the following command: - -``` -node script.js -``` - -3. Import Postman collection and environment variables (CAPIF.postman_collection.json and CAPIF.postman_environment.json) -4. Select CAPIF Environment before start testing. - -## Not Local CAPIF - -If the CAPIF is not local, the host and port of both the CAPIF and the register would have to be specified in the variables, and the CAPIF_HOSTNAME in the script, necessary to obtain the server certificate. - -**Enviroments in Postman** -``` -CAPIF_HOSTNAME capifcore -CAPIF_PORT 8080 -REGISTER_HOSTNAME register -REGISTER_PORT 8084 -``` - -**Const in script.js** -``` -CAPIF_HOSTNAME capifcore -``` - -# CAPIF Flows -Once the first steps have been taken, we can now use Postman requests. These requests are numbered in the order that must be followed to obtain everything necessary from CAPIF. - -## Publication of an API - -### **01-register_user_provider** - -![Flow](../images/flows/01a%20-%20Register%20(Only)%20AEF.png) - -### **02-getauth_provider** - -![Flow](../images/flows/01b%20-%20Register%20of%20AEF%20GetAuth.png) - -### **03-onboard_provider** - -![Flow](../images/flows/02%20-%20AEF%20API%20Provider%20registration.png) - -At this point we move on to using certificate authentication in CAPIF. In Postman it is necessary to add the certificates manually and using more than one certificate for the same host as we do in CAPIF complicates things. For this reason, we use the script to overwrite a certificate and a key when it is necessary to have a specific one. - -To configure go to **settings** in Postman and open the **certificates** section. - -- Here, activate the **CA certificates** option and add the **ca_cert.pem** file found in the **Responses** folder. -- Adds a client certificate specifying the CAPIF host being used and the files **client_cert.crt** and **client_key.key** in the **Responses** folder. - - -Once this is done, the node script will be in charge of changing the certificate that is necessary in each request. - -### **04-publish_api** - -![Flow](../images/flows/03%20-%20AEF%20Publish.png) - -Once the api is published, we can start it. In this case we have a test one created in python that can be executed with the following command: - -``` -python3 hello_api.py -``` - -The API publication interface is set to localhost with port 8088, so the service must be set up locally. If you wanted to build it on another site, you would have to change the interface description in the body of publish_api. - -With this the provider part would be finished. - -## Calling the API - -### **05-register_user_invoker** - -![Flow](../images/flows/04a%20-%20Invoker%20(Only)%20Register.png) - -### **06-getauth_invoker** - -![Flow](../images/flows/04b%20-%20Invoker%20Register%20GetAuth.png) - -### **07-onboard_invoker** - -![Flow](../images/flows/05%20-%20Invoker%20Onboarding.png) - -At this point we move on to using certificate authentication in CAPIF. **If you did not configure the provider's certificates, you would have to do it now**. - -### **08-discover** - -![Flow](../images/flows/06%20-%20Invoker%20Discover%20AEF.png) - -### **09-security_context** - -![Flow](../images/flows/07%20-%20Invoker%20Create%20Security%20Context.png) - -### **10-get_token** - -![Flow](../images/flows/08%20-%20Invoker%20Get%20Token.png) - -### **11-call_service** - -![Flow](../images/flows/09%20-%20Invoker%20Send%20Request%20to%20AEF%20Service%20API.png) - -With this, we would have made the API call and finished the flow. - -## Other requests - -Other requests that we have added are the following: - -- **offboard_provider** Performs offboarding of the provider, thereby eliminating the published APIs. -- **offboard_invoker** Offboards the invoker, also eliminating access to the APIs of that invoker. -- **remove_user_invoker** Delete the user created for the invoker. -- **remove_user_provider** Delete the user created for the provider. - -# Notes - -- This process is designed to teach how requests are made in Postman and the flow that should be followed to publish and use an API. -- It is possible that if external CAPIFs are used (Public CAPIF) the test data may already be used or the API already registered. -- It is necessary to have the Node service running to make the certificate change for the requests, otherwise it will not work. -- We are working on adding more requests to the Postman collection. -- This collection is a testing guide and is recommended for testing purposes only. - -[Return To Main]: ../../README.md#using-postman - diff --git a/docs/testing_with_postman/hello_api.py b/docs/testing_with_postman/hello_api.py deleted file mode 100644 index 0b2a35989ecfaa144489d1b6012f61453c91bd68..0000000000000000000000000000000000000000 --- a/docs/testing_with_postman/hello_api.py +++ /dev/null @@ -1,38 +0,0 @@ -from flask import Flask, jsonify, request -from flask_jwt_extended import jwt_required, JWTManager, get_jwt_identity, get_jwt -import ssl -from werkzeug import serving -import socket, ssl -import OpenSSL -from OpenSSL import crypto -import jwt -import pyone - -app = Flask(__name__) - -jwt_flask = JWTManager(app) - - -with open("Responses/cert_server.pem", "rb") as cert_file: - cert= cert_file.read() - -crtObj = crypto.load_certificate(crypto.FILETYPE_PEM, cert) -pubKeyObject = crtObj.get_pubkey() -pubKeyString = crypto.dump_publickey(crypto.FILETYPE_PEM,pubKeyObject) - -app.config['JWT_ALGORITHM'] = 'RS256' -app.config['JWT_PUBLIC_KEY'] = pubKeyString - - -@app.route("/hello", methods=["POST"]) -@jwt_required() -def hello(): - - request_data = request.get_json() - - user_name = request_data['name'] - - return jsonify(f"Hello: {user_name}, welcome to CAPIF.") - -if __name__ == '__main__': - serving.run_simple("0.0.0.0", 8088, app) diff --git a/docs/testing_with_postman/package.json b/docs/testing_with_postman/package.json deleted file mode 100644 index 6d612a702d5a9fa9a112f1a2f47c44f75725fa00..0000000000000000000000000000000000000000 --- a/docs/testing_with_postman/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "node-server", - "version": "1.0.0", - "description": "", - "main": "index.js", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "author": "", - "license": "ISC", - "dependencies": { - "body-parser": "^1.18.3", - "express": "^4.16.3", - "shelljs": "^0.8.2" - } - } \ No newline at end of file diff --git a/docs/testing_with_postman/script.js b/docs/testing_with_postman/script.js deleted file mode 100644 index 980f81f33b4bda4f48f55dcd13d8f436dface9a5..0000000000000000000000000000000000000000 --- a/docs/testing_with_postman/script.js +++ /dev/null @@ -1,199 +0,0 @@ -// Change this variable if another host is used for CAPIF -const CAPIF_HOSTNAME = 'capifcore'; - -const express = require('express'), - app = express(), - fs = require('fs'), - shell = require('shelljs'), - - - folderPath = './Responses/', - bodyParser = require('body-parser'), - path = require('path'); - -const { exec } = require('child_process'); - -// Create the folder path in case it doesn't exist -shell.mkdir('-p', folderPath); - - // Change the limits according to your response size -app.use(bodyParser.json({limit: '50mb', extended: true})); -app.use(bodyParser.urlencoded({ limit: '50mb', extended: true })); -var opensslCommand = '' - -if (CAPIF_HOSTNAME.includes(':')){ - opensslCommand = `openssl s_client -connect ${CAPIF_HOSTNAME} | openssl x509 -text > ./Responses/cert_server.pem`; -} -else{ - opensslCommand = `openssl s_client -connect ${CAPIF_HOSTNAME}:443 | openssl x509 -text > ./Responses/cert_server.pem`; -} - -exec(opensslCommand, (error, stdout, stderr) => { - if (error) { - console.error(`Error generating CSR: ${stderr}`); - } -}); - -fs.writeFileSync('./Responses/client_cert.crt', ''); -fs.writeFileSync('./Responses/client_key.key', ''); - -app.get('/', (req, res) => res.send('Hello, I write data to file. Send them requests!')); - -app.post('/generate_csr', (req, res) => { - - console.log(req.body); - const csrFilePath = 'Responses/'+req.body.apiProvFuncRole+'_csr.pem'; - const privateKeyFilePath = 'Responses/'+req.body.apiProvFuncRole+'_key.key'; - - const subjectInfo = { - country: 'ES', - state: 'Madrid', - locality: 'Madrid', - organization: 'Telefonica I+D', - organizationalUnit: 'IT Department', - emailAddress: 'admin@example.com', - }; - - const opensslCommand = `openssl req -newkey rsa:2048 -nodes -keyout ${privateKeyFilePath} -out ${csrFilePath} -subj "/C=${subjectInfo.country}/ST=${subjectInfo.state}/L=${subjectInfo.locality}/O=${subjectInfo.organization}/OU=${subjectInfo.organizationalUnit}/emailAddress=${subjectInfo.emailAddress}"`; - - exec(opensslCommand, (error, stdout, stderr) => { - if (error) { - console.error(`Error generating CSR: ${stderr}`); - } else { - console.log('CSR generated successfully:'); - fs.readFile(csrFilePath, 'utf8', (readError, csrContent) => { - if (readError) { - console.error(`Error reading CSR: ${readError}`); - res.status(500).send('Error reading CSR'); - } else { - console.log('CSR read successfully:'); - // Send the CSR content in the response - fs.readFile(privateKeyFilePath, 'utf8', (readError, keyContent) => { - if (readError) { - console.error(`Error reading KEY: ${readError}`); - res.status(500).send('Error reading KEY'); - } else { - console.log('KEY read successfully:'); - // Send the CSR content in the response - fs.unlink(csrFilePath, (err) => { - if (err) { - console.error(`Error deleting file: ${err.message}`); - } - }); - fs.unlink(privateKeyFilePath, (err) => { - if (err) { - console.error(`Error deleting file: ${err.message}`); - } - }); - res.send({csr: csrContent, key: keyContent}); - } - }); - } - }); - } - }); -}); - -app.post('/generate_csr_invoker', (req, res) => { - - console.log(req.body); - const csrFilePath = 'Responses/invoker_csr.pem'; - const privateKeyFilePath = 'Responses/invoker_key.key'; - - const subjectInfo = { - country: 'ES', - state: 'Madrid', - locality: 'Madrid', - organization: 'Telefonica I+D', - organizationalUnit: 'IT Department', - emailAddress: 'admin@example.com', - }; - - const opensslCommand = `openssl req -newkey rsa:2048 -nodes -keyout ${privateKeyFilePath} -out ${csrFilePath} -subj "/C=${subjectInfo.country}/ST=${subjectInfo.state}/L=${subjectInfo.locality}/O=${subjectInfo.organization}/OU=${subjectInfo.organizationalUnit}/emailAddress=${subjectInfo.emailAddress}"`; - - exec(opensslCommand, (error, stdout, stderr) => { - if (error) { - console.error(`Error generating CSR: ${stderr}`); - } else { - console.log('CSR generated successfully:'); - fs.readFile(csrFilePath, 'utf8', (readError, csrContent) => { - if (readError) { - console.error(`Error reading CSR: ${readError}`); - res.status(500).send('Error reading CSR'); - } else { - console.log('CSR read successfuly:'); - // Send the CSR content in the response - fs.readFile(privateKeyFilePath, 'utf8', (readError, keyContent) => { - if (readError) { - console.error(`Error reading KEY: ${readError}`); - res.status(500).send('Error reading KEY'); - } else { - console.log('KEY read successfully:'); - // Send the CSR content in the response - fs.unlink(csrFilePath, (err) => { - if (err) { - console.error(`Error deleting file: ${err.message}`); - } - }); - fs.unlink(privateKeyFilePath, (err) => { - if (err) { - console.error(`Error deleting file: ${err.message}`); - } - }); - res.send({csr: csrContent, key: keyContent}); - } - }); - } - }); - } - }); -}); - - -app.post('/write_cert', (req, res) => { - let extension = 'crt', - fsMode = 'writeFile', - filename = "client_cert", - filePath = `${path.join(folderPath, filename)}.${extension}`, - options = {encoding: 'binary'}; - fs[fsMode](filePath, req.body.cert, options, (err) => { - if (err) { - console.log(err); - res.send('Error'); - } - }); - extension = 'key'; - filename = "client_key"; - filePath = `${path.join(folderPath, filename)}.${extension}`; - fs[fsMode](filePath, req.body.key, options, (err) => { - if (err) { - console.log(err); - res.send('Error'); - } - else { - res.send('Success'); - } - }); -}); - -app.post('/write_ca', (req, res) => { - let extension = 'pem', - fsMode = 'writeFile', - filename = "ca_cert", - filePath = `${path.join(folderPath, filename)}.${extension}`, - options = {encoding: 'binary'}; - fs[fsMode](filePath, req.body.ca_root, options, (err) => { - if (err) { - console.log(err); - res.send('Error'); - } - else { - res.send('Success'); - } - }); -}); - -app.listen(3000, () => { - console.log('ResponsesToFile App is listening now! Send them requests my way!'); - console.log(`Data is being stored at location: ${path.join(process.cwd(), folderPath)}`); -}); \ No newline at end of file diff --git a/docs/testing_with_robot/README.md b/docs/testing_with_robot/README.md deleted file mode 100644 index 71504c1fc5ab76377c54bf868516f33a5617f731..0000000000000000000000000000000000000000 --- a/docs/testing_with_robot/README.md +++ /dev/null @@ -1,74 +0,0 @@ -[**[Return To Main]**] -# Testing With Robot Framework - -- [Testing With Robot Framework](#testing-with-robot-framework) - - [Steps to Test](#steps-to-test) - - [Script Test Execution](#script-test-execution) - - [Manual Build And Test Execution](#manual-build-and-test-execution) - - [Test result review](#test-result-review) - -## Steps to Test - -To run any test locally you will need *docker* and *docker-compose* installed in order run services and execute test plan. Steps will be: -* **Run All Services**: See section [Run All CAPIF Services](../../README.md#run-all-capif-services-locally-with-docker-images) -* **Run desired tests**: At this point we have 2 options: - * **Using helper script**: [Script Test Execution](#script-test-execution) - * **Build robot docker image and execute manually robot docker**: [Manual Build And Test Execution](#manual-build-and-test-execution) - - -## Script Test Execution -This script will build robot docker image if it's need and execute tests selected by "include" option. Just go to service folder, execute and follow steps. -``` -./runCapifTests.sh --include -``` -Results will be stored at /results - -Please check parameters (include) under *Test Execution* at [Manual Build And Test Execution](#manual-build-and-test-execution). - -## Manual Build And Test Execution - -* **Build Robot docker image**: -``` -cd tools/robot -docker build . -t 5gnow-robot-test:latest -``` - -* **Tests Execution**: - -Execute all tests locally: -``` -=path in local machine to repository cloned. -=path to a folder on local machine to store results of Robot Framework execution. -=Is the hostname set when run.sh is executed, by default it will be capifcore. -=This is the port to reach when robot framework want to reach CAPIF deployment using http, this should be set to port without TLS set on Nginx, 8080 by default. - -To execute all tests run : -docker run -ti --rm --network="host" -v /tests:/opt/robot-tests/tests -v :/opt/robot-tests/results 5gnow-robot-test:latest --variable CAPIF_HOSTNAME:capifcore --variable CAPIF_HTTP_PORT:8080 --include all -``` - -Execute specific tests locally: -``` -To run more specific tests, for example, only one functionality: -=Select one from list: - "capif_api_discover_service", - "capif_api_invoker_management", - "capif_api_publish_service", - "capif_api_events", - "capif_security_api - -And Run: -docker run -ti --rm --network="host" -v /tests:/opt/robot-tests/tests -v :/opt/robot-tests/results 5gnow-robot-test:latest --variable CAPIF_HOSTNAME:capifcore --variable CAPIF_HTTP_PORT:8080 --include -``` - -## Test result review - -In order to Review results after tests, you can check general report at /report.html or if you need more detailed information /log.html, example: -* Report: -![Report](../images/robot_report_example.png) -* Detailed information: -![Log](../images/robot_log_example.png) - -**NOTE: If you need more detail at Robot Framework Logs you can set log level option just adding to command --loglevel DEBUG** - - -[Return To Main]: ../../README.md#robot-framework \ No newline at end of file diff --git a/helm/DELETE.txt b/helm/DELETE.txt new file mode 100644 index 0000000000000000000000000000000000000000..2d030d7bc1bbfbdee332aaf691447b30cdea375b --- /dev/null +++ b/helm/DELETE.txt @@ -0,0 +1 @@ +delete me diff --git a/helm/capif/Chart.yaml b/helm/capif/Chart.yaml index 625f95844b7f45365ff19a5df4e2da0b8492cd3f..1c49c2c37c782bfe4095533ddedc57750f2db18b 100644 --- a/helm/capif/Chart.yaml +++ b/helm/capif/Chart.yaml @@ -13,13 +13,61 @@ type: application # This is the chart version. This version number should be incremented each time you make changes # to the chart and its templates, including the app version. # Versions are expected to follow Semantic Versioning (https://semver.org/) -version: v3.1.4 +version: v3.1.6 # This is the version number of the application being deployed. This version number should be # incremented each time you make changes to the application. Versions are not expected to # follow Semantic Versioning. They should reflect the version the application is using. # It is recommended to use it with quotes. -appVersion: "v3.1.4" +appVersion: "v3.1.6" dependencies: + - name: ocf-access-control-policy + version: "*" + - name: ocf-api-invoker-management + version: "*" + - name: ocf-api-provider-management + version: "*" + - name: ocf-api-invocation-logs + version: "*" + - name: ocf-events + version: "*" + - name: ocf-helper + version: "*" + - name: ocf-routing-info + version: "*" + - name: ocf-security + version: "*" + - name: ocf-register + version: "*" + - name: mongo-register + version: "*" + - name: ocf-auditing-api-logs + version: "*" + - name: ocf-publish-service-api + version: "*" + - name: ocf-discover-service-api + version: "*" + - name: mongo + version: "*" + - name: mongo-express + version: "*" + - name: mongo-register-express + version: "*" + - name: nginx + version: "*" + - name: mock-server + version: "*" + - name: redis + version: "*" + - name: fluentbit + version: "*" + - name: grafana + version: "*" + - name: loki + version: "*" + - name: otelcollector + version: "*" + - name: renderer + version: "*" - name: "tempo" condition: tempo.enabled repository: "https://grafana.github.io/helm-charts" diff --git a/helm/capif/charts/fluentbit/.helmignore b/helm/capif/charts/fluentbit/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/fluentbit/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/fluentbit/Chart.yaml b/helm/capif/charts/fluentbit/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b10c00b6eb287628ab1f0da00b26a16c0aa5a6f6 --- /dev/null +++ b/helm/capif/charts/fluentbit/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: fluentbit +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/fluentbit/templates/NOTES.txt b/helm/capif/charts/fluentbit/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..8e6d43ee67b6be4f3d5a38e58f4a7450ffb36b5c --- /dev/null +++ b/helm/capif/charts/fluentbit/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "fluentbit.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "fluentbit.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "fluentbit.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "fluentbit.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/fluentbit/templates/_helpers.tpl b/helm/capif/charts/fluentbit/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..a880f20c35280848352894e8b5fa0fef05156d42 --- /dev/null +++ b/helm/capif/charts/fluentbit/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "fluentbit.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "fluentbit.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "fluentbit.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "fluentbit.labels" -}} +helm.sh/chart: {{ include "fluentbit.chart" . }} +{{ include "fluentbit.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "fluentbit.selectorLabels" -}} +app.kubernetes.io/name: {{ include "fluentbit.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "fluentbit.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "fluentbit.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/fluentbit-configmap.yaml b/helm/capif/charts/fluentbit/templates/configmap.yaml similarity index 79% rename from helm/capif/templates/fluentbit-configmap.yaml rename to helm/capif/charts/fluentbit/templates/configmap.yaml index 20467b10a80d79431e308c6c87cd9cdc42fffcd6..2561e38d4a4569022b6de40472f9d07349af4fac 100644 --- a/helm/capif/templates/fluentbit-configmap.yaml +++ b/helm/capif/charts/fluentbit/templates/configmap.yaml @@ -1,10 +1,10 @@ -{{- if eq .Values.monitoring.enable "true" }} +{{- if .Values.enabled | default false }} apiVersion: v1 kind: ConfigMap metadata: name: fluent-bit-configmap data: - LOKI_URL: {{ quote .Values.monitoring.fluentBit.env.lokiUrl }} + LOKI_URL: {{ quote .Values.env.lokiUrl }} fluent-bit.conf: | [INPUT] Name forward diff --git a/helm/capif/charts/fluentbit/templates/deployment.yaml b/helm/capif/charts/fluentbit/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ce6125c6258e1cbf151c212499c77ed4d4380800 --- /dev/null +++ b/helm/capif/charts/fluentbit/templates/deployment.yaml @@ -0,0 +1,79 @@ +{{- if .Values.enabled | default false }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "fluentbit.fullname" . }} + labels: + {{- include "fluentbit.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + strategy: + type: Recreate + selector: + matchLabels: + {{- include "fluentbit.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "fluentbit.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "fluentbit.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: fluent-bit-udp + containerPort: {{ .Values.service.port }} + protocol: UDP + - name: fluent-bit-tcp + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: LOKI_URL + valueFrom: + configMapKeyRef: + name: fluent-bit-configmap + key: LOKI_URL + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/fluentbit/templates/hpa.yaml b/helm/capif/charts/fluentbit/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9a6dd95ba03cf486e6bc4e43de66cc626a53494b --- /dev/null +++ b/helm/capif/charts/fluentbit/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "fluentbit.fullname" . }} + labels: + {{- include "fluentbit.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "fluentbit.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/fluentbit/templates/ingress.yaml b/helm/capif/charts/fluentbit/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..601131ccd476e395f0ee30f4dae90077596ac9e8 --- /dev/null +++ b/helm/capif/charts/fluentbit/templates/ingress.yaml @@ -0,0 +1,63 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "fluentbit.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "fluentbit.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/fluentbit/templates/service.yaml b/helm/capif/charts/fluentbit/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dd9be52de3c93def404d7d709da3619392f693c0 --- /dev/null +++ b/helm/capif/charts/fluentbit/templates/service.yaml @@ -0,0 +1,21 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Service +metadata: + name: fluent-bit + labels: + {{- include "fluentbit.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.port }} + protocol: UDP + name: fluent-bit-udp + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.port }} + protocol: TCP + name: fluent-bit-tcp + selector: + {{- include "fluentbit.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/capif/charts/fluentbit/templates/serviceaccount.yaml b/helm/capif/charts/fluentbit/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fbdb575f960c45557ab88ceda334e4843be6ce16 --- /dev/null +++ b/helm/capif/charts/fluentbit/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "fluentbit.serviceAccountName" . }} + labels: + {{- include "fluentbit.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/fluentbit/values.yaml b/helm/capif/charts/fluentbit/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..49aa7e72bfcc9469d20697160fd2653421eae435 --- /dev/null +++ b/helm/capif/charts/fluentbit/values.yaml @@ -0,0 +1,116 @@ +# Default values for fluentbit. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +enabled: false + +replicaCount: 1 + +image: + repository: grafana/fluent-bit-plugin-loki + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "latest" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + lokiUrl: http://loki:3100/loki/api/v1/push + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 24224 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + tcpSocket: + port: 24224 + initialDelaySeconds: 20 + periodSeconds: 5 +readinessProbe: + tcpSocket: + port: 24224 + initialDelaySeconds: 20 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: fluent-bit-conf + configMap: + name: fluent-bit-configmap + items: + - key: fluent-bit.conf + path: fluent-bit.conf + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: fluent-bit-conf + mountPath: /fluent-bit/etc/fluent-bit.conf + subPath: fluent-bit.conf + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/grafana/.helmignore b/helm/capif/charts/grafana/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/grafana/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/grafana/Chart.yaml b/helm/capif/charts/grafana/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2c7c54e5d4e37c3a84aea8825c5e447a5bc6a7d3 --- /dev/null +++ b/helm/capif/charts/grafana/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: grafana +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/grafana/README.md b/helm/capif/charts/grafana/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5325ad0dd72a30d59b8293e64d5a5f624857d0c9 --- /dev/null +++ b/helm/capif/charts/grafana/README.md @@ -0,0 +1,51 @@ +# grafana + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.16.0](https://img.shields.io/badge/AppVersion-1.16.0-informational?style=flat-square) + +A Helm chart for Kubernetes + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | | +| autoscaling.enabled | bool | `false` | | +| autoscaling.maxReplicas | int | `100` | | +| autoscaling.minReplicas | int | `1` | | +| autoscaling.targetCPUUtilizationPercentage | int | `80` | | +| env.gfAuthAnonymousEnable | bool | `true` | | +| env.gfAuthAnonymousOrgRole | string | `"Admin"` | | +| env.gfSecurityAdminPassword | string | `"secure_pass"` | | +| env.gfSecurityAllowEmbedding | bool | `true` | | +| env.prometheusUrl | string | `"http://prometheus.prometheus-system.svc.cluster.local:9090"` | | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"Always"` | | +| image.repository | string | `"grafana/grafana"` | | +| image.tag | string | `"latest"` | | +| imagePullSecrets | list | `[]` | | +| ingress.annotations | object | `{}` | | +| ingress.className | string | `"nginx"` | | +| ingress.enabled | bool | `true` | | +| ingress.environment | string | `"edge"` | | +| ingress.hosts[0].host | string | `"grafana-dt.tactile5g.int"` | | +| ingress.hosts[0].paths[0].path | string | `"/"` | | +| ingress.hosts[0].paths[0].pathType | string | `"Prefix"` | | +| ingress.tls | list | `[]` | | +| nameOverride | string | `""` | | +| nodeSelector | object | `{}` | | +| persistence.enable | bool | `false` | | +| persistence.storage | string | `"10Gi"` | | +| podAnnotations | object | `{}` | | +| podSecurityContext | object | `{}` | | +| replicaCount | int | `1` | | +| resources | object | `{}` | | +| securityContext | object | `{}` | | +| service.port | int | `80` | | +| service.type | string | `"NodePort"` | | +| serviceAccount.annotations | object | `{}` | | +| serviceAccount.create | bool | `true` | | +| serviceAccount.name | string | `""` | | +| tolerations | list | `[]` | | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.13.1](https://github.com/norwoodj/helm-docs/releases/v1.13.1) diff --git a/helm/capif/charts/grafana/kubernetes-dashboard.json b/helm/capif/charts/grafana/kubernetes-dashboard.json new file mode 100644 index 0000000000000000000000000000000000000000..ac97f80ebd0139f383c3f82920b9b9aec7b8c1e9 --- /dev/null +++ b/helm/capif/charts/grafana/kubernetes-dashboard.json @@ -0,0 +1,2629 @@ +{ + "annotations": { + "list": [ + { + "$$hashKey": "object:103", + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Monitors Kubernetes cluster using Prometheus. Shows overall cluster CPU / Memory / Filesystem usage as well as individual pod, containers, systemd services statistics. Uses cAdvisor metrics only.", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 12740, + "graphTooltip": 0, + "id": 7, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 33, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Network I/O pressure", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 6, + "w": 24, + "x": 0, + "y": 1 + }, + "height": "200px", + "hiddenSeries": false, + "id": 32, + "legend": { + "alignAsTable": false, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": false, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_receive_bytes_total{kubernetes_io_hostname=~\"^$Node$\"}[1m]))", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "Received", + "metric": "network", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{kubernetes_io_hostname=~\"^$Node$\"}[1m]))", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "Sent", + "metric": "network", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Network I/O pressure", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 0, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "Bps", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 34, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Total usage", + "type": "row" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 65 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 0, + "y": 8 + }, + "id": 4, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) / sum (machine_memory_bytes{kubernetes_io_hostname=~\"^$Node$\"}) * 100", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Cluster memory usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 65 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 8, + "y": 8 + }, + "id": 6, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) / sum (machine_cpu_cores{kubernetes_io_hostname=~\"^$Node$\"}) * 100", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Cluster CPU usage (1m avg)", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "max": 100, + "min": 0, + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "rgba(50, 172, 45, 0.97)", + "value": null + }, + { + "color": "rgba(237, 129, 40, 0.89)", + "value": 65 + }, + { + "color": "rgba(245, 54, 54, 0.9)", + "value": 90 + } + ] + }, + "unit": "percent" + }, + "overrides": [] + }, + "gridPos": { + "h": 5, + "w": 8, + "x": 16, + "y": 8 + }, + "id": 7, + "links": [], + "maxDataPoints": 100, + "options": { + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "showThresholdLabels": false, + "showThresholdMarkers": true + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_fs_usage_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) / sum (container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) * 100", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "", + "metric": "", + "refId": "A", + "step": 10 + } + ], + "title": "Cluster filesystem usage", + "type": "gauge" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 0, + "y": 13 + }, + "id": 9, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Used", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 4, + "y": 13 + }, + "id": 10, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (machine_memory_bytes{kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 8, + "y": 13 + }, + "id": 11, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{id=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m]))", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Used", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 12, + "y": 13 + }, + "id": 12, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (machine_cpu_cores{kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Total", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 16, + "y": 13 + }, + "id": 13, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_fs_usage_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Used", + "type": "stat" + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "decimals": 2, + "mappings": [ + { + "options": { + "match": "null", + "result": { + "text": "N/A" + } + }, + "type": "special" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "bytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 4, + "x": 20, + "y": 13 + }, + "id": 14, + "links": [], + "maxDataPoints": 100, + "options": { + "colorMode": "none", + "graphMode": "none", + "justifyMode": "auto", + "orientation": "horizontal", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "10.0.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_fs_limit_bytes{device=~\"^/dev/[sv]d[a-z][1-9]$\",id=\"/\",kubernetes_io_hostname=~\"^$Node$\"})", + "interval": "10s", + "intervalFactor": 1, + "refId": "A", + "step": 10 + } + ], + "title": "Total", + "type": "stat" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 16 + }, + "id": 35, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Pods CPU usage", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 3, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 17 + }, + "height": "", + "hiddenSeries": false, + "id": 17, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editorMode": "code", + "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (pod)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "metric": "container_cpu", + "range": true, + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pods CPU usage (1m avg)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:112", + "format": "none", + "label": "cores", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:113", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 24 + }, + "id": 39, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Pods memory usage", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 25 + }, + "hiddenSeries": false, + "id": 25, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editorMode": "code", + "expr": "sum (container_memory_working_set_bytes{image!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}) by (pod)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ pod }}", + "metric": "container_memory_usage:sort_desc", + "range": true, + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pods memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:181", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:182", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 32 + }, + "id": 43, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Pods network I/O", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 33 + }, + "hiddenSeries": false, + "id": 16, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editorMode": "code", + "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (pod)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> {{ pod }}", + "metric": "network", + "range": true, + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (pod)", + "hide": true, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- {{ pod }}", + "metric": "network", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Pods network I/O (1m avg)", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 40 + }, + "id": 37, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 3, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 41 + }, + "height": "", + "hiddenSeries": false, + "id": 24, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "hideEmpty": false, + "hideZero": false, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",name=~\"^k8s_.*\",container!=\"POD\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (container, pod)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "pod: {{ pod }}| {{ container }}", + "metric": "container_cpu", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, name, image)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", + "metric": "container_cpu", + "refId": "B", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", + "metric": "container_cpu", + "refId": "C", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Containers CPU usage (1m avg)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:337", + "format": "none", + "label": "cores", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:338", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Containers CPU usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 41 + }, + "id": 41, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 42 + }, + "hiddenSeries": false, + "id": 27, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{image!=\"\",name=~\"^k8s_.*\",container!=\"POD\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}) by (container, pod)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "pod: {{ pod }} | {{ container }}", + "metric": "container_memory_usage:sort_desc", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}) by (kubernetes_io_hostname, name, image)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", + "metric": "container_memory_usage:sort_desc", + "refId": "B", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}) by (kubernetes_io_hostname, rkt_container_name)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", + "metric": "container_memory_usage:sort_desc", + "refId": "C", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Containers memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:406", + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:407", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Containers memory usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 42 + }, + "id": 44, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 43 + }, + "hiddenSeries": false, + "id": 30, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (container, pod)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> pod: {{ pod }} | {{ container }}", + "metric": "network", + "refId": "B", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name=~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (container, pod)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- pod: {{ pod }} | {{ container }}", + "metric": "network", + "refId": "D", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_receive_bytes_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, name, image)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", + "metric": "network", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{image!=\"\",name!~\"^k8s_.*\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, name, image)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- docker: {{ kubernetes_io_hostname }} | {{ image }} ({{ name }})", + "metric": "network", + "refId": "C", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_transmit_bytes_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", + "metric": "network", + "refId": "E", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{rkt_container_name!=\"\",kubernetes_io_hostname=~\"^$Node$\",namespace=~\"^$namespace$\"}[1m])) by (kubernetes_io_hostname, rkt_container_name)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- rkt: {{ kubernetes_io_hostname }} | {{ rkt_container_name }}", + "metric": "network", + "refId": "F", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Containers network I/O (1m avg)", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "Containers network I/O", + "type": "row" + }, + { + "collapsed": false, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 43 + }, + "id": 36, + "panels": [], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "System services CPU usage", + "type": "row" + }, + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 3, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 44 + }, + "height": "", + "hiddenSeries": false, + "id": 23, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "editorMode": "code", + "expr": "sum (rate (container_cpu_usage_seconds_total{systemd_service_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (systemd_service_name)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ systemd_service_name }}", + "metric": "container_cpu", + "range": true, + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "System services CPU usage (1m avg)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "none", + "label": "cores", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 51 + }, + "id": 40, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 7, + "w": 24, + "x": 0, + "y": 29 + }, + "hiddenSeries": false, + "id": 26, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{systemd_service_name!=\"\",kubernetes_io_hostname=~\"^$Node$\"}) by (systemd_service_name)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ systemd_service_name }}", + "metric": "container_memory_usage:sort_desc", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "System services memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "System services memory usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 52 + }, + "id": 38, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 3, + "editable": true, + "error": false, + "fieldConfig": { + "defaults": { + "links": [] + }, + "overrides": [] + }, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 46 + }, + "hiddenSeries": false, + "id": 20, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "10.0.2", + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_cpu_usage_seconds_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", + "hide": false, + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ id }}", + "metric": "container_cpu", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "All processes CPU usage (1m avg)", + "tooltip": { + "msResolution": true, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "$$hashKey": "object:254", + "format": "none", + "label": "cores", + "logBase": 1, + "show": true + }, + { + "$$hashKey": "object:255", + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "All processes CPU usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 53 + }, + "id": 42, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fill": 0, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 47 + }, + "hiddenSeries": false, + "id": 28, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": true, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (container_memory_working_set_bytes{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}) by (id)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "{{ id }}", + "metric": "container_memory_usage:sort_desc", + "refId": "A", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "All processes memory usage", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "bytes", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "All processes memory usage", + "type": "row" + }, + { + "collapsed": true, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 54 + }, + "id": 45, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "decimals": 2, + "editable": true, + "error": false, + "fill": 1, + "fillGradient": 0, + "grid": {}, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 48 + }, + "hiddenSeries": false, + "id": 29, + "isNew": true, + "legend": { + "alignAsTable": true, + "avg": true, + "current": true, + "max": false, + "min": false, + "rightSide": false, + "show": true, + "sideWidth": 200, + "sort": "current", + "sortDesc": true, + "total": false, + "values": true + }, + "lines": true, + "linewidth": 2, + "links": [], + "nullPointMode": "connected", + "options": { + "dataLinks": [] + }, + "percentage": false, + "pointradius": 5, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": false, + "steppedLine": false, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "sum (rate (container_network_receive_bytes_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "-> {{ id }}", + "metric": "network", + "refId": "A", + "step": 10 + }, + { + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "expr": "- sum (rate (container_network_transmit_bytes_total{id!=\"/\",kubernetes_io_hostname=~\"^$Node$\"}[1m])) by (id)", + "interval": "10s", + "intervalFactor": 1, + "legendFormat": "<- {{ id }}", + "metric": "network", + "refId": "B", + "step": 10 + } + ], + "thresholds": [], + "timeRegions": [], + "title": "All processes network I/O (1m avg)", + "tooltip": { + "msResolution": false, + "shared": true, + "sort": 2, + "value_type": "cumulative" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "Bps", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": false + } + ], + "yaxis": { + "align": false + } + } + ], + "targets": [ + { + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "refId": "A" + } + ], + "title": "All processes network I/O", + "type": "row" + } + ], + "refresh": "10s", + "schemaVersion": 38, + "style": "dark", + "tags": [ + "kubernetes" + ], + "templating": { + "list": [ + { + "allValue": "", + "current": { + "selected": true, + "text": "monitoring", + "value": "monitoring" + }, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "definition": "label_values(namespace)", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "namespace", + "options": [], + "query": "label_values(namespace)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "prometheus", + "uid": "af6b44aa-0703-4979-825c-c1afba946534" + }, + "definition": "", + "hide": 0, + "includeAll": true, + "multi": false, + "name": "Node", + "options": [], + "query": "label_values(kubernetes_io_hostname)", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + } + ] + }, + "time": { + "from": "now-5m", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ], + "time_options": [ + "5m", + "15m", + "1h", + "6h", + "12h", + "24h", + "2d", + "7d", + "30d" + ] + }, + "timezone": "browser", + "title": "Kubernetes Monitoring Dashboard", + "uid": "msqzbWjWk", + "version": 2, + "weekStart": "" + } \ No newline at end of file diff --git a/helm/capif/charts/grafana/loki-logs.json b/helm/capif/charts/grafana/loki-logs.json new file mode 100644 index 0000000000000000000000000000000000000000..e7e4d72162ad88ab094ee11d3c49e257664b3324 --- /dev/null +++ b/helm/capif/charts/grafana/loki-logs.json @@ -0,0 +1,281 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "datasource", + "uid": "grafana" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "description": "Simple Loki dashboard", + "editable": true, + "fiscalYearStartMonth": 0, + "gnetId": 13198, + "graphTooltip": 0, + "id": 9, + "links": [], + "liveNow": false, + "panels": [ + { + "aliasColors": {}, + "bars": false, + "dashLength": 10, + "dashes": false, + "datasource": { + "type": "loki", + "uid": "$datasource" + }, + "fill": 0, + "fillGradient": 0, + "gridPos": { + "h": 8, + "w": 24, + "x": 0, + "y": 0 + }, + "hiddenSeries": false, + "id": 4, + "legend": { + "alignAsTable": true, + "avg": false, + "current": false, + "hideEmpty": true, + "hideZero": true, + "max": false, + "min": false, + "rightSide": true, + "show": true, + "total": false, + "values": false + }, + "lines": true, + "linewidth": 1, + "nullPointMode": "null", + "options": { + "alertThreshold": true + }, + "percentage": false, + "pluginVersion": "9.5.2", + "pointradius": 2, + "points": false, + "renderer": "flot", + "seriesOverrides": [], + "spaceLength": 10, + "stack": true, + "steppedLine": false, + "targets": [ + { + "datasource": { + "uid": "$datasource" + }, + "editorMode": "code", + "expr": "count_over_time({job=\"fluent-bit\"}[1m])", + "legendFormat": "{{ container_name }}", + "queryType": "range", + "refId": "A" + } + ], + "thresholds": [], + "timeRegions": [], + "title": "Metric Rate", + "tooltip": { + "shared": true, + "sort": 2, + "value_type": "individual" + }, + "type": "graph", + "xaxis": { + "mode": "time", + "show": true, + "values": [] + }, + "yaxes": [ + { + "format": "short", + "logBase": 1, + "show": true + }, + { + "format": "short", + "logBase": 1, + "show": true + } + ], + "yaxis": { + "align": false + } + }, + { + "datasource": { + "type": "loki", + "uid": "e4f43364-7019-45a7-aa7a-14ce2d4ddb0b" + }, + "gridPos": { + "h": 14, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "dedupStrategy": "none", + "enableLogDetails": true, + "prettifyLogMessage": false, + "showCommonLabels": false, + "showLabels": false, + "showTime": true, + "sortOrder": "Descending", + "wrapLogMessage": true + }, + "pluginVersion": "7.1.3", + "targets": [ + { + "datasource": { + "type": "loki", + "uid": "e4f43364-7019-45a7-aa7a-14ce2d4ddb0b" + }, + "editorMode": "code", + "expr": "{job=~\"fluent-bit\"} |~ \"$string\"", + "legendFormat": "", + "queryType": "range", + "refId": "A" + } + ], + "title": "Loki Search", + "type": "logs" + } + ], + "refresh": "1m", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "current": { + "selected": false, + "text": "Loki", + "value": "Loki" + }, + "hide": 0, + "includeAll": false, + "multi": false, + "name": "datasource", + "options": [], + "query": "loki", + "queryValue": "", + "refresh": 1, + "regex": "", + "skipUrlSync": false, + "type": "datasource" + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "loki", + "uid": "$datasource" + }, + "definition": "label_values(container_name)", + "hide": 0, + "includeAll": true, + "label": "app", + "multi": false, + "name": "app", + "options": [], + "query": "label_values(container_name)", + "refresh": 2, + "regex": "(.*)-.*-.*-.*-.*-.*", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "allValue": ".*", + "current": { + "selected": false, + "text": "All", + "value": "$__all" + }, + "datasource": { + "type": "loki", + "uid": "$datasource" + }, + "definition": "label_values(container_name)", + "hide": 0, + "includeAll": true, + "label": "job", + "multi": false, + "name": "job", + "options": [], + "query": "label_values(container_name)", + "refresh": 2, + "regex": "$app-(.*)", + "skipUrlSync": false, + "sort": 0, + "tagValuesQuery": "", + "tagsQuery": "", + "type": "query", + "useTags": false + }, + { + "current": { + "selected": false, + "text": "", + "value": "" + }, + "hide": 0, + "label": "string", + "name": "string", + "options": [ + { + "selected": true, + "text": "", + "value": "" + } + ], + "query": "", + "skipUrlSync": false, + "type": "textbox" + } + ] + }, + "time": { + "from": "now-1h", + "to": "now" + }, + "timepicker": { + "refresh_intervals": [ + "5s", + "10s", + "30s", + "1m", + "5m", + "15m", + "30m", + "1h", + "2h", + "1d" + ] + }, + "timezone": "", + "title": "Loki Logs", + "uid": "ffxEJdvGz", + "version": 6, + "weekStart": "" +} \ No newline at end of file diff --git a/helm/capif/charts/grafana/templates/NOTES.txt b/helm/capif/charts/grafana/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..c7ac87e80664a0f6ec0466ce8fda3d4ef8c08758 --- /dev/null +++ b/helm/capif/charts/grafana/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "grafana.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "grafana.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "grafana.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/grafana/templates/_helpers.tpl b/helm/capif/charts/grafana/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..993f46bdd8df0131780dfe58e5019bdb8e29eb53 --- /dev/null +++ b/helm/capif/charts/grafana/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "grafana.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "grafana.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "grafana.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "grafana.labels" -}} +helm.sh/chart: {{ include "grafana.chart" . }} +{{ include "grafana.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "grafana.selectorLabels" -}} +app.kubernetes.io/name: {{ include "grafana.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "grafana.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "grafana.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/grafana-configmap.yaml b/helm/capif/charts/grafana/templates/configmap.yaml similarity index 83% rename from helm/capif/templates/grafana-configmap.yaml rename to helm/capif/charts/grafana/templates/configmap.yaml index 654101f720e7c6d515aa17e5f14adedd532c44e9..dc70d236dd45e4522673e3f4cd5f8e327ac82d5f 100644 --- a/helm/capif/templates/grafana-configmap.yaml +++ b/helm/capif/charts/grafana/templates/configmap.yaml @@ -1,4 +1,4 @@ -{{- if eq .Values.monitoring.enable "true" }} +{{- if .Values.enabled | default false }} apiVersion: v1 kind: ConfigMap metadata: @@ -7,13 +7,29 @@ data: datasources.yaml: | apiVersion: 1 datasources: + - name: Prometheus + type: prometheus + typeName: Prometheus + typeLogoUrl: public/app/plugins/datasource/prometheus/img/prometheus_logo.svg + access: proxy + url: {{ .Values.env.prometheusUrl }} + uid: af6b44aa-0703-4979-825c-c1afba946534 + user: '' + database: '' + basicAuth: false + isDefault: false + jsonData: + httpMethod: POST + prometheusType: Prometheus + prometheusVersion: 2.40.1 + readOnly: false - name: Loki type: loki uid: e4f43364-7019-45a7-aa7a-14ce2d4ddb0b typeName: Loki typeLogoUrl: public/app/plugins/datasource/loki/img/loki_icon.svg access: proxy - url: {{ .Values.monitoring.grafana.env.lokiUrl }} + url: {{ .Values.env.lokiUrl }} user: '' database: '' basicAuth: false @@ -24,30 +40,14 @@ data: matcherRegex: '"traceID":\s*"([a-fA-F0-9]+)"' name: traceID url: "$${__value.raw}" - readOnly: false - - name: Prometheus - type: prometheus - typeName: Prometheus - typeLogoUrl: public/app/plugins/datasource/prometheus/img/prometheus_logo.svg - access: proxy - url: {{ .Values.monitoring.grafana.env.prometheusUrl }} - uid: af6b44aa-0703-4979-825c-c1afba946534 - user: '' - database: '' - basicAuth: false - isDefault: false - jsonData: - httpMethod: POST - prometheusType: Prometheus - prometheusVersion: 2.40.1 - readOnly: false + readOnly: false - name: Tempo type: tempo typeName: Tempo typeLogoUrl: public/app/plugins/datasource/tempo/img/tempo_logo.svg uid: fee7e008-f836-424a-b701-88cad583c715 access: proxy - url: {{ .Values.monitoring.grafana.env.tempoUrl }} + url: {{ .Values.env.tempoUrl }} user: '' database: '' basicAuth: false @@ -78,16 +78,6 @@ data: --- -apiVersion: v1 -kind: ConfigMap -metadata: - name: docker-monitoring -data: - Docker-monitoring.json: |- -{{ .Files.Get "docker-monitoring.json" | indent 4 }} - ---- - apiVersion: v1 kind: ConfigMap metadata: @@ -105,4 +95,4 @@ metadata: data: loki-logs.json: | {{ .Files.Get "loki-logs.json" | indent 4 }} -{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-deployment.yaml b/helm/capif/charts/grafana/templates/deployment.yaml similarity index 55% rename from helm/capif/templates/grafana-deployment.yaml rename to helm/capif/charts/grafana/templates/deployment.yaml index 844f32ece2ce27cc1d40774377c5dce7c6e5eaed..d74241f8fd2bdfc89810f4a2f9e64ac7e3a4e636 100644 --- a/helm/capif/templates/grafana-deployment.yaml +++ b/helm/capif/charts/grafana/templates/deployment.yaml @@ -1,54 +1,56 @@ -{{- if eq .Values.monitoring.enable "true" }} +{{- if .Values.enabled | default false }} apiVersion: apps/v1 kind: Deployment metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) + name: {{ include "grafana.fullname" . }} labels: - io.kompose.service: grafana - {{- include "capif.labels" . | nindent 4 }} - name: grafana + {{- include "grafana.labels" . | nindent 4 }} spec: - replicas: 1 + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} strategy: type: Recreate + {{- end }} selector: matchLabels: - io.kompose.service: grafana - {{- include "capif.selectorLabels" . | nindent 6 }} - strategy: - type: Recreate + {{- include "grafana.selectorLabels" . | nindent 6 }} template: metadata: annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - checksum/config: {{ include (print $.Template.BasePath "/grafana-configmap.yaml") . | sha256sum }} + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} labels: - io.kompose.network/monitoring-default: "true" - io.kompose.service: grafana - {{- include "capif.selectorLabels" . | nindent 8 }} + {{- include "grafana.selectorLabels" . | nindent 8 }} spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "grafana.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} containers: - env: - name: GF_AUTH_ANONYMOUS_ENABLED - value: {{ quote .Values.monitoring.grafana.env.gfAuthAnonymousEnable }} + value: {{ quote .Values.env.gfAuthAnonymousEnable }} - name: GF_SECURITY_ALLOW_EMBEDDING - value: {{ quote .Values.monitoring.grafana.env.gfSecurityAllowEmbedding }} + value: {{ quote .Values.env.gfSecurityAllowEmbedding }} - name: GF_PATHS_PROVISIONING value: /etc/grafana/provisioning - image: {{ .Values.monitoring.grafana.image.repository }}:{{ .Values.monitoring.grafana.image.tag }} - name: grafana + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + name: {{ .Chart.Name }} envFrom: - secretRef: name: grafana-secrets ports: - - containerPort: 3000 + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP +# livenessProbe: +# tcpSocket: +# port: {{ .Values.service.port }} resources: - {{- toYaml .Values.monitoring.grafana.resources | nindent 12 }} - securityContext: - runAsUser: 0 + {{- toYaml .Values.resources | nindent 12 }} volumeMounts: - name: grafana-datasources mountPath: /etc/grafana/provisioning/datasources/datasources.yaml @@ -56,16 +58,13 @@ spec: - name: grafana-default mountPath: /etc/grafana/provisioning/dashboards/default.yaml subPath: default.yaml - - name: grafana-docker - mountPath: /var/lib/grafana/dashboards/Docker-monitoring.json - subPath: Docker-monitoring.json - name: kubernetes-dashboard mountPath: /var/lib/grafana/dashboards/kubernetes-dashboard.json subPath: kubernetes-dashboard.json - name: grafana-loki mountPath: /var/lib/grafana/dashboards/Loki-Logs.json subPath: loki-logs.json - {{- if eq .Values.monitoring.grafana.persistence.enable "true" }} + {{- if .Values.persistence.enable | default false }} - name: grafana-claim0 mountPath: /var/lib/grafana {{- end }} @@ -82,12 +81,6 @@ spec: items: - key: "default.yaml" path: "default.yaml" - - name: grafana-docker - configMap: - name: docker-monitoring - items: - - key: "Docker-monitoring.json" - path: "Docker-monitoring.json" - name: kubernetes-dashboard configMap: name: kubernetes-dashboard @@ -100,10 +93,21 @@ spec: items: - key: "loki-logs.json" path: "loki-logs.json" - {{- if eq .Values.monitoring.grafana.persistence.enable "true" }} + {{- if .Values.persistence.enable | default false }} - name: grafana-claim0 persistentVolumeClaim: claimName: grafana-claim0 - {{- end }} - restartPolicy: Always + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} {{- end }} \ No newline at end of file diff --git a/helm/capif/charts/grafana/templates/hpa.yaml b/helm/capif/charts/grafana/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f8efd8794305d5a15836ff8ee488e83aa5f6c95c --- /dev/null +++ b/helm/capif/charts/grafana/templates/hpa.yaml @@ -0,0 +1,30 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "grafana.fullname" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "grafana.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/grafana/templates/ingress.yaml b/helm/capif/charts/grafana/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dfe5c9ac4c735a04e36897e8c891acca8f6220e6 --- /dev/null +++ b/helm/capif/charts/grafana/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "grafana.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: grafana + port: + number: {{ $svcPort }} + {{- else }} + serviceName: grafana + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/grafana/templates/pvc.yaml b/helm/capif/charts/grafana/templates/pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7aa2b7225959833fd97079735a064a7deb022039 --- /dev/null +++ b/helm/capif/charts/grafana/templates/pvc.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.persistence.enable | default false }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + io.kompose.service: grafana-claim0 + name: grafana-claim0 +spec: + storageClassName: {{ .Values.persistence.storageClass }} + accessModes: + - ReadWriteMany + resources: + requests: + storage: {{ .Values.persistence.storage }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/grafana/templates/secrets.yaml b/helm/capif/charts/grafana/templates/secrets.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0313f54cf53b1ac4c44c8cf51dfb5f21886f8e0c --- /dev/null +++ b/helm/capif/charts/grafana/templates/secrets.yaml @@ -0,0 +1,10 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Secret +metadata: + name: grafana-secrets +type: Opaque +data: + GF_AUTH_ANONYMOUS_ORG_ROLE: {{ .Values.env.gfAuthAnonymousOrgRole | b64enc | quote }} + GF_SECURITY_ADMIN_PASSWORD: {{ .Values.env.gfSecurityAdminPassword | b64enc | quote }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/grafana/templates/service.yaml b/helm/capif/charts/grafana/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b13c5fc52b187c3d3413e68fbe61ea2bdeccf0dc --- /dev/null +++ b/helm/capif/charts/grafana/templates/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Service +metadata: + name: grafana + labels: + {{- include "grafana.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.port }} + protocol: TCP + name: http + selector: + {{- include "grafana.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/grafana/templates/serviceaccount.yaml b/helm/capif/charts/grafana/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..049f60f7ad08293d20a5ad93ea2ad4ff4b125160 --- /dev/null +++ b/helm/capif/charts/grafana/templates/serviceaccount.yaml @@ -0,0 +1,14 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "grafana.serviceAccountName" . }} + labels: + {{- include "grafana.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/grafana/templates/tests/test-connection.yaml b/helm/capif/charts/grafana/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..27d46d2fdc2d509b21d0944c8ddb6cfa647ab1d4 --- /dev/null +++ b/helm/capif/charts/grafana/templates/tests/test-connection.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "grafana.fullname" . }}-test-connection" + labels: + {{- include "grafana.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['grafana:{{ .Values.service.port }}'] + restartPolicy: Never +{{- end }} diff --git a/helm/capif/charts/grafana/values.yaml b/helm/capif/charts/grafana/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8391800203a7f201b02594510981765701519502 --- /dev/null +++ b/helm/capif/charts/grafana/values.yaml @@ -0,0 +1,99 @@ +# Default values for grafana. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +enabled: false + +replicaCount: 1 + +image: + repository: grafana/grafana + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "latest" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +# PENDING: gfAuthAnonymousOrgRole and gfSecurityAdminPassword as aws external-secret +env: + gfAuthAnonymousEnable: true + gfSecurityAllowEmbedding: true + gfAuthAnonymousOrgRole: Admin + gfSecurityAdminPassword: secure_pass + prometheusUrl: http://prometheus.prometheus-system.svc.cluster.local:9090 + lokiUrl: http://loki:3100 + tempoUrl: http://tempo:3100 + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +persistence: + enable: true + storage: 10Gi + storageClass: nfs-01 + +service: + type: ClusterIP + port: 3000 + +ingress: + enabled: true + className: "nginx" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: grafana-dt.tactile5g.int + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/loki/.helmignore b/helm/capif/charts/loki/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/loki/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/loki/Chart.yaml b/helm/capif/charts/loki/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1125160529fba8c6ba65a04d0f2677c77401079a --- /dev/null +++ b/helm/capif/charts/loki/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: loki +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/loki/templates/NOTES.txt b/helm/capif/charts/loki/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..b448c2ffc2ebdbb8b0854efa8f18287e0dbd5376 --- /dev/null +++ b/helm/capif/charts/loki/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "loki.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "loki.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "loki.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "loki.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/loki/templates/_helpers.tpl b/helm/capif/charts/loki/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..fe4bc4e7dc67577130a35e56747f51816f953858 --- /dev/null +++ b/helm/capif/charts/loki/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "loki.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "loki.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "loki.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "loki.labels" -}} +helm.sh/chart: {{ include "loki.chart" . }} +{{ include "loki.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "loki.selectorLabels" -}} +app.kubernetes.io/name: {{ include "loki.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "loki.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "loki.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/loki/templates/deployment.yaml b/helm/capif/charts/loki/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7cd543e2706f6466947f156ae815e99ca4e66b81 --- /dev/null +++ b/helm/capif/charts/loki/templates/deployment.yaml @@ -0,0 +1,74 @@ +{{- if .Values.enabled | default false }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "loki.fullname" . }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + strategy: + type: Recreate + selector: + matchLabels: + {{- include "loki.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "loki.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "loki.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + args: + - -config.file=/etc/loki/local-config.yaml + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/loki/templates/hpa.yaml b/helm/capif/charts/loki/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3ffe63f0be74f096bc6b60a4b7f95fb32245e4e2 --- /dev/null +++ b/helm/capif/charts/loki/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "loki.fullname" . }} + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "loki.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/loki/templates/ingress.yaml b/helm/capif/charts/loki/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0ad609261d1689ac760e7346baf432d70cb5e78c --- /dev/null +++ b/helm/capif/charts/loki/templates/ingress.yaml @@ -0,0 +1,63 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "loki.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: loki + port: + number: {{ $svcPort }} + {{- else }} + serviceName: loki + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/loki/templates/pvc.yaml b/helm/capif/charts/loki/templates/pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c6594b23557d2446b1a86928b18485a7ceba704f --- /dev/null +++ b/helm/capif/charts/loki/templates/pvc.yaml @@ -0,0 +1,16 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.persistence.enable | default false }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + name: loki-claim0 +spec: + storageClassName: {{ .Values.persistence.storageClass }} + accessModes: + - ReadWriteMany + resources: + requests: + storage: {{ .Values.persistence.storage }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/loki/templates/service.yaml b/helm/capif/charts/loki/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5eb8004caf461ff8d019b6c2850872d1df465535 --- /dev/null +++ b/helm/capif/charts/loki/templates/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Service +metadata: + name: loki + labels: + {{- include "loki.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "loki.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/capif/charts/loki/templates/serviceaccount.yaml b/helm/capif/charts/loki/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..491cd0e422b0edd15be2e8813790da6d38a120a8 --- /dev/null +++ b/helm/capif/charts/loki/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "loki.serviceAccountName" . }} + labels: + {{- include "loki.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/loki/templates/tests/test-connection.yaml b/helm/capif/charts/loki/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..42bf0463bfdbf5fb360699ce6ae510464a0b1319 --- /dev/null +++ b/helm/capif/charts/loki/templates/tests/test-connection.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "loki.fullname" . }}-test-connection" + labels: + {{- include "loki.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['loki:{{ .Values.service.port }}'] + restartPolicy: Never +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/loki/values.yaml b/helm/capif/charts/loki/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..444311d2f1cb8c0de407ef19acb60b3ad2a86fa0 --- /dev/null +++ b/helm/capif/charts/loki/values.yaml @@ -0,0 +1,115 @@ +# Default values for loki. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +enabled: false + +replicaCount: 1 + +image: + repository: grafana/loki + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "2.8.0" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + runAsUser: 0 + +persistence: + enable: true + storage: 100Mi + storageClass: nfs-01 + +service: + type: ClusterIP + port: 3100 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + tcpSocket: + port: 3100 + initialDelaySeconds: 20 + periodSeconds: 5 + +readinessProbe: + tcpSocket: + port: 3100 + initialDelaySeconds: 20 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: loki-claim0 + persistentVolumeClaim: + claimName: loki-claim0 + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: loki-claim0 + mountPath: /loki/wal + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/mock-server/.helmignore b/helm/capif/charts/mock-server/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/mock-server/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/mock-server/Chart.yaml b/helm/capif/charts/mock-server/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9ca2cda3630662f9e05036d329d78d370c9113a9 --- /dev/null +++ b/helm/capif/charts/mock-server/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: mock-server +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/mock-server/templates/NOTES.txt b/helm/capif/charts/mock-server/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..4e3d05605049d751c0046a06276eafd20850848f --- /dev/null +++ b/helm/capif/charts/mock-server/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mock-server.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mock-server.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mock-server.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mock-server.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/mock-server/templates/_helpers.tpl b/helm/capif/charts/mock-server/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..4c9fe56f003d2ea9cbed9faa41881bfed3873079 --- /dev/null +++ b/helm/capif/charts/mock-server/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mock-server.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mock-server.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mock-server.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mock-server.labels" -}} +helm.sh/chart: {{ include "mock-server.chart" . }} +{{ include "mock-server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mock-server.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mock-server.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mock-server.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "mock-server.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/mock-server/templates/deployment.yaml b/helm/capif/charts/mock-server/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ea29ba94434dfcc6cf7d9eb2a30317305f775637 --- /dev/null +++ b/helm/capif/charts/mock-server/templates/deployment.yaml @@ -0,0 +1,73 @@ +{{- if .Values.enabled | default false }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mock-server.fullname" . }} + labels: + {{- include "mock-server.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "mock-server.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "mock-server.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "mock-server.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mock-server/templates/hpa.yaml b/helm/capif/charts/mock-server/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d0ae7618202e9f28552e199ef295b7a1089a7cde --- /dev/null +++ b/helm/capif/charts/mock-server/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "mock-server.fullname" . }} + labels: + {{- include "mock-server.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "mock-server.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mock-server/templates/ingress.yaml b/helm/capif/charts/mock-server/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..96c13aee810ba022e332490667c49b07aa698971 --- /dev/null +++ b/helm/capif/charts/mock-server/templates/ingress.yaml @@ -0,0 +1,63 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "mock-server.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "mock-server.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: mock-server + port: + number: {{ $svcPort }} + {{- else }} + serviceName: mock-server + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mock-server/templates/service.yaml b/helm/capif/charts/mock-server/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e11c5cf3a9dddc8887215ae1ffbe1b1c645fbc4a --- /dev/null +++ b/helm/capif/charts/mock-server/templates/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Service +metadata: + name: mock-server + labels: + {{- include "mock-server.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "mock-server.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mock-server/templates/serviceaccount.yaml b/helm/capif/charts/mock-server/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2538086cece009e5404a3b8cef4847d40bbc4d90 --- /dev/null +++ b/helm/capif/charts/mock-server/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mock-server.serviceAccountName" . }} + labels: + {{- include "mock-server.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mock-server/templates/tests/test-connection.yaml b/helm/capif/charts/mock-server/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7173753a3b7802018ae4eb2d8daf781f2d5d74f1 --- /dev/null +++ b/helm/capif/charts/mock-server/templates/tests/test-connection.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "mock-server.fullname" . }}-test-connection" + labels: + {{- include "mock-server.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['mock-server:{{ .Values.service.port }}'] + restartPolicy: Never +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mock-server/values.yaml b/helm/capif/charts/mock-server/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a34433aa97c060faddc1e412f8d93c791b3bdf75 --- /dev/null +++ b/helm/capif/charts/mock-server/values.yaml @@ -0,0 +1,113 @@ +# Default values for mock-server. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +enabled: false + +replicaCount: 1 + +image: + repository: mock-server + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 9090 + +ingress: + enabled: true + className: "nginx" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: mock-server.example.local + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + tcpSocket: + port: 9090 + initialDelaySeconds: 20 + periodSeconds: 5 +readinessProbe: +# httpGet: +# path: / +# port: http + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/mongo-express/.helmignore b/helm/capif/charts/mongo-express/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/mongo-express/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/mongo-express/Chart.yaml b/helm/capif/charts/mongo-express/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7150bbccdd23baed83ea708e050450f10b46e5ea --- /dev/null +++ b/helm/capif/charts/mongo-express/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: mongo-express +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/mongo-express/templates/NOTES.txt b/helm/capif/charts/mongo-express/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..b93d9e574686c0c8188ae7d2f35d9ea42afab7d5 --- /dev/null +++ b/helm/capif/charts/mongo-express/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mongo-express.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mongo-express.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mongo-express.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mongo-express.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/mongo-express/templates/_helpers.tpl b/helm/capif/charts/mongo-express/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..15950b20549ce66c581a6a970a19180507e054fc --- /dev/null +++ b/helm/capif/charts/mongo-express/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mongo-express.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mongo-express.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mongo-express.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mongo-express.labels" -}} +helm.sh/chart: {{ include "mongo-express.chart" . }} +{{ include "mongo-express.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mongo-express.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mongo-express.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mongo-express.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "mongo-express.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/mongo-express/templates/deployment.yaml b/helm/capif/charts/mongo-express/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..32bda4483e58ab4e41c973ac77e02a79b1b2cb5a --- /dev/null +++ b/helm/capif/charts/mongo-express/templates/deployment.yaml @@ -0,0 +1,75 @@ +{{- if .Values.enabled | default false }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mongo-express.fullname" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "mongo-express.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + labels: + {{- include "mongo-express.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "mongo-express.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.targetPort }} + protocol: TCP + env: + - name: ME_CONFIG_MONGODB_ADMINUSERNAME + value: {{ quote .Values.env.meConfigMongodbAdminusername }} + - name: ME_CONFIG_MONGODB_ADMINPASSWORD + value: {{ quote .Values.env.meConfigMongodbAdminpassword }} + - name: ME_CONFIG_MONGODB_URL + value: {{ quote .Values.env.meConfigMongodbUrl }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-express/templates/hpa.yaml b/helm/capif/charts/mongo-express/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d591daf8c40c43fe1e7928273ec08e9fafd16d07 --- /dev/null +++ b/helm/capif/charts/mongo-express/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "mongo-express.fullname" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "mongo-express.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-express/templates/ingress.yaml b/helm/capif/charts/mongo-express/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f4d860c197306b2c97ad79ffdbd11ebcee66aa1a --- /dev/null +++ b/helm/capif/charts/mongo-express/templates/ingress.yaml @@ -0,0 +1,63 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "mongo-express.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: mongo-express + port: + number: {{ $svcPort }} + {{- else }} + serviceName: mongo-express + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-express/templates/service.yaml b/helm/capif/charts/mongo-express/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c72729e8709a077c91e1c3a9e66197b0484d75d1 --- /dev/null +++ b/helm/capif/charts/mongo-express/templates/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Service +metadata: + name: mongo-express + labels: + {{- include "mongo-express.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "mongo-express.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-express/templates/serviceaccount.yaml b/helm/capif/charts/mongo-express/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4535ab9988e99f5c36c116a9606b24e6e64322e4 --- /dev/null +++ b/helm/capif/charts/mongo-express/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mongo-express.serviceAccountName" . }} + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-express/templates/tests/test-connection.yaml b/helm/capif/charts/mongo-express/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fc31c205547520582452787e338fa5cf6a451e48 --- /dev/null +++ b/helm/capif/charts/mongo-express/templates/tests/test-connection.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "mongo-express.fullname" . }}-test-connection" + labels: + {{- include "mongo-express.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['mongo-express:{{ .Values.service.port }}'] + restartPolicy: Never +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-express/values.yaml b/helm/capif/charts/mongo-express/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..36f3a8bdc3c1a4d6a8061b8d8f4fc150a34c2f73 --- /dev/null +++ b/helm/capif/charts/mongo-express/values.yaml @@ -0,0 +1,114 @@ +# Default values for mongo-express. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +enabled: false + +replicaCount: 1 + +image: + repository: mongo-express + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "1.0.0-alpha.4" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + meConfigMongodbAdminusername: root + meConfigMongodbAdminpassword: example + meConfigMongodbUrl: mongodb://root:example@mongo:27017/ +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8082 + targetPort: 8081 + +ingress: + enabled: false + className: "nginx" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8081 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/mongo-register-express/.helmignore b/helm/capif/charts/mongo-register-express/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/mongo-register-express/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/mongo-register-express/Chart.yaml b/helm/capif/charts/mongo-register-express/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b4e246c5371588b8649b2de23af3664ca6017f4b --- /dev/null +++ b/helm/capif/charts/mongo-register-express/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: mongo-register-express +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/mongo-register-express/templates/NOTES.txt b/helm/capif/charts/mongo-register-express/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..60013f0e02b91371136d3e932c30cde9452c1d22 --- /dev/null +++ b/helm/capif/charts/mongo-register-express/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mongo-register-express.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mongo-register-express.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mongo-register-express.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mongo-register-express.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/mongo-register-express/templates/_helpers.tpl b/helm/capif/charts/mongo-register-express/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..accb35f4b620d000237e96ef49f922308d5c280e --- /dev/null +++ b/helm/capif/charts/mongo-register-express/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mongo-register-express.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mongo-register-express.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mongo-register-express.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mongo-register-express.labels" -}} +helm.sh/chart: {{ include "mongo-register-express.chart" . }} +{{ include "mongo-register-express.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mongo-register-express.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mongo-register-express.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mongo-register-express.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "mongo-register-express.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/mongo-register-express/templates/deployment.yaml b/helm/capif/charts/mongo-register-express/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d77c8bcb5fed6e6fede4b423642aa277115bd43d --- /dev/null +++ b/helm/capif/charts/mongo-register-express/templates/deployment.yaml @@ -0,0 +1,75 @@ +{{- if .Values.enabled | default false }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mongo-register-express.fullname" . }} + labels: + {{- include "mongo-register-express.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "mongo-register-express.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + labels: + {{- include "mongo-register-express.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "mongo-register-express.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.targetPort }} + protocol: TCP + env: + - name: ME_CONFIG_MONGODB_ADMINPASSWORD + value: {{ quote .Values.env.meConfigMongodbAdminpassword }} + - name: ME_CONFIG_MONGODB_ADMINUSERNAME + value: {{ quote .Values.env.meConfigMongodbAdminusername }} + - name: ME_CONFIG_MONGODB_URL + value: {{ quote .Values.env.meConfigMongodbUrl }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-register-express/templates/hpa.yaml b/helm/capif/charts/mongo-register-express/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3804acdf01e965be640383d284c58ab571df7891 --- /dev/null +++ b/helm/capif/charts/mongo-register-express/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "mongo-register-express.fullname" . }} + labels: + {{- include "mongo-register-express.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "mongo-register-express.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-register-express/templates/ingress.yaml b/helm/capif/charts/mongo-register-express/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..be3d87fd73e2a742cd613ba6a4f7f8e90bb1a68d --- /dev/null +++ b/helm/capif/charts/mongo-register-express/templates/ingress.yaml @@ -0,0 +1,63 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "mongo-register-express.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "mongo-register-express.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: mongo-register-express + port: + number: {{ $svcPort }} + {{- else }} + serviceName: mongo-register-express + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-register-express/templates/service.yaml b/helm/capif/charts/mongo-register-express/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7598b3877246da5bb1a3cd1243d0181487975d7f --- /dev/null +++ b/helm/capif/charts/mongo-register-express/templates/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Service +metadata: + name: mongo-register-express + labels: + {{- include "mongo-register-express.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .Values.service.targetPort }} + protocol: TCP + name: http + selector: + {{- include "mongo-register-express.selectorLabels" . | nindent 4 }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-register-express/templates/serviceaccount.yaml b/helm/capif/charts/mongo-register-express/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ade812aae0ac6ff79c952173fb6e8babb742f781 --- /dev/null +++ b/helm/capif/charts/mongo-register-express/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mongo-register-express.serviceAccountName" . }} + labels: + {{- include "mongo-register-express.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-register-express/templates/tests/test-connection.yaml b/helm/capif/charts/mongo-register-express/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cdafc6305b37ccd44cb71b453732b329389fb7d4 --- /dev/null +++ b/helm/capif/charts/mongo-register-express/templates/tests/test-connection.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "mongo-register-express.fullname" . }}-test-connection" + labels: + {{- include "mongo-register-express.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['mongo-register-express:{{ .Values.service.port }}'] + restartPolicy: Never +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-register-express/values.yaml b/helm/capif/charts/mongo-register-express/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dd225f5d39888dc1c3281da4584f9f211452a68b --- /dev/null +++ b/helm/capif/charts/mongo-register-express/values.yaml @@ -0,0 +1,115 @@ +# Default values for mongo-register-express. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +enabled: false + +replicaCount: 1 + +image: + repository: mongo-express + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "1.0.0-alpha.4" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + meConfigMongodbAdminusername: root + meConfigMongodbAdminpassword: example + meConfigMongodbUrl: mongodb://root:example@mongo-register:27017/ + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8082 + targetPort: 8081 + +ingress: + enabled: false + className: "nginx" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8081 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/mongo-register/.helmignore b/helm/capif/charts/mongo-register/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/mongo-register/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/mongo-register/Chart.yaml b/helm/capif/charts/mongo-register/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..08a4264470125209be19d9403a59e9b96cabafd2 --- /dev/null +++ b/helm/capif/charts/mongo-register/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: mongo-register +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/mongo-register/templates/NOTES.txt b/helm/capif/charts/mongo-register/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..4cbdf5989ac5315409a61aae2fdbf149ae2ffc22 --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mongo-register.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mongo-register.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mongo-register.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mongo-register.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/mongo-register/templates/_helpers.tpl b/helm/capif/charts/mongo-register/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..8ade9442dce911269dcba7d0d6d2b8f764be038d --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mongo-register.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mongo-register.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mongo-register.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mongo-register.labels" -}} +helm.sh/chart: {{ include "mongo-register.chart" . }} +{{ include "mongo-register.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mongo-register.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mongo-register.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mongo-register.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "mongo-register.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/mongo-register/templates/deployment.yaml b/helm/capif/charts/mongo-register/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..442eee66b2153cd25bbb0c48416cdda8c15f784c --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/deployment.yaml @@ -0,0 +1,73 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mongo-register.fullname" . }} + labels: + {{- include "mongo-register.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + strategy: + type: Recreate + selector: + matchLabels: + {{- include "mongo-register.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + labels: + {{- include "mongo-register.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "mongo-register.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONGO_INITDB_ROOT_PASSWORD + value: {{ quote .Values.env.mongoInitdbRootPassword }} + - name: MONGO_INITDB_ROOT_USERNAME + value: {{ quote .Values.env.mongoInitdbRootUsername }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/mongo-register/templates/hpa.yaml b/helm/capif/charts/mongo-register/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7dd1b59cd4f2d8070336d5fbc3dab8d9e6733f95 --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "mongo-register.fullname" . }} + labels: + {{- include "mongo-register.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "mongo-register.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/mongo-register/templates/ingress.yaml b/helm/capif/charts/mongo-register/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d4897eca40afba8bd376dea3798f1ebccec6dfdb --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "mongo-register.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "mongo-register.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/mongo-register/templates/pvc.yaml b/helm/capif/charts/mongo-register/templates/pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..13f17337ddd201d860557b3005ec7804cfbd3fdc --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/pvc.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + {{- include "mongo-register.labels" . | nindent 8 }} + name: mongo-register-pvc +spec: + storageClassName: {{ .Values.persistence.storageClass }} + accessModes: + - ReadWriteMany + resources: + requests: + storage: {{ .Values.persistence.storage }} \ No newline at end of file diff --git a/helm/capif/charts/mongo-register/templates/service.yaml b/helm/capif/charts/mongo-register/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..46ea1106e24016d5ad1c88ec0132880f7284e748 --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongo-register + labels: + {{- include "mongo-register.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "mongo-register.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/mongo-register/templates/serviceaccount.yaml b/helm/capif/charts/mongo-register/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..56e94e65ca7985054f4feef6d67d22afc1de1458 --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mongo-register.serviceAccountName" . }} + labels: + {{- include "mongo-register.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/mongo-register/templates/tests/test-connection.yaml b/helm/capif/charts/mongo-register/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4d0e00a92b63eac09a7655734e69014e29f7114d --- /dev/null +++ b/helm/capif/charts/mongo-register/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "mongo-register.fullname" . }}-test-connection" + labels: + {{- include "mongo-register.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['mongo-register:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/mongo-register/values.yaml b/helm/capif/charts/mongo-register/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dcb783f18c8e5a9a8659d98784528f7c15fd6043 --- /dev/null +++ b/helm/capif/charts/mongo-register/values.yaml @@ -0,0 +1,113 @@ +# Default values for mongo-register. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: mongo + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "6.0.2" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + mongoInitdbRootPassword: example + mongoInitdbRootUsername: root + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + runAsUser: 999 + +service: + type: ClusterIP + port: 27017 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 27017 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +persistence: + storage: 8Gi + storageClass: nfs-01 + +# Additional volumes on the output Deployment definition. +volumes: + - name: mongo-register-pvc + persistentVolumeClaim: + claimName: mongo-register-pvc + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: mongo-register-pvc + mountPath: /data/db + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/mongo/.helmignore b/helm/capif/charts/mongo/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/mongo/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/mongo/Chart.yaml b/helm/capif/charts/mongo/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..638bb4522a792c9c9d856c1fb3999b68c1da0edf --- /dev/null +++ b/helm/capif/charts/mongo/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: mongo +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/mongo/templates/NOTES.txt b/helm/capif/charts/mongo/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..1fcc59357a7cf685e5a054400018bfef1981c834 --- /dev/null +++ b/helm/capif/charts/mongo/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "mongo.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "mongo.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "mongo.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "mongo.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/mongo/templates/_helpers.tpl b/helm/capif/charts/mongo/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..cce4e1b2fbad0c83e5a4e6b8c76d9ebf3503af54 --- /dev/null +++ b/helm/capif/charts/mongo/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mongo.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "mongo.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mongo.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mongo.labels" -}} +helm.sh/chart: {{ include "mongo.chart" . }} +{{ include "mongo.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mongo.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mongo.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "mongo.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "mongo.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/mongo/templates/deployment.yaml b/helm/capif/charts/mongo/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..80cedad5207f48141191f03ba58e0ec9bdf09646 --- /dev/null +++ b/helm/capif/charts/mongo/templates/deployment.yaml @@ -0,0 +1,83 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "mongo.fullname" . }} + labels: + {{- include "mongo.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + strategy: + type: Recreate + selector: + matchLabels: + {{- include "mongo.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + labels: + {{- include "mongo.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "mongo.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONGO_INITDB_ROOT_PASSWORD + value: {{ quote .Values.env.mongoInitdbRootPassword }} + - name: MONGO_INITDB_ROOT_USERNAME + value: {{ quote .Values.env.mongoInitdbRootUsername }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: mongo-helper + image: busybox + command: + - sh + - -c + - while true ; do echo alive ; sleep 10 ; done + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/mongo/templates/hpa.yaml b/helm/capif/charts/mongo/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ae64b40ecf91f10a759b796c774fc5bb28696494 --- /dev/null +++ b/helm/capif/charts/mongo/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "mongo.fullname" . }} + labels: + {{- include "mongo.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "mongo.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/mongo/templates/ingress.yaml b/helm/capif/charts/mongo/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b173c907deeed66d02276ff4276fa6d4bf9269cc --- /dev/null +++ b/helm/capif/charts/mongo/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "mongo.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "mongo.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/mongo/templates/pvc.yaml b/helm/capif/charts/mongo/templates/pvc.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c0ceafd7e06ed2ea6cdee2596923eebaa79bfdba --- /dev/null +++ b/helm/capif/charts/mongo/templates/pvc.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + labels: + {{- include "mongo.labels" . | nindent 8 }} + name: mongo-pvc +spec: + storageClassName: {{ .Values.persistence.storageClass }} + accessModes: + - ReadWriteMany + resources: + requests: + storage: {{ .Values.persistence.storage }} \ No newline at end of file diff --git a/helm/capif/charts/mongo/templates/service.yaml b/helm/capif/charts/mongo/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..be5b5f42d2b956ac4416d2bd811b4acc4fde774d --- /dev/null +++ b/helm/capif/charts/mongo/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: mongo + labels: + {{- include "mongo.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "mongo.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/mongo/templates/serviceaccount.yaml b/helm/capif/charts/mongo/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..95b6769933bdcbe7c3e554b37e797a468fe1f37f --- /dev/null +++ b/helm/capif/charts/mongo/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "mongo.serviceAccountName" . }} + labels: + {{- include "mongo.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/mongo/templates/tests/test-connection.yaml b/helm/capif/charts/mongo/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4cf0b7f6f382bde9a3a4a3463cab9977b73133a6 --- /dev/null +++ b/helm/capif/charts/mongo/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "mongo.fullname" . }}-test-connection" + labels: + {{- include "mongo.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['mongo:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/mongo/values.yaml b/helm/capif/charts/mongo/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..38e4b9b9846ca5c27bb74899c3113a77a6b804dc --- /dev/null +++ b/helm/capif/charts/mongo/values.yaml @@ -0,0 +1,116 @@ +# Default values for mongo. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: mongo + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "6.0.2" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + mongoInitdbRootPassword: example + mongoInitdbRootUsername: root + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + runAsUser: 999 + +service: + type: ClusterIP + port: 27017 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + tcpSocket: + port: 27017 + initialDelaySeconds: 20 + periodSeconds: 5 + +readinessProbe: + tcpSocket: + port: 27017 +# initialDelaySeconds: 5 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +persistence: + storage: 8Gi + storageClass: nfs-01 + +# Additional volumes on the output Deployment definition. +volumes: + - name: mongo-pvc + persistentVolumeClaim: + claimName: mongo-pvc + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: mongo-pvc + mountPath: /data/db + +nodeSelector: {} + +tolerations: [] + +affinity: {} \ No newline at end of file diff --git a/helm/capif/charts/nginx/.helmignore b/helm/capif/charts/nginx/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/nginx/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/nginx/Chart.yaml b/helm/capif/charts/nginx/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3464a394b4da5052006464f8fce5db8631012b09 --- /dev/null +++ b/helm/capif/charts/nginx/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: nginx +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/nginx/templates/NOTES.txt b/helm/capif/charts/nginx/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..918bb6420d81c821d463a157d8f3b4d86d7af060 --- /dev/null +++ b/helm/capif/charts/nginx/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "nginx.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "nginx.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "nginx.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "nginx.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/nginx/templates/_helpers.tpl b/helm/capif/charts/nginx/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..ad9f4328e3ced783bd0327cc6c342cab2ce2b7b9 --- /dev/null +++ b/helm/capif/charts/nginx/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "nginx.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "nginx.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "nginx.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "nginx.labels" -}} +helm.sh/chart: {{ include "nginx.chart" . }} +{{ include "nginx.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "nginx.selectorLabels" -}} +app.kubernetes.io/name: {{ include "nginx.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "nginx.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "nginx.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/nginx/templates/deployment.yaml b/helm/capif/charts/nginx/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..221ebfd0a234ca4c12cf90abf9d9d1518b64c9cb --- /dev/null +++ b/helm/capif/charts/nginx/templates/deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "nginx.fullname" . }} + labels: + {{- include "nginx.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "nginx.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + labels: + {{- include "nginx.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "nginx.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + {{- range .Values.services }} + - name: {{ .name }} + containerPort: {{ .port }} + {{- end }} + env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.env.capifHostname }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.env.vaultAccessToken }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/nginx/templates/hpa.yaml b/helm/capif/charts/nginx/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b664f71a1c17420f7d2ca497b19ea49fb4c4b303 --- /dev/null +++ b/helm/capif/charts/nginx/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "nginx.fullname" . }} + labels: + {{- include "nginx.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "nginx.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/nginx/templates/ingress-route.yaml b/helm/capif/charts/nginx/templates/ingress-route.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5fec0968795cf423969337754a78fbaf4bbc7a36 --- /dev/null +++ b/helm/capif/charts/nginx/templates/ingress-route.yaml @@ -0,0 +1,25 @@ +{{- if eq .Values.ingress.className "IngressRoute" }} +{{- $fullName := include "nginx.fullname" . -}} +--- +apiVersion: traefik.containo.us/v1alpha1 +kind: IngressRoute +metadata: + name: {{ $fullName }}-route +spec: + entryPoints: [web] + routes: + - kind: Rule + {{- range .Values.ingress.hosts }} + match: Host(`{{ .host | quote }} && Path(`/ca-root`, `/sign-csr`, `/certdata`, `/register`, `/testdata`, `/getauth`, `/test`)`) + services: + - kind: Service + name: nginx + port: 8080 + scheme: http + - kind: Service + name: nginx + port: 443 + tls: + passthrough: true + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/nginx/templates/ingress.yaml b/helm/capif/charts/nginx/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..82f373e309624442fe6f6613818c524d6ae12e56 --- /dev/null +++ b/helm/capif/charts/nginx/templates/ingress.yaml @@ -0,0 +1,59 @@ +{{- if .Values.ingress.enabled -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: nginx-ingress + labels: + {{- include "nginx.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: nginx + port: + number: 443 + {{- else }} + serviceName: nginx + servicePort: 443 + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/nginx/templates/service.yaml b/helm/capif/charts/nginx/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..64821616c184fd9edb34d133bb5971f81aabe1a1 --- /dev/null +++ b/helm/capif/charts/nginx/templates/service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: nginx + labels: + {{- include "nginx.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + {{- range .Values.service.ports }} + - name: {{ .name }} + port: {{ .port }} + targetPort: {{ .targetPort }} + {{- end }} + selector: + {{- include "nginx.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/helm/capif/charts/nginx/templates/serviceaccount.yaml b/helm/capif/charts/nginx/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..02c08bb0cf32f86abcdee2ce4a67c27d51d93ef9 --- /dev/null +++ b/helm/capif/charts/nginx/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "nginx.serviceAccountName" . }} + labels: + {{- include "nginx.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/nginx/templates/tests/test-connection.yaml b/helm/capif/charts/nginx/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bdbc141bc183124af706c2934d2bcffe79035b1f --- /dev/null +++ b/helm/capif/charts/nginx/templates/tests/test-connection.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "test-connection" + labels: + {{- include "nginx.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + {{- range .Values.service.ports }} + - name: wget-{{ .name }} + image: busybox + command: ['wget'] + args: ['nginx:{{ .port }}'] + {{- end }} + restartPolicy: Never diff --git a/helm/capif/charts/nginx/values.yaml b/helm/capif/charts/nginx/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..db0541e9b82c3cf135ece746b3815f84cb6c9b25 --- /dev/null +++ b/helm/capif/charts/nginx/values.yaml @@ -0,0 +1,123 @@ +# Default values for nginx. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: nginx + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + capifHostname: my-capif.apps.ocp-epg.hi.inet + vaultHostname: vault-internal.mon.svc.cluster.local + vaultPort: 8200 + vaultAccessToken: dev-only-token + logLevel: "info" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + ports: + - name: "http" + port: 8080 + targetPort: 8080 + - name: "https" + port: 443 + targetPort: 443 + type: ClusterIP + + +ingress: + enabled: true + className: nginx + annotations: + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + nginx.ingress.kubernetes.io/ssl-redirect: "true" + hosts: + - host: nginx-example.local + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 20 + periodSeconds: 5 +readinessProbe: +# httpGet: +# path: / +# port: http + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-access-control-policy/.helmignore b/helm/capif/charts/ocf-access-control-policy/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-access-control-policy/Chart.yaml b/helm/capif/charts/ocf-access-control-policy/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bed944736358047f394df7acd417a1f89e572932 --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-access-control-policy +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-access-control-policy/templates/NOTES.txt b/helm/capif/charts/ocf-access-control-policy/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..9928abe2bea18db77c1a24b4f101fdd95ee3a6b1 --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-access-control-policy.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-access-control-policy.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-access-control-policy.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-access-control-policy.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-access-control-policy/templates/_helpers.tpl b/helm/capif/charts/ocf-access-control-policy/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..d446320287061b7bd7d1fccce9baf6f47350b776 --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-access-control-policy.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-access-control-policy.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-access-control-policy.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-access-control-policy.labels" -}} +helm.sh/chart: {{ include "ocf-access-control-policy.chart" . }} +{{ include "ocf-access-control-policy.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-access-control-policy.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-access-control-policy.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-access-control-policy.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-access-control-policy.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-access-control-policy/templates/deployment.yaml b/helm/capif/charts/ocf-access-control-policy/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..987f20960b1b7b5133f83925c40969734efde1a4 --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/templates/deployment.yaml @@ -0,0 +1,73 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-access-control-policy.fullname" . }} + labels: + {{- include "ocf-access-control-policy.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-access-control-policy.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + labels: + {{- include "ocf-access-control-policy.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-access-control-policy.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.env.capifHostname }} + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-access-control-policy/templates/hpa.yaml b/helm/capif/charts/ocf-access-control-policy/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3e5774e603a8bb59df050fe0dbca6a751bb9a3b6 --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-access-control-policy.fullname" . }} + labels: + {{- include "ocf-access-control-policy.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-access-control-policy.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-access-control-policy/templates/ingress.yaml b/helm/capif/charts/ocf-access-control-policy/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7aa1dc7c7e0db4e6c7fc5f019d142410f8b5512e --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-access-control-policy.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-access-control-policy.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-access-control-policy/templates/service.yaml b/helm/capif/charts/ocf-access-control-policy/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..16616bdca3ff6bdfb3fe26bfdf74c568d5fa9d60 --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: access-control-policy + labels: + {{- include "ocf-access-control-policy.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-access-control-policy.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-access-control-policy/templates/serviceaccount.yaml b/helm/capif/charts/ocf-access-control-policy/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0f513f2d572b00370bcd6473f6c715e131fb8742 --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-access-control-policy.serviceAccountName" . }} + labels: + {{- include "ocf-access-control-policy.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-access-control-policy/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-access-control-policy/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b19566f6db02ad8578c3e6616f2d3689ae94a5fd --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-access-control-policy.fullname" . }}-test-connection" + labels: + {{- include "ocf-access-control-policy.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['access-control-policy:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-access-control-policy/values.yaml b/helm/capif/charts/ocf-access-control-policy/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9184d264b10da5022f4ce435f902c50c64522e0c --- /dev/null +++ b/helm/capif/charts/ocf-access-control-policy/values.yaml @@ -0,0 +1,113 @@ +# Default values for ocf-access-control-policy. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: ocf-access-control-policy + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + capifHostname: my-capif.apps.ocp-epg.hi.inet + monitoring: "true" + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-api-invocation-logs/.helmignore b/helm/capif/charts/ocf-api-invocation-logs/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-api-invocation-logs/Chart.yaml b/helm/capif/charts/ocf-api-invocation-logs/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d735b1627724a558c170dee1e339711e8f97a152 --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-api-invocation-logs +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-api-invocation-logs/templates/NOTES.txt b/helm/capif/charts/ocf-api-invocation-logs/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..8c7da8081a6e6c968cbd734d68e58d2c1dee0b0f --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-api-invocation-logs.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-api-invocation-logs.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-api-invocation-logs.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-api-invocation-logs.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-api-invocation-logs/templates/_helpers.tpl b/helm/capif/charts/ocf-api-invocation-logs/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..f2a83cfe56d49588173f9b88e3a660f3061eab77 --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-api-invocation-logs.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-api-invocation-logs.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-api-invocation-logs.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-api-invocation-logs.labels" -}} +helm.sh/chart: {{ include "ocf-api-invocation-logs.chart" . }} +{{ include "ocf-api-invocation-logs.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-api-invocation-logs.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-api-invocation-logs.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-api-invocation-logs.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-api-invocation-logs.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/capif-invocation-configmap.yaml b/helm/capif/charts/ocf-api-invocation-logs/templates/configmap.yaml similarity index 83% rename from helm/capif/templates/capif-invocation-configmap.yaml rename to helm/capif/charts/ocf-api-invocation-logs/templates/configmap.yaml index 68fc1f1444f515a6802332096e140615fda3c69f..bd13f9f18e9d11ad35ccc041c1cc02f6224107da 100644 --- a/helm/capif/templates/capif-invocation-configmap.yaml +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/configmap.yaml @@ -5,8 +5,8 @@ metadata: data: config.yaml: | mongo: { - 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', 'db': 'capif', 'logs_col': 'invocationlogs', 'invoker_col': 'invokerdetails', diff --git a/helm/capif/charts/ocf-api-invocation-logs/templates/deployment.yaml b/helm/capif/charts/ocf-api-invocation-logs/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b0262fe0dfe21e7b354b07747e191d24a18e672e --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/deployment.yaml @@ -0,0 +1,80 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-api-invocation-logs.fullname" . }} + labels: + {{- include "ocf-api-invocation-logs.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-api-invocation-logs.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-api-invocation-logs.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-api-invocation-logs.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.env.capifHostname }} + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.env.vaultAccessToken }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-api-invocation-logs/templates/hpa.yaml b/helm/capif/charts/ocf-api-invocation-logs/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..71df2ef59670c55c25e0ec45103a783b46216b2d --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-api-invocation-logs.fullname" . }} + labels: + {{- include "ocf-api-invocation-logs.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-api-invocation-logs.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-invocation-logs/templates/ingress.yaml b/helm/capif/charts/ocf-api-invocation-logs/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..47f0f46504a3bdb84217c67780da1b6938c34c0c --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-api-invocation-logs.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-api-invocation-logs.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-invocation-logs/templates/service.yaml b/helm/capif/charts/ocf-api-invocation-logs/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..48614fd21b500b7f9babc5800532b74d69ec376e --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-invocation-logs + labels: + {{- include "ocf-api-invocation-logs.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-api-invocation-logs.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-api-invocation-logs/templates/serviceaccount.yaml b/helm/capif/charts/ocf-api-invocation-logs/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c08cfed4956ec0710f42544b29337470bea2a995 --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-api-invocation-logs.serviceAccountName" . }} + labels: + {{- include "ocf-api-invocation-logs.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-invocation-logs/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-api-invocation-logs/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3c3098b4fd411cc8df58b9f71435dfeefcbc83cf --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-api-invocation-logs.fullname" . }}-test-connection" + labels: + {{- include "ocf-api-invocation-logs.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['api-invocation-logs:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-api-invocation-logs/values.yaml b/helm/capif/charts/ocf-api-invocation-logs/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dc63d4b53ae11261428458a7926bf39fbf14815b --- /dev/null +++ b/helm/capif/charts/ocf-api-invocation-logs/values.yaml @@ -0,0 +1,120 @@ +# Default values for ocf-api-invocation-logs. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: ocf-api-invocation-logs-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + capifHostname: capif + vaultHostname: vault + vaultPort: 8200 + vaultAccessToken: dev-only-token + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 10 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: capif-invocation-config + configMap: + name: capif-invocation-configmap + items: + - key: "config.yaml" + path: "config.yaml" + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: capif-invocation-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-api-invoker-management/.helmignore b/helm/capif/charts/ocf-api-invoker-management/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-api-invoker-management/Chart.yaml b/helm/capif/charts/ocf-api-invoker-management/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2a9ef72f16a224e3790cf85e51a7d19e5b25eccd --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-api-invoker-management +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-api-invoker-management/templates/NOTES.txt b/helm/capif/charts/ocf-api-invoker-management/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..cfccd3a4e2fcdf1857a39c233204fcf25e427238 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-api-invoker-management.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-api-invoker-management.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-api-invoker-management.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-api-invoker-management.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-api-invoker-management/templates/_helpers.tpl b/helm/capif/charts/ocf-api-invoker-management/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..35e999458fd390872ce7ed4f0691a4fbeb101760 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-api-invoker-management.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-api-invoker-management.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-api-invoker-management.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-api-invoker-management.labels" -}} +helm.sh/chart: {{ include "ocf-api-invoker-management.chart" . }} +{{ include "ocf-api-invoker-management.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-api-invoker-management.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-api-invoker-management.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-api-invoker-management.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-api-invoker-management.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/capif-invoker-configmap.yaml b/helm/capif/charts/ocf-api-invoker-management/templates/configmap.yaml similarity index 61% rename from helm/capif/templates/capif-invoker-configmap.yaml rename to helm/capif/charts/ocf-api-invoker-management/templates/configmap.yaml index 32bab3cbcafbc40d0e028f75c33c1da2b811c240..4d83c986d75cee2cc228f2b34bae07ee8b95cfb7 100644 --- a/helm/capif/templates/capif-invoker-configmap.yaml +++ b/helm/capif/charts/ocf-api-invoker-management/templates/configmap.yaml @@ -5,8 +5,8 @@ metadata: data: config.yaml: | mongo: { - 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', 'db': 'capif', 'col': 'invokerdetails', 'capif_users_col': "user", @@ -16,17 +16,17 @@ data: 'port': "27017" } mongo_register: { - 'user': '{{ .Values.mongoRegister.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongoRegister.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoRegister.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoRegister.mongoInitdbRootPassword }}', 'db': 'capif_users', 'col': 'user', 'host': 'mongo-register', 'port': '27017' } ca_factory: { - "url": {{ quote .Values.parametersVault.env.vaultHostname }}, - "port": {{ quote .Values.parametersVault.env.vaultPort }}, - "token": {{ quote .Values.parametersVault.env.vaultAccessToken }} + "url": {{ quote .Values.env.vaultHostname }}, + "port": {{ quote .Values.env.vaultPort }}, + "token": {{ quote .Values.env.vaultAccessToken }} } monitoring: { diff --git a/helm/capif/charts/ocf-api-invoker-management/templates/deployment.yaml b/helm/capif/charts/ocf-api-invoker-management/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5b210cb25b01f71318975a84bd89256b11183b44 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/templates/deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-api-invoker-management.fullname" . }} + labels: + {{- include "ocf-api-invoker-management.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-api-invoker-management.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-api-invoker-management.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-api-invoker-management.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.env.vaultAccessToken }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-api-invoker-management/templates/hpa.yaml b/helm/capif/charts/ocf-api-invoker-management/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..44d58a78aaf6451153bd18955c9304371c71edb9 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-api-invoker-management.fullname" . }} + labels: + {{- include "ocf-api-invoker-management.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-api-invoker-management.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-invoker-management/templates/ingress.yaml b/helm/capif/charts/ocf-api-invoker-management/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..aee54f4b3ab4584a7e2b5e8bbee2f1a210ff69f4 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-api-invoker-management.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-api-invoker-management.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-invoker-management/templates/service.yaml b/helm/capif/charts/ocf-api-invoker-management/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f62fb9bee5e237a4b0ccafb57e3555251a264a91 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-invoker-management + labels: + {{- include "ocf-api-invoker-management.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-api-invoker-management.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-api-invoker-management/templates/serviceaccount.yaml b/helm/capif/charts/ocf-api-invoker-management/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c32851734d6651c5eb3847b50f2edbd5af791c5b --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-api-invoker-management.serviceAccountName" . }} + labels: + {{- include "ocf-api-invoker-management.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-invoker-management/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-api-invoker-management/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f194ec63aff0a8e396aa70940e9c23900d346699 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-api-invoker-management.fullname" . }}-test-connection" + labels: + {{- include "ocf-api-invoker-management.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['api-invoker-management:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-api-invoker-management/values.yaml b/helm/capif/charts/ocf-api-invoker-management/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e832c7d4ed28cd21113a6f367e2c9cbcfeb3af03 --- /dev/null +++ b/helm/capif/charts/ocf-api-invoker-management/values.yaml @@ -0,0 +1,120 @@ +# Default values for ocf-api-invoker-management. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: ocf-api-invoker-management-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + vaultHostname: vault + vaultPort: 8200 + vaultAccessToken: dev-only-token + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + mongoRegister: + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: capif-invoker-config + configMap: + name: capif-invoker-configmap + items: + - key: "config.yaml" + path: "config.yaml" + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: capif-invoker-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-api-provider-management/.helmignore b/helm/capif/charts/ocf-api-provider-management/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-api-provider-management/Chart.yaml b/helm/capif/charts/ocf-api-provider-management/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..773f014ce46e79ae2ddd0d0abe1255197b304f88 --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-api-provider-management +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-api-provider-management/templates/NOTES.txt b/helm/capif/charts/ocf-api-provider-management/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..d65d7c1af26244c91063337027eabb4f4c4dece9 --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-api-provider-management.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-api-provider-management.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-api-provider-management.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-api-provider-management.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-api-provider-management/templates/_helpers.tpl b/helm/capif/charts/ocf-api-provider-management/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..eb706b4960e38946df559aea75a813688ae44d1f --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-api-provider-management.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-api-provider-management.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-api-provider-management.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-api-provider-management.labels" -}} +helm.sh/chart: {{ include "ocf-api-provider-management.chart" . }} +{{ include "ocf-api-provider-management.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-api-provider-management.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-api-provider-management.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-api-provider-management.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-api-provider-management.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/capif-provider-configmap.yaml b/helm/capif/charts/ocf-api-provider-management/templates/configmap.yaml similarity index 60% rename from helm/capif/templates/capif-provider-configmap.yaml rename to helm/capif/charts/ocf-api-provider-management/templates/configmap.yaml index 28e530fddd16402c9f7ec70734bf6f0d82220bed..e59cfe179aa1e2cd88444e2785371a5b398a40de 100644 --- a/helm/capif/templates/capif-provider-configmap.yaml +++ b/helm/capif/charts/ocf-api-provider-management/templates/configmap.yaml @@ -5,8 +5,8 @@ metadata: data: config.yaml: | mongo: { - 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', 'db': 'capif', 'col': 'providerenrolmentdetails', 'certs_col': "certs", @@ -15,17 +15,17 @@ data: 'port': "27017" } mongo_register: { - 'user': '{{ .Values.mongoRegister.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongoRegister.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoRegister.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoRegister.mongoInitdbRootPassword }}', 'db': 'capif_users', 'col': 'user', 'host': 'mongo-register', 'port': '27017' } ca_factory: { - "url": {{ quote .Values.parametersVault.env.vaultHostname }}, - "port": {{ quote .Values.parametersVault.env.vaultPort }}, - "token": {{ quote .Values.parametersVault.env.vaultAccessToken }} + "url": {{ quote .Values.env.vaultHostname }}, + "port": {{ quote .Values.env.vaultPort }}, + "token": {{ quote .Values.env.vaultAccessToken }} } diff --git a/helm/capif/charts/ocf-api-provider-management/templates/deployment.yaml b/helm/capif/charts/ocf-api-provider-management/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7f95b9d602eb70ce4eeb5b34df18d506eef47d1b --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/templates/deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-api-provider-management.fullname" . }} + labels: + {{- include "ocf-api-provider-management.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-api-provider-management.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-api-provider-management.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-api-provider-management.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.env.vaultAccessToken }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-api-provider-management/templates/hpa.yaml b/helm/capif/charts/ocf-api-provider-management/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f3453cc6fdf2ce37c74e08cde742c1a1676c7d4e --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-api-provider-management.fullname" . }} + labels: + {{- include "ocf-api-provider-management.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-api-provider-management.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-provider-management/templates/ingress.yaml b/helm/capif/charts/ocf-api-provider-management/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2edad453f1f3acc5cd2405e47693536f69cd3915 --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-api-provider-management.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-api-provider-management.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-provider-management/templates/service.yaml b/helm/capif/charts/ocf-api-provider-management/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cf51d10b557348740ea9ba93abdf7e1934a5c59d --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: api-provider-management + labels: + {{- include "ocf-api-provider-management.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-api-provider-management.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-api-provider-management/templates/serviceaccount.yaml b/helm/capif/charts/ocf-api-provider-management/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..39bbc5c6dab16f8c0f716cd93c605e07c21caf10 --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-api-provider-management.serviceAccountName" . }} + labels: + {{- include "ocf-api-provider-management.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-api-provider-management/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-api-provider-management/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c8ca529574a46b66e7e5d7482eb82a8de1a01eec --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-api-provider-management.fullname" . }}-test-connection" + labels: + {{- include "ocf-api-provider-management.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['api-provider-management:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-api-provider-management/values.yaml b/helm/capif/charts/ocf-api-provider-management/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..547bb05431771b6e9a3668f7b133119781e8b4a7 --- /dev/null +++ b/helm/capif/charts/ocf-api-provider-management/values.yaml @@ -0,0 +1,120 @@ +# Default values for ocf-api-provider-management. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: ocf-api-provider-management-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + vaultHostname: vault + vaultPort: 8200 + vaultAccessToken: dev-only-token + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + mongoRegister: + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: capif-provider-config + configMap: + name: capif-provider-configmap + items: + - key: "config.yaml" + path: "config.yaml" + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: capif-provider-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-auditing-api-logs/.helmignore b/helm/capif/charts/ocf-auditing-api-logs/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-auditing-api-logs/Chart.yaml b/helm/capif/charts/ocf-auditing-api-logs/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dd3585c35ca18a4c1229d0d4b05299cf97e990d7 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-auditing-api-logs +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/templates/capif-logs-configmap.yaml b/helm/capif/charts/ocf-auditing-api-logs/configmap.yaml similarity index 80% rename from helm/capif/templates/capif-logs-configmap.yaml rename to helm/capif/charts/ocf-auditing-api-logs/configmap.yaml index 53cae6ea3eaf65b017001ef504367eef67ce15d2..729d751f3656155cb05d6b3b4ea28b80c350cb97 100644 --- a/helm/capif/templates/capif-logs-configmap.yaml +++ b/helm/capif/charts/ocf-auditing-api-logs/configmap.yaml @@ -5,8 +5,8 @@ metadata: data: config.yaml: | mongo: { - 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', 'db': 'capif', 'logs_col': 'invocationlogs', 'capif_users_col': "user", diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/NOTES.txt b/helm/capif/charts/ocf-auditing-api-logs/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..639b66801e9ad454868bdbc1903616e1fa7bd709 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-auditing-api-logs.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-auditing-api-logs.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-auditing-api-logs.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-auditing-api-logs.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/_helpers.tpl b/helm/capif/charts/ocf-auditing-api-logs/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..6f69487ba371dbf5c3896902a936f36b56bf8d89 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-auditing-api-logs.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-auditing-api-logs.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-auditing-api-logs.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-auditing-api-logs.labels" -}} +helm.sh/chart: {{ include "ocf-auditing-api-logs.chart" . }} +{{ include "ocf-auditing-api-logs.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-auditing-api-logs.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-auditing-api-logs.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-auditing-api-logs.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-auditing-api-logs.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/configmap.yaml b/helm/capif/charts/ocf-auditing-api-logs/templates/configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..729d751f3656155cb05d6b3b4ea28b80c350cb97 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/configmap.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: capif-logs-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'logs_col': 'invocationlogs', + 'capif_users_col': "user", + 'host': 'mongo', + 'port': "27017" + } + + monitoring: { + "fluent_bit_host": fluent-bit, + "fluent_bit_port": 24224, + "opentelemetry_url": "otel-collector", + "opentelemetry_port": "55680", + "opentelemetry_max_queue_size": 8192, + "opentelemetry_schedule_delay_millis": 20000, + "opentelemetry_max_export_batch_size": 2048, + "opentelemetry_export_timeout_millis": 60000 + } + diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/deployment.yaml b/helm/capif/charts/ocf-auditing-api-logs/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8248606b8385e819a3df8b58513685c2c5c004fd --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/deployment.yaml @@ -0,0 +1,72 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-auditing-api-logs.fullname" . }} + labels: + {{- include "ocf-auditing-api-logs.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-auditing-api-logs.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-auditing-api-logs.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-auditing-api-logs.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/hpa.yaml b/helm/capif/charts/ocf-auditing-api-logs/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4133851d6ed4a9c56fc2b42ae7bafa99de2913e4 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-auditing-api-logs.fullname" . }} + labels: + {{- include "ocf-auditing-api-logs.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-auditing-api-logs.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/ingress.yaml b/helm/capif/charts/ocf-auditing-api-logs/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1a63f2f1c393a29d9c13c0d9e91d28b044b36318 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-auditing-api-logs.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-auditing-api-logs.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/service.yaml b/helm/capif/charts/ocf-auditing-api-logs/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cc0a6858516a3cfe5249ee04de416bb64eaf64f3 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: logs + labels: + {{- include "ocf-auditing-api-logs.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-auditing-api-logs.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/serviceaccount.yaml b/helm/capif/charts/ocf-auditing-api-logs/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7cc126f50eeed851dfe8f08373cd71e0352c2b49 --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-auditing-api-logs.serviceAccountName" . }} + labels: + {{- include "ocf-auditing-api-logs.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-auditing-api-logs/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-auditing-api-logs/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ddd02e7f83aa06ed90049db1bc2803b590addddc --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-auditing-api-logs.fullname" . }}-test-connection" + labels: + {{- include "ocf-auditing-api-logs.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['logs:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-auditing-api-logs/values.yaml b/helm/capif/charts/ocf-auditing-api-logs/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..859ba129d567caf4b1ca047d05e531a9bcddf3ea --- /dev/null +++ b/helm/capif/charts/ocf-auditing-api-logs/values.yaml @@ -0,0 +1,116 @@ +# Default values for ocf-auditing-api-logs. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: auditing-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: capif-logs-config + configMap: + name: capif-logs-configmap + items: + - key: "config.yaml" + path: "config.yaml" + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: capif-logs-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-discover-service-api/.helmignore b/helm/capif/charts/ocf-discover-service-api/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-discover-service-api/Chart.yaml b/helm/capif/charts/ocf-discover-service-api/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3bffbb8ac0f624fc2b1648fb7ad3aa9ce3098849 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-discover-service-api +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-discover-service-api/templates/NOTES.txt b/helm/capif/charts/ocf-discover-service-api/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..64d223081e221900c4e1addd5b9ba6274c1ac3cc --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-discover-service-api.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-discover-service-api.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-discover-service-api.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-discover-service-api.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-discover-service-api/templates/_helpers.tpl b/helm/capif/charts/ocf-discover-service-api/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..2c42280ec9edf4d9a42fa4962bc1612619a6ceb7 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-discover-service-api.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-discover-service-api.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-discover-service-api.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-discover-service-api.labels" -}} +helm.sh/chart: {{ include "ocf-discover-service-api.chart" . }} +{{ include "ocf-discover-service-api.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-discover-service-api.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-discover-service-api.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-discover-service-api.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-discover-service-api.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/capif-service-configmap.yaml b/helm/capif/charts/ocf-discover-service-api/templates/configmap.yaml similarity index 81% rename from helm/capif/templates/capif-service-configmap.yaml rename to helm/capif/charts/ocf-discover-service-api/templates/configmap.yaml index 1cd3d6610c9e3850ec0231f3680345fac8aad969..96d0c367f3380331806c9c040a985cf22f9b4b27 100644 --- a/helm/capif/templates/capif-service-configmap.yaml +++ b/helm/capif/charts/ocf-discover-service-api/templates/configmap.yaml @@ -5,8 +5,8 @@ metadata: data: config.yaml: | mongo: { - 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', 'db': 'capif', 'col': 'serviceapidescriptions', 'invokers_col': 'invokerdetails', diff --git a/helm/capif/charts/ocf-discover-service-api/templates/deployment.yaml b/helm/capif/charts/ocf-discover-service-api/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0c6bfb02fe9fdf8376c865e33f7ee64b19447399 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/templates/deployment.yaml @@ -0,0 +1,72 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-discover-service-api.fullname" . }} + labels: + {{- include "ocf-discover-service-api.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-discover-service-api.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-discover-service-api.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-discover-service-api.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-discover-service-api/templates/hpa.yaml b/helm/capif/charts/ocf-discover-service-api/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bb4c30108f1f4c6ad5eb06d2fbad476c136448f5 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-discover-service-api.fullname" . }} + labels: + {{- include "ocf-discover-service-api.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-discover-service-api.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-discover-service-api/templates/ingress.yaml b/helm/capif/charts/ocf-discover-service-api/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b5187292641e3869ed3d61bfeff4cbcbe4691835 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-discover-service-api.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-discover-service-api.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-discover-service-api/templates/service.yaml b/helm/capif/charts/ocf-discover-service-api/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fda46c37a5b6f417967729be1279196a2b3f3692 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: service-apis + labels: + {{- include "ocf-discover-service-api.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-discover-service-api.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-discover-service-api/templates/serviceaccount.yaml b/helm/capif/charts/ocf-discover-service-api/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..be789193c71fd550cb8b2819bf182d3f12d9abf9 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-discover-service-api.serviceAccountName" . }} + labels: + {{- include "ocf-discover-service-api.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-discover-service-api/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-discover-service-api/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3551457a5509607abffe1fdff612aeae18ac6a4e --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-discover-service-api.fullname" . }}-test-connection" + labels: + {{- include "ocf-discover-service-api.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['service-apis:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-discover-service-api/values.yaml b/helm/capif/charts/ocf-discover-service-api/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6aa8e611bff38c395604f22d17b730663905b8a6 --- /dev/null +++ b/helm/capif/charts/ocf-discover-service-api/values.yaml @@ -0,0 +1,117 @@ +# Default values for ocf-discover-service-api. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: discover-service-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: capif-service-config + configMap: + name: capif-service-configmap + items: + - key: "config.yaml" + path: "config.yaml" + + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: capif-service-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-events/.helmignore b/helm/capif/charts/ocf-events/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-events/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-events/Chart.yaml b/helm/capif/charts/ocf-events/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9e9667fd23cdb8dcec69b3d70bef1368ed3ea137 --- /dev/null +++ b/helm/capif/charts/ocf-events/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-events +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-events/templates/NOTES.txt b/helm/capif/charts/ocf-events/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..2fe07465d9d89220e6fd9c98b7ae8e96232e86ed --- /dev/null +++ b/helm/capif/charts/ocf-events/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-events.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-events.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-events.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-events.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-events/templates/_helpers.tpl b/helm/capif/charts/ocf-events/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..1c0caa6698fad8013869ef62c03ed2b95cc2d7f7 --- /dev/null +++ b/helm/capif/charts/ocf-events/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-events.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-events.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-events.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-events.labels" -}} +helm.sh/chart: {{ include "ocf-events.chart" . }} +{{ include "ocf-events.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-events.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-events.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-events.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-events.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/capif-events-configmap.yaml b/helm/capif/charts/ocf-events/templates/configmap.yaml similarity index 82% rename from helm/capif/templates/capif-events-configmap.yaml rename to helm/capif/charts/ocf-events/templates/configmap.yaml index ca31c23ec295806d0941623b19848a920ada61b9..a928cac58ffce782abccb40375ae00cfeae41a24 100644 --- a/helm/capif/templates/capif-events-configmap.yaml +++ b/helm/capif/charts/ocf-events/templates/configmap.yaml @@ -5,8 +5,8 @@ metadata: data: config.yaml: | mongo: { - 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', 'db': 'capif', 'col': 'eventsdetails', 'certs_col': "certs", @@ -25,4 +25,4 @@ data: "opentelemetry_schedule_delay_millis": 20000, "opentelemetry_max_export_batch_size": 2048, "opentelemetry_export_timeout_millis": 60000 - } + } \ No newline at end of file diff --git a/helm/capif/charts/ocf-events/templates/deployment.yaml b/helm/capif/charts/ocf-events/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..50b58cc909d0f3878268457fa6d6610066e0ceb9 --- /dev/null +++ b/helm/capif/charts/ocf-events/templates/deployment.yaml @@ -0,0 +1,72 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-events.fullname" . }} + labels: + {{- include "ocf-events.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-events.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-events.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-events.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-events/templates/hpa.yaml b/helm/capif/charts/ocf-events/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f494b0322e7c1fedf398b715e4a149732210b73e --- /dev/null +++ b/helm/capif/charts/ocf-events/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-events.fullname" . }} + labels: + {{- include "ocf-events.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-events.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-events/templates/ingress.yaml b/helm/capif/charts/ocf-events/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9844a7f08861b750869af8e47f7a61ed1642e5ce --- /dev/null +++ b/helm/capif/charts/ocf-events/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-events.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-events.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-events/templates/service.yaml b/helm/capif/charts/ocf-events/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..dd54acae3a8762966cac4d06f9cbc485c894f73b --- /dev/null +++ b/helm/capif/charts/ocf-events/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: capif-events + labels: + {{- include "ocf-events.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-events.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-events/templates/serviceaccount.yaml b/helm/capif/charts/ocf-events/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f29121ae1598f7c47f6601493cf2b77326e24982 --- /dev/null +++ b/helm/capif/charts/ocf-events/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-events.serviceAccountName" . }} + labels: + {{- include "ocf-events.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-events/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-events/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fc2243308fceb55fc1382fd53671a61ca4bc2f18 --- /dev/null +++ b/helm/capif/charts/ocf-events/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-events.fullname" . }}-test-connection" + labels: + {{- include "ocf-events.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['capif-events:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-events/values.yaml b/helm/capif/charts/ocf-events/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b3ca6b0cdef9cf244e733e986365e0b7853b0334 --- /dev/null +++ b/helm/capif/charts/ocf-events/values.yaml @@ -0,0 +1,116 @@ +# Default values for ocf-events. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: events-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: capif-events-config + configMap: + name: capif-events-configmap + items: + - key: "config.yaml" + path: "config.yaml" + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: capif-events-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-helper/.helmignore b/helm/capif/charts/ocf-helper/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-helper/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-helper/Chart.yaml b/helm/capif/charts/ocf-helper/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ac740bc6db0d0d23687c74f95c6bc9e33772206b --- /dev/null +++ b/helm/capif/charts/ocf-helper/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-helper +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-helper/templates/NOTES.txt b/helm/capif/charts/ocf-helper/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..abd131876d4961f0b2b6feaff90fc993078e473f --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-helper.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-helper.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-helper.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-helper.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-helper/templates/_helpers.tpl b/helm/capif/charts/ocf-helper/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..df679e324422695bb8e7f7d6f89df54b59cf6f68 --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-helper.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-helper.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-helper.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-helper.labels" -}} +helm.sh/chart: {{ include "ocf-helper.chart" . }} +{{ include "ocf-helper.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-helper.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-helper.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-helper.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-helper.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-helper/templates/deployment.yaml b/helm/capif/charts/ocf-helper/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..16f43a0226d2d4d580799ee5252f46a4820c0712 --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/deployment.yaml @@ -0,0 +1,78 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-helper.fullname" . }} + labels: + {{- include "ocf-helper.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-helper.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/ocf-helper-configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-helper.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-helper.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.env.capifHostname }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.env.vaultAccessToken }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-helper/templates/hpa.yaml b/helm/capif/charts/ocf-helper/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..670686abeeddfe767164c1d4a7282af2a23049cb --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-helper.fullname" . }} + labels: + {{- include "ocf-helper.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-helper.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-helper/templates/ingress.yaml b/helm/capif/charts/ocf-helper/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..76d37c85807a6ca1e23ea0b676ed44d67a72cecd --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-helper.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-helper.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-helper/templates/ocf-helper-configmap.yaml b/helm/capif/charts/ocf-helper/templates/ocf-helper-configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..796a55cf7e451343b05c793a4bb1eb40486029f2 --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/ocf-helper-configmap.yaml @@ -0,0 +1,24 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: ocf-helper-configmap +data: + config.yaml: | + mongo: { + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', + 'db': 'capif', + 'invoker_col': 'invokerdetails', + 'provider_col': 'providerenrolmentdetails', + 'col_services': "serviceapidescriptions", + 'col_security': "security", + 'col_event': "eventsdetails", + 'host': '{{ .Values.env.mongoHost }}', + 'port': "{{ .Values.env.mongoPort }}" + } + + ca_factory: { + "url": {{ quote .Values.env.vaultHostname }}, + "port": {{ quote .Values.env.vaultPort }}, + "token": {{ quote .Values.env.vaultAccessToken }} + } \ No newline at end of file diff --git a/helm/capif/charts/ocf-helper/templates/service.yaml b/helm/capif/charts/ocf-helper/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..87006ebaeabdd5d23bae463f5660099f9d74f824 --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: helper + labels: + {{- include "ocf-helper.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-helper.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-helper/templates/serviceaccount.yaml b/helm/capif/charts/ocf-helper/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a3da0593c11791f56c4d3b7cbf0502b1b118e182 --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-helper.serviceAccountName" . }} + labels: + {{- include "ocf-helper.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-helper/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-helper/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..57760421413aef99ceb4b63f2c3a24a7f0be0e43 --- /dev/null +++ b/helm/capif/charts/ocf-helper/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-helper.fullname" . }}-test-connection" + labels: + {{- include "ocf-helper.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['helper:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-helper/values.yaml b/helm/capif/charts/ocf-helper/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f9e35bdb8134283ce065ef657e496f6d1c0336e2 --- /dev/null +++ b/helm/capif/charts/ocf-helper/values.yaml @@ -0,0 +1,120 @@ +# Default values for ocf-helper. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: "ocf-helper" + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + vaultHostname: vault-internal.mon.svc.cluster.local + vaultPort: 8200 + vaultAccessToken: dev-only-token + mongoHost: mongo + mongoPort: 27017 + capifHostname: capif + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: + app: ocf-ocf-helper + +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + tcpSocket: + port: 8080 +readinessProbe: + tcpSocket: + port: 8080 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: ocf-helper-configmap + configMap: + name: ocf-helper-configmap + items: + - key: "config.yaml" + path: "config.yaml" + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: ocf-helper-configmap + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-publish-service-api/.helmignore b/helm/capif/charts/ocf-publish-service-api/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-publish-service-api/Chart.yaml b/helm/capif/charts/ocf-publish-service-api/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..166d252382ca14ef29516690bcf32b1f09e46ca0 --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-publish-service-api +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-publish-service-api/templates/NOTES.txt b/helm/capif/charts/ocf-publish-service-api/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..deaaa58854f5113d5e5af75e6acfeda67acaf752 --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-publish-service-api.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-publish-service-api.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-publish-service-api.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-publish-service-api.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-publish-service-api/templates/_helpers.tpl b/helm/capif/charts/ocf-publish-service-api/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..9ca28fabff67cce7fe1cf6223e595e87ed805abd --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-publish-service-api.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-publish-service-api.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-publish-service-api.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-publish-service-api.labels" -}} +helm.sh/chart: {{ include "ocf-publish-service-api.chart" . }} +{{ include "ocf-publish-service-api.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-publish-service-api.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-publish-service-api.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-publish-service-api.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-publish-service-api.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/capif-published-configmap.yaml b/helm/capif/charts/ocf-publish-service-api/templates/configmap.yaml similarity index 81% rename from helm/capif/templates/capif-published-configmap.yaml rename to helm/capif/charts/ocf-publish-service-api/templates/configmap.yaml index 507afd4a769e5598435bdf084fec5e866bad04d2..a76b2f2bbe1772205d1707635efb3df3209eeb8e 100644 --- a/helm/capif/templates/capif-published-configmap.yaml +++ b/helm/capif/charts/ocf-publish-service-api/templates/configmap.yaml @@ -5,8 +5,8 @@ metadata: data: config.yaml: | mongo: { - 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', 'db': 'capif', 'col': 'serviceapidescriptions', 'certs_col': "certs", diff --git a/helm/capif/charts/ocf-publish-service-api/templates/deployment.yaml b/helm/capif/charts/ocf-publish-service-api/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ceced651510218511744d9148811ee35f07fa01d --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/templates/deployment.yaml @@ -0,0 +1,72 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-publish-service-api.fullname" . }} + labels: + {{- include "ocf-publish-service-api.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-publish-service-api.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-publish-service-api.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-publish-service-api.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-publish-service-api/templates/hpa.yaml b/helm/capif/charts/ocf-publish-service-api/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..34c23685058274ee00eed5212e12fc56e3c98abf --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-publish-service-api.fullname" . }} + labels: + {{- include "ocf-publish-service-api.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-publish-service-api.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-publish-service-api/templates/ingress.yaml b/helm/capif/charts/ocf-publish-service-api/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..22cd9f36db99754c22c736ae633e7ae8282efc4c --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-publish-service-api.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-publish-service-api.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-publish-service-api/templates/service.yaml b/helm/capif/charts/ocf-publish-service-api/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2412215a5d3268e1c299c6f32d4a38124695c690 --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: published-apis + labels: + {{- include "ocf-publish-service-api.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-publish-service-api.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-publish-service-api/templates/serviceaccount.yaml b/helm/capif/charts/ocf-publish-service-api/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..22ca36f7ec915dcbe35ce7344ff7a009e27856f6 --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-publish-service-api.serviceAccountName" . }} + labels: + {{- include "ocf-publish-service-api.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-publish-service-api/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-publish-service-api/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..edbd061a6ec7b8b88016e0c6a8758f7aa263c21b --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-publish-service-api.fullname" . }}-test-connection" + labels: + {{- include "ocf-publish-service-api.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['published-apis:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-publish-service-api/values.yaml b/helm/capif/charts/ocf-publish-service-api/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ac32a9800a93bbb7cbf2a2125cf2b6668608805d --- /dev/null +++ b/helm/capif/charts/ocf-publish-service-api/values.yaml @@ -0,0 +1,116 @@ +# Default values for ocf-publish-service-api. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: publish-service-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: capif-published-config + configMap: + name: capif-published-configmap + items: + - key: "config.yaml" + path: "config.yaml" + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: capif-published-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-register/.helmignore b/helm/capif/charts/ocf-register/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-register/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-register/Chart.yaml b/helm/capif/charts/ocf-register/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..06dee8073879bd8dbd214be935e1101de7b70d2a --- /dev/null +++ b/helm/capif/charts/ocf-register/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-register +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-register/templates/NOTES.txt b/helm/capif/charts/ocf-register/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..f323bac844d2aace1c9dfb771cdd84a72ca9220d --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-register.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-register.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-register.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-register.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-register/templates/_helpers.tpl b/helm/capif/charts/ocf-register/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..c1d5489e1e66d3854db395fe5a8d1e1678efede1 --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-register.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-register.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-register.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-register.labels" -}} +helm.sh/chart: {{ include "ocf-register.chart" . }} +{{ include "ocf-register.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-register.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-register.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-register.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-register.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-register/templates/configmap.yaml b/helm/capif/charts/ocf-register/templates/configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0c01aedcddf6b4159a86ea52db051e809155e0b3 --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/configmap.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: register-configmap +data: + config.yaml: |- + mongo: { + 'user': 'root', + 'password': 'example', + 'db': 'capif_users', + 'col': 'user', + 'admins': 'admins', + 'host': '{{ .Values.env.mongoHost }}', + 'port': '{{ .Values.env.mongoPort }}' + } + ca_factory: { + "url": "{{ .Values.env.vaultHostname }}", + "port": "{{ .Values.env.vaultPort }}", + "token": "{{ .Values.env.vaultAccessToken }}" + } + ccf: { + "url": "{{ .Values.env.capifHostname }}", + "helper_remove_user": "/helper/deleteEntities/" + } + register: { + register_uuid: '6ba7b810-9dad-11d1-80b4-00c04fd430c8', + refresh_expiration: 30, #days + token_expiration: 10, #mins + admin_users: {admin_user: "admin", + admin_pass: "password123"} + } diff --git a/helm/capif/charts/ocf-register/templates/deployment.yaml b/helm/capif/charts/ocf-register/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0009f19fd1e709ea12b9072ff0b7938c14f90692 --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/deployment.yaml @@ -0,0 +1,76 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-register.fullname" . }} + labels: + {{- include "ocf-register.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-register.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-register.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-register.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: VAULT_HOSTNAME + value: {{ quote .Values.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.env.vaultAccessToken }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-register/templates/hpa.yaml b/helm/capif/charts/ocf-register/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..936dbb442fa042090b594ec46165477255d53a44 --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-register.fullname" . }} + labels: + {{- include "ocf-register.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-register.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-register/templates/ingress.yaml b/helm/capif/charts/ocf-register/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c5911eb22a274e2692e1b6466f12ba96faef3a49 --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/ingress.yaml @@ -0,0 +1,60 @@ +{{- if .Values.ingress.enabled -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: nginx-register + labels: + {{- include "ocf-register.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: register + port: + number: {{ $svcPort }} + {{- else }} + serviceName: register + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-register/templates/service.yaml b/helm/capif/charts/ocf-register/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ae6f7f61016530ecf8d76c781b881885a484b266 --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: register + labels: + {{- include "ocf-register.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: 8080 + protocol: TCP + name: http + selector: + {{- include "ocf-register.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-register/templates/serviceaccount.yaml b/helm/capif/charts/ocf-register/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d29545617aaa0a37d444cbd498ced77462a0947c --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-register.serviceAccountName" . }} + labels: + {{- include "ocf-register.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-register/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-register/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..40831f659dc9b7ff38b7b50908b6b1025f92b846 --- /dev/null +++ b/helm/capif/charts/ocf-register/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-register.fullname" . }}-test-connection" + labels: + {{- include "ocf-register.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['register:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-register/values.yaml b/helm/capif/charts/ocf-register/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ca8cfc3f43551526356ebf2250762c5f7c9c9d69 --- /dev/null +++ b/helm/capif/charts/ocf-register/values.yaml @@ -0,0 +1,120 @@ +# Default values for ocf-register. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: register + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + mongoHost: mongo-register + mongoPort: 27017 + vaultHostname: vault + vaultPort: 8200 + vaultAccessToken: dev-only-token + capifHostname: capif-test.example.int + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8084 + +ingress: + enabled: true + className: "nginx" + annotations: + #cert-manager.io/issuer: letsencrypt-issuer + nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" + nginx.ingress.kubernetes.io/ssl-passthrough: "true" + nginx.ingress.kubernetes.io/ssl-redirect: "true" + hosts: + - host: register.app.ocp-epg.hi.inet + paths: + - path: / + pathType: Prefix + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: register-configmap + configMap: + name: register-configmap + items: + - key: "config.yaml" + path: "config.yaml" + + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: register-configmap + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-routing-info/.helmignore b/helm/capif/charts/ocf-routing-info/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-routing-info/Chart.yaml b/helm/capif/charts/ocf-routing-info/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bf109e2ab9e69a5c54432fcc02c13c80535163ad --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-routing-info +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-routing-info/templates/NOTES.txt b/helm/capif/charts/ocf-routing-info/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..f08d1a05273d56d24322d10898bd6a6924048bb9 --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-routing-info.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-routing-info.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-routing-info.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-routing-info.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-routing-info/templates/_helpers.tpl b/helm/capif/charts/ocf-routing-info/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..58bef4e641305e6299ca38701f5a5b84031af278 --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-routing-info.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-routing-info.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-routing-info.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-routing-info.labels" -}} +helm.sh/chart: {{ include "ocf-routing-info.chart" . }} +{{ include "ocf-routing-info.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-routing-info.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-routing-info.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-routing-info.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-routing-info.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-routing-info/templates/deployment.yaml b/helm/capif/charts/ocf-routing-info/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..214f38fbe1ebbf4c451e6ee5e189a9981f49a8fe --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/templates/deployment.yaml @@ -0,0 +1,71 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-routing-info.fullname" . }} + labels: + {{- include "ocf-routing-info.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-routing-info.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + labels: + {{- include "ocf-routing-info.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-routing-info.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-routing-info/templates/hpa.yaml b/helm/capif/charts/ocf-routing-info/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6172807bb8f75d9e75f79223456e5f897f73912d --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-routing-info.fullname" . }} + labels: + {{- include "ocf-routing-info.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-routing-info.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-routing-info/templates/ingress.yaml b/helm/capif/charts/ocf-routing-info/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cf74fa945cc6675a0ad2d70c4fedb39f9f7ba8b5 --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-routing-info.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-routing-info.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-routing-info/templates/service.yaml b/helm/capif/charts/ocf-routing-info/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..125bf085ccd84032dd835c361ee05bc22095a973 --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: capif-routing-info + labels: + {{- include "ocf-routing-info.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-routing-info.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-routing-info/templates/serviceaccount.yaml b/helm/capif/charts/ocf-routing-info/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6d1721d348c317cc0cc4f92e8dc28b931ff71cbd --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-routing-info.serviceAccountName" . }} + labels: + {{- include "ocf-routing-info.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-routing-info/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-routing-info/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..26169c1408a69ded1d397992773e344f9f5f0432 --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-routing-info.fullname" . }}-test-connection" + labels: + {{- include "ocf-routing-info.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['capif-routing-info:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-routing-info/values.yaml b/helm/capif/charts/ocf-routing-info/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d6c6a3d63c48e8d517347f2c1df70704b218ee56 --- /dev/null +++ b/helm/capif/charts/ocf-routing-info/values.yaml @@ -0,0 +1,112 @@ +# Default values for ocf-routing-info. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: routing-info-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/ocf-security/.helmignore b/helm/capif/charts/ocf-security/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/ocf-security/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/ocf-security/Chart.yaml b/helm/capif/charts/ocf-security/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..93606cd6e5dc2315bea00f2a117feea2c3423df3 --- /dev/null +++ b/helm/capif/charts/ocf-security/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: ocf-security +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/ocf-security/templates/NOTES.txt b/helm/capif/charts/ocf-security/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..3654878ac39c7642e096ad255a8aeb6ba7e76a1e --- /dev/null +++ b/helm/capif/charts/ocf-security/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "ocf-security.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "ocf-security.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "ocf-security.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "ocf-security.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/ocf-security/templates/_helpers.tpl b/helm/capif/charts/ocf-security/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..11c7d3faf525a8212c78bf762e6f2298e747df64 --- /dev/null +++ b/helm/capif/charts/ocf-security/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "ocf-security.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "ocf-security.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "ocf-security.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "ocf-security.labels" -}} +helm.sh/chart: {{ include "ocf-security.chart" . }} +{{ include "ocf-security.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "ocf-security.selectorLabels" -}} +app.kubernetes.io/name: {{ include "ocf-security.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "ocf-security.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "ocf-security.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/templates/capif-security-configmap.yaml b/helm/capif/charts/ocf-security/templates/configmap.yaml similarity index 82% rename from helm/capif/templates/capif-security-configmap.yaml rename to helm/capif/charts/ocf-security/templates/configmap.yaml index ade6a59257fe064ae1a27d36af23dc608e452ad4..5d099d194854f2bc3a63fa1c83e075c4b3edff36 100644 --- a/helm/capif/templates/capif-security-configmap.yaml +++ b/helm/capif/charts/ocf-security/templates/configmap.yaml @@ -5,8 +5,8 @@ metadata: data: config.yaml: | mongo: { - 'user': '{{ .Values.mongo.mongo.env.mongoInitdbRootUsername }}', - 'password': '{{ .Values.mongo.mongo.env.mongoInitdbRootPassword }}', + 'user': '{{ .Values.env.mongoInitdbRootUsername }}', + 'password': '{{ .Values.env.mongoInitdbRootPassword }}', 'db': 'capif', 'col': 'security', 'capif_service_col': 'serviceapidescriptions', diff --git a/helm/capif/charts/ocf-security/templates/deployment.yaml b/helm/capif/charts/ocf-security/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..48ab76404d940062fcc5cfd0ba3f53224050535a --- /dev/null +++ b/helm/capif/charts/ocf-security/templates/deployment.yaml @@ -0,0 +1,80 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "ocf-security.fullname" . }} + labels: + {{- include "ocf-security.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "ocf-security.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "ocf-security.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "ocf-security.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: CAPIF_HOSTNAME + value: {{ quote .Values.env.capifHostname }} + - name: MONITORING + value: {{ quote .Values.env.monitoring }} + - name: VAULT_HOSTNAME + value: {{ quote .Values.env.vaultHostname }} + - name: VAULT_PORT + value: {{ quote .Values.env.vaultPort }} + - name: VAULT_ACCESS_TOKEN + value: {{ quote .Values.env.vaultAccessToken }} + - name: LOG_LEVEL + value: {{ quote .Values.env.logLevel }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/ocf-security/templates/hpa.yaml b/helm/capif/charts/ocf-security/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7b4759b3597339d3c8ba775408d5e0a3ab85c37f --- /dev/null +++ b/helm/capif/charts/ocf-security/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "ocf-security.fullname" . }} + labels: + {{- include "ocf-security.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "ocf-security.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-security/templates/ingress.yaml b/helm/capif/charts/ocf-security/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5656fea5f9a4e80b6ad0679ba7e8f9f1d2707a39 --- /dev/null +++ b/helm/capif/charts/ocf-security/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "ocf-security.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "ocf-security.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/ocf-security/templates/service.yaml b/helm/capif/charts/ocf-security/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..553dc57afb374e17f76f58cdc2269d2883e99156 --- /dev/null +++ b/helm/capif/charts/ocf-security/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: capif-security + labels: + {{- include "ocf-security.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "ocf-security.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/ocf-security/templates/serviceaccount.yaml b/helm/capif/charts/ocf-security/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..29faf430a13481b28406b9d648dab920b6abcdaf --- /dev/null +++ b/helm/capif/charts/ocf-security/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "ocf-security.serviceAccountName" . }} + labels: + {{- include "ocf-security.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/ocf-security/templates/tests/test-connection.yaml b/helm/capif/charts/ocf-security/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..08b375292539668fec4d9a3acbd0741f4601ebe9 --- /dev/null +++ b/helm/capif/charts/ocf-security/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "ocf-security.fullname" . }}-test-connection" + labels: + {{- include "ocf-security.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['capif-security:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/ocf-security/values.yaml b/helm/capif/charts/ocf-security/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2be42885aacd8679b17ab198c6affe89c727f485 --- /dev/null +++ b/helm/capif/charts/ocf-security/values.yaml @@ -0,0 +1,119 @@ +# Default values for ocf-security. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: security-api + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + monitoring: "true" + capifHostname: capif + vaultHostname: vault + vaultPort: 8200 + vaultAccessToken: dev-only-token + mongoInitdbRootUsername: root + mongoInitdbRootPassword: example + logLevel: "INFO" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8080 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: + tcpSocket: + port: 8080 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: capif-security-config + configMap: + name: capif-security-configmap + items: + - key: "config.yaml" + path: "config.yaml" + + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: capif-security-config + mountPath: /usr/src/app/config.yaml + subPath: config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/otelcollector/.helmignore b/helm/capif/charts/otelcollector/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/otelcollector/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/otelcollector/Chart.yaml b/helm/capif/charts/otelcollector/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..77867b3cc10ba587d06cd2fb283329ec18dbda85 --- /dev/null +++ b/helm/capif/charts/otelcollector/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: otelcollector +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/otelcollector/templates/NOTES.txt b/helm/capif/charts/otelcollector/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..a0fe6217412e55cf12d5815464c37b7727b43e2b --- /dev/null +++ b/helm/capif/charts/otelcollector/templates/NOTES.txt @@ -0,0 +1,26 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else }} +{{- range .Values.service }} + {{- if contains "NodePort" .type }} + export NODE_PORT=$(kubectl get --namespace {{ $.Release.Namespace }} -o jsonpath="{.spec.ports[?(@.name=='{{ .name }}')].nodePort}" services {{ include "otelcollector.fullname" $ }}) + export NODE_IP=$(kubectl get nodes --namespace {{ $.Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT + {{- else if contains "LoadBalancer" .type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ $.Release.Namespace }} svc -w {{ include "otelcollector.fullname" $ }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ $.Release.Namespace }} {{ include "otelcollector.fullname" $ }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ (index .ports 0).port }} + {{- else if contains "ClusterIP" .type }} + export POD_NAME=$(kubectl get pods --namespace {{ $.Release.Namespace }} -l "app.kubernetes.io/name={{ include "otelcollector.name" $ }},app.kubernetes.io/instance={{ $.Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ $.Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ $.Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT + {{- end }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/otelcollector/templates/_helpers.tpl b/helm/capif/charts/otelcollector/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..0868fea33dc825e100df63fb48a4c1e6f1b64465 --- /dev/null +++ b/helm/capif/charts/otelcollector/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "otelcollector.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "otelcollector.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "otelcollector.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "otelcollector.labels" -}} +helm.sh/chart: {{ include "otelcollector.chart" . }} +{{ include "otelcollector.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "otelcollector.selectorLabels" -}} +app.kubernetes.io/name: {{ include "otelcollector.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "otelcollector.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "otelcollector.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/otel-collector-configmap.yaml b/helm/capif/charts/otelcollector/templates/configmap.yaml similarity index 81% rename from helm/capif/templates/otel-collector-configmap.yaml rename to helm/capif/charts/otelcollector/templates/configmap.yaml index fed15350a9b18e02a7e0a09935526034dfd316d9..d169e1f5f21fcbeb8e94e645a8c574c120b871be 100644 --- a/helm/capif/templates/otel-collector-configmap.yaml +++ b/helm/capif/charts/otelcollector/templates/configmap.yaml @@ -1,4 +1,4 @@ -{{- if eq .Values.monitoring.enable "true" }} +{{- if .Values.enabled | default false }} apiVersion: v1 kind: ConfigMap metadata: @@ -22,7 +22,7 @@ data: loglevel: debug otlp: #timeout: 60s - endpoint: {{ .Values.monitoring.otel.configMap.tempoEndpoint }} + endpoint: {{ .Values.configMap.tempoEndpoint }} tls: insecure: true diff --git a/helm/capif/charts/otelcollector/templates/deployment.yaml b/helm/capif/charts/otelcollector/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a39db22ae90e7d0b782ae0a05d8c54e580de5bbd --- /dev/null +++ b/helm/capif/charts/otelcollector/templates/deployment.yaml @@ -0,0 +1,75 @@ +{{- if .Values.enabled | default false }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "otelcollector.fullname" . }} + labels: + {{- include "otelcollector.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + strategy: + type: Recreate + selector: + matchLabels: + {{- include "otelcollector.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "otelcollector.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "otelcollector.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + {{- range .Values.service }} + - containerPort: {{ .port }} + name: {{ .name }} + protocol: {{ if eq .name "otel-collector-udp" }}UDP{{ else }}TCP{{ end }} + {{- end }} + args: + - --config + - /etc/otel-collector-config.yaml + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/otelcollector/templates/hpa.yaml b/helm/capif/charts/otelcollector/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..69863bee2e62261247fc0d0596899779e30d68bb --- /dev/null +++ b/helm/capif/charts/otelcollector/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "otelcollector.fullname" . }} + labels: + {{- include "otelcollector.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "otelcollector.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/otelcollector/templates/ingress.yaml b/helm/capif/charts/otelcollector/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5e3fae98df631efd8b47fef0a88738cb0922512e --- /dev/null +++ b/helm/capif/charts/otelcollector/templates/ingress.yaml @@ -0,0 +1,63 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "otelcollector.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "otelcollector.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/otelcollector/templates/service.yaml b/helm/capif/charts/otelcollector/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cb8afeeb28b194fe3df18a66e9b1a8e7adcefba2 --- /dev/null +++ b/helm/capif/charts/otelcollector/templates/service.yaml @@ -0,0 +1,19 @@ +{{- if .Values.enabled }} +{{- range .Values.service }} +apiVersion: v1 +kind: Service +metadata: + name: {{ .name }} + labels: + {{- include "otelcollector.labels" $ | nindent 4 }} +spec: + type: {{ .type }} + ports: + - port: {{ .port }} + name: {{ .name }} + protocol: {{ if eq .name "otel-collector-udp" }}UDP{{ else }}TCP{{ end }} + selector: + {{- include "otelcollector.selectorLabels" $ | nindent 4 }} +--- +{{- end }} +{{- end }} diff --git a/helm/capif/charts/otelcollector/templates/serviceaccount.yaml b/helm/capif/charts/otelcollector/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..68267fd28ff9a29d050b516d4de20c9a4247a753 --- /dev/null +++ b/helm/capif/charts/otelcollector/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "otelcollector.serviceAccountName" . }} + labels: + {{- include "otelcollector.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/otelcollector/values.yaml b/helm/capif/charts/otelcollector/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cd541af17d7143ab1c8fb43e64ad9706db2994b3 --- /dev/null +++ b/helm/capif/charts/otelcollector/values.yaml @@ -0,0 +1,119 @@ +# Default values for otelcollector. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + + +enabled: false + +replicaCount: 1 + +image: + repository: otel/opentelemetry-collector + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "0.81.0" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +configMap: + tempoEndpoint: tempo:4317 + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + - name: otel-collector + type: ClusterIP + port: 55680 + - name: otel-tcp + type: ClusterIP + port: 4318 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: +# httpGet: +# path: / +# port: http +readinessProbe: +# httpGet: +# path: / +# port: http + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: + - name: op-telemetry + configMap: + name: open-telemetry-configmap + items: + - key: "otel-collector-config.yaml" + path: "otel-collector-config.yaml" + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: + - name: op-telemetry + mountPath: /etc/otel-collector-config.yaml + subPath: otel-collector-config.yaml + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/redis/.helmignore b/helm/capif/charts/redis/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/redis/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/redis/Chart.yaml b/helm/capif/charts/redis/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..165c19693100b7edaa044b2b32db184d179d588e --- /dev/null +++ b/helm/capif/charts/redis/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: redis +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/redis/templates/NOTES.txt b/helm/capif/charts/redis/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..0735ad40cfe95142cd0bf35b11dea2437e3a0966 --- /dev/null +++ b/helm/capif/charts/redis/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "redis.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "redis.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "redis.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "redis.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/redis/templates/_helpers.tpl b/helm/capif/charts/redis/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..f6a718ba69d02205c4664c65af6ae5c2b8cd2195 --- /dev/null +++ b/helm/capif/charts/redis/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "redis.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "redis.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "redis.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "redis.labels" -}} +helm.sh/chart: {{ include "redis.chart" . }} +{{ include "redis.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "redis.selectorLabels" -}} +app.kubernetes.io/name: {{ include "redis.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "redis.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "redis.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/redis/templates/deployment.yaml b/helm/capif/charts/redis/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..235042963318e97a446b5b189ed22b61776624c6 --- /dev/null +++ b/helm/capif/charts/redis/templates/deployment.yaml @@ -0,0 +1,69 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "redis.fullname" . }} + labels: + {{- include "redis.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "redis.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + date: "{{ now | unixEpoch }}" + labels: + {{- include "redis.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "redis.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: REDIS_REPLICATION_MODE + value: {{ quote .Values.env.redisReplicationMode }} + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/helm/capif/charts/redis/templates/hpa.yaml b/helm/capif/charts/redis/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..db46f1ba2312230f00f24c6d60cef682273e893c --- /dev/null +++ b/helm/capif/charts/redis/templates/hpa.yaml @@ -0,0 +1,32 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "redis.fullname" . }} + labels: + {{- include "redis.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "redis.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/redis/templates/ingress.yaml b/helm/capif/charts/redis/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f5674cbdff37d83842de06af5a350a578d93c750 --- /dev/null +++ b/helm/capif/charts/redis/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "redis.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "redis.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} diff --git a/helm/capif/charts/redis/templates/service.yaml b/helm/capif/charts/redis/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6482b835ad5ce849c524be46afad97fc6ffbe73e --- /dev/null +++ b/helm/capif/charts/redis/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis + labels: + {{- include "redis.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "redis.selectorLabels" . | nindent 4 }} diff --git a/helm/capif/charts/redis/templates/serviceaccount.yaml b/helm/capif/charts/redis/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8f21aeb2bc8d07b43769710523d05a7fc9fb0cbb --- /dev/null +++ b/helm/capif/charts/redis/templates/serviceaccount.yaml @@ -0,0 +1,13 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "redis.serviceAccountName" . }} + labels: + {{- include "redis.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} diff --git a/helm/capif/charts/redis/templates/tests/test-connection.yaml b/helm/capif/charts/redis/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..998be8e4111c87865506c5807e9593277b993f05 --- /dev/null +++ b/helm/capif/charts/redis/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "redis.fullname" . }}-test-connection" + labels: + {{- include "redis.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "redis.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/helm/capif/charts/redis/values.yaml b/helm/capif/charts/redis/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4011e979c05c3f79c20173c51e527da53a69cb3f --- /dev/null +++ b/helm/capif/charts/redis/values.yaml @@ -0,0 +1,111 @@ +# Default values for redis. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: redis + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "alpine" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + redisReplicationMode: master + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 6379 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + limits: + cpu: 100m + memory: 128Mi + requests: + cpu: 100m + memory: 128Mi + +livenessProbe: + tcpSocket: + port: 6379 + initialDelaySeconds: 5 + periodSeconds: 5 +readinessProbe: + tcpSocket: + port: 6379 + periodSeconds: 5 + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/charts/renderer/.helmignore b/helm/capif/charts/renderer/.helmignore new file mode 100644 index 0000000000000000000000000000000000000000..0e8a0eb36f4ca2c939201c0d54b5d82a1ea34778 --- /dev/null +++ b/helm/capif/charts/renderer/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/capif/charts/renderer/Chart.yaml b/helm/capif/charts/renderer/Chart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..49cab700e2147fc1a8ee02034758880b11cf2fea --- /dev/null +++ b/helm/capif/charts/renderer/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: renderer +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/helm/capif/charts/renderer/templates/NOTES.txt b/helm/capif/charts/renderer/templates/NOTES.txt new file mode 100644 index 0000000000000000000000000000000000000000..c3a1259e74460e88e1de5cf22eef15f9dceabe2c --- /dev/null +++ b/helm/capif/charts/renderer/templates/NOTES.txt @@ -0,0 +1,22 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} +{{- range $host := .Values.ingress.hosts }} + {{- range .paths }} + http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ .path }} + {{- end }} +{{- end }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "renderer.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "renderer.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "renderer.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "renderer.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/helm/capif/charts/renderer/templates/_helpers.tpl b/helm/capif/charts/renderer/templates/_helpers.tpl new file mode 100644 index 0000000000000000000000000000000000000000..6ed72f247823a43ba7f41bfc46c1ee33306f7f03 --- /dev/null +++ b/helm/capif/charts/renderer/templates/_helpers.tpl @@ -0,0 +1,62 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "renderer.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "renderer.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "renderer.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "renderer.labels" -}} +helm.sh/chart: {{ include "renderer.chart" . }} +{{ include "renderer.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "renderer.selectorLabels" -}} +app.kubernetes.io/name: {{ include "renderer.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "renderer.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "renderer.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} diff --git a/helm/capif/charts/renderer/templates/configmap.yaml b/helm/capif/charts/renderer/templates/configmap.yaml new file mode 100644 index 0000000000000000000000000000000000000000..102b8592f05c07add05c3a470cb0f5a8081c40d0 --- /dev/null +++ b/helm/capif/charts/renderer/templates/configmap.yaml @@ -0,0 +1,8 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: ConfigMap +metadata: + name: renderer-configmap +data: + ENABLE_METRICS: {{ quote .Values.env.enableMetrics }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/renderer/templates/deployment.yaml b/helm/capif/charts/renderer/templates/deployment.yaml new file mode 100644 index 0000000000000000000000000000000000000000..42cab3fa2366c780bbddbc3cd5d899020f4419ec --- /dev/null +++ b/helm/capif/charts/renderer/templates/deployment.yaml @@ -0,0 +1,74 @@ +{{- if .Values.enabled | default false }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "renderer.fullname" . }} + labels: + {{- include "renderer.labels" . | nindent 4 }} +spec: + {{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} + {{- end }} + selector: + matchLabels: + {{- include "renderer.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + labels: + {{- include "renderer.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "renderer.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + env: + - name: ENABLE_METRICS + valueFrom: + configMapKeyRef: + name: renderer-configmap + key: ENABLE_METRICS + livenessProbe: + {{- toYaml .Values.livenessProbe | nindent 12 }} + readinessProbe: + {{- toYaml .Values.readinessProbe | nindent 12 }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- with .Values.volumeMounts }} + volumeMounts: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- with .Values.volumes }} + volumes: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/renderer/templates/hpa.yaml b/helm/capif/charts/renderer/templates/hpa.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7783b71940b7895f4aaa73e9eb854ccd1e34e1b4 --- /dev/null +++ b/helm/capif/charts/renderer/templates/hpa.yaml @@ -0,0 +1,34 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "renderer.fullname" . }} + labels: + {{- include "renderer.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "renderer.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + target: + type: Utilization + averageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/renderer/templates/ingress.yaml b/helm/capif/charts/renderer/templates/ingress.yaml new file mode 100644 index 0000000000000000000000000000000000000000..86f62eef0110c5b095542ef443a2fa7abe7c353d --- /dev/null +++ b/helm/capif/charts/renderer/templates/ingress.yaml @@ -0,0 +1,63 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "renderer.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "renderer.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/renderer/templates/service.yaml b/helm/capif/charts/renderer/templates/service.yaml new file mode 100644 index 0000000000000000000000000000000000000000..47f91aff91973e94678ad7d6bcc4fba0728db204 --- /dev/null +++ b/helm/capif/charts/renderer/templates/service.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Service +metadata: + name: renderer + labels: + {{- include "renderer.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "renderer.selectorLabels" . | nindent 4 }} +{{- end }} diff --git a/helm/capif/charts/renderer/templates/serviceaccount.yaml b/helm/capif/charts/renderer/templates/serviceaccount.yaml new file mode 100644 index 0000000000000000000000000000000000000000..00ff2dcb79c132e01ed16bb972ff44109f13eb10 --- /dev/null +++ b/helm/capif/charts/renderer/templates/serviceaccount.yaml @@ -0,0 +1,15 @@ +{{- if .Values.enabled | default false }} +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "renderer.serviceAccountName" . }} + labels: + {{- include "renderer.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +automountServiceAccountToken: {{ .Values.serviceAccount.automount }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/capif/charts/renderer/templates/tests/test-connection.yaml b/helm/capif/charts/renderer/templates/tests/test-connection.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9e7838aee781c85a01851c843e925685c5210579 --- /dev/null +++ b/helm/capif/charts/renderer/templates/tests/test-connection.yaml @@ -0,0 +1,17 @@ +{{- if .Values.enabled | default false }} +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "renderer.fullname" . }}-test-connection" + labels: + {{- include "renderer.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['renderer:{{ .Values.service.port }}'] + restartPolicy: Never +{{- end }} diff --git a/helm/capif/charts/renderer/values.yaml b/helm/capif/charts/renderer/values.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7696150a7fd3cfd46af58e6a1e19d13f32f14867 --- /dev/null +++ b/helm/capif/charts/renderer/values.yaml @@ -0,0 +1,112 @@ +# Default values for renderer. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +enabled: false + +replicaCount: 1 + +image: + repository: grafana/grafana-image-renderer + pullPolicy: Always + # Overrides the image tag whose default is the chart appVersion. + tag: "latest" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +env: + enableMetrics: "true" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Automatically mount a ServiceAccount's API credentials? + automount: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} +podLabels: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 8081 + +ingress: + enabled: false + className: "" + annotations: {} + # kubernetes.io/ingress.class: nginx + # kubernetes.io/tls-acme: "true" + hosts: + - host: chart-example.local + paths: + - path: / + pathType: ImplementationSpecific + tls: [] + # - secretName: chart-example-tls + # hosts: + # - chart-example.local + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +livenessProbe: + httpGet: + path: / + port: http +readinessProbe: + httpGet: + path: / + port: http + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +# Additional volumes on the output Deployment definition. +volumes: [] +# - name: foo +# secret: +# secretName: mysecret +# optional: false + +# Additional volumeMounts on the output Deployment definition. +volumeMounts: [] +# - name: foo +# mountPath: "/etc/foo" +# readOnly: true + +nodeSelector: {} + +tolerations: [] + +affinity: {} diff --git a/helm/capif/templates/access-control-policy.yaml b/helm/capif/templates/access-control-policy.yaml deleted file mode 100644 index 8b2b198beddf3e97793b994c43c86ef1df644e5e..0000000000000000000000000000000000000000 --- a/helm/capif/templates/access-control-policy.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: access-control-policy - labels: - io.kompose.service: access-control-policy - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.accessControlPolicy.type }} - selector: - io.kompose.service: access-control-policy - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.accessControlPolicy.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/api-invocation-logs.yaml b/helm/capif/templates/api-invocation-logs.yaml deleted file mode 100644 index a9b4d8fd63deb56395c11b225503ce60e7b248f9..0000000000000000000000000000000000000000 --- a/helm/capif/templates/api-invocation-logs.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: api-invocation-logs - labels: - io.kompose.service: api-invocation-logs - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.apiInvocationLogs.type }} - selector: - io.kompose.service: api-invocation-logs - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.apiInvocationLogs.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/api-invoker-management.yaml b/helm/capif/templates/api-invoker-management.yaml deleted file mode 100644 index 3eaeda40135ba0f97db68fe3acc00b96a05ead58..0000000000000000000000000000000000000000 --- a/helm/capif/templates/api-invoker-management.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: api-invoker-management - labels: - io.kompose.service: api-invoker-management - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.apiInvokerManagement.type }} - selector: - io.kompose.service: api-invoker-management - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.apiInvokerManagement.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/api-provider-management.yaml b/helm/capif/templates/api-provider-management.yaml deleted file mode 100644 index 42379862e425bf8b796cc7234262fcf3310faa4a..0000000000000000000000000000000000000000 --- a/helm/capif/templates/api-provider-management.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: api-provider-management - labels: - io.kompose.service: api-provider-management - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.apiProviderManagement.type }} - selector: - io.kompose.service: api-provider-management - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.apiProviderManagement.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/capif-events.yaml b/helm/capif/templates/capif-events.yaml deleted file mode 100644 index 40b3d7bdcf7a01aca3f6c78a108039ff1ba22ca3..0000000000000000000000000000000000000000 --- a/helm/capif/templates/capif-events.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: capif-events - labels: - io.kompose.service: capif-events - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.capifEvents.type }} - selector: - io.kompose.service: capif-events - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.capifEvents.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/capif-routing-info.yaml b/helm/capif/templates/capif-routing-info.yaml deleted file mode 100644 index 6de48aa99149970097522dc28f0a1b4340debae3..0000000000000000000000000000000000000000 --- a/helm/capif/templates/capif-routing-info.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: capif-routing-info - labels: - io.kompose.service: capif-routing-info - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.capifRoutingInfo.type }} - selector: - io.kompose.service: capif-routing-info - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.capifRoutingInfo.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/capif-security.yaml b/helm/capif/templates/capif-security.yaml deleted file mode 100644 index e0bf7d885643e717c9fa4b587fe0cadbb25d0fec..0000000000000000000000000000000000000000 --- a/helm/capif/templates/capif-security.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: capif-security - labels: - io.kompose.service: capif-security - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.capifSecurity.type }} - selector: - io.kompose.service: capif-security - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.capifSecurity.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/deployment.yaml b/helm/capif/templates/deployment.yaml deleted file mode 100644 index 4c2e0265d80a53931ac74bea856cd59a94b09ccb..0000000000000000000000000000000000000000 --- a/helm/capif/templates/deployment.yaml +++ /dev/null @@ -1,1001 +0,0 @@ -{{- if eq .Values.CapifClient.enable "true" }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: capif-client - labels: - io.kompose.service: capif-client - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.CapifClient.replicas }} - selector: - matchLabels: - io.kompose.service: capif-client - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: capif-client - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: CAPIF_HOSTNAME - value: nginx.mon.svc.cluster.local - - name: VAULT_HOSTNAME - value: {{ quote .Values.parametersVault.env.vaultHostname }} - - name: VAULT_PORT - value: {{ quote .Values.parametersVault.env.vaultPort }} - - name: VAULT_ACCESS_TOKEN - value: {{ quote .Values.parametersVault.env.vaultAccessToken }} - image: {{ .Values.CapifClient.image.repository }}:{{ .Values.CapifClient.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.CapifClient.image.imagePullPolicy }} - name: capif-client - resources: - {{- toYaml .Values.CapifClient.resources | nindent 12 }} - restartPolicy: Always -{{- end }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: access-control-policy - labels: - io.kompose.service: access-control-policy - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.accessControlPolicy.replicas }} - selector: - matchLabels: - io.kompose.service: access-control-policy - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: access-control-policy - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: CAPIF_HOSTNAME - value: {{ quote .Values.nginx.nginx.env.capifHostname }} - - name: MONITORING - value: {{ quote .Values.accessControlPolicy.env.monitoring }} - image: {{ .Values.accessControlPolicy.image.repository }}:{{ .Values.accessControlPolicy.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.accessControlPolicy.image.imagePullPolicy }} - name: access-control-policy - ports: - - containerPort: 8080 - resources: - {{- toYaml .Values.accessControlPolicy.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 5 - restartPolicy: Always - ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api-invocation-logs - labels: - io.kompose.service: api-invocation-logs - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.apiInvocationLogs.replicas }} - selector: - matchLabels: - io.kompose.service: api-invocation-logs - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: api-invocation-logs - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/capif-invocation-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: CAPIF_HOSTNAME - value: {{ quote .Values.nginx.nginx.env.capifHostname }} - - name: MONITORING - value: {{ quote .Values.apiInvocationLogs.apiInvocationLogs.env.monitoring }} - - name: VAULT_HOSTNAME - value: {{ quote .Values.parametersVault.env.vaultHostname }} - - name: VAULT_PORT - value: {{ quote .Values.parametersVault.env.vaultPort }} - - name: VAULT_ACCESS_TOKEN - value: {{ quote .Values.parametersVault.env.vaultAccessToken }} - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - image: {{ .Values.apiInvocationLogs.apiInvocationLogs.image.repository }}:{{ .Values.apiInvocationLogs.apiInvocationLogs.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.apiInvocationLogs.apiInvocationLogs.image.imagePullPolicy }} - name: api-invocation-logs - ports: - - containerPort: 8080 - volumeMounts: - - name: capif-invocation-config - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - resources: - {{- toYaml .Values.apiInvocationLogs.apiInvocationLogs.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 8080 - initialDelaySeconds: 10 - periodSeconds: 5 - volumes: - - name: capif-invocation-config - configMap: - name: capif-invocation-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api-invoker-management - labels: - io.kompose.service: api-invoker-management - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.apiInvokerManagement.replicas }} - selector: - matchLabels: - io.kompose.service: api-invoker-management - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: api-invoker-management - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/capif-invoker-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - - name: MONITORING - value: {{ quote .Values.apiInvokerManagement.apiInvokerManagement.env.monitoring }} - - name: VAULT_HOSTNAME - value: {{ quote .Values.parametersVault.env.vaultHostname }} - - name: VAULT_PORT - value: {{ quote .Values.parametersVault.env.vaultPort }} - - name: VAULT_ACCESS_TOKEN - value: {{ quote .Values.parametersVault.env.vaultAccessToken }} - image: {{ .Values.apiInvokerManagement.apiInvokerManagement.image.repository }}:{{ - .Values.apiInvokerManagement.apiInvokerManagement.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.apiInvokerManagement.apiInvokerManagement.image.imagePullPolicy }} - name: api-invoker-management - ports: - - containerPort: 8080 - volumeMounts: - - name: capif-invoker-config - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - resources: - {{- toYaml .Values.apiInvokerManagement.apiInvokerManagement.resources | nindent 12 }} - volumes: - - name: capif-invoker-config - configMap: - name: capif-invoker-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: api-provider-management - labels: - io.kompose.service: api-provider-management - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.apiProviderManagement.replicas }} - selector: - matchLabels: - io.kompose.service: api-provider-management - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: api-provider-management - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/capif-provider-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - - name: MONITORING - value: {{ quote .Values.apiProviderManagement.apiProviderManagement.env.monitoring }} - - name: VAULT_HOSTNAME - value: {{ quote .Values.parametersVault.env.vaultHostname }} - - name: VAULT_PORT - value: {{ quote .Values.parametersVault.env.vaultPort }} - - name: VAULT_ACCESS_TOKEN - value: {{ quote .Values.parametersVault.env.vaultAccessToken }} - image: {{ .Values.apiProviderManagement.apiProviderManagement.image.repository - }}:{{ .Values.apiProviderManagement.apiProviderManagement.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.apiProviderManagement.apiProviderManagement.image.imagePullPolicy }} - name: api-provider-management - ports: - - containerPort: 8080 - volumeMounts: - - name: capif-provider-config - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - resources: - {{- toYaml .Values.apiProviderManagement.apiProviderManagement.resources | nindent 12 }} - volumes: - - name: capif-provider-config - configMap: - name: capif-provider-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: capif-events - labels: - io.kompose.service: capif-events - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.capifEvents.replicas }} - selector: - matchLabels: - io.kompose.service: capif-events - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: capif-events - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/capif-events-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - - name: MONITORING - value: {{ quote .Values.capifEvents.capifEvents.env.monitoring }} - image: {{ .Values.capifEvents.capifEvents.image.repository }}:{{ .Values.capifEvents.capifEvents.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.capifEvents.capifEvents.image.imagePullPolicy }} - name: capif-events - ports: - - containerPort: 8080 - volumeMounts: - - name: capif-events-config - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - resources: - {{- toYaml .Values.capifEvents.capifEvents.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: capif-events-config - configMap: - name: capif-events-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: capif-routing-info - labels: - io.kompose.service: capif-routing-info - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.capifRoutingInfo.replicas }} - selector: - matchLabels: - io.kompose.service: capif-routing-info - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: capif-routing-info - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - - name: MONITORING - value: {{ quote .Values.capifRoutingInfo.capifRoutingInfo.env.monitoring }} - image: {{ .Values.capifRoutingInfo.capifRoutingInfo.image.repository }}:{{ .Values.capifRoutingInfo.capifRoutingInfo.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.capifRoutingInfo.capifRoutingInfo.image.imagePullPolicy }} - name: capif-routing-info - ports: - - containerPort: 8080 - resources: - {{- toYaml .Values.capifRoutingInfo.capifRoutingInfo.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: capif-security - labels: - io.kompose.service: capif-security - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.capifSecurity.replicas }} - selector: - matchLabels: - io.kompose.service: capif-security - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: capif-security - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/capif-security-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: CAPIF_HOSTNAME - value: {{ quote .Values.nginx.nginx.env.capifHostname }} - - name: MONITORING - value: {{ quote .Values.capifSecurity.capifSecurity.env.monitoring }} - - name: VAULT_HOSTNAME - value: {{ quote .Values.parametersVault.env.vaultHostname }} - - name: VAULT_PORT - value: {{ quote .Values.parametersVault.env.vaultPort }} - - name: VAULT_ACCESS_TOKEN - value: {{ quote .Values.parametersVault.env.vaultAccessToken }} - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - image: {{ .Values.capifSecurity.capifSecurity.image.repository }}:{{ .Values.capifSecurity.capifSecurity.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.capifSecurity.capifSecurity.image.imagePullPolicy }} - name: capif-security - ports: - - containerPort: 8080 - volumeMounts: - - name: capif-security-config - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - resources: - {{- toYaml .Values.capifSecurity.capifSecurity.resources | nindent 12 }} - volumes: - - name: capif-security-config - configMap: - name: capif-security-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always - restartPolicy: Always - -{{- if eq .Values.register.enable "true" }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: register - labels: - io.kompose.service: register - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.register.replicas }} - selector: - matchLabels: - io.kompose.service: register - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: register - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/register-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - - name: VAULT_HOSTNAME - value: {{ quote .Values.parametersVault.env.vaultHostname }} - - name: VAULT_PORT - value: {{ quote .Values.parametersVault.env.vaultPort }} - - name: VAULT_ACCESS_TOKEN - value: {{ quote .Values.parametersVault.env.vaultAccessToken }} - image: {{ .Values.register.register.image.repository }}:{{ .Values.register.register.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.register.register.image.imagePullPolicy }} - name: register - ports: - - containerPort: 8080 - resources: - {{- toYaml .Values.register.register.resources | nindent 12 }} - volumeMounts: - - name: register-configmap - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - volumes: - - name: register-configmap - configMap: - name: register-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mongo-register - labels: - io.kompose.service: mongo-register - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.mongoRegister.replicas }} - selector: - matchLabels: - io.kompose.service: mongo-register - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: mongo-register - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: MONGO_INITDB_ROOT_PASSWORD - value: {{ quote .Values.mongoRegister.mongo.env.mongoInitdbRootPassword }} - - name: MONGO_INITDB_ROOT_USERNAME - value: {{ quote .Values.mongoRegister.mongo.env.mongoInitdbRootUsername }} - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - image: {{ .Values.mongoRegister.mongo.image.repository }}:{{ .Values.mongoRegister.mongo.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.mongoRegister.mongo.image.imagePullPolicy }} - name: mongo-register - ports: - - containerPort: 27017 - resources: - {{- toYaml .Values.mongoRegister.mongo.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 27017 -# initialDelaySeconds: 5 - periodSeconds: 5 - restartPolicy: Always -{{- end }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: logs - labels: - io.kompose.service: logs - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.logs.replicas }} - selector: - matchLabels: - io.kompose.service: logs - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: logs - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/capif-logs-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - - name: MONITORING - value: {{ quote .Values.logs.logs.env.monitoring }} - image: {{ .Values.logs.logs.image.repository }}:{{ .Values.logs.logs.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.logs.logs.image.imagePullPolicy }} - name: logs - ports: - - containerPort: 8080 - volumeMounts: - - name: capif-logs-config - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - resources: - {{- toYaml .Values.logs.logs.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: capif-logs-config - configMap: - name: capif-logs-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mongo - labels: - io.kompose.service: mongo - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.mongo.replicas }} - strategy: - type: Recreate - selector: - matchLabels: - io.kompose.service: mongo - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: mongo - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: MONGO_INITDB_ROOT_PASSWORD - value: {{ quote .Values.mongo.mongo.env.mongoInitdbRootPassword }} - - name: MONGO_INITDB_ROOT_USERNAME - value: {{ quote .Values.mongo.mongo.env.mongoInitdbRootUsername }} - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - image: {{ .Values.mongo.mongo.image.repository }}:{{ .Values.mongo.mongo.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.mongo.mongo.image.imagePullPolicy }} - name: mongo - ports: - - containerPort: 27017 - securityContext: - runAsUser: 0 - {{- if eq .Values.mongo.persistence.enable "true" }} - volumeMounts: - - name: mongo-pvc - mountPath: /data/db - {{- end }} - resources: - {{- toYaml .Values.mongo.mongo.resources | nindent 12 }} - livenessProbe: - tcpSocket: - port: 27017 - initialDelaySeconds: 20 - periodSeconds: 5 - readinessProbe: - tcpSocket: - port: 27017 -# initialDelaySeconds: 5 - periodSeconds: 5 - - name: mongo-helper - image: busybox - command: - - sh - - -c - - while true ; do echo alive ; sleep 10 ; done - {{- if eq .Values.mongo.persistence.enable "true" }} - volumeMounts: - - mountPath: /mongodata - name: mongo-pvc - {{- end }} - {{- if eq .Values.mongo.persistence.enable "true" }} - volumes: - - name: mongo-pvc - persistentVolumeClaim: - claimName: mongo-pvc - {{- end }} - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: mongo-express - labels: - io.kompose.service: mongo-express - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.mongoExpress.replicas }} - selector: - matchLabels: - io.kompose.service: mongo-express - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: mongo-express - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: ME_CONFIG_MONGODB_ADMINPASSWORD - value: {{ quote .Values.mongoExpress.mongoExpress.env.meConfigMongodbAdminpassword - }} - - name: ME_CONFIG_MONGODB_ADMINUSERNAME - value: {{ quote .Values.mongoExpress.mongoExpress.env.meConfigMongodbAdminusername - }} - - name: ME_CONFIG_MONGODB_URL - value: {{ quote .Values.mongoExpress.mongoExpress.env.meConfigMongodbUrl }} - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - image: {{ .Values.mongoExpress.mongoExpress.image.repository }}:{{ .Values.mongoExpress.mongoExpress.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.mongoExpress.mongoExpress.image.imagePullPolicy }} - name: mongo-express - ports: - - containerPort: 8081 - resources: - {{- toYaml .Values.mongoExpress.mongoExpress.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 8081 -# initialDelaySeconds: 0 - periodSeconds: 5 - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: nginx - labels: - io.kompose.service: nginx - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.nginx.replicas }} - selector: - matchLabels: - io.kompose.service: nginx - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: nginx - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: CAPIF_HOSTNAME - value: {{ quote .Values.nginx.nginx.env.capifHostname }} - - name: VAULT_HOSTNAME - value: {{ quote .Values.parametersVault.env.vaultHostname }} - - name: VAULT_PORT - value: {{ quote .Values.parametersVault.env.vaultPort }} - - name: VAULT_ACCESS_TOKEN - value: {{ quote .Values.parametersVault.env.vaultAccessToken }} - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - image: {{ .Values.nginx.nginx.image.repository }}:{{ .Values.nginx.nginx.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.nginx.nginx.image.imagePullPolicy }} - name: nginx - ports: - - containerPort: 8080 - - containerPort: 443 - livenessProbe: - tcpSocket: - port: 8080 - initialDelaySeconds: 20 - periodSeconds: 5 -# readinessProbe: -# tcpSocket: -# port: 8080 -# initialDelaySeconds: 60 -# periodSeconds: 5 - resources: - {{- toYaml .Values.nginx.nginx.resources | nindent 12 }} - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: published-apis - labels: - io.kompose.service: published-apis - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.publishedApis.replicas }} - selector: - matchLabels: - io.kompose.service: published-apis - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: published-apis - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/capif-published-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - - name: MONITORING - value: {{ quote .Values.publishedApis.publishedApis.env.monitoring }} - image: {{ .Values.publishedApis.publishedApis.image.repository }}:{{ .Values.publishedApis.publishedApis.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.publishedApis.publishedApis.image.imagePullPolicy }} - name: published-apis - ports: - - containerPort: 8080 - volumeMounts: - - name: capif-published-config - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - resources: - {{- toYaml .Values.publishedApis.publishedApis.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: capif-published-config - configMap: - name: capif-published-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: redis - labels: - io.kompose.service: redis - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.redis.replicas }} - selector: - matchLabels: - io.kompose.service: redis - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: redis - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - args: - - redis-server - env: - - name: REDIS_REPLICATION_MODE - value: {{ quote .Values.redis.redis.env.redisReplicationMode }} - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - image: {{ .Values.redis.redis.image.repository }}:{{ .Values.redis.redis.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.redis.redis.image.imagePullPolicy }} - name: redis - ports: - - containerPort: 6379 - resources: - {{- toYaml .Values.redis.redis.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 6379 -# initialDelaySeconds: 5 - periodSeconds: 5 - livenessProbe: - tcpSocket: - port: 6379 - initialDelaySeconds: 5 - periodSeconds: 5 - restartPolicy: Always ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: service-apis - labels: - io.kompose.service: service-apis - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert -spec: - replicas: {{ .Values.serviceApis.replicas }} - selector: - matchLabels: - io.kompose.service: service-apis - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - labels: - io.kompose.network/services-default: "true" - io.kompose.service: service-apis - {{- include "capif.selectorLabels" . | nindent 8 }} - annotations: - date: "{{ now | unixEpoch }}" - checksum/config: {{ include (print $.Template.BasePath "/capif-service-configmap.yaml") . | sha256sum }} - spec: - hostAliases: - - ip: "{{ .Values.ingress.ip }}" - hostnames: - - "{{ .Values.nginx.nginx.env.capifHostname }}" - containers: - - env: - - name: KUBERNETES_CLUSTER_DOMAIN - value: {{ quote .Values.kubernetesClusterDomain }} - - name: MONITORING - value: {{ quote .Values.serviceApis.serviceApis.env.monitoring }} - image: {{ .Values.serviceApis.serviceApis.image.repository }}:{{ .Values.serviceApis.serviceApis.image.tag | default .Chart.AppVersion }} - imagePullPolicy: {{ .Values.serviceApis.serviceApis.image.imagePullPolicy }} - name: service-apis - ports: - - containerPort: 8080 - volumeMounts: - - name: capif-service-config - mountPath: /usr/src/app/config.yaml - subPath: config.yaml - resources: - {{- toYaml .Values.serviceApis.serviceApis.resources | nindent 12 }} - readinessProbe: - tcpSocket: - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - volumes: - - name: capif-service-config - configMap: - name: capif-service-configmap - items: - - key: "config.yaml" - path: "config.yaml" - restartPolicy: Always \ No newline at end of file diff --git a/helm/capif/templates/fluent-bit-service.yaml b/helm/capif/templates/fluent-bit-service.yaml deleted file mode 100644 index 90653b3aabb306b61829bd4f5ae02cec5dbdd817..0000000000000000000000000000000000000000 --- a/helm/capif/templates/fluent-bit-service.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: fluent-bit - {{- include "capif.labels" . | nindent 4 }} - name: fluent-bit -spec: - ports: - - name: "24224-tcp" - port: 24224 - targetPort: 24224 - - name: 24224-udp - port: 24224 - protocol: UDP - targetPort: 24224 - selector: - io.kompose.service: fluent-bit -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/fluentbit-deployment.yaml b/helm/capif/templates/fluentbit-deployment.yaml deleted file mode 100644 index 925ec022bb6bd5a2763ffacac23bb4113ca7072d..0000000000000000000000000000000000000000 --- a/helm/capif/templates/fluentbit-deployment.yaml +++ /dev/null @@ -1,59 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - labels: - io.kompose.service: fluent-bit - {{- include "capif.labels" . | nindent 4 }} - name: fluent-bit -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: fluent-bit - {{- include "capif.selectorLabels" . | nindent 6 }} - strategy: - type: Recreate - template: - metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - checksum/config: {{ include (print $.Template.BasePath "/fluentbit-configmap.yaml") . | sha256sum }} - creationTimestamp: null - labels: - io.kompose.network/monitoring-default: "true" - io.kompose.service: fluent-bit - {{- include "capif.selectorLabels" . | nindent 8 }} - spec: - containers: - - env: - - name: LOKI_URL - valueFrom: - configMapKeyRef: - name: fluent-bit-configmap - key: LOKI_URL - image: {{ .Values.monitoring.fluentBit.image.repository }}:{{ .Values.monitoring.fluentBit.image.tag }} - name: fluent-bit - ports: - - containerPort: 24224 - - containerPort: 24224 - protocol: UDP - resources: - {{- toYaml .Values.monitoring.fluentBit.resources | nindent 12 }} - volumeMounts: - - name: fluent-bit-conf - mountPath: /fluent-bit/etc/fluent-bit.conf - subPath: fluent-bit.conf - restartPolicy: Always - volumes: - - name: fluent-bit-conf - configMap: - name: fluent-bit-configmap - items: - - key: "fluent-bit.conf" - path: "fluent-bit.conf" -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-ingress-route.yaml b/helm/capif/templates/grafana-ingress-route.yaml deleted file mode 100644 index 2e2648bf5f4b7e52d5d1e1ca73037d4e2dc7a18b..0000000000000000000000000000000000000000 --- a/helm/capif/templates/grafana-ingress-route.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.grafana.ingressRoute.enable "true" }} -apiVersion: traefik.containo.us/v1alpha1 -kind: IngressRoute -metadata: - name: grafana-ingress-route -spec: - entryPoints: [web] - routes: - - kind: Rule - match: Host(`{{ .Values.monitoring.grafana.ingressRoute.host }}`) - services: - - kind: Service - name: grafana - port: {{ .Values.monitoring.grafana.service.port }} - scheme: http -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-ingress.yaml b/helm/capif/templates/grafana-ingress.yaml deleted file mode 100644 index 7d7d0cba2890fee678fc110be2f44592019be198..0000000000000000000000000000000000000000 --- a/helm/capif/templates/grafana-ingress.yaml +++ /dev/null @@ -1,34 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if .Values.monitoring.grafana.ingress.enabled -}} -{{- $svcPort := .Values.monitoring.grafana.service.port -}} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: grafana-ingress - labels: - {{- include "capif.labels" . | nindent 4 }} - {{- with .Values.monitoring.grafana.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: -{{- if .Values.monitoring.grafana.ingress.ingressClassName }} - ingressClassName: {{ .Values.monitoring.grafana.ingress.ingressClassName }} -{{- end }} - rules: - {{- range .Values.monitoring.grafana.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - pathType: {{ .pathType }} - backend: - service: - name: grafana - port: - number: {{ $svcPort }} - {{- end }} - {{- end }} -{{- end }} -{{- end }} diff --git a/helm/capif/templates/grafana-pvc.yaml b/helm/capif/templates/grafana-pvc.yaml deleted file mode 100644 index b2c6672ec88770fbc2ef0ff3d67a826971be668f..0000000000000000000000000000000000000000 --- a/helm/capif/templates/grafana-pvc.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.grafana.persistence.enable "true" }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - io.kompose.service: grafana-claim0 - name: grafana-claim0 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.monitoring.grafana.persistence.storage }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-secrets.yaml b/helm/capif/templates/grafana-secrets.yaml deleted file mode 100644 index a6796d4a9de32cfdd2557ff68dfd1ec721414005..0000000000000000000000000000000000000000 --- a/helm/capif/templates/grafana-secrets.yaml +++ /dev/null @@ -1,10 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: v1 -kind: Secret -metadata: - name: grafana-secrets -type: Opaque -data: - GF_AUTH_ANONYMOUS_ORG_ROLE: {{ .Values.monitoring.grafana.env.gfAuthAnonymousOrgRole | b64enc | quote }} - GF_SECURITY_ADMIN_PASSWORD: {{ .Values.monitoring.grafana.env.gfSecurityAdminPassword | b64enc | quote }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/grafana-service.yaml b/helm/capif/templates/grafana-service.yaml deleted file mode 100644 index c6280438f7cd896ae2e05f41a2de6039593af55c..0000000000000000000000000000000000000000 --- a/helm/capif/templates/grafana-service.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: v1 -kind: Service -metadata: - name: grafana - labels: - {{- include "capif.labels" . | nindent 4 }} -spec: - type: {{ .Values.monitoring.grafana.service.type }} - ports: - - port: {{ .Values.monitoring.grafana.service.port }} - targetPort: {{ .Values.monitoring.grafana.service.port }} - protocol: TCP - name: http-port - selector: - io.kompose.service: grafana -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/logs.yaml b/helm/capif/templates/logs.yaml deleted file mode 100644 index 7382eff22fd777be0631d70f913efdf947c8c4b5..0000000000000000000000000000000000000000 --- a/helm/capif/templates/logs.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: logs - labels: - io.kompose.service: logs - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.logs.type }} - selector: - io.kompose.service: logs - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.logs.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/loki-deployment.yaml b/helm/capif/templates/loki-deployment.yaml deleted file mode 100644 index cadf37d067e88b18fb7c835a5af2f5c0bafea5f4..0000000000000000000000000000000000000000 --- a/helm/capif/templates/loki-deployment.yaml +++ /dev/null @@ -1,54 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - labels: - io.kompose.service: loki - {{- include "capif.labels" . | nindent 4 }} - name: loki -spec: - replicas: 1 - strategy: - type: Recreate - selector: - matchLabels: - io.kompose.service: loki - {{- include "capif.selectorLabels" . | nindent 6 }} - strategy: {} - template: - metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - labels: - io.kompose.network/monitoring-default: "true" - io.kompose.service: loki - {{- include "capif.selectorLabels" . | nindent 8 }} - spec: - containers: - - args: - - -config.file=/etc/loki/local-config.yaml - image: {{ .Values.monitoring.loki.image.repository }}:{{ .Values.monitoring.loki.image.tag }} - name: loki - ports: - - containerPort: 3100 - {{- if eq .Values.monitoring.loki.persistence.enable "true" }} - volumeMounts: - - name: loki-claim0 - mountPath: /loki/wal - {{- end }} - resources: - {{- toYaml .Values.monitoring.loki.resources | nindent 12 }} - securityContext: - runAsUser: 0 - {{- if eq .Values.monitoring.loki.persistence.enable "true" }} - volumes: - - name: loki-claim0 - persistentVolumeClaim: - claimName: loki-claim0 - {{- end }} - restartPolicy: Always -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/loki-pvc.yaml b/helm/capif/templates/loki-pvc.yaml deleted file mode 100644 index 7da7816938afdb1850f7d2f312f967811dafb69d..0000000000000000000000000000000000000000 --- a/helm/capif/templates/loki-pvc.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.loki.persistence.enable "true" }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - io.kompose.service: loki-claim0 - name: loki-claim0 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.monitoring.loki.persistence.storage }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/loki-service.yaml b/helm/capif/templates/loki-service.yaml deleted file mode 100644 index cf711a9d162ef071fd1601983f1f8e9f11814c96..0000000000000000000000000000000000000000 --- a/helm/capif/templates/loki-service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - labels: - io.kompose.service: loki - {{- include "capif.labels" . | nindent 4 }} - name: loki -spec: - ports: - - name: "loki-port" - port: 3100 - targetPort: 3100 - selector: - io.kompose.service: loki -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/mongo-express.yaml b/helm/capif/templates/mongo-express.yaml deleted file mode 100644 index 28d553b2fa05594f414638d5122e3cc442889ec7..0000000000000000000000000000000000000000 --- a/helm/capif/templates/mongo-express.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mongo-express - labels: - io.kompose.service: mongo-express - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.mongoExpress.type }} - selector: - io.kompose.service: mongo-express - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.mongoExpress.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/mongo-pvc.yaml b/helm/capif/templates/mongo-pvc.yaml deleted file mode 100644 index 2996d57e2c121fe12c2fd04d5ceaceee14320f4c..0000000000000000000000000000000000000000 --- a/helm/capif/templates/mongo-pvc.yaml +++ /dev/null @@ -1,16 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.mongo.persistence.enable "true" }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - io.kompose.service: mongo-pvc - name: mongo-pvc -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.mongo.persistence.storage }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/mongo-register.yaml b/helm/capif/templates/mongo-register.yaml deleted file mode 100644 index 82b307f5f2bae9e026b1efb78c15a09d319d7306..0000000000000000000000000000000000000000 --- a/helm/capif/templates/mongo-register.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mongo-register - labels: - io.kompose.service: mongo-register - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.mongoRegister.type }} - selector: - io.kompose.service: mongo-register - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.mongoRegister.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/mongo.yaml b/helm/capif/templates/mongo.yaml deleted file mode 100644 index 864276480d68191f6363191ab080936d43484d17..0000000000000000000000000000000000000000 --- a/helm/capif/templates/mongo.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: mongo - labels: - io.kompose.service: mongo - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.mongo.type }} - selector: - io.kompose.service: mongo - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.mongo.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/nginx-ingress-route.yaml b/helm/capif/templates/nginx-ingress-route.yaml deleted file mode 100644 index 57ca0bed1a4c8de978e244a34f346edb8606b003..0000000000000000000000000000000000000000 --- a/helm/capif/templates/nginx-ingress-route.yaml +++ /dev/null @@ -1,17 +0,0 @@ -{{- if eq .Values.nginx.ingressType "IngressRoute" }} ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: IngressRoute -metadata: - name: nginx-capif-ingress-route -spec: - entryPoints: [web] - routes: - - kind: Rule - match: Host(`{{ .Values.nginx.nginx.env.capifHostname }} && Path(`/ca-root`, `/sign-csr`, `/certdata`, `/register`, `/testdata`, `/getauth`, `/test`)`) - services: - - kind: Service - name: nginx - port: 8080 - scheme: http -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/nginx-ssl-ingress-route.yaml b/helm/capif/templates/nginx-ssl-ingress-route.yaml deleted file mode 100644 index 8c806b69a712ee995f4c97c8e406383acb507190..0000000000000000000000000000000000000000 --- a/helm/capif/templates/nginx-ssl-ingress-route.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if eq .Values.nginx.ingressType "IngressRoute" }} ---- -apiVersion: traefik.containo.us/v1alpha1 -kind: IngressRoute -metadata: - name: nginx-ssl-capif-ingress-route -spec: - entryPoints: [web] - routes: - - kind: Rule - match: Host(`{{ .Values.nginx.nginx.env.capifHostname }}`) - services: - - kind: Service - name: nginx - port: 443 - tls: - passthrough: true -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/nginx-ssl-route.yaml b/helm/capif/templates/nginx-ssl-route.yaml deleted file mode 100644 index 3e24b72131a56915468f2dc40329fbf9c480f222..0000000000000000000000000000000000000000 --- a/helm/capif/templates/nginx-ssl-route.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if eq .Values.env "openshift" }} -apiVersion: route.openshift.io/v1 -kind: Route -metadata: - labels: - name: nginx-ssl -spec: - host: {{ .Values.nginx.nginx.env.capifHostname }} - port: - targetPort: "443" - tls: - termination: passthrough - to: - kind: Service - name: nginx - weight: 100 -status: - ingress: - - conditions: - host: {{ .Values.nginx.nginx.env.capifHostname }} - routerCanonicalHostname: router-default.apps.ocp-epg.hi.inet -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/nginx-ssl.yaml b/helm/capif/templates/nginx-ssl.yaml deleted file mode 100644 index 275e2c782095b810a385e95babaef5da223cb396..0000000000000000000000000000000000000000 --- a/helm/capif/templates/nginx-ssl.yaml +++ /dev/null @@ -1,32 +0,0 @@ -{{- if eq .Values.nginx.ingressType "Ingress" }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: nginx-register - labels: - {{- include "capif.labels" . | nindent 4 }} - {{- with .Values.nginx.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - cert-manager.io/issuer: letsencrypt-issuer - {{- end }} -spec: -{{- if .Values.nginx.ingressClassName }} - ingressClassName: {{ .Values.nginx.ingressClassName }} -{{- end }} - rules: - - host: "register{{ .Values.nginx.nginx.env.capifHostname }}" - http: - paths: - - backend: - service: - name: 'register' - port: - number: 8084 - path: / - pathType: Prefix - tls: - - hosts: - - "register{{ .Values.nginx.nginx.env.capifHostname }}" - secretName: letsencrypt-secret -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/nginx.yaml b/helm/capif/templates/nginx.yaml deleted file mode 100644 index 61856f56231201a76f82b2dce5b79c802a8e6953..0000000000000000000000000000000000000000 --- a/helm/capif/templates/nginx.yaml +++ /dev/null @@ -1,48 +0,0 @@ -{{- if eq .Values.nginx.ingressType "Ingress" }} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: nginx - labels: - {{- include "capif.labels" . | nindent 4 }} - {{- with .Values.nginx.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - nginx.ingress.kubernetes.io/ssl-passthrough: "true" - nginx.ingress.kubernetes.io/ssl-redirect: "true" - {{- end }} -spec: -{{- if .Values.nginx.ingressClassName }} - ingressClassName: {{ .Values.nginx.ingressClassName }} -{{- end }} - rules: - - host: "{{ .Values.nginx.nginx.env.capifHostname }}" - http: - paths: - - backend: - service: - name: 'nginx' - port: - number: 443 - path: / - pathType: Prefix -{{- end }} ---- -apiVersion: v1 -kind: Service -metadata: - name: nginx - labels: - io.kompose.service: nginx - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.nginx.type }} - selector: - io.kompose.service: nginx - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.nginx.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/otel-collector-deployment.yaml b/helm/capif/templates/otel-collector-deployment.yaml deleted file mode 100644 index 8c83eca1ae2fe50c98b8ce73dde333c59f710579..0000000000000000000000000000000000000000 --- a/helm/capif/templates/otel-collector-deployment.yaml +++ /dev/null @@ -1,54 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - labels: - io.kompose.service: otel-collector - {{- include "capif.labels" . | nindent 4 }} - name: otel-collector -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: otel-collector - {{- include "capif.selectorLabels" . | nindent 6 }} - strategy: - type: Recreate - template: - metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - checksum/config: {{ include (print $.Template.BasePath "/otel-collector-configmap.yaml") . | sha256sum }} - labels: - io.kompose.network/monitoring-default: "true" - io.kompose.service: otel-collector - {{- include "capif.selectorLabels" . | nindent 8 }} - spec: - containers: - - args: - - --config - - /etc/otel-collector-config.yaml - image: {{ .Values.monitoring.otel.image.repository }}:{{ .Values.monitoring.otel.image.tag }} - name: otel-collector - ports: - - containerPort: 55680 - - containerPort: 4317 - resources: - {{- toYaml .Values.monitoring.otel.resources | nindent 12 }} - volumeMounts: - - name: op-telemetry - mountPath: /etc/otel-collector-config.yaml - subPath: otel-collector-config.yaml - restartPolicy: Always - volumes: - - name: op-telemetry - configMap: - name: open-telemetry-configmap - items: - - key: "otel-collector-config.yaml" - path: "otel-collector-config.yaml" -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/otel-collector-service.yaml b/helm/capif/templates/otel-collector-service.yaml deleted file mode 100644 index 761b8ceb4a3d1d96bfe098d7485037b8a2b21c78..0000000000000000000000000000000000000000 --- a/helm/capif/templates/otel-collector-service.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - labels: - io.kompose.service: otel-collector - {{- include "capif.labels" . | nindent 4 }} - name: otel-collector -spec: - ports: - - name: "grpc-port" - port: 55680 - targetPort: 55680 - - name: "http-port" - port: 4318 - targetPort: 4318 - selector: - io.kompose.service: otel-collector -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-clusterrole.yaml b/helm/capif/templates/prometheus-clusterrole.yaml deleted file mode 100644 index 3470ffd70714c68113df3ad009b36980cd1f147f..0000000000000000000000000000000000000000 --- a/helm/capif/templates/prometheus-clusterrole.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.prometheus.enable "true" }} -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: prometheus - labels: - app: prometheus -rules: -- apiGroups: [""] - resources: - - nodes - - nodes/proxy - - services - - endpoints - - pods - verbs: ["get", "list", "watch"] -- apiGroups: - - extensions - resources: - - ingresses - verbs: ["get", "list", "watch"] -- nonResourceURLs: ["/metrics"] - verbs: ["get"] ---- -apiVersion: v1 -kind: ServiceAccount -metadata: - name: prometheus - namespace: {{ .Release.Namespace }} - labels: - app: prometheus ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: prometheus - labels: - app: prometheus -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: prometheus -subjects: -- kind: ServiceAccount - name: prometheus - namespace: {{ .Release.Namespace }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-configmap.yaml b/helm/capif/templates/prometheus-configmap.yaml deleted file mode 100644 index d2ab952e4ddb7013a0019f5c00586d5043db5cfe..0000000000000000000000000000000000000000 --- a/helm/capif/templates/prometheus-configmap.yaml +++ /dev/null @@ -1,141 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.prometheus.enable "true" }} -apiVersion: v1 -kind: ConfigMap -metadata: - labels: - app: prometheus - name: prometheus-config -data: - prometheus.rules: |- - groups: - - name: devopscube alert - rules: - - alert: High Pod Memory - expr: sum(container_memory_usage_bytes) > 1 - for: 1m - labels: - severity: slack - annotations: - summary: High Memory Usage - prometheus.yml: |- - global: - scrape_interval: 30s - scrape_timeout: 10s - scrape_configs: - #------------- configuration to collect pods metrics kubelet ------------------- - - job_name: 'kubernetes-cadvisor' - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics/cadvisor - #------------- configuration to collect pods metrics ------------------- - - job_name: 'kubernetes-pods' - honor_labels: true - kubernetes_sd_configs: - - role: pod - relabel_configs: - # select only those pods that has "prometheus.io/scrape: true" annotation - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape] - action: keep - regex: true - # set metrics_path (default is /metrics) to the metrics path specified in "prometheus.io/path: " annotation. - - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - # set the scrapping port to the port specified in "prometheus.io/port: " annotation and set address accordingly. - - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port] - action: replace - regex: ([^:]+)(?::\d+)?;(\d+) - replacement: $1:$2 - target_label: __address__ - - action: labelmap - regex: __meta_kubernetes_pod_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_pod_name] - action: replace - target_label: kubernetes_pod_name - - #-------------- configuration to collect metrics from service endpoints ----------------------- - - job_name: 'kubernetes-service-endpoints' - honor_labels: true - kubernetes_sd_configs: - - role: endpoints - relabel_configs: - # select only those endpoints whose service has "prometheus.io/scrape: true" annotation - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_scrape] - action: keep - regex: true - # set the metrics_path to the path specified in "prometheus.io/path: " annotation. - - source_labels: [__meta_kubernetes_service_annotation_prometheus_io_path] - action: replace - target_label: __metrics_path__ - regex: (.+) - # set the scrapping port to the port specified in "prometheus.io/port: " annotation and set address accordingly. - - source_labels: [__address__, __meta_kubernetes_service_annotation_prometheus_io_port] - action: replace - target_label: __address__ - regex: ([^:]+)(?::\d+)?;(\d+) - replacement: $1:$2 - - action: labelmap - regex: __meta_kubernetes_service_label_(.+) - - source_labels: [__meta_kubernetes_namespace] - action: replace - target_label: kubernetes_namespace - - source_labels: [__meta_kubernetes_service_name] - action: replace - target_label: kubernetes_name - - #---------------- configuration to collect metrics from kubernetes apiserver ------------------------- - - job_name: 'kubernetes-apiservers' - honor_labels: true - kubernetes_sd_configs: - - role: endpoints - # kubernetes apiserver serve metrics on a TLS secure endpoints. so, we have to use "https" scheme - scheme: https - # we have to provide certificate to establish tls secure connection - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - # bearer_token_file is required for authorizating prometheus server to kubernetes apiserver - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - - relabel_configs: - - source_labels: [__meta_kubernetes_namespace, __meta_kubernetes_service_name, __meta_kubernetes_endpoint_port_name] - action: keep - regex: default;kubernetes;https - - #--------------- configuration to collect metrics from nodes ----------------------- - - job_name: 'kubernetes-nodes' - honor_labels: true - scheme: https - tls_config: - ca_file: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt - bearer_token_file: /var/run/secrets/kubernetes.io/serviceaccount/token - - kubernetes_sd_configs: - - role: node - relabel_configs: - - action: labelmap - regex: __meta_kubernetes_node_label_(.+) - - target_label: __address__ - replacement: kubernetes.default.svc:443 - - source_labels: [__meta_kubernetes_node_name] - regex: (.+) - target_label: __metrics_path__ - replacement: /api/v1/nodes/${1}/proxy/metrics -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-deployment.yaml b/helm/capif/templates/prometheus-deployment.yaml deleted file mode 100644 index d70cf09ddd5b37061b73992076fccc318e0fb208..0000000000000000000000000000000000000000 --- a/helm/capif/templates/prometheus-deployment.yaml +++ /dev/null @@ -1,68 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.prometheus.enable "true" }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: prometheus - labels: - app: prometheus - {{- include "capif.labels" . | nindent 4 }} -spec: - replicas: 1 - strategy: - type: Recreate - selector: - matchLabels: - app: prometheus - {{- include "capif.selectorLabels" . | nindent 6 }} - template: - metadata: - annotations: - checksum/config: {{ include (print $.Template.BasePath "/prometheus-configmap.yaml") . | sha256sum }} - labels: - app: prometheus - {{- include "capif.selectorLabels" . | nindent 8 }} - spec: - serviceAccountName: prometheus - containers: - - name: prometheus - image: {{ .Values.monitoring.prometheus.image.repository }}:{{ .Values.monitoring.prometheus.image.tag }} - args: - - "--config.file=/etc/prometheus/prometheus.yml" - - "--storage.tsdb.path=/prometheus/" - - "--storage.tsdb.retention.time={{.Values.monitoring.prometheus.retentionTime }}" - ports: - - containerPort: 9090 - resources: - {{- toYaml .Values.monitoring.prometheus.resources | nindent 12 }} - securityContext: - runAsUser: 0 - livenessProbe: - tcpSocket: - port: 9090 - initialDelaySeconds: 20 - volumeMounts: - - name: prometheus-config - mountPath: /etc/prometheus/ - {{- if eq .Values.monitoring.prometheus.persistence.enable "true" }} - - name: prometheus-storage-volume - mountPath: /prometheus/ - {{ else }} - - name: prometheus-storage - mountPath: /prometheus/ - {{- end }} - volumes: - - name: prometheus-config - configMap: - defaultMode: 420 - name: prometheus-config - {{- if eq .Values.monitoring.prometheus.persistence.enable "true" }} - - name: prometheus-storage-volume - persistentVolumeClaim: - claimName: prometheus-pvc - {{ else }} - - name: prometheus-storage - emptyDir: {} - {{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-ingress-route.yaml b/helm/capif/templates/prometheus-ingress-route.yaml deleted file mode 100644 index b7a0d2b0e02ebbb80c5e4a53aa9240066759f581..0000000000000000000000000000000000000000 --- a/helm/capif/templates/prometheus-ingress-route.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.prometheus.enable "true" }} -{{- if eq .Values.monitoring.prometheus.ingressRoute.enable "true" }} -apiVersion: traefik.containo.us/v1alpha1 -kind: IngressRoute -metadata: - name: prometheus-ingress-route -spec: - entryPoints: [web] - routes: - - kind: Rule - match: Host(`{{ .Values.monitoring.prometheus.ingressRoute.host }}`) - services: - - kind: Service - name: prometheus - port: {{ .Values.monitoring.prometheus.service.port }} - scheme: http -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-ingress.yaml b/helm/capif/templates/prometheus-ingress.yaml deleted file mode 100644 index d08297327eac7192db7618a5937e2af6e5f05d1d..0000000000000000000000000000000000000000 --- a/helm/capif/templates/prometheus-ingress.yaml +++ /dev/null @@ -1,36 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.prometheus.enable "true" }} -{{- if .Values.monitoring.prometheus.ingress.enabled -}} -{{- $svcPort := .Values.monitoring.prometheus.service.port -}} -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: prometheus-ingress - labels: - {{- include "capif.labels" . | nindent 4 }} - {{- with .Values.monitoring.prometheus.ingress.annotations }} - annotations: - {{- toYaml . | nindent 4 }} - {{- end }} -spec: -{{- if .Values.monitoring.prometheus.ingress.ingressClassName }} - ingressClassName: {{ .Values.monitoring.prometheus.ingress.ingressClassName }} -{{- end }} - rules: - {{- range .Values.monitoring.prometheus.ingress.hosts }} - - host: {{ .host | quote }} - http: - paths: - {{- range .paths }} - - path: {{ .path }} - pathType: {{ .pathType }} - backend: - service: - name: prometheus - port: - number: {{ $svcPort }} - {{- end }} - {{- end }} -{{- end }} -{{- end }} -{{- end }} diff --git a/helm/capif/templates/prometheus-pvc.yaml b/helm/capif/templates/prometheus-pvc.yaml deleted file mode 100644 index 0ba676f3e817a25928e79c024021f62663e05de5..0000000000000000000000000000000000000000 --- a/helm/capif/templates/prometheus-pvc.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.prometheus.enable "true" }} -{{- if eq .Values.monitoring.prometheus.persistence.enable "true" }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: prometheus-pvc - labels: - app: prometheus - {{- include "capif.labels" . | nindent 4 }} -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.monitoring.prometheus.persistence.storage }} -{{- end }} -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/prometheus-service.yaml b/helm/capif/templates/prometheus-service.yaml deleted file mode 100644 index 778dbd580e55f200bb735b5605f0e00ba4ef1d94..0000000000000000000000000000000000000000 --- a/helm/capif/templates/prometheus-service.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -{{- if eq .Values.monitoring.prometheus.enable "true" }} -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/path: /metrics - prometheus.io/port: {{ quote .Values.monitoring.prometheus.service.port }} - prometheus.io/scrape: "true" - name: prometheus - labels: - {{- include "capif.labels" . | nindent 4 }} -spec: - type: {{ .Values.monitoring.prometheus.service.type }} - ports: - - port: {{ .Values.monitoring.prometheus.service.port }} - protocol: TCP - targetPort: {{ .Values.monitoring.prometheus.service.port }} - selector: - app: prometheus -{{- end }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/published-apis.yaml b/helm/capif/templates/published-apis.yaml deleted file mode 100644 index a5444f1640bf02b113d3bfd967bcde78122efcf2..0000000000000000000000000000000000000000 --- a/helm/capif/templates/published-apis.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: published-apis - labels: - io.kompose.service: published-apis - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.publishedApis.type }} - selector: - io.kompose.service: published-apis - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.publishedApis.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/redis.yaml b/helm/capif/templates/redis.yaml deleted file mode 100644 index 3254a95f48f9b36be9de55d7f0c1d08df2ba5f73..0000000000000000000000000000000000000000 --- a/helm/capif/templates/redis.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: redis - labels: - io.kompose.service: redis - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.redis.type }} - selector: - io.kompose.service: redis - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.redis.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/templates/register-configmap.yaml b/helm/capif/templates/register-configmap.yaml deleted file mode 100644 index 51293a5b7824d6688d9545d600c5571f9db4d55d..0000000000000000000000000000000000000000 --- a/helm/capif/templates/register-configmap.yaml +++ /dev/null @@ -1,21 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: register-configmap - labels: - {{- include "capif.labels" . | nindent 4 }} -data: - config.yaml: |- - mongo: { - 'user': 'root', - 'password': 'example', - 'db': 'capif_users', - 'col': 'user', - 'host': '{{ .Values.register.register.env.mongoHost }}', - 'port': '{{ .Values.register.register.env.mongoPort }}' - } - ca_factory: { - "url": "{{ .Values.parametersVault.env.vaultHostname }}", - "port": "{{ .Values.parametersVault.env.vaultPort }}", - "token": "{{ .Values.parametersVault.env.vaultAccessToken }}" - } \ No newline at end of file diff --git a/helm/capif/templates/register.yaml b/helm/capif/templates/register.yaml deleted file mode 100644 index 2de1d64248110745b5999c1e50e1b5801166b709..0000000000000000000000000000000000000000 --- a/helm/capif/templates/register.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if eq .Values.register.enable "true" }} -apiVersion: v1 -kind: Service -metadata: - name: register - labels: - io.kompose.service: register - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.register.type }} - selector: - io.kompose.service: register - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.register.ports | toYaml | nindent 2 -}} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/renderer-configmap.yaml b/helm/capif/templates/renderer-configmap.yaml deleted file mode 100644 index 0159fcbc02450bc9a3eb9522e11e11c42656977e..0000000000000000000000000000000000000000 --- a/helm/capif/templates/renderer-configmap.yaml +++ /dev/null @@ -1,8 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: v1 -kind: ConfigMap -metadata: - name: renderer-configmap -data: - ENABLE_METRICS: {{ quote .Values.monitoring.renderer.env.enableMetrics }} -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/renderer-deployment.yaml b/helm/capif/templates/renderer-deployment.yaml deleted file mode 100644 index 83a7ee2f73cb0c5254a3d75e1673a4e22d42dfab..0000000000000000000000000000000000000000 --- a/helm/capif/templates/renderer-deployment.yaml +++ /dev/null @@ -1,44 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - labels: - io.kompose.service: renderer - {{- include "capif.labels" . | nindent 4 }} - name: renderer -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: renderer - {{- include "capif.selectorLabels" . | nindent 6 }} - strategy: {} - template: - metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - checksum/config: {{ include (print $.Template.BasePath "/renderer-configmap.yaml") . | sha256sum }} - labels: - io.kompose.network/monitoring-default: "true" - io.kompose.service: renderer - {{- include "capif.selectorLabels" . | nindent 8 }} - spec: - containers: - - env: - - name: ENABLE_METRICS - valueFrom: - configMapKeyRef: - name: renderer-configmap - key: ENABLE_METRICS - image: {{ .Values.monitoring.renderer.image.repository }}:{{ .Values.monitoring.renderer.image.tag }} - name: grafana-image-renderer - ports: - - containerPort: 8081 - resources: - {{- toYaml .Values.monitoring.renderer.resources | nindent 12 }} - restartPolicy: Always -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/renderer-service.yaml b/helm/capif/templates/renderer-service.yaml deleted file mode 100644 index 471a51dca046b1d35fcf0afd68a500a48db62cdc..0000000000000000000000000000000000000000 --- a/helm/capif/templates/renderer-service.yaml +++ /dev/null @@ -1,18 +0,0 @@ -{{- if eq .Values.monitoring.enable "true" }} -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - labels: - io.kompose.service: renderer - name: renderer -spec: - ports: - - name: "rendere-port" - port: 8081 - targetPort: 8081 - selector: - io.kompose.service: renderer -{{- end }} \ No newline at end of file diff --git a/helm/capif/templates/service-apis.yaml b/helm/capif/templates/service-apis.yaml deleted file mode 100644 index bff1af594b5ceba6a7ba58a78103fb1b885b43ea..0000000000000000000000000000000000000000 --- a/helm/capif/templates/service-apis.yaml +++ /dev/null @@ -1,17 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: service-apis - labels: - io.kompose.service: service-apis - {{- include "capif.labels" . | nindent 4 }} - annotations: - kompose.cmd: kompose -f ../services/docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) -spec: - type: {{ .Values.serviceApis.type }} - selector: - io.kompose.service: service-apis - {{- include "capif.selectorLabels" . | nindent 4 }} - ports: - {{- .Values.serviceApis.ports | toYaml | nindent 2 -}} \ No newline at end of file diff --git a/helm/capif/values.yaml b/helm/capif/values.yaml index a2aea33c43517bce909dad4d8133e6846fe94873..9ecc11e00f197520bc04814c61a4381c66b4992f 100644 --- a/helm/capif/values.yaml +++ b/helm/capif/values.yaml @@ -1,493 +1,9 @@ -# -- The Environment variable. Use openshift if you are deploying in Openshift cluster. anotherwise use the field empty -env: "" +# -- To enable monitoring in ocf. +# -- enabled the next services: +# -- tempo, fluentbit, grafana, loki, otelcollector and renderer. +# -- prometheus service must be previously installed in kubernetes -# Use the Ip address dude for the kubernetes to your Ingress Controller ej: kubectl -n NAMESPACE_CAPIF get ing -ingress: - ip: "10.17.173.127" - -monitoring: - enable: "true" - -accessControlPolicy: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/access-control-policy" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP - -CapifClient: - # -- If enable capif client. - enable: "true" - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/client" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP - -apiInvocationLogs: - apiInvocationLogs: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/api-invocation-logs-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP -apiInvokerManagement: - apiInvokerManagement: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/api-invoker-management-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP -apiProviderManagement: - apiProviderManagement: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/api-provider-management-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP -capifEvents: - capifEvents: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/events-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP -capifRoutingInfo: - capifRoutingInfo: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/routing-info-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP -capifSecurity: - capifSecurity: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/security-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP -register: - # -- If register enabled. enable: true, enable: "" = not enabled - enable: "true" - register: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/register" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - env: - mongoHost: mongo-register - mongoPort: 27017 - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8084 - targetPort: 8080 - replicas: 1 - type: ClusterIP -mongoRegister: - mongo: - env: - # User's password MongoDB - mongoInitdbRootPassword: example - # Name of User's mongodb - mongoInitdbRootUsername: root - image: - # -- The docker image repository to use - repository: "mongo" - # -- The docker image tag to use - # @default Chart version - tag: "6.0.2" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - resources: {} -# limits: -# cpu: 100m -# memory: 128Mi -# requests: -# cpu: 100m -# memory: 128Mi - ports: - - name: "27017" - port: 27017 - targetPort: 27017 - replicas: 1 - type: ClusterIP - -kubernetesClusterDomain: cluster.local -logs: - # -- If register enabled. enable: true, enable: "" = not enabled - enable: "true" - logs: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/auditing-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - type: ClusterIP -mongo: - mongo: - env: - # User's password MongoDB - mongoInitdbRootPassword: example - # Name of User's mongodb - mongoInitdbRootUsername: root - image: - # -- The docker image repository to use - repository: "mongo" - # -- The docker image tag to use - # @default Chart version - tag: "6.0.2" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - resources: {} -# limits: -# cpu: 100m -# memory: 128Mi -# requests: -# cpu: 100m -# memory: 128Mi - ports: - - name: "27017" - port: 27017 - targetPort: 27017 - replicas: 1 - type: ClusterIP - # -- If mongo.persistence enabled. enable: true, enable: "" = not enabled - persistence: - enable: "true" - storage: 8Gi -mongoExpress: - mongoExpress: - env: - # User's password MongoDB - meConfigMongodbAdminpassword: example - # Name of User's mongodb - meConfigMongodbAdminusername: root - # URI for connecting MongoDB - meConfigMongodbUrl: mongodb://root:example@mongo:27017/ - image: - # -- The docker image repository to use - repository: "mongo-express" - # -- The docker image tag to use - # @default Chart version - tag: "1.0.0-alpha.4" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8082" - port: 8082 - targetPort: 8081 - replicas: 1 - type: ClusterIP -nginx: - # -- if nginx.ingressType: "Ingress". set up monitoring.prometheus.ingress: true - # and monitoring.grafana.ingress: true - # Use IngressRoute if you want to use Gateway API. ex traefix - ingressType: "Ingress" - ingressClassName: nginx - annotations: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" - nginx.ingress.kubernetes.io/ssl-passthrough: "true" - nginx.ingress.kubernetes.io/ssl-redirect: "true" - nginx: - env: - # -- Ingress's host to Capif - capifHostname: "my-capif.apps.ocp-epg.hi.inet" - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/nginx" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - - name: "443" - port: 443 - targetPort: 443 - replicas: 1 - type: ClusterIP -publishedApis: - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - publishedApis: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/publish-service-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - replicas: 1 - type: ClusterIP -redis: - ports: - - name: "6379" - port: 6379 - targetPort: 6379 - redis: - env: - # Mode of replication - redisReplicationMode: master - image: - # -- The docker image repository to use - repository: "redis" - # -- The docker image tag to use - # @default Chart version - tag: "alpine" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - replicas: 1 - type: ClusterIP -serviceApis: - ports: - - name: "8080" - port: 8080 - targetPort: 8080 - replicas: 1 - serviceApis: - image: - # -- The docker image repository to use - repository: "public.ecr.aws/o2v4a8t6/opencapif/discover-service-api" - # -- The docker image tag to use - # @default Chart version - tag: "" - # -- Image pull policy: Always, IfNotPresent - imagePullPolicy: Always - # -- If env.monitoring: true. Setup monitoring.enable: true - env: - monitoring: "true" - resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi - type: ClusterIP -parametersVault: - env: - vaultHostname: vault-internal.mon.svc.cluster.local - vaultPort: 8200 - vaultAccessToken: dev-only-token # -- With tempo.enabled: false. It won't be deployed -# -- If monitoring.enable: "true". Also enable tempo.enabled: true tempo: enabled: true tempo: @@ -497,164 +13,35 @@ tempo: persistence: enabled: true size: 3Gi -monitoring: - # -- If monitoring enabled. enable: true, enable: "" = not enabled - enable: "true" - fluentBit: - image: - # -- The docker image repository to use - repository: "grafana/fluent-bit-plugin-loki" - # -- The docker image tag to use - # @default Chart version - tag: "latest" - env: - lokiUrl: http://loki:3100/loki/api/v1/push - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - loki: - image: - # -- The docker image repository to use - repository: "grafana/loki" - # -- The docker image tag to use - # @default Chart version - tag: "2.8.0" - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - # -- If grafana.persistence enabled. enable: true, enable: "" = not enabled - persistence: - enable: "true" - storage: 100Mi - otel: - image: - # -- The docker image repository to use - repository: "otel/opentelemetry-collector" - # -- The docker image tag to use - # @default Chart version - tag: "0.81.0" - configMap: - tempoEndpoint: monitoring-capif-tempo:4317 - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - renderer: - image: - # -- The docker image repository to use - repository: "grafana/grafana-image-renderer" - # -- The docker image tag to use - # @default Chart version - tag: "latest" - env: - enableMetrics: "true" - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - prometheus: - # -- With prometheus.enabled: "". It won't be deployed. prometheus.enable: "true" - # -- It will deploy prometheus - enable: "true" - image: - # -- The docker image repository to use - repository: "prom/prometheus" - # -- The docker image tag to use - # @default Chart version - tag: "latest" - retentionTime: 5d - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - persistence: - enable: "true" - storage: 8Gi - service: - type: ClusterIP - port: 9090 - ingress: - enabled: true - ingressClassName: nginx - annotations: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: prometheus.5gnacar.int - paths: - - path: / - pathType: Prefix - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - # -- If ingressRoute enable=true, use monitoring.prometheus.ingress.enabled="" - ingressRoute: - enable: "" - host: prometheus.5gnacar.int - grafana: - image: - # -- The docker image repository to use - repository: "grafana/grafana" - # -- The docker image tag to use - # @default Chart version - tag: "latest" - env: - gfAuthAnonymousEnable: true - gfSecurityAllowEmbedding: true - gfAuthAnonymousOrgRole: Admin - gfSecurityAdminPassword: secure_pass - lokiUrl: http://loki:3100 - prometheusUrl: http://prometheus.mon.svc.cluster.local:9090 - tempoUrl: http://monitoring-capif-tempo:3100 - resources: {} - # limits: - # cpu: 100m - # memory: 128Mi - # requests: - # cpu: 100m - # memory: 128Mi - # -- If grafana.persistence enabled. enable: true, enable: "" = not enabled - persistence: - enable: "true" - storage: 100Mi - service: - type: ClusterIP - port: 3000 - # -- If ingress enabled=true, use monitoring.grafana.ingressRoute.enable="" - ingress: - enabled: true - ingressClassName: nginx - annotations: - # kubernetes.io/ingress.class: nginx - # kubernetes.io/tls-acme: "true" - hosts: - - host: grafana.5gnacar.int - paths: - - path: / - pathType: Prefix - tls: [] - # - secretName: chart-example-tls - # hosts: - # - chart-example.local - # -- If ingressRoute enable=true, use monitoring.grafana.ingress.enabled="" - ingressRoute: - enable: "" - host: grafana.5gnacar.int + +# -- With fluentbit.enabled: false. It won't be deployed +fluentbit: + enabled: false + +# -- With grafana.enabled: false. It won't be deployed +grafana: + enabled: false + +# -- With loki.enabled: false. It won't be deployed +loki: + enabled: false + +# -- With otelcollector.enabled: false. It won't be deployed +otelcollector: + enabled: false + +# -- With renderer.enabled: false. It won't be deployed +renderer: + enabled: false + +# -- With mongo-express.enabled: false. It won't be deployed +mongo-express: + enabled: false + +# -- With mongo-register-express.enabled: false. It won't be deployed +mongo-register-express: + enabled: false + +# -- With mock-server.enabled: false. It won't be deployed +mock-server: + enabled: false diff --git a/helm/vault-job/vault-job.yaml b/helm/vault-job/vault-job.yaml index 6e0e9ce696cfa6ab1d5ae023e405c87bddc5a836..a68f2f9eb0c1e142be88606b3ea246cf97748cd5 100644 --- a/helm/vault-job/vault-job.yaml +++ b/helm/vault-job/vault-job.yaml @@ -3,7 +3,7 @@ apiVersion: v1 kind: ConfigMap metadata: name: vault-prepare-certs - namespace: mon + namespace: ocf-vault labels: io.kompose.service: api-invocation-logs app: capif @@ -25,8 +25,15 @@ data: # to execute the next commands in vault # otherwise, if use the vault as dev's mode. Just # type the token's dev. - export VAULT_TOKEN="dev-only-token" - export DOMAIN1=capif.mobilesandbox.cloud + export VAULT_TOKEN="" + export DOMAIN1=*.ocf.pre-production + export DOMAIN2=*.ocf.validation + export DOMAIN3=*.ocf.develop + + # local domains + # export DOMAIN4=*.pre-prod.svc.cluster.local + # export DOMAIN5=*.staging.svc.cluster.local + # export DOMAIN6=*.developer.svc.cluster.local vault secrets enable pki @@ -69,7 +76,7 @@ data: vault write pki_int/intermediate/set-signed certificate=@capif_intermediate.cert.pem #Crear rol en Vault - vault write pki_int/roles/my-ca use_csr_common_name=true require_cn=false allowed_domains="*" allow_any_name=true allow_bare_domains=true allow_glob_domains=true allow_subdomains=true max_ttl=4300h ttl=4300h + vault write pki_int/roles/my-ca use_csr_common_name=false require_cn=false allowed_domains="*" allow_any_name=true allow_bare_domains=true allow_glob_domains=true allow_subdomains=true max_ttl=4300h ttl=4300h # Emitir un certificado firmado por la CA intermedia # vault write -format=json pki_int/issue/my-ca \ @@ -119,8 +126,6 @@ data: DNS.3 = \$ENV::DOMAIN3 EOF - export DOMAIN2=nginx.mon.svc.cluster.local - export DOMAIN3=nginx.mon-staging.svc.cluster.local export COUNTRY=ES # 2 letter country-code export STATE=Madrid # state or province name export LOCALITY=Madrid # Locality Name (e.g. city) @@ -170,7 +175,7 @@ data: openssl x509 -pubkey -noout -in server_certificate.crt.pem > server_certificate_pub.pem - #vault kv put secret/ca ca=@root_ca.crt.pem root_2023_ca.crt + #vault kv put secret/ca ca=@root_helm.pem root_2023_ca.crt #cat root_2023_ca.crt root_2023_ca.crt > ca.crt @@ -222,7 +227,7 @@ apiVersion: batch/v1 kind: Job metadata: name: vault-pki - namespace: mon + namespace: ocf-vault labels: io.kompose.service: vault-pki app: capif diff --git a/prometheus/kustomization.yaml b/prometheus/kustomization.yaml deleted file mode 100644 index bebcddc3552d7a0b5b3d97e0274d12ae420a6516..0000000000000000000000000000000000000000 --- a/prometheus/kustomization.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: kustomize.config.k8s.io/v1beta1 -kind: Kustomization -namespace: evol5-capif-mon -resources: - - prometheus-claim1-persistentvolumeclaim.yaml - - prometheus-claim2-persistentvolumeclaim.yaml - - prometheus-claim3-persistentvolumeclaim.yaml - - prometheus-claim4-persistentvolumeclaim.yaml - - prometheus-configmap.yaml - - prometheus-deployment.yaml - - prometheus-service.yaml \ No newline at end of file diff --git a/prometheus/prometheus-claim1-persistentvolumeclaim.yaml b/prometheus/prometheus-claim1-persistentvolumeclaim.yaml deleted file mode 100644 index 99ca0f13183dfbb0894b1bbf99ab7633c646fcc2..0000000000000000000000000000000000000000 --- a/prometheus/prometheus-claim1-persistentvolumeclaim.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - creationTimestamp: null - labels: - io.kompose.service: prometheus-claim1 - name: prometheus-claim1 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 100Mi -status: {} diff --git a/prometheus/prometheus-claim2-persistentvolumeclaim.yaml b/prometheus/prometheus-claim2-persistentvolumeclaim.yaml deleted file mode 100644 index 3a1a586d9a918b30bb41da7ae195da72f9cc29a0..0000000000000000000000000000000000000000 --- a/prometheus/prometheus-claim2-persistentvolumeclaim.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - creationTimestamp: null - labels: - io.kompose.service: prometheus-claim2 - name: prometheus-claim2 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 100Mi -status: {} diff --git a/prometheus/prometheus-claim3-persistentvolumeclaim.yaml b/prometheus/prometheus-claim3-persistentvolumeclaim.yaml deleted file mode 100644 index 755a66b594deadef2a62a10b350334dd32b9e715..0000000000000000000000000000000000000000 --- a/prometheus/prometheus-claim3-persistentvolumeclaim.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - creationTimestamp: null - labels: - io.kompose.service: prometheus-claim3 - name: prometheus-claim3 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 100Mi -status: {} diff --git a/prometheus/prometheus-claim4-persistentvolumeclaim.yaml b/prometheus/prometheus-claim4-persistentvolumeclaim.yaml deleted file mode 100644 index 9a6cb2d30c78a2e3f1070c92c797b0a8179cbff0..0000000000000000000000000000000000000000 --- a/prometheus/prometheus-claim4-persistentvolumeclaim.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - creationTimestamp: null - labels: - io.kompose.service: prometheus-claim4 - name: prometheus-claim4 -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 100Mi -status: {} diff --git a/prometheus/prometheus-configmap.yaml b/prometheus/prometheus-configmap.yaml deleted file mode 100644 index ccfb013800255c2975dd6bc342af627f52ef0ba3..0000000000000000000000000000000000000000 --- a/prometheus/prometheus-configmap.yaml +++ /dev/null @@ -1,38 +0,0 @@ -apiVersion: v1 -kind: ConfigMap -metadata: - name: prometheus-configmap -data: - prometheus.yml: | - # global: - # scrape_interval: 5s - # external_labels: - # monitor: 'prakash-monitor' - # scrape_configs: - # - job_name: 'prometheus' - # static_configs: - # - targets: ['0.0.0.0:9090'] ## IP Address of the localhost - # - job_name: 'cAdvisor' - # static_configs: - # - targets: ['0.0.0.0:8090'] - # #- cadvisor:8090 - - global: - scrape_interval: 15s - evaluation_interval: 15s - alerting: - alertmanagers: - - static_configs: - - targets: - # whatever you want - scrape_configs: - - job_name: 'prometheus' - static_configs: - - targets: ['prometheus:9090'] - labels: - alias: 'prometheus' - - job_name: 'cadvisor' - static_configs: - - targets: ['cadvisor:8080'] - labels: - alias: 'cadvisor' \ No newline at end of file diff --git a/prometheus/prometheus-deployment.yaml b/prometheus/prometheus-deployment.yaml deleted file mode 100644 index 7ae939f45cc07c922d96437663dff48da61c4ef9..0000000000000000000000000000000000000000 --- a/prometheus/prometheus-deployment.yaml +++ /dev/null @@ -1,71 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: prometheus - name: prometheus -spec: - replicas: 1 - selector: - matchLabels: - io.kompose.service: prometheus - strategy: - type: Recreate - template: - metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.network/monitoring-default: "true" - io.kompose.service: prometheus - spec: - containers: - - args: - - --config.file=/tmp/prometheus.yml - - --web.route-prefix=/ - - --storage.tsdb.retention.time=200h - - --web.enable-lifecycle - image: prom/prometheus:latest - name: prometheus - ports: - - containerPort: 9090 - resources: {} - volumeMounts: - - name: prometheus-config - mountPath: /tmp/prometheus.yml - subPath: prometheus.yml - - mountPath: /var/lib/prometheus - name: prometheus-claim1 - - mountPath: /prometheus - name: prometheus-claim2 - - mountPath: /etc/prometheus - name: prometheus-claim3 - - mountPath: /etc/prometheus/alert.rules - name: prometheus-claim4 - restartPolicy: Always - volumes: - - name: prometheus-config - configMap: - name: prometheus-configmap - items: - - key: "prometheus.yml" - path: "prometheus.yml" - - name: prometheus-claim1 - persistentVolumeClaim: - claimName: prometheus-claim1 - - name: prometheus-claim2 - persistentVolumeClaim: - claimName: prometheus-claim2 - - name: prometheus-claim3 - persistentVolumeClaim: - claimName: prometheus-claim3 - - name: prometheus-claim4 - persistentVolumeClaim: - claimName: prometheus-claim4 -status: {} diff --git a/prometheus/prometheus-service.yaml b/prometheus/prometheus-service.yaml deleted file mode 100644 index d7fa32d94c92574e44d1b99b74e06569181d32b7..0000000000000000000000000000000000000000 --- a/prometheus/prometheus-service.yaml +++ /dev/null @@ -1,19 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - annotations: - kompose.cmd: kompose -f docker-compose.yml convert - kompose.version: 1.28.0 (c4137012e) - creationTimestamp: null - labels: - io.kompose.service: prometheus - name: prometheus -spec: - ports: - - name: "9090" - port: 9090 - targetPort: 9090 - selector: - io.kompose.service: prometheus -status: - loadBalancer: {} diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/__main__.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/app.py similarity index 89% rename from services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/__main__.py rename to services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/app.py index 32ccc2eb015def617c98d798aa9ba55adf04cbd2..9d55bc5adba29d09c93b1e1909bb79bea88aaaff 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/__main__.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/app.py @@ -2,13 +2,10 @@ import connexion import logging -from api_invoker_management import encoder - -from flask import Flask, jsonify, request +import encoder from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient -from .config import Config -from .core.consumer_messager import Subscriber +from config import Config +from core.consumer_messager import Subscriber from logging.handlers import RotatingFileHandler import os from fluent import sender @@ -23,14 +20,12 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - -import sys -import uuid - - - NAME = "Invoker-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -95,10 +90,10 @@ def configure_logging(app): loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="invoker_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -108,7 +103,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) @@ -136,7 +131,8 @@ config = Config() jwt = JWTManager(app.app) configure_logging(app.app) -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": configure_monitoring(app.app, config.get_config()) executor = Executor(app.app) @@ -144,9 +140,4 @@ subscriber = Subscriber() @app.app.before_first_request def create_listener_message(): - executor.submit(subscriber.listen) - -if __name__ == '__main__': - import logging - app.run(debug=True, port=8080) - + executor.submit(subscriber.listen) \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py index 11e1c4f3626d7440c6cd999ed118afb3c93caa2e..01f9914cc141eb3c49fd73506e9b1c5470edd781 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py index 456b4ecc8bbde1dbd1aff2c88b14bee17bdcf727..f2b0df69780e4ebde99f3df1a43fb34bca9805b9 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/controllers/default_controller.py @@ -1,21 +1,16 @@ import connexion -from api_invoker_management.models.api_invoker_enrolment_details import APIInvokerEnrolmentDetails # noqa: E501 +from ..models.api_invoker_enrolment_details import APIInvokerEnrolmentDetails # noqa: E501 from ..core.apiinvokerenrolmentdetails import InvokerManagementOperations from ..core.validate_user import ControlAccess -import json from flask import Response, request, current_app from flask_jwt_extended import jwt_required, get_jwt_identity -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails from cryptography import x509 from cryptography.hazmat.backends import default_backend -from ..core.publisher import Publisher from functools import wraps invoker_operations = InvokerManagementOperations() -publisher_ops = Publisher() valid_user = ControlAccess() @@ -59,11 +54,6 @@ def onboarded_invokers_onboarding_id_delete(onboarding_id): # noqa: E501 current_app.logger.info("Removing invoker") res = invoker_operations.remove_apiinvokerenrolmentdetail(onboarding_id) - if res.status_code == 204: - current_app.logger.info("Invoker Removed") - publisher_ops.publish_message("events", "API_INVOKER_OFFBOARDED") - publisher_ops.publish_message("internal-messages", f"invoker-removed:{onboarding_id}") - return res @cert_validation() @@ -84,10 +74,6 @@ def onboarded_invokers_onboarding_id_put(onboarding_id, body): # noqa: E501 body = APIInvokerEnrolmentDetails.from_dict(connexion.request.get_json()) # noqa: E501 res = invoker_operations.update_apiinvokerenrolmentdetail(onboarding_id,body) - if res.status_code == 200: - current_app.logger.info("Invoker Updated") - publisher_ops.publish_message("events", "API_INVOKER_UPDATED") - return res @@ -104,20 +90,12 @@ def onboarded_invokers_post(body): # noqa: E501 """ identity = get_jwt_identity() - username, role = identity.split() - - if role != "invoker": - prob = ProblemDetails(title="Unauthorized", status=401, detail="Role not authorized for this API route", - cause="User role must be invoker") - return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype='application/json') + username, uuid = identity.split() if connexion.request.is_json: body = APIInvokerEnrolmentDetails.from_dict(connexion.request.get_json()) # noqa: E501 current_app.logger.info("Creating Invoker") - res = invoker_operations.add_apiinvokerenrolmentdetail(body, username) - if res.status_code == 201: - current_app.logger.info("Invoker Created") - publisher_ops.publish_message("events", "API_INVOKER_ONBOARDED") + res = invoker_operations.add_apiinvokerenrolmentdetail(body, username, uuid) return res diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py index 8969ec17bffce2d94e8b94ce315d1a7b04d52e08..bcf1905da8b4f3a5901a833fad70112740877c8b 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/apiinvokerenrolmentdetails.py @@ -5,13 +5,16 @@ import requests from .responses import bad_request_error, not_found_error, forbidden_error, internal_server_error, make_response from flask import current_app, Flask, Response import json -from ..util import dict_to_camel_case +from datetime import datetime +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case from .auth_manager import AuthManager from .resources import Resource from ..config import Config +from api_invoker_management.models.api_invoker_enrolment_details import APIInvokerEnrolmentDetails +from .redis_event import RedisEvent +from .publisher import Publisher - - +publisher_ops = Publisher() class InvokerManagementOperations(Resource): def __check_api_invoker_id(self, api_invoker_id): @@ -23,7 +26,7 @@ class InvokerManagementOperations(Resource): if old_values is None: current_app.logger.error("Not found api invoker id") - return not_found_error(detail="Please provide an existing Netapp ID", cause= "Not exist NetappID" ) + return not_found_error(detail="Please provide an existing Network App ID", cause= "Not exist Network App ID" ) return old_values @@ -38,7 +41,7 @@ class InvokerManagementOperations(Resource): 'common_name': invoker_id } - response = requests.request("POST", url, headers=headers, data=data, verify = False) + response = requests.request("POST", url, headers=headers, data=data, verify = self.config["ca_factory"].get("verify", False)) print(response) response_payload = json.loads(response.text) @@ -50,13 +53,11 @@ class InvokerManagementOperations(Resource): self.config = Config().get_config() - def add_apiinvokerenrolmentdetail(self, apiinvokerenrolmentdetail, username): + def add_apiinvokerenrolmentdetail(self, apiinvokerenrolmentdetail, username, uuid): mycol = self.db.get_col_by_name(self.db.invoker_enrolment_details) - register = self.db.get_col_by_name_register(self.db.capif_users) #try: - current_app.logger.debug("Creating invoker resource") res = mycol.find_one({'onboarding_information.api_invoker_public_key': apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key}) @@ -73,27 +74,30 @@ class InvokerManagementOperations(Resource): api_invoker_id = 'INV'+str(secrets.token_hex(15)) cert = self.__sign_cert(apiinvokerenrolmentdetail.onboarding_information.api_invoker_public_key, api_invoker_id) - apiinvokerenrolmentdetail.api_invoker_id = api_invoker_id current_app.logger.debug(cert) apiinvokerenrolmentdetail.onboarding_information.api_invoker_certificate = cert['data']['certificate'] - mycol.insert_one(apiinvokerenrolmentdetail.to_dict()) - register.update_one({'username':username}, {"$push":{'list_invokers':api_invoker_id}}) + # Onboarding Date Record + invoker_dict = apiinvokerenrolmentdetail.to_dict() + invoker_dict["onboarding_date"] = datetime.now() + invoker_dict["username"]=username + invoker_dict["uuid"]=uuid + + mycol.insert_one(invoker_dict) current_app.logger.debug("Invoker inserted in database") current_app.logger.debug("Netapp onboarded sucessfuly") self.auth_manager.add_auth_invoker(cert['data']['certificate'], api_invoker_id) - res = make_response(object=apiinvokerenrolmentdetail, status=201) + res = make_response(object=serialize_clean_camel_case(apiinvokerenrolmentdetail), status=201) res.headers['Location'] = "/api-invoker-management/v1/onboardedInvokers/" + str(api_invoker_id) - return res - # except Exception as e: - # exception = "An exception occurred in create invoker" - # current_app.logger.error(exception + "::" + str(e)) - # return internal_server_error(detail=exception, cause=str(e)) + if res.status_code == 201: + current_app.logger.info("Invoker Created") + RedisEvent("API_INVOKER_ONBOARDED", "apiInvokerIds", [str(api_invoker_id)]).send_event() + return res def update_apiinvokerenrolmentdetail(self, onboard_id, apiinvokerenrolmentdetail): @@ -123,7 +127,13 @@ class InvokerManagementOperations(Resource): } current_app.logger.debug("Invoker Resource inserted in database") - res = make_response(object=dict_to_camel_case(result), status=200) + + invoker_updated = APIInvokerEnrolmentDetails().from_dict(dict_to_camel_case(result)) + + res = make_response(object=serialize_clean_camel_case(invoker_updated), status=200) + if res.status_code == 200: + current_app.logger.info("Invoker Updated") + RedisEvent("API_INVOKER_UPDATED", "apiInvokerIds", [onboard_id]).send_event() return res except Exception as e: @@ -134,7 +144,6 @@ class InvokerManagementOperations(Resource): def remove_apiinvokerenrolmentdetail(self, onboard_id): mycol = self.db.get_col_by_name(self.db.invoker_enrolment_details) - register = self.db.get_col_by_name_register(self.db.capif_users) try: current_app.logger.debug("Removing invoker resource") result = self.__check_api_invoker_id(onboard_id) @@ -143,13 +152,17 @@ class InvokerManagementOperations(Resource): return result mycol.delete_one({'api_invoker_id':onboard_id}) - register.update_one({'list_invokers':onboard_id}, {"$pull":{'list_invokers':onboard_id}}) self.auth_manager.remove_auth_invoker(onboard_id) current_app.logger.debug("Invoker resource removed from database") current_app.logger.debug("Netapp offboarded sucessfuly") - out = "The Netapp matching onboardingId " + onboard_id + " was offboarded." - return make_response(out, status=204) + out = "The Network App matching onboardingId " + onboard_id + " was offboarded." + res = make_response(out, status=204) + if res.status_code == 204: + current_app.logger.info("Invoker Removed") + RedisEvent("API_INVOKER_OFFBOARDED", "apiInvokerIds", [onboard_id]).send_event() + publisher_ops.publish_message("internal-messages", f"invoker-removed:{onboard_id}") + return res except Exception as e: exception = "An exception occurred in remove invoker" diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py index cfab01e271b46df831399394a92ce54732ff8003..c3736a6d4e2e95d58ab6a96c1e62fe42404538f1 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/auth_manager.py @@ -1,5 +1,3 @@ - -from flask import current_app from cryptography import x509 from cryptography.hazmat.backends import default_backend from .resources import Resource diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py index a0aa138a0d9c63b49446b4fa04c93e6afde3d03a..a680d4d53205846ed11e6723b553138877c564d8 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/invoker_internal_ops.py @@ -1,6 +1,5 @@ from .resources import Resource -from flask import current_app class InvokerInternalOperations(Resource): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py index 3898c4b8309b14a05f8b5de89626fac8ebea4fc4..34fcdf453873b4b59a894d9f6b96b7ce1a217c2e 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/publisher.py @@ -1,6 +1,4 @@ import redis -import sys -from flask import current_app class Publisher(): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/redis_event.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/redis_event.py new file mode 100644 index 0000000000000000000000000000000000000000..aadbdbb6b3116cf288648de41effdb12b9ca9143 --- /dev/null +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/redis_event.py @@ -0,0 +1,41 @@ +from ..encoder import JSONEncoder +from .publisher import Publisher +import json + +publisher_ops = Publisher() + + +class RedisEvent(): + def __init__(self, event, event_detail_key=None, information=None) -> None: + self.EVENTS_ENUM = [ + 'SERVICE_API_AVAILABLE', + 'SERVICE_API_UNAVAILABLE', + 'SERVICE_API_UPDATE', + 'API_INVOKER_ONBOARDED', + 'API_INVOKER_OFFBOARDED', + 'SERVICE_API_INVOCATION_SUCCESS', + 'SERVICE_API_INVOCATION_FAILURE', + 'ACCESS_CONTROL_POLICY_UPDATE', + 'ACCESS_CONTROL_POLICY_UNAVAILABLE', + 'API_INVOKER_AUTHORIZATION_REVOKED', + 'API_INVOKER_UPDATED', + 'API_TOPOLOGY_HIDING_CREATED', + 'API_TOPOLOGY_HIDING_REVOKED'] + if event not in self.EVENTS_ENUM: + raise Exception( + "Event (" + event + ") is not on event enum (" + ','.join(self.EVENTS_ENUM) + ")") + self.redis_event = { + "event": event + } + if event_detail_key != None and information != None: + self.redis_event['key'] = event_detail_key + self.redis_event['information'] = information + + def to_string(self): + return json.dumps(self.redis_event, cls=JSONEncoder) + + def send_event(self): + publisher_ops.publish_message("events", self.to_string()) + + def __call__(self): + return self.redis_event diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py index 94e29ec07359c93a78d520f24fa91c88971d65c4..efbe3c2d4cf28cec298ef17b394011dcd6aa66cb 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/resources.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py index 962c4b6dd6ae07bce79dc8e810f10a507d526663..f647dbf7b3f5ca6fa7bd36367f863ba21e99f8f4 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/responses.py @@ -2,30 +2,40 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response import json +from ..util import serialize_clean_camel_case mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py index 5a2a5dc560b1a7a6c2a62791ded0792da4746a90..b1e7a9bf9c0bfd032b37e08ca47c2669c6999d09 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/core/validate_user.py @@ -4,6 +4,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import serialize_clean_camel_case + class ControlAccess(Resource): @@ -18,6 +20,7 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py index 32a34b857cd44ea065ab6dc30b8c75a7c671fc5a..1ef0262504047495eba1c6f05d4d2e3de8d5391d 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/db/db.py @@ -1,13 +1,13 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() class MongoDatabse(): @@ -15,9 +15,7 @@ class MongoDatabse(): def __init__(self): self.config = Config().get_config() self.db = self.__connect() - self.register = self.__connect_register() self.invoker_enrolment_details = self.config['mongo']['col'] - self.capif_users = self.config['mongo']['capif_users_col'] self.service_col = self.config['mongo']["service_col"] self.certs_col = self.config['mongo']['certs_col'] @@ -25,10 +23,6 @@ class MongoDatabse(): def get_col_by_name(self, name): return self.db[name].with_options(codec_options=CodecOptions(tz_aware=True)) - def get_col_by_name_register(self, name): - return self.register[name].with_options(codec_options=CodecOptions(tz_aware=True)) - - def __connect(self, max_retries=3, retry_delay=1): retries = 0 @@ -48,29 +42,8 @@ class MongoDatabse(): print(f"Reconnecting... Retry {retries} of {max_retries}") time.sleep(retry_delay) return None - - def __connect_register(self, max_retries=3, retry_delay=1): - - retries = 0 - - while retries < max_retries: - try: - uri = f"mongodb://{self.config['mongo_register']['user']}:{self.config['mongo_register']['password']}@" \ - f"{self.config['mongo_register']['host']}:{self.config['mongo_register']['port']}" - - - client = MongoClient(uri) - mydb = client[self.config['mongo_register']['db']] - mydb.command("ping") - return mydb - except AutoReconnect: - retries += 1 - print(f"Reconnecting... Retry {retries} of {max_retries}") - time.sleep(retry_delay) - return None def close_connection(self): if self.db.client: self.db.client.close() - if self.register.client: - self.register.client.close() + diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py index 04b06eb0adb09b675ccd98384aa98fc9fabbbe2c..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from api_invoker_management.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py index 6ce55d89b6a2673f6ad15702c9335d578877825e..31af7ab10eab38338398dd85eadcfa42e500519d 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/util.py @@ -1,8 +1,28 @@ import datetime import six -import typing -from api_invoker_management import typing_utils +import typing_utils + + +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res + + +def clean_empty(d): + if isinstance(d, dict): + return { + k: v + for k, v in ((k, clean_empty(v)) for k, v in d.items()) + if v + } + if isinstance(d, list): + return [v for v in map(clean_empty, d) if v] + return d + def dict_to_camel_case(my_dict): @@ -11,8 +31,11 @@ def dict_to_camel_case(my_dict): for attr, value in my_dict.items(): - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key = ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr if isinstance(value, list): result[my_key] = list(map( diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/wsgi.py b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/api_invoker_management/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/config.yaml b/services/TS29222_CAPIF_API_Invoker_Management_API/config.yaml index e208a78ccfe2a48d16071e149b36575ba865e4d7..3107e411fbdaecb7e9bf44f86025d4b27fd81e49 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/config.yaml +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/config.yaml @@ -3,24 +3,17 @@ mongo: { 'password': 'example', 'db': 'capif', 'col': 'invokerdetails', - 'capif_users_col': "user", 'certs_col': "certs", 'service_col': 'serviceapidescriptions', 'host': 'mongo', 'port': "27017" } -mongo_register: { - 'user': 'root', - 'password': 'example', - 'db': 'capif_users', - 'col': 'user', - 'host': 'mongo_register', - 'port': '27017' -} + ca_factory: { "url": "vault", "port": "8200", - "token": "dev-only-token" + "token": "dev-only-token", + "verify": False } monitoring: { diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh b/services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh index 90ce2be086ecaa87740728f0f1f32c10627b0c1e..df73fa6481be279fa52e2d825b529024f1f36bff 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/prepare_invoker.sh @@ -14,5 +14,5 @@ curl -vv -k -retry 30 \ --request GET "$VAULT_ADDR/v1/secret/data/server_cert/pub" 2>/dev/null | jq -r '.data.data.pub_key' -j > /usr/src/app/api_invoker_management/pubkey.pem -cd /usr/src/app/ -python3 -m api_invoker_management \ No newline at end of file +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/api_invoker_management wsgi:app \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt b/services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt index ce843e66061b4a6627a867b9853ce81adb411441..dbf0f198c54c3dea4807fe473ffcde6d560a528c 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/requirements.txt @@ -1,11 +1,11 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 -pymongo == 4.3.3 +pymongo == 4.7.3 flask_jwt_extended == 4.4.4 -pyopenssl == 23.0.0 +cryptography == 42.0.8 rfc3987 == 1.3.8 redis == 4.5.4 opentelemetry-instrumentation == 0.40b0 @@ -13,9 +13,12 @@ opentelemetry-instrumentation-flask == 0.40b0 opentelemetry-instrumentation-redis == 0.40b0 opentelemetry-instrumentation-pymongo == 0.40b0 opentelemetry-exporter-otlp == 1.19.0 -opentelemetry-exporter-jaeger==1.17.0 +opentelemetry-exporter-jaeger == 1.17.0 fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.19.0 opentelemetry-sdk == 1.19.0 flask_executor == 1.0.0 +Werkzeug == 2.2.3 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_API_Invoker_Management_API/test-requirements.txt b/services/TS29222_CAPIF_API_Invoker_Management_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_API_Invoker_Management_API/test-requirements.txt +++ b/services/TS29222_CAPIF_API_Invoker_Management_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/__main__.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/app.py similarity index 79% rename from services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/__main__.py rename to services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/app.py index f52d69c40eaa4612ea6069b5226490ec95c17fc2..2896830ca9ff062875fd666db2bc654a9c8bc0d2 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/__main__.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/app.py @@ -3,14 +3,13 @@ import connexion import logging -from api_provider_management import encoder +import encoder from flask_jwt_extended import JWTManager from logging.handlers import RotatingFileHandler -from .config import Config +from config import Config import os import sys from fluent import sender -from flask_executor import Executor from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry import trace from opentelemetry.trace.propagation.tracecontext import TraceContextTextMapPropagator @@ -24,6 +23,10 @@ from opentelemetry.instrumentation.redis import RedisInstrumentor NAME = "Provider-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -86,10 +89,10 @@ def configure_logging(app): loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="provider_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -98,7 +101,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) def verbose_formatter(): return logging.Formatter( @@ -106,31 +109,24 @@ def verbose_formatter(): datefmt='%d/%m/%Y %H:%M:%S' ) -def main(): - - with open("/usr/src/app/api_provider_management/pubkey.pem", "rb") as pub_file: - pub_data = pub_file.read() - - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - app.add_api('openapi.yaml', - arguments={'title': 'CAPIF_API_Provider_Management_API'}, - pythonic_params=True) - - config = Config() - configure_logging(app.app) - - if eval(os.environ.get("MONITORING").lower().capitalize()): - configure_monitoring(app.app, config.get_config()) - app.app.config['JWT_ALGORITHM'] = 'RS256' - app.app.config['JWT_PUBLIC_KEY'] = pub_data +with open("/usr/src/app/api_provider_management/pubkey.pem", "rb") as pub_file: + pub_data = pub_file.read() - JWTManager(app.app) +app = connexion.App(__name__, specification_dir='./openapi/') +app.app.json_encoder = encoder.JSONEncoder +app.add_api('openapi.yaml', + arguments={'title': 'CAPIF_API_Provider_Management_API'}, + pythonic_params=True) +config = Config() +configure_logging(app.app) - app.run(port=8080, debug=True) +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": + configure_monitoring(app.app, config.get_config()) +app.app.config['JWT_ALGORITHM'] = 'RS256' +app.app.config['JWT_PUBLIC_KEY'] = pub_data -if __name__ == '__main__': - main() +JWTManager(app.app) diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py index 377b14f8c368cebf98409223d089fc31326d1987..bed212ac136607ee7459f333b0f50bf7f3481b6b 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime if stamp != self.cached: diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py index 70e53734507bc9a3838db164d277b808e3bc0f4e..d9a190cd5cd48ceca8fcb7c8ecea79bc5c173b29 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/default_controller.py @@ -1,19 +1,18 @@ import connexion -import six -import json - from flask import Response, request, current_app + from ..core.provider_enrolment_details_api import ProviderManagementOperations -from ..encoder import JSONEncoder -from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 -from api_provider_management.models.problem_details import ProblemDetails # noqa: E501 -from api_provider_management import util +from ..models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 +from ..models.problem_details import ProblemDetails # noqa: E501 +from .. import util +from ..core.validate_user import ControlAccess + from cryptography import x509 from cryptography.hazmat.backends import default_backend from flask_jwt_extended import jwt_required, get_jwt_identity from cryptography import x509 from functools import wraps -from ..core.validate_user import ControlAccess + import sys @@ -59,20 +58,15 @@ def registrations_post(body): # noqa: E501 """ identity = get_jwt_identity() - username, role = identity.split() + username, uuid = identity.split() current_app.logger.info("Registering Provider Domain") - if role != "provider": - prob = ProblemDetails(title="Unauthorized", status=401, detail="Role not authorized for this API route", - cause="User role must be provider") - return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype='application/json') - if connexion.request.is_json: body = APIProviderEnrolmentDetails.from_dict(connexion.request.get_json()) # noqa: E501 - res = provider_management_ops.register_api_provider_enrolment_details(body, username) + res = provider_management_ops.register_api_provider_enrolment_details(body, username, uuid) return res diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py index dde822bbfbd9a8099bf4f7dcc9f84dfc7f57a2ad..dee8d1539b8945e2ff049a9ad8afb5dc4a0c34c9 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/controllers/individual_api_provider_enrolment_details_controller.py @@ -1,15 +1,12 @@ -from email.quoprimime import body_decode import connexion -import six -import json - from flask import Response, request, current_app from ..core.provider_enrolment_details_api import ProviderManagementOperations from ..encoder import JSONEncoder -from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 -from api_provider_management.models.api_provider_enrolment_details_patch import APIProviderEnrolmentDetailsPatch # noqa: E501 -from api_provider_management.models.problem_details import ProblemDetails # noqa: E501 -from api_provider_management import util +from ..models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 +from ..models.api_provider_enrolment_details_patch import APIProviderEnrolmentDetailsPatch # noqa: E501 +from ..models.problem_details import ProblemDetails # noqa: E501 +from .. import util + from cryptography.hazmat.backends import default_backend from cryptography import x509 diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py index a4a2d2419926d281426ce7876f4d45c1165fed40..cfa302ada519fbe9116b2bc33cae39ddeb009f87 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/auth_manager.py @@ -1,5 +1,4 @@ -from flask import current_app from cryptography import x509 from cryptography.hazmat.backends import default_backend from .resources import Resource diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py index 2077003b10f9ceaed4585d005783d81db741a5c9..30760b996db7ae7fbbc5fcd212bfaf979dc8a7f2 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/provider_enrolment_details_api.py @@ -4,11 +4,13 @@ import secrets from flask import current_app, Flask, Response from ..core.sign_certificate import sign_certificate from .responses import internal_server_error, not_found_error, forbidden_error, make_response, bad_request_error - -from ..util import dict_to_camel_case, clean_empty +from datetime import datetime +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case from .resources import Resource from .auth_manager import AuthManager +from api_provider_management.models.api_provider_enrolment_details import APIProviderEnrolmentDetails # noqa: E501 + class ProviderManagementOperations(Resource): @@ -29,10 +31,9 @@ class ProviderManagementOperations(Resource): Resource.__init__(self) self.auth_manager = AuthManager() - def register_api_provider_enrolment_details(self, api_provider_enrolment_details, username): + def register_api_provider_enrolment_details(self, api_provider_enrolment_details, username, uuid): try: mycol = self.db.get_col_by_name(self.db.provider_enrolment_details) - register = self.db.get_col_by_name_register(self.db.capif_users) current_app.logger.debug("Creating api provider domain") search_filter = {'reg_sec': api_provider_enrolment_details.reg_sec} @@ -44,7 +45,7 @@ class ProviderManagementOperations(Resource): api_provider_enrolment_details.api_prov_dom_id = secrets.token_hex(15) - current_app.logger.debug("Geretaing certs to api prov funcs") + current_app.logger.debug("Generating certs to api prov funcs") for api_provider_func in api_provider_enrolment_details.api_prov_funcs: api_provider_func.api_prov_func_id = api_provider_func.api_prov_func_role + str(secrets.token_hex(15)) @@ -53,13 +54,18 @@ class ProviderManagementOperations(Resource): self.auth_manager.add_auth_provider(certificate, api_provider_func.api_prov_func_id, api_provider_func.api_prov_func_role, api_provider_enrolment_details.api_prov_dom_id) + # Onboarding Date Record + provider_dict = api_provider_enrolment_details.to_dict() + provider_dict["onboarding_date"] = datetime.now() + provider_dict["username"] = username + provider_dict["uuid"] = uuid - mycol.insert_one(api_provider_enrolment_details.to_dict()) - register.update_one({'username':username}, {"$push":{'list_providers':api_provider_enrolment_details.api_prov_dom_id}}) - + mycol.insert_one(provider_dict) + current_app.logger.debug("Provider inserted in database") - res = make_response(object=api_provider_enrolment_details, status=201) + res = make_response(object=serialize_clean_camel_case(api_provider_enrolment_details), status=201) + res.headers['Location'] = "/api-provider-management/v1/registrations/" + str(api_provider_enrolment_details.api_prov_dom_id) return res @@ -71,7 +77,6 @@ class ProviderManagementOperations(Resource): def delete_api_provider_enrolment_details(self, api_prov_dom_id): try: mycol = self.db.get_col_by_name(self.db.provider_enrolment_details) - register = self.db.get_col_by_name_register(self.db.capif_users) current_app.logger.debug("Deleting provider domain") result = self.__check_api_provider_domain(api_prov_dom_id) @@ -84,13 +89,12 @@ class ProviderManagementOperations(Resource): amf_id = [ provider_func['api_prov_func_id'] for provider_func in result["api_prov_funcs"] if provider_func['api_prov_func_role'] == 'AMF' ] mycol.delete_one({'api_prov_dom_id': api_prov_dom_id}) - register.update_one({'list_providers':api_prov_dom_id}, {"$pull":{'list_providers':api_prov_dom_id}}) out = "The provider matching apiProvDomainId " + api_prov_dom_id + " was offboarded." current_app.logger.debug("Removed provider domain from database") self.auth_manager.remove_auth_provider([apf_id[0], aef_id[0], amf_id[0]]) - self.publish_ops.publish_message("internal-messages", f"provider-removed:{aef_id[0]}:{apf_id[0]}") + self.publish_ops.publish_message("internal-messages", f"provider-removed:{aef_id[0]}:{apf_id[0]}:{amf_id[0]}") return make_response(object=out, status=204) except Exception as e: @@ -120,22 +124,22 @@ class ProviderManagementOperations(Resource): for api_func in api_prov_funcs: if func.api_prov_func_id == api_func["api_prov_func_id"]: if func.api_prov_func_role != api_func["api_prov_func_role"]: - return bad_request_error(detail="Bad Role in provider", cause="Different role in update reqeuest", invalid_params=[{"param":"api_prov_func_role","reason":"differente role with same id"}]) + return bad_request_error(detail="Bad Role in provider", cause="Different role in update reqeuest", invalid_params=[{"param":"api_prov_func_role","reason":"different role with same id"}]) if func.reg_info.api_prov_pub_key != api_func["reg_info"]["api_prov_pub_key"]: certificate = sign_certificate(func.reg_info.api_prov_pub_key, api_func["api_prov_func_id"]) func.reg_info.api_prov_cert = certificate self.auth_manager.update_auth_provider(certificate, func.api_prov_func_id, api_prov_dom_id, func.api_prov_func_role) - api_provider_enrolment_details = api_provider_enrolment_details.to_dict() api_provider_enrolment_details = clean_empty(api_provider_enrolment_details) result = mycol.find_one_and_update(result, {"$set":api_provider_enrolment_details}, projection={'_id': 0},return_document=ReturnDocument.AFTER ,upsert=False) - result = clean_empty(result) current_app.logger.debug("Provider domain updated in database") - return make_response(object=dict_to_camel_case(result), status=200) + provider_updated = APIProviderEnrolmentDetails().from_dict(dict_to_camel_case(result)) + + return make_response(object=serialize_clean_camel_case(provider_updated), status=200) except Exception as e: exception = "An exception occurred in update provider" @@ -160,8 +164,9 @@ class ProviderManagementOperations(Resource): result = clean_empty(result) current_app.logger.debug("Provider domain updated in database") + provider_updated = APIProviderEnrolmentDetails().from_dict(dict_to_camel_case(result)) - return make_response(object=dict_to_camel_case(result), status=200) + return make_response(object=serialize_clean_camel_case(provider_updated), status=200) except Exception as e: exception = "An exception occurred in patch provider" diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py index 38d7259fbf3480e808cd67c3f25f965a5ffcdba4..acedb7e3e337fda548faf59c1a1b240a4ca6f905 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/publisher.py @@ -1,5 +1,4 @@ import redis -import sys class Publisher(): diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py index 86e99d4bfcd5811fcc9256cfdb82839266dbd8b5..7b8092ab35ed7214a6eddfdad30577747e3a673a 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/resources.py @@ -1,6 +1,6 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse -from .publisher import Publisher +from abc import ABC +from db.db import MongoDatabse +from core.publisher import Publisher class Resource(ABC): diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py index 962c4b6dd6ae07bce79dc8e810f10a507d526663..98eca0c9453aa3eaf676c209e9f2708b2b2d44e2 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/responses.py @@ -1,31 +1,41 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder -from flask import Response +from ..util import serialize_clean_camel_case +from flask import Response, current_app import json mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py index 6ec96cf181ad21ebcbeec3247a34b17da559e214..1e23a8104ede297eaa13a2c870c7df5635ad412c 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/sign_certificate.py @@ -1,6 +1,5 @@ import requests import json -import sys from ..config import Config def sign_certificate(publick_key, provider_id): @@ -16,7 +15,7 @@ def sign_certificate(publick_key, provider_id): 'common_name': provider_id } - response = requests.request("POST", url, headers=headers, data=json.dumps(data), verify = False) + response = requests.request("POST", url, headers=headers, data=json.dumps(data), verify = config["ca_factory"].get("verify", False)) response_payload = json.loads(response.text) return response_payload["data"]["certificate"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py index 4d101aee06bd0e3a763f8727c7bdb2f9a09caa61..29043d520f6bfab2f3be3b0b63479440a4ba8aad 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/core/validate_user.py @@ -4,6 +4,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import serialize_clean_camel_case + class ControlAccess(Resource): @@ -18,6 +20,7 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py index a5d843a4bc61f0edac3caae779c1f16852378ea8..024529c6927f900e815804567bf3dd283c3d2a57 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/db/db.py @@ -1,13 +1,13 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() @@ -16,17 +16,11 @@ class MongoDatabse(): def __init__(self): self.config = Config().get_config() self.db = self.__connect() - self.register = self.__connect_register() self.provider_enrolment_details = self.config['mongo']['col'] - self.capif_users = self.config['mongo']['capif_users'] self.certs_col = self.config['mongo']['certs_col'] def get_col_by_name(self, name): return self.db[name].with_options(codec_options=CodecOptions(tz_aware=True)) - def get_col_by_name_register(self, name): - return self.register[name].with_options(codec_options=CodecOptions(tz_aware=True)) - - def __connect(self, max_retries=3, retry_delay=1): retries = 0 @@ -44,30 +38,8 @@ class MongoDatabse(): time.sleep(retry_delay) return None - def __connect_register(self, max_retries=3, retry_delay=1): - - retries = 0 - - while retries < max_retries: - try: - uri = f"mongodb://{self.config['mongo_register']['user']}:{self.config['mongo_register']['password']}@" \ - f"{self.config['mongo_register']['host']}:{self.config['mongo_register']['port']}" - - - client = MongoClient(uri) - mydb = client[self.config['mongo_register']['db']] - mydb.command("ping") - return mydb - except AutoReconnect: - retries += 1 - print(f"Reconnecting... Retry {retries} of {max_retries}") - time.sleep(retry_delay) - return None - def close_connection(self): if self.db.client: self.db.client.close() - if self.register.client: - self.register.client.close() diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py index 01531f242309ec381907e92bba20d3cf9f01306d..3f1c01ce6812b1ff12e0d1d284bc433e951e1ea6 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/encoder.py @@ -1,8 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from api_provider_management.models.base_model_ import Model - +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): include_nulls = False diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py index e769d2852d772e8716895c7c9313987f4e44bf74..431a28c6f522dec54599eb6e30ac9f9e4a040d49 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/util.py @@ -1,8 +1,15 @@ import datetime - import six -import typing -from api_provider_management import typing_utils +import typing_utils + + +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res + def clean_empty(d): if isinstance(d, dict): @@ -15,6 +22,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): @@ -22,8 +30,11 @@ def dict_to_camel_case(my_dict): for attr, value in my_dict.items(): - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key = ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr if isinstance(value, list): result[my_key] = list(map( @@ -40,6 +51,7 @@ def dict_to_camel_case(my_dict): return result + def _deserialize(data, klass): """Deserializes dict, list, str into an object. diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/wsgi.py b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_API_Provider_Management_API/api_provider_management/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/config.yaml b/services/TS29222_CAPIF_API_Provider_Management_API/config.yaml index 8de29a4385fffc05236cae4a9e72f9490969e47f..ce684f368f6bec6f91775710f96ed097fe0d6bf3 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/config.yaml +++ b/services/TS29222_CAPIF_API_Provider_Management_API/config.yaml @@ -4,24 +4,16 @@ mongo: { 'db': 'capif', 'col': 'providerenrolmentdetails', 'certs_col': "certs", - 'capif_users': 'user', 'host': 'mongo', 'port': "27017" } -mongo_register: { - 'user': 'root', - 'password': 'example', - 'db': 'capif_users', - 'col': 'user', - 'host': 'mongo_register', - 'port': '27017' -} ca_factory: { "url": "vault", "port": "8200", - "token": "dev-only-token" + "token": "dev-only-token", + "verify": False } diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh b/services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh index 93bf420144dcbd0fdfb40055dc94104d9e63d07b..5ec3096850c15a6a5ec6f9ad7173e61a122baf97 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh +++ b/services/TS29222_CAPIF_API_Provider_Management_API/prepare_provider.sh @@ -13,7 +13,7 @@ curl -vv -k -retry 30 \ --request GET "$VAULT_ADDR/v1/secret/data/server_cert/pub" 2>/dev/null | jq -r '.data.data.pub_key' -j > /usr/src/app/api_provider_management/pubkey.pem +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/api_provider_management wsgi:app -cd /usr/src/app/ -python3 -m api_provider_management diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt b/services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt index d45d1e529f471f976ba4d88f0141be29bc38a4be..a5c9ccef16b0c711e5d502db5efc6f574eb97476 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt +++ b/services/TS29222_CAPIF_API_Provider_Management_API/requirements.txt @@ -1,12 +1,12 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 -pymongo == 4.0.1 +pymongo == 4.7.3 redis == 4.5.4 flask_jwt_extended == 4.4.4 -pyopenssl == 23.0.0 +cryptography == 42.0.8 rfc3987 == 1.3.8 opentelemetry-instrumentation == 0.38b0 opentelemetry-instrumentation-flask == 0.38b0 @@ -18,4 +18,6 @@ fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 - +Werkzeug == 2.2.3 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_API_Provider_Management_API/test-requirements.txt b/services/TS29222_CAPIF_API_Provider_Management_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_API_Provider_Management_API/test-requirements.txt +++ b/services/TS29222_CAPIF_API_Provider_Management_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile b/services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile index 92dcb338cb2592781871d50a47f69796ab664f41..9c1382590feac6390a85c9ac48dc55b64b805496 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/Dockerfile @@ -11,6 +11,4 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] - -CMD ["-m", "openapi_server"] \ No newline at end of file +CMD ["sh", "prepare_capif_acl.sh"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/__init__.py similarity index 100% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__init__.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/__init__.py diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__main__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/app.py similarity index 90% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__main__.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/app.py index 215e85efe43a80a28bd8ac8bb3875498ced1bcd0..59a0f90b9976dfd4ee1cecb0173ec6b03cf4cd8f 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/__main__.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/app.py @@ -2,19 +2,17 @@ import connexion -from openapi_server import encoder +import encoder import logging -from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient from logging.handlers import RotatingFileHandler -from .config import Config +from config import Config from datetime import datetime import os from fluent import sender -from .core.consumer_messager import Subscriber +from core.consumer_messager import Subscriber from flask_executor import Executor from flask_apscheduler import APScheduler from opentelemetry.instrumentation.flask import FlaskInstrumentor @@ -28,6 +26,10 @@ from opentelemetry.instrumentation.redis import RedisInstrumentor NAME = "Acl-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -91,10 +93,10 @@ def configure_logging(app): loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="acl_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -103,7 +105,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) def verbose_formatter(): return logging.Formatter( @@ -117,16 +119,13 @@ app.add_api('openapi.yaml', arguments={'title': 'CAPIF_Access_Control_policy_API'}, pythonic_params=True) - config = Config() - - jwt = JWTManager(app.app) configure_logging(app.app) - -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": configure_monitoring(app.app, config.get_config()) app.app.config["invocations"]=config.get_config()["invocations"] @@ -138,12 +137,9 @@ subscriber = Subscriber() scheduler = APScheduler() scheduler.api_enabled = True scheduler.init_app(app.app) +scheduler.start() @scheduler.task('date', id='listener', next_run_time=datetime.now()) def up_listener(): with scheduler.app.app_context(): executor.submit(subscriber.listen()) - -if __name__ == '__main__': - scheduler.start() - app.run(debug=True,port=8080, use_reloader=False) diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/config.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/config.py similarity index 92% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/config.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/config.py index 11e1c4f3626d7440c6cd999ed118afb3c93caa2e..01f9914cc141eb3c49fd73506e9b1c5470edd781 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/config.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/__init__.py similarity index 100% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/__init__.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/__init__.py diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/default_controller.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/default_controller.py similarity index 95% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/default_controller.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/default_controller.py index c17e19585710f78c4374eb50e1cafa2070973432..52174b1eee09160d184a65d3d412954f187240db 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/default_controller.py @@ -1,4 +1,4 @@ -from typing import Dict + from functools import wraps from flask import request, current_app from cryptography import x509 @@ -6,6 +6,7 @@ from cryptography.hazmat.backends import default_backend from ..core.accesscontrolpolicyapi import accessControlPolicyApi + def cert_validation(): def _cert_validation(f): @wraps(f) @@ -42,5 +43,4 @@ def access_control_policy_list_service_api_id_get(service_api_id, aef_id, api_in :rtype: Union[AccessControlPolicyList, Tuple[AccessControlPolicyList, int], Tuple[AccessControlPolicyList, int, Dict[str, str]] """ current_app.logger.debug("Obtaining service ACLs") - #current_app.logger.debug(f"AEF-id: {service_api_id}") return accessControlPolicyApi().get_acl(service_api_id, aef_id, api_invoker_id, supported_features) diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/security_controller_.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/security_controller_.py similarity index 100% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/controllers/security_controller_.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/controllers/security_controller_.py diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/accesscontrolpolicyapi.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/accesscontrolpolicyapi.py similarity index 85% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/accesscontrolpolicyapi.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/accesscontrolpolicyapi.py index fd14e80dc86e5754e79f66e251e2bda2212266b8..48bf04e69b04e537e5c3de4f957a87fabe8125c8 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/accesscontrolpolicyapi.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/accesscontrolpolicyapi.py @@ -2,7 +2,8 @@ from ..core.resources import Resource from flask import current_app from .responses import make_response, not_found_error, internal_server_error from ..models.access_control_policy_list import AccessControlPolicyList -from ..util import dict_to_camel_case, clean_empty +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case + class accessControlPolicyApi(Resource): def get_acl(self, service_api_id, aef_id, api_invoker_id, supported_features): @@ -20,8 +21,8 @@ class accessControlPolicyApi(Resource): projection = {"_id":0} if api_invoker_id is not None: - query['apiInvokerPolicies.api_invoker_id'] = api_invoker_id - projection['apiInvokerPolicies.$'] = 1 + query['api_invoker_policies.api_invoker_id'] = api_invoker_id + projection['api_invoker_policies.$'] = 1 if supported_features is not None: current_app.logger.debug(f"SupportedFeatures present on query with value {supported_features}, but currently not used") @@ -37,17 +38,16 @@ class accessControlPolicyApi(Resource): current_app.logger.debug(policies) - api_invoker_policies = policies[0]['apiInvokerPolicies'] - current_app.logger.debug(f"apiinvokerPolicies: {api_invoker_policies}") + api_invoker_policies = policies[0]['api_invoker_policies'] + current_app.logger.debug(f"api_invoker_policies: {api_invoker_policies}") if not api_invoker_policies: current_app.logger.info(f"ACLs list is present but empty, then no ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}") #Not found error return not_found_error(f"No ACLs found for the requested service: {service_api_id}, aef_id: {aef_id}, invoker: {api_invoker_id} and supportedFeatures: {supported_features}", "Wrong id") acl = AccessControlPolicyList(api_invoker_policies) - response = acl.to_dict() - return make_response(object=dict_to_camel_case(response), status=200) - + return make_response(object=serialize_clean_camel_case(acl), status=200) + except Exception as e: exception = "An exception occurred in get acl" current_app.logger.error(exception + "::" + str(e)) diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/consumer_messager.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/consumer_messager.py similarity index 98% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/consumer_messager.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/consumer_messager.py index 72c51eeacdbf45668cde55141e17a4ad87db0e09..0da24408e801f22693e0412636df090680c1424c 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/consumer_messager.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/consumer_messager.py @@ -1,6 +1,6 @@ # subscriber.py import redis -from ..config import Config +from config import Config from .internal_service_ops import InternalServiceOps from flask import current_app diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py new file mode 100644 index 0000000000000000000000000000000000000000..1e5aa20c0d708dee31e51b2586e0295ba3ea629a --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/internal_service_ops.py @@ -0,0 +1,109 @@ + +from flask import current_app +from .resources import Resource +from models.api_invoker_policy import ApiInvokerPolicy +from models.time_range_list import TimeRangeList +from datetime import datetime, timedelta + +from .redis_event import RedisEvent +from util import dict_to_camel_case, clean_empty + + +class InternalServiceOps(Resource): + + def create_acl(self, invoker_id, service_id, aef_id): + + current_app.logger.info(f"Creating ACL for invoker: {invoker_id}") + + if "acls" not in self.db.db.list_collection_names(): + self.db.db.create_collection("acls") + + mycol = self.db.get_col_by_name(self.db.acls) + + res = mycol.find_one( + {"service_id": service_id, "aef_id": aef_id}, {"_id": 0}) + + if res: + current_app.logger.info( + f"Adding invoker ACL for invoker {invoker_id}") + range_list = [TimeRangeList( + datetime.utcnow(), datetime.utcnow()+timedelta(days=365))] + invoker_acl = ApiInvokerPolicy( + invoker_id, current_app.config["invocations"]["total"], current_app.config["invocations"]["perSecond"], range_list) + r = mycol.find_one({"service_id": service_id, "aef_id": aef_id, + "api_invoker_policies.api_invoker_id": invoker_id}, {"_id": 0}) + if r is None: + mycol.update_one({"service_id": service_id, "aef_id": aef_id}, { + "$push": {"api_invoker_policies": invoker_acl.to_dict()}}) + else: + current_app.logger.info( + f"Creating service ACLs for service: {service_id}") + range_list = [TimeRangeList( + datetime.utcnow(), datetime.utcnow()+timedelta(days=365))] + invoker_acl = ApiInvokerPolicy( + invoker_id, current_app.config["invocations"]["total"], current_app.config["invocations"]["perSecond"], range_list) + + service_acls = { + "service_id": service_id, + "aef_id": aef_id, + "api_invoker_policies": [invoker_acl.to_dict()] + } + result = mycol.insert_one(service_acls) + + inserted_service_acls=mycol.find_one({"_id": result.inserted_id}, {"_id": 0}) + current_app.logger.info(inserted_service_acls) + inserted_service_acls_camel=dict_to_camel_case(inserted_service_acls) + current_app.logger.info(inserted_service_acls_camel) + accCtrlPolListExt = { + "apiId": service_id, + "apiInvokerPolicies": inserted_service_acls_camel['apiInvokerPolicies'] + } + RedisEvent("ACCESS_CONTROL_POLICY_UPDATE", + "accCtrlPolList", accCtrlPolListExt).send_event() + + current_app.logger.info( + f"Invoker ACL added for invoker: {invoker_id} for service: {service_id}") + + def remove_acl(self, invoker_id, service_id, aef_id): + + current_app.logger.info(f"Removing ACL for invoker: {invoker_id}") + + mycol = self.db.get_col_by_name(self.db.acls) + + res = mycol.find_one( + {"service_id": service_id, "aef_id": aef_id}, {"_id": 0}) + + if res: + mycol.update_many({"service_id": service_id, "aef_id": aef_id}, + {"$pull": {"api_invoker_policies": { + "api_invoker_id": invoker_id}}} + ) + else: + current_app.logger.info( + f"Not found: {service_id} for api : {service_id}") + + RedisEvent("ACCESS_CONTROL_POLICY_UNAVAILABLE").send_event() + + current_app.logger.info( + f"Invoker ACL removed for invoker: {invoker_id} for service: {service_id}") + + def remove_invoker_acl(self, invoker_id): + + current_app.logger.info(f"Removing ACLs for invoker: {invoker_id}") + mycol = self.db.get_col_by_name(self.db.acls) + + mycol.update_many({"api_invoker_policies.api_invoker_id": invoker_id}, + {"$pull": {"api_invoker_policies": { + "api_invoker_id": invoker_id}}} + ) + RedisEvent("ACCESS_CONTROL_POLICY_UNAVAILABLE").send_event() + current_app.logger.info(f"ACLs for invoker: {invoker_id} removed") + + def remove_provider_acls(self, id): + + current_app.logger.info(f"Removing ACLs for provider/service: {id}") + mycol = self.db.get_col_by_name(self.db.acls) + + mycol.delete_many({"$or": [{"service_id": id}, {"aef_id": id}]}) + RedisEvent("ACCESS_CONTROL_POLICY_UNAVAILABLE").send_event() + current_app.logger.info(f"ACLs for provider/service: {id} removed") diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/publisher.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/publisher.py similarity index 83% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/publisher.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/publisher.py index 3898c4b8309b14a05f8b5de89626fac8ebea4fc4..8292de4d4330b14c17be74e7448403b56fc5b9e3 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/publisher.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/publisher.py @@ -1,6 +1,5 @@ import redis -import sys -from flask import current_app + class Publisher(): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/redis_event.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/redis_event.py new file mode 100644 index 0000000000000000000000000000000000000000..40e3e406830e58a72359e4283d8ff6e0d66bb893 --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/redis_event.py @@ -0,0 +1,41 @@ +from encoder import JSONEncoder +from .publisher import Publisher +import json + +publisher_ops = Publisher() + + +class RedisEvent(): + def __init__(self, event, event_detail_key=None, information=None) -> None: + self.EVENTS_ENUM = [ + 'SERVICE_API_AVAILABLE', + 'SERVICE_API_UNAVAILABLE', + 'SERVICE_API_UPDATE', + 'API_INVOKER_ONBOARDED', + 'API_INVOKER_OFFBOARDED', + 'SERVICE_API_INVOCATION_SUCCESS', + 'SERVICE_API_INVOCATION_FAILURE', + 'ACCESS_CONTROL_POLICY_UPDATE', + 'ACCESS_CONTROL_POLICY_UNAVAILABLE', + 'API_INVOKER_AUTHORIZATION_REVOKED', + 'API_INVOKER_UPDATED', + 'API_TOPOLOGY_HIDING_CREATED', + 'API_TOPOLOGY_HIDING_REVOKED'] + if event not in self.EVENTS_ENUM: + raise Exception( + "Event (" + event + ") is not on event enum (" + ','.join(self.EVENTS_ENUM) + ")") + self.redis_event = { + "event": event + } + if event_detail_key != None and information != None: + self.redis_event['key'] = event_detail_key + self.redis_event['information'] = information + + def to_string(self): + return json.dumps(self.redis_event, cls=JSONEncoder) + + def send_event(self): + publisher_ops.publish_message("events", self.to_string()) + + def __call__(self): + return self.redis_event diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/resources.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/resources.py new file mode 100644 index 0000000000000000000000000000000000000000..d5a3552d6b3459a77d30df65d0bbda4a86c7fa61 --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/resources.py @@ -0,0 +1,8 @@ +from abc import ABC +from db.db import MongoDatabse + + +class Resource(ABC): + + def __init__(self): + self.db = MongoDatabse() \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/responses.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/responses.py similarity index 80% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/responses.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/responses.py index 962c4b6dd6ae07bce79dc8e810f10a507d526663..9f8c3e665d94e8d98044638870dcc65a9dab1a91 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/responses.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/core/responses.py @@ -1,31 +1,41 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case import json mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/db/db.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/db/db.py similarity index 91% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/db/db.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/db/db.py index b25c794b7699a6a904946e15810795825edb5ff5..e485c8923ea861c669454a68eb99716f86406023 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/db/db.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/db/db.py @@ -1,13 +1,14 @@ -import atexit + import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() class MongoDatabse(): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/encoder.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/encoder.py similarity index 91% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/encoder.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/encoder.py index 3bbef854f3b83dc985aea885756fd7147fa00001..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/encoder.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from openapi_server.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..4c4e60f91034863564e2c69f9c75a1d883d6990d --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/__init__.py @@ -0,0 +1,10 @@ +# coding: utf-8 + +# flake8: noqa +from __future__ import absolute_import +# import models into model package +from capif_acl.models.access_control_policy_list import AccessControlPolicyList +from capif_acl.models.api_invoker_policy import ApiInvokerPolicy +from capif_acl.models.invalid_param import InvalidParam +from capif_acl.models.problem_details import ProblemDetails +from capif_acl.models.time_range_list import TimeRangeList diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/access_control_policy_list.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/access_control_policy_list.py similarity index 90% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/access_control_policy_list.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/access_control_policy_list.py index 98f3fc122323f37a2868acd21375c3a6870b6970..b3cacd4164aab94158436597b462dc967f91a2f7 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/access_control_policy_list.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/access_control_policy_list.py @@ -5,11 +5,11 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server.models.api_invoker_policy import ApiInvokerPolicy -from openapi_server import util +from capif_acl.models.base_model_ import Model +from capif_acl.models.api_invoker_policy import ApiInvokerPolicy +from capif_acl import util -from openapi_server.models.api_invoker_policy import ApiInvokerPolicy # noqa: E501 +from capif_acl.models.api_invoker_policy import ApiInvokerPolicy # noqa: E501 class AccessControlPolicyList(Model): """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/api_invoker_policy.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/api_invoker_policy.py similarity index 96% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/api_invoker_policy.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/api_invoker_policy.py index a5f1b477c384bd485981ea49ab09ffb793796b1d..86ffec0cf84c8c867ebbd8db1594eb2746140591 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/api_invoker_policy.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/api_invoker_policy.py @@ -5,11 +5,11 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server.models.time_range_list import TimeRangeList -from openapi_server import util +from capif_acl.models.base_model_ import Model +from capif_acl.models.time_range_list import TimeRangeList +from capif_acl import util -from openapi_server.models.time_range_list import TimeRangeList # noqa: E501 +from capif_acl.models.time_range_list import TimeRangeList # noqa: E501 class ApiInvokerPolicy(Model): """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/base_model_.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/base_model_.py similarity index 98% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/base_model_.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/base_model_.py index 916e582ec27f19e7dbbb65885786760d5e7e4e98..cce5379c767ede112d5fdcdcffa34403bddb2884 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/base_model_.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/base_model_.py @@ -3,7 +3,7 @@ import pprint import six import typing -from openapi_server import util +from capif_acl import util T = typing.TypeVar('T') diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/invalid_param.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/invalid_param.py similarity index 96% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/invalid_param.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/invalid_param.py index 8d91e6c3f6dfe46c67a864916c0f8cd282d41f81..88606c4107c7ac4b408a0548af2feb398233b555 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/invalid_param.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/invalid_param.py @@ -5,8 +5,8 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server import util +from capif_acl.models.base_model_ import Model +from capif_acl import util class InvalidParam(Model): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/problem_details.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/problem_details.py similarity index 97% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/problem_details.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/problem_details.py index 08f2908c2964db647b8f890d2931f08dfceafeff..25caab4e29a65d9df08d966a551618c69a2ffa45 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/problem_details.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/problem_details.py @@ -5,12 +5,12 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server.models.invalid_param import InvalidParam +from capif_acl.models.base_model_ import Model +from capif_acl.models.invalid_param import InvalidParam import re -from openapi_server import util +from capif_acl import util -from openapi_server.models.invalid_param import InvalidParam # noqa: E501 +from capif_acl.models.invalid_param import InvalidParam # noqa: E501 import re # noqa: E501 class ProblemDetails(Model): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/time_range_list.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/time_range_list.py similarity index 96% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/time_range_list.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/time_range_list.py index eb18a7ed915166f82490460850cf108c384397c8..eaacad60592ff7acf1a9c2b7b71c21dfb6fd5083 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/time_range_list.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/models/time_range_list.py @@ -5,8 +5,8 @@ from datetime import date, datetime # noqa: F401 from typing import List, Dict # noqa: F401 -from openapi_server.models.base_model_ import Model -from openapi_server import util +from capif_acl.models.base_model_ import Model +from capif_acl import util class TimeRangeList(Model): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/openapi/openapi.yaml b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/openapi/openapi.yaml similarity index 99% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/openapi/openapi.yaml rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/openapi/openapi.yaml index 6f8c99d300bdb9b5224f8164f2c38e160c513699..1621baa9a449be7d8bb2377e7b2b6fd590cbec5d 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/openapi/openapi.yaml +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/openapi/openapi.yaml @@ -130,7 +130,7 @@ paths: description: Service Unavailable default: description: Generic Error - x-openapi-router-controller: openapi_server.controllers.default_controller + x-openapi-router-controller: capif_acl.controllers.default_controller components: responses: "307": diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/__init__.py similarity index 89% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/__init__.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/__init__.py index 364aba9fbf880b8a6d2d011380bd092f2e5d973a..5d664f823dc74e062cbb804324de82bf7d239643 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/__init__.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/__init__.py @@ -3,7 +3,7 @@ import logging import connexion from flask_testing import TestCase -from openapi_server.encoder import JSONEncoder +from capif_acl.encoder import JSONEncoder class BaseTestCase(TestCase): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/test_default_controller.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/test_default_controller.py similarity index 79% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/test_default_controller.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/test_default_controller.py index c850757e5ca3b3f1d5aa5ed6349b8ce22fb4186d..44ed0bee14671018ffb842dfe7e98edf26875ec2 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/test/test_default_controller.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/test/test_default_controller.py @@ -3,12 +3,7 @@ from __future__ import absolute_import import unittest -from flask import json -from six import BytesIO - -from openapi_server.models.access_control_policy_list import AccessControlPolicyList # noqa: E501 -from openapi_server.models.problem_details import ProblemDetails # noqa: E501 -from openapi_server.test import BaseTestCase +from test import BaseTestCase class TestDefaultController(BaseTestCase): diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/typing_utils.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/typing_utils.py similarity index 100% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/typing_utils.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/typing_utils.py diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/util.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/util.py similarity index 91% rename from services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/util.py rename to services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/util.py index 672406d079a400d7d50956c018539f2d5c95e370..72d18d9b7df0bfd24490b24c4b9d9bcd683ad9ef 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/util.py +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/util.py @@ -1,8 +1,16 @@ import datetime import six -import typing -from openapi_server import typing_utils +import typing_utils + + +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res + def clean_empty(d): if isinstance(d, dict): @@ -15,6 +23,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): @@ -22,8 +31,11 @@ def dict_to_camel_case(my_dict): for attr, value in my_dict.items(): - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key = ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr if isinstance(value, list): result[my_key] = list(map( @@ -41,8 +53,6 @@ def dict_to_camel_case(my_dict): return result - - def _deserialize(data, klass): """Deserializes dict, list, str into an object. diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/wsgi.py b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/capif_acl/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/internal_service_ops.py b/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/internal_service_ops.py deleted file mode 100644 index e10986adc4d84cec60374c8a21ddb04c149971ad..0000000000000000000000000000000000000000 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/internal_service_ops.py +++ /dev/null @@ -1,85 +0,0 @@ - -from flask import current_app -from .resources import Resource -from ..models.api_invoker_policy import ApiInvokerPolicy -from ..models.time_range_list import TimeRangeList -from datetime import datetime, timedelta -from ..core.publisher import Publisher - -publisher_ops = Publisher() -class InternalServiceOps(Resource): - - def create_acl(self, invoker_id, service_id, aef_id): - - current_app.logger.info(f"Creating ACL for invoker: {invoker_id}") - - if "acls" not in self.db.db.list_collection_names(): - self.db.db.create_collection("acls") - - mycol = self.db.get_col_by_name(self.db.acls) - - res = mycol.find_one({"service_id": service_id, "aef_id":aef_id}, {"_id":0}) - - if res: - current_app.logger.info(f"Adding invoker ACL for invoker {invoker_id}") - range_list = [TimeRangeList(datetime.utcnow(), datetime.utcnow()+timedelta(days=365))] - invoker_acl = ApiInvokerPolicy(invoker_id, current_app.config["invocations"]["total"], current_app.config["invocations"]["perSecond"], range_list) - r = mycol.find_one({"service_id": service_id, "aef_id":aef_id, "apiInvokerPolicies.api_invoker_id": invoker_id}, {"_id":0}) - if r is None: - mycol.update_one({"service_id": service_id, "aef_id":aef_id }, {"$push":{"apiInvokerPolicies":invoker_acl.to_dict()}}) - else: - current_app.logger.info(f"Creating service ACLs for service: {service_id}") - range_list = [TimeRangeList(datetime.utcnow(), datetime.utcnow()+timedelta(days=365))] - invoker_acl = ApiInvokerPolicy(invoker_id, current_app.config["invocations"]["total"], current_app.config["invocations"]["perSecond"], range_list) - - - - service_acls = { - "service_id": service_id, - "aef_id": aef_id, - "apiInvokerPolicies": [invoker_acl.to_dict()] - } - mycol.insert_one(service_acls) - publisher_ops.publish_message("events", "ACCESS_CONTROL_POLICY_UPDATE") - - current_app.logger.info(f"Invoker ACL added for invoker: {invoker_id} for service: {service_id}") - - def remove_acl(self, invoker_id, service_id, aef_id): - - current_app.logger.info(f"Removing ACL for invoker: {invoker_id}") - - mycol = self.db.get_col_by_name(self.db.acls) - - res = mycol.find_one({"service_id": service_id, "aef_id":aef_id}, {"_id":0}) - - if res: - mycol.update_many({"service_id": service_id, "aef_id":aef_id}, - {"$pull":{ "apiInvokerPolicies": { "api_invoker_id": invoker_id }}} - ) - else: - current_app.logger.info(f"Not found: {service_id} for api : {service_id}") - - publisher_ops.publish_message("events", "ACCESS_CONTROL_POLICY_UNAVAILABLE") - - current_app.logger.info(f"Invoker ACL removed for invoker: {invoker_id} for service: {service_id}") - - def remove_invoker_acl(self, invoker_id): - - current_app.logger.info(f"Removing ACLs for invoker: {invoker_id}") - mycol = self.db.get_col_by_name(self.db.acls) - - mycol.update_many({"apiInvokerPolicies.api_invoker_id": invoker_id}, - {"$pull":{ "apiInvokerPolicies": { "api_invoker_id": invoker_id }}} - ) - publisher_ops.publish_message("events", "ACCESS_CONTROL_POLICY_UNAVAILABLE") - current_app.logger.info(f"ACLs for invoker: {invoker_id} removed") - - def remove_provider_acls(self, id): - - current_app.logger.info(f"Removing ACLs for provider/service: {id}") - mycol = self.db.get_col_by_name(self.db.acls) - - mycol.delete_many({"$or":[{"service_id":id}, {"aef_id":id}]} - ) - publisher_ops.publish_message("events", "ACCESS_CONTROL_POLICY_UNAVAILABLE") - current_app.logger.info(f"ACLs for provider/service: {id} removed") \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/resources.py b/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/resources.py deleted file mode 100644 index 94e29ec07359c93a78d520f24fa91c88971d65c4..0000000000000000000000000000000000000000 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/core/resources.py +++ /dev/null @@ -1,7 +0,0 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse - -class Resource(ABC): - - def __init__(self): - self.db = MongoDatabse() \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/__init__.py b/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/__init__.py deleted file mode 100644 index a4269de2a23336ebf21fb6fe2813f1bc573459d0..0000000000000000000000000000000000000000 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/openapi_server/models/__init__.py +++ /dev/null @@ -1,10 +0,0 @@ -# coding: utf-8 - -# flake8: noqa -from __future__ import absolute_import -# import models into model package -from openapi_server.models.access_control_policy_list import AccessControlPolicyList -from openapi_server.models.api_invoker_policy import ApiInvokerPolicy -from openapi_server.models.invalid_param import InvalidParam -from openapi_server.models.problem_details import ProblemDetails -from openapi_server.models.time_range_list import TimeRangeList diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/prepare_capif_acl.sh b/services/TS29222_CAPIF_Access_Control_Policy_API/prepare_capif_acl.sh new file mode 100644 index 0000000000000000000000000000000000000000..fd0077ff49fd19e6e396a8253c2b63ce93e0c7c9 --- /dev/null +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/prepare_capif_acl.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/capif_acl wsgi:app \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt b/services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt index 03d8aafa8f87a0cfeeeddc14cb5ccc8a81c7ea83..2e82931ce42ddc44d6ae7c6e86961fcbe4751d7a 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/requirements.txt @@ -1,29 +1,26 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" -# 2.3 is the last version that supports python 3.4-3.5 -connexion[swagger-ui] <= 2.3.0; python_version=="3.5" or python_version=="3.4" -# connexion requires werkzeug but connexion < 2.4.0 does not install werkzeug -# we must peg werkzeug versions below to fix connexion -# https://github.com/zalando/connexion/pull/1044 -werkzeug == 0.16.1; python_version=="3.5" or python_version=="3.4" +Werkzeug == 2.2.3 swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 -Flask == 2.1.1 -pymongo == 4.3.3 +setuptools == 68.2.2 +Flask == 2.0.3 +pymongo == 4.7.3 flask_jwt_extended == 4.4.4 opentelemetry-instrumentation == 0.38b0 opentelemetry-instrumentation-flask == 0.38b0 opentelemetry-instrumentation-redis == 0.38b0 opentelemetry-instrumentation-pymongo == 0.38b0 opentelemetry-exporter-otlp == 1.17.0 -opentelemetry-exporter-jaeger==1.17.0 +opentelemetry-exporter-jaeger == 1.17.0 fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 -pyopenssl == 23.0.0 +cryptography == 42.0.8 redis == 4.5.4 flask_executor == 1.0.0 Flask-APScheduler == 1.12.4 Flask-Script == 2.0.6 +gunicorn == 22.0.0 +packaging == 24.0 \ No newline at end of file diff --git a/services/TS29222_CAPIF_Access_Control_Policy_API/test-requirements.txt b/services/TS29222_CAPIF_Access_Control_Policy_API/test-requirements.txt index 58f51d6a00272d7515a20e3618f345b73c68afa0..422ece88482f451c08b57e0109939c09bead2c20 100644 --- a/services/TS29222_CAPIF_Access_Control_Policy_API/test-requirements.txt +++ b/services/TS29222_CAPIF_Access_Control_Policy_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=7.1.0 pytest-cov>=2.8.1 pytest-randomly>=1.2.3 -Flask-Testing==0.8.1 +Flask-Testing == 0.8.1 diff --git a/services/TS29222_CAPIF_Auditing_API/Dockerfile b/services/TS29222_CAPIF_Auditing_API/Dockerfile index d7030b67013b0e43402f59ff7374a52c099a6b9d..1d1de3244165065973eec8ff86e502001b178373 100644 --- a/services/TS29222_CAPIF_Auditing_API/Dockerfile +++ b/services/TS29222_CAPIF_Auditing_API/Dockerfile @@ -12,6 +12,4 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] - -CMD ["-m", "logs"] \ No newline at end of file +CMD ["sh", "prepare_audit.sh"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Auditing_API/logs/__main__.py b/services/TS29222_CAPIF_Auditing_API/logs/app.py similarity index 91% rename from services/TS29222_CAPIF_Auditing_API/logs/__main__.py rename to services/TS29222_CAPIF_Auditing_API/logs/app.py index 385f0b589919612de7fc19c5315fea86f73d6e05..f68880cee26c27d442c50b2ec0b68ad07a825169 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/__main__.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/app.py @@ -3,8 +3,8 @@ import connexion import logging from logging.handlers import RotatingFileHandler -from logs import encoder -from .config import Config +import encoder +from config import Config import os from fluent import sender from opentelemetry.instrumentation.flask import FlaskInstrumentor @@ -18,6 +18,10 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor NAME = "Logs-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -79,10 +83,10 @@ def configure_logging(app): loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="service_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -91,7 +95,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) def verbose_formatter(): return logging.Formatter( @@ -109,8 +113,6 @@ app.add_api('openapi.yaml', configure_logging(app.app) config = Config() -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": configure_monitoring(app.app, config.get_config()) - -if __name__ == '__main__': - app.run(port=8080) diff --git a/services/TS29222_CAPIF_Auditing_API/logs/config.py b/services/TS29222_CAPIF_Auditing_API/logs/config.py index d04bd1acd87603f491b09f464d8db1d6cdc52ad7..97ab831fc7a69163163f7182f1f8c61bd9e3ffc4 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/config.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py b/services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py index c330f47dcf64184d10590cbf343373a19c255099..ead9ec5341d13bf3150ad460f174c3c91e714f3c 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/controllers/default_controller.py @@ -1,21 +1,8 @@ -import connexion -import six -import sys - -from logs.models.interface_description import InterfaceDescription # noqa: E501 -from logs.models.invocation_log import InvocationLog # noqa: E501 -from logs.models.operation import Operation # noqa: E501 -from logs.models.problem_details import ProblemDetails # noqa: E501 -from logs.models.protocol import Protocol # noqa: E501 -from logs import util +from ..util import deserialize_datetime from ..core.auditoperations import AuditOperations -import json from flask import Response, request, current_app -from ..encoder import JSONEncoder -from cryptography import x509 -from cryptography.hazmat.backends import default_backend -import pymongo + from ..core.responses import bad_request_error audit_operations = AuditOperations() @@ -65,8 +52,8 @@ def api_invocation_logs_get(aef_id=None, api_invoker_id=None, time_range_start=N cause="Mandatory parameters missing", invalid_params=[ {"param": "aef_id or api_invoker_id", "reason": "missing"}]) - time_range_start = util.deserialize_datetime(time_range_start) - time_range_end = util.deserialize_datetime(time_range_end) + time_range_start = deserialize_datetime(time_range_start) + time_range_end = deserialize_datetime(time_range_end) query_params = {"aef_id": aef_id, "api_invoker_id": api_invoker_id, diff --git a/services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py b/services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py index ac83701ce453c122e8445e41d808b9d658fd3928..f74ec112e2aa73c682463ca6d0502e0ae503e1c3 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/core/auditoperations.py @@ -1,12 +1,10 @@ -import sys from flask import current_app, Flask, Response import json -import sys -from datetime import datetime + from .resources import Resource -from bson import json_util -from ..util import dict_to_camel_case, clean_empty + +from ..util import serialize_clean_camel_case from .responses import bad_request_error, not_found_error, forbidden_error, internal_server_error, make_response from ..models.invocation_log import InvocationLog @@ -57,11 +55,9 @@ class AuditOperations (Resource): if not result['logs']: return not_found_error(detail="Parameters do not match any log entry", cause="No logs found") - - result = dict_to_camel_case(clean_empty(result)) - invocation_log = InvocationLog(result['aefId'], result['apiInvokerId'], result['logs'], - result['supportedFeatures']) - res = make_response(object=invocation_log, status=200) + invocation_log = InvocationLog(result['aef_id'], result['api_invoker_id'], result['logs'], + result['supported_features']) + res = make_response(object=serialize_clean_camel_case(invocation_log), status=200) current_app.logger.debug("Found invocation logs") return res diff --git a/services/TS29222_CAPIF_Auditing_API/logs/core/resources.py b/services/TS29222_CAPIF_Auditing_API/logs/core/resources.py index d55b30c74cf87bf22eec115dfc1bd0e6d413a018..d5a3552d6b3459a77d30df65d0bbda4a86c7fa61 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/core/resources.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/core/resources.py @@ -1,5 +1,5 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from abc import ABC +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Auditing_API/logs/core/responses.py b/services/TS29222_CAPIF_Auditing_API/logs/core/responses.py index 5986c5000910cc9c0f0d579051db9477f5943c17..89689a9e7b3a936e3ea953ed621853ce164d2d70 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/core/responses.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/core/responses.py @@ -1,6 +1,7 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import serialize_clean_camel_case import json mimetype = "application/json" @@ -14,23 +15,27 @@ def make_response(object, status): def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Auditing_API/logs/db/db.py b/services/TS29222_CAPIF_Auditing_API/logs/db/db.py index f3286d22125674dd3cbd9cc5b8dccc2dba73f25c..cf7c0d2ca60425a2e5a842aad94d97c095a47761 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/db/db.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/db/db.py @@ -1,13 +1,13 @@ -import atexit + import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config -from bson.codec_options import CodecOptions +from config import Config import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() diff --git a/services/TS29222_CAPIF_Auditing_API/logs/encoder.py b/services/TS29222_CAPIF_Auditing_API/logs/encoder.py index 55259f5fafc566e72cad147c9f1fada83c2d5130..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/encoder.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from logs.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Auditing_API/logs/util.py b/services/TS29222_CAPIF_Auditing_API/logs/util.py index ff812577975f62d6488f6ebc71bbed8492b7c0d3..d5deea1b7202ee5b603d373471d763f5953e6f2e 100644 --- a/services/TS29222_CAPIF_Auditing_API/logs/util.py +++ b/services/TS29222_CAPIF_Auditing_API/logs/util.py @@ -1,8 +1,16 @@ import datetime import six -import typing -from logs import typing_utils +import typing_utils + + +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res + def clean_empty(d): if isinstance(d, dict): @@ -15,6 +23,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): @@ -22,8 +31,11 @@ def dict_to_camel_case(my_dict): for attr, value in my_dict.items(): - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key = ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr if my_key == "serviceApiCategory": my_key = "serviceAPICategory" diff --git a/services/TS29222_CAPIF_Auditing_API/logs/wsgi.py b/services/TS29222_CAPIF_Auditing_API/logs/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Auditing_API/logs/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Auditing_API/prepare_audit.sh b/services/TS29222_CAPIF_Auditing_API/prepare_audit.sh new file mode 100644 index 0000000000000000000000000000000000000000..e47912ba6dd4a46eccfdd31e89107c76a838e82b --- /dev/null +++ b/services/TS29222_CAPIF_Auditing_API/prepare_audit.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/logs wsgi:app + + diff --git a/services/TS29222_CAPIF_Auditing_API/requirements.txt b/services/TS29222_CAPIF_Auditing_API/requirements.txt index 197399ff21107a2e3f2edc6519445c38b38de335..c2ef0b45391bea561624453a9049889ab0dd1567 100644 --- a/services/TS29222_CAPIF_Auditing_API/requirements.txt +++ b/services/TS29222_CAPIF_Auditing_API/requirements.txt @@ -1,9 +1,9 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 -pymongo == 4.0.1 +pymongo == 4.7.3 elasticsearch == 8.4.3 flask_jwt_extended == 4.4.4 opentelemetry-instrumentation == 0.38b0 @@ -11,10 +11,14 @@ opentelemetry-instrumentation-flask == 0.38b0 opentelemetry-instrumentation-redis == 0.38b0 opentelemetry-instrumentation-pymongo == 0.38b0 opentelemetry-exporter-otlp == 1.17.0 -opentelemetry-exporter-jaeger==1.17.0 +opentelemetry-exporter-jaeger == 1.17.0 fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 -pyopenssl == 23.0.0 +cryptography == 42.0.8 +Werkzeug == 2.2.3 +pyopenssl == 24.1.0 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_Auditing_API/test-requirements.txt b/services/TS29222_CAPIF_Auditing_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_Auditing_API/test-requirements.txt +++ b/services/TS29222_CAPIF_Auditing_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/TS29222_CAPIF_Discover_Service_API/Dockerfile b/services/TS29222_CAPIF_Discover_Service_API/Dockerfile index efa70c90c56f5e1cb49d14f0c551f2ce04a924e0..1478af82410e6e25457620961e115073ab1bcdbc 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/Dockerfile +++ b/services/TS29222_CAPIF_Discover_Service_API/Dockerfile @@ -12,6 +12,4 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] - -CMD ["-m", "service_apis"] \ No newline at end of file +CMD ["sh", "prepare_discover.sh"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Discover_Service_API/prepare_discover.sh b/services/TS29222_CAPIF_Discover_Service_API/prepare_discover.sh new file mode 100644 index 0000000000000000000000000000000000000000..dd9ad7d8b8b4a431a0623ad1da3b3a0c38e684a1 --- /dev/null +++ b/services/TS29222_CAPIF_Discover_Service_API/prepare_discover.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/service_apis wsgi:app + + diff --git a/services/TS29222_CAPIF_Discover_Service_API/requirements.txt b/services/TS29222_CAPIF_Discover_Service_API/requirements.txt index 33a22f4690946e965ae42ce289caff1fb2c707ac..1c57f79a6c75be2813dbca4d36f7c119adabe6a2 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/requirements.txt +++ b/services/TS29222_CAPIF_Discover_Service_API/requirements.txt @@ -1,11 +1,11 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 -pymongo == 4.0.1 +pymongo == 4.7.3 flask_jwt_extended == 4.4.4 -pyopenssl == 23.0.0 +cryptography == 42.0.8 rfc3987 == 1.3.8 redis == 4.5.4 opentelemetry-instrumentation == 0.38b0 @@ -13,10 +13,13 @@ opentelemetry-instrumentation-flask == 0.38b0 opentelemetry-instrumentation-redis == 0.38b0 opentelemetry-instrumentation-pymongo == 0.38b0 opentelemetry-exporter-otlp == 1.17.0 -opentelemetry-exporter-jaeger==1.17.0 +opentelemetry-exporter-jaeger == 1.17.0 fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 -flask_executor == 1.0.0 \ No newline at end of file +flask_executor == 1.0.0 +Werkzeug == 2.2.3 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/__main__.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/app.py similarity index 90% rename from services/TS29222_CAPIF_Discover_Service_API/service_apis/__main__.py rename to services/TS29222_CAPIF_Discover_Service_API/service_apis/app.py index 57326e94c3687e466735d998c4c7da75b64509a8..beec70806ff45a9d3795b952efb09906773a3eb3 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/__main__.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/app.py @@ -2,18 +2,15 @@ import connexion -from service_apis import encoder +import encoder -import pymongo import logging -from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient from logging.handlers import RotatingFileHandler -from .config import Config +from config import Config + import os from fluent import sender -from flask_executor import Executor from opentelemetry.instrumentation.flask import FlaskInstrumentor from opentelemetry import trace from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter @@ -23,10 +20,12 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - - NAME = "Discover-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -90,10 +89,10 @@ def configure_logging(app): loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="discover_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -102,7 +101,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) def verbose_formatter(): return logging.Formatter( @@ -121,11 +120,8 @@ configure_logging(app.app) config = Config() -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": configure_monitoring(app.app, config.get_config()) jwt = JWTManager(app.app) - - -if __name__ == '__main__': - app.run(debug=True, port=8080) diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py index d04bd1acd87603f491b09f464d8db1d6cdc52ad7..97ab831fc7a69163163f7182f1f8c61bd9e3ffc4 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py index aef2022efcf54738587431c9a84a38b43a8dcc09..2c81a78e019e640b140dbde5f6463f7784502ee2 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/controllers/default_controller.py @@ -1,13 +1,6 @@ -import sys -from service_apis.core.discoveredapis import DiscoverApisOperations -import json +from ..core.discoveredapis import DiscoverApisOperations from flask import Response, request, current_app -from service_apis.encoder import JSONEncoder -from service_apis.models.problem_details import ProblemDetails -from cryptography import x509 -from cryptography.hazmat.backends import default_backend -import pymongo discover_apis = DiscoverApisOperations() diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py index 5114c305650370db1ec592f16724e1db7ead0c91..487ceb14b65d6b7cca68b665257e0023dbcf926d 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/discoveredapis.py @@ -1,18 +1,9 @@ -import sys -import pymongo from flask import current_app, Flask, Response -import json -from service_apis.core.responses import internal_server_error, forbidden_error ,make_response, not_found_error -from service_apis.db.db import MongoDatabse -from service_apis.encoder import JSONEncoder -from service_apis.models.problem_details import ProblemDetails -from service_apis.models.service_api_description import ServiceAPIDescription -from service_apis.models.discovered_apis import DiscoveredAPIs -from service_apis.util import dict_to_camel_case, clean_empty -from service_apis.core.resources import Resource -from bson import json_util - +from ..core.responses import internal_server_error, forbidden_error ,make_response, not_found_error +from ..models.discovered_apis import DiscoveredAPIs +from ..util import serialize_clean_camel_case +from ..core.resources import Resource class DiscoverApisOperations(Resource): @@ -43,19 +34,16 @@ class DiscoverApisOperations(Resource): if my_params: my_query = {"$and": my_params} - discoved_apis = services.find(my_query, {"_id":0, "apf_id":0}) + discoved_apis = services.find(my_query, {"_id":0, "api_name":1, "api_id":1, "aef_profiles":1, "description":1, "supported_features":1, "shareable_info":1, "service_api_category":1, "api_supp_feats":1, "pub_api_path":1, "ccf_id":1}) json_docs = [] for discoved_api in discoved_apis: - my_api = dict_to_camel_case(discoved_api) - my_api = clean_empty(my_api) - json_docs.append(my_api) + json_docs.append(discoved_api) if len(json_docs) == 0: return not_found_error(detail="API Invoker " + api_invoker_id + " has no API Published that accomplish filter conditions", cause="No API Published accomplish filter conditions") - apis_discoveres = DiscoveredAPIs(service_api_descriptions=json_docs) - res = make_response(object=apis_discoveres, status=200) - current_app.logger.debug("Discovered APIs by: " + api_invoker_id) + apis_discovered = DiscoveredAPIs(service_api_descriptions=json_docs) + res = make_response(object=serialize_clean_camel_case(apis_discovered), status=200) return res except Exception as e: diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py index 94e29ec07359c93a78d520f24fa91c88971d65c4..efbe3c2d4cf28cec298ef17b394011dcd6aa66cb 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/resources.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py index 4f035781f68629246ade764083b620e3df3c72ae..b54555bf6178395418c0e3d378feddf6fe072f3f 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/core/responses.py @@ -1,32 +1,41 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response -from bson import json_util +from ..util import serialize_clean_camel_case import json mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py index 544545555ff393d3c2b43e825f3595af7df97bfd..fb741fbfa6d23a29ce7df142f68a02b7885c946c 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/db/db.py @@ -1,15 +1,16 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() + class MongoDatabse(): def __init__(self): diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py index c02675977bb308223c728bfbb3a393fb99c5a588..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from service_apis.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py index b3f89d7add5037cf33a17d3c717e8295080d8a8b..cfa4391ef80ec1d4177c26ba64e08795b28c8397 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/util.py @@ -1,9 +1,16 @@ import datetime -import sys import six -import typing -from service_apis import typing_utils +import typing_utils + + +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res + def clean_empty(d): if isinstance(d, dict): @@ -16,6 +23,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): @@ -23,10 +31,16 @@ def dict_to_camel_case(my_dict): for attr, value in my_dict.items(): - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key = ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr + if my_key == "serviceApiCategory": my_key = "serviceAPICategory" + elif my_key == "serviceApiDescriptions": + my_key = "serviceAPIDescriptions" if isinstance(value, list): result[my_key] = list(map( diff --git a/services/TS29222_CAPIF_Discover_Service_API/service_apis/wsgi.py b/services/TS29222_CAPIF_Discover_Service_API/service_apis/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Discover_Service_API/service_apis/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Discover_Service_API/test-requirements.txt b/services/TS29222_CAPIF_Discover_Service_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_Discover_Service_API/test-requirements.txt +++ b/services/TS29222_CAPIF_Discover_Service_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/TS29222_CAPIF_Events_API/Dockerfile b/services/TS29222_CAPIF_Events_API/Dockerfile index ddcf2da935752d7eb90aa1dd59c2eb5811eaf5e0..b8ba685688c633bd6ea2957c85839d6bf8a5555d 100644 --- a/services/TS29222_CAPIF_Events_API/Dockerfile +++ b/services/TS29222_CAPIF_Events_API/Dockerfile @@ -13,6 +13,4 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] - -CMD ["-m", "capif_events"] \ No newline at end of file +CMD ["sh", "prepare_events.sh"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Events_API/capif_events/__main__.py b/services/TS29222_CAPIF_Events_API/capif_events/app.py similarity index 90% rename from services/TS29222_CAPIF_Events_API/capif_events/__main__.py rename to services/TS29222_CAPIF_Events_API/capif_events/app.py index 1e602ef80d3468f980ce3c9b19d455cfeee1f285..d1d3de3c2a39e30afe0b02aea4ae85738f47fd67 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/__main__.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/app.py @@ -4,21 +4,21 @@ import connexion import sys import logging -from capif_events import encoder +import encoder from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, jwt_required, create_access_token from pymongo import MongoClient -from .config import Config -from .core.notifications import Notifications -from .core.consumer_messager import Subscriber + +from core.notifications import Notifications +from core.consumer_messager import Subscriber from multiprocessing import Process from threading import Thread from flask_executor import Executor from flask_apscheduler import APScheduler from logging.handlers import RotatingFileHandler -from .config import Config +from config import Config import os from fluent import sender from flask_executor import Executor @@ -32,9 +32,12 @@ from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - NAME = "Events-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -98,10 +101,10 @@ def configure_logging(app): loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="events_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -110,7 +113,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) @@ -134,7 +137,8 @@ notifications = Notifications() jwt = JWTManager(app.app) configure_logging(app.app) -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": configure_monitoring(app.app, config.get_config()) config = Config() @@ -146,6 +150,3 @@ subscriber = Subscriber() @app.app.before_first_request def create_listener_message(): executor.submit(subscriber.listen) - -if __name__ == '__main__': - app.run(debug=True, port=8080) diff --git a/services/TS29222_CAPIF_Events_API/capif_events/config.py b/services/TS29222_CAPIF_Events_API/capif_events/config.py index 377b14f8c368cebf98409223d089fc31326d1987..bed212ac136607ee7459f333b0f50bf7f3481b6b 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/config.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime if stamp != self.cached: diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/consumer_messager.py b/services/TS29222_CAPIF_Events_API/capif_events/core/consumer_messager.py index 0f9fa6ab3653ba97701c3f0e034809c69d6b5a08..ce6479afb5c3537246cb1b2192709c6e4ed83d8c 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/consumer_messager.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/consumer_messager.py @@ -20,14 +20,18 @@ class Subscriber(): def listen(self): for raw_message in self.p.listen(): + current_app.logger.info(raw_message) if raw_message["type"] == "message" and raw_message["channel"].decode('utf-8') == "events": current_app.logger.info("Event received") - self.notification.send_notifications(raw_message["data"].decode('utf-8')) - + redis_event=json.loads(raw_message["data"].decode('utf-8')) + current_app.logger.info(json.dumps(redis_event, indent=4)) + self.notification.send_notifications(redis_event) elif raw_message["type"] == "message" and raw_message["channel"].decode('utf-8') == "internal-messages": - message, *invoker_id = raw_message["data"].decode('utf-8').split(":") - if message == "invoker-removed" and len(invoker_id)>0: - self.event_ops.delete_all_events(invoker_id[0]) + message, *subscriber_ids = raw_message["data"].decode('utf-8').split(":") + if message == "invoker-removed" and len(subscriber_ids)>0: + self.event_ops.delete_all_events(subscriber_ids) + if message == "provider-removed" and len(subscriber_ids)>0: + self.event_ops.delete_all_events(subscriber_ids) diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py b/services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py index 1ece644c124fcf17b47f8aaea59ab4c67c1b0e86..14cddb0c1501edcf9f17426b59789a3fd23a5196 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/events_apis.py @@ -12,9 +12,10 @@ from .resources import Resource from bson import json_util from .responses import internal_server_error, not_found_error, make_response, bad_request_error from ..db.db import MongoDatabse -from ..util import dict_to_camel_case +from ..util import serialize_clean_camel_case from .auth_manager import AuthManager + class EventSubscriptionsOperations(Resource): def __check_subscriber_id(self, subscriber_id): @@ -73,7 +74,7 @@ class EventSubscriptionsOperations(Resource): self.auth_manager.add_auth_event(subscription_id, subscriber_id) - res = make_response(object=event_subscription, status=201) + res = make_response(object=serialize_clean_camel_case(event_subscription), status=201) res.headers['Location'] = "http://localhost:8080/capif-events/v1/" + \ str(subscriber_id) + "/subscriptions/" + str(subscription_id) diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/internal_event_ops.py b/services/TS29222_CAPIF_Events_API/capif_events/core/internal_event_ops.py index 3f4fc6a7274e9eddbfa51cf630f779d31bf18bfb..e49089a3756b4b3946bafa93b4138721e8a1be7b 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/internal_event_ops.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/internal_event_ops.py @@ -8,22 +8,23 @@ class InternalEventOperations(Resource): Resource.__init__(self) self.auth_manager = AuthManager() - def delete_all_events(self, subscriber_id): + def delete_all_events(self, subscriber_ids): - mycol = self.db.get_col_by_name(self.db.event_collection) - my_query = {'subscriber_id': subscriber_id} - mycol.delete_many(my_query) + for subscriber_id in subscriber_ids: + mycol = self.db.get_col_by_name(self.db.event_collection) + my_query = {'subscriber_id': subscriber_id} + mycol.delete_many(my_query) - current_app.logger.info(f"Removed events for this subscriber: {subscriber_id}") + current_app.logger.info(f"Removed events for this subscriber: {subscriber_id}") #We dont need remove all auth events, becase when invoker is removed, remove auth entry #self.auth_manager.remove_auth_all_event(subscriber_id) def get_event_subscriptions(self, event): + current_app.logger.info("get subscription from db") try: mycol = self.db.get_col_by_name(self.db.event_collection) - - query= {'events':event} + query={'events':{'$in':[event]}} subscriptions = mycol.find(query) if subscriptions is None: @@ -39,21 +40,3 @@ class InternalEventOperations(Resource): except Exception as e: current_app.logger.error("An exception occurred ::" + str(e)) return False - - # def get_acls(self, service_id): - # try: - # mycol = self.db.get_col_by_name(self.db.acls_col) - - # query= {'api_id': service_id} - # acls = mycol.find(query) - - # if acls is None: - # current_app.logger.error("Not found event subscriptions") - - # else: - - # return acls - - # except Exception as e: - # current_app.logger.error("An exception occurred ::" + str(e)) - # return False \ No newline at end of file diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py b/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py index a02f0abee8a4fa60a8405ea5175e20f3a33236c8..e005e7a8f53c25b18d9ceb0232f41a4a6934a6d7 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/notifications.py @@ -1,37 +1,42 @@ #import concurrent import requests from .internal_event_ops import InternalEventOperations -from ..models.event_notification import EventNotification -from ..models.access_control_policy_list_ext import AccessControlPolicyListExt -from ..models.capif_event_detail import CAPIFEventDetail -from ..encoder import JSONEncoder +from models.event_notification import EventNotification +from models.access_control_policy_list_ext import AccessControlPolicyListExt +from models.capif_event_detail import CAPIFEventDetail +from encoder import JSONEncoder import sys import json from flask import current_app +import asyncio +import aiohttp +from util import dict_to_camel_case, clean_empty, serialize_clean_camel_case class Notifications(): def __init__(self): self.events_ops = InternalEventOperations() - def send_notifications(self, event): - current_app.logger.info("Received event, sending notifications") - subscriptions = self.events_ops.get_event_subscriptions(event) - # message, *ids = event.split(":") - + def send_notifications(self, redis_event): try: + if redis_event.get('event', None) == None: + raise("Event value is not present on received event from REDIS") + + current_app.logger.info("Received event " + redis_event.get('event') + ", sending notifications") + subscriptions = self.events_ops.get_event_subscriptions(redis_event.get('event')) + current_app.logger.info(subscriptions) + for sub in subscriptions: url = sub["notification_destination"] - data = EventNotification(sub["subscription_id"], events=event) - # details = CAPIFEventDetail() - # if message == "ACCESS_CONTROL_POLICY_UPDATE": - # current_app.logger.info("event: ACCESS_CONTROL_POLICY_UPDATE") - # acls = self.events_ops.get_acls(ids[0]) - # details.acc_ctrl_pol_list = AccessControlPolicyListExt(api_id=acls['service_id'], api_invoker_policies=acls['apiInvokerPolicies']) + current_app.logger.debug(url) + event_detail=None + if redis_event.get('key', None) != None and redis_event.get('information', None) != None: + event_detail={redis_event.get('key'):redis_event.get('information')} + current_app.logger.debug(event_detail) + data = EventNotification(sub["subscription_id"], events=redis_event.get('event'), event_detail=event_detail) + current_app.logger.debug(json.dumps(data.to_dict(),cls=JSONEncoder)) - # data.event_detail=details - self.request_post(url, data) - #current_app.logger.info("notification sended") + asyncio.run(self.send(url, serialize_clean_camel_case(data))) except Exception as e: current_app.logger.error("An exception occurred ::" + str(e)) @@ -40,4 +45,20 @@ class Notifications(): def request_post(self, url, data): headers = {'content-type': 'application/json'} return requests.post(url, json={'text': str(data.to_str())}, headers=headers) - + + async def send_request(self, url, data): + async with aiohttp.ClientSession() as session: + timeout = aiohttp.ClientTimeout(total=10) # Establecer timeout a 10 segundos + headers = {'content-type': 'application/json'} + async with session.post(url, json=data, timeout=timeout, headers=headers) as response: + return await response.text() + + async def send(self, url, data): + try: + response = await self.send_request(url, data) + current_app.logger.debug(response) + except asyncio.TimeoutError: + current_app.logger.error("Timeout: Request timeout") + except Exception as e: + current_app.logger.error("An exception occurred sending notification::" + str(e)) + return False diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/resources.py b/services/TS29222_CAPIF_Events_API/capif_events/core/resources.py index 94e29ec07359c93a78d520f24fa91c88971d65c4..efbe3c2d4cf28cec298ef17b394011dcd6aa66cb 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/resources.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/resources.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/responses.py b/services/TS29222_CAPIF_Events_API/capif_events/core/responses.py index 962c4b6dd6ae07bce79dc8e810f10a507d526663..89689a9e7b3a936e3ea953ed621853ce164d2d70 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/responses.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/responses.py @@ -1,31 +1,41 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import serialize_clean_camel_case import json mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py b/services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py index 18d54a2ec108ecd87483cf0c314e52c8eb6fad6c..e7ddee1c50f58ef418483ab58056058f413bb62c 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/core/validate_user.py @@ -4,6 +4,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import serialize_clean_camel_case + class ControlAccess(Resource): @@ -18,6 +20,8 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature or "event_subscriptions" not in cert_entry["resources"] or event_id not in cert_entry["resources"]["event_subscriptions"]: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = serialize_clean_camel_case(prob) + return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_Events_API/capif_events/db/db.py b/services/TS29222_CAPIF_Events_API/capif_events/db/db.py index 2f4d1190297508fd9b49946fc193ba92b6e2d99e..68391d8866eaa6f88cbbbb5ab90fe07e792b17d6 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/db/db.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/db/db.py @@ -2,12 +2,13 @@ import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() diff --git a/services/TS29222_CAPIF_Events_API/capif_events/encoder.py b/services/TS29222_CAPIF_Events_API/capif_events/encoder.py index f6b018f22f8e92eb3c919f4cb4546d61a550fcd0..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/encoder.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from capif_events.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Events_API/capif_events/models/routing_rule.py b/services/TS29222_CAPIF_Events_API/capif_events/models/routing_rule.py index 7ff1d4e3a3b7bd28cc89b4db118d9d602ef00065..a4e4d0719a767c8424312da786c0a14163c66276 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/models/routing_rule.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/models/routing_rule.py @@ -11,10 +11,6 @@ from capif_events.models.ipv4_address_range import Ipv4AddressRange from capif_events.models.ipv6_address_range import Ipv6AddressRange from capif_events import util -from capif_events.models.aef_profile import AefProfile # noqa: E501 -from capif_events.models.ipv4_address_range import Ipv4AddressRange # noqa: E501 -from capif_events.models.ipv6_address_range import Ipv6AddressRange # noqa: E501 - class RoutingRule(Model): """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/services/TS29222_CAPIF_Events_API/capif_events/util.py b/services/TS29222_CAPIF_Events_API/capif_events/util.py index 396c6a5b258c051cf1c86b93d2bf79e998463ace..28a9e46b722f32c666f92850d09bf12d74b4d743 100644 --- a/services/TS29222_CAPIF_Events_API/capif_events/util.py +++ b/services/TS29222_CAPIF_Events_API/capif_events/util.py @@ -1,37 +1,50 @@ import datetime import six -import typing -from capif_events import typing_utils +import typing_utils -def dict_to_camel_case(my_dict): +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + return res - result = {} - for attr, value in my_dict.items(): +def clean_empty(d): + if isinstance(d, dict): + return { + k: v + for k, v in ((k, clean_empty(v)) for k, v in d.items()) + if v is not None or v == 0 + } + if isinstance(d, list): + return [v for v in map(clean_empty, d) if v is not None or v == 0] + return d - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) +def dict_to_camel_case(my_dict): + result = {} + for attr, value in my_dict.items(): + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key= ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr if isinstance(value, list): result[my_key] = list(map( lambda x: dict_to_camel_case(x) if isinstance(x, dict) else x, value )) - elif hasattr(value, "to_dict"): result[my_key] = dict_to_camel_case(value) - elif isinstance(value, dict): value = dict_to_camel_case(value) result[my_key] = value else: result[my_key] = value - return result - def _deserialize(data, klass): """Deserializes dict, list, str into an object. diff --git a/services/TS29222_CAPIF_Events_API/capif_events/wsgi.py b/services/TS29222_CAPIF_Events_API/capif_events/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Events_API/capif_events/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Events_API/prepare_events.sh b/services/TS29222_CAPIF_Events_API/prepare_events.sh new file mode 100644 index 0000000000000000000000000000000000000000..62bd7ee283c58a5e48b3cbc27c80bded443f1e14 --- /dev/null +++ b/services/TS29222_CAPIF_Events_API/prepare_events.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/capif_events wsgi:app diff --git a/services/TS29222_CAPIF_Events_API/requirements.txt b/services/TS29222_CAPIF_Events_API/requirements.txt index bbef950cda414a17f3ebb70ca8689ae35c121ca0..22b0d352078a44b38cf8d82c4d4cbfcc083ae5c0 100644 --- a/services/TS29222_CAPIF_Events_API/requirements.txt +++ b/services/TS29222_CAPIF_Events_API/requirements.txt @@ -1,23 +1,28 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 -pymongo == 4.0.1 +pymongo == 4.7.3 opentelemetry-instrumentation == 0.38b0 opentelemetry-instrumentation-flask == 0.38b0 opentelemetry-instrumentation-redis == 0.38b0 opentelemetry-instrumentation-pymongo == 0.38b0 opentelemetry-exporter-otlp == 1.17.0 -opentelemetry-exporter-jaeger==1.17.0 +opentelemetry-exporter-jaeger == 1.17.0 fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 flask_jwt_extended -pyopenssl -rfc3987 -redis -flask_executor -Flask-APScheduler +cryptography == 42.0.8 +rfc3987 == 1.3.8 +redis == 4.5.4 +Flask-APScheduler == 1.12.4 +aiohttp == 3.9.5 +async-timeout == 4.0.3 +Werkzeug == 2.2.3 +pyopenssl == 24.1.0 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_Events_API/test-requirements.txt b/services/TS29222_CAPIF_Events_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_Events_API/test-requirements.txt +++ b/services/TS29222_CAPIF_Events_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile b/services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile index 7339cecd74384864a4d4414b579e0dbc012e6b1c..f7cd99b2c94367d6bd968f4ea597854e478ac9ec 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/Dockerfile @@ -12,6 +12,4 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] - -CMD ["-m", "api_invocation_logs"] \ No newline at end of file +CMD ["sh", "prepare_logging.sh"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/__main__.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/app.py similarity index 91% rename from services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/__main__.py rename to services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/app.py index f5323c9ef96c6ffeb29dcdb8e932859a7d1f64d0..bf76d0fcdfd8abff158fb8473a82ca04bb9a9455 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/__main__.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/app.py @@ -3,8 +3,8 @@ import connexion import logging from logging.handlers import RotatingFileHandler -from api_invocation_logs import encoder -from .config import Config +import encoder +from config import Config import os from fluent import sender from opentelemetry.instrumentation.flask import FlaskInstrumentor @@ -16,10 +16,12 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor - - NAME = "Logging-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -81,10 +83,10 @@ def configure_logging(app): loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="logging_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -94,7 +96,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) def verbose_formatter(): @@ -113,8 +115,6 @@ configure_logging(app.app) config = Config() -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": configure_monitoring(app.app, config.get_config()) - -if __name__ == '__main__': - app.run(port=8080) diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py index d04bd1acd87603f491b09f464d8db1d6cdc52ad7..97ab831fc7a69163163f7182f1f8c61bd9e3ffc4 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py index eb0cd986a51c521efd0f201c10cb529f65e45d51..7ce9972710b904bdd045e6ca7525f0e46785fa06 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/controllers/default_controller.py @@ -1,13 +1,11 @@ import connexion -from api_invocation_logs.models.invocation_log import InvocationLog # noqa: E501 +from ..models.invocation_log import InvocationLog # noqa: E501 from ..core.invocationlogs import LoggingInvocationOperations -import json from flask import Response, request, current_app -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails + from ..core.validate_user import ControlAccess from cryptography import x509 from cryptography.hazmat.backends import default_backend diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py index dde0c649d29cbd53c51ba20119422551f415e031..bae9c5a4f26e04d589818041aba15aca27e491bf 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/invocationlogs.py @@ -1,18 +1,18 @@ -import sys + import os -import pymongo + import secrets from flask import current_app, Flask, Response -import json -from ..db.db import MongoDatabse -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails from pymongo import ReturnDocument -from ..util import dict_to_camel_case, clean_empty +from ..util import serialize_clean_camel_case +from ..encoder import JSONEncoder from .resources import Resource -from .responses import bad_request_error, internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response -from ..models.invocation_log import InvocationLog + +from .responses import internal_server_error, not_found_error, unauthorized_error, make_response +from .redis_event import RedisEvent +import json + class LoggingInvocationOperations(Resource): @@ -61,7 +61,7 @@ class LoggingInvocationOperations(Resource): return None def add_invocationlog(self, aef_id, invocationlog): - + mycol = self.db.get_col_by_name(self.db.invocation_logs) try: @@ -79,11 +79,29 @@ class LoggingInvocationOperations(Resource): return result current_app.logger.debug("Check service apis") + event=None + invocation_log_base=json.loads(json.dumps(invocationlog.to_dict(), cls=JSONEncoder)) + for log in invocationlog.logs: result = self.__check_service_apis(log.api_id, log.api_name) + current_app.logger.debug("Inside for loop.") if result is not None: return result + + if log.result: + current_app.logger.debug(log) + if int(log.result) >= 200 and int(log.result) < 300: + event="SERVICE_API_INVOCATION_SUCCESS" + else: + event="SERVICE_API_INVOCATION_FAILURE" + + current_app.logger.info(event) + invocation_log_base['logs']=[log.to_dict()] + invocationLogs=[invocation_log_base] + RedisEvent(event,"invocation_logs",invocationLogs).send_event() + + current_app.logger.debug("After log check") current_app.logger.debug("Check existing logs") my_query = {'aef_id': aef_id, 'api_invoker_id': invocationlog.api_invoker_id} @@ -104,7 +122,7 @@ class LoggingInvocationOperations(Resource): existing_invocationlog['logs'].append(updated_invocation_log) mycol.find_one_and_update(my_query, {"$set": existing_invocationlog}, projection={'_id': 0, 'log_id': 0}, return_document=ReturnDocument.AFTER, upsert=False) - res = make_response(object=invocationlog, status=201) + res = make_response(object=serialize_clean_camel_case(invocationlog), status=201) current_app.logger.debug("Invocation Logs response ready") apis_added = {log.api_id:log.api_name for log in invocationlog.logs} diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/publisher.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/publisher.py new file mode 100644 index 0000000000000000000000000000000000000000..a15c0d90e8d00233317a6c1ab748b8ff150be80e --- /dev/null +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/publisher.py @@ -0,0 +1,11 @@ +import redis +import sys +from flask import current_app + +class Publisher(): + + def __init__(self): + self.r = redis.Redis(host='redis', port=6379, db=0) + + def publish_message(self, channel, message): + self.r.publish(channel, message) diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/redis_event.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/redis_event.py new file mode 100644 index 0000000000000000000000000000000000000000..aadbdbb6b3116cf288648de41effdb12b9ca9143 --- /dev/null +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/redis_event.py @@ -0,0 +1,41 @@ +from ..encoder import JSONEncoder +from .publisher import Publisher +import json + +publisher_ops = Publisher() + + +class RedisEvent(): + def __init__(self, event, event_detail_key=None, information=None) -> None: + self.EVENTS_ENUM = [ + 'SERVICE_API_AVAILABLE', + 'SERVICE_API_UNAVAILABLE', + 'SERVICE_API_UPDATE', + 'API_INVOKER_ONBOARDED', + 'API_INVOKER_OFFBOARDED', + 'SERVICE_API_INVOCATION_SUCCESS', + 'SERVICE_API_INVOCATION_FAILURE', + 'ACCESS_CONTROL_POLICY_UPDATE', + 'ACCESS_CONTROL_POLICY_UNAVAILABLE', + 'API_INVOKER_AUTHORIZATION_REVOKED', + 'API_INVOKER_UPDATED', + 'API_TOPOLOGY_HIDING_CREATED', + 'API_TOPOLOGY_HIDING_REVOKED'] + if event not in self.EVENTS_ENUM: + raise Exception( + "Event (" + event + ") is not on event enum (" + ','.join(self.EVENTS_ENUM) + ")") + self.redis_event = { + "event": event + } + if event_detail_key != None and information != None: + self.redis_event['key'] = event_detail_key + self.redis_event['information'] = information + + def to_string(self): + return json.dumps(self.redis_event, cls=JSONEncoder) + + def send_event(self): + publisher_ops.publish_message("events", self.to_string()) + + def __call__(self): + return self.redis_event diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py index d55b30c74cf87bf22eec115dfc1bd0e6d413a018..d5a3552d6b3459a77d30df65d0bbda4a86c7fa61 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/resources.py @@ -1,5 +1,5 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from abc import ABC +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py index 3a136b1459f0cad9410148983fbdfbbe294a03d0..5c9803e85b6b639693ae33284b209ecbff38cc3a 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/responses.py @@ -1,8 +1,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import serialize_clean_camel_case import json -from bson import json_util mimetype = "application/json" @@ -15,29 +15,34 @@ def make_response(object, status): def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) def unauthorized_error(detail, cause): prob = ProblemDetails(title="Unauthorized", status=401, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py index 2a8943738218ab542605b4a3e5053ddd7dbefaf9..d9f7d5dc16def3abb9f92c5e6a0905657e0ccf54 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/core/validate_user.py @@ -4,6 +4,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import serialize_clean_camel_case + class ControlAccess(Resource): @@ -18,6 +20,7 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py index 96a39f3aa05be3e6945173dd832fc4777a4e01dd..87cc3a65f5101267a9c81ca548812a533b6bca23 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/db/db.py @@ -1,13 +1,13 @@ -import atexit + import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config -from bson.codec_options import CodecOptions +from config import Config import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py index efa1154be1714b16879b8fa9ee6d09169c86076e..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from api_invocation_logs.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py index af555673357bf337cf79d74e3dae42b9c84dafb9..baaea564448deb45d356e5149aac29a9459e16f5 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/util.py @@ -1,8 +1,16 @@ import datetime import six -import typing -from api_invocation_logs import typing_utils +import typing_utils + + +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res + def clean_empty(d): if isinstance(d, dict): @@ -15,6 +23,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): @@ -22,8 +31,12 @@ def dict_to_camel_case(my_dict): for attr, value in my_dict.items(): - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key = ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr + if my_key == "serviceApiCategory": my_key = "serviceAPICategory" diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/wsgi.py b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/api_invocation_logs/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/prepare_logging.sh b/services/TS29222_CAPIF_Logging_API_Invocation_API/prepare_logging.sh new file mode 100644 index 0000000000000000000000000000000000000000..4cd01a6ccf928e437c96462700e785422275913f --- /dev/null +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/prepare_logging.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/api_invocation_logs wsgi:app diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt b/services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt index 197399ff21107a2e3f2edc6519445c38b38de335..e92ae36d8fb1b0a19b8530808df64a440334547c 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/requirements.txt @@ -1,20 +1,25 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 -pymongo == 4.0.1 +pymongo == 4.7.3 elasticsearch == 8.4.3 flask_jwt_extended == 4.4.4 +redis == 4.5.4 opentelemetry-instrumentation == 0.38b0 opentelemetry-instrumentation-flask == 0.38b0 opentelemetry-instrumentation-redis == 0.38b0 opentelemetry-instrumentation-pymongo == 0.38b0 opentelemetry-exporter-otlp == 1.17.0 -opentelemetry-exporter-jaeger==1.17.0 +opentelemetry-exporter-jaeger == 1.17.0 fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 -pyopenssl == 23.0.0 +cryptography == 42.0.8 +Werkzeug == 2.2.3 +pyopenssl == 24.1.0 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_Logging_API_Invocation_API/test-requirements.txt b/services/TS29222_CAPIF_Logging_API_Invocation_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_Logging_API_Invocation_API/test-requirements.txt +++ b/services/TS29222_CAPIF_Logging_API_Invocation_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/TS29222_CAPIF_Publish_Service_API/Dockerfile b/services/TS29222_CAPIF_Publish_Service_API/Dockerfile index b2e6167309094b21ac6526fb45d679861032d65f..eca440204cf38f6f3ff1b27757be21deaaac7d09 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/Dockerfile +++ b/services/TS29222_CAPIF_Publish_Service_API/Dockerfile @@ -12,6 +12,4 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] - -CMD ["-m", "published_apis"] \ No newline at end of file +CMD ["sh", "prepare_publish.sh"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Publish_Service_API/prepare_publish.sh b/services/TS29222_CAPIF_Publish_Service_API/prepare_publish.sh new file mode 100644 index 0000000000000000000000000000000000000000..d0eed0b94e7189472bd6c659e4850b79adbf26f6 --- /dev/null +++ b/services/TS29222_CAPIF_Publish_Service_API/prepare_publish.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/published_apis wsgi:app diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/__main__.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/app.py similarity index 90% rename from services/TS29222_CAPIF_Publish_Service_API/published_apis/__main__.py rename to services/TS29222_CAPIF_Publish_Service_API/published_apis/app.py index dfba9ef99bcbb5c96e9260d7d1a1f22ace86e6b1..dedd2b563f2f83cf36c9a16d542053e7828201bf 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/__main__.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/app.py @@ -3,15 +3,14 @@ import connexion import logging -from published_apis import encoder +# from published_apis import encoder +import encoder -from flask import Flask, jsonify, request from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient -from .config import Config +from config import Config from logging.handlers import RotatingFileHandler -from .core.consumer_messager import Subscriber -from flask_executor import Executor +from core.consumer_messager import Subscriber + import os from fluent import sender from flask_executor import Executor @@ -24,10 +23,12 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - - NAME = "Publish-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -86,16 +87,15 @@ def configure_monitoring(app, config): l.addHandler(FluentBitHandler()) - def configure_logging(app): del app.logger.handlers[:] loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="publish_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -105,7 +105,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) def verbose_formatter(): @@ -114,6 +114,7 @@ def verbose_formatter(): datefmt='%d/%m/%Y %H:%M:%S' ) + app = connexion.App(__name__, specification_dir='./openapi/') app.app.json_encoder = encoder.JSONEncoder app.add_api('openapi.yaml', @@ -127,16 +128,14 @@ config = Config() jwt = JWTManager(app.app) configure_logging(app.app) -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": configure_monitoring(app.app, config.get_config()) executor = Executor(app.app) subscriber = Subscriber() + @app.app.before_first_request def up_listener(): executor.submit(subscriber.listen) - - -if __name__ == '__main__': - app.run(debug=True, port=8080) diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py index 11e1c4f3626d7440c6cd999ed118afb3c93caa2e..01f9914cc141eb3c49fd73506e9b1c5470edd781 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py index 8fc2b6269ac2c0363ca96b3d3e76cdac7edeba01..62e506a6be747d94efa513917913f03a75f20ca3 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/controllers/default_controller.py @@ -1,27 +1,20 @@ import connexion -from published_apis.models.service_api_description import ServiceAPIDescription # noqa: E501 -from ..core import serviceapidescriptions +from ..models.service_api_description import ServiceAPIDescription # noqa: E501 from ..core.serviceapidescriptions import PublishServiceOperations -from ..core.publisher import Publisher -import json from flask import Response, request, current_app -from flask_jwt_extended import jwt_required, get_jwt_identity -from flask import current_app -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails + from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps -import pymongo service_operations = PublishServiceOperations() -publisher_ops = Publisher() valid_user = ControlAccess() + def cert_validation(): def _cert_validation(f): @wraps(f) @@ -31,13 +24,16 @@ def cert_validation(): cert_tmp = request.headers['X-Ssl-Client-Cert'] cert_raw = cert_tmp.replace('\t', '') - cert = x509.load_pem_x509_certificate(str.encode(cert_raw), default_backend()) + cert = x509.load_pem_x509_certificate( + str.encode(cert_raw), default_backend()) - cn = cert.subject.get_attributes_for_oid(x509.OID_COMMON_NAME)[0].value.strip() + cn = cert.subject.get_attributes_for_oid( + x509.OID_COMMON_NAME)[0].value.strip() if cn != "superadmin": cert_signature = cert.signature.hex() - result = valid_user.validate_user_cert(args["apfId"], args["serviceApiId"], cert_signature) + result = valid_user.validate_user_cert( + args["apfId"], args["serviceApiId"], cert_signature) if result is not None: return result @@ -47,6 +43,7 @@ def cert_validation(): return __cert_validation return _cert_validation + def apf_id_service_apis_get(apf_id): # noqa: E501 """apf_id_service_apis_get @@ -82,12 +79,9 @@ def apf_id_service_apis_post(apf_id, body): # noqa: E501 res = service_operations.add_serviceapidescription(apf_id, body) - if res.status_code == 201: - current_app.logger.info("Service published") - publisher_ops.publish_message("events", "SERVICE_API_AVAILABLE") - return res + @cert_validation() def apf_id_service_apis_service_api_id_delete(service_api_id, apf_id): # noqa: E501 """apf_id_service_apis_service_api_id_delete @@ -103,15 +97,12 @@ def apf_id_service_apis_service_api_id_delete(service_api_id, apf_id): # noqa: """ current_app.logger.info("Removing service published") - res = service_operations.delete_serviceapidescription(service_api_id, apf_id) - - if res.status_code == 204: - current_app.logger.info("Removed service published") - publisher_ops.publish_message("events", "SERVICE_API_UNAVAILABLE") - publisher_ops.publish_message("internal-messages", f"service-removed:{service_api_id}") + res = service_operations.delete_serviceapidescription( + service_api_id, apf_id) return res + @cert_validation() def apf_id_service_apis_service_api_id_get(service_api_id, apf_id): # noqa: E501 """apf_id_service_apis_service_api_id_get @@ -131,6 +122,7 @@ def apf_id_service_apis_service_api_id_get(service_api_id, apf_id): # noqa: E50 return res + @cert_validation() def apf_id_service_apis_service_api_id_put(service_api_id, apf_id, body): # noqa: E501 """apf_id_service_apis_service_api_id_put @@ -147,14 +139,13 @@ def apf_id_service_apis_service_api_id_put(service_api_id, apf_id, body): # noq :rtype: ServiceAPIDescription """ - current_app.logger.info("Updating service api id with id: " + service_api_id) + current_app.logger.info( + "Updating service api id with id: " + service_api_id) if connexion.request.is_json: body = ServiceAPIDescription.from_dict(connexion.request.get_json()) # noqa: E501 - response = service_operations.update_serviceapidescription(service_api_id, apf_id, body) - - if response.status_code == 200: - publisher_ops.publish_message("events", "SERVICE_API_UPDATE") + response = service_operations.update_serviceapidescription( + service_api_id, apf_id, body) return response diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py index 6e329a486848233a1c0600e5625d095e32a54661..cb2f0b937a55d762a7f02bcdbc09d44a1865a5b9 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/auth_manager.py @@ -1,7 +1,5 @@ from flask import current_app -from cryptography import x509 -from cryptography.hazmat.backends import default_backend from .resources import Resource diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py index 93d35e481efb1c4550b4590934c70edd24b31795..f781ead9e3beb684bf6face38ef9c0e4fd5cc5bc 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/consumer_messager.py @@ -1,10 +1,5 @@ # subscriber.py import redis -import time -import sys -import json -import asyncio -from threading import Thread from .internal_service_ops import InternalServiceOps from flask import current_app @@ -21,7 +16,7 @@ class Subscriber(): for raw_message in self.p.listen(): if raw_message["type"] == "message" and raw_message["channel"].decode('utf-8') == "internal-messages": message, *ids = raw_message["data"].decode('utf-8').split(":") - if message == "provider-removed" and len(ids)==2: + if message == "provider-removed" and len(ids) > 0: self.security_ops.delete_intern_service(ids[1]) diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py index f7b0c3c4b25f9abbe24d2dc734a72a93ffe0af01..34fcdf453873b4b59a894d9f6b96b7ce1a217c2e 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/publisher.py @@ -1,5 +1,4 @@ import redis -import sys class Publisher(): diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/redis_event.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/redis_event.py new file mode 100644 index 0000000000000000000000000000000000000000..aadbdbb6b3116cf288648de41effdb12b9ca9143 --- /dev/null +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/redis_event.py @@ -0,0 +1,41 @@ +from ..encoder import JSONEncoder +from .publisher import Publisher +import json + +publisher_ops = Publisher() + + +class RedisEvent(): + def __init__(self, event, event_detail_key=None, information=None) -> None: + self.EVENTS_ENUM = [ + 'SERVICE_API_AVAILABLE', + 'SERVICE_API_UNAVAILABLE', + 'SERVICE_API_UPDATE', + 'API_INVOKER_ONBOARDED', + 'API_INVOKER_OFFBOARDED', + 'SERVICE_API_INVOCATION_SUCCESS', + 'SERVICE_API_INVOCATION_FAILURE', + 'ACCESS_CONTROL_POLICY_UPDATE', + 'ACCESS_CONTROL_POLICY_UNAVAILABLE', + 'API_INVOKER_AUTHORIZATION_REVOKED', + 'API_INVOKER_UPDATED', + 'API_TOPOLOGY_HIDING_CREATED', + 'API_TOPOLOGY_HIDING_REVOKED'] + if event not in self.EVENTS_ENUM: + raise Exception( + "Event (" + event + ") is not on event enum (" + ','.join(self.EVENTS_ENUM) + ")") + self.redis_event = { + "event": event + } + if event_detail_key != None and information != None: + self.redis_event['key'] = event_detail_key + self.redis_event['information'] = information + + def to_string(self): + return json.dumps(self.redis_event, cls=JSONEncoder) + + def send_event(self): + publisher_ops.publish_message("events", self.to_string()) + + def __call__(self): + return self.redis_event diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py index 94e29ec07359c93a78d520f24fa91c88971d65c4..efbe3c2d4cf28cec298ef17b394011dcd6aa66cb 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/resources.py @@ -1,5 +1,5 @@ from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from db.db import MongoDatabse class Resource(ABC): diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py index c1809eda5a7669e869fb2e83fa7ebf2628f4d3f2..3d10ff541afe36f7c3bc527a8a475805e532cdcc 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/responses.py @@ -1,37 +1,49 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response +from ..util import serialize_clean_camel_case import json -from bson import json_util + mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) + def unauthorized_error(detail, cause): prob = ProblemDetails(title="Unauthorized", status=401, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py index e2892e69573b8b42fff6f71aaf618162a4da6773..f32b7b2c1e652e08bdc98734bc9003d04e170c63 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/serviceapidescriptions.py @@ -1,40 +1,39 @@ -import sys - -import pymongo from pymongo import ReturnDocument import secrets from flask import current_app, Flask, Response -import json -from pymongo import response -from ..db.db import MongoDatabse -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails from .resources import Resource -from ..util import dict_to_camel_case, clean_empty -from .responses import bad_request_error, internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response -from bson import json_util +from datetime import datetime +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case +from .responses import internal_server_error, forbidden_error, not_found_error, unauthorized_error, make_response from .auth_manager import AuthManager +from .redis_event import RedisEvent +from .publisher import Publisher + +publisher_ops = Publisher() service_api_not_found_message = "Service API not found" + class PublishServiceOperations(Resource): def __check_apf(self, apf_id): providers_col = self.db.get_col_by_name(self.db.capif_provider_col) current_app.logger.debug("Checking apf id") - provider = providers_col.find_one({"api_prov_funcs.api_prov_func_id": apf_id}) + provider = providers_col.find_one( + {"api_prov_funcs.api_prov_func_id": apf_id}) if provider is None: current_app.logger.error("Publisher not exist") - return unauthorized_error(detail = "Publisher not existing", cause = "Publisher id not found") + return unauthorized_error(detail="Publisher not existing", cause="Publisher id not found") - list_apf_ids = [func["api_prov_func_id"] for func in provider["api_prov_funcs"] if func["api_prov_func_role"] == "APF"] + list_apf_ids = [func["api_prov_func_id"] + for func in provider["api_prov_funcs"] if func["api_prov_func_role"] == "APF"] if apf_id not in list_apf_ids: current_app.logger.debug("This id not belongs to APF") - return unauthorized_error(detail ="You are not a publisher", cause ="This API is only available for publishers") + return unauthorized_error(detail="You are not a publisher", cause="This API is only available for publishers") return None @@ -55,7 +54,9 @@ class PublishServiceOperations(Resource): if result != None: return result - service = mycol.find({"apf_id": apf_id}, {"apf_id":0, "_id":0}) + service = mycol.find({"apf_id": apf_id}, {"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, + "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}) + current_app.logger.debug(service) if service is None: current_app.logger.error("Not found services for this apf id") return not_found_error(detail="Not exist published services for this apf_id", cause="Not exist service with this apf_id") @@ -67,6 +68,7 @@ class PublishServiceOperations(Resource): json_docs.append(my_service_api) current_app.logger.debug("Obtained services apis") + current_app.logger.debug(json_docs) res = make_response(object=json_docs, status=200) return res @@ -88,24 +90,34 @@ class PublishServiceOperations(Resource): if result != None: return result - service = mycol.find_one({"api_name": serviceapidescription.api_name}) + service = mycol.find_one( + {"api_name": serviceapidescription.api_name}) if service is not None: - current_app.logger.error("Service already registered with same api name") + current_app.logger.error( + "Service already registered with same api name") return forbidden_error(detail="Already registered service with same api name", cause="Found service with same api name") api_id = secrets.token_hex(15) serviceapidescription.api_id = api_id rec = dict() rec['apf_id'] = apf_id + rec['onboarding_date'] = datetime.now() rec.update(serviceapidescription.to_dict()) + mycol.insert_one(rec) self.auth_manager.add_auth_service(api_id, apf_id) current_app.logger.debug("Service inserted in database") - res = make_response(object=serviceapidescription, status=201) - res.headers['Location'] = "http://localhost:8080/published-apis/v1/" + str(apf_id) + "/service-apis/" + str(api_id) + res = make_response(object=serialize_clean_camel_case(serviceapidescription), status=201) + res.headers['Location'] = "http://localhost:8080/published-apis/v1/" + \ + str(apf_id) + "/service-apis/" + str(api_id) + + if res.status_code == 201: + current_app.logger.info("Service published") + RedisEvent("SERVICE_API_AVAILABLE", "apiIds", + [str(api_id)]).send_event() return res except Exception as e: @@ -113,26 +125,25 @@ class PublishServiceOperations(Resource): current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) - - def get_one_serviceapi(self, service_api_id, apf_id): mycol = self.db.get_col_by_name(self.db.service_api_descriptions) try: - current_app.logger.debug("Geting service api with id: " + service_api_id) + current_app.logger.debug( + "Geting service api with id: " + service_api_id) result = self.__check_apf(apf_id) if result != None: return result my_query = {'apf_id': apf_id, 'api_id': service_api_id} - service_api = mycol.find_one(my_query, {"apf_id":0, "_id":0}) + service_api = mycol.find_one(my_query, {"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, + "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}) if service_api is None: current_app.logger.error(service_api_not_found_message) return not_found_error(detail=service_api_not_found_message, cause="No Service with specific credentials exists") - my_service_api = dict_to_camel_case(service_api) my_service_api = clean_empty(my_service_api) @@ -151,7 +162,8 @@ class PublishServiceOperations(Resource): try: - current_app.logger.debug("Removing api service with id: " + service_api_id) + current_app.logger.debug( + "Removing api service with id: " + service_api_id) result = self.__check_apf(apf_id) if result != None: @@ -169,22 +181,29 @@ class PublishServiceOperations(Resource): self.auth_manager.remove_auth_service(service_api_id, apf_id) current_app.logger.debug("Removed service from database") - out = "The service matching api_id " + service_api_id + " was deleted." - return make_response(out, status=204) + out = "The service matching api_id " + service_api_id + " was deleted." + res = make_response(out, status=204) + if res.status_code == 204: + current_app.logger.info("Removed service published") + RedisEvent("SERVICE_API_UNAVAILABLE", "apiIds", + [service_api_id]).send_event() + publisher_ops.publish_message( + "internal-messages", f"service-removed:{service_api_id}") + return res except Exception as e: exception = "An exception occurred in delete service" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) - def update_serviceapidescription(self, service_api_id, apf_id, service_api_description): mycol = self.db.get_col_by_name(self.db.service_api_descriptions) try: - current_app.logger.debug("Updating service api with id: " + service_api_id) + current_app.logger.debug( + "Updating service api with id: " + service_api_id) result = self.__check_apf(apf_id) @@ -201,18 +220,22 @@ class PublishServiceOperations(Resource): service_api_description = service_api_description.to_dict() service_api_description = clean_empty(service_api_description) - result = mycol.find_one_and_update(serviceapidescription, {"$set":service_api_description}, projection={"apf_id":0, "_id":0},return_document=ReturnDocument.AFTER ,upsert=False) + result = mycol.find_one_and_update(serviceapidescription, {"$set": service_api_description}, projection={"_id": 0, "api_name": 1, "api_id": 1, "aef_profiles": 1, "description": 1, + "supported_features": 1, "shareable_info": 1, "service_api_category": 1, "api_supp_feats": 1, "pub_api_path": 1, "ccf_id": 1}, return_document=ReturnDocument.AFTER, upsert=False) result = clean_empty(result) current_app.logger.debug("Updated service api") - - response = make_response(object=dict_to_camel_case(result), status=200) + service_api_description_updated = dict_to_camel_case(result) + response = make_response( + object=service_api_description_updated, status=200) + if response.status_code == 200: + RedisEvent("SERVICE_API_UPDATE", "serviceAPIDescriptions", [ + service_api_description_updated]).send_event() return response except Exception as e: exception = "An exception occurred in update service" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) - diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py index 67d434dc13624075dbc1698d90046d9c10326ac8..f48414943c1c384b10d52d21c1aac456a1d772bc 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/core/validate_user.py @@ -4,6 +4,8 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource from .responses import internal_server_error +from ..util import serialize_clean_camel_case + class ControlAccess(Resource): @@ -18,6 +20,7 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature or "services" not in cert_entry["resources"] or service_id not in cert_entry["resources"]["services"]: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py index 91f7b6bb9408859d41a1e9a8c05be563669902fd..643dda4f7a96c4e663d6aac3fd956ba0797bb39b 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/db/db.py @@ -1,13 +1,13 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py index c753f45e1f69eda91e19d4328d2447f9e7114fe0..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from published_apis.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py index 3f53de6f85ebf9316a86066e36089d73a96bd886..3d85256f947326515afce40014c53420ef7c4879 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/util.py @@ -1,8 +1,15 @@ import datetime import six -import typing -from published_apis import typing_utils +import typing_utils + + +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res def clean_empty(d): @@ -16,15 +23,19 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): result = {} for attr, value in my_dict.items(): + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key= ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) if my_key == "serviceApiCategory": my_key = "serviceAPICategory" diff --git a/services/TS29222_CAPIF_Publish_Service_API/published_apis/wsgi.py b/services/TS29222_CAPIF_Publish_Service_API/published_apis/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Publish_Service_API/published_apis/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Publish_Service_API/requirements.txt b/services/TS29222_CAPIF_Publish_Service_API/requirements.txt index 0ba8fb534606696f9f5e2cd5164563a048709b67..0b1b9e8c227957eae80431cd7df84296dabeb2c4 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/requirements.txt +++ b/services/TS29222_CAPIF_Publish_Service_API/requirements.txt @@ -1,21 +1,24 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 -pymongo == 4.0.1 +pymongo == 4.7.3 flask_jwt_extended == 4.4.4 opentelemetry-instrumentation == 0.38b0 opentelemetry-instrumentation-flask == 0.38b0 opentelemetry-instrumentation-redis == 0.38b0 opentelemetry-instrumentation-pymongo == 0.38b0 opentelemetry-exporter-otlp == 1.17.0 -opentelemetry-exporter-jaeger==1.17.0 +opentelemetry-exporter-jaeger == 1.17.0 fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 flask_executor == 1.0.0 -pyopenssl == 23.0.0 +cryptography == 42.0.8 redis == 4.5.4 flask_executor == 1.0.0 +Werkzeug == 2.2.3 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_Publish_Service_API/test-requirements.txt b/services/TS29222_CAPIF_Publish_Service_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_Publish_Service_API/test-requirements.txt +++ b/services/TS29222_CAPIF_Publish_Service_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/TS29222_CAPIF_Routing_Info_API/Dockerfile b/services/TS29222_CAPIF_Routing_Info_API/Dockerfile index 9911d06b662dc1890945b8ec73c862a5ae5a2fab..470877e41836eedb6467794b8af2f4d7281c14cd 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/Dockerfile +++ b/services/TS29222_CAPIF_Routing_Info_API/Dockerfile @@ -11,6 +11,4 @@ COPY . /usr/src/app EXPOSE 8080 -ENTRYPOINT ["python3"] - -CMD ["-m", "capif_routing_info"] \ No newline at end of file +CMD ["sh", "prepare_routing_info.sh"] \ No newline at end of file diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/__main__.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/__main__.py deleted file mode 100644 index e595fa02106ed80d620b8eb00f1d2a421bb1ee5f..0000000000000000000000000000000000000000 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/__main__.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python3 - -import connexion - -from capif_routing_info import encoder - - -def main(): - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - app.add_api('openapi.yaml', - arguments={'title': 'CAPIF_Routing_Info_API'}, - pythonic_params=True) - - app.run(port=8080) - - -if __name__ == '__main__': - main() diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/app.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/app.py new file mode 100644 index 0000000000000000000000000000000000000000..89135805b065ac22200eecdbf76b699f7035e680 --- /dev/null +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/app.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python3 + +import connexion +import encoder + + +app = connexion.App(__name__, specification_dir='./openapi/') +app.app.json_encoder = encoder.JSONEncoder +app.add_api('openapi.yaml', + arguments={'title': 'CAPIF_Routing_Info_API'}, + pythonic_params=True) diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py index 7cd07dd74ff2634a9487083283cad4ef354c61ae..13c24a3a52464679a765141f1963cc5bb21248ec 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/controllers/default_controller.py @@ -1,9 +1,4 @@ -import connexion -import six - -from capif_routing_info.models.problem_details import ProblemDetails # noqa: E501 -from capif_routing_info.models.routing_info import RoutingInfo # noqa: E501 -from capif_routing_info import util +from ..models.routing_info import RoutingInfo # noqa: E501 def service_apis_service_api_id_get(service_api_id, aef_id, supp_feat=None): # noqa: E501 diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py index b53647004a14457d83693f5909b69425d927d3c8..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from capif_routing_info.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/ipv4_address_range.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/ipv4_address_range.py index 8bf453284830c0d9696da8ccd2b8deea4ae98178..5f8e7c0745d8183a852e265bedb4a42dbe445f4e 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/ipv4_address_range.py +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/ipv4_address_range.py @@ -70,7 +70,7 @@ class Ipv4AddressRange(Model): :type start: str """ if start is not None and not re.search(r'^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$', start): # noqa: E501 - raise ValueError("Invalid value for `start`, must be a follow pattern or equal to `/^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/`") # noqa: E501 + raise ValueError("Invalid value for `start`, must be a follow pattern or equal to `/^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/`") # noqa: E501 self._start = start @@ -95,6 +95,6 @@ class Ipv4AddressRange(Model): :type end: str """ if end is not None and not re.search(r'^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$', end): # noqa: E501 - raise ValueError("Invalid value for `end`, must be a follow pattern or equal to `/^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/`") # noqa: E501 + raise ValueError("Invalid value for `end`, must be a follow pattern or equal to `/^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$/`") # noqa: E501 self._end = end diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/routing_rule.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/routing_rule.py index f177670a723ccc3594611b7ee85a8f6bbfff6e90..29c0930b40676c276cdd8df190b8b5a31d410dd7 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/routing_rule.py +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/models/routing_rule.py @@ -11,10 +11,6 @@ from capif_routing_info.models.ipv4_address_range import Ipv4AddressRange from capif_routing_info.models.ipv6_address_range import Ipv6AddressRange from capif_routing_info import util -from capif_routing_info.models.aef_profile import AefProfile # noqa: E501 -from capif_routing_info.models.ipv4_address_range import Ipv4AddressRange # noqa: E501 -from capif_routing_info.models.ipv6_address_range import Ipv6AddressRange # noqa: E501 - class RoutingRule(Model): """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py index 227076550fea5acb4f1f167a777f366215563261..54a13013df3b7fde574d61407acd23d0223f0be3 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/util.py @@ -1,8 +1,7 @@ import datetime import six -import typing -from capif_routing_info import typing_utils +import typing_utils def _deserialize(data, klass): diff --git a/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/wsgi.py b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Routing_Info_API/capif_routing_info/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Routing_Info_API/prepare_routing_info.sh b/services/TS29222_CAPIF_Routing_Info_API/prepare_routing_info.sh new file mode 100644 index 0000000000000000000000000000000000000000..53eaa2b084e73d1fe7e710f1acf94b48771b668b --- /dev/null +++ b/services/TS29222_CAPIF_Routing_Info_API/prepare_routing_info.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/capif_routing_info wsgi:app diff --git a/services/TS29222_CAPIF_Routing_Info_API/requirements.txt b/services/TS29222_CAPIF_Routing_Info_API/requirements.txt index 1be0346f149043abdcafbd540c98c73eca75275e..afaac687767e9f9669d7f6baadf40a77ceddedb8 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/requirements.txt +++ b/services/TS29222_CAPIF_Routing_Info_API/requirements.txt @@ -1,5 +1,8 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 +Werkzeug == 2.2.3 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_Routing_Info_API/test-requirements.txt b/services/TS29222_CAPIF_Routing_Info_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_Routing_Info_API/test-requirements.txt +++ b/services/TS29222_CAPIF_Routing_Info_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/TS29222_CAPIF_Security_API/Dockerfile b/services/TS29222_CAPIF_Security_API/Dockerfile index 9566c752eaa135a135faeb70c812db1d2d997c0a..9f73be9b86061f4cd1055ed23a54261db97853fd 100644 --- a/services/TS29222_CAPIF_Security_API/Dockerfile +++ b/services/TS29222_CAPIF_Security_API/Dockerfile @@ -15,4 +15,4 @@ COPY . /usr/src/app EXPOSE 8080 -CMD ["sh", "security_prepare.sh"] +CMD ["sh", "prepare_security.sh"] diff --git a/services/TS29222_CAPIF_Security_API/capif_security/__main__.py b/services/TS29222_CAPIF_Security_API/capif_security/app.py similarity index 76% rename from services/TS29222_CAPIF_Security_API/capif_security/__main__.py rename to services/TS29222_CAPIF_Security_API/capif_security/app.py index 98d396499dd9e5b056d1d63d9fbaa3dcf8fae442..43457008864cc00a84b515f3e210654e2bf82c4d 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/__main__.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/app.py @@ -2,14 +2,11 @@ import connexion import logging -from capif_security import encoder +import encoder from flask_jwt_extended import JWTManager -from .config import Config -from .core.consumer_messager import Subscriber -from threading import Thread -from flask_executor import Executor +from config import Config +from core.consumer_messager import Subscriber from logging.handlers import RotatingFileHandler -import sys import os from fluent import sender from flask_executor import Executor @@ -22,10 +19,12 @@ from opentelemetry.sdk.trace import TracerProvider from opentelemetry.sdk.trace.export import BatchSpanProcessor from opentelemetry.instrumentation.redis import RedisInstrumentor - - NAME = "Security-Service" +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + def configure_monitoring(app, config): resource = Resource(attributes={"service.name": NAME}) @@ -89,10 +88,10 @@ def configure_logging(app): loggers = [app.logger, ] handlers = [] console_handler = logging.StreamHandler() - console_handler.setLevel(logging.DEBUG) + console_handler.setLevel(numeric_level) console_handler.setFormatter(verbose_formatter()) file_handler = RotatingFileHandler(filename="security_logs.log", maxBytes=1024 * 1024 * 100, backupCount=20) - file_handler.setLevel(logging.DEBUG) + file_handler.setLevel(numeric_level) file_handler.setFormatter(verbose_formatter()) handlers.append(console_handler) handlers.append(file_handler) @@ -101,7 +100,7 @@ def configure_logging(app): for handler in handlers: l.addHandler(handler) l.propagate = False - l.setLevel(logging.DEBUG) + l.setLevel(numeric_level) def verbose_formatter(): @@ -110,39 +109,32 @@ def verbose_formatter(): datefmt='%d/%m/%Y %H:%M:%S' ) -def main(): - - with open("/usr/src/app/capif_security/server.key", "rb") as key_file: - key_data = key_file.read() - - app = connexion.App(__name__, specification_dir='./openapi/') - app.app.json_encoder = encoder.JSONEncoder - - - app.app.config['JWT_ALGORITHM'] = 'RS256' - app.app.config['JWT_PRIVATE_KEY'] = key_data - app.add_api('openapi.yaml', - arguments={'title': 'CAPIF_Security_API'}, - pythonic_params=True) - JWTManager(app.app) - subscriber = Subscriber() +with open("/usr/src/app/capif_security/server.key", "rb") as key_file: + key_data = key_file.read() - config = Config() - configure_logging(app.app) +app = connexion.App(__name__, specification_dir='./openapi/') +app.app.json_encoder = encoder.JSONEncoder - if eval(os.environ.get("MONITORING").lower().capitalize()): - configure_monitoring(app.app, config.get_config()) - executor = Executor(app.app) +app.app.config['JWT_ALGORITHM'] = 'RS256' +app.app.config['JWT_PRIVATE_KEY'] = key_data +app.add_api('openapi.yaml', + arguments={'title': 'CAPIF_Security_API'}, + pythonic_params=True) - @app.app.before_first_request - def up_listener(): - executor.submit(subscriber.listen) +JWTManager(app.app) +subscriber = Subscriber() +config = Config() +configure_logging(app.app) - app.run(port=8080, debug=True) +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": + configure_monitoring(app.app, config.get_config()) -if __name__ == '__main__': - main() +executor = Executor(app.app) +@app.app.before_first_request +def up_listener(): + executor.submit(subscriber.listen) diff --git a/services/TS29222_CAPIF_Security_API/capif_security/config.py b/services/TS29222_CAPIF_Security_API/capif_security/config.py index 11e1c4f3626d7440c6cd999ed118afb3c93caa2e..01f9914cc141eb3c49fd73506e9b1c5470edd781 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/config.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py b/services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py index aee7098c5de2963bb41ce27b110b5e0fbbd6394a..7e04d4df353bd4227d5b7bda72e3cb7236cf1dab 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/controllers/default_controller.py @@ -1,26 +1,20 @@ import connexion -import six - -from capif_security.models.access_token_err import AccessTokenErr # noqa: E501 -from capif_security.models.access_token_rsp import AccessTokenRsp # noqa: E501 -from capif_security.models.access_token_req import AccessTokenReq # noqa: E501 -from capif_security.models.security_notification import SecurityNotification # noqa: E501 -from capif_security.models.service_security import ServiceSecurity # noqa: E501 -from capif_security import util + +from ..models.access_token_req import AccessTokenReq # noqa: E501 +from ..models.security_notification import SecurityNotification # noqa: E501 +from ..models.service_security import ServiceSecurity # noqa: E501 + from ..core.servicesecurity import SecurityOperations -from ..core.consumer_messager import Subscriber + from ..core.publisher import Publisher -import json + from flask import Response, request, current_app -from flask_jwt_extended import jwt_required, get_jwt_identity -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails -import sys + from cryptography import x509 from cryptography.hazmat.backends import default_backend from ..core.validate_user import ControlAccess from functools import wraps -import pymongo + service_security_ops = SecurityOperations() publish_ops = Publisher() @@ -117,10 +111,7 @@ def trusted_invokers_api_invoker_id_delete_post(api_invoker_id, body): # noqa: current_app.logger.info("Revoking permissions") res = service_security_ops.revoke_api_authorization(api_invoker_id, body) - if res.status_code == 204: - current_app.logger.info("Permissions revoked") - publish_ops.publish_message("events", "API_INVOKER_AUTHORIZATION_REVOKED") - + return res @cert_validation() diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py b/services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py index fd9c328e47b82191780c4b88d69f4ab9fdd5b524..43445583236a5743ea1475079a3c329bb0788787 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/consumer_messager.py @@ -1,13 +1,9 @@ # subscriber.py import redis -import time -import sys -import json -import asyncio -from threading import Thread from .internal_security_ops import InternalSecurityOps from flask import current_app + class Subscriber(): def __init__(self): @@ -21,12 +17,7 @@ class Subscriber(): for raw_message in self.p.listen(): if raw_message["type"] == "message" and raw_message["channel"].decode('utf-8') == "internal-messages": message, *ids = raw_message["data"].decode('utf-8').split(":") - if message == "invoker-removed" and len(ids)>0: + if message == "invoker-removed" and len(ids) > 0: self.security_ops.delete_intern_servicesecurity(ids[0]) if message == "provider-removed" or message == "service-removed" and len(ids) > 0: self.security_ops.update_intern_servicesecurity(ids[0]) - - - - - diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py b/services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py index d5cbd968beee2cae29b63b8ad679f0e6d776da1f..d1b28d5938fa8f7c1d2c5d2bf9d4a3a9b3c68fda 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/internal_security_ops.py @@ -1,5 +1,4 @@ -from flask import current_app from .resources import Resource class InternalSecurityOps(Resource): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/notification.py b/services/TS29222_CAPIF_Security_API/capif_security/core/notification.py index 5d69adc7b79d47ce637309e3046f3937856e58cc..2efad5f7f28459e561ddcf9d22612275e1435dea 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/notification.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/notification.py @@ -1,7 +1,5 @@ import requests -from ..encoder import JSONEncoder -import sys -import json + class Notifications(): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py b/services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py index f7b0c3c4b25f9abbe24d2dc734a72a93ffe0af01..8292de4d4330b14c17be74e7448403b56fc5b9e3 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/publisher.py @@ -1,5 +1,5 @@ import redis -import sys + class Publisher(): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/redis_event.py b/services/TS29222_CAPIF_Security_API/capif_security/core/redis_event.py new file mode 100644 index 0000000000000000000000000000000000000000..aadbdbb6b3116cf288648de41effdb12b9ca9143 --- /dev/null +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/redis_event.py @@ -0,0 +1,41 @@ +from ..encoder import JSONEncoder +from .publisher import Publisher +import json + +publisher_ops = Publisher() + + +class RedisEvent(): + def __init__(self, event, event_detail_key=None, information=None) -> None: + self.EVENTS_ENUM = [ + 'SERVICE_API_AVAILABLE', + 'SERVICE_API_UNAVAILABLE', + 'SERVICE_API_UPDATE', + 'API_INVOKER_ONBOARDED', + 'API_INVOKER_OFFBOARDED', + 'SERVICE_API_INVOCATION_SUCCESS', + 'SERVICE_API_INVOCATION_FAILURE', + 'ACCESS_CONTROL_POLICY_UPDATE', + 'ACCESS_CONTROL_POLICY_UNAVAILABLE', + 'API_INVOKER_AUTHORIZATION_REVOKED', + 'API_INVOKER_UPDATED', + 'API_TOPOLOGY_HIDING_CREATED', + 'API_TOPOLOGY_HIDING_REVOKED'] + if event not in self.EVENTS_ENUM: + raise Exception( + "Event (" + event + ") is not on event enum (" + ','.join(self.EVENTS_ENUM) + ")") + self.redis_event = { + "event": event + } + if event_detail_key != None and information != None: + self.redis_event['key'] = event_detail_key + self.redis_event['information'] = information + + def to_string(self): + return json.dumps(self.redis_event, cls=JSONEncoder) + + def send_event(self): + publisher_ops.publish_message("events", self.to_string()) + + def __call__(self): + return self.redis_event diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/resources.py b/services/TS29222_CAPIF_Security_API/capif_security/core/resources.py index 2ba2a0f944c9ff47009a2d461aafde25751fcd88..53a35e5d60f0fbe6fd7735e0c766bee233f84b47 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/resources.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/resources.py @@ -1,7 +1,8 @@ -from abc import ABC, abstractmethod -from ..db.db import MongoDatabse +from abc import ABC +from db.db import MongoDatabse from .notification import Notifications + class Resource(ABC): def __init__(self): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/responses.py b/services/TS29222_CAPIF_Security_API/capif_security/core/responses.py index 26e82b68c92cc01fbd9682f119d5d6e3d58711a8..4e1eb35cbaf62e88311170d3afee308ab7aa5b64 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/responses.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/responses.py @@ -2,36 +2,47 @@ from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from flask import Response import json -from bson import json_util +from ..util import serialize_clean_camel_case mimetype = "application/json" + def make_response(object, status): res = Response(json.dumps(object, cls=JSONEncoder), status=status, mimetype=mimetype) return res + def internal_server_error(detail, cause): prob = ProblemDetails(title="Internal Server Error", status=500, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=500, mimetype=mimetype) + def forbidden_error(detail, cause): prob = ProblemDetails(title="Forbidden", status=403, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=403, mimetype=mimetype) + def bad_request_error(detail, cause, invalid_params): prob = ProblemDetails(title="Bad Request", status=400, detail=detail, cause=cause, invalid_params=invalid_params) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=400, mimetype=cause) + def not_found_error(detail, cause): prob = ProblemDetails(title="Not Found", status=404, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=404, mimetype=mimetype) + def unauthorized_error(detail, cause): prob = ProblemDetails(title="Unauthorized", status=401, detail=detail, cause=cause) + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype=mimetype) \ No newline at end of file diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py b/services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py index 69475ac99a1d3fd4fca004bea2e98913571e2e68..c754a314e3a3af554d9ed90cac19d036ea88943c 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/servicesecurity.py @@ -1,29 +1,21 @@ -import sys -import pymongo from pymongo import ReturnDocument -import secrets -import re + import rfc3987 from flask import current_app, Flask, Response from flask_jwt_extended import create_access_token from datetime import datetime, timedelta import json -from ..db.db import MongoDatabse -from ..encoder import JSONEncoder -from ..models.problem_details import ProblemDetails -from ..models.access_token_rsp import AccessTokenRsp -from ..models.access_token_claims import AccessTokenClaims from bson import json_util -import requests from ..core.publisher import Publisher from ..models.access_token_err import AccessTokenErr -from ..models.service_security import ServiceSecurity -from ..util import dict_to_camel_case, clean_empty +from ..models.access_token_rsp import AccessTokenRsp +from ..models.access_token_claims import AccessTokenClaims +from ..util import dict_to_camel_case, clean_empty, serialize_clean_camel_case from .responses import not_found_error, make_response, bad_request_error, internal_server_error, forbidden_error -from .notification import Notifications from .resources import Resource +from .redis_event import RedisEvent import os publish_ops = Publisher() @@ -31,13 +23,15 @@ publish_ops = Publisher() security_context_not_found_detail = "Security context not found" api_invoker_no_context_cause = "API Invoker has no security context" + class SecurityOperations(Resource): def __check_invoker(self, api_invoker_id): invokers_col = self.db.get_col_by_name(self.db.capif_invokers) - current_app.logger.debug("Checking api invoker with id: " + api_invoker_id) - invoker = invokers_col.find_one({"api_invoker_id": api_invoker_id}) + current_app.logger.debug( + "Checking api invoker with id: " + api_invoker_id) + invoker = invokers_col.find_one({"api_invoker_id": api_invoker_id}) if invoker is None: current_app.logger.error("Invoker not found") return not_found_error(detail="Invoker not found", cause="API Invoker not exists or invalid ID") @@ -53,11 +47,12 @@ class SecurityOperations(Resource): if header != "3gpp": current_app.logger.error("Bad format scope") token_error = AccessTokenErr(error="invalid_scope", error_description="The first characters must be '3gpp'") - return make_response(object=token_error, status=400) + return make_response(object=clean_empty(token_error.to_dict()), status=400) _, body = scope.split("#") - capif_service_col = self.db.get_col_by_name(self.db.capif_service_col) + capif_service_col = self.db.get_col_by_name( + self.db.capif_service_col) security_info = security_context["security_info"] aef_security_context = [info["aef_id"] for info in security_info] @@ -67,21 +62,25 @@ class SecurityOperations(Resource): if aef_id not in aef_security_context: current_app.logger.error("Bad format Scope, not valid aef id ") token_error = AccessTokenErr(error="invalid_scope", error_description="One of aef_id not belongs of your security context") - return make_response(object=token_error, status=400) + return make_response(object=clean_empty(token_error.to_dict()), status=400) + api_names = api_names.split(",") for api_name in api_names: - service = capif_service_col.find_one({"$and": [{"api_name":api_name},{self.filter_aef_id:aef_id}]}) + service = capif_service_col.find_one( + {"$and": [{"api_name": api_name}, {self.filter_aef_id: aef_id}]}) if service is None: current_app.logger.error("Bad format Scope, not valid api name") - token_error = AccessTokenErr(error="invalid_scope", error_description="One of the api names does not exist or is not associated with the aef id provided") - return make_response(object=token_error, status=400) + token_error = AccessTokenErr( + error="invalid_scope", + error_description="One of the api names does not exist or is not associated with the aef id provided") + return make_response(object=clean_empty(token_error.to_dict()), status=400) return None except Exception as e: current_app.logger.error("Bad format Scope: " + e) token_error = AccessTokenErr(error="invalid_scope", error_description="malformed scope") - return make_response(object=token_error, status=400) + return make_response(object=clean_empty(token_error.to_dict()), status=400) def __init__(self): Resource.__init__(self) @@ -93,16 +92,18 @@ class SecurityOperations(Resource): try: - current_app.logger.debug("Obtainig security context with id: " + api_invoker_id) + current_app.logger.debug( + "Obtainig security context with id: " + api_invoker_id) result = self.__check_invoker(api_invoker_id) if result != None: return result else: - services_security_object = mycol.find_one({"api_invoker_id": api_invoker_id}, {"_id":0, "api_invoker_id":0}) + services_security_object = mycol.find_one({"api_invoker_id": api_invoker_id}, { + "_id": 0, "api_invoker_id": 0}) if services_security_object is None: current_app.logger.error("Not found security context") - return not_found_error(detail= security_context_not_found_detail, cause=api_invoker_no_context_cause) + return not_found_error(detail=security_context_not_found_detail, cause=api_invoker_no_context_cause) if not authentication_info: for security_info_obj in services_security_object['security_info']: @@ -111,12 +112,15 @@ class SecurityOperations(Resource): for security_info_obj in services_security_object['security_info']: del security_info_obj['authorization_info'] - properyly_json= json.dumps(services_security_object, default=json_util.default) - my_service_security = dict_to_camel_case(json.loads(properyly_json)) + properyly_json = json.dumps( + services_security_object, default=json_util.default) + my_service_security = dict_to_camel_case( + json.loads(properyly_json)) my_service_security = clean_empty(my_service_security) - current_app.logger.debug("Obtained security context from database") - + current_app.logger.debug( + "Obtained security context from database") + res = make_response(object=my_service_security, status=200) return res @@ -125,7 +129,6 @@ class SecurityOperations(Resource): current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) - def create_servicesecurity(self, api_invoker_id, service_security): mycol = self.db.get_col_by_name(self.db.security_info) @@ -139,51 +142,64 @@ class SecurityOperations(Resource): if rfc3987.match(service_security.notification_destination, rule="URI") is None: current_app.logger.error("Bad url format") - return bad_request_error(detail="Bad Param", cause = "Detected Bad format of param", invalid_params=[{"param": "notificationDestination", "reason": "Not valid URL format"}]) + return bad_request_error(detail="Bad Param", cause="Detected Bad format of param", invalid_params=[{"param": "notificationDestination", "reason": "Not valid URL format"}]) - services_security_object = mycol.find_one({"api_invoker_id": api_invoker_id}) + services_security_object = mycol.find_one( + {"api_invoker_id": api_invoker_id}) if services_security_object is not None: - current_app.logger.error("Already security context defined with same api invoker id") + current_app.logger.error( + "Already security context defined with same api invoker id") return forbidden_error(detail="Security method already defined", cause="Identical AEF Profile IDs") - for service_instance in service_security.security_info: if service_instance.interface_details is not None: security_methods = service_instance.interface_details.security_methods pref_security_methods = service_instance.pref_security_methods - valid_security_method = set(security_methods) & set(pref_security_methods) + valid_security_method = set( + security_methods) & set(pref_security_methods) else: - capif_service_col = self.db.get_col_by_name(self.db.capif_service_col) - services_security_object = capif_service_col.find_one({"api_id":service_instance.api_id, self.filter_aef_id: service_instance.aef_id}, {"aef_profiles.security_methods.$":1}) + capif_service_col = self.db.get_col_by_name( + self.db.capif_service_col) + services_security_object = capif_service_col.find_one( + {"api_id": service_instance.api_id, self.filter_aef_id: service_instance.aef_id}, {"aef_profiles.security_methods.$": 1}) if services_security_object is None: - current_app.logger.error("Not found service with this aef id: " + service_instance.aef_id) + current_app.logger.error( + "Not found service with this aef id: " + service_instance.aef_id) return not_found_error(detail="Service with this aefId not found", cause="Not found Service") pref_security_methods = service_instance.pref_security_methods - valid_security_methods = [security_method for array_methods in services_security_object["aef_profiles"] for security_method in array_methods["security_methods"]] - valid_security_method = set(valid_security_methods) & set(pref_security_methods) + valid_security_methods = [security_method for array_methods in services_security_object["aef_profiles"] + for security_method in array_methods["security_methods"]] + valid_security_method = set( + valid_security_methods) & set(pref_security_methods) if len(list(valid_security_method)) == 0: - current_app.logger.error("Not found comptaible security method with pref security method") + current_app.logger.error( + "Not found comptaible security method with pref security method") return bad_request_error(detail="Not found compatible security method with pref security method", cause="Error pref security method", invalid_params=[{"param": "prefSecurityMethods", "reason": "pref security method not compatible with security method available"}]) - service_instance.sel_security_method = list(valid_security_method)[0] + service_instance.sel_security_method = list( + valid_security_method)[0] # Send service instance to ACL current_app.logger.debug("Sending message to create ACL") - publish_ops.publish_message("acls-messages", "create-acl:"+str(api_invoker_id)+":"+str(service_instance.api_id)+":"+str(service_instance.aef_id)) - current_app.logger.debug("Inserted security context in database") + publish_ops.publish_message("acls-messages", "create-acl:"+str( + api_invoker_id)+":"+str(service_instance.api_id)+":"+str(service_instance.aef_id)) + current_app.logger.debug( + "Inserted security context in database") rec = dict() rec['api_invoker_id'] = api_invoker_id rec.update(service_security.to_dict()) mycol.insert_one(rec) - res = make_response(object=service_security, status=201) - res.headers['Location'] = "https://{}/capif-security/v1/trustedInvokers/{}".format(os.getenv('CAPIF_HOSTNAME'),str(api_invoker_id)) + res = make_response(object=serialize_clean_camel_case(service_security), status=201) + res.headers['Location'] = "https://{}/capif-security/v1/trustedInvokers/{}".format( + os.getenv('CAPIF_HOSTNAME'), str(api_invoker_id)) + return res except Exception as e: @@ -191,7 +207,6 @@ class SecurityOperations(Resource): current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) - def delete_servicesecurity(self, api_invoker_id): mycol = self.db.get_col_by_name(self.db.security_info) @@ -210,19 +225,22 @@ class SecurityOperations(Resource): if services_security_count == 0: current_app.logger.error(security_context_not_found_detail) return not_found_error(detail=security_context_not_found_detail, cause=api_invoker_no_context_cause) - + mycol.delete_many(my_query) - publish_ops.publish_message("acls-messages", "remove-acl:"+api_invoker_id) + publish_ops.publish_message( + "acls-messages", "remove-acl:"+api_invoker_id) - current_app.logger.debug("Removed security context from database") - out= "The security info of Netapp with Netapp ID " + api_invoker_id + " were deleted.", 204 + current_app.logger.debug( + "Removed security context from database") + out = "The security info of Network App with Network App ID " + \ + api_invoker_id + " were deleted.", 204 return make_response(out, status=204) except Exception as e: exception = "An exception occurred in create security info" current_app.logger.error(exception + "::" + str(e)) - return internal_server_error(detail=exception, cause = str(e)) + return internal_server_error(detail=exception, cause=str(e)) def delete_intern_servicesecurity(self, api_invoker_id): @@ -240,45 +258,50 @@ class SecurityOperations(Resource): invokers_col = self.db.get_col_by_name(self.db.capif_invokers) - current_app.logger.debug("Checking api invoker with id: " + access_token_req["client_id"]) - invoker = invokers_col.find_one({"api_invoker_id": access_token_req["client_id"]}) + current_app.logger.debug( + "Checking api invoker with id: " + access_token_req["client_id"]) + invoker = invokers_col.find_one( + {"api_invoker_id": access_token_req["client_id"]}) if invoker is None: - client_id_error = AccessTokenErr(error="invalid_client", error_description="Client Id not found") - return make_response(object=client_id_error, status=400) - + client_id_error = AccessTokenErr(error="invalid_client", error_description="Client Id not found") + return make_response(object=clean_empty(client_id_error.to_dict()), status=400) if access_token_req["grant_type"] != "client_credentials": - client_id_error = AccessTokenErr(error="unsupported_grant_type", error_description="Invalid value for `grant_type` ({0}), must be one of ['client_credentials'] - 'grant_type'" - .format(access_token_req["grant_type"])) - return make_response(object=client_id_error, status=400) + client_id_error = AccessTokenErr(error="unsupported_grant_type", + error_description="Invalid value for `grant_type` ({0}), must be one of ['client_credentials'] - 'grant_type'" + .format(access_token_req["grant_type"])) + return make_response(object=clean_empty(client_id_error.to_dict()), status=400) service_security = mycol.find_one({"api_invoker_id": security_id}) if service_security is None: - current_app.logger.error("Not found securoty context with id: " + security_id) + current_app.logger.error("Not found security context with id: " + security_id) return not_found_error(detail= security_context_not_found_detail, cause=api_invoker_no_context_cause) - result = self.__check_scope(access_token_req["scope"], service_security) + result = self.__check_scope( + access_token_req["scope"], service_security) if result != None: return result expire_time = timedelta(minutes=10) - now=datetime.now() + now = datetime.now() - claims = AccessTokenClaims(iss = access_token_req["client_id"], scope=access_token_req["scope"], exp=int((now+expire_time).timestamp())) - access_token = create_access_token(identity = access_token_req["client_id"] , additional_claims=claims.to_dict()) - access_token_resp = AccessTokenRsp(access_token=access_token, token_type="Bearer", expires_in=int(expire_time.total_seconds()), scope=access_token_req["scope"]) + claims = AccessTokenClaims(iss=access_token_req["client_id"], scope=access_token_req["scope"], exp=int( + (now+expire_time).timestamp())) + access_token = create_access_token( + identity=access_token_req["client_id"], additional_claims=claims.to_dict()) + access_token_resp = AccessTokenRsp(access_token=access_token, token_type="Bearer", expires_in=int( + expire_time.total_seconds()), scope=access_token_req["scope"]) current_app.logger.debug("Created access token") - res = make_response(object=access_token_resp, status=200) + res = make_response(object=clean_empty(access_token_resp.to_dict()), status=200) return res except Exception as e: exception = "An exception occurred in return token" current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) - def update_servicesecurity(self, api_invoker_id, service_security): mycol = self.db.get_col_by_name(self.db.security_info) try: @@ -291,38 +314,48 @@ class SecurityOperations(Resource): old_object = mycol.find_one({"api_invoker_id": api_invoker_id}) if old_object is None: - current_app.logger.error("Service api not found with id: " + api_invoker_id) + current_app.logger.error( + "Service api not found with id: " + api_invoker_id) return not_found_error(detail="Service API not existing", cause="Not exist securiy information for this invoker") for service_instance in service_security.security_info: if service_instance.interface_details is not None: security_methods = service_instance.interface_details.security_methods pref_security_methods = service_instance.pref_security_methods - valid_security_method = set(security_methods) & set(pref_security_methods) - service_instance.sel_security_method = list(valid_security_method)[0] + valid_security_method = set( + security_methods) & set(pref_security_methods) + service_instance.sel_security_method = list( + valid_security_method)[0] else: - capif_service_col = self.db.get_col_by_name(self.db.capif_service_col) - services_security_object = capif_service_col.find_one({self.filter_aef_id: service_instance.aef_id}, {"aef_profiles.security_methods.$":1}) + capif_service_col = self.db.get_col_by_name( + self.db.capif_service_col) + services_security_object = capif_service_col.find_one( + {self.filter_aef_id: service_instance.aef_id}, {"aef_profiles.security_methods.$": 1}) if services_security_object is None: - current_app.logger.error("Service api with this aefId not found: " + service_instance.aef_id) + current_app.logger.error( + "Service api with this aefId not found: " + service_instance.aef_id) return not_found_error(detail="Service with this aefId not found", cause="Not found Service") pref_security_methods = service_instance.pref_security_methods - valid_security_methods = [security_method for array_methods in services_security_object["aef_profiles"] for security_method in array_methods["security_methods"]] - valid_security_method = set(valid_security_methods) & set(pref_security_methods) - service_instance.sel_security_method = list(valid_security_method)[0] + valid_security_methods = [security_method for array_methods in services_security_object["aef_profiles"] + for security_method in array_methods["security_methods"]] + valid_security_method = set( + valid_security_methods) & set(pref_security_methods) + service_instance.sel_security_method = list( + valid_security_method)[0] service_security = service_security.to_dict() service_security = clean_empty(service_security) - result = mycol.find_one_and_update(old_object, {"$set":service_security}, projection={'_id': 0, "api_invoker_id":0},return_document=ReturnDocument.AFTER ,upsert=False) + result = mycol.find_one_and_update(old_object, {"$set": service_security}, projection={ + '_id': 0, "api_invoker_id": 0}, return_document=ReturnDocument.AFTER, upsert=False) - result = clean_empty(result) + # result = clean_empty(result) current_app.logger.debug("Updated security context") - res= make_response(object=dict_to_camel_case(result), status=200) + res= make_response(object=dict_to_camel_case(clean_empty(result)), status=200) res.headers['Location'] = "https://${CAPIF_HOSTNAME}/capif-security/v1/trustedInvokers/" + str( api_invoker_id) return res @@ -331,7 +364,6 @@ class SecurityOperations(Resource): current_app.logger.error(exception + "::" + str(e)) return internal_server_error(detail=exception, cause=str(e)) - def revoke_api_authorization(self, api_invoker_id, security_notification): mycol = self.db.get_col_by_name(self.db.security_info) @@ -352,10 +384,12 @@ class SecurityOperations(Resource): updated_security_context = services_security_context.copy() for context in services_security_context["security_info"]: - index = services_security_context["security_info"].index(context) + index = services_security_context["security_info"].index( + context) if security_notification.aef_id == context["aef_id"] or context["api_id"] in security_notification.api_ids: current_app.logger.debug("Sending message.") - publish_ops.publish_message("acls-messages", "remove-acl:"+str(api_invoker_id)+":"+str(context["api_id"])+":"+str(security_notification.aef_id)) + publish_ops.publish_message("acls-messages", "remove-acl:"+str( + api_invoker_id)+":"+str(context["api_id"])+":"+str(security_notification.aef_id)) current_app.logger.debug("message sended.") updated_security_context["security_info"].pop(index) @@ -364,13 +398,16 @@ class SecurityOperations(Resource): if len(updated_security_context["security_info"]) == 0: mycol.delete_many(my_query) - #self.notification.send_notification(services_security_context["notification_destination"], security_notification) - current_app.logger.debug("Revoked security context") - out= "Netapp with ID " + api_invoker_id + " was revoked by some APIs.", 204 - return make_response(out, status=204) + out = "Netapp with ID " + api_invoker_id + " was revoked by some APIs.", 204 + res = make_response(out, status=204) + if res.status_code == 204: + current_app.logger.info("Permissions revoked") + RedisEvent("API_INVOKER_AUTHORIZATION_REVOKED").send_event() + + return res except Exception as e: exception = "An exception occurred in revoke security auth" current_app.logger.error(exception + "::" + str(e)) - return internal_server_error(detail=exception, cause=str(e)) \ No newline at end of file + return internal_server_error(detail=exception, cause=str(e)) diff --git a/services/TS29222_CAPIF_Security_API/capif_security/core/validate_user.py b/services/TS29222_CAPIF_Security_API/capif_security/core/validate_user.py index 45ec5184b5dee5a886ddbe16fa3f00eeb5172a57..04d893edc45aa4b477a123755a4aeb1d36c05868 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/core/validate_user.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/core/validate_user.py @@ -3,7 +3,7 @@ import json from ..models.problem_details import ProblemDetails from ..encoder import JSONEncoder from .resources import Resource -from .responses import internal_server_error +from .responses import internal_server_error,serialize_clean_camel_case class ControlAccess(Resource): @@ -18,6 +18,7 @@ class ControlAccess(Resource): if cert_entry is not None: if cert_entry["cert_signature"] != cert_signature: prob = ProblemDetails(title="Unauthorized", detail="User not authorized", cause="You are not the owner of this resource") + prob = serialize_clean_camel_case(prob) return Response(json.dumps(prob, cls=JSONEncoder), status=401, mimetype="application/json") except Exception as e: diff --git a/services/TS29222_CAPIF_Security_API/capif_security/db/db.py b/services/TS29222_CAPIF_Security_API/capif_security/db/db.py index dbbb99e7899c2bb68867f1c3f99b869e578c1efa..47a9538c9c70be0cb96fee4119eb024db27b79cc 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/db/db.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/db/db.py @@ -2,12 +2,13 @@ import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config +from config import Config from bson.codec_options import CodecOptions import os from opentelemetry.instrumentation.pymongo import PymongoInstrumentor -if eval(os.environ.get("MONITORING").lower().capitalize()): +monitoring_value = os.environ.get("MONITORING", "").lower() +if monitoring_value == "true": PymongoInstrumentor().instrument() diff --git a/services/TS29222_CAPIF_Security_API/capif_security/encoder.py b/services/TS29222_CAPIF_Security_API/capif_security/encoder.py index 9d6964e4ccb171ae9174d22c6d790d186f42cebf..80bad8fa9220ab873e044b7adc0a849746088ad5 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/encoder.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/encoder.py @@ -1,7 +1,7 @@ from connexion.apps.flask_app import FlaskJSONEncoder import six -from capif_security.models.base_model_ import Model +from models.base_model_ import Model class JSONEncoder(FlaskJSONEncoder): diff --git a/services/TS29222_CAPIF_Security_API/capif_security/util.py b/services/TS29222_CAPIF_Security_API/capif_security/util.py index 873c290d1d0bd4a1b6e0a9ff18e60630cc836f14..72d18d9b7df0bfd24490b24c4b9d9bcd683ad9ef 100644 --- a/services/TS29222_CAPIF_Security_API/capif_security/util.py +++ b/services/TS29222_CAPIF_Security_API/capif_security/util.py @@ -1,8 +1,15 @@ import datetime import six -import typing -from capif_security import typing_utils +import typing_utils + + +def serialize_clean_camel_case(obj): + res = obj.to_dict() + res = clean_empty(res) + res = dict_to_camel_case(res) + + return res def clean_empty(d): @@ -16,6 +23,7 @@ def clean_empty(d): return [v for v in map(clean_empty, d) if v] return d + def dict_to_camel_case(my_dict): @@ -23,8 +31,11 @@ def dict_to_camel_case(my_dict): for attr, value in my_dict.items(): - my_key = ''.join(word.title() for word in attr.split('_')) - my_key= ''.join([my_key[0].lower(), my_key[1:]]) + if len(attr.split('_')) != 1: + my_key = ''.join(word.title() for word in attr.split('_')) + my_key = ''.join([my_key[0].lower(), my_key[1:]]) + else: + my_key = attr if isinstance(value, list): result[my_key] = list(map( @@ -42,7 +53,6 @@ def dict_to_camel_case(my_dict): return result - def _deserialize(data, klass): """Deserializes dict, list, str into an object. diff --git a/services/TS29222_CAPIF_Security_API/capif_security/wsgi.py b/services/TS29222_CAPIF_Security_API/capif_security/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/TS29222_CAPIF_Security_API/capif_security/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/TS29222_CAPIF_Security_API/security_prepare.sh b/services/TS29222_CAPIF_Security_API/prepare_security.sh similarity index 83% rename from services/TS29222_CAPIF_Security_API/security_prepare.sh rename to services/TS29222_CAPIF_Security_API/prepare_security.sh index c28b38929ae793399b64b70fab1ccbcccc6aeab0..94bece0582e614c49d6fbab23307984a2ad9875d 100644 --- a/services/TS29222_CAPIF_Security_API/security_prepare.sh +++ b/services/TS29222_CAPIF_Security_API/prepare_security.sh @@ -15,5 +15,5 @@ curl -k -retry 30 \ --request GET "$VAULT_ADDR/v1/secret/data/server_cert/private" 2>/dev/null | jq -r '.data.data.key' -j > /usr/src/app/capif_security/server.key -cd /usr/src/app/ -python3 -m capif_security \ No newline at end of file +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/capif_security wsgi:app \ No newline at end of file diff --git a/services/TS29222_CAPIF_Security_API/requirements.txt b/services/TS29222_CAPIF_Security_API/requirements.txt index 220adafdb62aa6e9343fde8c22dc7b2f9c7e0ba7..b92f321e856892a89171bb517ae90e604445af75 100644 --- a/services/TS29222_CAPIF_Security_API/requirements.txt +++ b/services/TS29222_CAPIF_Security_API/requirements.txt @@ -1,11 +1,11 @@ connexion[swagger-ui] == 2.14.2; python_version>="3.6" swagger-ui-bundle >= 0.0.2 python_dateutil >= 2.6.0 -setuptools >= 21.0.0 +setuptools == 68.2.2 Flask == 2.0.3 -pymongo == 4.0.1 +pymongo == 4.7.3 flask_jwt_extended == 4.4.4 -pyopenssl == 23.0.0 +cryptography == 42.0.8 rfc3987 == 1.3.8 redis == 4.5.4 flask_executor == 1.0.0 @@ -14,9 +14,12 @@ opentelemetry-instrumentation-flask == 0.38b0 opentelemetry-instrumentation-redis == 0.38b0 opentelemetry-instrumentation-pymongo == 0.38b0 opentelemetry-exporter-otlp == 1.17.0 -opentelemetry-exporter-jaeger==1.17.0 +opentelemetry-exporter-jaeger == 1.17.0 fluent == 0.10.0 fluent-logger == 0.10.0 opentelemetry-api == 1.17.0 opentelemetry-sdk == 1.17.0 -flask_executor == 1.0.0 \ No newline at end of file +flask_executor == 1.0.0 +Werkzeug == 2.2.3 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/TS29222_CAPIF_Security_API/test-requirements.txt b/services/TS29222_CAPIF_Security_API/test-requirements.txt index 0970f28c7c5a344d7fd9b9c893c584e7336df266..202a684feef71ff540d6aa528d348febf0b37d1e 100644 --- a/services/TS29222_CAPIF_Security_API/test-requirements.txt +++ b/services/TS29222_CAPIF_Security_API/test-requirements.txt @@ -1,4 +1,4 @@ pytest~=4.6.7 # needed for python 2.7+3.4 pytest-cov>=2.8.1 -pytest-randomly==1.2.3 # needed for python 2.7+3.4 -Flask-Testing==0.8.0 +pytest-randomly == 1.2.3 # needed for python 2.7+3.4 +Flask-Testing == 0.8.0 diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/Dockerfile b/services/capif-client/CAPIFInvokerGUI/invoker_gui/Dockerfile deleted file mode 100644 index 8357bf96b3ffb21ac8b942395a6df5b54b708ccb..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/Dockerfile +++ /dev/null @@ -1,13 +0,0 @@ -FROM python:3.8 -ENV PYTHONUNBUFFERED 1 - -RUN apt-get update && apt-get install -y jq && apt-get clean -RUN apt-get install -y iputils-ping - -RUN mkdir -p /usr/src/app -WORKDIR /usr/src/app -ADD requirements.txt /usr/src/app/ -RUN pip install -r requirements.txt -ADD . /usr/src/app/ - -CMD ["sh", "prepare.sh"] \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/capif_registration.json b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/capif_registration.json deleted file mode 100644 index 498f2844f3b1090f489960a6469bdf6d5fa6064f..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/capif_registration.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "folder_to_store_certificates": "/usr/src/app/capif_onboarding", - "capif_host": "capifcore", - "capif_http_port": "8080", - "capif_https_port": "443", - "capif_netapp_username": "test_netapp_23", - "capif_netapp_password": "test_netapp_password", - "capif_callback_url": "http://192.168.1.11:5000", - "description": ",test_app_description", - "csr_common_name": "test_app_common_name", - "csr_organizational_unit": "test_app_ou", - "csr_organization": "test_app_o", - "crs_locality": "Madrid", - "csr_state_or_province_name": "Madrid", - "csr_country_name": "ES", - "csr_email_address": "test@example.com" -} \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/credentials.properties b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/credentials.properties deleted file mode 100755 index 0c39e2c313412f75ba0a252e17da79ef884cf5be..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/credentials.properties +++ /dev/null @@ -1,14 +0,0 @@ -[credentials] -invoker_username = customnetapp -invoker_password = pass123 -invoker_role = invoker -invoker_description = Dummy NetApp -invoker_cn = invoker -#capif_ip = capicore -#capif_port = 8080 -capif_callback_ip = host.docker.internal -capif_callback_port = 8086 -nef_ip = host.docker.internal -nef_port = 8888 -nef_callback_ip = host.docker.internal -nef_callback_port = 8085 \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/demo_values.json b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/demo_values.json deleted file mode 100644 index 3a8a2ab4fa101b15b95b45565765dbd00a8a5aab..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/demo_values.json +++ /dev/null @@ -1 +0,0 @@ -{"netappID": "93caff2e486955", "ccf_onboarding_url": "api-invoker-management/v1/onboardedInvokers", "ccf_discover_url": "service-apis/v1/allServiceAPIs?api-invoker-id=", "capif_access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTY4OTU4NzA1OCwianRpIjoiMDViOGMwYWMtYmU4OC00OWViLWFhNWItZTA0ZDM4NWJlYWFkIiwidHlwZSI6ImFjY2VzcyIsInN1YiI6ImN1c3RvbW5ldGFwcCBpbnZva2VyIiwibmJmIjoxNjg5NTg3MDU4LCJleHAiOjE2ODk1ODc5NTh9.k8ZXlgS0CJS-aDJCHgUv0oA4B6CLBjYpp5z3qIrzsvgr20wflpKXiO03c6U3G87T33ocEPR6BWG-ZhpQ1bfml2CKU16gef4nIDIgOKh17yBF0M1eW-gULBZL9exJQIpDWJXQK9oZOrkyHjgN89ieXlVYW9hKaGQfRl_B_HZL0hllWq6E9uE7kHG-VJTEmLJTEyP6uqmfIPLz2znHeTk8eP7IB_vxeIh-7Fr6LcyziDoxMskPDqxzg_6oLyd7biH9qZyWQYvtrEPsh_kJdK5Yc7vK1Kuh01uY9JRk9E97sXU8x0yBjejHgDn9K7_kH1gugPo7eP6nEPvm3BROWHFUmw", "api_id_0": "1d3c0c7803e650264ba30963b96549", "api_name_0": "/nef/api/v1/3gpp-as-session-with-qos/", "aef_id_0": "8cadd2bf35c6adf24bda897b4e8e99", "demo_ipv4_addr_0": "3gppnef", "demo_port_0": 8090, "demo_url_0": "/nef/api/v1/3gpp-as-session-with-qos/v1/{scsAsId}/subscriptions", "netapp_service_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJmcmVzaCI6ZmFsc2UsImlhdCI6MTY4OTU4ODEwOCwianRpIjoiY2NiNDNkNzktNTRjYS00NDI4LTg1OGMtN2MyNDI1MzhiZjU5IiwidHlwZSI6ImFjY2VzcyIsInN1YiI6IjIwZjAxMTY0OTRkNTA0MjhmZTI2ZDdhNjNkYjNlNSIsIm5iZiI6MTY4OTU4ODEwOCwiZXhwIjoxNjg5NTg4NzA4LCJpc3MiOiIyMGYwMTE2NDk0ZDUwNDI4ZmUyNmQ3YTYzZGIzZTUiLCJzY29wZSI6IjNncHAjOGNhZGQyYmYzNWM2YWRmMjRiZGE4OTdiNGU4ZTk5Oi9uZWYvYXBpL3YxLzNncHAtYXMtc2Vzc2lvbi13aXRoLXFvcy8ifQ.PTdAWSGCqEdxroxd1qF_cNA_JRohvNlgw_A49CyaUVqEKrky2_LnVtRll_KOHPGgGcIa8g_vqdM6We71CGx7w_KQPuSccb_wUkPQ5U2kfDT2-dkBZX8le_M1aQ9346tl3iQHqPsoMv3KdiD6mNSbO8f7vlRbQ1o7HQLtLaULB_0xbFr1iJAWdwO6Dm0KOKP_rM6kC5gKyVaLzUPUQBHGQwncQWlKp1Cey3G2cW5Aw_O6kF8mt1R1wgNCedU77JUmW3-ptc1kWmWlSo3UypYNm-XRAMWh44yYnGok5gE1tf451cRc5s9Hfl6Ya2fYYBI1by9x1S_zGlxi6f_OV9z4zg", "api_id_1": "cbc42102826d69a35de147c790a983", "api_name_1": "/nef/api/v1/3gpp-as-session-with-qos/", "aef_id_1": "1f1883a784c43f47aa4fae1dc4821f", "demo_ipv4_addr_1": "127.0.0.1", "demo_port_1": 8090, "demo_url_1": "/{scsAsId}/subscriptions", "demo_resource_id": ""} \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/events.json b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/events.json deleted file mode 100644 index 3d109204f59cee2b45773ea6d6844a15762a86d8..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/events.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "events": [ - "SERVICE_API_AVAILABLE" - ], - "notificationDestination": "http://192.168.1.11:8080/capifcallbacks" - } \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/invoker_details.json b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/invoker_details.json deleted file mode 100755 index d94aa7fe5ac73c53d7b55664f0b9e36a4a1c8c24..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/invoker_details.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "notificationDestination" : "http://X:Y/netapp_callback", - "supportedFeatures" : "fffffff", - "apiInvokerInformation" : "dummy", - "websockNotifConfig" : { - "requestWebsocketUri" : true, - "websocketUri" : "websocketUri" - }, - "onboardingInformation" : { - "apiInvokerPublicKey" : "" - }, - "requestTestNotification" : true -} \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/security_info.json b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/security_info.json deleted file mode 100755 index c1b08672b8c08e0c8775b6c8a689fbba48fb51c1..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/security_info.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "securityInfo": [ - { - "prefSecurityMethods": [ - "OAUTH" - ], - "authenticationInfo": "string", - "authorizationInfo": "string" - } - ], - "notificationDestination": "https://mynotificationdest.com", - "requestTestNotification": true, - "websockNotifConfig": { - "websocketUri": "string", - "requestWebsocketUri": true - }, - "supportedFeatures": "fff" - } \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/service_request_body.json b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/service_request_body.json deleted file mode 100644 index 189c49e4d67d9bd1bab5790f7bc6fa50c78d4169..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/service_request_body.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "ipv4Addr": "10.0.0.3", - "notificationDestination": "http://invoker_gui:9091/nefcallbacks", - "snssai": { - "sst": 1, - "sd": "000001" - }, -"dnn": "province1.mnc01.mcc202.gprs", -"qosReference": 82, - "altQoSReferences": [ -0 - ], -"usageThreshold": { -"duration": 0, - "totalVolume": 0, -"downlinkVolume": 0, - "uplinkVolume": 0 - }, -"qosMonInfo": { -"reqQosMonParams": [ -"DOWNLINK" -], -"repFreqs": [ -"EVENT_TRIGGERED" -], - "latThreshDl": 0, -"latThreshUl": 0, - "latThreshRp": 0, -"waitTime": 0, - "repPeriod": 0 -} -} \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/token_request.json b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/token_request.json deleted file mode 100755 index 5408b745186bf0d0bd3f92a43229eef846c989c1..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/config_files/token_request.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "grant_type": "client_credentials", - "client_id": "", - "client_secret": "string", - "scope": "" -} \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_delete.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_delete.py deleted file mode 100644 index 297f88e559f8724a4a77ac5aa370bdb567e9c5ad..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_delete.py +++ /dev/null @@ -1,71 +0,0 @@ -from dis import dis -import requests -import json -import configparser -import os -from termcolor import colored - - -class RemoveInvoker(): - - - def __offboard_netapp_to_capif(self, capif_ip, invoker_id, log_level): - - print(colored("Removing netapp from CAPIF","yellow")) - url = 'https://{}/api-invoker-management/v1/onboardedInvokers/{}'.format(capif_ip, invoker_id) - - headers = { - 'Content-Type': 'application/json' - } - - try: - - if log_level == "debug": - print(colored("''''''''''REQUEST'''''''''''''''''","blue")) - print(colored(f"Request: to {url}","blue")) - print(colored(f"Request Headers: {headers}", "blue")) - print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - - response = requests.request("DELETE", url, headers=headers, cert=( - 'capif_ops/certs/dummy.crt', 'capif_ops/certs/invoker_private_key.key'), verify='capif_ops/certs/ca.crt') - response.raise_for_status() - - if log_level == "debug": - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - print(colored(f"Response to: {response.url}","green")) - print(colored(f"Response Headers: {response.headers}","green")) - print(colored(f"Response: {response.json()}","green")) - print(colored(f"Response Status code: {response.status_code}","green")) - print(colored("Success onboard invoker","green")) - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - - except requests.exceptions.HTTPError as err: - raise Exception(err.response.text, err.response.status_code) - - - - def execute_remove_invoker(self, log_level): - - - capif_ip = os.getenv('CAPIF_HOSTNAME') - - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - - try: - - self.__offboard_netapp_to_capif(capif_ip, demo_values["invokerID"], log_level) - - print("ApiInvokerID: {}\n".format(demo_values["invokerID"])) - demo_values.pop("invokerID") - demo_values.pop("pub_key") - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - except Exception as e: - status_code = e.args[0] - if status_code == 403: - print("Invoker already registered.") - print("Chanage invoker public key in invoker_details.json\n") - else: - print(e) diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_discover_service.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_discover_service.py deleted file mode 100644 index 7b608ac6fd23ba097dd4b7ae73661f4ab0e300dd..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_discover_service.py +++ /dev/null @@ -1,96 +0,0 @@ -from dis import dis -import requests -import json -import configparser -import redis -import os -from termcolor import colored - - -class DiscoverService(): - - def __discover_service_apis(self, capif_ip, api_invoker_id, jwt_token, ccf_url, log_level): - - print(colored("Discover Service", "yellow")) - url = "https://{}/{}{}".format(capif_ip, ccf_url, api_invoker_id) - - payload = {} - files = {} - headers = { - 'Content-Type': 'application/json' - } - - try: - - if log_level == "debug": - print(colored("''''''''''REQUEST'''''''''''''''''", "blue")) - print(colored(f"Request: to {url}", "blue")) - print(colored(f"Request Headers: {headers}", "blue")) - print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - - response = requests.request("GET", url, headers=headers, data=payload, files=files, cert=( - 'capif_ops/certs/dummy.crt', 'capif_ops/certs/invoker_private_key.key'), verify='capif_ops/certs/ca.crt') - response.raise_for_status() - response_payload = json.loads(response.text) - - if log_level == "debug": - print(colored("''''''''''RESPONSE'''''''''''''''''", "green")) - print(colored(f"Response to: {response.url}", "green")) - print(colored(f"Response Headers: {response.headers}", "green")) - print(colored(f"Response: {response.json()}", "green")) - print( - colored(f"Response Status code: {response.status_code}", "green")) - print(colored("''''''''''RESPONSE'''''''''''''''''", "green")) - - return response_payload - except requests.exceptions.HTTPError as err: - print(err.response.text) - message = json.loads(err.response.text) - status = err.response.status_code - raise Exception(message, status) - - def execute_discover_service(self, log_level): - - - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - - capif_ip = os.getenv('CAPIF_HOSTNAME') - - try: - if 'invokerID' in demo_values: - invokerID = demo_values['invokerID'] - capif_access_token = demo_values['capif_access_token'] - ccf_discover_url = demo_values['ccf_discover_url'] - discovered_apis = self.__discover_service_apis( - capif_ip, invokerID, capif_access_token, ccf_discover_url, log_level) - print(colored(json.dumps(discovered_apis, indent=2), "yellow")) - - count = 0 - api_list = discovered_apis["serviceAPIDescriptions"] - for api in api_list: - getAEF_profiles = api["aefProfiles"][0] - getAEF_interfaces = getAEF_profiles["interfaceDescriptions"][0] - getAEF_versions = getAEF_profiles["versions"][0] - getAEF_resources = getAEF_versions["resources"][0] - demo_values[f'api_id_{count}'] = api["apiId"] - demo_values[f'api_name_{count}'] = api["apiName"] - demo_values[f'aef_id_{count}'] = getAEF_profiles["aefId"] - demo_values[f'demo_ipv4_addr_{count}'] = getAEF_interfaces["ipv4Addr"] - demo_values[f'demo_port_{count}'] = getAEF_interfaces["port"] - demo_values[f'demo_url_{count}'] = api["apiName"] + getAEF_versions["apiVersion"]+ getAEF_resources['uri'] - count += 1 - - print(colored("Discovered APIs", "yellow")) - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - except Exception as e: - status_code = e.args[0] - if status_code == 401: - print("API Invoker is not authorized") - elif status_code == 403: - print("API Invoker does not exist. API Invoker id not found") - else: - print(e) - diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_get_auth.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_get_auth.py deleted file mode 100644 index dde36942bb6b493791a3142ccae1e6a891d8d1c4..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_get_auth.py +++ /dev/null @@ -1,71 +0,0 @@ -import requests -import json -import configparser -import os -from termcolor import colored - -class PreviousAuth(): - - def __get_capif_auth(self, capif_ip, capif_port, username, password): - - #print("Geting Auth to exposer") - #url = "http://{}:{}/getauth".format(capif_ip, capif_port) - url = "https://register:8084/getauth".format(capif_port) - #url = "http://{}:{}/getauth".format(capif_ip, capif_port) - - payload = dict() - payload['username'] = username - payload['password'] = password - - headers = { - 'Content-Type': 'application/json' - } - - try: - response = requests.request("POST", url, headers=headers, data=json.dumps(payload), verify=False) - - response.raise_for_status() - response_payload = json.loads(response.text) - - return response_payload['access_token'] - - except requests.exceptions.HTTPError as err: - raise Exception(err.response.text, err.response.status_code) - - - def execute_get_auth(self, log_level): - - config = configparser.ConfigParser() - config.read('capif_ops/config_files/credentials.properties') - - username = config.get("credentials", "invoker_username") - password = config.get("credentials", "invoker_password") - - capif_ip = os.getenv('CAPIF_HOSTNAME') - capif_port = os.getenv('CAPIF_PORT') - - if os.path.exists("capif_ops/config_files/demo_values.json"): - #os.remove("capif_ops/config_files/demo_values.json") - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - else: - demo_values = {} - - #First we need register exposer in CAPIF - try: - if 'netappID' in demo_values: - access_token = self.__get_capif_auth(capif_ip, capif_port, username, password) - demo_values['capif_access_token'] = access_token - - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - print("Invoker auth Success!") - except Exception as e: - status_code = e.args[0] - if status_code == 409: - print("User already registed. Continue with token request\n") - else: - print(e) - - return True diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_get_security_auth.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_get_security_auth.py deleted file mode 100644 index 74b026fa9e4e5859b4143ec21e91169d2619dad7..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_get_security_auth.py +++ /dev/null @@ -1,90 +0,0 @@ -from dis import dis -from email import charset -import requests -import json -import configparser -import redis -import os -from termcolor import colored - - -class InvokerGetSecurityAuth(): - - def __get_security_token(self, capif_ip, api_invoker_id, jwt_token, ccf_url, aef_id, api_name, log_level): - - - url = "https://{}/capif-security/v1/securities/{}/token".format(capif_ip, api_invoker_id) - - with open('capif_ops/config_files/token_request.json', "rb") as f: - payload = json.load(f) - - payload["client_id"] = api_invoker_id - payload["scope"] = "3gpp#"+aef_id+":"+api_name - - headers = { - 'Content-Type': 'application/x-www-form-urlencoded', - } - - - payload_dict = json.dumps(payload, indent=2) - - print(colored(f"Request Body: {payload_dict}", "yellow")) - - try: - - if log_level == "debug": - print(colored("''''''''''REQUEST'''''''''''''''''","blue")) - print(colored(f"Request: to {url}","blue")) - print(colored(f"Request Headers: {headers}", "blue")) - print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - - response = requests.post(url, headers=headers, data=payload, cert=('capif_ops/certs/dummy.crt', 'capif_ops/certs/invoker_private_key.key'), verify='capif_ops/certs/ca.crt') - print(response.request.body) - response.raise_for_status() - response_payload = json.loads(response.text) - - if log_level == "debug": - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - print(colored(f"Response to: {response.url}","green")) - print(colored(f"Response Headers: {response.headers}","green")) - print(colored(f"Response: {response.json()}","green")) - print(colored(f"Response Status code: {response.status_code}","green")) - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - - return response_payload - except requests.exceptions.HTTPError as err: - print(err.response.text) - message = json.loads(err.response.text) - status = err.response.status_code - raise Exception(message, status) - - def execute_get_security_auth(self, log_level): - - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - - config = configparser.ConfigParser() - config.read('credentials.properties') - - capif_ip = os.getenv('CAPIF_HOSTNAME') - invokerID = demo_values['invokerID'] - capif_access_token = demo_values['capif_access_token'] - ccf_discover_url = demo_values['ccf_discover_url'] - - try: - if 'aef_id_0' in demo_values and 'api_name_0' in demo_values: - token = self.__get_security_token(capif_ip, invokerID, capif_access_token, ccf_discover_url, demo_values['aef_id_0'], demo_values['api_name_0'],log_level) - print(colored(json.dumps(token, indent=2),"yellow")) - demo_values["netapp_service_token"] = token["access_token"] - print(colored("Obtained Security Token","yellow")) - - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - except Exception as e: - status_code = e.args[0] - if status_code == 401: - print("API Invoker is not authorized") - elif status_code == 403: - print("API Invoker does not exist. API Invoker id not found") - else: - print(e) diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_previous_register.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_previous_register.py deleted file mode 100644 index 6a772648c1c862e6a3401941138bc91299d7ae41..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_previous_register.py +++ /dev/null @@ -1,134 +0,0 @@ -import requests -import json -import configparser -import os -from termcolor import colored - -class PreviousRegister(): - - def __register_invoker_to_capif(self, capif_ip, capif_port, username, password, role, description, cn): - - #print(colored("Registering exposer to CAPIF","yellow")) - url = "https://register:8084/register".format(capif_port) - #url = "http://{}:{}/register".format(capif_ip, capif_port) - - payload = dict() - payload['username'] = username - payload['password'] = password - payload['role'] = role - payload['description'] = description - payload['cn'] = cn - - headers = { - 'Content-Type': 'application/json' - } - - try: - # print(colored("''''''''''REQUEST'''''''''''''''''","blue")) - # print(colored(f"Request: to {url}","blue")) - # print(colored(f"Request Headers: {headers}", "blue")) - # print(colored(f"Request Body: {json.dumps(payload)}", "blue")) - # print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - - response = requests.request("POST", url, headers=headers, data=json.dumps(payload), verify=False) - response.raise_for_status() - response_payload = json.loads(response.text) - - # print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - # print(colored(f"Response to: {response.url}","green")) - # print(colored(f"Response Headers: {response.headers}","green")) - # print(colored(f"Response: {response.json()}","green")) - # print(colored(f"Response Status code: {response.status_code}","green")) - # print(colored("Success to register new exposer","green")) - # print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - return response_payload['id'], response_payload['ccf_onboarding_url'], response_payload['ccf_discover_url'], - except requests.exceptions.HTTPError as err: - raise Exception(err.response.status_code) - - - def __get_capif_auth(self, capif_ip, capif_port, username, password): - - #print("Geting Auth to exposer") - url = "https://register:8084/getauth".format(capif_port) - #url = "http://{}:{}/getauth".format(capif_ip, capif_port) - - payload = dict() - payload['username'] = username - payload['password'] = password - - headers = { - 'Content-Type': 'application/json' - } - - try: - # print("''''''''''REQUEST'''''''''''''''''") - # print("Request: to ",url) - # print("Request Headers: ", headers) - # print("Request Body: ", json.dumps(payload)) - # print("''''''''''REQUEST'''''''''''''''''") - - response = requests.request("POST", url, headers=headers, data=json.dumps(payload), verify = False) - - response.raise_for_status() - response_payload = json.loads(response.text) - - # print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - # print(colored(f"Response to: {response.url}","green")) - # print(colored(f"Response Headers: {response.headers}","green")) - # print(colored(f"Response: {response.json()}","green")) - # print(colored(f"Response Status code: {response.status_code}","green")) - # print(colored("Get AUTH Success. Received access token", "green")) - # print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - return response_payload['access_token'] - - except requests.exceptions.HTTPError as err: - raise Exception(err.response.text, err.response.status_code) - - - def execute_previous_register_invoker(self): - - config = configparser.ConfigParser() - config.read('capif_ops/config_files/credentials.properties') - - username = config.get("credentials", "invoker_username") - password = config.get("credentials", "invoker_password") - role = config.get("credentials", "invoker_role") - description = config.get("credentials", "invoker_description") - cn = config.get("credentials", "invoker_cn") - - capif_ip = os.getenv('CAPIF_HOSTNAME') - capif_port = os.getenv('CAPIF_PORT') - - if os.path.exists("capif_ops/config_files/demo_values.json"): - #os.remove("capif_ops/config_files/demo_values.json") - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - else: - demo_values = {} - - #First we need register exposer in CAPIF - try: - netappID, ccf_onboarding_url, ccf_discover_url = self.__register_invoker_to_capif(capif_ip, capif_port, username, password, role, description, cn) - demo_values['netappID'] = netappID - demo_values['ccf_onboarding_url'] = ccf_onboarding_url - demo_values['ccf_discover_url'] = ccf_discover_url - #print(colored(f"NetAppID: {netappID}\n","yellow")) - #print("provider ID: {}".format(providerID)) - - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - if 'netappID' in demo_values: - access_token = self.__get_capif_auth(capif_ip, capif_port, username, password) - demo_values['capif_access_token'] = access_token - - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - except Exception as e: - status_code = e.args[0] - if status_code == 409: - print() - else: - print(e) - - return True diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_register_to_capif.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_register_to_capif.py deleted file mode 100644 index 49be7316a33fdc85a6150fe2bbc00471cfe87f77..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_register_to_capif.py +++ /dev/null @@ -1,134 +0,0 @@ -from dis import dis -import requests -import json -import configparser -import redis -import os -from termcolor import colored - - -from OpenSSL.SSL import FILETYPE_PEM -from OpenSSL.crypto import (dump_certificate_request, dump_privatekey, load_publickey, PKey, TYPE_RSA, X509Req, dump_publickey) - - -class RegisterInvoker(): - def __create_csr(self, name): - - # create public/private key - key = PKey() - key.generate_key(TYPE_RSA, 2048) - - # Generate CSR - req = X509Req() - req.get_subject().CN = name - req.get_subject().O = 'Telefonica I+D' - req.get_subject().OU = 'Innovation' - req.get_subject().L = 'Madrid' - req.get_subject().ST = 'Madrid' - req.get_subject().C = 'ES' - req.get_subject().emailAddress = 'inno@tid.es' - req.set_pubkey(key) - req.sign(key, 'sha256') - - csr_request = dump_certificate_request(FILETYPE_PEM, req) - - private_key = dump_privatekey(FILETYPE_PEM, key) - - return csr_request, private_key - - - - - def __onboard_netapp_to_capif(self, capif_ip, capif_callback_ip, capif_callback_port, jwt_token, ccf_url, log_level): - - print(colored("Onboarding netapp to CAPIF","yellow")) - url = 'https://{}/{}'.format(capif_ip, ccf_url) - - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - - csr_request, private_key = self.__create_csr("invoker") - - if 'pub_key' not in demo_values: - private_key_file = open("capif_ops/certs/invoker_private_key.key", 'wb+') - private_key_file.write(bytes(private_key)) - - json_file = open('capif_ops/config_files/invoker_details.json', 'rb') - payload_dict = json.load(json_file) - if 'pub_key' not in demo_values: - payload_dict['onboardingInformation']['apiInvokerPublicKey'] = csr_request.decode("utf-8") - else: - payload_dict['onboardingInformation']['apiInvokerPublicKey'] = demo_values['pub_key'] - payload_dict['notificationDestination'] = payload_dict['notificationDestination'].replace("X", capif_callback_ip) - payload_dict['notificationDestination'] = payload_dict['notificationDestination'].replace("Y", capif_callback_port) - payload = json.dumps(payload_dict, indent=2) - - print(colored(f"Request Body: {payload}", "yellow")) - - headers = { - 'Authorization': 'Bearer {}'.format(jwt_token), - 'Content-Type': 'application/json' - } - - try: - - if log_level == "debug": - print(colored("''''''''''REQUEST'''''''''''''''''","blue")) - print(colored(f"Request: to {url}","blue")) - print(colored(f"Request Headers: {headers}", "blue")) - print(colored(f"Request Body: {json.dumps(payload)}", "blue")) - print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - - response = requests.request("POST", url, headers=headers, data=payload, verify='capif_ops/certs/ca.crt') - response.raise_for_status() - response_payload = json.loads(response.text) - certification_file = open('capif_ops/certs/dummy.crt', 'wb') - certification_file.write(bytes(response_payload['onboardingInformation']['apiInvokerCertificate'], 'utf-8')) - certification_file.close() - - if log_level == "debug": - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - print(colored(f"Response to: {response.url}","green")) - print(colored(f"Response Headers: {response.headers}","green")) - print(colored(f"Response: {response.json()}","green")) - print(colored(f"Response Status code: {response.status_code}","green")) - print(colored("Success onboard invoker","green")) - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - return response_payload['apiInvokerId'], payload_dict['onboardingInformation']['apiInvokerPublicKey'] - except requests.exceptions.HTTPError as err: - raise Exception(err.response.text, err.response.status_code) - - - - - - def execute_register_invoker(self, log_level): - - config = configparser.ConfigParser() - config.read('capif_ops/config_files/credentials.properties') - - capif_ip = os.getenv('CAPIF_HOSTNAME') - - capif_callback_ip = config.get("credentials", "capif_callback_ip") - capif_callback_port = config.get("credentials", "capif_callback_port") - - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - - try: - capif_access_token = demo_values['capif_access_token'] - ccf_onboarding_url = demo_values['ccf_onboarding_url'] - invokerID, pub_key = self.__onboard_netapp_to_capif(capif_ip, capif_callback_ip, capif_callback_port, capif_access_token, ccf_onboarding_url, log_level) - demo_values['invokerID'] = invokerID - demo_values['pub_key'] = pub_key - print("ApiInvokerID: {}\n".format(invokerID)) - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - except Exception as e: - status_code = e.args[0] - if status_code == 403: - print("Invoker already registered.") - print("Chanage invoker public key in invoker_details.json\n") - else: - print(e) diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_remove_security_context.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_remove_security_context.py deleted file mode 100644 index 18bb3f35966b07492cbe71f2f6cfb1120689d59e..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_remove_security_context.py +++ /dev/null @@ -1,82 +0,0 @@ -from dis import dis -from email import charset -import requests -import json -import configparser -import redis -import os -from termcolor import colored - - -class InvokerRemoveSecurityContext(): - - def __remove_security_service(self, capif_ip, api_invoker_id, jwt_token, ccf_url, demo_values, log_level): - - - url = "https://{}/capif-security/v1/trustedInvokers/{}".format(capif_ip, api_invoker_id) - - headers = { - 'Content-Type': 'application/json' - } - - try: - - if log_level == "debug": - print(colored("''''''''''REQUEST'''''''''''''''''","blue")) - print(colored(f"Request: to {url}","blue")) - print(colored(f"Request Headers: {headers}", "blue")) - print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - - response = requests.delete(url, cert=('capif_ops/certs/dummy.crt', 'capif_ops/certs/invoker_private_key.key'), verify='capif_ops/certs/ca.crt') - response.raise_for_status() - - if log_level == "debug": - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - print(colored(f"Response to: {response.url}","green")) - print(colored(f"Response Headers: {response.headers}","green")) - print(colored(f"Response: {response.json()}","green")) - print(colored(f"Response Status code: {response.status_code}","green")) - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - - return - except requests.exceptions.HTTPError as err: - print(err.response.text) - message = json.loads(err.response.text) - status = err.response.status_code - raise Exception(message, status) - - def execute_remove_security_context(self, log_level): - - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - - config = configparser.ConfigParser() - config.read('credentials.properties') - - capif_ip = os.getenv('CAPIF_HOSTNAME') - invokerID = "" - capif_access_token = "" - ccf_discover_url = "" - - try: - - invokerID = demo_values['invokerID'] - capif_access_token = demo_values['capif_access_token'] - ccf_discover_url = demo_values['ccf_discover_url'] - security_information = self.__remove_security_service(capif_ip, invokerID, capif_access_token, ccf_discover_url, demo_values,log_level) - print(colored(json.dumps(security_information, indent=2),"yellow")) - print(colored("Register Security context","yellow")) - - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - - except Exception as e: - status_code = e.args[0] - if status_code == 401: - print("API Invoker is not authorized") - elif status_code == 403: - print("API Invoker does not exist. API Invoker id not found") - else: - print(e) - diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_secutiry_context.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_secutiry_context.py deleted file mode 100644 index a26988f1c499697d219876e7ee16c2c95b8eef3b..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_secutiry_context.py +++ /dev/null @@ -1,96 +0,0 @@ -from dis import dis -from email import charset -import requests -import json -import configparser -import redis -import os -from termcolor import colored - - -class InvokerSecurityContext(): - - def __register_security_service(self, capif_ip, api_invoker_id, jwt_token, ccf_url, demo_values, log_level): - - - url = "https://{}/capif-security/v1/trustedInvokers/{}".format(capif_ip, api_invoker_id) - - with open('capif_ops/config_files/security_info.json', "rb") as f: - payload = json.load(f) - - count = 0 - for profile in payload["securityInfo"]: - profile["aefId"] = demo_values[f"aef_id_{count}"] - profile["apiId"] = demo_values[f"api_id_{count}"] - count += 1 - - headers = { - 'Content-Type': 'application/json' - } - - # payload_dict = json.dumps(payload, indent=2) - - # print(colored(f"Request Body: {payload_dict}", "yellow")) - - try: - - if log_level == "debug": - print(colored("''''''''''REQUEST'''''''''''''''''","blue")) - print(colored(f"Request: to {url}","blue")) - print(colored(f"Request Headers: {headers}", "blue")) - print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - - response = requests.put(url, json=payload, cert=('capif_ops/certs/dummy.crt', 'capif_ops/certs/invoker_private_key.key'), verify='capif_ops/certs/ca.crt') - response.raise_for_status() - response_payload = response.json() - - if log_level == "debug": - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - print(colored(f"Response to: {response.url}","green")) - print(colored(f"Response Headers: {response.headers}","green")) - print(colored(f"Response: {response.json()}","green")) - print(colored(f"Response Status code: {response.status_code}","green")) - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - - return response_payload - except requests.exceptions.HTTPError as err: - print(err.response.text) - message = json.loads(err.response.text) - status = err.response.status_code - raise Exception(message, status) - - def execute_register_security_context(self, log_level): - - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - - config = configparser.ConfigParser() - config.read('credentials.properties') - - capif_ip = os.getenv('CAPIF_HOSTNAME') - invokerID = "" - capif_access_token = "" - ccf_discover_url = "" - - try: - - invokerID = demo_values['invokerID'] - capif_access_token = demo_values['capif_access_token'] - ccf_discover_url = demo_values['ccf_discover_url'] - security_information = self.__register_security_service(capif_ip, invokerID, capif_access_token, ccf_discover_url, demo_values,log_level) - print(colored(json.dumps(security_information, indent=2),"yellow")) - print(colored("Register Security context","yellow")) - - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - - except Exception as e: - status_code = e.args[0] - if status_code == 401: - print("API Invoker is not authorized") - elif status_code == 403: - print("API Invoker does not exist. API Invoker id not found") - else: - print(e) - diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_to_service.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_to_service.py deleted file mode 100644 index bc54ad7077759696396525433075b004416b97d9..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/invoker_to_service.py +++ /dev/null @@ -1,168 +0,0 @@ -from dis import dis -import requests -import json -import configparser -import redis -import os -import argparse -import re -from termcolor import colored - -# Get environment variables - - -class InvokerToService(): - def __demo_to_aef(self, operation, demo_ip, demo_port, demo_url, jwt_token, name, log_level): - - #def register_netapp_to_nef(nef_ip, nef_port): - access_token_url = "https://{}:{}/api/v1/login/access-token".format(demo_ip, demo_port) - - access_payload = { - "username": "admin@my-email.com", - "password": "pass" - } - - response = requests.request('POST', access_token_url, data=access_payload, verify=False) - parsed = json.loads(response.text) - - access_token = parsed['access_token'] - - print(colored("Using AEF Service API","yellow")) - url = "https://{}:{}{}".format(demo_ip, demo_port, demo_url) - #url = "http://python_aef:8086/hello" - - - - json_file = open('capif_ops/config_files/service_request_body.json', 'rb') - payload_dict = json.load(json_file) - payload = json.dumps(payload_dict, indent=2) - - files = {} - headers = { - 'Content-Type': 'application/json', - 'Authorization': 'Bearer '+ access_token + "," +jwt_token - } - - if operation == "create": - print(colored(f"Request Body: {payload}", "yellow")) - try: - if log_level == "debug": - print(colored("''''''''''REQUEST'''''''''''''''''","blue")) - print(colored(f"Request: to {url}","blue")) - print(colored(f"Request Headers: {headers}", "blue")) - print(colored(f"Request Body: {json.dumps(payload, indent=2)}", "blue")) - print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - response = requests.request("POST", url, headers=headers, data=payload, files=files, verify=False) - response.raise_for_status() - response_payload = json.loads(response.text) - - if log_level == "debug": - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - print(colored(f"Response to: {response.url}","green")) - print(colored(f"Response Headers: {response.headers}","green")) - print(colored(f"Response: {response.json()}","green")) - print(colored(f"Response Status code: {response.status_code}","green")) - print(colored("Success to invoke service","green")) - print(colored(response_payload,"green")) - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - - link_created_resource = response_payload["link"] - resource_id = link_created_resource.rsplit('/', 1)[-1] - if resource_id: - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - demo_values["demo_resource_id"] = resource_id - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - return response_payload - except requests.exceptions.HTTPError as err: - print(err.response.text) - message = json.loads(err.response.text) - status = err.response.status_code - raise Exception(message, status) - - elif operation == "delete": - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - resource_id = demo_values["demo_resource_id"] - if resource_id == "": - print("Not found resource to delete") - return - - url = url + "/" + resource_id - try: - if log_level == "debug": - print(colored("''''''''''REQUEST'''''''''''''''''","blue")) - print(colored(f"Request: to {url}","blue")) - print(colored(f"Request Headers: {headers}", "blue")) - print(colored(f"''''''''''REQUEST'''''''''''''''''", "blue")) - response = requests.request("DELETE", url, headers=headers, verify=False) - response.raise_for_status() - response_payload = json.loads(response.text) - - if log_level == "debug": - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - print(colored(f"Response to: {response.url}","green")) - print(colored(f"Response Headers: {response.headers}","green")) - print(colored(f"Response: {response.json()}","green")) - print(colored(f"Response Status code: {response.status_code}","green")) - print(colored("Success to invoke service","green")) - print(colored(response_payload,"green")) - print(colored("''''''''''RESPONSE'''''''''''''''''","green")) - - demo_values["demo_resource_id"] = "" - with open('capif_ops/config_files/demo_values.json', 'w') as outfile: - json.dump(demo_values, outfile) - - return response_payload - except requests.exceptions.HTTPError as err: - print(err.response.text) - message = json.loads(err.response.text) - status = err.response.status_code - raise Exception(message, status) - - else: - print("You must spicify if you want create or delete resource") - - - def execute_invoker_to_service(self, input): - - # parser = argparse.ArgumentParser() - # parser.add_argument('--name', metavar= "name", type=str, default="Evolve5G", help="Name to send to the aef service") - # args = parser.parse_args() - input_name = "prueba" - operation = "" - log_level = "" - params = input.split() - if len(params) > 0: - operation = params[0] - if len(params) > 1: - log_level = params[1] - - with open('capif_ops/config_files/demo_values.json', 'r') as demo_file: - demo_values = json.load(demo_file) - - try: - if 'netapp_service_token' in demo_values: - - print(colored("Doing test","yellow")) - jwt_token = demo_values['netapp_service_token'] - invokerID = demo_values['invokerID'] - demo_ip = demo_values['demo_ipv4_addr_0'] - #demo_port = demo_values['demo_port_0'] - demo_port = 4443 - demo_url = demo_values['demo_url_0'] - demo_url = re.sub(r'\{scsAsId\}', 'myNetapp', demo_url) - - result = self.__demo_to_aef(operation, demo_ip, demo_port, demo_url, jwt_token, input_name, log_level) - print(colored(f"Response: {json.dumps(result, indent=2)}", "yellow")) - print(colored("Success","yellow")) - except Exception as e: - status_code = e.args[0] - if status_code == 401: - print("API Invoker is not authorized") - elif status_code == 403: - print("API Invoker does not exist. API Invoker id not found") - else: - print(e) \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/nef_calback_server/callback.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/nef_calback_server/callback.py deleted file mode 100644 index 682d35893dd8b8798fea225098779e0f65b07044..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/nef_calback_server/callback.py +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env python3 - -from flask import Flask, jsonify, request -# import redis -# from redis.commands.json.path import Path -import secrets -from werkzeug import serving -import os - - - -app = Flask(__name__) - -COUNTER = 0 - -@app.route("/nefcallbacks", methods=["POST"]) -def nefcallback(): - global COUNTER - COUNTER += 1 - print(f"Notification received from NEF: {COUNTER}") - - return jsonify(message="Receive message"), 200 - - -if __name__ == '__main__': - serving.run_simple('0.0.0.0', 8080, app) \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/main.py b/services/capif-client/CAPIFInvokerGUI/invoker_gui/main.py deleted file mode 100644 index bed7c8bcd6b02ac4ba0ffda5d42552040f7b505d..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/main.py +++ /dev/null @@ -1,98 +0,0 @@ - -from cmd import Cmd -from capif_ops.invoker_previous_register import PreviousRegister -from capif_ops.invoker_register_to_capif import RegisterInvoker -from capif_ops.invoker_discover_service import DiscoverService -from capif_ops.invoker_secutiry_context import InvokerSecurityContext -from capif_ops.invoker_get_security_auth import InvokerGetSecurityAuth -from capif_ops.invoker_delete import RemoveInvoker -from capif_ops.invoker_get_auth import PreviousAuth -from capif_ops.invoker_remove_security_context import InvokerRemoveSecurityContext -from capif_ops.invoker_to_service import InvokerToService -import shlex -import subprocess -from art import * - -prev_register = PreviousRegister() -regiter_capif = RegisterInvoker() -discover_service = DiscoverService() -register_security_context = InvokerSecurityContext() -security_context_auth = InvokerGetSecurityAuth() -remove_invoker = RemoveInvoker() -invoker_auth = PreviousAuth() -remove_security_service = InvokerRemoveSecurityContext() -invoker_service = InvokerToService() - - - -class CAPIFProvider(Cmd): - - def __init__(self): - Cmd.__init__(self) - self.prompt = "> " - self.intro = tprint("Welcome to Invoker Console") - - def emptyline(self): - """Do nothing on empty input line""" - pass - - def preloop(self): - state = prev_register.execute_previous_register_invoker() - self.previous_register_state = state - - def precmd(self, line): - - line = line.lower() - args = shlex.split(line) - - if len(args) >= 1 and args[0] in ["goodbye"]: - print("The first argument is username") - return "" - - elif len(args) >= 1 and args[0] not in ["->", "wall", "follows", "exit", "help"]: - pass - - return line - - def do_register_invoker(self, input): - 'Register invoker to CAPIF' - regiter_capif.execute_register_invoker(input) - - def do_discover_service(self, input): - 'Discover all services published in CAPIF' - discover_service.execute_discover_service(input) - - def do_register_security_context(self, input): - 'Create security context to use services' - register_security_context.execute_register_security_context(input) - - def do_get_security_auth(self, input): - "If you select Oauth as security method use this command to obtain jwt token to access service" - security_context_auth.execute_get_security_auth(input) - - def do_get_auth(self, input): - 'Get jwt token to register invoker in CAPIF (Optional, only if token expires)' - invoker_auth.execute_get_auth(input) - - def do_remove_security_context(self, input): - print("Not implemented yet") - #remove_security_service.execute_remove_security_context(input) - - def do_remove_invoker(self, input): - "Remove invoker from CAPIF" - remove_invoker.execute_remove_invoker(input) - - def do_call_service(self, input): - "Test invocation os service API" - invoker_service.execute_invoker_to_service(input) - - def do_exit(self, input): - print('\nExiting...') - return True - - -if __name__ == '__main__': - try: - CAPIFProvider().cmdloop() - except KeyboardInterrupt: - print('\nExiting...') \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/prepare.sh b/services/capif-client/CAPIFInvokerGUI/invoker_gui/prepare.sh deleted file mode 100755 index ca0305a044b9c7aa9f6d60a88bac3c4f13707fc0..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/prepare.sh +++ /dev/null @@ -1,11 +0,0 @@ -VAULT_ADDR="http://$VAULT_HOSTNAME:$VAULT_PORT" -VAULT_TOKEN=$VAULT_ACCESS_TOKEN - -curl -k -retry 30 \ - --retry-all-errors \ - --connect-timeout 5 \ - --max-time 10 \ - --retry-delay 10 \ - --retry-max-time 300 \ - --header "X-Vault-Token: $VAULT_TOKEN" \ - --request GET "$VAULT_ADDR/v1/secret/data/ca" 2>/dev/null | jq -r '.data.data.ca' -j > ./capif_ops/certs/ca.crt \ No newline at end of file diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/requirements.txt b/services/capif-client/CAPIFInvokerGUI/invoker_gui/requirements.txt deleted file mode 100755 index a9e6ededb6f821c6f5a8c6b991c68a4032dc5fad..0000000000000000000000000000000000000000 --- a/services/capif-client/CAPIFInvokerGUI/invoker_gui/requirements.txt +++ /dev/null @@ -1,13 +0,0 @@ -requests == 2.26.0 -evolved5g >= 0.8.9 -python_dateutil >= 2.6.0 -setuptools >= 21.0.0 -Flask -watchdog -redis -configparser -redis -pyopenssl -pyjwt -art -termcolor \ No newline at end of file diff --git a/services/capif-client/Dockerfile b/services/capif-client/Dockerfile deleted file mode 100644 index ad7e50339036e5012ef65b99bf89c66a747be050..0000000000000000000000000000000000000000 --- a/services/capif-client/Dockerfile +++ /dev/null @@ -1,5 +0,0 @@ -FROM public.ecr.aws/o2v4a8t6/opencapif/client:3.1.3 - -COPY ./CAPIFInvokerGUI . -RUN pip3 install -r ./invoker_gui/requirements.txt -CMD ["sleep", "infinity"] \ No newline at end of file diff --git a/services/check_services_are_running.sh b/services/check_services_are_running.sh index 53e8e6daccc681261cc14d5e1b83b17f4ab52a31..16de7046452f3faa4ab94b04e340def03d89d9d4 100755 --- a/services/check_services_are_running.sh +++ b/services/check_services_are_running.sh @@ -1,12 +1,39 @@ #!/bin/bash -running="$(docker-compose -f docker-compose-capif.yml ps --services --all --filter "status=running")" -services="$(docker-compose -f docker-compose-capif.yml ps --services --all)" +export CAPIF_PRIV_KEY= +export CAPIF_PRIV_KEY_BASE_64= +export MONITORING= + +running="$(docker compose -f docker-compose-vault.yml ps --services --all --filter "status=running")" +services="$(docker compose -f docker-compose-vault.yml ps --services --all)" if [ "$running" != "$services" ]; then - echo "Following services are not running:" + echo "Following Vault services are not running:" # Bash specific comm -13 <(sort <<<"$running") <(sort <<<"$services") exit 1 else - echo "All services are running" - exit 0 + echo "All Vault services are running" fi + +running="$(docker compose -f docker-compose-capif.yml ps --services --all --filter "status=running")" +services="$(docker compose -f docker-compose-capif.yml ps --services --all)" +if [ "$running" != "$services" ]; then + echo "Following CCF services are not running:" + # Bash specific + comm -13 <(sort <<<"$running") <(sort <<<"$services") + exit 1 +else + echo "All CCF services are running" +fi + +running="$(docker compose -f docker-compose-register.yml ps --services --all --filter "status=running")" +services="$(docker compose -f docker-compose-register.yml ps --services --all)" +if [ "$running" != "$services" ]; then + echo "Following Register services are not running:" + # Bash specific + comm -13 <(sort <<<"$running") <(sort <<<"$services") + exit 1 +else + echo "All Register services are running" +fi + +exit 0 diff --git a/services/clean_capif_docker_services.sh b/services/clean_capif_docker_services.sh index 7b3c91e031803c15e0443b7e3da2c6a38d391633..bd6ef111f010c8d5ed962a7c575fe2adfa32bbc1 100755 --- a/services/clean_capif_docker_services.sh +++ b/services/clean_capif_docker_services.sh @@ -6,6 +6,7 @@ help() { echo " -v : Clean vault service" echo " -r : Clean register service" echo " -m : Clean monitoring service" + echo " -s : Clean Robot Mock service" echo " -a : Clean all services" echo " -h : show this help" exit 1 @@ -21,7 +22,7 @@ FILES=() echo "${FILES[@]}" # Read params -while getopts "cvrahm" opt; do +while getopts "cvrahms" opt; do case $opt in c) echo "Remove Capif services" @@ -39,9 +40,13 @@ while getopts "cvrahm" opt; do echo "Remove monitoring service" FILES+=("../monitoring/docker-compose.yml") ;; + s) + echo "Robot Mock Server" + FILES+=("docker-compose-mock-server.yml") + ;; a) echo "Remove all services" - FILES=("docker-compose-capif.yml" "docker-compose-vault.yml" "docker-compose-register.yml" "../monitoring/docker-compose.yml") + FILES=("docker-compose-capif.yml" "docker-compose-vault.yml" "docker-compose-register.yml" "docker-compose-mock-server.yml" "../monitoring/docker-compose.yml") ;; h) help @@ -62,8 +67,8 @@ echo "after check" echo "${FILES[@]}" for FILE in "${FILES[@]}"; do - echo "Executing 'docker-compose down' for file $FILE" - docker-compose -f "$FILE" down --rmi all + echo "Executing 'docker compose down' for file $FILE" + CAPIF_PRIV_KEY=$CAPIF_PRIV_KEY_BASE_64 DUID=$DUID DGID=$DGID MONITORING=$MONITORING_STATE LOG_LEVEL=$LOG_LEVEL docker compose -f "$FILE" down --rmi all status=$? if [ $status -eq 0 ]; then echo "*** Removed Service from $FILE ***" @@ -74,4 +79,6 @@ done docker network rm capif-network +docker volume prune --all --force + echo "Clean complete." diff --git a/services/clean_capif_temporary_files.sh b/services/clean_capif_temporary_files.sh new file mode 100755 index 0000000000000000000000000000000000000000..4becd8bfd896c5d6b9bb5e24cd4620abb3cd3328 --- /dev/null +++ b/services/clean_capif_temporary_files.sh @@ -0,0 +1,85 @@ +#!/bin/bash + +help() { + echo "Usage: $1 " + echo " -c : Clean capif services tmp files" + echo " -m : Clean monitoring service tmp files" + echo " -t : Clean robot-test service tmp files" + echo " -d : Clean docs folder tmp files" + echo " -a : Clean all tmp files" + echo " -h : show this help" + exit 1 +} + +if [[ $# -lt 1 ]] +then + echo "You must specify an option before run script." + help +fi + + +FILES=() +echo "${FILES[@]}" + +# Read params +while getopts "cmtdah" opt; do + case $opt in + c) + echo "Remove capif services temporary files" + FILES+=("services") + ;; + m) + echo "Remove monitoring service temporary files" + FILES+=("monitoring") + ;; + t) + echo "Remove robot-test service temporary files" + FILES+=("tests") + ;; + d) + echo "Remove docs folder temporary files" + FILES+=("docs") + ;; + a) + echo "Remove all temporary files" + FILES=("services" "monitoring" "tests" "docs") + ;; + h) + help + ;; + \?) + echo "Not valid option: -$OPTARG" >&2 + help + exit 1 + ;; + :) + echo "The -$OPTARG option requires an argument." >&2 + help + exit 1 + ;; + esac +done +echo "after check" +echo "${FILES[@]}" + +cd .. + +for FILE in "${FILES[@]}"; do + echo "Remove temporary files for $FILE" + tmp_files=$(git ls-files . --ignored --exclude-standard --others --directory | grep $FILE) + if [[ $tmp_files ]]; then + sudo rm -r $tmp_files + status=$? + if [ $status -eq 0 ]; then + echo "*** Removed tmp files from $FILE ***" + else + echo "*** Some files from $FILE failed on removing ***" + fi + else + echo "No files found" + fi +done + + +echo "Remove tmp files complete." +cd ./services \ No newline at end of file diff --git a/services/clean_mock_server.sh b/services/clean_mock_server.sh new file mode 100755 index 0000000000000000000000000000000000000000..5ea886cdee5476d39a20440d1f2a27f3e49a0857 --- /dev/null +++ b/services/clean_mock_server.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +FILE="docker-compose-mock-server.yml" + +echo "Executing 'docker compose down' for file $FILE" +docker compose -f "$FILE" down --rmi all +status=$? + if [ $status -eq 0 ]; then + echo "*** Removed Service from $FILE ***" + else + echo "*** Some services of $FILE failed on clean ***" + fi + +docker volume prune --all --force + +echo "Clean complete." diff --git a/services/docker-compose-capif.yml b/services/docker-compose-capif.yml index d5521053d741f697631f538f3386052b4f72e2d1..44ed625fcc13b5d64606b5316272bb989713ba4b 100644 --- a/services/docker-compose-capif.yml +++ b/services/docker-compose-capif.yml @@ -1,5 +1,3 @@ -version: '3.7' - services: redis: image: "redis:alpine" @@ -11,6 +9,31 @@ services: - $PWD/redis.conf:/usr/local/etc/redis/redis.conf environment: - REDIS_REPLICATION_MODE=master + + + helper: + build: + context: ./helper + expose: + - "8080" + container_name: helper + restart: unless-stopped + volumes: + - ./helper:/usr/src/app + extra_hosts: + - host.docker.internal:host-gateway + - fluent-bit:host-gateway + - otel-collector:host-gateway + - vault:host-gateway + environment: + - CAPIF_HOSTNAME=${CAPIF_HOSTNAME} + - CONTAINER_NAME=helper + - VAULT_HOSTNAME=vault + - VAULT_ACCESS_TOKEN=dev-only-token + - VAULT_PORT=8200 + - LOG_LEVEL=${LOG_LEVEL} + depends_on: + - nginx access-control-policy: build: TS29222_CAPIF_Access_Control_Policy_API @@ -25,12 +48,12 @@ services: environment: - CONTAINER_NAME=access-control-policy - MONITORING=${MONITORING} + - LOG_LEVEL=${LOG_LEVEL} restart: unless-stopped image: public.ecr.aws/o2v4a8t6/opencapif/access-control-policy:3.1.3 depends_on: - redis - nginx - api-invoker-management: build: @@ -50,6 +73,7 @@ services: - VAULT_HOSTNAME=vault - VAULT_ACCESS_TOKEN=dev-only-token - VAULT_PORT=8200 + - LOG_LEVEL=${LOG_LEVEL} restart: unless-stopped image: public.ecr.aws/o2v4a8t6/opencapif/api-invoker-management-api:3.1.3 depends_on: @@ -74,6 +98,7 @@ services: - VAULT_HOSTNAME=vault - VAULT_ACCESS_TOKEN=dev-only-token - VAULT_PORT=8200 + - LOG_LEVEL=${LOG_LEVEL} depends_on: - redis - nginx @@ -94,6 +119,7 @@ services: environment: - CONTAINER_NAME=api-auditing - MONITORING=${MONITORING} + - LOG_LEVEL=${LOG_LEVEL} depends_on: - mongo @@ -113,6 +139,7 @@ services: environment: - CONTAINER_NAME=services-apis - MONITORING=${MONITORING} + - LOG_LEVEL=${LOG_LEVEL} depends_on: - mongo @@ -126,6 +153,7 @@ services: environment: - CONTAINER_NAME=api-events - MONITORING=${MONITORING} + - LOG_LEVEL=${LOG_LEVEL} extra_hosts: - host.docker.internal:host-gateway - fluent-bit:host-gateway @@ -151,6 +179,7 @@ services: - CAPIF_HOSTNAME=${CAPIF_HOSTNAME} - CONTAINER_NAME=api-invocation-logs - MONITORING=${MONITORING} + - LOG_LEVEL=${LOG_LEVEL} depends_on: - mongo @@ -169,6 +198,7 @@ services: environment: - CONTAINER_NAME=api-publish-apis - MONITORING=${MONITORING} + - LOG_LEVEL=${LOG_LEVEL} depends_on: - redis - mongo @@ -194,6 +224,7 @@ services: - VAULT_HOSTNAME=vault - VAULT_ACCESS_TOKEN=dev-only-token - VAULT_PORT=8200 + - LOG_LEVEL=${LOG_LEVEL} extra_hosts: - host.docker.internal:host-gateway - fluent-bit:host-gateway @@ -220,6 +251,9 @@ services: ports: - 8082:8081 environment: + ME_CONFIG_MONGODB_ENABLE_ADMIN: true + ME_CONFIG_BASICAUTH_USERNAME: admin + ME_CONFIG_BASICAUTH_PASSWORD: admin ME_CONFIG_MONGODB_ADMINUSERNAME: root ME_CONFIG_MONGODB_ADMINPASSWORD: example ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo:27017/ @@ -238,6 +272,7 @@ services: - VAULT_HOSTNAME=vault - VAULT_ACCESS_TOKEN=dev-only-token - VAULT_PORT=8200 + - LOG_LEVEL=${LOG_LEVEL} hostname: ${CAPIF_HOSTNAME} volumes: - ./nginx/certs:/etc/nginx/certs diff --git a/services/docker-compose-mock-server.yml b/services/docker-compose-mock-server.yml new file mode 100644 index 0000000000000000000000000000000000000000..1415b439bb1eec214b6adbd5af74812432544bf1 --- /dev/null +++ b/services/docker-compose-mock-server.yml @@ -0,0 +1,20 @@ +services: + mock-server: + build: + context: ./mock_server + ports: + - 9090:9090 + volumes: + - ./mock_server:/usr/src/app + extra_hosts: + - host.docker.internal:host-gateway + restart: unless-stopped + image: public.ecr.aws/o2v4a8t6/opencapif/mock_server:latest + +networks: + default: + name: capif-network + external: true + + + diff --git a/services/docker-compose-register.yml b/services/docker-compose-register.yml index 173d66172864206aa0ea23e4a4735a9f5e3abb62..53ed1017428ae03d3ab074c7378884ce9d871ba3 100644 --- a/services/docker-compose-register.yml +++ b/services/docker-compose-register.yml @@ -1,5 +1,3 @@ -version: '3.7' - services: register: build: @@ -13,6 +11,7 @@ services: - VAULT_HOSTNAME=vault - VAULT_ACCESS_TOKEN=dev-only-token - VAULT_PORT=8200 + - LOG_LEVEL=${LOG_LEVEL} extra_hosts: - host.docker.internal:host-gateway - vault:host-gateway @@ -23,6 +22,8 @@ services: mongo_register: image: mongo:6.0.2 + logging: + driver: 'none' restart: unless-stopped environment: MONGO_INITDB_ROOT_USERNAME: root @@ -36,6 +37,9 @@ services: ports: - 8083:8081 environment: + ME_CONFIG_MONGODB_ENABLE_ADMIN: true + ME_CONFIG_BASICAUTH_USERNAME: admin + ME_CONFIG_BASICAUTH_PASSWORD: admin ME_CONFIG_MONGODB_ADMINUSERNAME: root ME_CONFIG_MONGODB_ADMINPASSWORD: example ME_CONFIG_MONGODB_URL: mongodb://root:example@mongo_register:27017/ diff --git a/services/docker-compose-vault.yml b/services/docker-compose-vault.yml index e0bb7bce196fde18748da2967cb1b94485b2ef59..82a38d0a8dd9d728c74a44ffe131ae272c34f211 100644 --- a/services/docker-compose-vault.yml +++ b/services/docker-compose-vault.yml @@ -1,4 +1,3 @@ -version: '3.7' services: vault: build: diff --git a/services/helper/Dockerfile b/services/helper/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..36439567b9077997dac2b88cb1f362d3affd77e2 --- /dev/null +++ b/services/helper/Dockerfile @@ -0,0 +1,16 @@ +FROM public.ecr.aws/o2v4a8t6/opencapif/python:3-alpine + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +COPY requirements.txt /usr/src/app/requirements.txt + +RUN apk add -U --no-cache gcc build-base linux-headers ca-certificates libffi-dev libressl-dev libxslt-dev +RUN pip3 install --no-cache-dir -r requirements.txt +RUN apk add openssl curl redis + +COPY . /usr/src/app + +EXPOSE 8080 + +CMD ["sh", "prepare_helper.sh"] diff --git a/services/helper/config.yaml b/services/helper/config.yaml new file mode 100644 index 0000000000000000000000000000000000000000..bb090f086263a17001d9952b13befc7030696ef6 --- /dev/null +++ b/services/helper/config.yaml @@ -0,0 +1,19 @@ +mongo: { + 'user': 'root', + 'password': 'example', + 'db': 'capif', + 'invoker_col': 'invokerdetails', + 'provider_col': 'providerenrolmentdetails', + 'col_services': "serviceapidescriptions", + 'col_security': "security", + 'col_event': "eventsdetails", + 'host': 'mongo', + 'port': "27017" +} + +ca_factory: { + "url": "vault", + "port": "8200", + "token": "dev-only-token", + "verify": False +} diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/__init__.py b/services/helper/helper_service/__init__.py similarity index 100% rename from services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/__init__.py rename to services/helper/helper_service/__init__.py diff --git a/services/helper/helper_service/app.py b/services/helper/helper_service/app.py new file mode 100644 index 0000000000000000000000000000000000000000..e7a65ec22d813f5530e4af8e6bac5da96e81f372 --- /dev/null +++ b/services/helper/helper_service/app.py @@ -0,0 +1,70 @@ +from flask import Flask +import logging +from controllers.helper_controller import helper_routes +from OpenSSL.crypto import PKey, TYPE_RSA, X509Req, dump_certificate_request, FILETYPE_PEM, dump_privatekey +from config import Config +import json +import requests +import os + +app = Flask(__name__) +config = Config().get_config() + +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + +# Create a superadmin CSR and keys +key = PKey() +key.generate_key(TYPE_RSA, 2048) +req = X509Req() +req.get_subject().O = 'OCF helper' +req.get_subject().OU = 'helper' +req.get_subject().L = 'Madrid' +req.get_subject().ST = 'Madrid' +req.get_subject().C = 'ES' +req.get_subject().emailAddress = 'helper@tid.es' +req.set_pubkey(key) +req.sign(key, 'sha256') + +csr_request = dump_certificate_request(FILETYPE_PEM, req) +private_key = dump_privatekey(FILETYPE_PEM, key) + +# Save superadmin private key +key_file = open("certs/superadmin.key", 'wb+') +key_file.write(bytes(private_key)) +key_file.close() + +# Request superadmin certificate +url = 'http://{}:{}/v1/pki_int/sign/my-ca'.format(config["ca_factory"]["url"], config["ca_factory"]["port"]) +headers = {'X-Vault-Token': f"{config["ca_factory"]["token"]}"} +data = { + 'format':'pem_bundle', + 'ttl': '43000h', + 'csr': csr_request, + 'common_name': "superadmin" +} + +response = requests.request("POST", url, headers=headers, data=data, verify = config["ca_factory"].get("verify", False)) +superadmin_cert = json.loads(response.text)['data']['certificate'] + +# Save the superadmin certificate +cert_file = open("certs/superadmin.crt", 'wb') +cert_file.write(bytes(superadmin_cert, 'utf-8')) +cert_file.close() + +url = f"http://{config['ca_factory']['url']}:{config['ca_factory']['port']}/v1/secret/data/ca" +headers = { + + 'X-Vault-Token': config['ca_factory']['token'] +} +response = requests.request("GET", url, headers=headers, verify = config["ca_factory"].get("verify", False)) + +ca_root = json.loads(response.text)['data']['data']['ca'] +cert_file = open("certs/ca_root.crt", 'wb') +cert_file.write(bytes(ca_root, 'utf-8')) +cert_file.close() + +app.register_blueprint(helper_routes) +app.logger.setLevel(numeric_level) + diff --git a/services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/nef_calback_server/__init__.py b/services/helper/helper_service/certs/.gitkeep similarity index 100% rename from services/capif-client/CAPIFInvokerGUI/invoker_gui/capif_ops/nef_calback_server/__init__.py rename to services/helper/helper_service/certs/.gitkeep diff --git a/services/helper/helper_service/config.py b/services/helper/helper_service/config.py new file mode 100644 index 0000000000000000000000000000000000000000..f9574a678498483f4e138d4890fc1fa079cebce4 --- /dev/null +++ b/services/helper/helper_service/config.py @@ -0,0 +1,20 @@ +import yaml +import os + +#Config class to get config +class Config: + def __init__(self): + self.cached = 0 + self.file="../config.yaml" + self.my_config = {} + + stamp = os.stat(self.file).st_mtime + if stamp != self.cached: + self.cached = stamp + f = open(self.file) + self.my_config = yaml.safe_load(f) + f.close() + + def get_config(self): + return self.my_config + diff --git a/services/helper/helper_service/controllers/helper_controller.py b/services/helper/helper_service/controllers/helper_controller.py new file mode 100644 index 0000000000000000000000000000000000000000..f645a564ca88eb238ced5784cdc5ff2450910075 --- /dev/null +++ b/services/helper/helper_service/controllers/helper_controller.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python3 + +from flask import Blueprint, request, current_app, jsonify +from core.helper_operations import HelperOperations +from config import Config + +config = Config().get_config() + +helper_routes = Blueprint("helper_routes", __name__) +helper_operation = HelperOperations() + +@helper_routes.route("/helper/getInvokers", methods=["GET"]) +def getInvokers(): + uuid = request.args.get('uuid') + invoker_id = request.args.get('api_invoker_id') + page_size = request.args.get('page_size') + page = request.args.get('page') + sort_order = request.args.get('sort_order') + if page_size: + page_size = int(page_size) + if page_size < 0: + return jsonify(message="The value of the page_size parameter must be greater than 0"), 400 + if page: + page = int(page) + if page < 0: + return jsonify(message="The value of the page parameter must be greater than 0"), 400 + + current_app.logger.debug(f"uuid: {uuid}, invoker_id: {invoker_id}, page: {page}, page_size: {page_size}, sort_order: {sort_order}") + + return helper_operation.get_invokers(uuid, invoker_id, page, page_size, sort_order) + +@helper_routes.route("/helper/getProviders", methods=["GET"]) +def getProviders(): + uuid = request.args.get('uuid') + provider_id = request.args.get('api_prov_dom_id') + page_size = request.args.get('page_size') + page = request.args.get('page') + sort_order = request.args.get('sort_order') + + if page_size: + page_size = int(page_size) + if page_size < 0: + return jsonify(message="The value of the page_size parameter must be greater than 0"), 400 + if page: + page = int(page) + if page < 0: + return jsonify(message="The value of the page parameter must be greater than 0"), 400 + + current_app.logger.debug(f"uuid: {uuid}, provider_id: {provider_id}, page: {page}, page_size: {page_size}, sort_order: {sort_order}") + + return helper_operation.get_providers(uuid, provider_id, page, page_size, sort_order) + + +@helper_routes.route("/helper/getServices", methods=["GET"]) +def getServices(): + service_id = request.args.get('service_id') + apf_id = request.args.get('apf_id') + api_name = request.args.get('api_name') + page_size = request.args.get('page_size') + page = request.args.get('page') + sort_order = request.args.get('sort_order') + if page_size: + page_size = int(page_size) + if page_size < 0: + return jsonify(message="The value of the page_size parameter must be greater than 0"), 400 + if page: + page = int(page) + if page < 0: + return jsonify(message="The value of the page parameter must be greater than 0"), 400 + + current_app.logger.debug(f"service_id: {service_id}, apf_id: {apf_id}, api_name: {api_name}, page: {page}, page_size: {page_size}, sort_order: {sort_order}") + + return helper_operation.get_services(service_id, apf_id, api_name, page, page_size, sort_order) + +@helper_routes.route("/helper/getSecurity", methods=["GET"]) +def getSecurity(): + invoker_id = request.args.get('invoker_id') + page_size = request.args.get('page_size') + page = request.args.get('page') + if page_size: + page_size = int(page_size) + if page_size < 0: + return jsonify(message="The value of the page_size parameter must be greater than 0"), 400 + if page: + page = int(page) + if page < 0: + return jsonify(message="The value of the page parameter must be greater than 0"), 400 + + current_app.logger.debug(f"invoker_id: {invoker_id}, page: {page}, page_size: {page_size} ") + + return helper_operation.get_security(invoker_id, page, page_size) + +@helper_routes.route("/helper/getEvents", methods=["GET"]) +def getEvents(): + subscriber_id = request.args.get('subscriber_id') + subscription_id = request.args.get('subscription_id') + page_size = request.args.get('page_size') + page = request.args.get('page') + if page_size: + page_size = int(page_size) + if page_size < 0: + return jsonify(message="The value of the page_size parameter must be greater than 0"), 400 + if page: + page = int(page) + if page < 0: + return jsonify(message="The value of the page parameter must be greater than 0"), 400 + + current_app.logger.debug(f"subscriber_id: {subscriber_id}, subscription_id: {subscription_id}, page: {page}, page_size: {page_size} ") + + return helper_operation.get_events(subscriber_id, subscription_id, page, page_size) + + +@helper_routes.route("/helper/deleteEntities/", methods=["DELETE"]) +def deleteUserEntities(uuid): + return helper_operation.remove_entities(uuid) diff --git a/services/helper/helper_service/core/helper_operations.py b/services/helper/helper_service/core/helper_operations.py new file mode 100644 index 0000000000000000000000000000000000000000..9e6354675ae348efbd5b9f47c940f6145f371103 --- /dev/null +++ b/services/helper/helper_service/core/helper_operations.py @@ -0,0 +1,204 @@ +from flask import jsonify, current_app +import pymongo +from db.db import MongoDatabse +from config import Config +import requests +import os + +class HelperOperations: + + def __init__(self): + self.db = MongoDatabse() + self.mimetype = 'application/json' + self.config = Config().get_config() + + def get_invokers(self, uuid, invoker_id, page, page_size, sort_order): + current_app.logger.debug(f"Getting the invokers") + invoker_col = self.db.get_col_by_name(self.db.invoker_col) + + total_invokers = invoker_col.count_documents({}) + + filter = {} + if uuid: + filter["uuid"]=uuid + if invoker_id: + filter["api_invoker_id"]=invoker_id + + sort_direction = pymongo.DESCENDING if sort_order == "desc" else pymongo.ASCENDING + + if page_size and page: + index = (page - 1) * page_size + documents = invoker_col.find(filter,{"_id":0}).sort("onboarding_date", sort_direction).skip(index).limit(page_size) + pages = (total_invokers + page_size - 1) // page_size + else: + documents = invoker_col.find(filter,{"_id":0}).sort("onboarding_date", sort_direction) + pages = 1 + + list_invokers= list(documents) + long = len(list_invokers) + + return jsonify(message="Invokers returned successfully", + invokers=list_invokers, + total = total_invokers, + long = long, + totalPages = pages, + sortOrder = sort_order), 200 + + + def get_providers(self, uuid, provider_id, page, page_size, sort_order): + current_app.logger.debug(f"Getting the providers") + provider_col = self.db.get_col_by_name(self.db.provider_col) + + total_providers = provider_col.count_documents({}) + + filter = {} + if uuid: + filter["uuid"]=uuid + if provider_id: + filter["api_prov_dom_id"]=provider_id + + sort_direction = pymongo.DESCENDING if sort_order == "desc" else pymongo.ASCENDING + + if page_size and page: + index = (page - 1) * page_size + documents = provider_col.find(filter,{"_id":0}).sort("onboarding_date", sort_direction).skip(index).limit(page_size) + pages = (total_providers + page_size - 1) // page_size + else: + documents = provider_col.find(filter,{"_id":0}).sort("onboarding_date", sort_direction) + pages = 1 + + list_providers = list(documents) + long = len(list_providers) + + return jsonify(message="Providers returned successfully", + providers=list_providers, + total = total_providers, + long = long, + totalPages = pages, + sortOrder = sort_order), 200 + + def get_services(self, service_id, apf_id, api_name, page, page_size, sort_order): + current_app.logger.debug(f"Getting the services") + service_col = self.db.get_col_by_name(self.db.services_col) + + total_services = service_col.count_documents({}) + + filter = {} + if service_id: + filter["api_id"]=service_id + if apf_id: + filter["apf_id"]=apf_id + if api_name: + filter["api_name"]=api_name + + sort_direction = pymongo.DESCENDING if sort_order == "desc" else pymongo.ASCENDING + + if page_size and page: + index = (page - 1) * page_size + documents = service_col.find(filter,{"_id":0}).sort("onboarding_date", sort_direction).skip(index).limit(page_size) + pages = (total_services + page_size - 1) // page_size + else: + documents = service_col.find(filter,{"_id":0}).sort("onboarding_date", sort_direction) + pages = 1 + + list_services= list(documents) + long = len(list_services) + + return jsonify(message="Services returned successfully", + services=list_services, + total = total_services, + long = long, + totalPages = pages, + sortOrder = sort_order), 200 + + def get_security(self, invoker_id, page, page_size): + current_app.logger.debug(f"Getting the security context") + security_col = self.db.get_col_by_name(self.db.security_context_col) + + total_security = security_col.count_documents({}) + + filter = {} + + if invoker_id: + filter["api_invoker_id"]=invoker_id + + if page_size and page: + index = (page - 1) * page_size + documents = security_col.find(filter,{"_id":0}).skip(index).limit(page_size) + pages = (total_security + page_size - 1) // page_size + else: + documents = security_col.find(filter,{"_id":0}) + pages = 1 + + list_security= list(documents) + long = len(list_security) + + return jsonify(message="Security context returned successfully", + security=list_security, + total = total_security, + long = long, + totalPages = pages), 200 + + def get_events(self, subscriber_id, subscription_id, page, page_size): + current_app.logger.debug(f"Getting the events") + events_col = self.db.get_col_by_name(self.db.events) + + total_events = events_col.count_documents({}) + + filter = {} + + if subscriber_id: + filter["subscriber_id"]=subscriber_id + if subscription_id: + filter["subscription_id"]=subscription_id + + if page_size and page: + index = (page - 1) * page_size + documents = events_col.find(filter,{"_id":0}).skip(index).limit(page_size) + pages = (total_events + page_size - 1) // page_size + else: + documents = events_col.find(filter,{"_id":0}) + pages = 1 + + list_events= list(documents) + long = len(list_events) + + return jsonify(message="Events returned successfully", + events=list_events, + total = total_events, + long = long, + totalPages = pages), 200 + + def remove_entities(self, uuid): + + current_app.logger.debug(f"Removing entities for uuid: {uuid}") + invoker_col = self.db.get_col_by_name(self.db.invoker_col) + provider_col = self.db.get_col_by_name(self.db.provider_col) + + try: + if invoker_col.count_documents({'uuid':uuid}) == 0 and provider_col.count_documents({'uuid':uuid}) == 0: + current_app.logger.debug(f"No entities found for uuid: {uuid}") + return jsonify(message=f"No entities found for uuid: {uuid}"), 204 + + for invoker in invoker_col.find({'uuid':uuid}, {"_id":0}): + current_app.logger.debug(f"Removing Invoker: {invoker["api_invoker_id"]}") + url = 'https://{}/api-invoker-management/v1/onboardedInvokers/{}'.format(os.getenv('CAPIF_HOSTNAME'), invoker["api_invoker_id"]) + requests.request("DELETE", url, cert=( + '/usr/src/app/helper_service/certs/superadmin.crt', '/usr/src/app/helper_service/certs/superadmin.key'), verify='/usr/src/app/helper_service/certs/ca_root.crt') + + for provider in provider_col.find({'uuid':uuid}, {"_id":0}): + current_app.logger.debug(f"Removing Provider: {provider["api_prov_dom_id"]}") + url = 'https://{}/api-provider-management/v1/registrations/{}'.format(os.getenv('CAPIF_HOSTNAME'), provider["api_prov_dom_id"]) + + requests.request("DELETE", url, cert=( + '/usr/src/app/helper_service/certs/superadmin.crt', '/usr/src/app/helper_service/certs/superadmin.key'), verify='/usr/src/app/helper_service/certs/ca_root.crt') + except Exception as e: + current_app.logger.debug(f"Error deleting user entities: {e}") + jsonify(message=f"Error deleting user entities: {e}"), 500 + + current_app.logger.debug(f"User entities removed successfully") + return jsonify(message="User entities removed successfully"), 200 + + + + diff --git a/services/helper/helper_service/db/db.py b/services/helper/helper_service/db/db.py new file mode 100644 index 0000000000000000000000000000000000000000..bb2853ef6638b8d2294edbd8d7d1c2c225c8a061 --- /dev/null +++ b/services/helper/helper_service/db/db.py @@ -0,0 +1,45 @@ +import time +from pymongo import MongoClient +from pymongo.errors import AutoReconnect +from config import Config +from bson.codec_options import CodecOptions + +class MongoDatabse(): + + def __init__(self): + self.config = Config().get_config() + self.db = self.__connect() + self.invoker_col = self.config['mongo']['invoker_col'] + self.provider_col = self.config['mongo']['provider_col'] + self.services_col = self.config['mongo']['col_services'] + self.security_context_col = self.config['mongo']['col_security'] + self.events = self.config['mongo']['col_event'] + + + def get_col_by_name(self, name): + return self.db[name].with_options(codec_options=CodecOptions(tz_aware=True)) + + def __connect(self, max_retries=3, retry_delay=1): + + retries = 0 + + while retries < max_retries: + try: + uri = f"mongodb://{self.config['mongo']['user']}:{self.config['mongo']['password']}@" \ + f"{self.config['mongo']['host']}:{self.config['mongo']['port']}" + + + client = MongoClient(uri) + mydb = client[self.config['mongo']['db']] + mydb.command("ping") + return mydb + except AutoReconnect: + retries += 1 + print(f"Reconnecting... Retry {retries} of {max_retries}") + time.sleep(retry_delay) + return None + + def close_connection(self): + if self.db.client: + self.db.client.close() + diff --git a/services/helper/helper_service/wsgi.py b/services/helper/helper_service/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/helper/helper_service/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/helper/prepare_helper.sh b/services/helper/prepare_helper.sh new file mode 100644 index 0000000000000000000000000000000000000000..d4297f6484ddfe6ee867338b7d19b7eb97fc4b7d --- /dev/null +++ b/services/helper/prepare_helper.sh @@ -0,0 +1,5 @@ +#!/bin/bash + + +gunicorn --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/helper_service wsgi:app \ No newline at end of file diff --git a/services/helper/requirements.txt b/services/helper/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..23c2931293b753eb0580dae37dab345cd1335869 --- /dev/null +++ b/services/helper/requirements.txt @@ -0,0 +1,10 @@ +python_dateutil == 2.9.0.post0 +setuptools == 68.2.2 +Flask == 3.0.3 +pymongo == 4.7.3 +flask_jwt_extended == 4.6.0 +pyopenssl == 24.1.0 +pyyaml == 6.0.1 +requests == 2.32.2 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/mock_server/Dockerfile b/services/mock_server/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..6d72bf569899e6512254be59539231c0fb49b338 --- /dev/null +++ b/services/mock_server/Dockerfile @@ -0,0 +1,21 @@ +# start by pulling the python image +FROM python:3.10.0-alpine + +# copy the requirements file into the image +COPY ./requirements.txt /app/requirements.txt + +# switch working directory +WORKDIR /app + +# install the dependencies and packages in the requirements file +RUN pip install -r requirements.txt + +# copy every content from the local file to the image +COPY . /app + +EXPOSE 9090 + +# configure the container to run in an executed manner +ENTRYPOINT [ "python" ] + +CMD ["mock_server.py" ] \ No newline at end of file diff --git a/services/mock_server/mock_server.py b/services/mock_server/mock_server.py new file mode 100644 index 0000000000000000000000000000000000000000..41ba65066d81a1857f53a69eb752995c6bd14210 --- /dev/null +++ b/services/mock_server/mock_server.py @@ -0,0 +1,60 @@ +from flask import Flask, request +import logging +from logging.handlers import RotatingFileHandler +import os + +app = Flask(__name__) + +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + +# Lista para almacenar las solicitudes recibidas +requests_received = [] + +def verbose_formatter(): + return logging.Formatter( + '{"timestamp": "%(asctime)s", "level": "%(levelname)s", "logger": "%(name)s", "function": "%(funcName)s", "line": %(lineno)d, "message": %(message)s}', + datefmt='%d/%m/%Y %H:%M:%S' + ) + + +def configure_logging(app): + del app.logger.handlers[:] + loggers = [app.logger, ] + handlers = [] + console_handler = logging.StreamHandler() + console_handler.setLevel(numeric_level) + console_handler.setFormatter(verbose_formatter()) + file_handler = RotatingFileHandler(filename="mock_server.log", maxBytes=1024 * 1024 * 100, backupCount=20) + file_handler.setLevel(numeric_level) + file_handler.setFormatter(verbose_formatter()) + handlers.append(console_handler) + handlers.append(file_handler) + + + for l in loggers: + for handler in handlers: + l.addHandler(handler) + l.propagate = False + l.setLevel(numeric_level) + +@app.route('/testing', methods=['POST', 'GET']) +def index(): + if request.method == 'POST': + app.logger.debug(request.json) + app.logger.debug(request.headers) + requests_received.append(request.json) + return 'Mock Server is running' + +@app.route('/requests_list', methods=['GET','DELETE']) +def requests_list(): + if request.method == 'DELETE': + requests_received.clear() + return requests_received + + +configure_logging(app) + +if __name__ == '__main__': + app.run(host=os.environ.get("IP",'0.0.0.0'),port=os.environ.get("PORT",9090),debug=True) diff --git a/services/mock_server/requirements.txt b/services/mock_server/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..0764845fe7c34f969d1acfffea0be038793c0e55 --- /dev/null +++ b/services/mock_server/requirements.txt @@ -0,0 +1 @@ +flask == 3.0.3 \ No newline at end of file diff --git a/services/nginx/nginx.conf b/services/nginx/nginx.conf index d30ded7b2eb1863cc072284e1f6c5727bf849ef1..f51e177fd0fce53f6d151e3483fcd4802a5a1d3c 100644 --- a/services/nginx/nginx.conf +++ b/services/nginx/nginx.conf @@ -1,6 +1,6 @@ worker_processes auto; -error_log /var/log/nginx/error.log debug; +error_log /var/log/nginx/error.log ${LOG_LEVEL}; pid /tmp/nginx.pid; events { @@ -12,6 +12,10 @@ http { default ""; ~(^|,)CN=(?[^,]+) $CN; } + map "$request_method:$uri:$ssl_client_s_dn_cn" $helper_error_message { + default 'SUCCESS'; + "~*(GET|DELETE):.*:(?!(superadmin))(.*)" '{"status":401, "title":"Unauthorized" ,"detail":"Role not authorized for this API route", "cause":"User role must be superadmin"}'; + } map "$request_method:$uri:$ssl_client_s_dn_cn" $invoker_error_message { default 'SUCCESS'; "~*(PUT|DELETE):.*:(?!(INV|superadmin))(.*)" '{"status":401, "title":"Unauthorized" ,"detail":"Role not authorized for this API route", "cause":"User role must be invoker"}'; @@ -163,6 +167,15 @@ http { proxy_pass http://access-control-policy:8080; } + location /helper { + if ( $helper_error_message != SUCCESS ) { + add_header Content-Type 'application/problem+json'; + return 401 $helper_error_message; + } + proxy_set_header X-SSL-Client-Cert $ssl_client_cert; + proxy_pass http://helper:8080; + } + } } diff --git a/services/nginx/nginx_prepare.sh b/services/nginx/nginx_prepare.sh index 081b2c9ad1062c213f6cf04ed9c47847413ac12f..75fc9fd5e9a86d4dca66ef0b7124f08557b510ac 100644 --- a/services/nginx/nginx_prepare.sh +++ b/services/nginx/nginx_prepare.sh @@ -34,5 +34,20 @@ curl -k -retry 30 \ --header "X-Vault-Token: $VAULT_TOKEN" \ --request GET "$VAULT_ADDR/v1/secret/data/server_cert/private" 2>/dev/null | jq -r '.data.data.key' -j > $CERTS_FOLDER/server.key +LOG_LEVEL=$(echo "${LOG_LEVEL}" | tr '[:upper:]' '[:lower:]') +case "$LOG_LEVEL" in + critical) + LOG_LEVEL="crit" + ;; + fatal) + LOG_LEVEL="error" + ;; + notset) + LOG_LEVEL="info" + ;; +esac + +envsubst '$LOG_LEVEL' < /etc/nginx/nginx.conf > /etc/nginx/nginx.conf.tmp +mv /etc/nginx/nginx.conf.tmp /etc/nginx/nginx.conf nginx \ No newline at end of file diff --git a/services/register/config.yaml b/services/register/config.yaml index 2ac53bd343f3b76d82906c4ed871d6f4c71afcd0..f1e1a257290897585780b9fe5e8eac6ae5e2e0ee 100644 --- a/services/register/config.yaml +++ b/services/register/config.yaml @@ -3,12 +3,26 @@ mongo: { 'password': 'example', 'db': 'capif_users', 'col': 'user', + 'admins': 'admins', 'host': 'mongo_register', 'port': '27017' } ca_factory: { "url": "vault", "port": "8200", - "token": "dev-only-token" + "token": "dev-only-token", + "verify": False } +ccf: { + "url": "capifcore", + "helper_remove_user": "/helper/deleteEntities/" +} + +register: { + "register_uuid": '6ba7b810-9dad-11d1-80b4-00c04fd430c8', + "refresh_expiration": 30, #days + "token_expiration": 10, #mins + "admin_users": {admin_user: "admin", + admin_pass: "password123"} +} \ No newline at end of file diff --git a/services/register/pytest.ini b/services/register/pytest.ini new file mode 100644 index 0000000000000000000000000000000000000000..62fc4e2aa1169ef0638ebceab8d77e0cabe9d67a --- /dev/null +++ b/services/register/pytest.ini @@ -0,0 +1,4 @@ +# content of pytest.ini +[pytest] +python_files = register_services/config.py + diff --git a/services/register/register_prepare.sh b/services/register/register_prepare.sh index de69be7043beb9dc002bcc98004b975d31a979af..2ae8deff25fce905a937fa87767796a9685f8482 100644 --- a/services/register/register_prepare.sh +++ b/services/register/register_prepare.sh @@ -1,27 +1,16 @@ #!/bin/bash -CERTS_FOLDER="/usr/src/app/register_service" +CERTS_FOLDER="/usr/src/app/register_service/certs" cd $CERTS_FOLDER -VAULT_ADDR="http://$VAULT_HOSTNAME:$VAULT_PORT" -VAULT_TOKEN=$VAULT_ACCESS_TOKEN - -curl -k -retry 30 \ - --retry-all-errors \ - --connect-timeout 5 \ - --max-time 10 \ - --retry-delay 10 \ - --retry-max-time 300 \ - --header "X-Vault-Token: $VAULT_TOKEN" \ - --request GET "$VAULT_ADDR/v1/secret/data/server_cert/private" 2>/dev/null | jq -r '.data.data.key' -j > $CERTS_FOLDER/server.key - openssl req -x509 \ -sha256 -days 356 \ -nodes \ -newkey rsa:2048 \ -subj "/CN=register/C=ES/L=Madrid" \ - -keyout /usr/src/app/register_service/registerCA.key -out /usr/src/app/register_service/registerCA.crt + -keyout /usr/src/app/register_service/certs/registerCA.key -out /usr/src/app/register_service/certs/registerCA.crt + -openssl genrsa -out /usr/src/app/register_service/register_key.key 2048 +openssl genrsa -out /usr/src/app/register_service/certs/register_key.key 2048 COUNTRY="ES" # 2 letter country-code STATE="Madrid" # state or province name @@ -37,7 +26,7 @@ COMPANY="" # company name # DAYS="-days 365" # create the certificate request -cat <<__EOF__ | openssl req -new $DAYS -key /usr/src/app/register_service/register_key.key -out /usr/src/app/register_service/register.csr +cat <<__EOF__ | openssl req -new $DAYS -key /usr/src/app/register_service/certs/register_key.key -out /usr/src/app/register_service/certs/register.csr $COUNTRY $STATE $LOCALITY @@ -49,7 +38,9 @@ $CHALLENGE $COMPANY __EOF__ -openssl x509 -req -in /usr/src/app/register_service/register.csr -CA /usr/src/app/register_service/registerCA.crt -CAkey /usr/src/app/register_service/registerCA.key -CAcreateserial -out /usr/src/app/register_service/register_cert.crt -days 365 -sha256 +openssl x509 -req -in /usr/src/app/register_service/certs/register.csr -CA /usr/src/app/register_service/certs/registerCA.crt -CAkey /usr/src/app/register_service/certs/registerCA.key -CAcreateserial -out /usr/src/app/register_service/certs/register_cert.crt -days 365 -sha256 -cd /usr/src/app/ -python3 -m register_service \ No newline at end of file +gunicorn --certfile=/usr/src/app/register_service/certs/register_cert.crt \ + --keyfile=/usr/src/app/register_service/certs/register_key.key \ + --bind 0.0.0.0:8080 \ + --chdir /usr/src/app/register_service wsgi:app \ No newline at end of file diff --git a/services/register/register_service/__main__.py b/services/register/register_service/__main__.py deleted file mode 100644 index 5225f78e731c7297259c8b6f573cdb487c2ef3c6..0000000000000000000000000000000000000000 --- a/services/register/register_service/__main__.py +++ /dev/null @@ -1,27 +0,0 @@ - -import os -import base64 -from flask import Flask -from .controllers.register_controller import register_routes -from flask_jwt_extended import JWTManager - -app = Flask(__name__) - -jwt = JWTManager(app) - -with open("/usr/src/app/register_service/server.key", "rb") as key_file: - key_data = key_file.read() - - -app.config['JWT_ALGORITHM'] = 'RS256' -app.config['JWT_PRIVATE_KEY'] = key_data - -app.register_blueprint(register_routes) - - -#---------------------------------------- -# launch -#---------------------------------------- - -if __name__ == "__main__": - app.run(debug=True, host = '0.0.0.0', port=8080, ssl_context= ("/usr/src/app/register_service/register_cert.crt", "/usr/src/app/register_service/register_key.key")) diff --git a/services/register/register_service/app.py b/services/register/register_service/app.py new file mode 100644 index 0000000000000000000000000000000000000000..53d4b0507b62499e100407043f44a952994442c8 --- /dev/null +++ b/services/register/register_service/app.py @@ -0,0 +1,95 @@ + +from flask import Flask +from controllers.register_controller import register_routes +from flask_jwt_extended import JWTManager +from OpenSSL.crypto import PKey, TYPE_RSA, X509Req, dump_certificate_request, FILETYPE_PEM, dump_privatekey +import requests +import json +from config import Config +from db.db import MongoDatabse +import logging +import os + +app = Flask(__name__) + + +jwt_manager = JWTManager(app) + +config = Config().get_config() + +# Setting log level +log_level = os.getenv('LOG_LEVEL', 'INFO').upper() +numeric_level = getattr(logging, log_level, logging.INFO) + +# Create a superadmin CSR and keys +key = PKey() +key.generate_key(TYPE_RSA, 2048) +req = X509Req() +req.get_subject().O = 'Telefonica I+D' +req.get_subject().OU = 'Innovation' +req.get_subject().L = 'Madrid' +req.get_subject().ST = 'Madrid' +req.get_subject().C = 'ES' +req.get_subject().emailAddress = 'inno@tid.es' +req.set_pubkey(key) +req.sign(key, 'sha256') + +csr_request = dump_certificate_request(FILETYPE_PEM, req) +private_key = dump_privatekey(FILETYPE_PEM, key) + +# Save superadmin private key +key_file = open("certs/superadmin.key", 'wb+') +key_file.write(bytes(private_key)) +key_file.close() + +# Request superadmin certificate +url = 'http://{}:{}/v1/pki_int/sign/my-ca'.format(config["ca_factory"]["url"], config["ca_factory"]["port"]) +headers = {'X-Vault-Token': f"{config["ca_factory"]["token"]}"} +data = { + 'format':'pem_bundle', + 'ttl': '43000h', + 'csr': csr_request, + 'common_name': "superadmin" +} + +response = requests.request("POST", url, headers=headers, data=data, verify = config["ca_factory"].get("verify", False)) +superadmin_cert = json.loads(response.text)['data']['certificate'] + +# Save the superadmin certificate +cert_file = open("certs/superadmin.crt", 'wb') +cert_file.write(bytes(superadmin_cert, 'utf-8')) +cert_file.close() + +url = f"http://{config['ca_factory']['url']}:{config['ca_factory']['port']}/v1/secret/data/ca" +headers = { + + 'X-Vault-Token': config['ca_factory']['token'] +} +response = requests.request("GET", url, headers=headers, verify = config["ca_factory"].get("verify", False)) + +ca_root = json.loads(response.text)['data']['data']['ca'] +cert_file = open("certs/ca_root.crt", 'wb') +cert_file.write(bytes(ca_root, 'utf-8')) +cert_file.close() + +# Request CAPIF private key to encode the CAPIF token +url = 'http://{}:{}/v1/secret/data/server_cert/private'.format(config["ca_factory"]["url"], config["ca_factory"]["port"]) +headers = {'X-Vault-Token': f"{config["ca_factory"]["token"]}"} +response = requests.request("GET", url, headers=headers, verify = config["ca_factory"].get("verify", False)) + +key_data = json.loads(response.text)["data"]["data"]["key"] + +# Create an Admin in the Admin Collection +client = MongoDatabse() +if not client.get_col_by_name(client.capif_admins).find_one({"admin_name": config["register"]["admin_users"]["admin_user"], "admin_pass": config["register"]["admin_users"]["admin_pass"]}): + print(f'Inserting Initial Admin admin_name: {config["register"]["admin_users"]["admin_user"]}, admin_pass: {config["register"]["admin_users"]["admin_pass"]}') + client.get_col_by_name(client.capif_admins).insert_one({"admin_name": config["register"]["admin_users"]["admin_user"], "admin_pass": config["register"]["admin_users"]["admin_pass"]}) + + +app.config['JWT_ALGORITHM'] = 'RS256' +app.config['JWT_PRIVATE_KEY'] = key_data +app.config['REGISTRE_SECRET_KEY'] = config["register"]["register_uuid"] + +app.logger.setLevel(numeric_level) + +app.register_blueprint(register_routes) \ No newline at end of file diff --git a/services/register/register_service/certs/.gitkeep b/services/register/register_service/certs/.gitkeep new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/services/register/register_service/config.py b/services/register/register_service/config.py index d04bd1acd87603f491b09f464d8db1d6cdc52ad7..97ab831fc7a69163163f7182f1f8c61bd9e3ffc4 100644 --- a/services/register/register_service/config.py +++ b/services/register/register_service/config.py @@ -5,7 +5,7 @@ import os class Config: def __init__(self): self.cached = 0 - self.file="./config.yaml" + self.file="../config.yaml" self.my_config = {} stamp = os.stat(self.file).st_mtime diff --git a/services/register/register_service/controllers/register_controller.py b/services/register/register_service/controllers/register_controller.py index 71af562e59cbe6af5909fa65bd8d83f265ea490b..a82998fb7166e9847f81afea9d9377a4f046ab37 100644 --- a/services/register/register_service/controllers/register_controller.py +++ b/services/register/register_service/controllers/register_controller.py @@ -1,39 +1,160 @@ #!/usr/bin/env python3 -from flask import Flask, jsonify, request, Blueprint -from flask_jwt_extended import JWTManager, jwt_required, create_access_token -from pymongo import MongoClient -from ..core.register_operations import RegisterOperations -import secrets +from flask import current_app, Flask, jsonify, request, Blueprint +from core.register_operations import RegisterOperations +from config import Config + +from functools import wraps +from datetime import datetime, timedelta +from db.db import MongoDatabse + +from flask_httpauth import HTTPBasicAuth +import jwt + +auth = HTTPBasicAuth() + +config = Config().get_config() register_routes = Blueprint("register_routes", __name__) register_operation = RegisterOperations() -@register_routes.route("/register", methods=["POST"]) -def register(): - username = request.json["username"] - password = request.json["password"] - description = request.json["description"] - role = request.json["role"] - cn = request.json["cn"] - if role != "invoker" and role != "provider": - return jsonify(message="Role must be invoker or provider"), 400 +# Function to generate access tokens and refresh tokens +def generate_tokens(username): + current_app.logger.debug(f"generating admin tokens...") + access_payload = { + 'username': username, + 'exp': datetime.now() + timedelta(minutes=config["register"]["token_expiration"]) + } + refresh_payload = { + 'username': username, + 'exp': datetime.now() + timedelta(days=config["register"]["refresh_expiration"]) + } + access_token = jwt.encode(access_payload, current_app.config['REGISTRE_SECRET_KEY'], algorithm='HS256') + refresh_token = jwt.encode(refresh_payload, current_app.config['REGISTRE_SECRET_KEY'], algorithm='HS256') + current_app.logger.debug(f"Access token : {access_token}\nRefresh token : {refresh_token}") + return access_token, refresh_token + +# Function in charge of verifying the basic auth +@auth.verify_password +def verify_password(username, password): + current_app.logger.debug("Checking user credentials...") + users = register_operation.get_users()[0].json["users"] + client = MongoDatabse() + admin = client.get_col_by_name(client.capif_admins).find_one({"admin_name": username, "admin_pass": password}) + if admin: + current_app.logger.debug(f"Verified admin {username}") + return username, "admin" + for user in users: + if user["username"] == username and user["password"]==password: + current_app.logger.debug(f"Verified user {username}") + return username, "client" + +# Function responsible for verifying the token +def admin_required(): + def decorator(f): + @wraps(f) + def decorated(*args, **kwargs): + current_app.logger.debug("Checking admin token...") + token = request.headers.get('Authorization') + if not token: + current_app.logger.debug("Token is missing.") + return jsonify({'message': 'Token is missing'}), 401 + + if token.startswith('Bearer '): + current_app.logger.debug("Token is missing.") + token = token.split('Bearer ')[1] + + if not token: + current_app.logger.debug("Token is missing.") + return jsonify({'message': 'Token is missing'}), 401 + + try: + data = jwt.decode(token, current_app.config['REGISTRE_SECRET_KEY'], algorithms=['HS256'], options={'verify_exp': True}) + username = data['username'] + return f(username, *args, **kwargs) + except Exception as e: + current_app.logger.debug(f"Error: {str(e)}.") + return jsonify({'message': str(e)}), 401 + + return decorated + return decorator + +@register_routes.route('/login', methods=['POST']) +@auth.login_required +def login(): + username, rol = auth.current_user() + if rol != "admin": + current_app.logger.debug(f"User {username} trying to log in as admin") + return jsonify(message="Unauthorized. Administrator privileges required."), 401 + access_token, refresh_token = generate_tokens(username) + return jsonify({'access_token': access_token, 'refresh_token': refresh_token}) + +@register_routes.route('/refresh', methods=['POST']) +@admin_required() +def refresh_token(username): + current_app.logger.debug(f"Refreshing token for admin {username}") + access_token, _ = generate_tokens(username) + return jsonify({'access_token': access_token}) + +@register_routes.route("/createUser", methods=["POST"]) +@admin_required() +def register(username): + current_app.logger.debug(f"Admin {username} creating a user...") + required_fields = { + "username": str, + "password": str, + "enterprise": str, + "country": str, + "email": str, + "purpose": str + } + + optional_fields = { + "phone_number": str, + "company_web": str, + "description": str + } + + user_info = request.get_json() + current_app.logger.debug(f"User Info: {user_info}") + missing_fields = [] + for field, field_type in required_fields.items(): + if field not in user_info: + missing_fields.append(field) + elif not isinstance(user_info[field], field_type): + current_app.logger.debug(f"Error: Field {field} must be of type {field_type.__name__}") + return jsonify({"error": f"Field '{field}' must be of type {field_type.__name__}"}), 400 + for field, field_type in optional_fields.items(): + if field in user_info and not isinstance(user_info[field], field_type): + current_app.logger.debug(f"Error: Field {field} must be of type {field_type.__name__}") + return jsonify({"error": f"Optional field '{field}' must be of type {field_type.__name__}"}), 400 + if field not in user_info: + user_info[field] = None - return register_operation.register_user(username, password, description, cn, role) + if missing_fields: + current_app.logger.debug(f"Error: missing requuired fields : {missing_fields}") + return jsonify({"error": "Missing required fields", "fields": missing_fields}), 400 + return register_operation.register_user(user_info) -@register_routes.route("/getauth", methods=["POST"]) +@register_routes.route("/getauth", methods=["GET"]) +@auth.login_required def getauth(): - username = request.json["username"] - password = request.json["password"] + username, _ = auth.current_user() + current_app.logger.debug(f"Obtaining authorization for the user {username}") + return register_operation.get_auth(username) - return register_operation.get_auth(username, password) +@register_routes.route("/deleteUser/", methods=["DELETE"]) +@admin_required() +def remove(username, uuid): + current_app.logger.debug(f"Deleting user with id {uuid} by admin {username}") + return register_operation.remove_user(uuid) -@register_routes.route("/remove", methods=["DELETE"]) -def remove(): - username = request.json["username"] - password = request.json["password"] - return register_operation.remove_user(username, password) +@register_routes.route("/getUsers", methods=["GET"]) +@admin_required() +def getUsers(username): + current_app.logger.debug(f"Returning list of users to admin {username}") + return register_operation.get_users() diff --git a/services/register/register_service/core/register_operations.py b/services/register/register_service/core/register_operations.py index f929820f7e4d532af039ce50856d1e4bcbe86798..42627fd304b30322ee27a112405a5a5a2bc1da3d 100644 --- a/services/register/register_service/core/register_operations.py +++ b/services/register/register_service/core/register_operations.py @@ -1,11 +1,11 @@ -from flask import Flask, jsonify, request, current_app +from flask import jsonify, current_app from flask_jwt_extended import create_access_token -from ..db.db import MongoDatabse -from ..config import Config -import secrets +from db.db import MongoDatabse +from datetime import datetime +from config import Config import requests -import json -import sys +import uuid + class RegisterOperations: @@ -14,58 +14,79 @@ class RegisterOperations: self.mimetype = 'application/json' self.config = Config().get_config() - def register_user(self, username, password, description, cn, role): + def register_user(self, user_info): mycol = self.db.get_col_by_name(self.db.capif_users) - exist_user = mycol.find_one({"username": username}) + exist_user = mycol.find_one({"username": user_info["username"]}) if exist_user: + current_app.logger.debug(f"User already exists : {user_info["username"]}") return jsonify("user already exists"), 409 + + name_space = uuid.UUID(self.config["register"]["register_uuid"]) + user_uuid = str(uuid.uuid5(name_space,user_info["username"])) + current_app.logger.debug(f"User uuid : {user_uuid}") - user_info = dict(_id=secrets.token_hex(7), username=username, password=password, role=role, description=description, cn=cn, list_invokers=[], list_providers=[]) - obj = mycol.insert_one(user_info) + user_info["uuid"] = user_uuid + user_info["onboarding_date"]=datetime.now() + mycol.insert_one(user_info) - if role == "invoker": - return jsonify(message="invoker registered successfully", - id=obj.inserted_id, - ccf_onboarding_url="api-invoker-management/v1/onboardedInvokers", - ccf_discover_url="service-apis/v1/allServiceAPIs?api-invoker-id="), 201 - else: - return jsonify(message="provider" + " registered successfully", - id=obj.inserted_id, - ccf_api_onboarding_url="api-provider-management/v1/registrations", - ccf_publish_url="published-apis/v1//service-apis"), 201 + current_app.logger.debug(f"User with uuid {user_uuid} and username {user_info["username"]} registered successfully") + return jsonify(message="User registered successfully", uuid=user_uuid), 201 - def get_auth(self, username, password): + def get_auth(self, username): mycol = self.db.get_col_by_name(self.db.capif_users) try: - exist_user = mycol.find_one({"username": username, "password": password}) + exist_user = mycol.find_one({"username": username}) if exist_user is None: - return jsonify("Not exister user with this credentials"), 400 - - access_token = create_access_token(identity=(username + " " + exist_user["role"])) - url = f"http://{self.config['ca_factory']['url']}:{self.config['ca_factory']['port']}/v1/secret/data/ca" - headers = { - - 'X-Vault-Token': self.config['ca_factory']['token'] - } - response = requests.request("GET", url, headers=headers, verify = False) - response_payload = json.loads(response.text) - return jsonify(message="Token and CA root returned successfully", access_token=access_token, ca_root=response_payload['data']['data']['ca']), 200 + current_app.logger.debug(f"No user exists with these credentials: {username}") + return jsonify("No user exists with these credentials"), 400 + + access_token = create_access_token(identity=(username + " " + exist_user["uuid"])) + current_app.logger.debug(f"Access token generated for user {username} : {access_token}") + + cert_file = open("certs/ca_root.crt", 'rb') + ca_root = cert_file.read() + cert_file.close() + + current_app.logger.debug(f"Returning the requested information...") + + return jsonify(message="Token and CA root returned successfully", + access_token=access_token, + ca_root=ca_root.decode("utf-8"), + ccf_api_onboarding_url="api-provider-management/v1/registrations", + ccf_publish_url="published-apis/v1//service-apis", + ccf_onboarding_url="api-invoker-management/v1/onboardedInvokers", + ccf_discover_url="service-apis/v1/allServiceAPIs?api-invoker-id=", + ccf_security_url="capif-security/v1/trustedInvokers/"), 200 except Exception as e: return jsonify(message=f"Errors when try getting auth: {e}"), 500 - def remove_user(self, username, password): + def remove_user(self, uuid): mycol = self.db.get_col_by_name(self.db.capif_users) try: - mycol.delete_one({"username": username, "password": password}) + + url = f"https://{self.config["ccf"]["url"]}{self.config["ccf"]["helper_remove_user"]}{uuid}" + requests.delete(url, cert=("certs/superadmin.crt", "certs/superadmin.key"), verify="certs/ca_root.crt") + + mycol.delete_one({"uuid": uuid}) + current_app.logger.debug(f"User with uuid {uuid} removed successfully") return jsonify(message="User removed successfully"), 204 except Exception as e: return jsonify(message=f"Errors when try remove user: {e}"), 500 + + def get_users(self): + mycol = self.db.get_col_by_name(self.db.capif_users) + + try: + users=list(mycol.find({}, {"_id":0})) + return jsonify(message="Users successfully obtained", users=users), 200 + except Exception as e: + return jsonify(message=f"Error trying to get users: {e}"), 500 diff --git a/services/register/register_service/db/db.py b/services/register/register_service/db/db.py index 0b08933251035fc285b0983575d2e30844cce8f3..fdf448e5be3b675d585bccf141b8e2a6ffe67754 100644 --- a/services/register/register_service/db/db.py +++ b/services/register/register_service/db/db.py @@ -1,9 +1,7 @@ -import atexit import time from pymongo import MongoClient from pymongo.errors import AutoReconnect -from ..config import Config -from bson.codec_options import CodecOptions +from config import Config class MongoDatabse(): @@ -12,6 +10,7 @@ class MongoDatabse(): self.config = Config().get_config() self.db = self.__connect() self.capif_users = self.config['mongo']['col'] + self.capif_admins = self.config['mongo']['admins'] def get_col_by_name(self, name): diff --git a/services/register/register_service/wsgi.py b/services/register/register_service/wsgi.py new file mode 100644 index 0000000000000000000000000000000000000000..6026b0fa96078634d3455ab93d71dcdc78774276 --- /dev/null +++ b/services/register/register_service/wsgi.py @@ -0,0 +1,4 @@ +from app import app + +if __name__ == "__main__": + app.run() diff --git a/services/register/requirements.txt b/services/register/requirements.txt index c5a4f37e70ec061faaeb1876ee7d907e71c92d49..bf3e52ccc89c836571bf47bda630499347c54259 100644 --- a/services/register/requirements.txt +++ b/services/register/requirements.txt @@ -1,8 +1,12 @@ python_dateutil >= 2.6.0 -setuptools >= 21.0.0 -Flask >= 2.0.3 -pymongo == 4.0.1 -flask_jwt_extended -pyopenssl -pyyaml -requests +setuptools == 68.2.2 +Flask == 3.0.3 +pymongo == 4.7.3 +flask_jwt_extended == 4.6.0 +pyopenssl == 24.1.0 +pyyaml == 6.0.1 +requests == 2.32.2 +bcrypt == 4.0.1 +flask_httpauth == 4.8.0 +gunicorn == 22.0.0 +packaging == 24.0 diff --git a/services/run.sh b/services/run.sh index 8214516f7616da74eae34b8079cd2f3d479b87c8..cf500a936202a281b3232992257e44fc582c9bb5 100755 --- a/services/run.sh +++ b/services/run.sh @@ -3,7 +3,9 @@ help() { echo "Usage: $1 " echo " -c : Setup different hostname for capif" + echo " -s : Run Mock server" echo " -m : Clean monitoring service" + echo " -l : Set Log Level (default DEBUG). Select one of: [CRITICAL, FATAL, ERROR, WARNING, WARN, INFO, DEBUG, NOTSET]" echo " -h : show this help" exit 1 } @@ -11,11 +13,16 @@ help() { HOSTNAME=capifcore MONITORING_STATE=false DEPLOY=all +LOG_LEVEL=DEBUG -#Needed to avoid write permissions on bind volumes with prometheus and grafana +# Needed to avoid write permissions on bind volumes with prometheus and grafana DUID=$(id -u) DGID=$(id -g) +# Mock Server configuration +IP=0.0.0.0 +PORT=9090 + # Get docker compose version docker_version=$(docker compose version --short | cut -d',' -f1) IFS='.' read -ra version_components <<< "$docker_version" @@ -28,17 +35,23 @@ else fi # Read params -while getopts ":c:m:h" opt; do +while getopts ":c:l:msh" opt; do case $opt in c) HOSTNAME="$OPTARG" ;; m) - MONITORING_STATE="$OPTARG" + MONITORING_STATE=true + ;; + s) + ROBOT_MOCK_SERVER=true ;; h) help - ;; + ;; + l) + LOG_LEVEL="$OPTARG" + ;; \?) echo "Not valid option: -$OPTARG" >&2 help @@ -54,7 +67,7 @@ echo Nginx hostname will be $HOSTNAME, deploy $DEPLOY, monitoring $MONITORING_ST if [ "$MONITORING_STATE" == "true" ] ; then echo '***Monitoring set as true***' - echo '***Creating Monitoging stack***' + echo '***Creating Monitoring stack***' DUID=$DUID DGID=$DGID docker compose -f "../monitoring/docker-compose.yml" up --detach status=$? @@ -78,7 +91,7 @@ else exit $status fi -CAPIF_HOSTNAME=$HOSTNAME MONITORING=$MONITORING_STATE docker compose -f "docker-compose-capif.yml" up --detach --build +CAPIF_HOSTNAME=$HOSTNAME MONITORING=$MONITORING_STATE LOG_LEVEL=$LOG_LEVEL docker compose -f "docker-compose-capif.yml" up --detach --build status=$? if [ $status -eq 0 ]; then @@ -90,13 +103,28 @@ fi CAPIF_PRIV_KEY_BASE_64=$(echo "$(cat nginx/certs/server.key)") -CAPIF_PRIV_KEY=$CAPIF_PRIV_KEY_BASE_64 docker compose -f "docker-compose-register.yml" up --detach --build +CAPIF_PRIV_KEY=$CAPIF_PRIV_KEY_BASE_64 LOG_LEVEL=$LOG_LEVEL docker compose -f "docker-compose-register.yml" up --detach --build status=$? if [ $status -eq 0 ]; then echo "*** Register Service are running ***" else echo "*** Register Service failed to start ***" + exit $status +fi + +if [ "$ROBOT_MOCK_SERVER" == "true" ] ; then + echo '***Robot Mock Server set as true***' + echo '***Creating Robot Mock Server stack***' + + IP=$IP PORT=$PORT docker compose -f "docker-compose-mock-server.yml" up --detach + status=$? + if [ $status -eq 0 ]; then + echo "*** Monitoring Stack Runing ***" + else + echo "*** Monitoring Stack failed to start ***" + exit $status + fi fi exit $status diff --git a/services/run_capif_tests.sh b/services/run_capif_tests.sh index b73893a45ca40cacecb4dca088999461a9de55de..f0a3f07abeab4f238a8c720c0d6524fe285b0ca9 100755 --- a/services/run_capif_tests.sh +++ b/services/run_capif_tests.sh @@ -1,21 +1,43 @@ #!/bin/bash +timestamp=$(date +"%Y%m%d_%H%M%S") DOCKER_ROBOT_IMAGE=dockerhub.hi.inet/5ghacking/5gnow-robot-test-image DOCKER_ROBOT_IMAGE_VERSION=4.0 cd .. REPOSITORY_BASE_FOLDER=${PWD} TEST_FOLDER=$REPOSITORY_BASE_FOLDER/tests -RESULT_FOLDER=$REPOSITORY_BASE_FOLDER/results +RESULT_FOLDER=$REPOSITORY_BASE_FOLDER/results/$timestamp ROBOT_DOCKER_FILE_FOLDER=$REPOSITORY_BASE_FOLDER/tools/robot # nginx Hostname and http port (80 by default) to reach for tests +# CAPIF_REGISTER=registercapif.mobilesandbox.cloud +CAPIF_REGISTER=capifcore +# CAPIF_REGISTER_PORT=37211 +CAPIF_REGISTER_PORT=8084 +# CAPIF_HOSTNAME=capif.mobilesandbox.cloud CAPIF_HOSTNAME=capifcore CAPIF_HTTP_PORT=8080 CAPIF_HTTPS_PORT=443 -echo "HOSTNAME = $CAPIF_HOSTNAME" +# VAULT access configuration +# CAPIF_VAULT=vault.5gnacar.int +CAPIF_VAULT=vault +CAPIF_VAULT_PORT=8200 +# CAPIF_VAULT_TOKEN=dev-only-token +CAPIF_VAULT_TOKEN=read-ca-token + + +MOCK_SERVER_URL=http://mock-server:9090 + + +echo "CAPIF_HOSTNAME = $CAPIF_HOSTNAME" +echo "CAPIF_REGISTER = $CAPIF_REGISTER" echo "CAPIF_HTTP_PORT = $CAPIF_HTTP_PORT" echo "CAPIF_HTTPS_PORT = $CAPIF_HTTPS_PORT" +echo "CAPIF_VAULT = $CAPIF_VAULT" +echo "CAPIF_VAULT_PORT = $CAPIF_VAULT_PORT" +echo "CAPIF_VAULT_TOKEN = $CAPIF_VAULT_TOKEN" +echo "MOCK_SERVER_URL = $MOCK_SERVER_URL" docker >/dev/null 2>/dev/null if [[ $? -ne 0 ]] @@ -45,8 +67,15 @@ docker run -ti --rm --network="host" \ --add-host host.docker.internal:host-gateway \ --add-host vault:host-gateway \ --add-host register:host-gateway \ + --add-host mock-server:host-gateway \ -v $TEST_FOLDER:/opt/robot-tests/tests \ -v $RESULT_FOLDER:/opt/robot-tests/results ${DOCKER_ROBOT_IMAGE}:${DOCKER_ROBOT_IMAGE_VERSION} \ --variable CAPIF_HOSTNAME:$CAPIF_HOSTNAME \ --variable CAPIF_HTTP_PORT:$CAPIF_HTTP_PORT \ - --variable CAPIF_HTTPS_PORT:$CAPIF_HTTPS_PORT $@ + --variable CAPIF_HTTPS_PORT:$CAPIF_HTTPS_PORT \ + --variable CAPIF_REGISTER:$CAPIF_REGISTER \ + --variable CAPIF_REGISTER_PORT:$CAPIF_REGISTER_PORT \ + --variable CAPIF_VAULT:$CAPIF_VAULT \ + --variable CAPIF_VAULT_PORT:$CAPIF_VAULT_PORT \ + --variable CAPIF_VAULT_TOKEN:$CAPIF_VAULT_TOKEN \ + --variable MOCK_SERVER_URL:$MOCK_SERVER_URL $@ diff --git a/services/run_mock_server.sh b/services/run_mock_server.sh new file mode 100755 index 0000000000000000000000000000000000000000..5a194c469371de592d4f63ec5e8bbfc59598489c --- /dev/null +++ b/services/run_mock_server.sh @@ -0,0 +1,47 @@ +#!/bin/bash + +help() { + echo "Usage: $1 " + echo " -i : Setup different host ip for mock server (default 0.0.0.0)" + echo " -p : Setup different port for mock server (default 9090)" + echo " -h : show this help" + exit 1 +} + +IP=0.0.0.0 +PORT=9090 + +# Read params +while getopts ":i:p:h" opt; do + case $opt in + i) + IP="$OPTARG" + ;; + p) + PORT=$OPTARG + ;; + h) + help + ;; + \?) + echo "Not valid option: -$OPTARG" >&2 + help + ;; + :) + echo "The -$OPTARG option requires an argument." >&2 + help + ;; + esac +done + +echo Robot Framework Mock Server will listen on $IP:$PORT + +IP=$IP PORT=$PORT docker compose -f "docker-compose-mock-server.yml" up --detach --build + +status=$? +if [ $status -eq 0 ]; then + echo "*** All Capif services are running ***" +else + echo "*** Some Capif services failed to start ***" + exit $status +fi diff --git a/services/show_logs.sh b/services/show_logs.sh index b53641dd216e3cb43d9cd4ca0eaca85567ca60e4..c2bcf52d90607d3da9364c11c44c99d4bf209071 100755 --- a/services/show_logs.sh +++ b/services/show_logs.sh @@ -5,6 +5,7 @@ help() { echo " -c : Show capif services" echo " -v : Show vault service" echo " -r : Show register service" + echo " -s : Show Robot Mock Server service" echo " -m : Show monitoring service" echo " -a : Show all services" echo " -f : Follow log output" @@ -23,7 +24,7 @@ echo "${FILES[@]}" FOLLOW="" # Read params -while getopts "cvrahmf" opt; do +while getopts "cvrahmfs" opt; do case $opt in c) echo "Show Capif services" @@ -37,13 +38,17 @@ while getopts "cvrahmf" opt; do echo "Show register service" FILES+=("-f docker-compose-register.yml") ;; + s) + echo "Show Mock Server service" + FILES+=("-f docker-compose-mock-server.yml") + ;; m) echo "Show monitoring service" FILES+=("-f ../monitoring/docker-compose.yml") ;; a) echo "Show all services" - FILES=("-f docker-compose-capif.yml" -f "docker-compose-vault.yml" -f "docker-compose-register.yml" -f "../monitoring/docker-compose.yml") + FILES=("-f docker-compose-capif.yml" -f "docker-compose-vault.yml" -f "docker-compose-register.yml" -f "docker-compose-mock-server.yml" -f "../monitoring/docker-compose.yml") ;; f) echo "Setup follow logs" diff --git a/tests/features/CAPIF Api Access Control Policy/capif_api_access_control_policy.robot b/tests/features/CAPIF Api Access Control Policy/capif_api_access_control_policy.robot index 1772f3ba82943aaf7ff6a945e8de6117fb31a63d..cd497841ec3a381ef7ec390aebab4a6f8eb691a0 100644 --- a/tests/features/CAPIF Api Access Control Policy/capif_api_access_control_policy.robot +++ b/tests/features/CAPIF Api Access Control Policy/capif_api_access_control_policy.robot @@ -7,6 +7,7 @@ Resource ../../resources/common.resource Suite Teardown Reset Testing Environment Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment *** Variables *** @@ -23,13 +24,6 @@ Retrieve ACL # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method - ... ${CAPIF_USERS} - ... update_capif_users_dicts - ... ${register_user_info_provider['resource_url'].path} - ... ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info_provider} ... service_1 @@ -50,9 +44,6 @@ Retrieve ACL # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} @@ -97,13 +88,6 @@ Retrieve ACL with 2 Service APIs published # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method - ... ${CAPIF_USERS} - ... update_capif_users_dicts - ... ${register_user_info_provider['resource_url'].path} - ... ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info_provider} ... service_1 @@ -118,9 +102,6 @@ Retrieve ACL with 2 Service APIs published # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} @@ -179,13 +160,6 @@ Retrieve ACL with security context created by two different Invokers # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method - ... ${CAPIF_USERS} - ... update_capif_users_dicts - ... ${register_user_info_provider['resource_url'].path} - ... ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info_provider} ... service_1 @@ -206,18 +180,12 @@ Retrieve ACL with security context created by two different Invokers # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${INVOKER_USERNAME_2}= Set Variable ${INVOKER_USERNAME}_2 # Register another invoker ${register_user_info_invoker_2} ${url} ${request_body}= Invoker Default Onboarding ... ${INVOKER_USERNAME_2} - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME_2} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME_2} - # Get Published APIs ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} @@ -271,7 +239,6 @@ Retrieve ACL with security context created by two different Invokers ... username=${AEF_PROVIDER_USERNAME} Check Response Variable Type And Values ${resp} 200 AccessControlPolicyList - # Check returned values Should Not Be Empty ${resp.json()['apiInvokerPolicies']} Length Should Be ${resp.json()['apiInvokerPolicies']} 2 @@ -296,13 +263,6 @@ Retrieve ACL filtered by api-invoker-id # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method - ... ${CAPIF_USERS} - ... update_capif_users_dicts - ... ${register_user_info_provider['resource_url'].path} - ... ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info_provider} ... service_1 @@ -323,18 +283,12 @@ Retrieve ACL filtered by api-invoker-id # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${INVOKER_USERNAME_2}= Set Variable ${INVOKER_USERNAME}_2 # Register another invoker ${register_user_info_invoker_2} ${url} ${request_body}= Invoker Default Onboarding ... ${INVOKER_USERNAME_2} - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME_2} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME_2} - # Get Published APIs ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} @@ -607,7 +561,7 @@ No ACL for invoker after be removed Check Response Variable Type And Values ${resp} 200 AccessControlPolicyList - Remove entity ${INVOKER_USERNAME} + Remove entity ${INVOKER_USERNAME} ${resp}= Get Request Capif ... /access-control-policy/v1/accessControlPolicyList/${service_api_description_published['apiId']}?aef-id=${register_user_info_provider['aef_id']} @@ -624,4 +578,3 @@ No ACL for invoker after be removed ... title=Not Found ... detail=No ACLs found for the requested service: ${service_api_description_published['apiId']}, aef_id: ${register_user_info_provider['aef_id']}, invoker: None and supportedFeatures: None ... cause=Wrong id - diff --git a/tests/features/CAPIF Api Auditing Service/capif_auditing_api.robot b/tests/features/CAPIF Api Auditing Service/capif_auditing_api.robot index e4052ef40e9c21ac2c71ebc5718fc6a416ff255e..d850a5793a5b99f9bf96dfd7dd6a9d1f10ea994a 100644 --- a/tests/features/CAPIF Api Auditing Service/capif_auditing_api.robot +++ b/tests/features/CAPIF Api Auditing Service/capif_auditing_api.robot @@ -1,12 +1,14 @@ *** Settings *** -Resource /opt/robot-tests/tests/resources/common.resource -Library /opt/robot-tests/tests/libraries/bodyRequests.py -Library Collections -Resource /opt/robot-tests/tests/resources/common/basicRequests.robot -Resource ../../resources/common.resource +Resource /opt/robot-tests/tests/resources/common.resource +Library /opt/robot-tests/tests/libraries/bodyRequests.py +Library Collections +Resource /opt/robot-tests/tests/resources/common/basicRequests.robot +Resource ../../resources/common.resource + +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment -Test Setup Reset Testing Environment -Suite Teardown Reset Testing Environment *** Variables *** ${AEF_ID_NOT_VALID} aef-example @@ -16,34 +18,33 @@ ${NOTIFICATION_DESTINATION} http://robot.testing:1080 ${API_VERSION_VALID} v1 ${API_VERSION_NOT_VALID} v58 + *** Test Cases *** Get Log Entry [Tags] capif_api_auditing_service-1 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Create Log Entry - ${request_body}= Create Log Entry ${register_user_info['aef_id']} ${register_user_info_invoker['api_invoker_id']} ${api_ids} ${api_names} + ${request_body}= Create Log Entry + ... ${register_user_info['aef_id']} + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ... ${api_names} ${resp_1}= Post Request Capif ... /api-invocation-logs/v1/${register_user_info['aef_id']}/logs ... json=${request_body} @@ -51,7 +52,6 @@ Get Log Entry ... verify=ca.crt ... username=${AEF_PROVIDER_USERNAME} - ${resp_2}= Get Request Capif ... /logs/v1/apiInvocationLogs?aef-id=${register_user_info['aef_id']}&api-invoker-id=${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} @@ -60,67 +60,56 @@ Get Log Entry # Check Results Check Response Variable Type And Values ${resp_2} 200 InvocationLog - Length Should Be ${resp_2.json()["logs"]} 2 + Length Should Be ${resp_2.json()["logs"]} 2 Get a log entry without entry created [Tags] capif_api_auditing_service-2 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - - - ${resp_1}= Get Request Capif + ${resp_1}= Get Request Capif ... /logs/v1/apiInvocationLogs?aef-id=${register_user_info['aef_id']}&api-invoker-id=${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${AMF_PROVIDER_USERNAME} # Check Results - Check Response Variable Type And Values ${resp_1} 404 ProblemDetails + Check Response Variable Type And Values ${resp_1} 404 ProblemDetails ... title=Not Found ... status=404 ... detail=aefId or/and apiInvokerId do not match any InvocationLogs ... cause=No log invocations found - Get a log entry withut aefid and apiInvokerId [Tags] capif_api_auditing_service-3 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Create Log Entry - ${request_body}= Create Log Entry ${register_user_info['aef_id']} ${register_user_info_invoker['api_invoker_id']} ${api_ids} ${api_names} + ${request_body}= Create Log Entry + ... ${register_user_info['aef_id']} + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ... ${api_names} ${resp_1}= Post Request Capif ... /api-invocation-logs/v1/${AEF_ID_NOT_VALID}/logs ... json=${request_body} @@ -128,48 +117,44 @@ Get a log entry withut aefid and apiInvokerId ... verify=ca.crt ... username=${AEF_PROVIDER_USERNAME} - - ${resp_2}= Get Request Capif + ${resp_2}= Get Request Capif ... /logs/v1/apiInvocationLogs ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${AMF_PROVIDER_USERNAME} # Check Results - Check Response Variable Type And Values ${resp_2} 400 ProblemDetails + Check Response Variable Type And Values ${resp_2} 400 ProblemDetails ... title=Bad Request ... status=400 ... detail=aef_id and api_invoker_id parameters are mandatory ... cause=Mandatory parameters missing - Get Log Entry with apiVersion filter [Tags] capif_api_auditing_service-4 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Create Log Entry - ${request_body}= Create Log Entry ${register_user_info['aef_id']} ${register_user_info_invoker['api_invoker_id']} ${api_ids} ${api_names} + ${request_body}= Create Log Entry + ... ${register_user_info['aef_id']} + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ... ${api_names} ${resp_1}= Post Request Capif ... /api-invocation-logs/v1/${register_user_info['aef_id']}/logs ... json=${request_body} @@ -177,45 +162,41 @@ Get Log Entry with apiVersion filter ... verify=ca.crt ... username=${AEF_PROVIDER_USERNAME} - ${resp_2}= Get Request Capif - ... /logs/v1/apiInvocationLogs?aef-id=${register_user_info['aef_id']}&api-invoker-id=${register_user_info_invoker['api_invoker_id']}&api-version=${API_VERSION_VALID} + ... /logs/v1/apiInvocationLogs?aef-id=${register_user_info['aef_id']}&api-invoker-id=${register_user_info_invoker['api_invoker_id']}&api-version=${API_VERSION_VALID} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${AMF_PROVIDER_USERNAME} # Check Results Check Response Variable Type And Values ${resp_2} 200 InvocationLog - Length Should Be ${resp_2.json()["logs"]} 1 + Length Should Be ${resp_2.json()["logs"]} 1 -Get Log Entry with no exist apiVersion filter +Get Log Entry with no exist apiVersion filter [Tags] capif_api_auditing_service-5 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Create Log Entry - ${request_body}= Create Log Entry ${register_user_info['aef_id']} ${register_user_info_invoker['api_invoker_id']} ${api_ids} ${api_names} + ${request_body}= Create Log Entry + ... ${register_user_info['aef_id']} + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ... ${api_names} ${resp_1}= Post Request Capif ... /api-invocation-logs/v1/${register_user_info['aef_id']}/logs ... json=${request_body} @@ -223,21 +204,16 @@ Get Log Entry with no exist apiVersion filter ... verify=ca.crt ... username=${AEF_PROVIDER_USERNAME} - ${resp_2}= Get Request Capif - ... /logs/v1/apiInvocationLogs?aef-id=${register_user_info['aef_id']}&api-invoker-id=${register_user_info_invoker['api_invoker_id']}&api-version=${API_VERSION_NOT_VALID} + ... /logs/v1/apiInvocationLogs?aef-id=${register_user_info['aef_id']}&api-invoker-id=${register_user_info_invoker['api_invoker_id']}&api-version=${API_VERSION_NOT_VALID} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${AMF_PROVIDER_USERNAME} # Check Results - # Check Results - Check Response Variable Type And Values ${resp_2} 404 ProblemDetails + # Check Results + Check Response Variable Type And Values ${resp_2} 404 ProblemDetails ... title=Not Found ... status=404 ... detail=Parameters do not match any log entry ... cause=No logs found - - - - diff --git a/tests/features/CAPIF Api Discover Service/capif_api_service_discover.robot b/tests/features/CAPIF Api Discover Service/capif_api_service_discover.robot index 0e2a5f7ba27531d9b8470304867ffc3d191dfaca..e780526ce82217446018c8d06aa5fd545eae34d1 100644 --- a/tests/features/CAPIF Api Discover Service/capif_api_service_discover.robot +++ b/tests/features/CAPIF Api Discover Service/capif_api_service_discover.robot @@ -1,12 +1,12 @@ *** Settings *** -Resource /opt/robot-tests/tests/resources/common.resource -Resource /opt/robot-tests/tests/resources/api_invoker_management_requests/apiInvokerManagementRequests.robot -Resource ../../resources/common.resource -Library /opt/robot-tests/tests/libraries/bodyRequests.py +Resource /opt/robot-tests/tests/resources/common.resource +Resource /opt/robot-tests/tests/resources/api_invoker_management_requests/apiInvokerManagementRequests.robot +Resource ../../resources/common.resource +Library /opt/robot-tests/tests/libraries/bodyRequests.py -Test Setup Reset Testing Environment -Suite Teardown Reset Testing Environment -# Test Setup Initialize Test And Register role=invoker +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment *** Variables *** @@ -16,12 +16,9 @@ ${API_INVOKER_NOT_REGISTERED} not-valid *** Test Cases *** Discover Published service APIs by Authorised API Invoker [Tags] capif_api_discover_service-1 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api ${service_api_description_published} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info} @@ -29,9 +26,6 @@ Discover Published service APIs by Authorised API Invoker # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${resp}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info['aef_id']} @@ -45,26 +39,19 @@ Discover Published service APIs by Authorised API Invoker Dictionary Should Contain Key ${resp.json()} serviceAPIDescriptions Should Not Be Empty ${resp.json()['serviceAPIDescriptions']} Length Should Be ${resp.json()['serviceAPIDescriptions']} 1 - List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published} - + List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published} Discover Published service APIs by Non Authorised API Invoker [Tags] capif_api_discover_service-2 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} @@ -80,21 +67,15 @@ Discover Published service APIs by Non Authorised API Invoker Discover Published service APIs by not registered API Invoker [Tags] capif_api_discover_service-3 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Get Request Capif ... ${DISCOVER_URL}${API_INVOKER_NOT_REGISTERED} ... server=${CAPIF_HTTPS_URL} @@ -110,12 +91,9 @@ Discover Published service APIs by not registered API Invoker Discover Published service APIs by registered API Invoker with 1 result filtered [Tags] capif_api_discover_service-4 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name_1}= Set Variable service_1 ${api_name_2}= Set Variable service_2 @@ -130,9 +108,6 @@ Discover Published service APIs by registered API Invoker with 1 result filtered # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Request all APIs for Invoker ${resp}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info['aef_id']} @@ -145,8 +120,8 @@ Discover Published service APIs by registered API Invoker with 1 result filtered # Check returned values Should Not Be Empty ${resp.json()['serviceAPIDescriptions']} Length Should Be ${resp.json()['serviceAPIDescriptions']} 2 - List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_1} - List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_2} + List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_1} + List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_2} # Request api 1 ${resp}= Get Request Capif @@ -164,12 +139,9 @@ Discover Published service APIs by registered API Invoker with 1 result filtered Discover Published service APIs by registered API Invoker filtered with no match [Tags] capif_api_discover_service-5 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name_1}= Set Variable apiName1 ${api_name_2}= Set Variable apiName2 @@ -184,9 +156,6 @@ Discover Published service APIs by registered API Invoker filtered with no match # Change to invoker role and register at api invoker management ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Request all APIs for Invoker ${resp}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info['aef_id']} @@ -199,8 +168,8 @@ Discover Published service APIs by registered API Invoker filtered with no match # Check returned values Should Not Be Empty ${resp.json()['serviceAPIDescriptions']} Length Should Be ${resp.json()['serviceAPIDescriptions']} 2 - List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_1} - List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_2} + List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_1} + List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_2} # Request api 1 ${resp}= Get Request Capif @@ -210,7 +179,10 @@ Discover Published service APIs by registered API Invoker filtered with no match ... username=${INVOKER_USERNAME} # Check Results - Check Response Variable Type And Values ${resp} 404 ProblemDetails + Check Response Variable Type And Values + ... ${resp} + ... 404 + ... ProblemDetails ... title=Not Found ... status=404 ... detail=API Invoker ${register_user_info_invoker['api_invoker_id']} has no API Published that accomplish filter conditions @@ -218,12 +190,9 @@ Discover Published service APIs by registered API Invoker filtered with no match Discover Published service APIs by registered API Invoker not filtered [Tags] capif_api_discover_service-6 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name_1}= Set Variable apiName1 ${api_name_2}= Set Variable apiName2 @@ -238,9 +207,6 @@ Discover Published service APIs by registered API Invoker not filtered # Change to invoker role and register at api invoker management ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Request all APIs for Invoker ${resp}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info['aef_id']} @@ -253,5 +219,5 @@ Discover Published service APIs by registered API Invoker not filtered # Check Results Should Not Be Empty ${resp.json()['serviceAPIDescriptions']} Length Should Be ${resp.json()['serviceAPIDescriptions']} 2 - List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_1} - List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_2} + List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_1} + List Should Contain Value ${resp.json()['serviceAPIDescriptions']} ${service_api_description_published_2} diff --git a/tests/features/CAPIF Api Events/capif_events_api.robot b/tests/features/CAPIF Api Events/capif_events_api.robot index aecff959070855eaff11efbe3893fffa8199c38f..fdec6a935ef0baf5386597f91a655d1a57f79e31 100644 --- a/tests/features/CAPIF Api Events/capif_events_api.robot +++ b/tests/features/CAPIF Api Events/capif_events_api.robot @@ -1,12 +1,14 @@ *** Settings *** -Resource /opt/robot-tests/tests/resources/common.resource -Library /opt/robot-tests/tests/libraries/bodyRequests.py -Library XML -Resource /opt/robot-tests/tests/resources/common/basicRequests.robot -Resource ../../resources/common.resource +Resource /opt/robot-tests/tests/resources/common.resource +Library /opt/robot-tests/tests/libraries/bodyRequests.py +Library XML +Library String +Resource /opt/robot-tests/tests/resources/common/basicRequests.robot +Resource ../../resources/common.resource -Test Setup Reset Testing Environment -Suite Teardown Reset Testing Environment +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment *** Variables *** @@ -21,9 +23,6 @@ Creates a new individual CAPIF Event Subscription # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Events Subscription ${resp}= Post Request Capif ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions @@ -41,9 +40,6 @@ Creates a new individual CAPIF Event Subscription with Invalid SubscriberId # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Events Subscription ${resp}= Post Request Capif ... /capif-events/v1/${SUBSCRIBER_ID_NOT_VALID}/subscriptions @@ -53,7 +49,7 @@ Creates a new individual CAPIF Event Subscription with Invalid SubscriberId ... username=${INVOKER_USERNAME} # Check Results - Check Response Variable Type And Values ${resp} 404 ProblemDetails + Check Response Variable Type And Values ${resp} 404 ProblemDetails ... title=Not Found ... status=404 ... detail=Invoker or APF or AEF or AMF Not found @@ -64,9 +60,6 @@ Deletes an individual CAPIF Event Subscription # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Events Subscription ${resp}= Post Request Capif ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions @@ -92,9 +85,6 @@ Deletes an individual CAPIF Event Subscription with invalid SubscriberId # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Events Subscription ${resp}= Post Request Capif ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions @@ -112,24 +102,20 @@ Deletes an individual CAPIF Event Subscription with invalid SubscriberId ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - + # Check Results - Check Response Variable Type And Values ${resp} 404 ProblemDetails + Check Response Variable Type And Values ${resp} 404 ProblemDetails ... title=Not Found ... status=404 ... detail=Invoker or APF or AEF or AMF Not found ... cause=Subscriber Not Found - Deletes an individual CAPIF Event Subscription with invalid SubscriptionId [Tags] capif_api_events-5 # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Events Subscription ${resp}= Post Request Capif ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions @@ -154,3 +140,664 @@ Deletes an individual CAPIF Event Subscription with invalid SubscriptionId ... detail=User not authorized ... cause=You are not the owner of this resource +Invoker receives Service API Invocation events + [Tags] capif_api_events-6 mockserver + + # Initialize Mock server + Init Mock Server + + # Register APF + ${register_user_info}= Provider Default Registration + + # Publish one api + Publish Service Api ${register_user_info} + + # Register INVOKER + ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding + + ${discover_response}= Get Request Capif + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + + # Subscribe to events + ${events_list}= Create List SERVICE_API_INVOCATION_SUCCESS SERVICE_API_INVOCATION_FAILURE + ${aef_ids}= Create List ${register_user_info['aef_id']} + ${event_filter}= Create Capif Event Filter aefIds=${aef_ids} + ${event_filters}= Create List ${event_filter} + + ${request_body}= Create Events Subscription + ... events=@{events_list} + ... notificationDestination=${MOCK_SERVER_URL}/testing + ... eventFilters=${event_filters} + ${resp}= Post Request Capif + ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Results + Check Response Variable Type And Values ${resp} 201 EventSubscription + ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} + + # Create Log Entry, emulate success and failure api invocation + ${results}= Create List 200 400 + ${request_body}= Create Log Entry + ... ${register_user_info['aef_id']} + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ... ${api_names} + ... results=${results} + ${resp}= Post Request Capif + ... /api-invocation-logs/v1/${register_user_info['aef_id']}/logs + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${AEF_PROVIDER_USERNAME} + + # Check Results + Check Response Variable Type And Values ${resp} 201 InvocationLog + ${resource_url}= Check Location Header ${resp} ${LOCATION_LOGGING_RESOURCE_REGEX} + + # Check Event Notifications + ## Create check Events to ensure all notifications were received + ${events_expected}= Create Events From InvocationLogs + ... ${subscription_id} + ... ${request_body} + ## Check Events Expected towards received notifications at mock server + Check Mock Server Notification Events ${events_expected} + +Invoker subscribe to Service API Available and Unavailable events + [Tags] capif_api_events-7 mockserver + + # Initialize Mock server + Init Mock Server + + # Register APF + ${register_user_info_provider}= Provider Default Registration + + # Publish one api + ${service_api_description_published_1} ${resource_url_1} ${request_body}= Publish Service Api + ... ${register_user_info_provider} + + # Register INVOKER + ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding + + ${discover_response}= Get Request Capif + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + + # Subscribe to events + ${events_list}= Create List SERVICE_API_AVAILABLE SERVICE_API_UNAVAILABLE + ${aef_ids}= Create List ${register_user_info_provider['aef_id']} + ${event_filter}= Create Capif Event Filter aefIds=${aef_ids} + ${event_filters}= Create List ${event_filter} + + ${request_body}= Create Events Subscription + ... events=@{events_list} + ... notificationDestination=${MOCK_SERVER_URL}/testing + ... eventFilters=${event_filters} + ${resp}= Post Request Capif + ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Results + Check Response Variable Type And Values ${resp} 201 EventSubscription + ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} + + # Provider publish new API + ${service_api_description_published_2} ${resource_url_2} ${request_body}= Publish Service Api + ... ${register_user_info_provider} + ... service_2 + + # Provider Remove service_1 published API + ${resp}= Delete Request Capif + ... ${resource_url_1.path} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${APF_PROVIDER_USERNAME} + + Status Should Be 204 ${resp} + + # Check Event Notifications + ## Create check Events to ensure all notifications were received + ${service_api_available_resources}= Create List ${resource_url_2} + ${service_api_unavailable_resources}= Create List ${resource_url_1} + ${events_expected}= Create Expected Events For Service API Notifications + ... subscription_id=${subscription_id} + ... service_api_available_resources=${service_api_available_resources} + ... service_api_unavailable_resources=${service_api_unavailable_resources} + ## Check Events Expected towards received notifications at mock server + Check Mock Server Notification Events ${events_expected} + +Invoker subscribe to Service API Update + [Tags] capif_api_events-8 mockserver + + # Initialize Mock server + Init Mock Server + + # Register APF + ${register_user_info_provider}= Provider Default Registration + + # Publish one api + ${service_api_description_published} ${resource_url} ${request_body}= Publish Service Api + ... ${register_user_info_provider} + + # Register INVOKER + ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding + + ${discover_response}= Get Request Capif + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + + # Subscribe to events + ${events_list}= Create List SERVICE_API_UPDATE + ${aef_ids}= Create List ${register_user_info_provider['aef_id']} + ${event_filter}= Create Capif Event Filter aefIds=${aef_ids} + ${event_filters}= Create List ${event_filter} + + ${request_body}= Create Events Subscription + ... events=@{events_list} + ... notificationDestination=${MOCK_SERVER_URL}/testing + ... eventFilters=${event_filters} + ${resp}= Post Request Capif + ... /capif-events/v1/${register_user_info_invoker['api_invoker_id']}/subscriptions + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Results + Check Response Variable Type And Values ${resp} 201 EventSubscription + ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} + + # Update Service API + ${service_api_description_modified}= Create Service Api Description service_1_modified + ${resp}= Put Request Capif + ... ${resource_url.path} + ... json=${service_api_description_modified} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${APF_PROVIDER_USERNAME} + + Check Response Variable Type And Values ${resp} 200 ServiceAPIDescription + ... apiName=service_1_modified + + # Check Event Notifications + ## Create check Events to ensure all notifications were received + ${events_expected}= Create Expected Service Update Event ${subscription_id} ${resource_url} ${service_api_description_modified} + ## Check Events Expected towards received notifications at mock server + Check Mock Server Notification Events ${events_expected} + +Provider subscribe to API Invoker events + [Tags] capif_api_events-9 mockserver + + # Initialize Mock server + Init Mock Server + + # Register APF + ${register_user_info_provider}= Provider Default Registration + + # Subscribe to events + ${events_list}= Create List API_INVOKER_ONBOARDED API_INVOKER_UPDATED API_INVOKER_OFFBOARDED + ${request_body}= Create Events Subscription + ... events=@{events_list} + ... notificationDestination=${MOCK_SERVER_URL}/testing + ${resp}= Post Request Capif + ... /capif-events/v1/${register_user_info_provider['amf_id']}/subscriptions + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${AMF_PROVIDER_USERNAME} + + # Check Results + Check Response Variable Type And Values ${resp} 201 EventSubscription + ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} + + # Register INVOKER + ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding + + # Update Invoker onboarded information + ${new_notification_destination}= Set Variable + ... http://${CAPIF_CALLBACK_IP}:${CAPIF_CALLBACK_PORT}/netapp_new_callback + Set To Dictionary + ... ${request_body} + ... notificationDestination=${new_notification_destination} + ${resp}= Put Request Capif + ... ${url.path} + ... ${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Update + Check Response Variable Type And Values ${resp} 200 APIInvokerEnrolmentDetails + ... notificationDestination=${new_notification_destination} + + # Remove Invoker from CCF + ${resp}= Delete Request Capif + ... ${url.path} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + Call Method ${CAPIF_USERS} remove_capif_users_entry ${url.path} + + # Check Remove + Should Be Equal As Strings ${resp.status_code} 204 + + # Check Event Notifications + ## Create check Events to ensure all notifications were received + ${events_expected}= Create Expected Api Invoker Events + ... ${subscription_id} + ... ${register_user_info_invoker['api_invoker_id']} + ## Check Events Expected towards received notifications at mock server + Check Mock Server Notification Events ${events_expected} + +Invoker subscribed to ACL update event + [Tags] capif_api_events-10 mockserver + + # Initialize Mock server + Init Mock Server + + # Register APF + ${register_user_info_provider}= Provider Default Registration + + # Publish one api + ${service_api_description_published} ${resource_url} ${request_body}= Publish Service Api + ... ${register_user_info_provider} + + # Store apiId1 + ${service_api_id}= Set Variable ${service_api_description_published['apiId']} + + # Register INVOKER + ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding + + # Subscribe to events + ${events_list}= Create List ACCESS_CONTROL_POLICY_UPDATE + ${request_body}= Create Events Subscription + ... events=@{events_list} + ... notificationDestination=${MOCK_SERVER_URL}/testing + ${resp}= Post Request Capif + ... /capif-events/v1/${register_user_info_provider['amf_id']}/subscriptions + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${AMF_PROVIDER_USERNAME} + + # Check Results + Check Response Variable Type And Values ${resp} 201 EventSubscription + ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} + + # Test + ${discover_response}= Get Request Capif + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + Check Response Variable Type And Values ${discover_response} 200 DiscoveredAPIs + + # create Security Context + ${request_service_security_body}= Create Service Security From Discover Response + ... http://${CAPIF_HOSTNAME}:${CAPIF_HTTP_PORT}/test + ... ${discover_response} + ${resp}= Put Request Capif + ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} + ... json=${request_service_security_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Service Security + Check Response Variable Type And Values ${resp} 201 ServiceSecurity + ${resource_url}= Check Location Header ${resp} ${LOCATION_SECURITY_RESOURCE_REGEX} + + ${resp}= Get Request Capif + ... /access-control-policy/v1/accessControlPolicyList/${service_api_id}?aef-id=${register_user_info_provider['aef_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${AEF_PROVIDER_USERNAME} + + Check Response Variable Type And Values ${resp} 200 AccessControlPolicyList + # Check returned values + Should Not Be Empty ${resp.json()['apiInvokerPolicies']} + Length Should Be ${resp.json()['apiInvokerPolicies']} 1 + Should Be Equal As Strings + ... ${resp.json()['apiInvokerPolicies'][0]['apiInvokerId']} + ... ${register_user_info_invoker['api_invoker_id']} + + ${api_invoker_policies}= Set Variable ${resp.json()['apiInvokerPolicies']} + + # Check Event Notifications + ## Create check Events to ensure all notifications were received + ${events_expected}= Create Expected Access Control Policy Update Event + ... ${subscription_id} + ... ${service_api_id} + ... ${api_invoker_policies} + ## Check Events Expected towards received notifications at mock server + Check Mock Server Notification Events ${events_expected} + +Provider receives an ACL unavailable event when invoker remove Security Context. + [Tags] capif_api_events-11 mockserver + + # Initialize Mock server + Init Mock Server + + # Register APF + ${register_user_info_provider}= Provider Default Registration + + # Publish one api + ${service_api_description_published} ${resource_url} ${request_body}= Publish Service Api + ... ${register_user_info_provider} + + # Store apiId1 + ${serviceApiId}= Set Variable ${service_api_description_published['apiId']} + + # Register INVOKER + ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding + + # Subscribe to events + ${events_list}= Create List ACCESS_CONTROL_POLICY_UNAVAILABLE + ${request_body}= Create Events Subscription + ... events=@{events_list} + ... notificationDestination=${MOCK_SERVER_URL}/testing + ${resp}= Post Request Capif + ... /capif-events/v1/${register_user_info_provider['amf_id']}/subscriptions + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Results + Check Response Variable Type And Values ${resp} 201 EventSubscription + ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} + + # Test + ${discover_response}= Get Request Capif + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + Check Response Variable Type And Values ${discover_response} 200 DiscoveredAPIs + + # create Security Context + ${request_service_security_body}= Create Service Security From Discover Response + ... http://${CAPIF_HOSTNAME}:${CAPIF_HTTP_PORT}/test + ... ${discover_response} + ${resp}= Put Request Capif + ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} + ... json=${request_service_security_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Service Security + Check Response Variable Type And Values ${resp} 201 ServiceSecurity + ${resource_url}= Check Location Header ${resp} ${LOCATION_SECURITY_RESOURCE_REGEX} + + # Remove Security Context by Provider + ${resp}= Delete Request Capif + ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${AEF_PROVIDER_USERNAME} + + Status Should Be 204 ${resp} + + # Check Event Notifications + ## Create check Events to ensure all notifications were received + ${events_expected}= Create Expected Access Control Policy Unavailable ${subscription_id} + ## Check Events Expected towards received notifications at mock server + Check Mock Server Notification Events ${events_expected} + +Invoker receives an Invoker Authorization Revoked and ACL unavailable event when Provider revoke Invoker Authorization. + [Tags] capif_api_events-12 mockserver + + # Initialize Mock server + Init Mock Server + + # Register APF + ${register_user_info_provider}= Provider Default Registration + + # Publish one api + ${service_api_description_published} ${resource_url} ${request_body}= Publish Service Api + ... ${register_user_info_provider} + + # Store apiId1 + ${serviceApiId}= Set Variable ${service_api_description_published['apiId']} + + # Register INVOKER + ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding + + # Subscribe to events + ${events_list}= Create List ACCESS_CONTROL_POLICY_UNAVAILABLE API_INVOKER_AUTHORIZATION_REVOKED + ${request_body}= Create Events Subscription + ... events=@{events_list} + ... notificationDestination=${MOCK_SERVER_URL}/testing + ${resp}= Post Request Capif + ... /capif-events/v1/${register_user_info_provider['amf_id']}/subscriptions + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Results + Check Response Variable Type And Values ${resp} 201 EventSubscription + ${subscriber_id} ${subscription_id}= Check Event Location Header ${resp} + + # Test + ${discover_response}= Get Request Capif + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + Check Response Variable Type And Values ${discover_response} 200 DiscoveredAPIs + + ${api_ids}= Get Api Ids From Discover Response ${discover_response} + + # create Security Context + ${request_service_security_body}= Create Service Security From Discover Response + ... http://${CAPIF_HOSTNAME}:${CAPIF_HTTP_PORT}/test + ... ${discover_response} + ${resp}= Put Request Capif + ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} + ... json=${request_service_security_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${INVOKER_USERNAME} + + # Check Service Security + Check Response Variable Type And Values ${resp} 201 ServiceSecurity + ${resource_url}= Check Location Header ${resp} ${LOCATION_SECURITY_RESOURCE_REGEX} + + # Revoke Security Context by Provider + ${request_body}= Create Security Notification Body + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ${resp}= Post Request Capif + ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']}/delete + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${AEF_PROVIDER_USERNAME} + + # Check Results + Status Should Be 204 ${resp} + + # Check Event Notifications + ## Create check Events to ensure all notifications were received + ${events_expected}= Create Expected Access Control Policy Unavailable ${subscription_id} + ${events_expected}= Create Expected Api Invoker Authorization Revoked + ... ${subscription_id} + ... events_expected=${events_expected} + ## Check Events Expected towards received notifications at mock server + Check Mock Server Notification Events ${events_expected} + + +*** Keywords *** +Create Events From InvocationLogs + [Arguments] ${subscription_id} ${invocation_log} ${events_expected}=${NONE} + IF ${events_expected} == ${NONE} + ${events_expected}= Create List + END + + # Now we create the expected events received at notification server according to logs sent to loggin service in order to check if all are present. + ${invocation_log_base}= Copy Dictionary ${invocation_log} deepcopy=True + # Store log array because each log will be notified in one Event Notification + ${invocation_log_logs}= Copy List ${invocation_log_base['logs']} + # Remove logs array from invocationLog data + Remove From Dictionary ${invocation_log_base} logs + + FOR ${log} IN @{invocation_log_logs} + Log Dictionary ${log} + ${invocation_logs}= Copy Dictionary ${invocation_log_base} deepcopy=True + + # Get Event Enum for this result + ${event_enum}= Set Variable + IF ${log['result']} >= 200 and ${log['result']} < 300 + ${event_enum}= Set Variable SERVICE_API_INVOCATION_SUCCESS + ELSE + ${event_enum}= Set Variable SERVICE_API_INVOCATION_FAILURE + END + # Create a log array with only one component + ${log_list}= Create List ${log} + # Setup logs array with previously created list + Set To Dictionary ${invocation_logs} logs=${log_list} + ${event_expected}= Create Notification Event ${subscription_id} ${event_enum} invocationLogs=${invocation_logs} + Append To List ${events_expected} ${event_expected} + END + + RETURN ${events_expected} +Create Expected Events For Service API Notifications + [Arguments] + ... ${subscription_id} + ... ${service_api_available_resources}=${NONE} + ... ${service_api_unavailable_resources}=${NONE} + ... ${events_expected}=${NONE} + + IF ${events_expected} == ${NONE} + ${events_expected}= Create List + END + + FOR ${service_api_available_resource} IN @{service_api_available_resources} + Log ${service_api_available_resource} + ${api_id}= Fetch From Right ${service_api_available_resource.path} / + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... SERVICE_API_AVAILABLE + ... apiIds=${api_id} + Append To List ${events_expected} ${event_expected} + END + + FOR ${service_api_unavailable_resource} IN @{service_api_unavailable_resources} + Log ${service_api_unavailable_resource} + ${api_id}= Fetch From Right ${service_api_unavailable_resource.path} / + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... SERVICE_API_UNAVAILABLE + ... apiIds=${api_id} + Append To List ${events_expected} ${event_expected} + END + + RETURN ${events_expected} + +Create Expected Api Invoker Events + [Arguments] ${subscription_id} ${api_invoker_id} ${events_expected}=${NONE} + IF ${events_expected} == ${NONE} + ${events_expected}= Create List + END + ## Create events expected + # Create Notification Events expected to be received for Onboard event + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... API_INVOKER_ONBOARDED + ... apiInvokerIds=${api_invoker_id} + Append To List ${events_expected} ${event_expected} + + # Create Notification Events expected to be received for Updated event + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... API_INVOKER_UPDATED + ... apiInvokerIds=${api_invoker_id} + Append To List ${events_expected} ${event_expected} + + # Create Notification Events expected to be received for Offboard event + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... API_INVOKER_OFFBOARDED + ... apiInvokerIds=${api_invoker_id} + Append To List ${events_expected} ${event_expected} + + RETURN ${events_expected} + +Create Expected Access Control Policy Update Event + [Arguments] ${subscription_id} ${service_api_id} ${api_invoker_policies} ${events_expected}=${NONE} + IF ${events_expected} == ${NONE} + ${events_expected}= Create List + END + ${acc_ctrl_pol_list}= Create Dictionary apiId=${service_api_id} apiInvokerPolicies=${api_invoker_policies} + Check Variable ${acc_ctrl_pol_list} AccessControlPolicyListExt + + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... ACCESS_CONTROL_POLICY_UPDATE + ... accCtrlPolList=${acc_ctrl_pol_list} + Append To List ${events_expected} ${event_expected} + + RETURN ${events_expected} + +Create Expected Access Control Policy Unavailable + [Arguments] ${subscription_id} ${events_expected}=${NONE} + IF ${events_expected} == ${NONE} + ${events_expected}= Create List + END + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... ACCESS_CONTROL_POLICY_UNAVAILABLE + Append To List ${events_expected} ${event_expected} + + RETURN ${events_expected} + +Create Expected Api Invoker Authorization Revoked + [Arguments] ${subscription_id} ${events_expected}=${NONE} + IF ${events_expected} == ${NONE} + ${events_expected}= Create List + END + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... API_INVOKER_AUTHORIZATION_REVOKED + Append To List ${events_expected} ${event_expected} + RETURN ${events_expected} + +Create Expected Service Update Event + [Arguments] ${subscription_id} ${service_api_resource} ${service_api_descriptions} ${events_expected}=${NONE} + IF ${events_expected} == ${NONE} + ${events_expected}= Create List + END + ${api_id}= Fetch From Right ${service_api_resource.path} / + Set To Dictionary ${service_api_descriptions} apiId=${api_id} + ${events_expected}= Create List + ${event_expected}= Create Notification Event + ... ${subscription_id} + ... SERVICE_API_UPDATE + ... serviceAPIDescriptions=${service_api_descriptions} + Append To List ${events_expected} ${event_expected} + RETURN ${events_expected} \ No newline at end of file diff --git a/tests/features/CAPIF Api Invoker Management/capif_api_invoker_managenet.robot b/tests/features/CAPIF Api Invoker Management/capif_api_invoker_managenet.robot index 48eaa879065564a02d73836e6de26ec144880f01..6ab8ba5d01336f44a27edf13f83da7539ed1e53f 100644 --- a/tests/features/CAPIF Api Invoker Management/capif_api_invoker_managenet.robot +++ b/tests/features/CAPIF Api Invoker Management/capif_api_invoker_managenet.robot @@ -1,13 +1,14 @@ *** Settings *** -Resource /opt/robot-tests/tests/resources/common.resource -Resource /opt/robot-tests/tests/resources/api_invoker_management_requests/apiInvokerManagementRequests.robot -Resource ../../resources/common.resource -Library /opt/robot-tests/tests/libraries/bodyRequests.py -Library Process -Library Collections +Resource /opt/robot-tests/tests/resources/common.resource +Resource /opt/robot-tests/tests/resources/api_invoker_management_requests/apiInvokerManagementRequests.robot +Resource ../../resources/common.resource +Library /opt/robot-tests/tests/libraries/bodyRequests.py +Library Process +Library Collections -Test Setup Reset Testing Environment -Suite Teardown Reset Testing Environment +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment *** Variables *** @@ -15,9 +16,9 @@ ${API_INVOKER_NOT_REGISTERED} not-valid *** Test Cases *** -Onboard NetApp +Onboard Network App [Tags] capif_api_invoker_management-1 - #Register Netapp + # Register Network App ${register_user_info}= Register User At Jwt Auth ... username=${INVOKER_USERNAME} role=${INVOKER_ROLE} @@ -34,23 +35,19 @@ Onboard NetApp ... access_token=${register_user_info['access_token']} # Check Results - Check Response Variable Type And Values ${resp} 201 APIInvokerEnrolmentDetails + Check Response Variable Type And Values ${resp} 201 APIInvokerEnrolmentDetails ${url}= Parse Url ${resp.headers['Location']} - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} + Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} Check Location Header ${resp} ${LOCATION_INVOKER_RESOURCE_REGEX} # Store dummy signed certificate Store In File ${INVOKER_USERNAME}.crt ${resp.json()['onboardingInformation']['apiInvokerCertificate']} -Register NetApp Already Onboarded +Register Network App Already Onboarded [Tags] capif_api_invoker_management-2 # Default Invoker Registration and Onboarding ${register_user_info} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Post Request Capif ... ${register_user_info['ccf_onboarding_url']} ... json=${request_body} @@ -65,16 +62,13 @@ Register NetApp Already Onboarded ... detail=Invoker already registered ... cause=Identical invoker public key -Update Onboarded NetApp +Update Onboarded Network App [Tags] capif_api_invoker_management-3 ${new_notification_destination}= Set Variable ... http://${CAPIF_CALLBACK_IP}:${CAPIF_CALLBACK_PORT}/netapp_new_callback # Default Invoker Registration and Onboarding ${register_user_info} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - Set To Dictionary ... ${request_body} ... notificationDestination=${new_notification_destination} @@ -90,14 +84,11 @@ Update Onboarded NetApp Check Response Variable Type And Values ${resp} 200 APIInvokerEnrolmentDetails ... notificationDestination=${new_notification_destination} -Update Not Onboarded NetApp +Update Not Onboarded Network App [Tags] capif_api_invoker_management-4 # Default Invoker Registration and Onboarding ${register_user_info} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Put Request Capif ... /api-invoker-management/v1/onboardedInvokers/${INVOKER_NOT_REGISTERED} ... ${request_body} @@ -109,33 +100,30 @@ Update Not Onboarded NetApp Check Response Variable Type And Values ${resp} 404 ProblemDetails ... status=404 ... title=Not Found - ... detail=Please provide an existing Netapp ID - ... cause=Not exist NetappID + ... detail=Please provide an existing Network App ID + ... cause=Not exist Network App ID -Offboard NetApp +Offboard Network App [Tags] capif_api_invoker_management-5 # Default Invoker Registration and Onboarding ${register_user_info} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Delete Request Capif ... ${url.path} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} + + Call Method ${CAPIF_USERS} remove_capif_users_entry ${url.path} # Check Results Should Be Equal As Strings ${resp.status_code} 204 -Offboard Not Previously Onboarded NetApp +Offboard Not Previously Onboarded Network App [Tags] capif_api_invoker_management-6 # Default Invoker Registration and Onboarding ${register_user_info} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Delete Request Capif ... /api-invoker-management/v1/onboardedInvokers/${INVOKER_NOT_REGISTERED} ... server=${CAPIF_HTTPS_URL} @@ -146,20 +134,17 @@ Offboard Not Previously Onboarded NetApp Check Response Variable Type And Values ${resp} 404 ProblemDetails ... status=404 ... title=Not Found - ... detail=Please provide an existing Netapp ID - ... cause=Not exist NetappID + ... detail=Please provide an existing Network App ID + ... cause=Not exist Network App ID -Update Onboarded NetApp Certificate +Update Onboarded Network App Certificate [Tags] capif_api_invoker_management-7 ${new_notification_destination}= Set Variable ... http://${CAPIF_CALLBACK_IP}:${CAPIF_CALLBACK_PORT}/netapp_new_callback # Default Invoker Registration and Onboarding ${register_user_info} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - - ${INVOKER_USERNAME_NEW}= Set Variable ${INVOKER_USERNAME}_NEW + ${INVOKER_USERNAME_NEW}= Set Variable ${INVOKER_USERNAME}_NEW ${csr_request_new}= Create User Csr ${INVOKER_USERNAME_NEW} invoker @@ -197,5 +182,3 @@ Update Onboarded NetApp Certificate # Check Results Check Response Variable Type And Values ${resp} 200 APIInvokerEnrolmentDetails ... notificationDestination=${new_notification_destination} - - diff --git a/tests/features/CAPIF Api Logging Service/capif_logging_api.robot b/tests/features/CAPIF Api Logging Service/capif_logging_api.robot index de9c6726f983a28bfe631bd0bb8090d73ea8de91..4db54b2c821ca4e25835fb72b7c8095441e43157 100644 --- a/tests/features/CAPIF Api Logging Service/capif_logging_api.robot +++ b/tests/features/CAPIF Api Logging Service/capif_logging_api.robot @@ -1,12 +1,14 @@ *** Settings *** -Resource /opt/robot-tests/tests/resources/common.resource -Library /opt/robot-tests/tests/libraries/bodyRequests.py -Library Collections -Resource /opt/robot-tests/tests/resources/common/basicRequests.robot -Resource ../../resources/common.resource +Resource /opt/robot-tests/tests/resources/common.resource +Library /opt/robot-tests/tests/libraries/bodyRequests.py +Library Collections +Resource /opt/robot-tests/tests/resources/common/basicRequests.robot +Resource ../../resources/common.resource + +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment -Test Setup Reset Testing Environment -Suite Teardown Reset Testing Environment *** Variables *** ${AEF_ID_NOT_VALID} aef-example @@ -14,34 +16,33 @@ ${SERVICE_API_ID_NOT_VALID} not-valid ${API_INVOKER_NOT_VALID} not-valid ${NOTIFICATION_DESTINATION} http://robot.testing:1080 + *** Test Cases *** Create a log entry [Tags] capif_api_logging_service-1 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Create Log Entry - ${request_body}= Create Log Entry ${register_user_info['aef_id']} ${register_user_info_invoker['api_invoker_id']} ${api_ids} ${api_names} + ${request_body}= Create Log Entry + ... ${register_user_info['aef_id']} + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ... ${api_names} ${resp}= Post Request Capif ... /api-invocation-logs/v1/${register_user_info['aef_id']}/logs ... json=${request_body} @@ -49,38 +50,35 @@ Create a log entry ... verify=ca.crt ... username=${AEF_PROVIDER_USERNAME} - # Check Results Check Response Variable Type And Values ${resp} 201 InvocationLog ${resource_url}= Check Location Header ${resp} ${LOCATION_LOGGING_RESOURCE_REGEX} Create a log entry invalid aefId [Tags] capif_api_logging_service-2 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Create Log Entry - ${request_body}= Create Log Entry ${register_user_info['aef_id']} ${register_user_info_invoker['api_invoker_id']} ${api_ids} ${api_names} + ${request_body}= Create Log Entry + ... ${register_user_info['aef_id']} + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ... ${api_names} ${resp}= Post Request Capif ... /api-invocation-logs/v1/${AEF_ID_NOT_VALID}/logs ... json=${request_body} @@ -89,31 +87,23 @@ Create a log entry invalid aefId ... username=${AEF_PROVIDER_USERNAME} # Check Results - Check Response Variable Type And Values ${resp} 404 ProblemDetails + Check Response Variable Type And Values ${resp} 404 ProblemDetails ... title=Not Found ... status=404 ... detail=Exposer not exist ... cause=Exposer id not found - - Create a log entry invalid serviceApi [Tags] capif_api_logging_service-3 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} @@ -121,7 +111,9 @@ Create a log entry invalid serviceApi ... username=${INVOKER_USERNAME} # Create Log Entry - ${request_body}= Create Log Entry Bad Service ${register_user_info['aef_id']} ${register_user_info_invoker['api_invoker_id']} + ${request_body}= Create Log Entry Bad Service + ... ${register_user_info['aef_id']} + ... ${register_user_info_invoker['api_invoker_id']} ${resp}= Post Request Capif ... /api-invocation-logs/v1/${register_user_info['aef_id']}/logs ... json=${request_body} @@ -137,31 +129,29 @@ Create a log entry invalid serviceApi Create a log entry invalid apiInvokerId [Tags] capif_api_logging_service-4 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Create Log Entry - ${request_body}= Create Log Entry ${register_user_info['aef_id']} ${API_INVOKER_NOT_VALID} ${api_ids} ${api_names} + ${request_body}= Create Log Entry + ... ${register_user_info['aef_id']} + ... ${API_INVOKER_NOT_VALID} + ... ${api_ids} + ... ${api_names} ${resp}= Post Request Capif ... /api-invocation-logs/v1/${register_user_info['aef_id']}/logs ... json=${request_body} @@ -176,35 +166,31 @@ Create a log entry invalid apiInvokerId ... detail=Invoker not exist ... cause=Invoker id not found - Create a log entry different aef_id in body [Tags] capif_api_logging_service-5 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish one api Publish Service Api ${register_user_info} - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - - ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} - ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} + ${api_ids} ${api_names}= Get Api Ids And Names From Discover Response ${discover_response} # Create Log Entry - ${request_body}= Create Log Entry ${AEF_ID_NOT_VALID} ${register_user_info_invoker['api_invoker_id']} ${api_ids} ${api_names} + ${request_body}= Create Log Entry + ... ${AEF_ID_NOT_VALID} + ... ${register_user_info_invoker['api_invoker_id']} + ... ${api_ids} + ... ${api_names} ${resp}= Post Request Capif ... /api-invocation-logs/v1/${register_user_info['aef_id']}/logs ... json=${request_body} @@ -218,4 +204,3 @@ Create a log entry different aef_id in body ... status=401 ... detail=AEF id not matching in request and body ... cause=Not identical AEF id - diff --git a/tests/features/CAPIF Api Provider Management/capif_api_provider_management.robot b/tests/features/CAPIF Api Provider Management/capif_api_provider_management.robot index fd70925603b386487b54f0c2a01de3b543be2979..31aa55e8b6415c40fbff2ab56a3a7e6972a6505f 100644 --- a/tests/features/CAPIF Api Provider Management/capif_api_provider_management.robot +++ b/tests/features/CAPIF Api Provider Management/capif_api_provider_management.robot @@ -1,12 +1,13 @@ *** Settings *** -Resource /opt/robot-tests/tests/resources/common.resource -Resource ../../resources/common.resource -Library /opt/robot-tests/tests/libraries/bodyRequests.py -Library Process -Library Collections +Resource /opt/robot-tests/tests/resources/common.resource +Resource ../../resources/common.resource +Library /opt/robot-tests/tests/libraries/bodyRequests.py +Library Process +Library Collections -Test Setup Reset Testing Environment -Suite Teardown Reset Testing Environment +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment *** Variables *** @@ -16,7 +17,7 @@ ${API_PROVIDER_NOT_REGISTERED} notValid *** Test Cases *** Register Api Provider [Tags] capif_api_provider_management-1 - #Register Provider User An create Certificates for each function + # Register Provider User An create Certificates for each function ${register_user_info}= Register User At Jwt Auth Provider ... username=${PROVIDER_USERNAME} role=${PROVIDER_ROLE} @@ -51,12 +52,10 @@ Register Api Provider Check Response Variable Type And Values ${resp} 201 APIProviderEnrolmentDetails ${url}= Parse Url ${resp.headers['Location']} - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${register_user_info['amf_username']} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} + Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${register_user_info['amf_username']} ${resource_url}= Check Location Header ${resp} ${LOCATION_PROVIDER_RESOURCE_REGEX} - FOR ${prov} IN @{resp.json()['apiProvFuncs']} Log Dictionary ${prov} Store In File ${prov['apiProvFuncInfo']}.crt ${prov['regInfo']['apiProvCert']} @@ -66,10 +65,6 @@ Register Api Provider Already registered [Tags] capif_api_provider_management-2 ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - - ${resp}= Post Request Capif ... /api-provider-management/v1/registrations ... json=${register_user_info['provider_enrollment_details']} @@ -88,9 +83,6 @@ Update Registered Api Provider [Tags] capif_api_provider_management-3 ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${request_body}= Set Variable ${register_user_info['provider_enrollment_details']} Set To Dictionary ${request_body} apiProvDomInfo=ROBOT_TESTING_MOD @@ -124,9 +116,6 @@ Update Not Registered Api Provider [Tags] capif_api_provider_management-4 ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${request_body}= Set Variable ${register_user_info['provider_enrollment_details']} ${resp}= Put Request Capif @@ -144,32 +133,29 @@ Update Not Registered Api Provider ... cause=Not found registrations to send this api provider details # Partially Update Registered Api Provider -# [Tags] capif_api_provider_management-5 -# ${register_user_info}= Provider Default Registration +# [Tags] capif_api_provider_management-5 +# ${register_user_info}= Provider Default Registration -# ${request_body}= Create Api Provider Enrolment Details Patch Body ROBOT_TESTING_MOD +# ${request_body}= Create Api Provider Enrolment Details Patch Body ROBOT_TESTING_MOD -# ${resp}= Patch Request Capif -# ... ${register_user_info['resource_url'].path} -# ... json=${request_body} -# ... server=${CAPIF_HTTPS_URL} -# ... verify=ca.crt -# ... username=${AMF_PROVIDER_USERNAME} +# ${resp}= Patch Request Capif +# ... ${register_user_info['resource_url'].path} +# ... json=${request_body} +# ... server=${CAPIF_HTTPS_URL} +# ... verify=ca.crt +# ... username=${AMF_PROVIDER_USERNAME} -# Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${register_user_info['amf_username']} -# Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} +# Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${register_user_info['amf_username']} +# -# # Check Results -# Check Response Variable Type And Values ${resp} 200 APIProviderEnrolmentDetails -# ... apiProvDomInfo=ROBOT_TESTING_MOD +# # Check Results +# Check Response Variable Type And Values ${resp} 200 APIProviderEnrolmentDetails +# ... apiProvDomInfo=ROBOT_TESTING_MOD Partially Update Not Registered Api Provider [Tags] capif_api_provider_management-6 ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${request_body}= Create Api Provider Enrolment Details Patch Body ${resp}= Patch Request Capif @@ -190,14 +176,14 @@ Delete Registered Api Provider [Tags] capif_api_provider_management-7 ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${resp}= Delete Request Capif ... ${register_user_info['resource_url'].path} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${AMF_PROVIDER_USERNAME} + Call Method ${CAPIF_USERS} remove_capif_users_entry ${register_user_info['resource_url'].path} + # Check Results Status Should Be 204 ${resp} @@ -205,9 +191,6 @@ Delete Not Registered Api Provider [Tags] capif_api_provider_management-8 ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${resp}= Delete Request Capif ... /api-provider-management/v1/registrations/${API_PROVIDER_NOT_REGISTERED} ... server=${CAPIF_HTTPS_URL} diff --git a/tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot b/tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot index cd58b3ea2a30687002f2847a6c510ebe2ad7817f..f3556a4b5517385791622a476f988c6ae01dc343 100644 --- a/tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot +++ b/tests/features/CAPIF Api Publish Service/capif_api_publish_service.robot @@ -1,11 +1,12 @@ *** Settings *** -Resource /opt/robot-tests/tests/resources/common.resource -Resource ../../resources/common/basicRequests.robot -Resource ../../resources/common.resource -Library /opt/robot-tests/tests/libraries/bodyRequests.py +Resource /opt/robot-tests/tests/resources/common.resource +Resource ../../resources/common/basicRequests.robot +Resource ../../resources/common.resource +Library /opt/robot-tests/tests/libraries/bodyRequests.py -Test Setup Reset Testing Environment -Suite Teardown Reset Testing Environment +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment *** Variables *** @@ -16,12 +17,9 @@ ${SERVICE_API_ID_NOT_VALID} not-valid *** Test Cases *** Publish API by Authorised API Publisher [Tags] capif_api_publish_service-1 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Test ${request_body}= Create Service Api Description service_1 ${resp}= Post Request Capif @@ -38,12 +36,9 @@ Publish API by Authorised API Publisher Publish API by NON Authorised API Publisher [Tags] capif_api_publish_service-2 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${request_body}= Create Service Api Description ${resp}= Post Request Capif ... /published-apis/v1/${APF_ID_NOT_VALID}/service-apis @@ -60,12 +55,9 @@ Publish API by NON Authorised API Publisher Retrieve all APIs Published by Authorised apfId [Tags] capif_api_publish_service-3 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Register One Service ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info} @@ -88,12 +80,9 @@ Retrieve all APIs Published by Authorised apfId Retrieve all APIs Published by NON Authorised apfId [Tags] capif_api_publish_service-4 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Retrieve Services published ${resp}= Get Request Capif ... /published-apis/v1/${APF_ID_NOT_VALID}/service-apis @@ -109,12 +98,9 @@ Retrieve all APIs Published by NON Authorised apfId Retrieve single APIs Published by Authorised apfId [Tags] capif_api_publish_service-5 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info} ... service_1 @@ -148,19 +134,15 @@ Retrieve single APIs Published by Authorised apfId Retrieve single APIs non Published by Authorised apfId [Tags] capif_api_publish_service-6 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${resp}= Get Request Capif ... /published-apis/v1/${register_user_info['apf_id']}/service-apis/${SERVICE_API_ID_NOT_VALID} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${APF_PROVIDER_USERNAME} - Check Response Variable Type And Values ${resp} 401 ProblemDetails ... title=Unauthorized ... detail=User not authorized @@ -171,9 +153,6 @@ Retrieve single APIs Published by NON Authorised apfId # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Publish Service API ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info} @@ -182,9 +161,6 @@ Retrieve single APIs Published by NON Authorised apfId # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Get Request Capif ... ${resource_url.path} ... server=${CAPIF_HTTPS_URL} @@ -199,12 +175,9 @@ Retrieve single APIs Published by NON Authorised apfId Update API Published by Authorised apfId with valid serviceApiId [Tags] capif_api_publish_service-8 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info} ... service_1 @@ -232,12 +205,9 @@ Update API Published by Authorised apfId with valid serviceApiId Update APIs Published by Authorised apfId with invalid serviceApiId [Tags] capif_api_publish_service-9 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info} ... service_1 @@ -257,22 +227,16 @@ Update APIs Published by Authorised apfId with invalid serviceApiId Update APIs Published by NON Authorised apfId [Tags] capif_api_publish_service-10 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info} ... service_1 - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Api Description service_1_modified ${resp}= Put Request Capif ... ${resource_url.path} @@ -299,12 +263,9 @@ Update APIs Published by NON Authorised apfId Delete API Published by Authorised apfId with valid serviceApiId [Tags] capif_api_publish_service-11 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published_1} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info} ... first_service @@ -330,12 +291,9 @@ Delete API Published by Authorised apfId with valid serviceApiId Delete APIs Published by Authorised apfId with invalid serviceApiId [Tags] capif_api_publish_service-12 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${resp}= Delete Request Capif ... /published-apis/v1/${register_user_info['apf_id']}/service-apis/${SERVICE_API_ID_NOT_VALID} ... server=${CAPIF_HTTPS_URL} @@ -349,18 +307,12 @@ Delete APIs Published by Authorised apfId with invalid serviceApiId Delete APIs Published by NON Authorised apfId [Tags] capif_api_publish_service-13 - #Register APF + # Register APF ${register_user_info}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - - #Register INVOKER + # Register INVOKER ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Delete Request Capif ... /published-apis/v1/${register_user_info['apf_id']}/service-apis/${SERVICE_API_ID_NOT_VALID} ... server=${CAPIF_HTTPS_URL} diff --git a/tests/features/CAPIF Security Api/capif_security_api.robot b/tests/features/CAPIF Security Api/capif_security_api.robot index 2a41e80d3d49131d970826e9f48f1609b20ba2e2..f6448390a251e66755e21df6c5fa09ef58b81ac6 100644 --- a/tests/features/CAPIF Security Api/capif_security_api.robot +++ b/tests/features/CAPIF Security Api/capif_security_api.robot @@ -1,12 +1,13 @@ *** Settings *** -Resource /opt/robot-tests/tests/resources/common.resource -Library /opt/robot-tests/tests/libraries/bodyRequests.py -Library Collections -Resource /opt/robot-tests/tests/resources/common/basicRequests.robot -Resource ../../resources/common.resource +Resource /opt/robot-tests/tests/resources/common.resource +Library /opt/robot-tests/tests/libraries/bodyRequests.py +Library Collections +Resource /opt/robot-tests/tests/resources/common/basicRequests.robot +Resource ../../resources/common.resource -Test Setup Reset Testing Environment -Suite Teardown Reset Testing Environment +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment +Test Teardown Reset Testing Environment *** Variables *** @@ -22,9 +23,6 @@ Create a security context for an API invoker # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Create Security Context ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif @@ -43,15 +41,9 @@ Create a security context for an API invoker with Provider role # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Register Provider ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Create Security Context ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif @@ -73,9 +65,6 @@ Create a security context for an API invoker with Provider entity role and inval # Register APF ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Create Security Context ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif @@ -97,9 +86,6 @@ Create a security context for an API invoker with Invalid apiInvokerID # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${API_INVOKER_NOT_VALID} @@ -120,9 +106,6 @@ Retrieve the Security Context of an API Invoker # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -139,9 +122,6 @@ Retrieve the Security Context of an API Invoker # Register APF ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Retrieve Security context can setup by parameters if authenticationInfo and authorizationInfo are needed at response. # ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']}?authenticationInfo=true&authorizationInfo=true ${resp}= Get Request Capif @@ -165,9 +145,6 @@ Retrieve the Security Context of an API Invoker with invalid apiInvokerID # Register APF ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${resp}= Get Request Capif ... /capif-security/v1/trustedInvokers/${API_INVOKER_NOT_VALID} ... server=${CAPIF_HTTPS_URL} @@ -185,9 +162,6 @@ Retrieve the Security Context of an API Invoker with invalid apfId # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -217,9 +191,6 @@ Delete the Security Context of an API Invoker # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -233,9 +204,6 @@ Delete the Security Context of an API Invoker # Register APF ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Remove Security Context ${resp}= Delete Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -263,9 +231,6 @@ Delete the Security Context of an API Invoker with Invoker entity role # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -294,9 +259,6 @@ Delete the Security Context of an API Invoker with Invoker entity role and inval # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${resp}= Delete Request Capif ... /capif-security/v1/trustedInvokers/${API_INVOKER_NOT_VALID} ... server=${CAPIF_HTTPS_URL} @@ -315,9 +277,6 @@ Delete the Security Context of an API Invoker with invalid apiInvokerID # Register Provider ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${resp}= Delete Request Capif ... /capif-security/v1/trustedInvokers/${API_INVOKER_NOT_VALID} ... server=${CAPIF_HTTPS_URL} @@ -336,15 +295,9 @@ Update the Security Context of an API Invoker # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Register Provider ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -389,9 +342,6 @@ Update the Security Context of an API Invoker with Provider entity role # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -402,12 +352,9 @@ Update the Security Context of an API Invoker with Provider entity role Check Response Variable Type And Values ${resp} 201 ServiceSecurity - #Register Provider + # Register Provider ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${resp}= Post Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']}/update ... json=${request_body} @@ -424,12 +371,9 @@ Update the Security Context of an API Invoker with Provider entity role Update the Security Context of an API Invoker with AEF entity role and invalid apiInvokerId [Tags] capif_security_api-14 - #Register Provider + # Register Provider ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Post Request Capif ... /capif-security/v1/trustedInvokers/${API_INVOKER_NOT_VALID}/update @@ -449,9 +393,6 @@ Update the Security Context of an API Invoker with invalid apiInvokerID # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Post Request Capif ... /capif-security/v1/trustedInvokers/${API_INVOKER_NOT_VALID}/update @@ -472,9 +413,6 @@ Revoke the authorization of the API invoker for APIs # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -485,10 +423,6 @@ Revoke the authorization of the API invoker for APIs # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - - # Test ${discover_response}= Get Request Capif ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} @@ -545,9 +479,6 @@ Revoke the authorization of the API invoker for APIs without valid apfID. # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -563,9 +494,6 @@ Revoke the authorization of the API invoker for APIs without valid apfID. # Register Provider ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - # Revoke Security Context by Invoker ${request_body}= Create Security Notification Body ${register_user_info_invoker['api_invoker_id']} 1234 ${resp}= Post Request Capif @@ -601,9 +529,6 @@ Revoke the authorization of the API invoker for APIs with invalid apiInvokerId # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - ${request_body}= Create Service Security Body ${NOTIFICATION_DESTINATION} ${resp}= Put Request Capif ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} @@ -616,12 +541,9 @@ Revoke the authorization of the API invoker for APIs with invalid apiInvokerId ${security_context}= Set Variable ${resp.json()} - #Register Provider + # Register Provider ${register_user_info_publisher}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_publisher['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${request_body}= Create Security Notification Body ${API_INVOKER_NOT_VALID} 1234 ${resp}= Post Request Capif ... /capif-security/v1/trustedInvokers/${API_INVOKER_NOT_VALID}/delete @@ -652,9 +574,6 @@ Retrieve access token # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -665,12 +584,9 @@ Retrieve access token # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -711,9 +627,6 @@ Retrieve access token by Provider # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -724,12 +637,9 @@ Retrieve access token by Provider # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -769,9 +679,6 @@ Retrieve access token by Provider with invalid apiInvokerId # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -782,12 +689,9 @@ Retrieve access token by Provider with invalid apiInvokerId # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -828,9 +732,6 @@ Retrieve access token with invalid apiInvokerId # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -841,12 +742,9 @@ Retrieve access token with invalid apiInvokerId # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -889,9 +787,6 @@ Retrieve access token with invalid client_id # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -902,12 +797,9 @@ Retrieve access token with invalid client_id # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -948,9 +840,6 @@ Retrieve access token with unsupported grant_type # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -961,12 +850,9 @@ Retrieve access token with unsupported grant_type # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -1014,9 +900,6 @@ Retrieve access token with invalid scope # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -1027,12 +910,9 @@ Retrieve access token with invalid scope # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -1075,9 +955,6 @@ Retrieve access token with invalid aefid at scope # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -1088,12 +965,9 @@ Retrieve access token with invalid aefid at scope # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -1136,9 +1010,6 @@ Retrieve access token with invalid apiName at scope # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method ${CAPIF_USERS} update_capif_users_dicts ${register_user_info_provider['resource_url'].path} ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${api_name}= Set Variable service_1 # Register One Service @@ -1149,12 +1020,9 @@ Retrieve access token with invalid apiName at scope # Default Invoker Registration and Onboarding ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding - Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} - # Test ${discover_response}= Get Request Capif - ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']} + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&api-name=${api_name} ... server=${CAPIF_HTTPS_URL} ... verify=ca.crt ... username=${INVOKER_USERNAME} @@ -1189,4 +1057,4 @@ Retrieve access token with invalid apiName at scope # Check Results Check Response Variable Type And Values ${resp} 400 AccessTokenErr ... error=invalid_scope - ... error_description=One of the api names does not exist or is not associated with the aef id provided \ No newline at end of file + ... error_description=One of the api names does not exist or is not associated with the aef id provided diff --git a/tests/libraries/api_events/bodyRequests.py b/tests/libraries/api_events/bodyRequests.py index ab6e4dae3d646bccbb9ac3f994c7f71112d9e2dc..17fd1b57f743adeecd6da459a8d0a3179b11af90 100644 --- a/tests/libraries/api_events/bodyRequests.py +++ b/tests/libraries/api_events/bodyRequests.py @@ -1,32 +1,97 @@ -def create_events_subscription(): +def create_events_subscription(events=["SERVICE_API_AVAILABLE", "API_INVOKER_ONBOARDED"], notificationDestination="http://robot.testing", eventFilters=None, eventReq=None, requestTestNotification=None, supportedFeatures=None, websockNotifConfig=None): + event_subscription = { + "events": events, + "notificationDestination": notificationDestination, + } + if eventFilters != None: + event_subscription['eventFilters'] = eventFilters + if eventReq != None: + event_subscription['eventReq'] = eventReq + if requestTestNotification != None: + event_subscription['requestTestNotification'] = requestTestNotification + if supportedFeatures != None: + event_subscription['supportedFeatures'] = supportedFeatures + if websockNotifConfig != None: + event_subscription['websockNotifConfig'] = websockNotifConfig + + return event_subscription + + +def create_capif_event_filter(aefIds=None, apiIds=None, apiInvokerIds=None): + if aefIds == None and apiIds == None and apiInvokerIds: + raise ("Error, no data present to create event filter") + capif_event_filter = dict() + if aefIds != None: + capif_event_filter['aefIds'] = aefIds + if apiIds != None: + capif_event_filter['apiIds'] = apiIds + if apiInvokerIds != None: + capif_event_filter['apiInvokerIds'] = apiInvokerIds + return capif_event_filter + + +def create_default_event_req(): + return { + "grpRepTime": 5, + "immRep": True, + "maxReportNbr": 0, + "monDur": "2000-01-23T04:56:07+00:00", + "partitionCriteria": ["TAC", "GEOAREA"], + "repPeriod": 6, + "sampRatio": 15 + } + + +def create_websock_notif_config_default(): return { - "eventFilters": [ - { - "aefIds": ["aefIds", "aefIds"], - "apiIds": ["apiIds", "apiIds"], - "apiInvokerIds": ["apiInvokerIds", "apiInvokerIds"] - }, - { - "aefIds": ["aefIds", "aefIds"], - "apiIds": ["apiIds", "apiIds"], - "apiInvokerIds": ["apiInvokerIds", "apiInvokerIds"] - } - ], - "eventReq": { - "grpRepTime": 5, - "immRep": True, - "maxReportNbr": 0, - "monDur": "2000-01-23T04:56:07+00:00", - "partitionCriteria": ["TAC", "GEOAREA"], - "repPeriod": 6, - "sampRatio": 15 - }, - "events": ["SERVICE_API_AVAILABLE", "API_INVOKER_ONBOARDED"], - "notificationDestination": "http://robot.testing", - "requestTestNotification": True, - "supportedFeatures": "aaa", - "websockNotifConfig": { - "requestWebsocketUri": True, - "websocketUri": "websocketUri" - } + "requestWebsocketUri": True, + "websocketUri": "websocketUri" + } + + +def create_notification_event(subscriptionId, event, serviceAPIDescriptions=None, apiIds=None, apiInvokerIds=None, accCtrlPolList=None, invocationLogs=None, apiTopoHide=None): + result = { + "subscriptionId": subscriptionId, + "events": event, + "eventDetail": dict() } + count = 0 + if serviceAPIDescriptions != None: + if isinstance(serviceAPIDescriptions, list): + result['eventDetail']['serviceAPIDescriptions'] = serviceAPIDescriptions + else: + result['eventDetail']['serviceAPIDescriptions'] = [ + serviceAPIDescriptions] + count = count+1 + if apiIds != None: + if isinstance(apiIds, list): + result['eventDetail']['apiIds'] = apiIds + else: + result['eventDetail']['apiIds'] = [apiIds] + count = count+1 + if apiInvokerIds != None: + if isinstance(apiInvokerIds, list): + result['eventDetail']['apiInvokerIds'] = apiInvokerIds + else: + result['eventDetail']['apiInvokerIds'] = [apiInvokerIds] + count = count+1 + if accCtrlPolList != None: + result['eventDetail']['accCtrlPolList'] = accCtrlPolList + count = count+1 + if invocationLogs != None: + if isinstance(invocationLogs, list): + result['eventDetail']['invocationLogs'] = invocationLogs + else: + result['eventDetail']['invocationLogs'] = [invocationLogs] + count = count+1 + if apiTopoHide != None: + if isinstance(apiTopoHide, list): + result['eventDetail']['apiTopoHide'] = apiTopoHide + else: + result['eventDetail']['apiTopoHide'] = [apiTopoHide] + count = count+1 + + if count == 0: + del result['eventDetail'] + + return result diff --git a/tests/libraries/api_logging_service/bodyRequests.py b/tests/libraries/api_logging_service/bodyRequests.py index fe3faf1dd9dbc1ccd0fb96ce96e5b73d0cd805f9..a4d2a18770dca3d2d43742010bf9d336aaf728d3 100644 --- a/tests/libraries/api_logging_service/bodyRequests.py +++ b/tests/libraries/api_logging_service/bodyRequests.py @@ -1,84 +1,21 @@ -def create_log_entry(aefId=None, apiInvokerId=None, apiId=None, apiName=None): +def create_log_entry(aefId, apiInvokerId, apiId, apiName, results=['200','500'],api_versions=['v1','v2']): data = { "aefId": aefId, "apiInvokerId": apiInvokerId, - "logs": [ - { - "apiId": apiId[0], - "apiName": apiName[0], - "apiVersion": "v1", - "resourceName": "string", - "uri": "http://resource/endpoint", - "protocol": "HTTP_1_1", - "operation": "GET", - "result": "string", - "invocationTime": "2023-03-30T10:30:21.408Z", - "invocationLatency": 0, - "inputParameters": "string", - "outputParameters": "string", - "srcInterface": { - "ipv4Addr": "192.168.1.1", - "fqdn": "string", - "port": 65535, - "apiPrefix": "string", - "securityMethods": [ - "PSK", - "string" - ] - }, - "destInterface": { - "ipv4Addr": "192.168.1.23", - "fqdn": "string", - "port": 65535, - "apiPrefix": "string", - "securityMethods": [ - "PSK", - "string" - ] - }, - "fwdInterface": "string" - }, - { - "apiId": apiId[0], - "apiName": apiName[0], - "apiVersion": "v2", - "resourceName": "string", - "uri": "http://resource/endpoint", - "protocol": "HTTP_1_1", - "operation": "GET", - "result": "string", - "invocationTime": "2023-03-30T10:30:21.408Z", - "invocationLatency": 0, - "inputParameters": "string", - "outputParameters": "string", - "srcInterface": { - "ipv4Addr": "192.168.1.1", - "fqdn": "string", - "port": 65535, - "apiPrefix": "string", - "securityMethods": [ - "PSK", - "string" - ] - }, - "destInterface": { - "ipv4Addr": "192.168.1.23", - "fqdn": "string", - "port": 65535, - "apiPrefix": "string", - "securityMethods": [ - "PSK", - "string" - ] - }, - "fwdInterface": "string" - } - ], + "logs": [], "supportedFeatures": "ffff" } + if len(results) > 0: + count=0 + for result in results: + data['logs'].append(create_log(apiId,apiName,result,api_versions[count])) + count=count+1 + if count == len(api_versions): + count=0 + return data -def create_log_entry_bad_service(aefId=None, apiInvokerId=None): +def create_log_entry_bad_service(aefId, apiInvokerId, result='500'): data = { "aefId": aefId, "apiInvokerId": apiInvokerId, @@ -91,29 +28,25 @@ def create_log_entry_bad_service(aefId=None, apiInvokerId=None): "uri": "string", "protocol": "HTTP_1_1", "operation": "GET", - "result": "string", - "invocationTime": "2023-03-30T10:30:21.408Z", + "result": result, + "invocationTime": "2023-03-30T10:30:21.408000+00:00", "invocationLatency": 0, "inputParameters": "string", "outputParameters": "string", "srcInterface": { "ipv4Addr": "192.168.1.1", - "fqdn": "string", "port": 65535, - "apiPrefix": "string", "securityMethods": [ "PSK", - "string" + "PKI" ] }, "destInterface": { "ipv4Addr": "192.168.1.23", - "fqdn": "string", "port": 65535, - "apiPrefix": "string", "securityMethods": [ "PSK", - "string" + "PKI" ] }, "fwdInterface": "string" @@ -131,3 +64,29 @@ def get_api_ids_and_names_from_discover_response(discover_response): api_ids.append(service_api_description['apiId']) api_names.append(service_api_description['apiName']) return api_ids, api_names + + +def create_log(apiId, apiName, result, api_version='v1'): + log= { + "apiId": apiId[0], + "apiName": apiName[0], + "apiVersion": api_version, + "resourceName": "string", + "uri": "http://resource/endpoint", + "protocol": "HTTP_1_1", + "operation": "GET", + "result": result, + "invocationTime": "2023-03-30T10:30:21.408000+00:00", + "invocationLatency": 0, + "inputParameters": "string", + "outputParameters": "string", + "srcInterface": { + "ipv4Addr": "192.168.1.1", + "port": 65535, + "securityMethods": [ + "PSK", + "PKI" + ] + } + } + return log \ No newline at end of file diff --git a/tests/libraries/api_publish_service/bodyRequests.py b/tests/libraries/api_publish_service/bodyRequests.py index 17ac4a794a5ba1a38357ee229d04b3b4590bfdc8..69e7bb117f01b4c53ee7d1db74b7da09e20bf3a1 100644 --- a/tests/libraries/api_publish_service/bodyRequests.py +++ b/tests/libraries/api_publish_service/bodyRequests.py @@ -7,7 +7,7 @@ def create_service_api_description(api_name="service_1",aef_id="aef_id"): "versions": [ { "apiVersion": "v1", - "expiry": "2021-11-30T10:32:02.004000Z", + "expiry": "2021-11-30T10:32:02.004000+00:00", "resources": [ { "resourceName": "string", @@ -20,27 +20,12 @@ def create_service_api_description(api_name="service_1",aef_id="aef_id"): "description": "string" } ], - "custOperations": [ - { - "commType": "REQUEST_RESPONSE", - "custOpName": "string", - "operations": [ - "GET" - ], - "description": "string" - } - ] } ], "protocol": "HTTP_1_1", "dataFormat": "JSON", "securityMethods": ["PSK"], "interfaceDescriptions": [ - { - "ipv4Addr": "string", - "port": 65535, - "securityMethods": ["PSK"] - }, { "ipv4Addr": "string", "port": 65535, diff --git a/tests/libraries/common/bodyRequests.py b/tests/libraries/common/bodyRequests.py index 3f1e482d4717bc5d3ddfc298962afb8e42bc1a7e..1d4ec14f60759bfb221b686ba84df23b1386fa6c 100644 --- a/tests/libraries/common/bodyRequests.py +++ b/tests/libraries/common/bodyRequests.py @@ -15,7 +15,7 @@ def check_variable(input, data_type): if isinstance(input, list): for one in input: check_variable(one, data_type) - return True + return True if data_type == "string": if isinstance(input, str): return True diff --git a/tests/libraries/common/types.json b/tests/libraries/common/types.json index 4b683595c43c912f868856107d21ed84ad08032d..220dd0f5710796fd875ddda8d05dfb3e39a272cd 100644 --- a/tests/libraries/common/types.json +++ b/tests/libraries/common/types.json @@ -259,6 +259,67 @@ "aefIds": "string" } }, + "EventNotification": { + "mandatory_attributes": { + "subscriptionId": "string", + "events": "CAPIFEvent" + }, + "optional_attributes": { + "eventDetail": "CAPIFEventDetail" + } + }, + "CAPIFEventDetail": { + "mandatory_attributes": {}, + "optional_attributes": { + "serviceAPIDescriptions": "ServiceAPIDescription", + "apiIds": "string", + "apiInvokerIds": "string", + "accCtrlPolList": "AccessControlPolicyListExt", + "invocationLogs": "InvocationLog", + "apiTopoHide": "TopologyHiding" + } + }, + "AccessControlPolicyListExt":{ + "mandatory_attributes": { + "apiId": "string" + }, + "optional_attributes": { + "apiInvokerPolicies": "ApiInvokerPolicy" + } + }, + "TopologyHiding": { + "mandatory_attributes":{ + "apiId": "string", + "routingRules": "RoutingRule" + }, + "optional_attributes": {} + }, + "RoutingRule":{ + "mandatory_attributes": { + "aefProfile": "AefProfile" + }, + "optional_attributes": { + "ipv4AddrRanges": "Ipv4AddressRange", + "ipv6AddrRanges": "Ipv6AddressRange" + } + }, + "Ipv4AddressRange":{ + "mandatory_attributes": {}, + "optional_attributes": { + "start": "Ipv4Addr", + "stop": "Ipv4Addr" + } + }, + "Ipv4Addr": { + "regex": "^(([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])$" + }, + "Ipv6AddressRange":{ + "mandatory_attributes":{ + "start": "string", + "end": "string" + }, + "optional_attributes":{} + }, "ReportingInformation": { "mandatory_attributes": {}, "optional_attributes": { diff --git a/tests/libraries/environment.py b/tests/libraries/environment.py index d8100fa4fc79a0cfbb7c1e2cf2b3ff420b282247..8b7a504e8e138b8ade707caf07a786d2f96aa1b6 100644 --- a/tests/libraries/environment.py +++ b/tests/libraries/environment.py @@ -1,10 +1,10 @@ class CapifUserManager(): def __init__(self): self.capif_users = {} - self.register_users = [] + self.register_users = {} - def update_register_users(self, value): - self.register_users.append(value) + def update_register_users(self, uuid, username): + self.register_users[uuid] = username def update_capif_users_dicts(self, key, value): self.capif_users[key] = value @@ -12,14 +12,22 @@ class CapifUserManager(): def remove_capif_users_entry(self, key): self.capif_users.pop(key) - def remove_register_users_entry(self, value): - self.register_users.remove(value) + def remove_register_users_entry(self, uuid=None, username=None): + if uuid != None: + self.register_users.pop(uuid) + elif username != None: + uuid=self.get_user_uuid(username) + self.register_users.pop(uuid) def get_capif_users_dict(self): return self.capif_users - def get_register_users(self): + def get_register_users_dict(self): return self.register_users - + + def get_user_uuid(self, username): + for uuid, stored_user in self.register_users.items(): + if stored_user == username: + return uuid CAPIF_USERS = CapifUserManager() \ No newline at end of file diff --git a/tests/libraries/helpers.py b/tests/libraries/helpers.py index ec1abe0d8b49c00971a013faff814416e68dfead..94c850fbe537b37d449ec355dd7779ea52ba3bf5 100644 --- a/tests/libraries/helpers.py +++ b/tests/libraries/helpers.py @@ -7,6 +7,8 @@ from OpenSSL.crypto import (dump_certificate_request, dump_privatekey, from OpenSSL.SSL import FILETYPE_PEM import socket import copy +import json +import pickle def parse_url(input): @@ -139,3 +141,14 @@ def create_scope(aef_id, api_name): data = "3gpp#" + aef_id + ":" + api_name return data + +def read_dictionary(file_path): + with open(file_path, 'rb') as fp: + data = pickle.load(fp) + print('Dictionary loaded') + return data + +def write_dictionary(file_path, data): + with open(file_path, 'wb') as fp: + pickle.dump(data, fp) + print('dictionary saved successfully to file ' + file_path) diff --git a/tests/libraries/interrupt_listener.py b/tests/libraries/interrupt_listener.py new file mode 100644 index 0000000000000000000000000000000000000000..ec2f5d43e117c5aba1a197a3f8e1fcf9f1d1d407 --- /dev/null +++ b/tests/libraries/interrupt_listener.py @@ -0,0 +1,24 @@ +import signal +from robot.libraries.BuiltIn import BuiltIn + +class InterruptListener: + ROBOT_LISTENER_API_VERSION = 3 + + def __init__(self): + signal.signal(signal.SIGINT, self._handle_interrupt) + self.builtin = BuiltIn() + + def _handle_interrupt(self, signum, frame): + print("Execution interrupted! Running cleanup keyword...") + try: + self.builtin.run_keyword('Reset Testing Environment') + except Exception as e: + print(f"Error during cleanup: {e}") + finally: + exit(0) + + def start_suite(self, name, attrs): + print(f"Starting suite: {name}") + + def end_suite(self, name, attrs): + print(f"Ending suite: {name}") \ No newline at end of file diff --git a/tests/requirements.txt b/tests/requirements.txt index 71b55e2329efca2577a402b24133de42a318d187..3119b5ca73095dfdc4a018dc35abaf83c5bc5ab2 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -1,7 +1,2 @@ # Requirements file for tests. -robotframework-mongodb-library==3.2 -requests==2.28.1 -configparser==5.3.0 -redis==4.3.4 -rfc3987==1.3.8 -robotframework-httpctrl \ No newline at end of file + diff --git a/tests/resources/common.resource b/tests/resources/common.resource index b111127701b3a18a33282044d46efd3e38f076cc..fcd9a97efb354180ba2b639f23787641b3a84038 100644 --- a/tests/resources/common.resource +++ b/tests/resources/common.resource @@ -1,7 +1,10 @@ *** Settings *** -Library /opt/robot-tests/tests/libraries/helpers.py -Variables /opt/robot-tests/tests/libraries/environment.py -Resource /opt/robot-tests/tests/resources/common/basicRequests.robot +Library /opt/robot-tests/tests/libraries/helpers.py +Library /opt/robot-tests/tests/libraries/interrupt_listener.py +Library Process +Library Collections +Variables /opt/robot-tests/tests/libraries/environment.py +Resource /opt/robot-tests/tests/resources/common/basicRequests.robot *** Variables *** @@ -21,12 +24,20 @@ ${CAPIF_VAULT_PORT} 8200 ${CAPIF_VAULT_TOKEN} read-ca-token ${CAPIF_REGISTER} register ${CAPIF_REGISTER_PORT} 8084 -${CAPIF_HTTP_PORT} -${CAPIF_HTTPS_PORT} +${CAPIF_HTTP_PORT} ${EMPTY} +${CAPIF_HTTPS_PORT} ${EMPTY} ${CAPIF_IP} 127.0.0.1 ${CAPIF_CALLBACK_IP} host.docker.internal ${CAPIF_CALLBACK_PORT} 8086 +${REGISTER_ADMIN_USER} admin +${REGISTER_ADMIN_PASSWORD} password123 + +${REQUESTS_TIMEOUT} 120s + +${MOCK_SERVER_URL} + + ${DISCOVER_URL} /service-apis/v1/allServiceAPIs?api-invoker-id= @@ -34,7 +45,7 @@ ${DISCOVER_URL} /service-apis/v1/allServiceAPIs?api-invoker-id= Reset Testing Environment Log Db capif.invokerdetails collection will be removed in order to isolate each test. - #Clean Test Information By HTTP Requests + # Clean Test Information By HTTP Requests Clean Test Information Check Location Header @@ -82,3 +93,78 @@ Remove Keys From Object Test ${TEST NAME} Currently Not Supported Log Test "${TEST NAME}" Currently not supported WARN Skip Test "${TEST NAME}" Currently not supported + +Init Mock Server + Check Mock Server + Clean Mock Server + +Check Mock Server + Log Checking mock Server for Robot Framework. + + IF "${MOCK_SERVER_URL}" == "" + Fail Mock Server Url is not setup on Tests execution, check MOCK_SERVER_URL variable mockserver-not-ready + END + + Create Session mockserver ${MOCK_SERVER_URL} + + ${endpoint}= Set Variable /requests_list + + ${resp}= GET On Session + ... mockserver + ... ${endpoint} + ... expected_status=any + ... verify=False + + Status Should Be 200 ${resp} Mock Server response is not 200 OK at ${MOCK_SERVER_URL}, check server status. + +Clean Mock Server + Log Checking mock Server for Robot Framework. + + Create Session mockserver ${MOCK_SERVER_URL} + + ${endpoint}= Set Variable /requests_list + + ${resp}= DELETE On Session + ... mockserver + ... ${endpoint} + ... expected_status=any + ... verify=False + + Status Should Be 200 ${resp} + + +Get Mock Server Messages + Log Checking mock Server for Robot Framework. + + Create Session mockserver ${MOCK_SERVER_URL} + + ${endpoint}= Set Variable /requests_list + + ${resp}= GET On Session + ... mockserver + ... ${endpoint} + ... expected_status=any + ... verify=False + + Status Should Be 200 ${resp} + Log List ${resp.json()} + RETURN ${resp} + +Check Mock Server Notification Events + [Arguments] ${events_expected} + + Check Variable ${events_expected} EventNotification + # Check results + ${events_expected_length}= Get Length ${events_expected} + + Sleep 3s + # Get from Mock server the EventNotification Messages sent to callback setup on event subscription. + ${resp}= Get Mock Server Messages + ${notification_events_on_mock_server}= Set Variable ${resp.json()} + Check Variable ${notification_events_on_mock_server} EventNotification + + Length Should Be ${notification_events_on_mock_server} ${events_expected_length} + FOR ${event_expected} IN @{events_expected} + Log ${event_expected} + List Should Contain Value ${notification_events_on_mock_server} ${event_expected} + END \ No newline at end of file diff --git a/tests/resources/common/basicRequests.robot b/tests/resources/common/basicRequests.robot index 1d8d69553cd9e905b95463627e0e1c8a72c20973..6d4f4569592e1685ec9b72554b9849f368db0082 100644 --- a/tests/resources/common/basicRequests.robot +++ b/tests/resources/common/basicRequests.robot @@ -5,6 +5,7 @@ Library RequestsLibrary Library Collections Library OperatingSystem Library XML +Library Telnet *** Variables *** @@ -53,8 +54,95 @@ Create CAPIF Session RETURN ${headers} +Create Register Admin Session + [Documentation] Create needed session to reach Register as Administrator. + [Arguments] ${server}=${NONE} ${access_token}=${NONE} ${verify}=${NONE} ${vault_token}=${NONE} + IF "${server}" != "${NONE}" + IF "${access_token}" != "${NONE}" + ## Return Header with bearer + ${headers}= Create Dictionary Authorization=Bearer ${access_token} + + RETURN ${headers} + END + + # Request Admin Login to retrieve access token + Create Session register_session ${server} verify=${verify} disable_warnings=1 + + ${auth}= Set variable ${{ ('${REGISTER_ADMIN_USER}','${REGISTER_ADMIN_PASSWORD}') }} + ${resp}= POST On Session register_session /login auth=${auth} + + Log Dictionary ${resp.json()} + + ## Crear sesión con token + ${headers}= Create Dictionary Authorization=Bearer ${resp.json()['access_token']} + + RETURN ${headers} + END + + RETURN ${NONE} + +## NEW REQUESTS TO REGISTER + +Post Request Admin Register + [Timeout] ${REQUESTS_TIMEOUT} + [Arguments] + ... ${endpoint} + ... ${json}=${NONE} + ... ${server}=${NONE} + ... ${access_token}=${NONE} + ... ${auth}=${NONE} + ... ${verify}=${FALSE} + ... ${cert}=${NONE} + ... ${username}=${NONE} + ... ${data}=${NONE} + + ${headers}= Create Register Admin Session ${server} ${access_token} ${verify} + + IF '${username}' != '${NONE}' + ${cert}= Set variable ${{ ('${username}.crt','${username}.key') }} + END + + ${resp}= POST On Session + ... register_session + ... ${endpoint} + ... headers=${headers} + ... json=${json} + ... expected_status=any + ... verify=${verify} + ... cert=${cert} + ... data=${data} + RETURN ${resp} + +Get Request Admin Register + [Timeout] ${REQUESTS_TIMEOUT} + [Arguments] + ... ${endpoint} + ... ${server}=${NONE} + ... ${access_token}=${NONE} + ... ${auth}=${NONE} + ... ${verify}=${FALSE} + ... ${cert}=${NONE} + ... ${username}=${NONE} + + ${headers}= Create Register Admin Session ${server} ${access_token} + + IF '${username}' != '${NONE}' + ${cert}= Set variable ${{ ('${username}.crt','${username}.key') }} + END + + ${resp}= GET On Session + ... register_session + ... ${endpoint} + ... headers=${headers} + ... expected_status=any + ... verify=${verify} + ... cert=${cert} + RETURN ${resp} + +# NEW REQUESTS END + Post Request Capif - [Timeout] 60s + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${json}=${NONE} @@ -84,7 +172,7 @@ Post Request Capif RETURN ${resp} Get Request Capif - [Timeout] 60s + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${server}=${NONE} @@ -110,7 +198,7 @@ Get Request Capif RETURN ${resp} Get CA Vault - [Timeout] 60s + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${server}=${NONE} @@ -137,7 +225,7 @@ Get CA Vault RETURN ${response} Put Request Capif - [Timeout] 60s + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${json}=${NONE} @@ -166,7 +254,7 @@ Put Request Capif RETURN ${resp} Patch Request Capif - [Timeout] 60s + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${json}=${NONE} @@ -195,7 +283,7 @@ Patch Request Capif RETURN ${resp} Delete Request Capif - [Timeout] 60s + [Timeout] ${REQUESTS_TIMEOUT} [Arguments] ... ${endpoint} ... ${server}=${NONE} @@ -236,23 +324,18 @@ Register User At Jwt Auth Log cn=${cn} - &{body}= Create Dictionary - ... password=${password} - ... username=${username} - ... role=${role} - ... description=${description} - ... cn=${cn} - - Create Session jwtsession ${CAPIF_HTTPS_REGISTER_URL} verify=False disable_warnings=1 - - ${resp}= POST On Session jwtsession /register json=${body} - - Should Be Equal As Strings ${resp.status_code} 201 + ${resp}= Create User At Register + ... ${username} + ... ${password} + ... ${description} + ... email="${username}@nobody.com" ${get_auth_response}= Get Auth For User ${username} ${password} + Log Dictionary ${get_auth_response} + ${register_user_info}= Create Dictionary - ... netappID=${resp.json()['id']} + ... netappID=${resp.json()['uuid']} ... csr_request=${csr_request} ... &{resp.json()} ... &{get_auth_response} @@ -270,6 +353,8 @@ Register User At Jwt Auth Store In File ${username}.key ${register_user_info['private_key']} END + Call Method ${CAPIF_USERS} update_register_users ${register_user_info['uuid']} ${username} + RETURN ${register_user_info} Register User At Jwt Auth Provider @@ -287,24 +372,18 @@ Register User At Jwt Auth Provider ${amf_csr_request}= Create User Csr ${amf_username} amf # Register provider - &{body}= Create Dictionary - ... password=${password} - ... username=${username} - ... role=${role} - ... description=${description} - ... cn=${username} - - Create Session jwtsession ${CAPIF_HTTPS_REGISTER_URL} verify=False disable_warnings=1 - - ${resp}= POST On Session jwtsession /register json=${body} + ${resp}= Create User At Register + ... ${username} + ... ${password} + ... ${description} + ... email="${username}@nobody.com" - Should Be Equal As Strings ${resp.status_code} 201 - - # Get Auth to obtain access_token ${get_auth_response}= Get Auth For User ${username} ${password} + Log Dictionary ${get_auth_response} + ${register_user_info}= Create Dictionary - ... netappID=${resp.json()['id']} + ... netappID=${resp.json()['uuid']} ... csr_request=${csr_request} ... apf_csr_request=${apf_csr_request} ... aef_csr_request=${aef_csr_request} @@ -317,31 +396,80 @@ Register User At Jwt Auth Provider Log Dictionary ${register_user_info} + Call Method ${CAPIF_USERS} update_register_users ${register_user_info['uuid']} ${username} + RETURN ${register_user_info} -Get Auth For User - [Arguments] ${username} ${password} +Login Register Admin + ${headers}= Create Register Admin Session ${CAPIF_HTTPS_REGISTER_URL} + RETURN ${headers} + +Create User At Register + [Documentation] (Administrator) This Keyword create a user at register component. + [Arguments] ${username} ${password} ${description} ${email} - &{body}= Create Dictionary username=${username} password=${password} + # Obtain Admin Token to request creation of User + ${headers}= Login Register Admin - ${resp}= POST On Session jwtsession /getauth json=${body} + &{body}= Create Dictionary + ... username=${username} + ... password=${password} + ... description=${description} + ... email=${email} + ... enterprise=enterprise + ... country=Spain + ... purpose=testing + ... phone_number=123456789 + ... company_web=www.enterprise.com + ${resp}= Post On Session register_session /createUser headers=${headers} json=${body} + Should Be Equal As Strings ${resp.status_code} 201 + + RETURN ${resp} + +Delete User At Register + [Documentation] (Administrator) This Keyword delete a user from register. + [Arguments] ${username}=${NONE} ${uuid}=${NONE} + ${user_uuid}= Set Variable ${uuid} + + IF "${username}" != "${NONE}" + ${user_uuid}= Call Method ${CAPIF_USERS} get_user_uuid ${username} + END + + ${headers}= Create Register Admin Session ${CAPIF_HTTPS_REGISTER_URL} verify=False + + ${resp}= DELETE On Session register_session /deleteUser/${user_uuid} headers=${headers} + + Should Be Equal As Strings ${resp.status_code} 204 + + Call Method ${CAPIF_USERS} remove_register_users_entry ${user_uuid} + + RETURN ${resp} + +Get List of User At Register + [Documentation] (Administrator) This Keyword retrieve a list of users from register. + ${headers}= Create Register Admin Session ${CAPIF_HTTPS_REGISTER_URL} verify=False + + ${resp}= DELETE On Session register_session /getUsers headers=${headers} Should Be Equal As Strings ${resp.status_code} 200 - # Should Be Equal As Strings ${resp.json()['message']} Certificate created successfuly + RETURN ${resp.json()['users']} - RETURN ${resp.json()} +Get Auth For User + [Documentation] (User) This Keyword retrieve token to be used by user towards first interaction with CCF. + [Arguments] ${username} ${password} + ${auth}= Set variable ${{ ('${username}','${password}') }} + ${resp}= GET On Session register_session /getauth auth=${auth} -# Clean Test Information By HTTP Requests -# Create Session jwtsession ${CAPIF_HTTP_URL} verify=True + Should Be Equal As Strings ${resp.status_code} 200 + Log Dictionary ${resp.json()} -# ${resp}= DELETE On Session jwtsession /testdata -# Should Be Equal As Strings ${resp.status_code} 200 + RETURN ${resp.json()} Clean Test Information ${capif_users_dict}= Call Method ${CAPIF_USERS} get_capif_users_dict - ${register_users}= Call Method ${CAPIF_USERS} get_register_users + ${register_users_dict}= Call Method ${CAPIF_USERS} get_register_users_dict ${keys}= Get Dictionary Keys ${capif_users_dict} @@ -358,34 +486,25 @@ Clean Test Information Call Method ${CAPIF_USERS} remove_capif_users_entry ${key} END - FOR ${user} IN @{register_users} - &{body}= Create Dictionary - ... password=password - ... username=${user} - - Create Session jwtsession ${CAPIF_HTTPS_REGISTER_URL} verify=False disable_warnings=1 - - ${resp}= DELETE On Session jwtsession /remove json=${body} - - Should Be Equal As Strings ${resp.status_code} 204 - - Call Method ${CAPIF_USERS} remove_register_users_entry ${user} + ${uuids}= Get Dictionary Keys ${register_users_dict} + FOR ${uuid} IN @{uuids} + Delete User At Register uuid=${uuid} END Remove entity - [Arguments] ${entity_user} ${certificate_name}=${entity_user} + [Arguments] ${entity_user} ${certificate_name}=${entity_user} ${capif_users_dict}= Call Method ${CAPIF_USERS} get_capif_users_dict - ${register_users}= Call Method ${CAPIF_USERS} get_register_users + ${register_users_dict}= Call Method ${CAPIF_USERS} get_register_users_dict Log Dictionary ${capif_users_dict} - Log List ${register_users} + Log Dictionary ${register_users_dict} ${keys}= Get Dictionary Keys ${capif_users_dict} FOR ${key} IN @{keys} ${value}= Get From Dictionary ${capif_users_dict} ${key} - IF "${value}" == "${certificate_name}" + IF "${value}" == "${certificate_name}" ${resp}= Delete Request Capif ... ${key} ... server=${CAPIF_HTTPS_URL} @@ -398,9 +517,25 @@ Remove entity END END + Delete User At Register username=${entity_user} + + Log Dictionary ${capif_users_dict} + Log Dictionary ${register_users_dict} + +Remove Resource + [Arguments] ${resource_url} ${management_cert} ${username} + + ${resp}= Delete Request Capif + ... ${resource_url} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${management_cert} + + Status Should Be 204 ${resp} + &{body}= Create Dictionary ... password=password - ... username=${entity_user} + ... username=${username} Create Session jwtsession ${CAPIF_HTTPS_REGISTER_URL} verify=False disable_warnings=1 @@ -408,22 +543,16 @@ Remove entity Should Be Equal As Strings ${resp.status_code} 204 - Call Method ${CAPIF_USERS} remove_register_users_entry ${entity_user} - - Log Dictionary ${capif_users_dict} - Log List ${register_users} - - Invoker Default Onboarding [Arguments] ${invoker_username}=${INVOKER_USERNAME} ${register_user_info}= Register User At Jwt Auth - ... username=${INVOKER_USERNAME} role=${INVOKER_ROLE} + ... username=${invoker_username} role=${INVOKER_ROLE} # Send Onboarding Request ${request_body}= Create Onboarding Notification Body ... http://${CAPIF_CALLBACK_IP}:${CAPIF_CALLBACK_PORT}/netapp_callback ... ${register_user_info['csr_request']} - ... ${INVOKER_USERNAME} + ... ${invoker_username} ${resp}= Post Request Capif ... ${register_user_info['ccf_onboarding_url']} ... json=${request_body} @@ -437,11 +566,15 @@ Invoker Default Onboarding # Assertions Status Should Be 201 ${resp} Check Variable ${resp.json()} APIInvokerEnrolmentDetails - Check Location Header ${resp} ${LOCATION_INVOKER_RESOURCE_REGEX} + ${resource_url}= Check Location Header ${resp} ${LOCATION_INVOKER_RESOURCE_REGEX} # Store dummy signede certificate - Store In File ${INVOKER_USERNAME}.crt ${resp.json()['onboardingInformation']['apiInvokerCertificate']} + Store In File ${invoker_username}.crt ${resp.json()['onboardingInformation']['apiInvokerCertificate']} ${url}= Parse Url ${resp.headers['Location']} + Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${invoker_username} + + Set To Dictionary ${register_user_info} resource_url=${resource_url} + Set To Dictionary ${register_user_info} management_cert=${invoker_username} RETURN ${register_user_info} ${url} ${request_body} @@ -500,17 +633,26 @@ Provider Registration ... provider_enrollment_details=${request_body} ... resource_url=${resource_url} ... provider_register_response=${resp} + ... management_cert=${register_user_info['amf_username']} + + Call Method + ... ${CAPIF_USERS} + ... update_capif_users_dicts + ... ${register_user_info['resource_url'].path} + ... ${register_user_info['amf_username']} RETURN ${register_user_info} Provider Default Registration + [Arguments] ${provider_username}=${PROVIDER_USERNAME} # Register Provider ${register_user_info}= Register User At Jwt Auth Provider - ... username=${PROVIDER_USERNAME} role=${PROVIDER_ROLE} + ... username=${provider_username} role=${PROVIDER_ROLE} ${register_user_info}= Provider Registration ${register_user_info} Log Dictionary ${register_user_info} + RETURN ${register_user_info} Publish Service Api @@ -535,13 +677,6 @@ Basic ACL registration # Register APF ${register_user_info_provider}= Provider Default Registration - Call Method - ... ${CAPIF_USERS} - ... update_capif_users_dicts - ... ${register_user_info_provider['resource_url'].path} - ... ${AMF_PROVIDER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${PROVIDER_USERNAME} - ${service_api_description_published} ${resource_url} ${request_body}= Publish Service Api ... ${register_user_info_provider} ... service_1 @@ -563,7 +698,6 @@ Basic ACL registration ${register_user_info_invoker} ${url} ${request_body}= Invoker Default Onboarding Call Method ${CAPIF_USERS} update_capif_users_dicts ${url.path} ${INVOKER_USERNAME} - Call Method ${CAPIF_USERS} update_register_users ${INVOKER_USERNAME} # Test ${discover_response}= Get Request Capif @@ -591,3 +725,29 @@ Basic ACL registration END RETURN ${register_user_info_invoker} ${register_user_info_provider} ${service_api_description_published} + +Create Security Context Between invoker and provider + [Arguments] ${register_user_info_invoker} ${register_user_info_provider} + + ${discover_response}= Get Request Capif + ... ${DISCOVER_URL}${register_user_info_invoker['api_invoker_id']}&aef-id=${register_user_info_provider['aef_id']} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${register_user_info_invoker['management_cert']} + + Check Response Variable Type And Values ${discover_response} 200 DiscoveredAPIs + + # create Security Context + ${request_body}= Create Service Security From Discover Response + ... http://${CAPIF_HOSTNAME}:${CAPIF_HTTP_PORT}/test + ... ${discover_response} + + ${resp}= Put Request Capif + ... /capif-security/v1/trustedInvokers/${register_user_info_invoker['api_invoker_id']} + ... json=${request_body} + ... server=${CAPIF_HTTPS_URL} + ... verify=ca.crt + ... username=${register_user_info_invoker['management_cert']} + + Check Response Variable Type And Values ${resp} 201 ServiceSecurity + diff --git a/tests/tasks/Dummy Info/__init__.robot b/tests/tasks/Dummy Info/__init__.robot new file mode 100644 index 0000000000000000000000000000000000000000..f6bbb181671c4e30588946237ed7050ff619613e --- /dev/null +++ b/tests/tasks/Dummy Info/__init__.robot @@ -0,0 +1,2 @@ +*** Settings *** +Force Tags populate \ No newline at end of file diff --git a/tests/tasks/Dummy Info/populate.robot b/tests/tasks/Dummy Info/populate.robot new file mode 100644 index 0000000000000000000000000000000000000000..9a61a4075a5085bb4d0a8a56a283f96ecb4113b1 --- /dev/null +++ b/tests/tasks/Dummy Info/populate.robot @@ -0,0 +1,126 @@ +*** Settings *** +Resource /opt/robot-tests/tests/resources/common.resource +Resource /opt/robot-tests/tests/resources/api_invoker_management_requests/apiInvokerManagementRequests.robot +Resource ../../resources/common.resource +Resource ../../resources/common/basicRequests.robot +Library /opt/robot-tests/tests/libraries/bodyRequests.py +Library Process +Library Collections +Library ArchiveLibrary +Library OperatingSystem +Library DateTime + +Suite Teardown Reset Testing Environment +Test Setup Reset Testing Environment + + +*** Variables *** +${API_INVOKER_NOT_REGISTERED} not-valid +${TOTAL_INVOKERS} 10 +${TOTAL_PROVIDERS} 10 + +${BACKUP_DIRECTORY} backup +${RESULT_FOLDER} /opt/robot-tests/results +${OUTPUT_ZIP_FILE} entities_loaded.zip + +${INVOKER_USERNAME_POPULATE} ${INVOKER_USERNAME}_POPULATE +${PROVIDER_USERNAME_POPULATE} ${PROVIDER_USERNAME}_POPULATE + + +*** Test Cases *** +Create Dummy Invokers and Providers + [Tags] populate-create + ${entities_dictionary}= Create Dictionary + Create Directory ${BACKUP_DIRECTORY} + + FOR ${counter} IN RANGE ${TOTAL_PROVIDERS} + ${USERNAME}= Set Variable ${PROVIDER_USERNAME_POPULATE}_${counter} + ${register_user_info}= Run Keyword And Continue On Failure Provider Default Registration ${USERNAME} + + Set To Dictionary ${entities_dictionary} ${USERNAME}=${register_user_info} + Copy Files *${USERNAME}* ${BACKUP_DIRECTORY}/ + + ${service_api_description_published} + ... ${resource_url} + ... ${request_body}= + ... Run Keyword And Continue On Failure + ... Publish Service Api + ... ${register_user_info} + ... ROBOT_SERVICE_${counter} + END + + ${last_provider_used}= Evaluate -1 + FOR ${counter} IN RANGE ${TOTAL_INVOKERS} + ${USERNAME}= Set Variable ${INVOKER_USERNAME_POPULATE}_${counter} + ${register_user_info} ${url} ${request_body}= Run Keyword And Continue On Failure + ... Invoker Default Onboarding + ... ${USERNAME} + + IF ${TOTAL_PROVIDERS} > 0 + ${last_provider_used} ${register_user_info_provider}= Get Provider + ... ${last_provider_used} + ... ${entities_dictionary} + Log Dictionary ${register_user_info_provider} + + Run Keyword And Continue On Failure + ... Create Security Context Between invoker and provider + ... ${register_user_info} + ... ${register_user_info_provider} + END + + Set To Dictionary ${entities_dictionary} ${USERNAME}=${register_user_info} + Copy Files ${USERNAME}* ${BACKUP_DIRECTORY}/ + END + + Write Dictionary ${BACKUP_DIRECTORY}/registers.json ${entities_dictionary} + ${date}= Get Current Date result_format=%Y_%m_%d_%H_%M_%S + Create Zip From Files In Directory ${BACKUP_DIRECTORY} ${RESULT_FOLDER}/${date}_${OUTPUT_ZIP_FILE} + + ${result}= Run Process ls -l + + Log Many ${result.stdout} + +Remove Dummy Invokers and Providers + [Tags] populate-remove + ${files}= List Files In Directory ${RESULT_FOLDER} *${OUTPUT_ZIP_FILE} + ${sorted_list}= Copy List ${files} + + Sort List ${sorted_list} + ${last_backup}= Get From List ${sorted_list} -1 + + Copy File ${RESULT_FOLDER}/${last_backup} ./ + Extract Zip File ${last_backup} + + ${entities_dictionary}= Read Dictionary registers.json + + Log Dictionary ${entities_dictionary} + + FOR ${username} IN @{entities_dictionary} + Log ${username}=${entities_dictionary}[${username}] + ${resource_url}= Set Variable ${entities_dictionary}[${username}][resource_url] + ${management_cert}= Set Variable ${entities_dictionary}[${username}][management_cert] + Run Keyword And Ignore Error Remove Resource ${resource_url.path} ${management_cert} ${username} + END + + ${result}= Run Process ls -l + + Log Many ${result.stdout} + + +*** Keywords *** +Get Provider + [Arguments] ${index} ${entities_dictionary} + ${index}= Evaluate ${index} + 1 + IF ${index} == ${TOTAL_PROVIDERS} + ${index}= Evaluate 0 + END + + ${username}= Set Variable ${PROVIDER_USERNAME_POPULATE}_${index} + ${usernames}= Get Dictionary Keys ${entities_dictionary} + IF '${username}' in ${usernames} + log ${username} is in the list + ELSE + Log Dictionary not contain ${username}, no provider returned + END + + RETURN ${index} ${entities_dictionary}[${username}] diff --git a/tests/tasks/__init__.robot b/tests/tasks/__init__.robot new file mode 100644 index 0000000000000000000000000000000000000000..a65a0e734aefe8abbd5786c5f14af684576f2b36 --- /dev/null +++ b/tests/tasks/__init__.robot @@ -0,0 +1,56 @@ +*** Settings *** +Resource /opt/robot-tests/tests/resources/common.resource +Resource ../resources/common.resource + +Suite Setup Prepare environment +# Suite Teardown Reset Testing Environment + +Force Tags tasks + + +*** Keywords *** +Prepare environment + Log ${CAPIF_HOSTNAME} + Log "${CAPIF_HTTP_PORT}" + Log "${CAPIF_HTTPS_PORT}" + + Set Global Variable ${CAPIF_HTTP_VAULT_URL} http://${CAPIF_VAULT}/ + IF "${CAPIF_VAULT_PORT}" != "" + Set Global Variable ${CAPIF_HTTP_VAULT_URL} http://${CAPIF_VAULT}:${CAPIF_VAULT_PORT}/ + END + + Set Global Variable ${CAPIF_HTTPS_REGISTER_URL} https://${CAPIF_REGISTER}/ + IF "${CAPIF_REGISTER_PORT}" != "" + Set Global Variable ${CAPIF_HTTPS_REGISTER_URL} https://${CAPIF_REGISTER}:${CAPIF_REGISTER_PORT}/ + END + + Set Global Variable ${CAPIF_HTTP_URL} http://${CAPIF_HOSTNAME}/ + IF "${CAPIF_HTTP_PORT}" != "" + Set Global Variable ${CAPIF_HTTP_URL} http://${CAPIF_HOSTNAME}:${CAPIF_HTTP_PORT}/ + END + + Set Global Variable ${CAPIF_HTTPS_URL} https://${CAPIF_HOSTNAME}/ + IF "${CAPIF_HTTPS_PORT}" != "" + Set Global Variable ${CAPIF_HTTPS_URL} https://${CAPIF_HOSTNAME}:${CAPIF_HTTPS_PORT}/ + END + + ${status} ${CAPIF_IP}= Run Keyword And Ignore Error Get Ip From Hostname ${CAPIF_HOSTNAME} + + IF "${status}" == "PASS" + Log We will use a remote deployment + Log ${CAPIF_IP} + ELSE + Log We will use a local deployment + Add Dns To Hosts 127.0.0.1 ${CAPIF_HOSTNAME} + END + # Obtain ca root certificate + Retrieve Ca Root + + Reset Testing Environment + +Retrieve Ca Root + [Documentation] This keyword retrieve ca.root from CAPIF and store it at ca.crt in order to use at TLS communications + ${resp}= Get CA Vault /v1/secret/data/ca ${CAPIF_HTTP_VAULT_URL} + Status Should Be 200 ${resp} + Log ${resp.json()['data']['data']['ca']} + Store In File ca.crt ${resp.json()['data']['data']['ca']} diff --git a/tools/robot/Dockerfile b/tools/robot/Dockerfile index 49cea1714ace28c777903b7c30f30bad1ae674cf..347f226da0bf93d5e1f8a9adaa18901c5dafc000 100644 --- a/tools/robot/Dockerfile +++ b/tools/robot/Dockerfile @@ -25,6 +25,7 @@ VOLUME $ROBOT_RESULTS_DIRECTORY WORKDIR $ROBOT_DIRECTORY ENV DEBIAN_FRONTEND=noninteractive +RUN echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections # Install dependencies RUN apt-get update @@ -49,14 +50,15 @@ RUN apt-get install -y --no-install-recommends \ python3-venv \ python2.7-dev \ libssl-dev \ - libldap2-dev libsasl2-dev ldap-utils slapd tox lcov valgrind\ - tshark + libldap2-dev libsasl2-dev ldap-utils slapd tox lcov valgrind \ + tshark \ + nodejs \ + npm -RUN add-apt-repository ppa:deadsnakes/ppa +RUN add-apt-repository -y ppa:deadsnakes/ppa RUN apt-get update RUN apt-get install -y --fix-missing python3.10 python3.10-venv python3.10-dev - RUN mkdir /opt/venv RUN python3.10 -m venv /opt/venv diff --git a/tools/robot/basicRequirements.txt b/tools/robot/basicRequirements.txt index 87752271253dc67c7e0c0d8e8f42d4768001b074..06e5cc276ee6b6b950d1e1cff0cb272deee5a0b6 100644 --- a/tools/robot/basicRequirements.txt +++ b/tools/robot/basicRequirements.txt @@ -1,101 +1,103 @@ # Requirements needed when generating releases. See BUILD.rst for details. -appdirs==1.4.4 -argh==0.26.2 -arrow==1.2.3 -async-generator==1.10 -async-timeout==4.0.2 -attrs==22.1.0 -bcrypt==4.0.1 -beautifulsoup4==4.11.1 -binaryornot==0.4.4 -bson==0.5.10 -certifi==2021.10.8 -cffi==1.15.1 -chardet==5.0.0 -charset-normalizer==2.0.12 -click==8.0.1 -configparser==5.3.0 -cookiecutter==2.1.1 -coverage==4.5.4 -cryptography==38.0.1 -Deprecated==1.2.13 -distlib==0.3.6 -dnspython==2.2.1 -docutils==0.19 -exceptiongroup==1.0.0rc9 -filelock==3.8.0 -flake8==3.9.2 -h11==0.14.0 -robotframework-httpctrl==0.3.1 -idna==3.4 -iniconfig==1.1.1 -invoke==1.6.0 -ipaddress==1.0.23 -Jinja2==3.1.2 -jinja2-time==0.2.0 -lxml==4.9.1 -MarkupSafe==2.1.1 -mccabe==0.6.1 -numpy==1.23.4 -outcome==1.2.0 -packaging==21.3 -pandas==1.5.1 -paramiko==2.11.0 -pathtools==0.1.2 -platformdirs==2.5.2 -pluggy==0.13.1 -psutil==5.9.3 -py==1.11.0 -pyasn1==0.4.8 -pyasn1-modules==0.2.8 -pycodestyle==2.7.0 -pycparser==2.21 -pyflakes==2.3.1 -PyGithub==1.56 -PyJWT==2.6.0 -pymongo==4.3.2 -PyNaCl==1.5.0 -pyOpenSSL==22.1.0 -pyparsing==3.0.9 -PySocks==1.7.1 -pytest==6.2.4 -python-dateutil==2.8.2 -python-ldap==3.4.3 -python-slugify==6.1.2 -pythonping==1.1.3 -pytz==2022.5 -PyYAML==6.0 -redis==4.3.4 -rellu==0.7 -requests==2.28.1 -rfc3987==1.3.8 -robotframework==6.0 -robotframework-lint==1.1 -robotframework-mongodb-library==3.2 -robotframework-pythonlibcore==3.0.0 -robotframework-requests==0.9.3 -robotframework-seleniumlibrary==6.0.0 -robotframework-sshlibrary==3.8.0 -robotremoteserver==1.1 -scp==0.14.4 -selenium==4.5.0 -six==1.16.0 -sniffio==1.3.0 -sortedcontainers==2.4.0 -soupsieve==2.3.2.post1 -sshconf==0.2.5 -text-unidecode==1.3 -toml==0.10.2 -tomli==2.0.1 -tox==3.26.0 -tqdm==4.64.1 -trio==0.22.0 -trio-websocket==0.9.2 -typing-extensions==3.10.0.2 -urllib3==1.26.12 -virtualenv==20.16.5 -watchdog==0.9.0 -webdrivermanager==0.10.0 -wrapt==1.14.1 -wsproto==1.2.0 -xlrd==2.0.1 \ No newline at end of file +appdirs == 1.4.4 +argh == 0.26.2 +arrow == 1.2.3 +async-generator == 1.10 +async-timeout == 4.0.2 +attrs == 22.1.0 +bcrypt == 4.0.1 +beautifulsoup4 == 4.11.1 +binaryornot == 0.4.4 +bson == 0.5.10 +certifi == 2021.10.8 +cffi == 1.15.1 +chardet == 5.0.0 +charset-normalizer == 2.0.12 +click == 8.1.7 +configparser == 5.3.0 +cookiecutter == 2.1.1 +coverage == 4.5.4 +cryptography == 42.0.8 +Deprecated == 1.2.13 +distlib == 0.3.6 +dnspython == 2.2.1 +docutils == 0.19 +exceptiongroup == 1.0.0rc9 +filelock == 3.8.0 +flake8 == 3.9.2 +flask == 3.0.3 +h11 == 0.14.0 +idna == 3.4 +iniconfig == 1.1.1 +invoke == 1.6.0 +ipaddress == 1.0.23 +Jinja2 == 3.1.2 +jinja2-time == 0.2.0 +lxml == 4.9.1 +MarkupSafe == 2.1.1 +mccabe == 0.6.1 +numpy == 1.23.4 +outcome == 1.2.0 +packaging == 21.3 +pandas == 1.5.1 +paramiko == 2.11.0 +pathtools == 0.1.2 +platformdirs == 2.5.2 +pluggy == 0.13.1 +psutil == 5.9.3 +py == 1.11.0 +pyasn1 == 0.4.8 +pyasn1-modules == 0.2.8 +pycodestyle == 2.7.0 +pycparser == 2.21 +pyflakes == 2.3.1 +PyGithub == 1.56 +PyJWT == 2.6.0 +pymongo == 4.7.3 +PyNaCl == 1.5.0 +pyOpenSSL == 24.1.0 +pyparsing == 3.0.9 +PySocks == 1.7.1 +pytest == 6.2.4 +python-dateutil == 2.8.2 +python-ldap == 3.4.3 +python-slugify == 6.1.2 +pythonping == 1.1.3 +pytz == 2022.5 +PyYAML == 6.0 +redis == 4.5.4 +rellu == 0.7 +requests == 2.28.1 +rfc3987 == 1.3.8 +robotframework == 7.0 +robotframework-archivelibrary == 0.4.2 +robotframework-httpctrl == 0.3.1 +robotframework-lint == 1.1 +robotframework-mongodb-library == 3.2 +robotframework-pythonlibcore == 4.4.1 +robotframework-requests == 0.9.3 +robotframework-seleniumlibrary == 6.0.0 +robotframework-sshlibrary == 3.8.0 +robotremoteserver == 1.1 +scp == 0.14.4 +selenium == 4.5.0 +six == 1.16.0 +sniffio == 1.3.0 +sortedcontainers == 2.4.0 +soupsieve == 2.3.2.post1 +sshconf == 0.2.5 +text-unidecode == 1.3 +toml == 0.10.2 +tomli == 2.0.1 +tox == 3.26.0 +tqdm == 4.64.1 +trio == 0.22.0 +trio-websocket == 0.9.2 +typing-extensions == 4.11.0 +urllib3 == 1.26.12 +virtualenv == 20.16.5 +watchdog == 4.0.0 +webdrivermanager == 0.10.0 +wrapt == 1.15.0 +wsproto == 1.2.0 +xlrd == 2.0.1 diff --git a/tools/robot/basicRobotInstall.sh b/tools/robot/basicRobotInstall.sh index 511821fbab10d55f80dd2a13af1d60035ca0bd40..ae0bd6bd8b1bdedccc34b4d6152bffc8bb5f467b 100644 --- a/tools/robot/basicRobotInstall.sh +++ b/tools/robot/basicRobotInstall.sh @@ -1,7 +1,6 @@ #!/bin/bash echo "Installing basic software related with robotFramework" -source /opt/venv/bin/activate; +source /opt/venv/bin/activate pip install --upgrade pip -pip install --upgrade robotframework; -pip install -r $1 +pip install -r $1 echo "Robot framework installed"