Python Interface for Cloud Foundry APIs
Project description
# Python Cloud Foundry API Client
This module provides a pure Python interface to the Cloud Foundry APIs.
## Installation
You can install from PIP
`pip install cf-api`
or view it on [PyPI](https://pypi.python.org/pypi/cf_api).
## Documentation
See the docs at [https://cf-api.readthedocs.io/en/latest/](https://cf-api.readthedocs.io/en/latest/) or in the [./docs](docs) directory and the [./examples](examples) directory.
## Versioning
*Version 1.x*
- Supports both Python 2.7/3.6
- Removed `cf_api.dropsonde` module in favor of the `dropsonde` module.
*Version 0.x*
- Supports Python 2.7
## Getting Started
The following examples should be enough to get you started using this library.
```python
# Initializing the Cloud Controller client
from getpass import getpass
import cf_api
import json
cloud_controller = 'https://api.yourcloudfoundry.com'
deploy_client_id = 'cf'
deploy_client_secret = ''
verify_ssl = True
username = 'youser'
password = getpass('Password: ').strip()
cc = cf_api.new_cloud_controller(
cloud_controller,
client_id=deploy_client_id,
client_secret=deploy_client_secret,
username=username,
password=password,
).set_verify_ssl(verify_ssl)
# List all organizations
req = cc.organizations()
res = req.get()
orgs = res.resources
for r in orgs:
print('org', r.guid, r.name)
# List all spaces
res = cc.spaces().get()
spaces = res.resources
for r in spaces:
print('space', r.guid, r.name)
# List all applications
res = cc.apps().get()
apps = res.resources
for r in apps:
print('app', r.guid, r.name)
# Find an app by it's org/space/name
org_name = 'your_org'
space_name = 'your_space'
app_name = 'your_app'
# find your org by name
res = cc.organizations().get_by_name(org_name)
# you can access the first array resource using the `resource` attribute
your_org = res.resource
# find your space by name within your org
res = cc.request(your_org.spaces_url).get_by_name(space_name)
your_space = res.resource
# find your app by name within your space
res = cc.request(your_space.apps_url).get_by_name(app_name)
your_app = res.resource
print('your_app', your_app)
# Find an app by it's GUID
#
# Note that this same pattern applies to all Cloud Controller resources
#
res = cc.apps(your_app.guid).get()
# you can also use the `resource` attribute to access a response with a
# non-array result
your_same_app = res.resource
print('your_same_app', your_same_app)
# Find a stack by name
your_stack = 'some_stack'
res = cc.stacks().get_by_name(your_stack)
stack = res.resource
# Create an app
your_buildpack = 'some_buildpack'
command = 'python server.py'
res = cc.apps().set_params(
name=app_name,
space_guid=your_space.guid,
stack_guid=stack.guid,
buildpack=your_buildpack,
command=command,
health_check_type='port',
health_check_timeout=60,
instances=2,
memory=512,
disk_quota=512
).post()
print('new app', res.data)
# Upload the bits for an app
my_zipfile = '/tmp/app.zip'
with open(my_zipfile, 'r') as f:
res = cc.apps(your_app.guid, 'bits')\
.set_query(async='true')\
.add_field('resources', json.dumps([]))\
.add_file('application', 'application.zip', f, 'application/zip')\
.put()
print(res.data)
```
## Environment Variables
The library is also configurable via environment variables.
| Variable | Description |
| --- | --- |
| `PYTHON_CF_URL` | This is the cloud controller base URL. **Do not include a trailing slash on the URL.**
| `PYTHON_CF_CLIENT_ID` | This is the UAA client ID the library should use.
| `PYTHON_CF_CLIENT_SECRET` | This is the UAA client secret the library should use.
| `PYTHON_CF_IGNORE_SSL` | This indicates whether to verify SSL certs. Default is false. Set to `true` to ignore SSL verification.
| `CF_DOCKER_PASSWORD` | This variable optionally provides the Docker user's password if a docker image is being used. This variable is not necessarily required to use a docker image.
An example library usage with these variables set would look like this:
```python
# env vars might be set as follows
# PYTHON_CF_URL=https://api.cloudfoundry.com
# PYTHON_CF_CLIENT_ID=my_client_id
# PYTHON_CF_CLIENT_SECRET=my_client_secret
import cf_api
# no args are required when the above env vars are detected
cc = cf_api.new_cloud_controller()
res = cc.apps().get()
# ...
# the same principle applies to new_uaa()
uaa = cf_api.new_uaa()
# ...
```
## Log in with Cloud Foundry Authorization Code
The following functions may be used to implement login with Cloud Foundry via Authorization Codes.
The function `get_openid_connect_url()` shows how to build UAA URL to which the user can be
redirected in order to log in.
The function `verify_code()` can be used when the user successfully logs in and UAA redirects back
to redirect_uri with the `code` attached. Pass the code and original redirect_uri into this function
in order to get the OAuth2 Token and to also verify the signature of the JWT.
This particular example applies to OpenID Connect.
```python
import cf_api
cc = 'https://api.yourcloudfoundry.com'
client_id = 'yourclient'
client_secret = 'yoursecret'
response_type = 'code'
def get_openid_connect_url(redirect_uri):
return cf_api\
.new_uaa(cc=cc, client_id=client_id, client_secret=client_secret, no_auth=True)\
.authorization_code_url(response_type, scope='openid', redirect_uri=redirect_uri)
def verify_code(code, redirect_uri):
uaa = cf_api.new_uaa(cc=cc, client_id=client_id, client_secret=client_secret, no_auth=True)
res = uaa.authorization_code(code, response_type, redirect_uri)
data = res.data
uaa.verify_token(data['id_token'], audience=uaa.client_id)
return data
```
## Deploy an Application
The `cf_api.deploy_manifest` module may be used to deploy a Cloud Foundry app. The
following snippet demonstrates the usage for deploying an app.
```bash
cd path/to/your/project
python -m cf_api.deploy_manifest \
--cloud-controller https://api.yourcloudfoundry.com \
-u youser -o yourg -s yourspace \
-m manifest.yml -v -w
# For the CLI usage of deploy_manifest, you may also set
# the CF_REFRESH_TOKEN environment variable as a substitute
# for collecting username and password
```
This module may also be used programmatically.
```python
from __future__ import print_function
import cf_api
from getpass import getpass
from cf_api.deploy_manifest import Deploy
cc = cf_api.new_cloud_controller(
'https://api.yourcloudfoundry.com',
username='youruser',
password=getpass().strip(),
client_id='cf',
client_secret='',
verify_ssl=True
)
manifest_filename = 'path/to/manifest.yml'
apps = Deploy.parse_manifest(manifest_filename, cc)
for app in apps:
app.set_debug(True)
app.set_org_and_space('yourorg', 'yourspace')
print (app.push())
# print (app.destroy(destroy_routes=True))
```
## Deploy a Service
The `cf_api.deploy_service` module may be used to deploy a Cloud Foundry service to a space. The
following snippet demonstrates the usage for deploying a service.
```bash
cd path/to/your/project
python -m cf_api.deploy_service \
--cloud-controller https://api.yourcloudfoundry.com \
-u youser -o yourg -s yourspace \
--name your-custom-service-name --service-name cf-service-type \
--service-plan cf-service-type-plan -v -w
```
This module may also be used programmatically.
```python
from __future__ import print_function
import cf_api
from getpass import getpass
from cf_api.deploy_service import DeployService
cc = cf_api.new_cloud_controller(
'https://api.yourcloudfoundry.com',
username='youruser',
password=getpass().strip(),
client_id='cf',
client_secret='',
verify_ssl=True
)
service = DeployService(cc)\
.set_debug(True)\
.set_org_and_space('yourorg', 'yourspace')
result = service.create('my-custom-db', 'database-service', 'small-database-plan')
print(result)
```
## Query a Space
The `cf_api.deploy_space` module provides a convenience interface for working with Cloud Foundry
spaces. The module provides read-only (i.e. GET requests only) support for the Cloud Controller API
endpoints scoped to a specific space i.e. /v2/spaces/<space_guid>/(routes|service_instances|apps).
The following snippet demonstrates the usage for listing apps for in a space.
```bash
cd path/to/your/project
python -m cf_api.deploy_space \
--cloud-controller https://api.yourcloudfoundry.com \
-u youser -o yourg -s yourspace apps
```
This module may also be used programmatically.
```python
from __future__ import print_function
import cf_api
from getpass import getpass
from cf_api.deploy_space import Space
cc = cf_api.new_cloud_controller(
'https://api.yourcloudfoundry.com',
username='youruser',
password=getpass().strip(),
client_id='cf',
client_secret='',
verify_ssl=True
)
space = Space(cc, org_name='yourorg', space_name='yourspace')
# create the space
space.create()
# destroy the space
space.destroy()
# make a Cloud Controller request within the space
apps_in_the_space = space.request('apps').get()
# deploys an application to this space
space.deploy_manifest('/path/to/manifest.yml') # push the app
space.wait_manifest('/path/to/manifest.yml') # wait for the app to start
space.destroy_manifest('/path/to/manifest.yml') # destroy the app
app = space.get_app_by_name('yourappname') # find an application by its name within the space
# deploy a service in this space
space.get_deploy_service().create('my-custom-db', 'database-service', 'small-database-plan')
service = space.get_service_instance_by_name('my-custom-db') # find a service by its name within the space
```
## Tail Application Logs
The `cf_api.logs_util` module may be used to tail Cloud Foundry application logs. Both
`recentlogs` and `stream` modes are supported. The following snippet demonstrates the usage for
listing recent logs and tailing app logs simultaneously.
```bash
cd path/to/your/project
python -m cf_api.logs_util \
--cloud-controller https://api.yourcloudfoundry.com \
-u youser -o yourg -s yourspace -a yourapp \
-r -t
```
This module may also be used programmatically.
```python
from __future__ import print_function
import cf_api
from getpass import getpass
from cf_api import dropsonde_util
cc = cf_api.new_cloud_controller(
'https://api.yourcloudfoundry.com',
username='youruser',
password=getpass().strip(),
client_id='cf',
client_secret='',
verify_ssl=True,
init_doppler=True
)
app_guid = 'your-app-guid'
app = cc.apps(app_guid).get().resource
# get recent logs
logs = cc.doppler.apps(app.guid, 'recentlogs').get().multipart
# convert log envelopes from protobuf to dict
logs = [dropsonde_util.parse_envelope_protobuf(log) for log in logs]
print(logs)
# stream logs
ws = cc.doppler.ws_request('apps', app.guid, 'stream')
try:
ws.connect()
ws.watch(lambda m: print(dropsonde_util.parse_envelope_protobuf(m)))
except Exception as e:
print(e)
finally:
ws.close()
```
## TODO
### v1.x plans
- Move core logic out of `__init__.py` and into a `core.py` module so that we can import `cf_api` without triggering `ImportError` due to requirements not being installed yet.
- Make `deploy_manifest`, `deploy_service` use `deploy_space` to initialize
- Rename `deploy_manifest` to `manifest` and `deploy_manifest.Deploy` to `manifest.Manifest`
- Rename `deploy_service` to `service` and `deploy_service.DeployService` to `service.Service`
- Rename `deploy_space` to `space`
- Simplify `cf_api.new_uaa()` by removing functionality to initialize from Cloud Controller URL as well as UAA URL; consider always requiring a `cc` instance to initialize
- Remove dependency on `PyJWT` if possible, to remove the sub-dependency on `cryptography` which slows down the package install.
- Full support for Python 3
- Consider moving helper modules like `deploy_manifest`, `deploy_service`, and `deploy_blue_green` into a separate package.
This module provides a pure Python interface to the Cloud Foundry APIs.
## Installation
You can install from PIP
`pip install cf-api`
or view it on [PyPI](https://pypi.python.org/pypi/cf_api).
## Documentation
See the docs at [https://cf-api.readthedocs.io/en/latest/](https://cf-api.readthedocs.io/en/latest/) or in the [./docs](docs) directory and the [./examples](examples) directory.
## Versioning
*Version 1.x*
- Supports both Python 2.7/3.6
- Removed `cf_api.dropsonde` module in favor of the `dropsonde` module.
*Version 0.x*
- Supports Python 2.7
## Getting Started
The following examples should be enough to get you started using this library.
```python
# Initializing the Cloud Controller client
from getpass import getpass
import cf_api
import json
cloud_controller = 'https://api.yourcloudfoundry.com'
deploy_client_id = 'cf'
deploy_client_secret = ''
verify_ssl = True
username = 'youser'
password = getpass('Password: ').strip()
cc = cf_api.new_cloud_controller(
cloud_controller,
client_id=deploy_client_id,
client_secret=deploy_client_secret,
username=username,
password=password,
).set_verify_ssl(verify_ssl)
# List all organizations
req = cc.organizations()
res = req.get()
orgs = res.resources
for r in orgs:
print('org', r.guid, r.name)
# List all spaces
res = cc.spaces().get()
spaces = res.resources
for r in spaces:
print('space', r.guid, r.name)
# List all applications
res = cc.apps().get()
apps = res.resources
for r in apps:
print('app', r.guid, r.name)
# Find an app by it's org/space/name
org_name = 'your_org'
space_name = 'your_space'
app_name = 'your_app'
# find your org by name
res = cc.organizations().get_by_name(org_name)
# you can access the first array resource using the `resource` attribute
your_org = res.resource
# find your space by name within your org
res = cc.request(your_org.spaces_url).get_by_name(space_name)
your_space = res.resource
# find your app by name within your space
res = cc.request(your_space.apps_url).get_by_name(app_name)
your_app = res.resource
print('your_app', your_app)
# Find an app by it's GUID
#
# Note that this same pattern applies to all Cloud Controller resources
#
res = cc.apps(your_app.guid).get()
# you can also use the `resource` attribute to access a response with a
# non-array result
your_same_app = res.resource
print('your_same_app', your_same_app)
# Find a stack by name
your_stack = 'some_stack'
res = cc.stacks().get_by_name(your_stack)
stack = res.resource
# Create an app
your_buildpack = 'some_buildpack'
command = 'python server.py'
res = cc.apps().set_params(
name=app_name,
space_guid=your_space.guid,
stack_guid=stack.guid,
buildpack=your_buildpack,
command=command,
health_check_type='port',
health_check_timeout=60,
instances=2,
memory=512,
disk_quota=512
).post()
print('new app', res.data)
# Upload the bits for an app
my_zipfile = '/tmp/app.zip'
with open(my_zipfile, 'r') as f:
res = cc.apps(your_app.guid, 'bits')\
.set_query(async='true')\
.add_field('resources', json.dumps([]))\
.add_file('application', 'application.zip', f, 'application/zip')\
.put()
print(res.data)
```
## Environment Variables
The library is also configurable via environment variables.
| Variable | Description |
| --- | --- |
| `PYTHON_CF_URL` | This is the cloud controller base URL. **Do not include a trailing slash on the URL.**
| `PYTHON_CF_CLIENT_ID` | This is the UAA client ID the library should use.
| `PYTHON_CF_CLIENT_SECRET` | This is the UAA client secret the library should use.
| `PYTHON_CF_IGNORE_SSL` | This indicates whether to verify SSL certs. Default is false. Set to `true` to ignore SSL verification.
| `CF_DOCKER_PASSWORD` | This variable optionally provides the Docker user's password if a docker image is being used. This variable is not necessarily required to use a docker image.
An example library usage with these variables set would look like this:
```python
# env vars might be set as follows
# PYTHON_CF_URL=https://api.cloudfoundry.com
# PYTHON_CF_CLIENT_ID=my_client_id
# PYTHON_CF_CLIENT_SECRET=my_client_secret
import cf_api
# no args are required when the above env vars are detected
cc = cf_api.new_cloud_controller()
res = cc.apps().get()
# ...
# the same principle applies to new_uaa()
uaa = cf_api.new_uaa()
# ...
```
## Log in with Cloud Foundry Authorization Code
The following functions may be used to implement login with Cloud Foundry via Authorization Codes.
The function `get_openid_connect_url()` shows how to build UAA URL to which the user can be
redirected in order to log in.
The function `verify_code()` can be used when the user successfully logs in and UAA redirects back
to redirect_uri with the `code` attached. Pass the code and original redirect_uri into this function
in order to get the OAuth2 Token and to also verify the signature of the JWT.
This particular example applies to OpenID Connect.
```python
import cf_api
cc = 'https://api.yourcloudfoundry.com'
client_id = 'yourclient'
client_secret = 'yoursecret'
response_type = 'code'
def get_openid_connect_url(redirect_uri):
return cf_api\
.new_uaa(cc=cc, client_id=client_id, client_secret=client_secret, no_auth=True)\
.authorization_code_url(response_type, scope='openid', redirect_uri=redirect_uri)
def verify_code(code, redirect_uri):
uaa = cf_api.new_uaa(cc=cc, client_id=client_id, client_secret=client_secret, no_auth=True)
res = uaa.authorization_code(code, response_type, redirect_uri)
data = res.data
uaa.verify_token(data['id_token'], audience=uaa.client_id)
return data
```
## Deploy an Application
The `cf_api.deploy_manifest` module may be used to deploy a Cloud Foundry app. The
following snippet demonstrates the usage for deploying an app.
```bash
cd path/to/your/project
python -m cf_api.deploy_manifest \
--cloud-controller https://api.yourcloudfoundry.com \
-u youser -o yourg -s yourspace \
-m manifest.yml -v -w
# For the CLI usage of deploy_manifest, you may also set
# the CF_REFRESH_TOKEN environment variable as a substitute
# for collecting username and password
```
This module may also be used programmatically.
```python
from __future__ import print_function
import cf_api
from getpass import getpass
from cf_api.deploy_manifest import Deploy
cc = cf_api.new_cloud_controller(
'https://api.yourcloudfoundry.com',
username='youruser',
password=getpass().strip(),
client_id='cf',
client_secret='',
verify_ssl=True
)
manifest_filename = 'path/to/manifest.yml'
apps = Deploy.parse_manifest(manifest_filename, cc)
for app in apps:
app.set_debug(True)
app.set_org_and_space('yourorg', 'yourspace')
print (app.push())
# print (app.destroy(destroy_routes=True))
```
## Deploy a Service
The `cf_api.deploy_service` module may be used to deploy a Cloud Foundry service to a space. The
following snippet demonstrates the usage for deploying a service.
```bash
cd path/to/your/project
python -m cf_api.deploy_service \
--cloud-controller https://api.yourcloudfoundry.com \
-u youser -o yourg -s yourspace \
--name your-custom-service-name --service-name cf-service-type \
--service-plan cf-service-type-plan -v -w
```
This module may also be used programmatically.
```python
from __future__ import print_function
import cf_api
from getpass import getpass
from cf_api.deploy_service import DeployService
cc = cf_api.new_cloud_controller(
'https://api.yourcloudfoundry.com',
username='youruser',
password=getpass().strip(),
client_id='cf',
client_secret='',
verify_ssl=True
)
service = DeployService(cc)\
.set_debug(True)\
.set_org_and_space('yourorg', 'yourspace')
result = service.create('my-custom-db', 'database-service', 'small-database-plan')
print(result)
```
## Query a Space
The `cf_api.deploy_space` module provides a convenience interface for working with Cloud Foundry
spaces. The module provides read-only (i.e. GET requests only) support for the Cloud Controller API
endpoints scoped to a specific space i.e. /v2/spaces/<space_guid>/(routes|service_instances|apps).
The following snippet demonstrates the usage for listing apps for in a space.
```bash
cd path/to/your/project
python -m cf_api.deploy_space \
--cloud-controller https://api.yourcloudfoundry.com \
-u youser -o yourg -s yourspace apps
```
This module may also be used programmatically.
```python
from __future__ import print_function
import cf_api
from getpass import getpass
from cf_api.deploy_space import Space
cc = cf_api.new_cloud_controller(
'https://api.yourcloudfoundry.com',
username='youruser',
password=getpass().strip(),
client_id='cf',
client_secret='',
verify_ssl=True
)
space = Space(cc, org_name='yourorg', space_name='yourspace')
# create the space
space.create()
# destroy the space
space.destroy()
# make a Cloud Controller request within the space
apps_in_the_space = space.request('apps').get()
# deploys an application to this space
space.deploy_manifest('/path/to/manifest.yml') # push the app
space.wait_manifest('/path/to/manifest.yml') # wait for the app to start
space.destroy_manifest('/path/to/manifest.yml') # destroy the app
app = space.get_app_by_name('yourappname') # find an application by its name within the space
# deploy a service in this space
space.get_deploy_service().create('my-custom-db', 'database-service', 'small-database-plan')
service = space.get_service_instance_by_name('my-custom-db') # find a service by its name within the space
```
## Tail Application Logs
The `cf_api.logs_util` module may be used to tail Cloud Foundry application logs. Both
`recentlogs` and `stream` modes are supported. The following snippet demonstrates the usage for
listing recent logs and tailing app logs simultaneously.
```bash
cd path/to/your/project
python -m cf_api.logs_util \
--cloud-controller https://api.yourcloudfoundry.com \
-u youser -o yourg -s yourspace -a yourapp \
-r -t
```
This module may also be used programmatically.
```python
from __future__ import print_function
import cf_api
from getpass import getpass
from cf_api import dropsonde_util
cc = cf_api.new_cloud_controller(
'https://api.yourcloudfoundry.com',
username='youruser',
password=getpass().strip(),
client_id='cf',
client_secret='',
verify_ssl=True,
init_doppler=True
)
app_guid = 'your-app-guid'
app = cc.apps(app_guid).get().resource
# get recent logs
logs = cc.doppler.apps(app.guid, 'recentlogs').get().multipart
# convert log envelopes from protobuf to dict
logs = [dropsonde_util.parse_envelope_protobuf(log) for log in logs]
print(logs)
# stream logs
ws = cc.doppler.ws_request('apps', app.guid, 'stream')
try:
ws.connect()
ws.watch(lambda m: print(dropsonde_util.parse_envelope_protobuf(m)))
except Exception as e:
print(e)
finally:
ws.close()
```
## TODO
### v1.x plans
- Move core logic out of `__init__.py` and into a `core.py` module so that we can import `cf_api` without triggering `ImportError` due to requirements not being installed yet.
- Make `deploy_manifest`, `deploy_service` use `deploy_space` to initialize
- Rename `deploy_manifest` to `manifest` and `deploy_manifest.Deploy` to `manifest.Manifest`
- Rename `deploy_service` to `service` and `deploy_service.DeployService` to `service.Service`
- Rename `deploy_space` to `space`
- Simplify `cf_api.new_uaa()` by removing functionality to initialize from Cloud Controller URL as well as UAA URL; consider always requiring a `cc` instance to initialize
- Remove dependency on `PyJWT` if possible, to remove the sub-dependency on `cryptography` which slows down the package install.
- Full support for Python 3
- Consider moving helper modules like `deploy_manifest`, `deploy_service`, and `deploy_blue_green` into a separate package.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
cf_api-1.0.0a5.tar.gz
(50.7 kB
view hashes)