Skip to content

Commit 3adffa8

Browse files
committed
fixes(api) allow no v2 api
Allow client without no V2 api Closes #220
1 parent 77c1923 commit 3adffa8

39 files changed

+164
-87
lines changed

.github/workflows/pythonpackage.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
max-parallel: 1
1515
matrix:
16-
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
16+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
1717

1818
steps:
1919
- uses: actions/checkout@v4

main/cloudfoundry_client/client.py

Lines changed: 45 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,27 @@
5252
class Info:
5353
def __init__(
5454
self,
55-
api_v2_version: str,
55+
api_v2_url: str,
56+
api_v3_url: str,
5657
authorization_endpoint: str,
5758
api_endpoint: str,
5859
doppler_endpoint: Optional[str],
5960
log_stream_endpoint: Optional[str],
6061
):
61-
self.api_v2_version = api_v2_version
62+
self._api_v2_url = api_v2_url
63+
self._api_v3_url = api_v3_url
6264
self.authorization_endpoint = authorization_endpoint
6365
self.api_endpoint = api_endpoint
6466
self.doppler_endpoint = doppler_endpoint
6567
self.log_stream_endpoint = log_stream_endpoint
6668

69+
@property
70+
def api_v2_url(self) -> Optional[str]:
71+
return self._api_v2_url
72+
73+
@property
74+
def api_v3_url(self) -> Optional[str]:
75+
return self._api_v3_url
6776

