# Copyright 2016 Google LLC. 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. """Client deploy info. Library for parsing client_deploy.yaml files and working with these in memory. """ # WARNING: This file is externally viewable by our users. All comments from # this file will be stripped. The docstrings will NOT. Do not put sensitive # information in docstrings. If you must communicate internal information in # this source file, please place them in comments only. from __future__ import absolute_import import os # pylint: disable=g-import-not-at-top if os.environ.get('APPENGINE_RUNTIME') == 'python27': from google.appengine.api import appinfo from google.appengine.api import validation from google.appengine.api import yaml_builder from google.appengine.api import yaml_listener from google.appengine.api import yaml_object else: from googlecloudsdk.appengine.api import appinfo from googlecloudsdk.appengine.api import validation from googlecloudsdk.appengine.api import yaml_builder from googlecloudsdk.appengine.api import yaml_listener from googlecloudsdk.appengine.api import yaml_object # pylint: enable=g-import-not-at-top RUNTIME = 'runtime' START_TIME_USEC = 'start_time_usec' END_TIME_USEC = 'end_time_usec' REQUESTS = 'requests' SUCCESS = 'success' PATH = 'path' RESPONSE_CODE = 'response_code' REQUEST_SIZE_BYTES = 'request_size_bytes' SDK_VERSION = 'sdk_version' class Request(validation.Validated): """A Request describes a single http request within a deployment attempt.""" ATTRIBUTES = { PATH: validation.TYPE_STR, RESPONSE_CODE: validation.Range(100, 599), START_TIME_USEC: validation.TYPE_LONG, END_TIME_USEC: validation.TYPE_LONG, REQUEST_SIZE_BYTES: validation.TYPE_LONG, } class ClientDeployInfoExternal(validation.Validated): """Describes the format of a client_deployinfo.yaml file.""" ATTRIBUTES = { RUNTIME: appinfo.RUNTIME_RE_STRING, START_TIME_USEC: validation.TYPE_LONG, END_TIME_USEC: validation.TYPE_LONG, REQUESTS: validation.Optional(validation.Repeated(Request)), SUCCESS: validation.TYPE_BOOL, SDK_VERSION: validation.Optional(validation.TYPE_STR) } class Error(Exception): """Base ClientDeployInfo Exception type.""" class EmptyYaml(Error): """Tried to load an empty yaml.""" class MultipleClientDeployInfo(Error): """Tried to load a yaml containing multiple client deploy info definitions.""" def LoadSingleClientDeployInfo(client_deploy_info): """Returns a ClientDeployInfoExternal from a deploy_info.yaml file or string. Args: client_deploy_info: The contents of a client_deploy_info.yaml file or string, or an open file object. Returns: A ClientDeployInfoExternal instance which represents the contents of the parsed yaml. Raises: EmptyYaml: when there are no documents in yaml. MultipleClientDeployInfo: when there are multiple documents in yaml. yaml_errors.EventError: when an error occurs while parsing the yaml. """ builder = yaml_object.ObjectBuilder(ClientDeployInfoExternal) handler = yaml_builder.BuilderHandler(builder) listener = yaml_listener.EventListener(handler) listener.Parse(client_deploy_info) parsed_yaml = handler.GetResults() if not parsed_yaml: raise EmptyYaml() if len(parsed_yaml) > 1: raise MultipleClientDeployInfo() return parsed_yaml[0]