From f3ca15d569b253b2b562b8e06689e47ee92d8a8d Mon Sep 17 00:00:00 2001 From: David Duarte <102606398+daviddmd@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:38:43 +0200 Subject: [PATCH 1/4] fix(networking): Update entities _get_url_filtered function fix(networking): Update _append_encoded_parameter function to append the parameters with the %s=%s format, in order to be compliant with the Policy Server API interface --- cloudfoundry_client/networking/entities.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cloudfoundry_client/networking/entities.py b/cloudfoundry_client/networking/entities.py index da393d6..07d34e7 100644 --- a/cloudfoundry_client/networking/entities.py +++ b/cloudfoundry_client/networking/entities.py @@ -116,9 +116,9 @@ def _append_encoded_parameter(parameters: List[str], args: Tuple[str, Any]) -> L for value in value_list: parameters.append("%s=%s" % (parameter_name, str(value))) elif isinstance(parameter_value, (list, tuple)): - parameters.append("q=%s" % quote("%s IN %s" % (parameter_name, ",".join(parameter_value)))) + parameters.append("%s=%s" % (parameter_name, quote(",".join(parameter_value)))) else: - parameters.append("q=%s" % quote("%s:%s" % (parameter_name, str(parameter_value)))) + parameters.append("%s=%s" % (parameter_name, quote(str(parameter_value)))) return parameters if len(kwargs) > 0: From 6f289ee10385c2e846c1bb3800be1a2a930bd769 Mon Sep 17 00:00:00 2001 From: David Duarte <102606398+daviddmd@users.noreply.github.com> Date: Fri, 27 Jun 2025 16:47:21 +0200 Subject: [PATCH 2/4] feat(apps): Add function for the /v3/apps/:guid/manifest endpoint --- cloudfoundry_client/v3/apps.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cloudfoundry_client/v3/apps.py b/cloudfoundry_client/v3/apps.py index 1453575..4382ea2 100644 --- a/cloudfoundry_client/v3/apps.py +++ b/cloudfoundry_client/v3/apps.py @@ -24,3 +24,6 @@ def get_env(self, application_guid: str) -> JsonObject: def get_routes(self, application_guid: str) -> JsonObject: return super(AppManager, self)._get("%s%s/%s/routes" % (self.target_endpoint, self.entity_uri, application_guid)) + + def get_manifest(self, application_guid: str) -> str: + return self.client.get(url="%s%s/%s/manifest" % (self.target_endpoint, self.entity_uri, application_guid)).text From ac205012251ccb753e01827c064409156b53180f Mon Sep 17 00:00:00 2001 From: David Duarte <102606398+daviddmd@users.noreply.github.com> Date: Sat, 5 Jul 2025 19:14:12 +0200 Subject: [PATCH 3/4] test: Add test for the v3 apps get_manifest function --- .../v3/apps/GET_{id}_manifest_response.yml | 28 +++++++++++++++++++ tests/v3/test_apps.py | 28 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 tests/fixtures/v3/apps/GET_{id}_manifest_response.yml diff --git a/tests/fixtures/v3/apps/GET_{id}_manifest_response.yml b/tests/fixtures/v3/apps/GET_{id}_manifest_response.yml new file mode 100644 index 0000000..f263616 --- /dev/null +++ b/tests/fixtures/v3/apps/GET_{id}_manifest_response.yml @@ -0,0 +1,28 @@ +--- +applications: + - name: my-app + stack: cflinuxfs4 + features: + ssh: true + revisions: true + service-binding-k8s: false + file-based-vcap-services: false + services: + - my-service + routes: + - route: my-app.example.com + protocol: http1 + processes: + - type: web + instances: 2 + memory: 512M + log-rate-limit-per-second: 1KB + disk_quota: 1024M + health-check-type: http + health-check-http-endpoint: /healthy + health-check-invocation-timeout: 10 + health-check-interval: 5 + readiness-health-check-type: http + readiness-health-check-http-endpoint: /ready + readiness-health-check-invocation-timeout: 20 + readiness-health-check-interval: 5 \ No newline at end of file diff --git a/tests/v3/test_apps.py b/tests/v3/test_apps.py index c601170..b8a6432 100644 --- a/tests/v3/test_apps.py +++ b/tests/v3/test_apps.py @@ -1,5 +1,7 @@ import unittest +import yaml from http import HTTPStatus +from typing import Optional, List, Union from abstract_test_case import AbstractTestCase from cloudfoundry_client.common_objects import JsonObject @@ -132,3 +134,29 @@ def test_list_include_space(self): self.assertIsInstance(all_spaces[0], Entity) self.assertEqual(all_spaces[1]["name"], "my_space") self.assertIsInstance(all_spaces[1], Entity) + + def test_get_manifest(self): + self.client.get.return_value = self.mock_response( + "/v3/apps/app_id/manifest", HTTPStatus.OK, {"Content-Type": "application/x-yaml"}, "v3", "apps", + "GET_{id}_manifest_response.yml" + ) + manifest_response: str = self.client.v3.apps.get_manifest("app_id") + self.assertIsInstance(manifest_response, str) + manifest: dict = yaml.safe_load(manifest_response) + applications: Optional[list[dict]] = manifest.get("applications") + self.assertIsInstance(applications, list) + self.assertEqual(len(applications), 1) + application: dict = applications[0] + self.assertEqual(application.get("name"), "my-app") + self.assertEqual(application.get("stack"), "cflinuxfs4") + application_services: Optional[list[str]] = application.get("services") + self.assertIsInstance(application_services, list) + self.assertEqual(len(application_services),1) + self.assertEqual(application_services[0],"my-service") + application_routes: Optional[List[Union[dict,str]]] = application.get("routes") + self.assertIsInstance(application_routes,list) + self.assertEqual(len(application_routes),1) + application_route: dict = application_routes[0] + self.assertIsInstance(application_route,dict) + self.assertEqual(application_route.get("route"),"my-app.example.com") + self.assertEqual(application_route.get("protocol"),"http1") \ No newline at end of file From 206b0f285eba831b09a7fb28624550a39d5f5b7d Mon Sep 17 00:00:00 2001 From: David Duarte <102606398+daviddmd@users.noreply.github.com> Date: Sat, 5 Jul 2025 20:31:20 +0200 Subject: [PATCH 4/4] test: Fix formatting of statements in test_get_manifest function --- tests/v3/test_apps.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/v3/test_apps.py b/tests/v3/test_apps.py index b8a6432..8aeb0cf 100644 --- a/tests/v3/test_apps.py +++ b/tests/v3/test_apps.py @@ -151,12 +151,12 @@ def test_get_manifest(self): self.assertEqual(application.get("stack"), "cflinuxfs4") application_services: Optional[list[str]] = application.get("services") self.assertIsInstance(application_services, list) - self.assertEqual(len(application_services),1) - self.assertEqual(application_services[0],"my-service") - application_routes: Optional[List[Union[dict,str]]] = application.get("routes") - self.assertIsInstance(application_routes,list) - self.assertEqual(len(application_routes),1) + self.assertEqual(len(application_services), 1) + self.assertEqual(application_services[0], "my-service") + application_routes: Optional[List[Union[dict, str]]] = application.get("routes") + self.assertIsInstance(application_routes, list) + self.assertEqual(len(application_routes), 1) application_route: dict = application_routes[0] - self.assertIsInstance(application_route,dict) - self.assertEqual(application_route.get("route"),"my-app.example.com") - self.assertEqual(application_route.get("protocol"),"http1") \ No newline at end of file + self.assertIsInstance(application_route, dict) + self.assertEqual(application_route.get("route"), "my-app.example.com") + self.assertEqual(application_route.get("protocol"), "http1")