Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial commit of Resource Manager API #933

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
3 changes: 3 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
pubsub-usage
pubsub-subscription
pubsub-topic
resource-manager-api
resource-manager-client
resource-manager-project


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

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

Overview
~~~~~~~~

The Cloud Resource Manager API provides methods that you can use
to programmatically manage your projects in the Google Cloud Platform.
With this API, you can do the following:

- Get a list of all projects associated with an account
- Create new projects
- Update existing projects
- Delete projects
- Undelete, or recover, projects that you don't want to delete

.. note::

Don't forget to look at the **Authentication** section below.
It's slightly different from the rest of this library.

Here's a quick example of the full life-cycle::

>>> from gcloud import resource_manager

>>> # List all projects you have access to
>>> client = resource_manager.Client()
>>> for project in client.list_projects():
... print project

>>> # Create a new project
>>> new_project = client.project('your-project-id-here')
>>> new_project.name = 'My new project'
>>> new_project.create()

>>> # Update an existing project
>>> project = client.get_project('my-existing-project')
>>> print project
<Project: Existing Project (my-existing-project)>
>>> project.name = 'Modified name'
>>> project.update()
>>> print project
<Project: Modified name (my-existing-project)>

>>> # Delete a project
>>> project = client.get_project('my-existing-project')
>>> project.delete()

>>> # Undelete a project
>>> project = client.get_project('my-existing-project')
>>> project.undelete()

Authentication
~~~~~~~~~~~~~~

Unlike the other APIs, the Resource Manager API is focused on managing your
various projects inside Google Cloud Platform. What this means (currently) is
that you can't use a Service Account to work with some parts of this API
(for example, creating projects).

The reason is actually pretty simple: if your API call is trying to do
something like create a project, what project's Service Account can you use?
Currently none.

This means that for this API you should always use the credentials
provided by the Cloud SDK, which you can get by running ``gcloud auth login``
(if you're not familiar with this, take a look at http://cloud.google.com/sdk).

Once you run that command, ``gcloud`` will automatically pick up the

This comment was marked as spam.

This comment was marked as spam.

credentials from the Cloud SDK, and you can use the "automatic discovery"
feature of the library.

Start by authenticating::

$ gcloud auth login

And then simply create a client::

>>> from gcloud import resource_manager
>>> client = resource_manager.Client()
19 changes: 19 additions & 0 deletions docs/resource-manager-client.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.. toctree::
:maxdepth: 0
:hidden:

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:
25 changes: 25 additions & 0 deletions gcloud/resource_manager/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# 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.

This comment was marked as spam.

This comment was marked as spam.

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
238 changes: 238 additions & 0 deletions gcloud/resource_manager/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,238 @@
# 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.

"""A Client for interacting with the Resource Manager API.

Overview
~~~~~~~~

There are three main methods in the ``Client`` class:

- :func:`gcloud.resource_manager.client.Client.list_projects`
- :func:`gcloud.resource_manager.client.Client.project`
- :func:`gcloud.resource_manager.client.Client.get_project`

This comment was marked as spam.


``project()`` versus ``get_project()``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The difference between ``project`` and ``get_project`` is subtle,
so it might be worthwhile to make a quick distinction.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


If you want to simply "get a hold of a Project" object,
but **don't** want to actually retrieve any metadata about that project
(for example, when you want to create a new project, or delete a project
in a single API request), ``project()`` is the best method to use::

>>> from gcloud import resource_manager
>>> client = resource_manager.Client()
>>> project = client.project('purple-spaceship-123')
>>> project.number is None
True

The ``project`` referenced above has no extra metadata associated with it,
however you can still operate on it (ie, ``project.create()`` or
``project.delete()``).

If you want to retrieve a project and all of it's metadata, the best method
to use is ``get_project()``, which will return ``None`` if the project
doesn't exist::

>>> from gcloud import resource_manager
>>> client = resource_manager.Client()
>>> project = client.get_project('purple-spaceship-123')
>>> project.number is None
False
>>> project = client.get_project('doesnt-exist')
>>> project is None
True
"""


from gcloud.client import Client as BaseClient
from gcloud.exceptions import NotFound
from gcloud.iterator import Iterator
from gcloud.resource_manager.connection import Connection
from gcloud.resource_manager.project import Project


class Client(BaseClient):
"""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 want to use either the constructor with no arguments,
or one of the factory methods (like
:func:`gcloud.resource_manager.client.Client.from_service_account_json`
or similar).

This comment was marked as spam.

This comment was marked as spam.


Even more likely is that you want to use the Cloud SDK to get
credentials for these API calls (that is, run ``gcloud auth login``).

: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.
"""

_connection_class = Connection

def list_projects(self, filter_params=None, page_size=None):
"""List the projects visible to this client.

Example::

>>> from gcloud import resource_manager
>>> client = resource_manager.Client()
>>> for project in client.list_projects():
... print project.project_id

List all projects with label ``'environment'`` set to ``'prod'``
(filtering by labels)::

>>> from gcloud import resource_manager
>>> client = resource_manager.Client()
>>> env_filter = {'labels.environment': 'prod'}

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

>>> for project in client.list_projects(env_filter):
... print project.project_id

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


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(project_filter)

:type filter_params: dict
:param filter_params: 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.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.


: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.

:rtype: :class:`gcloud.resource_manager.iterator.ProjectIterator`

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

:returns: A ProjectIterator class, which allows you to iterate through
all of the results without thinking about pagination.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

Each item will be a :class:`.project.Project` object.
"""
params = {}

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

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

client = self

class ProjectIterator(Iterator):

This comment was marked as spam.

This comment was marked as spam.

"""An iterator over a list of Project resources."""

def get_items_from_response(self, response):
"""Yield :class:`.resource_manager.project.Project` items
from response.

:type response: dict
:param response: The JSON API response for a page of projects.
"""
for resource in response.get('projects', []):
item = Project.from_api_repr(resource, client=client)
yield item

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

def project(self, project_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.project_id
purple-spaceship-123

:type project_id: str
:param project_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(project_id=project_id, client=self)

def get_project(self, project_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.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 project_id: str
:param project_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(project_id)
project.reload()
except NotFound:

This comment was marked as spam.

project = None
return project
Loading