Examples

The following examples demonstrate the use cases of this library.

Initializing the Cloud Controller client

Create a new cloud controller client

import cf_api

cc = cf_api.new_cloud_controller(
    'https://api.yourcloudfoundry.com',
    client_id='cf',
    client_secret='',
    username='myuser',
    password='uaapassword',
)

print(cc)

This code authenticates the user with UAA using the given client and user credentials and, if authentication is successful, returns a Cloud Controller request builder.

Making API requests with the Cloud Controller client

To make a request to the Cloud Controller API

import cf_api

cc = cf_api.new_cloud_controller(...)

request = cc.request('apps')
response = request.get()

print(response.data)

This code uses a cloud controller client object to create a new request for the Cloud Controller API endpoint /v2/apps, execute that request as an HTTP GET request and print out a dictionary representation of the response.

Note

Observe that the cc.request() method returns a CloudControllerRequest object and does NOT execute the request. This allows the user to choose which HTTP method they want to execute.

The Request Object

Since the cc variable is an instance of the CloudController class, it is a “RequestFactory” instance, which provides a method, request(), that produces a “Request” object that is preset with the HTTP headers and base url from the “RequestFactory” that produced it. This “Request” object has several methods named for the HTTP verbs such as get() for GET, post() for POST, delete() for DELETE. You can set any query parameters, body parameters, or headers on this “Request” object and the parent “RequestFactory” will not be modified.

The CloudController class provides many methods that are convenience methods named after their respective Cloud Controller API endpoints, such as organizations(), spaces(), and apps() which simply invoke request() with single arguments of organizations, spaces, and apps. This request() method accepts a list of strings which are joined to make a URL which is joined to the base URL of the “RequestFactory”, like so:

req = cc.request('organizations', org_guid, 'spaces')

The above example produces a “Request” object with a URL set to cloud_controller_url/v2/organizations/<org_guid>/spaces.

An equivalent way to represent the above URL is as follows

req = cc.organizations(org_guid, 'spaces')

Executing the request object produces a CloudControllerResponse object. To execute the request as an HTTP GET request, do

res = req.get()

Searching with the API endpoints

The v2 Cloud Controller API supports the same query syntax for every endpoint it provides. This query syntax is q=<search-key>:<some-resource-name>. The CloudControllerRequest class provides a function, search(), that accepts a list of string arguments in the form

org_name = 'myorg'
space_guid = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
res = req.search('name', org_name, 'space_guid', space_guid)

This syntax sets the internal query parameters as follows q=name:<org_name>&q=space_guid:<space_guid>.

Further query parameters may also be set using the keyword arguments, like so

org_name = 'myorg'
res = req.search('name', org_name, **{'results-per-page': 10})

As searches by q=name:<some-name> are quite common, a further convenience function is provided in the get_by_name() method, which is used like so

org_name = 'myorg'
res = req.get_by_name(org_name)

Debugging a request

The request object also exposes a method, get_requests_args(), which, when invoked, returns the exact parameters that will be passed to the python-requests module to execute the Cloud Controller API request. The result is a tuple containing:

  1. the python-requests function that will be used (chosen based on the HTTP method set in the request object, i.e. requests.get, etc)
  2. the relative URL that will be invoked
  3. the keyword arguments that will be passed into the python-requests function.

Note

The HTTP method MUST be set in order for this function to work correctly. You may get an exception if the method is not set! Often times the method is not set until the request is invoked with one of the functions that maps to the HTTP verbs (i.e. .get() or .post()) and so, in order to view the request exactly as it would be executed, you must set the request method prior to invoking this function, using the set_method() function.

print(req.set_query(...)\
         .set_header(...)\
         .set_params(...)\
         .set_method('POST')\
         .get_requests_args())

The Response Object

The response object from an executed API request object is an instance of CloudControllerResponse class. This class has a few members worth noting.

To access the response data as a simple dict(), use the data attribute, like so

res = req.get()
print(res.data)

This data attribute internally checks if the request was successful (HTTP 200 range) and returns a simple dict if successful, or throws an Exception if there was an error.

You can check if an error occurred using has_error. You can get the error code and message using error_code and error_message.

The v2 Cloud Controller API returns all its data types in the same Resource format, whether a list of results or a single result object.

If you’re searching for a single org by name using, for example, the organizations endpoint, you can reference the first result (assuming there is only one result) like so

org_name = 'myorg'
req = cc.organizations().search('name', org_name)
res = req.get()
my_org = res.resource

This works when requesting an organization by ID as well, like so

org_guid = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
req = cc.organizations(org_guid)
res = req.get()
my_org = res.resource

