341 lines
12 KiB
Python
341 lines
12 KiB
Python
|
# 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.
|
||
|
|
||
|
import unittest2
|
||
|
|
||
|
|
||
|
class TestProject(unittest2.TestCase):
|
||
|
|
||
|
def _getTargetClass(self):
|
||
|
from gcloud.resource_manager.project import Project
|
||
|
return Project
|
||
|
|
||
|
def _makeOne(self, *args, **kw):
|
||
|
return self._getTargetClass()(*args, **kw)
|
||
|
|
||
|
def test_constructor_defaults(self):
|
||
|
client = object()
|
||
|
PROJECT_ID = 'project-id'
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
self.assertEqual(project.project_id, PROJECT_ID)
|
||
|
self.assertEqual(project._client, client)
|
||
|
self.assertEqual(project.name, None)
|
||
|
self.assertEqual(project.number, None)
|
||
|
self.assertEqual(project.labels, {})
|
||
|
self.assertEqual(project.status, None)
|
||
|
|
||
|
def test_constructor_explicit(self):
|
||
|
client = object()
|
||
|
PROJECT_ID = 'project-id'
|
||
|
DISPLAY_NAME = 'name'
|
||
|
LABELS = {'foo': 'bar'}
|
||
|
project = self._makeOne(PROJECT_ID, client,
|
||
|
name=DISPLAY_NAME, labels=LABELS)
|
||
|
self.assertEqual(project.project_id, PROJECT_ID)
|
||
|
self.assertEqual(project._client, client)
|
||
|
self.assertEqual(project.name, DISPLAY_NAME)
|
||
|
self.assertEqual(project.number, None)
|
||
|
self.assertEqual(project.labels, LABELS)
|
||
|
self.assertEqual(project.status, None)
|
||
|
|
||
|
def test_from_api_repr(self):
|
||
|
client = object()
|
||
|
PROJECT_ID = 'project-id'
|
||
|
PROJECT_NAME = 'My Project Name'
|
||
|
PROJECT_NUMBER = 12345678
|
||
|
PROJECT_LABELS = {'env': 'prod'}
|
||
|
PROJECT_LIFECYCLE_STATE = 'ACTIVE'
|
||
|
resource = {'projectId': PROJECT_ID,
|
||
|
'name': PROJECT_NAME,
|
||
|
'projectNumber': PROJECT_NUMBER,
|
||
|
'labels': PROJECT_LABELS,
|
||
|
'lifecycleState': PROJECT_LIFECYCLE_STATE}
|
||
|
project = self._getTargetClass().from_api_repr(resource, client)
|
||
|
self.assertEqual(project.project_id, PROJECT_ID)
|
||
|
self.assertEqual(project._client, client)
|
||
|
self.assertEqual(project.name, PROJECT_NAME)
|
||
|
self.assertEqual(project.number, PROJECT_NUMBER)
|
||
|
self.assertEqual(project.labels, PROJECT_LABELS)
|
||
|
self.assertEqual(project.status, PROJECT_LIFECYCLE_STATE)
|
||
|
|
||
|
def test_full_name(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
project = self._makeOne(PROJECT_ID, None)
|
||
|
self.assertEqual('projects/%s' % PROJECT_ID, project.full_name)
|
||
|
|
||
|
def test_full_name_missing_id(self):
|
||
|
project = self._makeOne(None, None)
|
||
|
with self.assertRaises(ValueError):
|
||
|
self.assertIsNone(project.full_name)
|
||
|
|
||
|
def test_path(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
project = self._makeOne(PROJECT_ID, None)
|
||
|
self.assertEqual('/projects/%s' % PROJECT_ID, project.path)
|
||
|
|
||
|
def test_create(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
PROJECT_NUMBER = 123
|
||
|
PROJECT_RESOURCE = {
|
||
|
'projectId': PROJECT_ID,
|
||
|
'projectNumber': PROJECT_NUMBER,
|
||
|
'name': 'Project Name',
|
||
|
'labels': {},
|
||
|
'lifecycleState': 'ACTIVE',
|
||
|
}
|
||
|
connection = _Connection(PROJECT_RESOURCE)
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
self.assertEqual(project.number, None)
|
||
|
project.create()
|
||
|
self.assertEqual(project.number, PROJECT_NUMBER)
|
||
|
request, = connection._requested
|
||
|
|
||
|
expected_request = {
|
||
|
'method': 'POST',
|
||
|
'data': {
|
||
|
'projectId': PROJECT_ID,
|
||
|
'labels': {},
|
||
|
'name': None,
|
||
|
},
|
||
|
'path': '/projects',
|
||
|
}
|
||
|
self.assertEqual(request, expected_request)
|
||
|
|
||
|
def test_reload(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
PROJECT_NUMBER = 123
|
||
|
PROJECT_RESOURCE = {
|
||
|
'projectId': PROJECT_ID,
|
||
|
'projectNumber': PROJECT_NUMBER,
|
||
|
'name': 'Project Name',
|
||
|
'labels': {'env': 'prod'},
|
||
|
'lifecycleState': 'ACTIVE',
|
||
|
}
|
||
|
connection = _Connection(PROJECT_RESOURCE)
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
self.assertEqual(project.number, None)
|
||
|
self.assertEqual(project.name, None)
|
||
|
self.assertEqual(project.labels, {})
|
||
|
self.assertEqual(project.status, None)
|
||
|
project.reload()
|
||
|
self.assertEqual(project.name, PROJECT_RESOURCE['name'])
|
||
|
self.assertEqual(project.number, PROJECT_NUMBER)
|
||
|
self.assertEqual(project.labels, PROJECT_RESOURCE['labels'])
|
||
|
self.assertEqual(project.status, PROJECT_RESOURCE['lifecycleState'])
|
||
|
|
||
|
request, = connection._requested
|
||
|
# NOTE: data is not in the request since a GET request.
|
||
|
expected_request = {
|
||
|
'method': 'GET',
|
||
|
'path': project.path,
|
||
|
}
|
||
|
self.assertEqual(request, expected_request)
|
||
|
|
||
|
def test_exists(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
connection = _Connection({'projectId': PROJECT_ID})
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
self.assertTrue(project.exists())
|
||
|
|
||
|
def test_exists_with_explicitly_passed_client(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
connection = _Connection({'projectId': PROJECT_ID})
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, None)
|
||
|
self.assertTrue(project.exists(client=client))
|
||
|
|
||
|
def test_exists_with_missing_client(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
project = self._makeOne(PROJECT_ID, None)
|
||
|
with self.assertRaises(AttributeError):
|
||
|
project.exists()
|
||
|
|
||
|
def test_exists_not_found(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
connection = _Connection()
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
self.assertFalse(project.exists())
|
||
|
|
||
|
def test_update(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
PROJECT_NUMBER = 123
|
||
|
PROJECT_NAME = 'Project Name'
|
||
|
LABELS = {'env': 'prod'}
|
||
|
PROJECT_RESOURCE = {
|
||
|
'projectId': PROJECT_ID,
|
||
|
'projectNumber': PROJECT_NUMBER,
|
||
|
'name': PROJECT_NAME,
|
||
|
'labels': LABELS,
|
||
|
'lifecycleState': 'ACTIVE',
|
||
|
}
|
||
|
connection = _Connection(PROJECT_RESOURCE)
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
project.name = PROJECT_NAME
|
||
|
project.labels = LABELS
|
||
|
project.update()
|
||
|
|
||
|
request, = connection._requested
|
||
|
expected_request = {
|
||
|
'method': 'PUT',
|
||
|
'data': {
|
||
|
'name': PROJECT_NAME,
|
||
|
'labels': LABELS,
|
||
|
},
|
||
|
'path': project.path,
|
||
|
}
|
||
|
self.assertEqual(request, expected_request)
|
||
|
|
||
|
def test_delete_without_reload_data(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
PROJECT_NUMBER = 123
|
||
|
PROJECT_RESOURCE = {
|
||
|
'projectId': PROJECT_ID,
|
||
|
'projectNumber': PROJECT_NUMBER,
|
||
|
'name': 'Project Name',
|
||
|
'labels': {'env': 'prod'},
|
||
|
'lifecycleState': 'ACTIVE',
|
||
|
}
|
||
|
connection = _Connection(PROJECT_RESOURCE)
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
project.delete(reload_data=False)
|
||
|
|
||
|
request, = connection._requested
|
||
|
# NOTE: data is not in the request since a DELETE request.
|
||
|
expected_request = {
|
||
|
'method': 'DELETE',
|
||
|
'path': project.path,
|
||
|
}
|
||
|
self.assertEqual(request, expected_request)
|
||
|
|
||
|
def test_delete_with_reload_data(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
PROJECT_NUMBER = 123
|
||
|
PROJECT_RESOURCE = {
|
||
|
'projectId': PROJECT_ID,
|
||
|
'projectNumber': PROJECT_NUMBER,
|
||
|
'name': 'Project Name',
|
||
|
'labels': {'env': 'prod'},
|
||
|
'lifecycleState': 'ACTIVE',
|
||
|
}
|
||
|
DELETING_PROJECT = PROJECT_RESOURCE.copy()
|
||
|
DELETING_PROJECT['lifecycleState'] = NEW_STATE = 'DELETE_REQUESTED'
|
||
|
|
||
|
connection = _Connection(PROJECT_RESOURCE, DELETING_PROJECT)
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
project.delete(reload_data=True)
|
||
|
self.assertEqual(project.status, NEW_STATE)
|
||
|
|
||
|
delete_request, get_request = connection._requested
|
||
|
# NOTE: data is not in the request since a DELETE request.
|
||
|
expected_delete_request = {
|
||
|
'method': 'DELETE',
|
||
|
'path': project.path,
|
||
|
}
|
||
|
self.assertEqual(delete_request, expected_delete_request)
|
||
|
|
||
|
# NOTE: data is not in the request since a GET request.
|
||
|
expected_get_request = {
|
||
|
'method': 'GET',
|
||
|
'path': project.path,
|
||
|
}
|
||
|
self.assertEqual(get_request, expected_get_request)
|
||
|
|
||
|
def test_undelete_without_reload_data(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
PROJECT_NUMBER = 123
|
||
|
PROJECT_RESOURCE = {
|
||
|
'projectId': PROJECT_ID,
|
||
|
'projectNumber': PROJECT_NUMBER,
|
||
|
'name': 'Project Name',
|
||
|
'labels': {'env': 'prod'},
|
||
|
'lifecycleState': 'DELETE_REQUESTED',
|
||
|
}
|
||
|
connection = _Connection(PROJECT_RESOURCE)
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
project.undelete(reload_data=False)
|
||
|
|
||
|
request, = connection._requested
|
||
|
# NOTE: data is not in the request, undelete doesn't need it.
|
||
|
expected_request = {
|
||
|
'method': 'POST',
|
||
|
'path': project.path + ':undelete',
|
||
|
}
|
||
|
self.assertEqual(request, expected_request)
|
||
|
|
||
|
def test_undelete_with_reload_data(self):
|
||
|
PROJECT_ID = 'project-id'
|
||
|
PROJECT_NUMBER = 123
|
||
|
PROJECT_RESOURCE = {
|
||
|
'projectId': PROJECT_ID,
|
||
|
'projectNumber': PROJECT_NUMBER,
|
||
|
'name': 'Project Name',
|
||
|
'labels': {'env': 'prod'},
|
||
|
'lifecycleState': 'DELETE_REQUESTED',
|
||
|
}
|
||
|
UNDELETED_PROJECT = PROJECT_RESOURCE.copy()
|
||
|
UNDELETED_PROJECT['lifecycleState'] = NEW_STATE = 'ACTIVE'
|
||
|
|
||
|
connection = _Connection(PROJECT_RESOURCE, UNDELETED_PROJECT)
|
||
|
client = _Client(connection=connection)
|
||
|
project = self._makeOne(PROJECT_ID, client)
|
||
|
project.undelete(reload_data=True)
|
||
|
self.assertEqual(project.status, NEW_STATE)
|
||
|
|
||
|
undelete_request, get_request = connection._requested
|
||
|
# NOTE: data is not in the request, undelete doesn't need it.
|
||
|
expected_undelete_request = {
|
||
|
'method': 'POST',
|
||
|
'path': project.path + ':undelete',
|
||
|
}
|
||
|
self.assertEqual(undelete_request, expected_undelete_request)
|
||
|
|
||
|
# NOTE: data is not in the request since a GET request.
|
||
|
expected_get_request = {
|
||
|
'method': 'GET',
|
||
|
'path': project.path,
|
||
|
}
|
||
|
self.assertEqual(get_request, expected_get_request)
|
||
|
|
||
|
|
||
|
class _Connection(object):
|
||
|
|
||
|
def __init__(self, *responses):
|
||
|
self._responses = responses
|
||
|
self._requested = []
|
||
|
|
||
|
def api_request(self, **kw):
|
||
|
from gcloud.exceptions import NotFound
|
||
|
self._requested.append(kw)
|
||
|
|
||
|
try:
|
||
|
response, self._responses = self._responses[0], self._responses[1:]
|
||
|
except:
|
||
|
raise NotFound('miss')
|
||
|
else:
|
||
|
return response
|
||
|
|
||
|
|
||
|
class _Client(object):
|
||
|
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = connection
|