cloudfoundry-community / cf-python-client

Small cloudfoundry client implemented in python
Apache License 2.0
52 stars 50 forks source link

Possibility to retrive includes? #218

Open krismarc opened 1 month ago

krismarc commented 1 month ago

Hey, not sure if it's missing or I don't know how to exactly use it. However, I can't retrieve 'included' from any out of the box options eg. list, get, get_first. However, if I get retrieved payload from underlying methods then it's there. So I assume, parameter is passed while calling API, however, method returning payload only process 'resources' and 'included' is omitted.

Using CF CLI:

cf curl /v3/apps/9a81aaf5-7dac-4adc-a764-263b98935707?include=org | jq -r .included.organizations[].guid
42b716bb-42c5-4bcf-9c1c-f4be4d11685b

Using Python client:

app = client.v3.apps.get("9a81aaf5-7dac-4adc-a764-263b98935707", include="org")
print(json.dumps(app["included"], indent=4))
    print(json.dumps(app["included"], indent=4))
KeyError: 'included'

By changing the first line only, a single request fetches all the data. The navigation from app to space and space to organization remains unchanged. app = client.v3.apps.get("app-guid", include="space.organization")

The managers provide the same methods as the V2 managers with the following differences: get(**kwargs): supports keyword arguments that are passed on to the API, e.g. "include"

krismarc commented 1 month ago

Ok, I see. https://github.com/cloudfoundry-community/cf-python-client/pull/130/files

I need to call app.space() and then space.organization() This is supported even if no includes specified as params, however then it contunie calling the api to gather info about spaces and orgs while with includes the info is already known.

In this case, why it's not simply a default? :) If you miss to add includes, the same code works while it's performance is drastically worse.

apps = CF.client.v3.apps.list(include="org,space")
i=1
for app in apps:
  space = app.space()
  org = space.organization()
  i = i + 1
  if i > 500:
    break

real    0m4.311s
user    0m0.383s
sys     0m0.073s
apps = CF.client.v3.apps.list()
i=1
for app in apps:
  space = app.space()
  org = space.organization()
  i = i + 1
  if i > 500:
    break

real    0m46.486s
user    0m0.970s
sys     0m0.074s
krismarc commented 1 month ago

In combination with per_page which actually supports up to 5000 records. The difference would be something between 200 times faster. 2s to 4000s

..and if I am not mistaken, underlying processing with includes set, would require only 1 call to be done against CF api in order to collect all necessary info about 5000 apps, while with no includes it would be 10001 calls, 1 for all apps payload, and 5k calls per space and org.