If your request returns a list of resources, then you can iterate over them using the resources attribute, like so

res = cc.organizations().get()
for org in res.resources:
    print(org)

If you want to access the raw response, use the raw_data attribute to get a simple dict. Accessing this attribute does not throw an error.

If you want to access the underlying python-requests Response object, you can use the response attribute.

Getting all pages of a given resource list

To retrieve a paginated list of items, for example, a list of organizations.

import cf_api

cc = cf_api.new_cloud_controller(...)
req = cc.organizations()
orgs = cc.get_all_resources(req)

Note

Note that you MUST NOT execute HTTP GET method on the request. You must pass the prepared request object into the get_all_resources() method. This get_all_resources() method will internally execute an HTTP GET and store the results while next_url attribute is set on the response. Once there is no next_url the get_all_resources() method will return the aggregated list of resources.

Further examples

The following examples implement some common use cases for this library.

You can find the code for these examples in the examples directory.

Logging in

The following examples demonstrate usage of the four grant types for authentication with UAA.

Grant type: password

"""Log in with your UAA user credentials (using grant_type "password")

This example mimics the CF login action and uses the same "cf" client that
the CF CLI uses.
"""
from __future__ import print_function
import sys
import json
import cf_api
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')

print('----------')
access_token = cc.uaa.get_access_token()
refresh_token = cc.uaa.get_refresh_token()
print('access_token: ' + access_token.to_string() + '\n')
print('refresh_token: ' + refresh_token.to_string() + '\n')
print('user_id: ' + access_token.user_id + '\n')
print('user_name: ' + access_token.user_name + '\n')
print('access_token_data:')
json.dump(access_token.attrs, sys.stdout, indent=2)
print()

Grant type: authorization code

"""Log with UAA web login page (using grant_type "authorization_code")

The use case for this grant type is for websites that want to
"Log in with UAA".

This example is more of snippets, since it requires redirecting to UAA and
then receiving the authorization code on your web server...
"""
from __future__ import print_function
import os
import sys
import json
import cf_api
from webbrowser import open_new
from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler


PORT = int(os.getenv('PORT', 8080))


def browser_authorize(auth_uri):
    """Opens the UAA login page in the default web browser to allow the user
    to login, then waits for UAA to redirect back to http://localhost:8080,
    and then, then captures the authorization code and verifies it with UAA,
    and finally displays the login info.
    """

    # open the UAA login page in the web browser
    open_new(auth_uri)

    class CodeHandler(BaseHTTPRequestHandler):
        def do_GET(self):
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.end_headers()
            self.wfile.write("""
                <html><head>
                <script>window.onload = function() {window.close();}</script>
                </head><body>
                Hi... and bye! (you may close this window)</body>
                </html>
            """)
            parts = self.path.split('=')
            if len(parts) < 2:
                raise Exception('invalid response {0}'.format(self.path))
            auth_code = parts[1]
            self.server.result = auth_code

    # create a server to handle the redirected authorization code from UAA
    server = HTTPServer(('', PORT), CodeHandler)

    # this method waits for a single HTTP request and then shuts down the
    # server
    server.handle_request()

    return server.result


print('----------')
cloud_controller_url = raw_input('cloud controller url: ').strip()
client_id = 'test-client-id'
client_secret = 'test-client-secret'

print('----------')
print('Redirecting to UAA...')
# we create an instance of the cloud controller, but tell it to NOT authorize
# with UAA.
cc_noauth = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id=client_id,
    client_secret=client_secret,
    no_auth=True
)

# we use noauth client to create the redirect URI
uaa_uri = cc_noauth.uaa.authorization_code_url('code')

# get the authorization code by logging in at the web browser, receiving
# the redirect, and extracting the authorization code
code = browser_authorize(uaa_uri)
print('authorization code: ' + str(code))

print('----------')
print('Verifying authorization code...')
# we create a UAA authenticated client using the authorization code by passing
# in the "authorization_code" keyword argument
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id=client_id,
    client_secret=client_secret,
    authorization_code=dict(
        code=code,
        response_type='code',
    )
)
print('Login OK!')

print('----------')
access_token = cc.uaa.get_access_token()
refresh_token = cc.uaa.get_refresh_token()
print('access_token: ' + access_token.to_string() + '\n')
print('refresh_token: ' + refresh_token.to_string() + '\n')
print('user_id: ' + access_token.user_id + '\n')
print('user_name: ' + access_token.user_name + '\n')
print('access_token_data:')
json.dump(access_token.attrs, sys.stdout, indent=2)
print()

Grant type: client credentials

