class Property(validation.Validated): """Representation for a property of an index as it appears in YAML. Attributes (all in string form): name: Name of attribute to sort by. direction: Direction of sort. mode: How the property is indexed. Either 'geospatial' or None (unspecified). """ ATTRIBUTES = { 'name': validation.Type(str, convert=False), 'direction': validation.Optional([('asc', ('ascending', )), ('desc', ('descending', ))]), 'mode': validation.Optional(['geospatial']) } def IsAscending(self): # TODO(user): raise an internal consistency assertion failure # if this Property has a "mode" (or actually if *any* Property in # the containing Index has a "mode"), because in that case it doesn't # make sense to ask for the direction. # # TODO(user): shouldn't we also check for 'descending' here? return self.direction != 'desc' def CheckInitialized(self): if self.direction is not None and self.mode is not None: raise validation.ValidationError( 'direction and mode are mutually exclusive') super(Property, self).CheckInitialized()
class CronInfoExternal(validation.Validated): """CronInfoExternal describes all cron entries for an application.""" ATTRIBUTES = { appinfo.APPLICATION: validation.Optional(appinfo.APPLICATION_RE_STRING), CRON: validation.Optional(validation.Repeated(CronEntry)) }
class DispatchEntry(validation.Validated): """A Dispatch entry describes a mapping from a URL pattern to a module.""" ATTRIBUTES = { URL: DispatchEntryURLValidator(), MODULE: validation.Optional(appinfo.MODULE_ID_RE_STRING), SERVICE: validation.Optional(appinfo.MODULE_ID_RE_STRING) }
class DosInfoExternal(validation.Validated): """Describes the format of a dos.yaml file.""" ATTRIBUTES = { appinfo.APPLICATION: validation.Optional(appinfo.APPLICATION_RE_STRING), BLACKLIST: validation.Optional(validation.Repeated(BlacklistEntry)), }
class PagespeedEntry(validation.Validated): """Describes the format of a pagespeed configuration from a yaml file. URL blacklist entries are patterns (with '?' and '*' as wildcards). Any URLs that match a pattern on the blacklist will not be optimized by PageSpeed. Rewriter names are strings (like 'CombineCss' or 'RemoveComments') describing individual PageSpeed rewriters. A full list of valid rewriter names can be found in the PageSpeed documentation. The domains-to-rewrite list is a whitelist of domain name patterns with '*' as a wildcard, optionally starting with 'http://' or 'https://'. If no protocol is given, 'http://' is assumed. A resource will only be rewritten if it is on the same domain as the HTML that references it, or if its domain is on the domains-to-rewrite list. """ ATTRIBUTES = { URL_BLACKLIST: validation.Optional( validation.Repeated(validation.Regex(_URL_BLACKLIST_REGEX))), ENABLED_REWRITERS: validation.Optional( validation.Repeated(validation.Regex(_REWRITER_NAME_REGEX))), DISABLED_REWRITERS: validation.Optional( validation.Repeated(validation.Regex(_REWRITER_NAME_REGEX))), DOMAINS_TO_REWRITE: validation.Optional( validation.Repeated(validation.Regex(_DOMAINS_TO_REWRITE_REGEX))), }
class QueueInfoExternal(validation.Validated): """Describes all of the queue entries for an application.""" ATTRIBUTES = { appinfo.APPLICATION: validation.Optional(appinfo.APPLICATION_RE_STRING), TOTAL_STORAGE_LIMIT: validation.Optional(_TOTAL_STORAGE_LIMIT_REGEX), QUEUE: validation.Optional(validation.Repeated(QueueEntry)), }
class RetryParameters(validation.Validated): """Specifies the retry parameters for a single task queue.""" ATTRIBUTES = { TASK_RETRY_LIMIT: validation.Optional(validation.TYPE_INT), TASK_AGE_LIMIT: validation.Optional(validation.TimeValue()), MIN_BACKOFF_SECONDS: validation.Optional(validation.TYPE_FLOAT), MAX_BACKOFF_SECONDS: validation.Optional(validation.TYPE_FLOAT), MAX_DOUBLINGS: validation.Optional(validation.TYPE_INT), }
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 CronEntry(validation.Validated): """A cron entry describes a single cron job.""" ATTRIBUTES = { URL: _URL_REGEX, SCHEDULE: GrocValidator(), TIMEZONE: TimezoneValidator(), DESCRIPTION: validation.Optional(_DESCRIPTION_REGEX), RETRY_PARAMETERS: validation.Optional(RetryParameters), TARGET: validation.Optional(_VERSION_REGEX), }
class IndexDefinitions(validation.Validated): """Top level for index definition file. Attributes: indexes: List of Index definitions. """ ATTRIBUTES = { appinfo.APPLICATION: validation.Optional(appinfo.APPLICATION_RE_STRING), 'indexes': validation.Optional(validation.Repeated(Index)), }
class RetryParameters(validation.Validated): """Retry parameters for a single cron job.""" ATTRIBUTES = { JOB_RETRY_LIMIT: validation.Optional( validation.Range(0, None, range_type=int)), JOB_AGE_LIMIT: validation.Optional(validation.TimeValue()), MIN_BACKOFF_SECONDS: validation.Optional( validation.Range(0.0, None, range_type=float)), MAX_BACKOFF_SECONDS: validation.Optional( validation.Range(0.0, None, range_type=float)), MAX_DOUBLINGS: validation.Optional( validation.Range(0, None, range_type=int)), }
class Index(validation.Validated): """Individual index definition. Order of the properties determines a given index's sort priority. Attributes: kind: Datastore kind that index belongs to. ancestors: Include ancestors in index. properties: Properties to be included. """ ATTRIBUTES = { 'kind': validation.Type(str, convert=False), 'ancestor': validation.Type(bool, convert=False, default=False), 'properties': validation.Optional(validation.Repeated(Property)), } def CheckInitialized(self): self._Normalize() super(Index, self).CheckInitialized() def _Normalize(self): if self.properties is None: return is_geo = any(x.mode == 'geospatial' for x in self.properties) for prop in self.properties: if is_geo: if prop.direction is not None: raise validation.ValidationError( 'direction not supported in a geospatial index') else: # Normalize the property object by making direction explicit if prop.IsAscending(): prop.direction = 'asc'
class QueueEntry(validation.Validated): """A queue entry describes a single task queue.""" ATTRIBUTES = { NAME: _NAME_REGEX, RATE: validation.Optional(_RATE_REGEX), MODE: validation.Optional(_MODE_REGEX), BUCKET_SIZE: validation.Optional(validation.TYPE_INT), MAX_CONCURRENT_REQUESTS: validation.Optional(validation.TYPE_INT), RETRY_PARAMETERS: validation.Optional(RetryParameters), ACL: validation.Optional(validation.Repeated(Acl)), # and version. TARGET: validation.Optional(_VERSION_REGEX), }
class QueueEntry(validation.Validated): """Describes a single task queue.""" ATTRIBUTES = { NAME: _NAME_REGEX, RATE: validation.Optional(_RATE_REGEX), MODE: validation.Optional(_MODE_REGEX), BUCKET_SIZE: validation.Optional(validation.TYPE_INT), MAX_CONCURRENT_REQUESTS: validation.Optional(validation.TYPE_INT), RETRY_PARAMETERS: validation.Optional(RetryParameters), ACL: validation.Optional(validation.Repeated(Acl)), # TODO(user): http://b/issue?id=6231287 to split this out to engine # and version. TARGET: validation.Optional(_VERSION_REGEX), }
class Acl(validation.Validated): """Controls the access control list for a single task queue.""" ATTRIBUTES = { USER_EMAIL: validation.Optional(validation.TYPE_STR), WRITER_EMAIL: validation.Optional(validation.TYPE_STR), }
class DispatchInfoExternal(validation.Validated): """Describes the format of a dispatch.yaml file.""" ATTRIBUTES = { APPLICATION: validation.Optional(appinfo.APPLICATION_RE_STRING), DISPATCH: validation.Optional(validation.Repeated(DispatchEntry)), }
class BlacklistEntry(validation.Validated): """A blacklist entry describes a blocked IP address or subnet.""" ATTRIBUTES = { DESCRIPTION: validation.Optional(_DESCRIPTION_REGEX), SUBNET: SubnetValidator(), }
# Copyright 2017 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 module to modify appinfo during import.""" from googlecloudsdk.third_party.appengine.api import appinfo from googlecloudsdk.third_party.appengine.api import validation # TODO(b/37542869): Get rid of this hack once the server can correct accept # runtime names that start with gs://. Until then, override the regex for # validation in gcloud. _RUNTIME_RE_STRING_OVERRIDE = (r'((gs://[a-z0-9\-\._/]+)|({orig}))'.format( orig=appinfo.RUNTIME_RE_STRING)) appinfo.AppInfoExternal.ATTRIBUTES[appinfo.RUNTIME] = ( validation.Optional(_RUNTIME_RE_STRING_OVERRIDE))