Skip to content

Commit 4ad4148

Browse files
committed
First version of the client
This patch implements the first version of the cloudfoundry client implementing several GET api calls which are needed for the initial congress integration. Change-Id: I461db52d25785f7c17f681993371c3731f54cf52
1 parent 68cc648 commit 4ad4148

5 files changed

Lines changed: 182 additions & 0 deletions

File tree

‎cloudfoundryclient/common/__init__.py‎

Whitespace-only changes.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Copyright (c) 2015 OpenStack Foundation.
2+
# All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
16+
17+
class LoginError(Exception):
18+
pass
19+
20+
21+
class NotLoggedIn(Exception):
22+
pass

‎cloudfoundryclient/v2/__init__.py‎

Whitespace-only changes.

‎cloudfoundryclient/v2/client.py‎

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
# Copyright (c) 2015 OpenStack Foundation.
2+
# All Rights Reserved.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5+
# not use this file except in compliance with the License. You may obtain
6+
# a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
# License for the specific language governing permissions and limitations
14+
# under the License.
15+
16+
import requests
17+
18+
from cloudfoundryclient.common import exceptions
19+
20+
21+
class Client(object):
22+
"""Client to interface with Cloudfoundry.
23+
24+
usage:
25+
from cloudfoundryclient.v2 import client
26+
cf_client = client.Client(username="foo@bar.com",
27+
password="BAAAAH")
28+
cf_client.login()
29+
"""
30+
31+
# user-agent
32+
USER_AGENT = "python-cloudfoundryclient"
33+
34+
# urls
35+
info_url = '/v2/info'
36+
auth_token_url = '/oauth/token'
37+
organizations_url = '/v2/organizations'
38+
organization_space_url = '/v2/organizations/%s/spaces'
39+
organization_summary_url = '/v2/organizations/%s/summary'
40+
organization_services_url = '/v2/organizations/%s/services'
41+
organization_space_quota_definitions_url = (
42+
'/v2/organizations/%s/space_quota_definitions')
43+
apps_space_url = '/v2/spaces/%s/apps'
44+
45+
def __init__(self, username="", password="",
46+
base_url="https://api.run.pivotal.io/"):
47+
self._base_url = base_url
48+
self._username = username
49+
self._password = password
50+
self._server_api_info = self.get_info()
51+
self._auth_data = None
52+
53+
def _get_headers(self):
54+
return {"Accept": "application/json",
55+
"Content-Type": "application/json",
56+
"User-Agent": self.USER_AGENT}
57+
58+
def get_info(self):
59+
r = requests.get(self._base_url + self.info_url)
60+
return r.json()
61+
62+
def login(self):
63+
headers = self._get_headers()
64+
# A login request requires these special header values.
65+
headers["Authorization"] = "Basic Y2Y6"
66+
headers["Content-Type"] = "application/x-www-form-urlencoded"
67+
payload = (("grant_type=password&password=%(password)s"
68+
"&scope=&username=%(username)s") %
69+
{'password': self._password, 'username': self._username})
70+
url = self._server_api_info['token_endpoint'] + self.auth_token_url
71+
r = requests.post(url, data=payload, headers=headers)
72+
if r.status_code != requests.codes.ok:
73+
raise exceptions.LoginError(r.text)
74+
else:
75+
# stash response for other api calls.
76+
self._auth_data = r.json()
77+
return r.json()
78+
79+
def logout(self):
80+
self._auth_data = None
81+
82+
def _check_logged_in(self):
83+
if not self._auth_data:
84+
raise exceptions.NotLoggedIn
85+
86+
def _generic_request_headers(self):
87+
self._check_logged_in()
88+
headers = self._get_headers()
89+
headers["Authorization"] = ("%s %s" %
90+
(self._auth_data['token_type'],
91+
self._auth_data['access_token']))
92+
return headers
93+
94+
def get_organizations(self):
95+
"""Return oranizations that a user is part of.
96+
97+
An org consists of users grouped together for management purposes.
98+
All members of an org share a resource quota plan, services
99+
availability, and custom domains.
100+
"""
101+
headers = self._generic_request_headers()
102+
url = self._base_url + self.organizations_url
103+
r = requests.get(url, headers=headers)
104+
return r.json()
105+
106+
def get_organization_summary(self, guid):
107+
headers = self._generic_request_headers()
108+
url = self._base_url + (self.organization_summary_url % guid)
109+
r = requests.get(url, headers=headers)
110+
return r.json()
111+
112+
def get_organization_spaces(self, guid):
113+
"""Return list of all spaces for an organization
114+
115+
param - guid: the guid of the organization.
116+
117+
Every application and service is scoped to a space. Each org
118+
contains at least one space. A space provides a set of users
119+
access to a shared location for application development,
120+
deployment, and maintenance. Each space role applies only to
121+
a particular space.
122+
"""
123+
124+
headers = self._generic_request_headers()
125+
url = self._base_url + (self.organization_space_url % guid)
126+
r = requests.get(url, headers=headers)
127+
return r.json()
128+
129+
def get_organization_services(self, guid):
130+
"""Return list of all services for an organization
131+
132+
param - guid: the guid of the organization.
133+
"""
134+
headers = self._generic_request_headers()
135+
url = self._base_url + (self.organization_services_url % guid)
136+
r = requests.get(url, headers=headers)
137+
return r.json()
138+
139+
def get_organization_space_quota_definitions(self, guid):
140+
"""Return list of all space quota definiations
141+
142+
param - guid: the guid of the organization.
143+
"""
144+
headers = self._generic_request_headers()
145+
url = self._base_url + (
146+
self.organization_space_quota_definitions_url % guid)
147+
r = requests.get(url, headers=headers)
148+
return r.json()
149+
150+
def get_apps_in_space(self, guid):
151+
"""Return list of all space quota definiations
152+
153+
param - guid: the guid of the organization.
154+
"""
155+
headers = self._generic_request_headers()
156+
url = self._base_url + (
157+
self.apps_space_url % guid)
158+
r = requests.get(url, headers=headers)
159+
return r.json()

‎requirements.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@
44

55
pbr>=0.6,!=0.7,<1.0
66
Babel>=1.3
7+
requests!=2.4.0,>=2.2.0

0 commit comments

Comments
 (0)