"""Log in with UAA client credentials (using grant_type "client_credentials")
"""
from __future__ import print_function
import sys
import json
import cf_api
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
client_id = raw_input('client id: ').strip()
client_secret = getpass('client secret: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id=client_id,
    client_secret=client_secret,
)
print('Login OK!')

print('----------')
access_token = cc.uaa.get_access_token()
print('access_token: ' + str(access_token) + '\n')
print('access_token_data:')
json.dump(access_token.attrs, sys.stdout, indent=2)
print()

Grant type: refresh token

"""Log in with UAA refresh token (using grant_type "refresh_token")

The if the user has CF CLI installed this script checks for
``~/.cf/config.json`` and reads the refresh token from there, otherwise,
the user is asked to enter client credentials and the refresh token
"""
from __future__ import print_function
import os
import sys
import json
import cf_api
from getpass import getpass


cloud_controller_url = raw_input('cloud controller url: ').strip()
config_file = os.path.expanduser('~/.cf/config.json')
print('----------')
if os.path.isfile(config_file):
    print('Loading refresh token from ~/.cf/config.json ...')
    with open(config_file) as f:
        config = json.load(f)
        refresh_token = config['RefreshToken']
        client_id = 'cf'
        client_secret = ''
else:
    client_id = raw_input('client id: ').strip()
    client_secret = getpass('client secret: ').strip()
    refresh_token = raw_input('refresh token: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id=client_id,
    client_secret=client_secret,
    refresh_token=refresh_token,
)

print('----------')
access_token = cc.uaa.get_access_token()
refresh_token = cc.uaa.get_refresh_token()
print('access_token: ' + access_token.to_string() + '\n')
print('refresh_token: ' + refresh_token.to_string() + '\n')
print('user_id: ' + access_token.user_id + '\n')
print('user_name: ' + access_token.user_name + '\n')
print('access_token_data:')
json.dump(access_token.attrs, sys.stdout, indent=2)
print()

Listing Organizations

Think cf orgs.

"""Searches for an organization by name on the Cloud Controller API
"""
from __future__ import print_function
import sys
import json
import cf_api
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')
print('----------')

print('Searching for organizations...')
req = cc.request('organizations')
resources_list = cc.get_all_resources(req)

print('----------')
json.dump(resources_list, sys.stdout, indent=2)
print()

Listing Spaces

Think cf spaces.

"""Searches for spaces in an organization by name on the Cloud Controller API
"""
from __future__ import print_function
import sys
import json
import cf_api
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')

print('----------')
organization_name = raw_input('organization name: ').strip()
# see http://apidocs.cloudfoundry.org/280/organizations/list_all_organizations.html
# for an explanation of the query parameters
print('Searching for organization "{0}"...'.format(organization_name))
req = cc.request('organizations').set_query(q='name:' + organization_name)
res = req.get()
print(str(res.response.status_code) + ' ' + res.response.reason)
if res.has_error:
    print(str(res.error_code) + ': ' + str(res.error_message))
    sys.exit(1)

print('----------')
print('Searching for spaces in "{0}"...'.format(organization_name))
first_org = res.resource
org_spaces_url = first_org.spaces_url
req = cc.request(org_spaces_url)
resources_list = cc.get_all_resources(req)

print('----------')
json.dump(resources_list, sys.stdout, indent=2)
print()

Listing Applications

Think cf apps.

This example shows how to list applications in a space using the standard functions in cf_api

"""Searches for apps in a space in an organization on the Cloud Controller API
"""
from __future__ import print_function
import sys
import json
import cf_api
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')
print('----------')

organization_name = raw_input('organization name: ').strip()
# see http://apidocs.cloudfoundry.org/280/organizations/list_all_organizations.html
# for an explanation of the query parameters
print('Searching for organization "{0}"...'.format(organization_name))
req = cc.request('organizations').set_query(q='name:' + organization_name)
res = req.get()

print(str(res.response.status_code) + ' ' + res.response.reason)
print('----------')

if res.has_error:
    print(str(res.error_code) + ': ' + str(res.error_message))
    sys.exit(1)

space_name = raw_input('space name: ').strip()
# see http://apidocs.cloudfoundry.org/280/spaces/list_all_spaces.html
# for an explanation of the query parameters
print('Searching for space "{0}"...'.format(space_name))
spaces_url = res.resource.spaces_url
req = cc.request(spaces_url).set_query(q='name:' + space_name)
res = req.get()

print(str(res.response.status_code) + ' ' + res.response.reason)
print('----------')

if res.has_error:
    print(str(res.error_code) + ': ' + str(res.error_message))
    sys.exit(1)

print('Searching for apps in "{0} / {1}"...'.format(
      organization_name, space_name))
