Skip to content

Commit a9f5c7a

Browse files
authored
feature(v3) add droplets + fixes list app routes + initiate packages (#285)
See #280
1 parent bedfb19 commit a9f5c7a

18 files changed

+1040
-111
lines changed

cloudfoundry_client/client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,11 @@
3030
from cloudfoundry_client.v3.apps import AppManager
3131
from cloudfoundry_client.v3.buildpacks import BuildpackManager
3232
from cloudfoundry_client.v3.domains import DomainManager
33+
from cloudfoundry_client.v3.droplets import DropletManager
3334
from cloudfoundry_client.v3.feature_flags import FeatureFlagManager
3435
from cloudfoundry_client.v3.isolation_segments import IsolationSegmentManager
3536
from cloudfoundry_client.v3.organization_quotas import OrganizationQuotaManager
37+
from cloudfoundry_client.v3.packages import PackageManager
3638
from cloudfoundry_client.v3.processes import ProcessManager
3739
from cloudfoundry_client.v3.organizations import OrganizationManager
3840
from cloudfoundry_client.v3.roles import RoleManager
@@ -118,11 +120,13 @@ def __init__(self, cloud_controller_v3_url: str, credential_manager: "CloudFound
118120
self.apps = AppManager(target_endpoint, credential_manager)
119121
self.buildpacks = BuildpackManager(target_endpoint, credential_manager)
120122
self.domains = DomainManager(target_endpoint, credential_manager)
123+
self.droplets = DropletManager(target_endpoint, credential_manager)
121124
self.feature_flags = FeatureFlagManager(target_endpoint, credential_manager)
122125
self.isolation_segments = IsolationSegmentManager(target_endpoint, credential_manager)
123126
self.jobs = JobManager(target_endpoint, credential_manager)
124127
self.organizations = OrganizationManager(target_endpoint, credential_manager)
125128
self.organization_quotas = OrganizationQuotaManager(target_endpoint, credential_manager)
129+
self.packages = PackageManager(target_endpoint, credential_manager)
126130
self.processes = ProcessManager(target_endpoint, credential_manager)
127131
self.roles = RoleManager(target_endpoint, credential_manager)
128132
self.routes = RouteManager(target_endpoint, credential_manager)

cloudfoundry_client/v3/apps.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,13 @@ def remove(self, application_guid: str, asynchronous: bool = True) -> str | None
2222
def get_env(self, application_guid: str) -> JsonObject:
2323
return super(AppManager, self)._get("%s%s/%s/env" % (self.target_endpoint, self.entity_uri, application_guid))
2424

25-
def get_routes(self, application_guid: str) -> JsonObject:
26-
return super(AppManager, self)._get("%s%s/%s/routes" % (self.target_endpoint, self.entity_uri, application_guid))
25+
def list_routes(self, application_guid: str, **kwargs) -> Pagination[Entity]:
26+
uri: str = "%s/%s/routes" % (self.entity_uri, application_guid)
27+
return super(AppManager, self)._list(requested_path=uri, **kwargs)
28+
29+
def list_droplets(self, application_guid: str, **kwargs) -> Pagination[Entity]:
30+
uri: str = "%s/%s/droplets" % (self.entity_uri, application_guid)
31+
return super(AppManager, self)._list(requested_path=uri, **kwargs)
2732

2833
def get_manifest(self, application_guid: str) -> str:
2934
return self.client.get(url="%s%s/%s/manifest" % (self.target_endpoint, self.entity_uri, application_guid)).text

cloudfoundry_client/v3/droplets.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
from typing import TYPE_CHECKING, Any
2+
3+
from cloudfoundry_client.v3.entities import EntityManager, Entity, ToOneRelationship
4+
5+
if TYPE_CHECKING:
6+
from cloudfoundry_client.client import CloudFoundryClient
7+
8+
9+
class DropletManager(EntityManager[Entity]):
10+
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
11+
super(DropletManager, self).__init__(target_endpoint, client, "/v3/droplets")
12+
13+
def create(self,
14+
app_guid: str,
15+
process_types: dict[str, str] | None = None,
16+
meta_labels: dict | None = None,
17+
meta_annotations: dict | None = None,
18+
) -> Entity:
19+
data: dict[str, Any] = {
20+
"relationships": {
21+
"app": ToOneRelationship(app_guid)
22+
},
23+
}
24+
if process_types is not None:
25+
data["process_types"] = process_types
26+
self._metadata(data, meta_labels, meta_annotations)
27+
return super(DropletManager, self)._create(data)
28+
29+
def copy(self,
30+
droplet_guid: str,
31+
app_guid: str,
32+
meta_labels: dict | None = None,
33+
meta_annotations: dict | None = None,
34+
) -> Entity:
35+
data: dict[str, Any] = {
36+
"relationships": {
37+
"app": ToOneRelationship(app_guid)
38+
},
39+
}
40+
self._metadata(data, meta_labels, meta_annotations)
41+
url = EntityManager._get_url_with_encoded_params(
42+
"%s%s" % (self.target_endpoint, self.entity_uri),
43+
source_guid=droplet_guid
44+
)
45+
return self._post(url, data=data)
46+
47+
def update(self,
48+
droplet_gid: str,
49+
meta_labels: dict | None = None,
50+
meta_annotations: dict | None = None,
51+
) -> Entity:
52+
data: dict[str, Any] = {}
53+
self._metadata(data, meta_labels, meta_annotations)
54+
return super(DropletManager, self)._update(droplet_gid, data)
55+
56+
def remove(self, route_gid: str):
57+
return super(DropletManager, self)._remove(route_gid)

cloudfoundry_client/v3/entities.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,16 @@ def _get(self, url: str, entity_type: type[ENTITY_TYPE] | None = None, **kwargs)
135135
def _post(
136136
self,
137137
url: str,
138-
data: dict | None = None,
139138
entity_type: type[ENTITY_TYPE] | None = None,
139+
data: dict | None = None,
140+
params: dict | None = None,
140141
files: Any = None
141142
) -> ENTITY_TYPE:
142-
response = self.client.post(url, json=data, files=files)
143+
response = self.client.post(
144+
url if params is None else EntityManager._get_url_with_encoded_params(url, **params),
145+
json=data,
146+
files=files
147+
)
143148
return self._read_response(response, entity_type)
144149

145150
def _put(self, url: str, data: dict, entity_type: type[ENTITY_TYPE] | None = None) -> ENTITY_TYPE:

cloudfoundry_client/v3/packages.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from typing import TYPE_CHECKING
2+
3+
from cloudfoundry_client.common_objects import Pagination
4+
from cloudfoundry_client.v3.entities import EntityManager, Entity
5+
6+
if TYPE_CHECKING:
7+
from cloudfoundry_client.client import CloudFoundryClient
8+
9+
10+
class PackageManager(EntityManager[Entity]):
11+
def __init__(self, target_endpoint: str, client: "CloudFoundryClient"):
12+
super(PackageManager, self).__init__(target_endpoint, client, "/v3/packages")
13+
14+
def list_droplets(self, package_guid: str, **kwargs) -> Pagination[Entity]:
15+
uri: str = "%s/%s/droplets" % (self.entity_uri, package_guid)
16+
return super(PackageManager, self)._list(requested_path=uri, **kwargs)
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
{
2+
"pagination": {
3+
"total_results": 2,
4+
"total_pages": 1,
5+
"first": {
6+
"href": "https://api.example.org/v3/app/7b34f1cf-7e73-428a-bb5a-8a17a8058396/droplets?page=1&per_page=50"
7+
},
8+
"last": {
9+
"href": "https://api.example.org/v3/app/7b34f1cf-7e73-428a-bb5a-8a17a8058396/droplets?page=1&per_page=50"
10+
},
11+
"next": null,
12+
"previous": null
13+
},
14+
"resources": [
15+
{
16+
"guid": "585bc3c1-3743-497d-88b0-403ad6b56d16",
17+
"state": "STAGED",
18+
"error": null,
19+
"lifecycle": {
20+
"type": "buildpack",
21+
"data": {}
22+
},
23+
"image": null,
24+
"execution_metadata": "PRIVATE DATA HIDDEN",
25+
"process_types": {
26+
"redacted_message": "[PRIVATE DATA HIDDEN IN LISTS]"
27+
},
28+
"checksum": {
29+
"type": "sha256",
30+
"value": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
31+
},
32+
"buildpacks": [
33+
{
34+
"name": "ruby_buildpack",
35+
"detect_output": "ruby 1.6.14",
36+
"version": "1.1.1.",
37+
"buildpack_name": "ruby"
38+
}
39+
],
40+
"stack": "cflinuxfs4",
41+
"created_at": "2016-03-28T23:39:34Z",
42+
"updated_at": "2016-03-28T23:39:47Z",
43+
"relationships": {
44+
"app": {
45+
"data": {
46+
"guid": "7b34f1cf-7e73-428a-bb5a-8a17a8058396"
47+
}
48+
}
49+
},
50+
"links": {
51+
"self": {
52+
"href": "https://api.example.org/v3/droplets/585bc3c1-3743-497d-88b0-403ad6b56d16"
53+
},
54+
"package": {
55+
"href": "https://api.example.org/v3/packages/8222f76a-9e09-4360-b3aa-1ed329945e92"
56+
},
57+
"app": {
58+
"href": "https://api.example.org/v3/apps/7b34f1cf-7e73-428a-bb5a-8a17a8058396"
59+
},
60+
"assign_current_droplet": {
61+
"href": "https://api.example.org/v3/apps/7b34f1cf-7e73-428a-bb5a-8a17a8058396/relationships/current_droplet",
62+
"method": "PATCH"
63+
},
64+
"download": {
65+
"href": "https://api.example.org/v3/droplets/585bc3c1-3743-497d-88b0-403ad6b56d16/download"
66+
}
67+
},
68+
"metadata": {
69+
"labels": {},
70+
"annotations": {}
71+
}
72+
},
73+
{
74+
"guid": "fdf3851c-def8-4de1-87f1-6d4543189e22",
75+
"state": "STAGED",
76+
"error": null,
77+
"lifecycle": {
78+
"type": "docker",
79+
"data": {}
80+
},
81+
"execution_metadata": "[PRIVATE DATA HIDDEN IN LISTS]",
82+
"process_types": {
83+
"redacted_message": "[PRIVATE DATA HIDDEN IN LISTS]"
84+
},
85+
"image": "cloudfoundry/diego-docker-app-custom:latest",
86+
"checksum": null,
87+
"buildpacks": null,
88+
"stack": null,
89+
"created_at": "2016-03-17T00:00:01Z",
90+
"updated_at": "2016-03-17T21:41:32Z",
91+
"relationships": {
92+
"app": {
93+
"data": {
94+
"guid": "7b34f1cf-7e73-428a-bb5a-8a17a8058396"
95+
}
96+
}
97+
},
98+
"links": {
99+
"self": {
100+
"href": "https://api.example.org/v3/droplets/fdf3851c-def8-4de1-87f1-6d4543189e22"
101+
},
102+
"package": {
103+
"href": "https://api.example.org/v3/packages/c5725684-a02f-4e59-bc67-8f36ae944688"
104+
},
105+
"app": {
106+
"href": "https://api.example.org/v3/apps/7b34f1cf-7e73-428a-bb5a-8a17a8058396"
107+
},
108+
"assign_current_droplet": {
109+
"href": "https://api.example.org/v3/apps/7b34f1cf-7e73-428a-bb5a-8a17a8058396/relationships/current_droplet",
110+
"method": "PATCH"
111+
}
112+
},
113+
"metadata": {
114+
"labels": {},
115+
"annotations": {}
116+
}
117+
}
118+
]
119+
}

0 commit comments

Comments
 (0)