6877
class NetworkingV1External(object):
6978
def __init__(self, target_endpoint: str, credential_manager: "CloudFoundryClient"):
@@ -83,18 +92,18 @@ def __init__(self, target_endpoint: str, credential_manager: "CloudFoundryClient
8392
self.service_plans = ServicePlanManagerV2(target_endpoint, credential_manager)
8493
# Default implementations
8594
self.event = EventManager(target_endpoint, credential_manager)
86-
self.organizations = EntityManagerV2(target_endpoint, credential_manager, "/v2/organizations")
87-
self.private_domains = EntityManagerV2(target_endpoint, credential_manager, "/v2/private_domains")
95+
self.organizations = EntityManagerV2(target_endpoint, credential_manager, "/organizations")
96+
self.private_domains = EntityManagerV2(target_endpoint, credential_manager, "/private_domains")
8897
self.routes = RouteManager(target_endpoint, credential_manager)
89-
self.services = EntityManagerV2(target_endpoint, credential_manager, "/v2/services")
90-
self.shared_domains = EntityManagerV2(target_endpoint, credential_manager, "/v2/shared_domains")
98+
self.services = EntityManagerV2(target_endpoint, credential_manager, "/services")
99+
self.shared_domains = EntityManagerV2(target_endpoint, credential_manager, "/shared_domains")
91100
self.spaces = SpaceManagerV2(target_endpoint, credential_manager)
92-
self.stacks = EntityManagerV2(target_endpoint, credential_manager, "/v2/stacks")
101+
self.stacks = EntityManagerV2(target_endpoint, credential_manager, "/stacks")
93102
self.user_provided_service_instances = EntityManagerV2(
94-
target_endpoint, credential_manager, "/v2/user_provided_service_instances"
103+
target_endpoint, credential_manager, "/user_provided_service_instances"
95104
)
96-
self.security_groups = EntityManagerV2(target_endpoint, credential_manager, "/v2/security_groups")
97-
self.users = EntityManagerV2(target_endpoint, credential_manager, "/v2/users")
105+
self.security_groups = EntityManagerV2(target_endpoint, credential_manager, "/security_groups")
106+
self.users = EntityManagerV2(target_endpoint, credential_manager, "/users")
98107
# Resources implementation used by push operation
99108
self.resources = ResourceManager(target_endpoint, credential_manager)
100109

@@ -146,8 +155,6 @@ def __init__(self, target_endpoint: str, client_id: str = "cf", client_secret: s
146155
self.login_hint = kwargs.get("login_hint")
147156
target_endpoint_trimmed = target_endpoint.rstrip("/")
148157
info = self._get_info(target_endpoint_trimmed, proxy, verify=verify)
149-
if not info.api_v2_version.startswith("2."):
150-
raise AssertionError("Only version 2 is supported for now. Found %s" % info.api_v2_version)
151158
service_information = ServiceInformation(
152159
None, "%s/oauth/token" % info.authorization_endpoint, client_id, client_secret, [], verify
153160
)
@@ -156,8 +163,16 @@ def __init__(self, target_endpoint: str, client_id: str = "cf", client_secret: s
156163
proxies=proxy,
157164
user_agent=kwargs.get("user_agent", "cf-python-client")
158165
)
159-
self.v2 = V2(target_endpoint_trimmed, self)
160-
self.v3 = V3(target_endpoint_trimmed, self)
166+
self._v2 = (
167+
V2(info.api_v2_url, self)
168+
if info.api_v2_url is not None
169+
else None
170+
)
171+
self._v3 = (
172+
V3(info.api_v3_url, self)
173+
if info.api_v3_url is not None
174+
else None
175+
)
161176
self._doppler = (
162177
DopplerClient(
163178
info.doppler_endpoint,
@@ -181,6 +196,18 @@ def __init__(self, target_endpoint: str, client_id: str = "cf", client_secret: s
181196
self.networking_v1_external = NetworkingV1External(target_endpoint_trimmed, self)
182197
self.info = info
183198

199+
@property
200+
def v2(self) -> V2:
201+
if self._v2 is None:
202+
raise NotImplementedError("No V2 endpoint for this instance")
203+
return self._v2
204+
205+
@property
206+
def v3(self) -> V3:
207+
if self._v3 is None:
208+
raise NotImplementedError("No V3 endpoint for this instance")
209+
return self._v3
210+
184211
@property
185212
def doppler(self) -> DopplerClient:
186213
if self._doppler is None:
@@ -194,7 +221,6 @@ def rlpgateway(self):
194221
if self._rlpgateway is None:
195222
raise NotImplementedError("No RLP gateway endpoint for this instance")
196223
else:
197-
198224
return self._rlpgateway
199225

200226
def _get_info(self, target_endpoint: str, proxy: Optional[dict] = None, verify: bool = True) -> Info:
@@ -206,8 +232,11 @@ def _get_info(self, target_endpoint: str, proxy: Optional[dict] = None, verify:
206232
root_links = root_info["links"]
207233
logging = root_links.get("logging")
208234
log_stream = root_links.get("log_stream")
235+
cloud_controller_v2 = root_links.get("cloud_controller_v2")
236+
cloud_controller_v3 = root_links.get("cloud_controller_v3")
209237
return Info(
210-
root_links["cloud_controller_v2"]["meta"]["version"],
238+
cloud_controller_v2["href"] if cloud_controller_v2 is not None else None,
239+
cloud_controller_v3["href"] if cloud_controller_v3 is not None else None,
211240
self._resolve_login_endpoint(root_links),
212241
target_endpoint,
213242
logging.get("href") if logging is not None else None,

main/cloudfoundry_client/common_objects.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import json
2-
from typing import Callable, TypeVar, Generic, List, Union
2+
from typing import Callable, TypeVar, Generic, List, Union, Optional
33

44

55
class Request(dict):
@@ -21,7 +21,7 @@ def __init__(self, *args, **kwargs):
2121
class Pagination(Generic[ENTITY]):
2222
def __init__(self, first_page: JsonObject,
2323
total_result: int,
24-
next_page_loader: Callable[[JsonObject], Union[None, JsonObject]],
24+
next_page_loader: Callable[[JsonObject], Optional[JsonObject]],
2525
resources_accessor: Callable[[JsonObject], List[JsonObject]],
2626
instance_creator: Callable[[JsonObject], ENTITY]):
2727
self._first_page = first_page

main/cloudfoundry_client/v2/apps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class AppManager(EntityManager):
7777

7878
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
7979
super(AppManager, self).__init__(
80-
target_endpoint, client, "/v2/apps", lambda pairs: Application(target_endpoint, client, pairs)
80+
target_endpoint, client, "/apps", lambda pairs: Application(target_endpoint, client, pairs)
8181
)
8282

8383
def get_stats(self, application_guid: str) -> Dict[str, JsonObject]:

main/cloudfoundry_client/v2/buildpacks.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class BuildpackManager(EntityManager):
1010
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
11-
super(BuildpackManager, self).__init__(target_endpoint, client, "/v2/buildpacks")
11+
super(BuildpackManager, self).__init__(target_endpoint, client, "/buildpacks")
1212

1313
def update(self, buildpack_guid: str, parameters: dict) -> Entity:
1414
return super(BuildpackManager, self)._update(buildpack_guid, parameters)

main/cloudfoundry_client/v2/entities.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def _list(self, requested_path: str, entity_builder: Optional[EntityBuilder] = N
6868
lambda page: page["resources"],
6969
lambda json_object: current_builder(list(json_object.items())))
7070

71-
def _next_page(self, current_page: JsonObject) -> Union[None, JsonObject]:
71+
def _next_page(self, current_page: JsonObject) -> Optional[JsonObject]:
7272
next_url = current_page.get("next_url")
7373
if next_url is None:
7474
return None

main/cloudfoundry_client/v2/events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class EventManager(EntityManager):
1010
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
11-
super(EventManager, self).__init__(target_endpoint, client, "/v2/events")
11+
super(EventManager, self).__init__(target_endpoint, client, "/events")
1212

1313
def list_by_type(self, event_type: str) -> Generator[Entity, None, None]:
1414
return self._list(self.entity_uri, type=event_type)

main/cloudfoundry_client/v2/jobs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@ def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1212
self.client = client
1313

1414
def get(self, job_guid: str) -> JsonObject:
15-
return self.client.get("%s/v2/jobs/%s" % (self.target_endpoint, job_guid)).json(object_pairs_hook=JsonObject)
15+
return self.client.get("%s/jobs/%s" % (self.target_endpoint, job_guid)).json(object_pairs_hook=JsonObject)

main/cloudfoundry_client/v2/resources.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@ def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
1212
self.client = client
1313

1414
def match(self, items: List[dict]) -> List[JsonObject]:
15-
response = self.client.put("%s/v2/resource_match" % self.client.info.api_endpoint, json=items)
15+
response = self.client.put("%s/resource_match" % self.client.info.api_endpoint, json=items)
1616
return response.json(object_pairs_hook=JsonObject)

main/cloudfoundry_client/v2/routes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class RouteManager(EntityManager):
1010
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
11-
super(RouteManager, self).__init__(target_endpoint, client, "/v2/routes")
11+
super(RouteManager, self).__init__(target_endpoint, client, "/routes")
1212

1313
def create_tcp_route(self, domain_guid: str, space_guid: str, port: Optional[int] = None) -> Entity:
1414
request = self._request(domain_guid=domain_guid, space_guid=space_guid)

0 commit comments

Comments
 (0)