first_space = res.resource
space_apps_url = first_space.apps_url
req = cc.request(space_apps_url)
res = cc.get_all_resources(req)

print('----------')
json.dump(res, sys.stdout, indent=2)
print()

This example shows how to list applications in a space using the Space helper class.

"""Searches for apps in a space in an organization on the Cloud Controller API
"""
from __future__ import print_function
import sys
import json
import cf_api
from cf_api.deploy_space import Space
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')

print('----------')
org_name = raw_input('organization name: ').strip()
space_name = raw_input('space name: ').strip()
print('Looking up "{0} / {1}"...'.format(org_name, space_name))
space = Space(cc, org_name=org_name, space_name=space_name)
print('Found space!')

print('----------')
print('Searching for apps in "{0} / {1}"...'.format(org_name, space_name))
apps = space.request('apps').get().data
print('Found apps!')

print('----------')
json.dump(apps, sys.stdout, indent=2)
print()

Deploying Applications in a space with a manifest (cf push)

This example shows how to deploy an application using the standard functions in cf_api

"""Deploys a Cloud Foundry application using a manifest
"""
from __future__ import print_function
import os
import sys
import json
import cf_api
from cf_api.deploy_manifest import Deploy
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')
print('----------')

organization_name = raw_input('organization name: ').strip()
# see http://apidocs.cloudfoundry.org/280/organizations/list_all_organizations.html
# for an explanation of the query parameters
print('Searching for organization "{0}"...'.format(organization_name))
req = cc.request('organizations').set_query(q='name:' + organization_name)
res = req.get()
print(str(res.response.status_code) + ' ' + res.response.reason)
print('----------')
if res.has_error:
    print(str(res.error_code) + ': ' + str(res.error_message))
    sys.exit(1)

space_name = raw_input('space name: ').strip()
# see http://apidocs.cloudfoundry.org/280/spaces/list_all_spaces.html
# for an explanation of the query parameters
print('Searching for space...')
spaces_url = res.resource.spaces_url
req = cc.request(spaces_url).set_query(q='name:' + space_name)
res = req.get()
print(str(res.response.status_code) + ' ' + res.response.reason)
print('----------')
if res.has_error:
    print(str(res.error_code) + ': ' + str(res.error_message))
    sys.exit(1)

manifest_path = raw_input('manifest path: ').strip()
manifest_path = os.path.abspath(manifest_path)

app_entries = Deploy.parse_manifest(manifest_path, cc)
for app_entry in app_entries:
    app_entry.set_org_and_space(organization_name, space_name)
    app_entry.set_debug(True)
    app_entry.push()
    app_entry.wait_for_app_start(tailing=True)

print('Deployed {0} apps successfully!'.format(len(app_entries)))

This example shows how to deploy an applcation using the Space helper class.

"""Deploys a Cloud Foundry application using a manifest
"""
from __future__ import print_function
import os
import sys
import json
import cf_api
from cf_api.deploy_manifest import Deploy
from cf_api.deploy_space import Space
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')

print('----------')
org_name = raw_input('organization name: ').strip()
space_name = raw_input('space name: ').strip()
print('Looking up "{0} / {1}"...'.format(org_name, space_name))
space = Space(cc, org_name=org_name, space_name=space_name, is_debug=True)
print('Found space!')

print('----------')
manifest_path = raw_input('manifest path: ').strip()
manifest_path = os.path.abspath(manifest_path)

app_entries = space.get_deploy_manifest(manifest_path)
for app_entry in app_entries:
    app_entry.push()
    app_entry.wait_for_app_start(tailing=True)

print('Deployed {0} apps successfully!'.format(len(app_entries)))

Deploying Applications in a space with a manifest with no downtime

This example uses the BlueGreen helper class.

"""Runs a Blue Green deploy of a Cloud Foundry application using a manifest
"""
from __future__ import print_function
import os
import sys
import json
import cf_api
from cf_api.deploy_manifest import Deploy
from cf_api.deploy_space import Space
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')

print('----------')
org_name = raw_input('organization name: ').strip()
space_name = raw_input('space name: ').strip()
print('Looking up "{0} / {1}"...'.format(org_name, space_name))
space = Space(cc, org_name=org_name, space_name=space_name, is_debug=True)
print('Found space!')

print('----------')
manifest_path = raw_input('manifest path: ').strip()
manifest_path = os.path.abspath(manifest_path)

space.deploy_blue_green(manifest_path)
print('Deployed {0} successfully!'.format(app_name))

Creating a service in a space

"""Searches for service instances in a space in an organization on the
Cloud Controller API
"""
from __future__ import print_function
import sys
import json
import cf_api
from cf_api.deploy_space import Space
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')
print('----------')

