Skip to content

Commit

Permalink
Initial commit of Resource Manager API
Browse files Browse the repository at this point in the history
  • Loading branch information
jgeewax committed Jun 22, 2015
1 parent b0aef16 commit 9cb642e
Show file tree
Hide file tree
Showing 13 changed files with 1,156 additions and 1 deletion.
2 changes: 1 addition & 1 deletion docs/_static/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ $('.headerlink').parent().each(function() {
$('.side-nav').children('ul:nth-child(2)').children().each(function() {
var itemName = $(this).text();
if (itemName !== 'Datastore' && itemName !== 'Storage' &&
itemName !== 'Pub/Sub') {
itemName !== 'Pub/Sub' && itemName !== 'Resource Manager') {
$(this).css('padding-left','2em');
}
});
Expand Down
2 changes: 2 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
pubsub-usage
pubsub-subscription
pubsub-topic
resource-manager-api
resource-manager-project


Getting started
Expand Down
22 changes: 22 additions & 0 deletions docs/resource-manager-api.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.. toctree::
:maxdepth: 1
:hidden:

Resource Manager
----------------

Client
~~~~~~

.. automodule:: gcloud.resource_manager.client
:members:
:undoc-members:
:show-inheritance:

Connection
~~~~~~~~~~

.. automodule:: gcloud.resource_manager.connection
:members:
:undoc-members:
:show-inheritance:
7 changes: 7 additions & 0 deletions docs/resource-manager-project.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Projects
~~~~~~~~

.. automodule:: gcloud.resource_manager.project
:members:
:undoc-members:
:show-inheritance:
4 changes: 4 additions & 0 deletions gcloud/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
_HTTP_CODE_TO_EXCEPTION = {} # populated at end of module


class MissingClientError(Exception):
pass


class GCloudError(Exception):
"""Base error class for gcloud errors (abstract).
Expand Down
26 changes: 26 additions & 0 deletions gcloud/resource_manager/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Cloud ResourceManager API wrapper.
The main concepts with this API are:
- :class:`gcloud.resource_manager.project.Project` represents
a Google Cloud project.
"""

from gcloud.resource_manager.client import Client
from gcloud.resource_manager.connection import SCOPE
from gcloud.resource_manager.project import Project
249 changes: 249 additions & 0 deletions gcloud/resource_manager/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""gcloud.resource_manager client for interacting with API."""


from gcloud.credentials import get_credentials
from gcloud.credentials import get_for_service_account_json
from gcloud.credentials import get_for_service_account_p12
from gcloud.exceptions import NotFound
from gcloud.resource_manager.connection import Connection
from gcloud.resource_manager.iterator import ProjectIterator
from gcloud.resource_manager.project import Project


class Client(object):
"""Client to bundle configuration needed for API requests.
See
https://cloud.google.com/resource-manager/reference/rest/
for more information on this API.
Automatically get credentials::
>>> from gcloud.resource_manager import Client
>>> client = Client()
.. note::
Chances are you don't want to use the arguments in the constructor
but instead want one of the factory methods (like
:func:`gcloud.resource_manager.client.Client.from_service_account_json`
or similar).
:type credentials: :class:`oauth2client.client.OAuth2Credentials` or
:class:`NoneType`
:param credentials: The OAuth2 Credentials to use for the connection
owned by this client. If not passed (and if no ``http``
object is passed), falls back to the default inferred
from the environment.
:type http: :class:`httplib2.Http` or class that defines ``request()``.
:param http: An optional HTTP object to make requests. If not passed, an
``http`` object is created that is bound to the
``credentials`` for the current object.
"""
def __init__(self, credentials=None, http=None):
self._connection = None
self._credentials = credentials
self._http = http

@property
def connection(self):
"""Property that creates a Connection object on-demand."""
if self._connection is None:
self._connection = self._create_connection(
credentials=self._credentials, http=self._http)
return self._connection

@staticmethod
def _create_connection(credentials=None, http=None):
"""Create and return a new connection object."""
return Connection(credentials=credentials or get_credentials(),
http=http)

@classmethod
def from_service_account_json(cls, json_credentials_path):
"""Factory to retrieve JSON credentials while creating client.
Example::
>>> from gcloud.resource_manager import Client
>>> keyfile = '~/purple-spaceship-123-key.json'
>>> client = Client.from_service_account_json(keyfile)
:type json_credentials_path: string
:param json_credentials_path: The path to a private key file (this file
was given to you when you created the
service account). This file must contain
a JSON object with a private key and
other credentials information (downloaded
from the Google APIs console).
:rtype: :class:`gcloud.resource_manager.client.Client`
:returns: The client created with the retrieved JSON credentials.
"""
credentials = get_for_service_account_json(json_credentials_path)
return cls(credentials=credentials)

@classmethod
def from_service_account_p12(cls, client_email, private_key_path):
"""Factory to retrieve P12 credentials while creating client.
.. note::
Unless you have an explicit reason to use a PKCS12 key for your
service account, we recommend using a JSON key.
:type client_email: string
:param client_email: The e-mail attached to the service account.
:type private_key_path: string
:param private_key_path: The path to a private key file (this file was
given to you when you created the service
account). This file must be in P12 format.
:rtype: :class:`gcloud.resource_manager.client.Client`
:returns: The client created with the retrieved P12 credentials.
"""
credentials = get_for_service_account_p12(client_email,
private_key_path)
return cls(credentials=credentials)

def list_projects(self, filter=None, page_size=None, page_token=None):
"""List the projects visible to the account associated with this client.
Example::
>>> from gcloud import resource_manager
>>> client = resource_manager.Client()
>>> for project in client.list_projects():
... print project.id
List all projects with label ``'environment'`` set to ``'prod'``
(filtering by labels)::
>>> from gcloud import resource_manager
>>> client = resource_manager.Client()
>>> filter = {'labels.environment': 'prod'}
>>> for project in client.list_projects(filter=filter):
... print project.id
See:
https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects/list
Complete filtering example::
>>> project_filter = { # Return projects with...
... 'name': 'My Project', # name set to 'My Project'.
... 'id': 'my-project-id', # id set to 'my-project-id'.
... 'labels.stage': 'prod', # the label 'stage' set to 'prod'
... # set to prod.
... 'labels.color': '*' # a label 'color' set to anything.
... }
>>> client.list_projects(filter=project_filter)
:type filter: dict
:param filter: A dictionary of filter options where the keys are the
property to filter on, and the value is the
case-insensitive value to check (or * to check for
existence of the property). See the example above
for more details.
Note that property values are case-insensitive.
:type page_size: int
:param page_size: maximum number of projects to return in a single page.
If not passed, defaults to a value set by the API.
:type page_token: string
:param page_token: opaque marker for the next "page" of projects. If
not passed, the API will return the first page of
projects.
:rtype: :class:`gcloud.resource_manager.iterator.ProjectIterator`
:returns: A ProjectIterator class, which allows you to iterate through
all of the results without thinking about pagination.
Each item will be a :class:`.project.Project` object.
"""
params = {}

if page_size is not None:
params['pageSize'] = page_size

if page_token is not None:
params['pageToken'] = page_token

if filter is not None:
params['filter'] = filter

return ProjectIterator(client=self, extra_params=params,
path='/projects')

def project(self, id):
"""Get a Project instance without making an API call.
Typically used when creating a new project.
See :func:`gcloud.resource_manager.client.Client.get_project` if you
want to load a project and its metadata using an API call.
Example::
>>> client = Client()
>>> project = client.project('purple-spaceship-123')
>>> print project.name
None
>>> print project.id
purple-spaceship-123
:type id: str
:param id: The ID for this project.
:rtype: :class:`gcloud.resource_manager.project.Project`
:returns: A new instance of a :class:`.project.Project` **without**
any metadata loaded.
"""
return Project(id=id, client=self)

def get_project(self, id):
"""Get a Project instance and its metadata via an API call.
Example::
>>> client = Client()
>>> project = client.get_project('purple-spaceship-123')
>>> print project.name
Purple Spaceship 123
>>> print project.id
purple-spaceship-123
See :func:`gcloud.resource_manager.client.Client.project` if you
want to load a project **without** its metadata (aka, without an
API call).
:type id: str
:param id: The ID for this project.
:rtype: :class:`gcloud.resource_manager.project.Project`
:returns: A new instance of a :class:`.project.Project` with all
its metadata loaded.
"""
try:
project = self.project(id)
project.reload()
except NotFound:
project = None
return project
38 changes: 38 additions & 0 deletions gcloud/resource_manager/connection.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright 2015 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Create / interact with gcloud.resource_manager connections."""

from gcloud import connection as base_connection


SCOPE = ('https://www.googleapis.com/auth/cloud-platform')
"""The scopes required for authenticating as a Resouce Manager consumer."""


class Connection(base_connection.JSONConnection):
"""A connection to Google Cloud Resource Manager via the JSON REST API."""

API_BASE_URL = 'https://cloudresourcemanager.googleapis.com'
"""The base of the API call URL."""

API_VERSION = 'v1beta1'
"""The version of the API, used in building the API call's URL."""

API_URL_TEMPLATE = '{api_base_url}/{api_version}{path}'
"""A template for the URL of a particular API call."""

def __init__(self, credentials=None, http=None):
credentials = self._create_scoped_credentials(credentials, SCOPE)
super(Connection, self).__init__(credentials=credentials, http=http)
Loading

0 comments on commit 9cb642e

Please sign in to comment.