Metadata-Version: 1.0
Name: cf_api
Version: 1.0.0a4
Summary: Python Interface for Cloud Foundry APIs
Home-page: https://github.com/hsdp/python-cf-api
Author: Adam Jaso
Author-email: ajaso@hsdp.io
License: Apache License Version 2.0
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.
        
Platform: UNKNOWN