org_name = raw_input('organization name: ').strip()
space_name = raw_input('space name: ').strip()

space = Space(cc, org_name=org_name, space_name=space_name)

service_name = raw_input('service type: ').strip()
service_plan = raw_input('service plan: ').strip()
service_instance_name = raw_input('service name: ').strip()
service = space.get_deploy_service()
res = service.create(service_instance_name, service_name, service_plan)
print('----------')
json.dump(res, sys.stdout, indent=2)
print()

Tailing application logs

This example shows how to tail an application’s logs using the standard functions in cf_api

"""Tails application logs like ``cf logs``

This example shows how to use the core :module:`~cf_api` module to tail
the logs of an application.
"""
from __future__ import print_function
import sys
from getpass import getpass
import cf_api
from cf_api.dropsonde_util import DopplerEnvelope


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')

print('----------')
org_name = raw_input('organization name: ').strip()
res = cc.organizations().get_by_name(org_name)
print(str(res.response.status_code) + ' ' + res.response.reason)
if res.has_error:
    print(str(res.error_code) + ': ' + str(res.error_message))
    sys.exit(1)

print('----------')
space_name = raw_input('space name: ').strip()
res = cc.request(res.resource.spaces_url).get_by_name(space_name)
print(str(res.response.status_code) + ' ' + res.response.reason)
if res.has_error:
    print(str(res.error_code) + ': ' + str(res.error_message))
    sys.exit(1)

print('----------')
app_name = raw_input('app name: ').strip()
res = cc.request(res.resource.apps_url).get_by_name(app_name)
print(str(res.response.status_code) + ' ' + res.response.reason)
if res.has_error:
    print(str(res.error_code) + ': ' + str(res.error_message))
    sys.exit(1)

print('----------')
websocket = cc.doppler.ws_request('apps', res.resource.guid, 'stream')
websocket.connect()
print('Connected and tailing logs for "{0}" in "{1} / {2}"!'.format(
    org_name, space_name, app_name))

print('----------')

def render_log(msg):
    d = DopplerEnvelope.wrap(msg)
    sys.stdout.write(''.join([str(d), '\n']))
    sys.stdout.flush()

websocket.watch(render_log)

This example shows how to deploy an applcation using the Space helper class.

"""Tails application logs like ``cf logs``
"""
from __future__ import print_function
import sys
import cf_api
from getpass import getpass
from cf_api.dropsonde_util import DopplerEnvelope
from cf_api.deploy_space import Space


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')

print('----------')
org_name = raw_input('organization name: ').strip()
space_name = raw_input('space name: ').strip()
print('Looking up org space "{0} / {1}"...'.format(org_name, space_name))
space = Space(cc, org_name=org_name, space_name=space_name, is_debug=True)
print('Found space!')

print('----------')
app_name = raw_input('app name: ').strip()
print('Looking up app "{0}" in "{1} / {2}"...'
      .format(app_name, org_name, space_name))
app = space.get_app_by_name(app_name)
print('Found app!')

print('----------')
print('Connecting to app log stream "{0}"...'.format(app_name))
websocket = cc.doppler.ws_request('apps', app.guid, 'stream')
websocket.connect()
print('Connected and tailing logs for "{0}" in "{1} / {2}"!'.format(
        org_name, space_name, app_name))

print('----------')

def render_log(msg):
    d = DopplerEnvelope.wrap(msg)
    sys.stdout.write(''.join([str(d), '\n']))
    sys.stdout.flush()

websocket.watch(render_log)

Looking up an application by its FQDN

If you have a CF app’s domain name and you’re not sure where it lives you can find it using this example.

"""Look up an application resource by it's route.
(i.e. host.domain(:port)?(/path)? )
"""
from __future__ import print_function
import sys
import cf_api
import json
from cf_api import routes_util
from getpass import getpass


print('----------')
# cloud_controller_url = 'https://api.changeme.com'
cloud_controller_url = raw_input('cloud controller url: ').strip()
username = raw_input('username: ').strip()
password = getpass('password: ').strip()

print('----------')
print('Authenticating with UAA...')
cc = cf_api.new_cloud_controller(
    cloud_controller_url,
    client_id='cf',  # the ``cf`` command uses this client and the secret below
    client_secret='',
    username=username,
    password=password,
)
print('Login OK!')

print('----------')
route_url = raw_input('route url: ').strip() # myapp.changme.com:4443/v2

print('----------')
apps = routes_util.get_route_apps_from_url(cc, route_url)

print('----------')
json.dump(apps, sys.stdout, indent=2)
print()