1012 lines
35 KiB
Python
1012 lines
35 KiB
Python
# Copyright 2016 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
|
|
|
|
|
|
try:
|
|
# pylint: disable=unused-import
|
|
import gcloud.pubsub._gax
|
|
# pylint: enable=unused-import
|
|
except ImportError: # pragma: NO COVER
|
|
_HAVE_GAX = False
|
|
else:
|
|
_HAVE_GAX = True
|
|
|
|
|
|
class _Base(object):
|
|
PROJECT = 'PROJECT'
|
|
PROJECT_PATH = 'projects/%s' % (PROJECT,)
|
|
FILTER = 'logName:syslog AND severity>=ERROR'
|
|
|
|
def _makeOne(self, *args, **kw):
|
|
return self._getTargetClass()(*args, **kw)
|
|
|
|
|
|
@unittest2.skipUnless(_HAVE_GAX, 'No gax-python')
|
|
class Test_LoggingAPI(_Base, unittest2.TestCase):
|
|
LOG_NAME = 'log_name'
|
|
|
|
def _getTargetClass(self):
|
|
from gcloud.logging._gax import _LoggingAPI
|
|
return _LoggingAPI
|
|
|
|
def test_ctor(self):
|
|
gax_api = _GAXLoggingAPI()
|
|
api = self._makeOne(gax_api)
|
|
self.assertTrue(api._gax_api is gax_api)
|
|
|
|
def test_list_entries_no_paging(self):
|
|
from google.gax import INITIAL_PAGE
|
|
from gcloud.logging import DESCENDING
|
|
from gcloud._testing import _GAXPageIterator
|
|
TOKEN = 'TOKEN'
|
|
TEXT = 'TEXT'
|
|
response = _GAXPageIterator(
|
|
[_LogEntryPB(self.LOG_NAME, text_payload=TEXT)], TOKEN)
|
|
gax_api = _GAXLoggingAPI(_list_log_entries_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
entries, next_token = api.list_entries(
|
|
[self.PROJECT], self.FILTER, DESCENDING)
|
|
|
|
self.assertEqual(len(entries), 1)
|
|
entry = entries[0]
|
|
self.assertIsInstance(entry, dict)
|
|
self.assertEqual(entry['logName'], self.LOG_NAME)
|
|
self.assertEqual(entry['resource'], {'type': 'global'})
|
|
self.assertEqual(entry['textPayload'], TEXT)
|
|
self.assertEqual(next_token, TOKEN)
|
|
|
|
projects, filter_, order_by, page_size, options = (
|
|
gax_api._list_log_entries_called_with)
|
|
self.assertEqual(projects, [self.PROJECT])
|
|
self.assertEqual(filter_, self.FILTER)
|
|
self.assertEqual(order_by, DESCENDING)
|
|
self.assertEqual(page_size, 0)
|
|
self.assertTrue(options.page_token is INITIAL_PAGE)
|
|
|
|
def test_list_entries_with_paging(self):
|
|
from gcloud._testing import _GAXPageIterator
|
|
SIZE = 23
|
|
TOKEN = 'TOKEN'
|
|
NEW_TOKEN = 'NEW_TOKEN'
|
|
PAYLOAD = {'message': 'MESSAGE', 'weather': 'sunny'}
|
|
response = _GAXPageIterator(
|
|
[_LogEntryPB(self.LOG_NAME, json_payload=PAYLOAD)], NEW_TOKEN)
|
|
gax_api = _GAXLoggingAPI(_list_log_entries_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
entries, next_token = api.list_entries(
|
|
[self.PROJECT], page_size=SIZE, page_token=TOKEN)
|
|
|
|
self.assertEqual(len(entries), 1)
|
|
entry = entries[0]
|
|
self.assertIsInstance(entry, dict)
|
|
self.assertEqual(entry['logName'], self.LOG_NAME)
|
|
self.assertEqual(entry['resource'], {'type': 'global'})
|
|
self.assertEqual(entry['jsonPayload'], PAYLOAD)
|
|
self.assertEqual(next_token, NEW_TOKEN)
|
|
|
|
projects, filter_, order_by, page_size, options = (
|
|
gax_api._list_log_entries_called_with)
|
|
self.assertEqual(projects, [self.PROJECT])
|
|
self.assertEqual(filter_, '')
|
|
self.assertEqual(order_by, '')
|
|
self.assertEqual(page_size, SIZE)
|
|
self.assertEqual(options.page_token, TOKEN)
|
|
|
|
def test_list_entries_with_extra_properties(self):
|
|
from datetime import datetime
|
|
from gcloud._testing import _GAXPageIterator
|
|
from gcloud._helpers import UTC
|
|
from gcloud._helpers import _datetime_to_rfc3339
|
|
from gcloud._helpers import _datetime_to_pb_timestamp
|
|
NOW = datetime.utcnow().replace(tzinfo=UTC)
|
|
SIZE = 23
|
|
TOKEN = 'TOKEN'
|
|
NEW_TOKEN = 'NEW_TOKEN'
|
|
PAYLOAD = {'message': 'MESSAGE', 'weather': 'sunny'}
|
|
SEVERITY = 'WARNING'
|
|
LABELS = {
|
|
'foo': 'bar',
|
|
}
|
|
IID = 'IID'
|
|
request = _HTTPRequestPB()
|
|
operation = _LogEntryOperationPB()
|
|
EXTRAS = {
|
|
'severity': SEVERITY,
|
|
'labels': LABELS,
|
|
'insert_id': IID,
|
|
'http_request': request,
|
|
'operation': operation,
|
|
}
|
|
ENTRY = _LogEntryPB(self.LOG_NAME, proto_payload=PAYLOAD, **EXTRAS)
|
|
ENTRY.resource.labels['foo'] = 'bar'
|
|
ENTRY.timestamp = _datetime_to_pb_timestamp(NOW)
|
|
response = _GAXPageIterator([ENTRY], NEW_TOKEN)
|
|
gax_api = _GAXLoggingAPI(_list_log_entries_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
entries, next_token = api.list_entries(
|
|
[self.PROJECT], page_size=SIZE, page_token=TOKEN)
|
|
|
|
self.assertEqual(len(entries), 1)
|
|
entry = entries[0]
|
|
self.assertIsInstance(entry, dict)
|
|
self.assertEqual(entry['logName'], self.LOG_NAME)
|
|
self.assertEqual(entry['resource'],
|
|
{'type': 'global', 'labels': {'foo': 'bar'}})
|
|
self.assertEqual(entry['protoPayload'], PAYLOAD)
|
|
self.assertEqual(entry['severity'], SEVERITY)
|
|
self.assertEqual(entry['labels'], LABELS)
|
|
self.assertEqual(entry['insertId'], IID)
|
|
self.assertEqual(entry['timestamp'], _datetime_to_rfc3339(NOW))
|
|
EXPECTED_REQUEST = {
|
|
'request_method': request.request_method,
|
|
'request_url': request.request_url,
|
|
'status': request.status,
|
|
'request_size': request.request_size,
|
|
'response_size': request.response_size,
|
|
'referer': request.referer,
|
|
'user_agent': request.user_agent,
|
|
'remote_ip': request.remote_ip,
|
|
'cache_hit': request.cache_hit,
|
|
}
|
|
self.assertEqual(entry['httpRequest'], EXPECTED_REQUEST)
|
|
EXPECTED_OPERATION = {
|
|
'producer': operation.producer,
|
|
'id': operation.id,
|
|
'first': operation.first,
|
|
'last': operation.last,
|
|
}
|
|
self.assertEqual(entry['operation'], EXPECTED_OPERATION)
|
|
self.assertEqual(next_token, NEW_TOKEN)
|
|
|
|
projects, filter_, order_by, page_size, options = (
|
|
gax_api._list_log_entries_called_with)
|
|
self.assertEqual(projects, [self.PROJECT])
|
|
self.assertEqual(filter_, '')
|
|
self.assertEqual(order_by, '')
|
|
self.assertEqual(page_size, SIZE)
|
|
self.assertEqual(options.page_token, TOKEN)
|
|
|
|
def test_write_entries_single(self):
|
|
from google.logging.v2.log_entry_pb2 import LogEntry
|
|
TEXT = 'TEXT'
|
|
LOG_PATH = 'projects/%s/logs/%s' % (self.PROJECT, self.LOG_NAME)
|
|
ENTRY = {
|
|
'logName': LOG_PATH,
|
|
'resource': {'type': 'global'},
|
|
'textPayload': TEXT,
|
|
}
|
|
gax_api = _GAXLoggingAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.write_entries([ENTRY])
|
|
|
|
entries, log_name, resource, labels, partial_success, options = (
|
|
gax_api._write_log_entries_called_with)
|
|
self.assertEqual(len(entries), 1)
|
|
|
|
entry = entries[0]
|
|
self.assertTrue(isinstance(entry, LogEntry))
|
|
self.assertEqual(entry.log_name, LOG_PATH)
|
|
self.assertEqual(entry.resource.type, 'global')
|
|
self.assertEqual(entry.labels, {})
|
|
self.assertEqual(entry.text_payload, TEXT)
|
|
|
|
self.assertEqual(log_name, None)
|
|
self.assertEqual(resource, None)
|
|
self.assertEqual(labels, None)
|
|
self.assertEqual(partial_success, False)
|
|
self.assertEqual(options, None)
|
|
|
|
def test_write_entries_w_extra_properties(self):
|
|
# pylint: disable=too-many-statements
|
|
from datetime import datetime
|
|
from google.logging.type.log_severity_pb2 import WARNING
|
|
from google.logging.v2.log_entry_pb2 import LogEntry
|
|
from gcloud._helpers import UTC, _pb_timestamp_to_datetime
|
|
NOW = datetime.utcnow().replace(tzinfo=UTC)
|
|
TEXT = 'TEXT'
|
|
LOG_PATH = 'projects/%s/logs/%s' % (self.PROJECT, self.LOG_NAME)
|
|
SEVERITY = 'WARNING'
|
|
LABELS = {
|
|
'foo': 'bar',
|
|
}
|
|
IID = 'IID'
|
|
REQUEST_METHOD = 'GET'
|
|
REQUEST_URL = 'http://example.com/requested'
|
|
STATUS = 200
|
|
REQUEST_SIZE = 256
|
|
RESPONSE_SIZE = 1024
|
|
REFERRER_URL = 'http://example.com/referer'
|
|
USER_AGENT = 'Agent/1.0'
|
|
REMOTE_IP = '1.2.3.4'
|
|
REQUEST = {
|
|
'requestMethod': REQUEST_METHOD,
|
|
'requestUrl': REQUEST_URL,
|
|
'status': STATUS,
|
|
'requestSize': REQUEST_SIZE,
|
|
'responseSize': RESPONSE_SIZE,
|
|
'referer': REFERRER_URL,
|
|
'userAgent': USER_AGENT,
|
|
'remoteIp': REMOTE_IP,
|
|
'cacheHit': False,
|
|
}
|
|
PRODUCER = 'PRODUCER'
|
|
OPID = 'OPID'
|
|
OPERATION = {
|
|
'producer': PRODUCER,
|
|
'id': OPID,
|
|
'first': False,
|
|
'last': True,
|
|
}
|
|
ENTRY = {
|
|
'logName': LOG_PATH,
|
|
'resource': {'type': 'global'},
|
|
'textPayload': TEXT,
|
|
'severity': SEVERITY,
|
|
'labels': LABELS,
|
|
'insertId': IID,
|
|
'timestamp': NOW,
|
|
'httpRequest': REQUEST,
|
|
'operation': OPERATION,
|
|
}
|
|
gax_api = _GAXLoggingAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.write_entries([ENTRY])
|
|
|
|
entries, log_name, resource, labels, partial_success, options = (
|
|
gax_api._write_log_entries_called_with)
|
|
self.assertEqual(len(entries), 1)
|
|
|
|
entry = entries[0]
|
|
self.assertTrue(isinstance(entry, LogEntry))
|
|
self.assertEqual(entry.log_name, LOG_PATH)
|
|
self.assertEqual(entry.resource.type, 'global')
|
|
self.assertEqual(entry.text_payload, TEXT)
|
|
self.assertEqual(entry.severity, WARNING)
|
|
self.assertEqual(entry.labels, LABELS)
|
|
self.assertEqual(entry.insert_id, IID)
|
|
stamp = _pb_timestamp_to_datetime(entry.timestamp)
|
|
self.assertEqual(stamp, NOW)
|
|
|
|
request = entry.http_request
|
|
self.assertEqual(request.request_method, REQUEST_METHOD)
|
|
self.assertEqual(request.request_url, REQUEST_URL)
|
|
self.assertEqual(request.status, STATUS)
|
|
self.assertEqual(request.request_size, REQUEST_SIZE)
|
|
self.assertEqual(request.response_size, RESPONSE_SIZE)
|
|
self.assertEqual(request.referer, REFERRER_URL)
|
|
self.assertEqual(request.user_agent, USER_AGENT)
|
|
self.assertEqual(request.remote_ip, REMOTE_IP)
|
|
self.assertEqual(request.cache_hit, False)
|
|
|
|
operation = entry.operation
|
|
self.assertEqual(operation.producer, PRODUCER)
|
|
self.assertEqual(operation.id, OPID)
|
|
self.assertFalse(operation.first)
|
|
self.assertTrue(operation.last)
|
|
|
|
self.assertEqual(log_name, None)
|
|
self.assertEqual(resource, None)
|
|
self.assertEqual(labels, None)
|
|
self.assertEqual(partial_success, False)
|
|
self.assertEqual(options, None)
|
|
# pylint: enable=too-many-statements
|
|
|
|
def test_write_entries_multiple(self):
|
|
# pylint: disable=too-many-statements
|
|
import datetime
|
|
from google.logging.type.log_severity_pb2 import WARNING
|
|
from google.logging.v2.log_entry_pb2 import LogEntry
|
|
from google.protobuf.any_pb2 import Any
|
|
from google.protobuf.struct_pb2 import Struct
|
|
from gcloud._helpers import _datetime_to_rfc3339, UTC
|
|
TEXT = 'TEXT'
|
|
NOW = datetime.datetime.utcnow().replace(tzinfo=UTC)
|
|
TIMESTAMP_TYPE_URL = 'type.googleapis.com/google.protobuf.Timestamp'
|
|
JSON = {'payload': 'PAYLOAD', 'type': 'json'}
|
|
PROTO = {
|
|
'@type': TIMESTAMP_TYPE_URL,
|
|
'value': _datetime_to_rfc3339(NOW),
|
|
}
|
|
PRODUCER = 'PRODUCER'
|
|
OPID = 'OPID'
|
|
URL = 'http://example.com/'
|
|
ENTRIES = [
|
|
{'textPayload': TEXT,
|
|
'severity': WARNING},
|
|
{'jsonPayload': JSON,
|
|
'operation': {'producer': PRODUCER, 'id': OPID}},
|
|
{'protoPayload': PROTO,
|
|
'httpRequest': {'requestUrl': URL}},
|
|
]
|
|
LOG_PATH = 'projects/%s/logs/%s' % (self.PROJECT, self.LOG_NAME)
|
|
RESOURCE = {
|
|
'type': 'global',
|
|
}
|
|
LABELS = {
|
|
'foo': 'bar',
|
|
}
|
|
gax_api = _GAXLoggingAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.write_entries(ENTRIES, LOG_PATH, RESOURCE, LABELS)
|
|
|
|
entries, log_name, resource, labels, partial_success, options = (
|
|
gax_api._write_log_entries_called_with)
|
|
self.assertEqual(len(entries), len(ENTRIES))
|
|
|
|
entry = entries[0]
|
|
self.assertTrue(isinstance(entry, LogEntry))
|
|
self.assertEqual(entry.log_name, '')
|
|
self.assertEqual(entry.resource.type, '')
|
|
self.assertEqual(entry.labels, {})
|
|
self.assertEqual(entry.text_payload, TEXT)
|
|
self.assertEqual(entry.severity, WARNING)
|
|
|
|
entry = entries[1]
|
|
self.assertTrue(isinstance(entry, LogEntry))
|
|
self.assertEqual(entry.log_name, '')
|
|
self.assertEqual(entry.resource.type, '')
|
|
self.assertEqual(entry.labels, {})
|
|
json_struct = entry.json_payload
|
|
self.assertTrue(isinstance(json_struct, Struct))
|
|
self.assertEqual(json_struct.fields['payload'].string_value,
|
|
JSON['payload'])
|
|
operation = entry.operation
|
|
self.assertEqual(operation.producer, PRODUCER)
|
|
self.assertEqual(operation.id, OPID)
|
|
|
|
entry = entries[2]
|
|
self.assertTrue(isinstance(entry, LogEntry))
|
|
self.assertEqual(entry.log_name, '')
|
|
self.assertEqual(entry.resource.type, '')
|
|
self.assertEqual(entry.labels, {})
|
|
proto = entry.proto_payload
|
|
self.assertTrue(isinstance(proto, Any))
|
|
self.assertEqual(proto.type_url, TIMESTAMP_TYPE_URL)
|
|
request = entry.http_request
|
|
self.assertEqual(request.request_url, URL)
|
|
|
|
self.assertEqual(log_name, LOG_PATH)
|
|
self.assertEqual(resource, RESOURCE)
|
|
self.assertEqual(labels, LABELS)
|
|
self.assertEqual(partial_success, False)
|
|
self.assertEqual(options, None)
|
|
# pylint: enable=too-many-statements
|
|
|
|
def test_logger_delete(self):
|
|
LOG_PATH = 'projects/%s/logs/%s' % (self.PROJECT, self.LOG_NAME)
|
|
gax_api = _GAXLoggingAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.logger_delete(self.PROJECT, self.LOG_NAME)
|
|
|
|
log_name, options = gax_api._delete_log_called_with
|
|
self.assertEqual(log_name, LOG_PATH)
|
|
self.assertEqual(options, None)
|
|
|
|
|
|
@unittest2.skipUnless(_HAVE_GAX, 'No gax-python')
|
|
class Test_SinksAPI(_Base, unittest2.TestCase):
|
|
SINK_NAME = 'sink_name'
|
|
SINK_PATH = 'projects/%s/sinks/%s' % (_Base.PROJECT, SINK_NAME)
|
|
DESTINATION_URI = 'faux.googleapis.com/destination'
|
|
|
|
def _getTargetClass(self):
|
|
from gcloud.logging._gax import _SinksAPI
|
|
return _SinksAPI
|
|
|
|
def test_ctor(self):
|
|
gax_api = _GAXSinksAPI()
|
|
api = self._makeOne(gax_api)
|
|
self.assertTrue(api._gax_api is gax_api)
|
|
|
|
def test_list_sinks_no_paging(self):
|
|
from google.gax import INITIAL_PAGE
|
|
from gcloud._testing import _GAXPageIterator
|
|
TOKEN = 'TOKEN'
|
|
SINKS = [{
|
|
'name': self.SINK_PATH,
|
|
'filter': self.FILTER,
|
|
'destination': self.DESTINATION_URI,
|
|
}]
|
|
response = _GAXPageIterator(
|
|
[_LogSinkPB(self.SINK_PATH, self.DESTINATION_URI, self.FILTER)],
|
|
TOKEN)
|
|
gax_api = _GAXSinksAPI(_list_sinks_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
sinks, token = api.list_sinks(self.PROJECT)
|
|
|
|
self.assertEqual(sinks, SINKS)
|
|
self.assertEqual(token, TOKEN)
|
|
|
|
project, page_size, options = gax_api._list_sinks_called_with
|
|
self.assertEqual(project, self.PROJECT)
|
|
self.assertEqual(page_size, 0)
|
|
self.assertEqual(options.page_token, INITIAL_PAGE)
|
|
|
|
def test_list_sinks_w_paging(self):
|
|
from gcloud._testing import _GAXPageIterator
|
|
TOKEN = 'TOKEN'
|
|
PAGE_SIZE = 42
|
|
SINKS = [{
|
|
'name': self.SINK_PATH,
|
|
'filter': self.FILTER,
|
|
'destination': self.DESTINATION_URI,
|
|
}]
|
|
response = _GAXPageIterator(
|
|
[_LogSinkPB(self.SINK_PATH, self.DESTINATION_URI, self.FILTER)],
|
|
None)
|
|
gax_api = _GAXSinksAPI(_list_sinks_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
sinks, token = api.list_sinks(
|
|
self.PROJECT, page_size=PAGE_SIZE, page_token=TOKEN)
|
|
|
|
self.assertEqual(sinks, SINKS)
|
|
self.assertEqual(token, None)
|
|
|
|
project, page_size, options = gax_api._list_sinks_called_with
|
|
self.assertEqual(project, self.PROJECT)
|
|
self.assertEqual(page_size, PAGE_SIZE)
|
|
self.assertEqual(options.page_token, TOKEN)
|
|
|
|
def test_sink_create_error(self):
|
|
from google.gax.errors import GaxError
|
|
gax_api = _GAXSinksAPI(_random_gax_error=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(GaxError):
|
|
api.sink_create(
|
|
self.PROJECT, self.SINK_NAME, self.FILTER,
|
|
self.DESTINATION_URI)
|
|
|
|
def test_sink_create_conflict(self):
|
|
from gcloud.exceptions import Conflict
|
|
gax_api = _GAXSinksAPI(_create_sink_conflict=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(Conflict):
|
|
api.sink_create(
|
|
self.PROJECT, self.SINK_NAME, self.FILTER,
|
|
self.DESTINATION_URI)
|
|
|
|
def test_sink_create_ok(self):
|
|
from google.logging.v2.logging_config_pb2 import LogSink
|
|
gax_api = _GAXSinksAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.sink_create(
|
|
self.PROJECT, self.SINK_NAME, self.FILTER, self.DESTINATION_URI)
|
|
|
|
parent, sink, options = (
|
|
gax_api._create_sink_called_with)
|
|
self.assertEqual(parent, self.PROJECT_PATH)
|
|
self.assertTrue(isinstance(sink, LogSink))
|
|
self.assertEqual(sink.name, self.SINK_NAME)
|
|
self.assertEqual(sink.filter, self.FILTER)
|
|
self.assertEqual(sink.destination, self.DESTINATION_URI)
|
|
self.assertEqual(options, None)
|
|
|
|
def test_sink_get_error(self):
|
|
from gcloud.exceptions import NotFound
|
|
gax_api = _GAXSinksAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(NotFound):
|
|
api.sink_get(self.PROJECT, self.SINK_NAME)
|
|
|
|
def test_sink_get_miss(self):
|
|
from google.gax.errors import GaxError
|
|
gax_api = _GAXSinksAPI(_random_gax_error=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(GaxError):
|
|
api.sink_get(self.PROJECT, self.SINK_NAME)
|
|
|
|
def test_sink_get_hit(self):
|
|
RESPONSE = {
|
|
'name': self.SINK_PATH,
|
|
'filter': self.FILTER,
|
|
'destination': self.DESTINATION_URI,
|
|
}
|
|
sink_pb = _LogSinkPB(
|
|
self.SINK_PATH, self.DESTINATION_URI, self.FILTER)
|
|
gax_api = _GAXSinksAPI(_get_sink_response=sink_pb)
|
|
api = self._makeOne(gax_api)
|
|
|
|
response = api.sink_get(self.PROJECT, self.SINK_NAME)
|
|
|
|
self.assertEqual(response, RESPONSE)
|
|
|
|
sink_name, options = gax_api._get_sink_called_with
|
|
self.assertEqual(sink_name, self.SINK_PATH)
|
|
self.assertEqual(options, None)
|
|
|
|
def test_sink_update_error(self):
|
|
from google.gax.errors import GaxError
|
|
gax_api = _GAXSinksAPI(_random_gax_error=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(GaxError):
|
|
api.sink_update(
|
|
self.PROJECT, self.SINK_NAME, self.FILTER,
|
|
self.DESTINATION_URI)
|
|
|
|
def test_sink_update_miss(self):
|
|
from gcloud.exceptions import NotFound
|
|
gax_api = _GAXSinksAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(NotFound):
|
|
api.sink_update(
|
|
self.PROJECT, self.SINK_NAME, self.FILTER,
|
|
self.DESTINATION_URI)
|
|
|
|
def test_sink_update_hit(self):
|
|
from google.logging.v2.logging_config_pb2 import LogSink
|
|
response = _LogSinkPB(
|
|
self.SINK_NAME, self.FILTER, self.DESTINATION_URI)
|
|
gax_api = _GAXSinksAPI(_update_sink_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.sink_update(
|
|
self.PROJECT, self.SINK_NAME, self.FILTER, self.DESTINATION_URI)
|
|
|
|
sink_name, sink, options = (
|
|
gax_api._update_sink_called_with)
|
|
self.assertEqual(sink_name, self.SINK_PATH)
|
|
self.assertTrue(isinstance(sink, LogSink))
|
|
self.assertEqual(sink.name, self.SINK_PATH)
|
|
self.assertEqual(sink.filter, self.FILTER)
|
|
self.assertEqual(sink.destination, self.DESTINATION_URI)
|
|
self.assertEqual(options, None)
|
|
|
|
def test_sink_delete_error(self):
|
|
from google.gax.errors import GaxError
|
|
gax_api = _GAXSinksAPI(_random_gax_error=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(GaxError):
|
|
api.sink_delete(self.PROJECT, self.SINK_NAME)
|
|
|
|
def test_sink_delete_miss(self):
|
|
from gcloud.exceptions import NotFound
|
|
gax_api = _GAXSinksAPI(_sink_not_found=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(NotFound):
|
|
api.sink_delete(self.PROJECT, self.SINK_NAME)
|
|
|
|
def test_sink_delete_hit(self):
|
|
gax_api = _GAXSinksAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.sink_delete(self.PROJECT, self.SINK_NAME)
|
|
|
|
sink_name, options = gax_api._delete_sink_called_with
|
|
self.assertEqual(sink_name, self.SINK_PATH)
|
|
self.assertEqual(options, None)
|
|
|
|
|
|
@unittest2.skipUnless(_HAVE_GAX, 'No gax-python')
|
|
class Test_MetricsAPI(_Base, unittest2.TestCase):
|
|
METRIC_NAME = 'metric_name'
|
|
METRIC_PATH = 'projects/%s/metrics/%s' % (_Base.PROJECT, METRIC_NAME)
|
|
DESCRIPTION = 'Description'
|
|
|
|
def _getTargetClass(self):
|
|
from gcloud.logging._gax import _MetricsAPI
|
|
return _MetricsAPI
|
|
|
|
def test_ctor(self):
|
|
gax_api = _GAXMetricsAPI()
|
|
api = self._makeOne(gax_api)
|
|
self.assertTrue(api._gax_api is gax_api)
|
|
|
|
def test_list_metrics_no_paging(self):
|
|
from google.gax import INITIAL_PAGE
|
|
from gcloud._testing import _GAXPageIterator
|
|
TOKEN = 'TOKEN'
|
|
METRICS = [{
|
|
'name': self.METRIC_PATH,
|
|
'filter': self.FILTER,
|
|
'description': self.DESCRIPTION,
|
|
}]
|
|
response = _GAXPageIterator(
|
|
[_LogMetricPB(self.METRIC_PATH, self.DESCRIPTION, self.FILTER)],
|
|
TOKEN)
|
|
gax_api = _GAXMetricsAPI(_list_log_metrics_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
metrics, token = api.list_metrics(self.PROJECT)
|
|
|
|
self.assertEqual(metrics, METRICS)
|
|
self.assertEqual(token, TOKEN)
|
|
|
|
project, page_size, options = gax_api._list_log_metrics_called_with
|
|
self.assertEqual(project, self.PROJECT)
|
|
self.assertEqual(page_size, 0)
|
|
self.assertEqual(options.page_token, INITIAL_PAGE)
|
|
|
|
def test_list_metrics_w_paging(self):
|
|
from gcloud._testing import _GAXPageIterator
|
|
TOKEN = 'TOKEN'
|
|
PAGE_SIZE = 42
|
|
METRICS = [{
|
|
'name': self.METRIC_PATH,
|
|
'filter': self.FILTER,
|
|
'description': self.DESCRIPTION,
|
|
}]
|
|
response = _GAXPageIterator(
|
|
[_LogMetricPB(self.METRIC_PATH, self.DESCRIPTION, self.FILTER)],
|
|
None)
|
|
gax_api = _GAXMetricsAPI(_list_log_metrics_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
metrics, token = api.list_metrics(
|
|
self.PROJECT, page_size=PAGE_SIZE, page_token=TOKEN)
|
|
|
|
self.assertEqual(metrics, METRICS)
|
|
self.assertEqual(token, None)
|
|
|
|
project, page_size, options = gax_api._list_log_metrics_called_with
|
|
self.assertEqual(project, self.PROJECT)
|
|
self.assertEqual(page_size, PAGE_SIZE)
|
|
self.assertEqual(options.page_token, TOKEN)
|
|
|
|
def test_metric_create_error(self):
|
|
from google.gax.errors import GaxError
|
|
gax_api = _GAXMetricsAPI(_random_gax_error=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(GaxError):
|
|
api.metric_create(
|
|
self.PROJECT, self.METRIC_NAME, self.FILTER,
|
|
self.DESCRIPTION)
|
|
|
|
def test_metric_create_conflict(self):
|
|
from gcloud.exceptions import Conflict
|
|
gax_api = _GAXMetricsAPI(_create_log_metric_conflict=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(Conflict):
|
|
api.metric_create(
|
|
self.PROJECT, self.METRIC_NAME, self.FILTER,
|
|
self.DESCRIPTION)
|
|
|
|
def test_metric_create_ok(self):
|
|
from google.logging.v2.logging_metrics_pb2 import LogMetric
|
|
gax_api = _GAXMetricsAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.metric_create(
|
|
self.PROJECT, self.METRIC_NAME, self.FILTER, self.DESCRIPTION)
|
|
|
|
parent, metric, options = (
|
|
gax_api._create_log_metric_called_with)
|
|
self.assertEqual(parent, self.PROJECT_PATH)
|
|
self.assertTrue(isinstance(metric, LogMetric))
|
|
self.assertEqual(metric.name, self.METRIC_NAME)
|
|
self.assertEqual(metric.filter, self.FILTER)
|
|
self.assertEqual(metric.description, self.DESCRIPTION)
|
|
self.assertEqual(options, None)
|
|
|
|
def test_metric_get_error(self):
|
|
from gcloud.exceptions import NotFound
|
|
gax_api = _GAXMetricsAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(NotFound):
|
|
api.metric_get(self.PROJECT, self.METRIC_NAME)
|
|
|
|
def test_metric_get_miss(self):
|
|
from google.gax.errors import GaxError
|
|
gax_api = _GAXMetricsAPI(_random_gax_error=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(GaxError):
|
|
api.metric_get(self.PROJECT, self.METRIC_NAME)
|
|
|
|
def test_metric_get_hit(self):
|
|
RESPONSE = {
|
|
'name': self.METRIC_PATH,
|
|
'filter': self.FILTER,
|
|
'description': self.DESCRIPTION,
|
|
}
|
|
metric_pb = _LogMetricPB(
|
|
self.METRIC_PATH, self.DESCRIPTION, self.FILTER)
|
|
gax_api = _GAXMetricsAPI(_get_log_metric_response=metric_pb)
|
|
api = self._makeOne(gax_api)
|
|
|
|
response = api.metric_get(self.PROJECT, self.METRIC_NAME)
|
|
|
|
self.assertEqual(response, RESPONSE)
|
|
|
|
metric_name, options = gax_api._get_log_metric_called_with
|
|
self.assertEqual(metric_name, self.METRIC_PATH)
|
|
self.assertEqual(options, None)
|
|
|
|
def test_metric_update_error(self):
|
|
from google.gax.errors import GaxError
|
|
gax_api = _GAXMetricsAPI(_random_gax_error=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(GaxError):
|
|
api.metric_update(
|
|
self.PROJECT, self.METRIC_NAME, self.FILTER,
|
|
self.DESCRIPTION)
|
|
|
|
def test_metric_update_miss(self):
|
|
from gcloud.exceptions import NotFound
|
|
gax_api = _GAXMetricsAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(NotFound):
|
|
api.metric_update(
|
|
self.PROJECT, self.METRIC_NAME, self.FILTER,
|
|
self.DESCRIPTION)
|
|
|
|
def test_metric_update_hit(self):
|
|
from google.logging.v2.logging_metrics_pb2 import LogMetric
|
|
response = _LogMetricPB(
|
|
self.METRIC_NAME, self.FILTER, self.DESCRIPTION)
|
|
gax_api = _GAXMetricsAPI(_update_log_metric_response=response)
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.metric_update(
|
|
self.PROJECT, self.METRIC_NAME, self.FILTER, self.DESCRIPTION)
|
|
|
|
metric_name, metric, options = (
|
|
gax_api._update_log_metric_called_with)
|
|
self.assertEqual(metric_name, self.METRIC_PATH)
|
|
self.assertTrue(isinstance(metric, LogMetric))
|
|
self.assertEqual(metric.name, self.METRIC_PATH)
|
|
self.assertEqual(metric.filter, self.FILTER)
|
|
self.assertEqual(metric.description, self.DESCRIPTION)
|
|
self.assertEqual(options, None)
|
|
|
|
def test_metric_delete_error(self):
|
|
from google.gax.errors import GaxError
|
|
gax_api = _GAXMetricsAPI(_random_gax_error=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(GaxError):
|
|
api.metric_delete(self.PROJECT, self.METRIC_NAME)
|
|
|
|
def test_metric_delete_miss(self):
|
|
from gcloud.exceptions import NotFound
|
|
gax_api = _GAXMetricsAPI(_log_metric_not_found=True)
|
|
api = self._makeOne(gax_api)
|
|
|
|
with self.assertRaises(NotFound):
|
|
api.metric_delete(self.PROJECT, self.METRIC_NAME)
|
|
|
|
def test_metric_delete_hit(self):
|
|
gax_api = _GAXMetricsAPI()
|
|
api = self._makeOne(gax_api)
|
|
|
|
api.metric_delete(self.PROJECT, self.METRIC_NAME)
|
|
|
|
metric_name, options = gax_api._delete_log_metric_called_with
|
|
self.assertEqual(metric_name, self.METRIC_PATH)
|
|
self.assertEqual(options, None)
|
|
|
|
|
|
class _GAXBaseAPI(object):
|
|
|
|
_random_gax_error = False
|
|
|
|
def __init__(self, **kw):
|
|
self.__dict__.update(kw)
|
|
|
|
def _make_grpc_error(self, status_code):
|
|
from grpc.framework.interfaces.face.face import AbortionError
|
|
|
|
class _DummyException(AbortionError):
|
|
code = status_code
|
|
|
|
def __init__(self):
|
|
pass
|
|
|
|
return _DummyException()
|
|
|
|
def _make_grpc_not_found(self):
|
|
from grpc.beta.interfaces import StatusCode
|
|
return self._make_grpc_error(StatusCode.NOT_FOUND)
|
|
|
|
def _make_grpc_failed_precondition(self):
|
|
from grpc.beta.interfaces import StatusCode
|
|
return self._make_grpc_error(StatusCode.FAILED_PRECONDITION)
|
|
|
|
|
|
class _GAXLoggingAPI(_GAXBaseAPI):
|
|
|
|
def list_log_entries(
|
|
self, projects, filter_, order_by, page_size, options):
|
|
self._list_log_entries_called_with = (
|
|
projects, filter_, order_by, page_size, options)
|
|
return self._list_log_entries_response
|
|
|
|
def write_log_entries(self, entries, log_name, resource, labels,
|
|
partial_success, options):
|
|
self._write_log_entries_called_with = (
|
|
entries, log_name, resource, labels, partial_success, options)
|
|
|
|
def delete_log(self, log_name, options):
|
|
self._delete_log_called_with = log_name, options
|
|
|
|
|
|
class _GAXSinksAPI(_GAXBaseAPI):
|
|
|
|
_create_sink_conflict = False
|
|
_sink_not_found = False
|
|
|
|
def list_sinks(self, parent, page_size, options):
|
|
self._list_sinks_called_with = parent, page_size, options
|
|
return self._list_sinks_response
|
|
|
|
def create_sink(self, parent, sink, options):
|
|
from google.gax.errors import GaxError
|
|
self._create_sink_called_with = parent, sink, options
|
|
if self._random_gax_error:
|
|
raise GaxError('error')
|
|
if self._create_sink_conflict:
|
|
raise GaxError('conflict', self._make_grpc_failed_precondition())
|
|
|
|
def get_sink(self, sink_name, options):
|
|
from google.gax.errors import GaxError
|
|
self._get_sink_called_with = sink_name, options
|
|
if self._random_gax_error:
|
|
raise GaxError('error')
|
|
try:
|
|
return self._get_sink_response
|
|
except AttributeError:
|
|
raise GaxError('notfound', self._make_grpc_not_found())
|
|
|
|
def update_sink(self, sink_name, sink, options=None):
|
|
from google.gax.errors import GaxError
|
|
self._update_sink_called_with = sink_name, sink, options
|
|
if self._random_gax_error:
|
|
raise GaxError('error')
|
|
try:
|
|
return self._update_sink_response
|
|
except AttributeError:
|
|
raise GaxError('notfound', self._make_grpc_not_found())
|
|
|
|
def delete_sink(self, sink_name, options=None):
|
|
from google.gax.errors import GaxError
|
|
self._delete_sink_called_with = sink_name, options
|
|
if self._random_gax_error:
|
|
raise GaxError('error')
|
|
if self._sink_not_found:
|
|
raise GaxError('notfound', self._make_grpc_not_found())
|
|
|
|
|
|
class _GAXMetricsAPI(_GAXBaseAPI):
|
|
|
|
_create_log_metric_conflict = False
|
|
_log_metric_not_found = False
|
|
|
|
def list_log_metrics(self, parent, page_size, options):
|
|
self._list_log_metrics_called_with = parent, page_size, options
|
|
return self._list_log_metrics_response
|
|
|
|
def create_log_metric(self, parent, metric, options):
|
|
from google.gax.errors import GaxError
|
|
self._create_log_metric_called_with = parent, metric, options
|
|
if self._random_gax_error:
|
|
raise GaxError('error')
|
|
if self._create_log_metric_conflict:
|
|
raise GaxError('conflict', self._make_grpc_failed_precondition())
|
|
|
|
def get_log_metric(self, metric_name, options):
|
|
from google.gax.errors import GaxError
|
|
self._get_log_metric_called_with = metric_name, options
|
|
if self._random_gax_error:
|
|
raise GaxError('error')
|
|
try:
|
|
return self._get_log_metric_response
|
|
except AttributeError:
|
|
raise GaxError('notfound', self._make_grpc_not_found())
|
|
|
|
def update_log_metric(self, metric_name, metric, options=None):
|
|
from google.gax.errors import GaxError
|
|
self._update_log_metric_called_with = metric_name, metric, options
|
|
if self._random_gax_error:
|
|
raise GaxError('error')
|
|
try:
|
|
return self._update_log_metric_response
|
|
except AttributeError:
|
|
raise GaxError('notfound', self._make_grpc_not_found())
|
|
|
|
def delete_log_metric(self, metric_name, options=None):
|
|
from google.gax.errors import GaxError
|
|
self._delete_log_metric_called_with = metric_name, options
|
|
if self._random_gax_error:
|
|
raise GaxError('error')
|
|
if self._log_metric_not_found:
|
|
raise GaxError('notfound', self._make_grpc_not_found())
|
|
|
|
|
|
class _HTTPRequestPB(object):
|
|
|
|
request_url = 'http://example.com/requested'
|
|
request_method = 'GET'
|
|
status = 200
|
|
referer = 'http://example.com/referer'
|
|
user_agent = 'AGENT'
|
|
cache_hit = False
|
|
request_size = 256
|
|
response_size = 1024
|
|
remote_ip = '1.2.3.4'
|
|
|
|
|
|
class _LogEntryOperationPB(object):
|
|
|
|
producer = 'PRODUCER'
|
|
first = last = False
|
|
id = 'OPID'
|
|
|
|
|
|
class _ResourcePB(object):
|
|
|
|
def __init__(self, type_='global', **labels):
|
|
self.type = type_
|
|
self.labels = labels
|
|
|
|
|
|
class _LogEntryPB(object):
|
|
|
|
severity = 'DEFAULT'
|
|
http_request = operation = insert_id = None
|
|
text_payload = json_payload = proto_payload = None
|
|
|
|
def __init__(self, log_name, **kw):
|
|
self.log_name = log_name
|
|
self.resource = _ResourcePB()
|
|
self.timestamp = self._make_timestamp()
|
|
self.labels = kw.pop('labels', {})
|
|
self.__dict__.update(kw)
|
|
|
|
@staticmethod
|
|
def _make_timestamp():
|
|
from datetime import datetime
|
|
from gcloud._helpers import UTC
|
|
from gcloud._helpers import _datetime_to_pb_timestamp
|
|
NOW = datetime.utcnow().replace(tzinfo=UTC)
|
|
return _datetime_to_pb_timestamp(NOW)
|
|
|
|
|
|
class _LogSinkPB(object):
|
|
|
|
def __init__(self, name, destination, filter_):
|
|
self.name = name
|
|
self.destination = destination
|
|
self.filter = filter_
|
|
|
|
|
|
class _LogMetricPB(object):
|
|
|
|
def __init__(self, name, description, filter_):
|
|
self.name = name
|
|
self.description = description
|
|
self.filter = filter_
|