def ProcessBackendNode(self, node): """Processes XML nodes labeled 'backend' into a Backends object.""" tag = xml_parser_utils.GetTag(node) if tag != 'backend': self.errors.append('Unrecognized node: <%s>' % tag) return backend = Backend() name = xml_parser_utils.GetAttribute(node, 'name') if not name: self.errors.append('All backends must have names') backend.name = '-' else: backend.name = name instance_class = xml_parser_utils.GetChildNodeText(node, 'class') if instance_class: backend.instance_class = instance_class instances = xml_parser_utils.GetChildNodeText(node, 'instances') if instances: try: backend.instances = int(instances) except ValueError: self.errors.append( '<instances> must be an integer (bad value %s) in backend %s' % (instances, backend.name)) max_concurrent_requests = xml_parser_utils.GetChildNodeText( node, 'max-concurrent-requests') if max_concurrent_requests: try: backend.max_concurrent_requests = int(max_concurrent_requests) except ValueError: self.errors.append( '<max-concurrent-requests> must be an integer ' '(bad value %s) in backend %s' % (max_concurrent_requests, backend.name)) options_node = xml_parser_utils.GetChild(node, 'options') if options_node is not None: for sub_node in options_node.getchildren(): tag = xml_parser_utils.GetTag(sub_node) if tag not in ('fail-fast', 'dynamic', 'public'): self.errors.append( '<options> only supports values fail-fast, ' 'dynamic, and public (bad value %s) in backend %s' % (tag, backend.name)) continue tag = tag.replace('-', '') if xml_parser_utils.BooleanValue(sub_node.text): backend.options.add(tag) else: if tag in backend.options: backend.options.remove(tag) self.backends.append(backend)
def ProcessCronNode(self, node): """Processes XML <cron> nodes into Cron objects. The following information is parsed out: description: Describing the purpose of the cron job. url: The location of the script. schedule: Written in groc; the schedule according to which the job is executed. timezone: The timezone that the schedule runs in. target: Which version of the app this applies to. Args: node: <cron> XML node in cron.xml. """ tag = xml_parser_utils.GetTag(node) if tag != 'cron': self.errors.append('Unrecognized node: <%s>' % tag) return cron = Cron() cron.url = xml_parser_utils.GetChildNodeText(node, 'url') cron.timezone = xml_parser_utils.GetChildNodeText(node, 'timezone') cron.target = xml_parser_utils.GetChildNodeText(node, 'target') cron.description = xml_parser_utils.GetChildNodeText( node, 'description') cron.schedule = xml_parser_utils.GetChildNodeText(node, 'schedule') validation_error = self._ValidateCronEntry(cron) if validation_error: self.errors.append(validation_error) else: self.crons.append(cron)
def ProcessVmHealthCheckNode(self, node): vm_health_check = VmHealthCheck() for child in node: tag = xml_parser_utils.GetTag(child) if tag == 'enable-health-check': vm_health_check.enable_health_check = ( xml_parser_utils.BooleanValue(child.text)) elif tag == 'host': vm_health_check.host = child.text elif tag in ('check-interval-sec', 'healthy-threshold', 'restart-threshold', 'timeout-sec', 'unhealthy-threshold'): text = child.text or '' try: value = self._PositiveInt(text) setattr(vm_health_check, tag.replace('-', '_'), value) except ValueError: self.errors.append( 'value for %s must be a positive integer: "%s"' % (tag, text)) else: self.errors.append( 'unrecognized element within <vm-health-check>: <%s>' % tag) self.app_engine_web_xml.vm_health_check = vm_health_check
def ProcessXml(self, xml_str): """Parses XML string and returns object representation of relevant info. Args: xml_str: The XML string. Returns: A list of Index objects containing information about datastore indexes from the XML. Raises: AppEngineConfigException: In case of malformed XML or illegal inputs. """ try: self.indexes = [] self.errors = [] xml_root = ElementTree.fromstring(xml_str) if xml_parser_utils.GetTag(xml_root) != 'datastore-indexes': raise AppEngineConfigException( 'Root tag must be <datastore-indexes>') for child in xml_root.getchildren(): self.ProcessIndexNode(child) if self.errors: raise AppEngineConfigException('\n'.join(self.errors)) return self.indexes except ElementTree.ParseError: raise AppEngineConfigException('Bad input -- not valid XML')
def ProcessBlacklistNode(self, node): """Processes XML <blacklist> nodes into BlacklistEntry objects. The following information is parsed out: subnet: The IP, in CIDR notation. description: (optional) If there are no errors, the data is loaded into a BlackListEntry object and added to a list. Upon error, a description of the error is added to a list and the method terminates. Args: node: <blacklist> XML node in dos.xml. """ tag = xml_parser_utils.GetTag(node) if tag != 'blacklist': self.errors.append('Unrecognized node: <%s>' % tag) return entry = BlacklistEntry() entry.subnet = xml_parser_utils.GetChildNodeText(node, 'subnet') entry.description = xml_parser_utils.GetChildNodeText( node, 'description') validation = self._ValidateEntry(entry) if validation: self.errors.append(validation) return self.blacklist_entries.append(entry)
def ProcessXml(self, xml_str): """Parses XML string and returns object representation of relevant info. Args: xml_str: The XML string. Returns: A QueueXml object containing information about task queue specifications from the XML. Raises: AppEngineConfigException: In case of malformed XML or illegal inputs. """ try: self.errors = [] xml_root = ElementTree.fromstring(xml_str) if xml_parser_utils.GetTag(xml_root) != 'queue-entries': raise AppEngineConfigException( 'Root tag must be <queue-entries>') self.queue_xml = QueueXml() self.queue_xml.queues = [] self.queue_xml.total_storage_limit = xml_parser_utils.GetChildNodeText( xml_root, 'total-storage-limit') for child in xml_parser_utils.GetNodes(xml_root, 'queue'): self.ProcessQueueNode(child) if self.errors: raise AppEngineConfigException('\n'.join(self.errors)) return self.queue_xml except ElementTree.ParseError as e: raise AppEngineConfigException('Bad input -- not valid XML: %s' % e)
def ProcessDispatchNode(self, node): """Processes XML <dispatch> nodes into DispatchEntry objects. The following information is parsed out: url: The URL or URL pattern to route. module: The module to route it to. If there are no errors, the data is loaded into a DispatchEntry object and added to a list. Upon error, a description of the error is added to a list and the method terminates. Args: node: <dispatch> XML node in dos.xml. """ tag = xml_parser_utils.GetTag(node) if tag != 'dispatch': self.errors.append('Unrecognized node: <%s>' % tag) return entry = DispatchEntry() entry.url = xml_parser_utils.GetChildNodeText(node, 'url') entry.module = xml_parser_utils.GetChildNodeText(node, 'module') validation = self._ValidateEntry(entry) if validation: self.errors.append(validation) return self.dispatch_entries.append(entry)
def ProcessResourcesNode(self, node): resources = Resources() for child in node: tag = xml_parser_utils.GetTag(child) if tag in ('cpu', 'memory-gb', 'disk-size-gb'): text = child.text or '' setattr(resources, tag.replace('-', '_'), text) else: self.errors.append( 'unrecognized element within <resources>: <%s>' % tag) self.app_engine_web_xml.resources = resources
def ProcessSecondLevelNode(self, node): element_name = xml_parser_utils.GetTag(node) if element_name in self._IGNORED_NODES: return camel_case_name = ''.join(part.title() for part in element_name.split('-')) method_name = 'Process%sNode' % camel_case_name if (hasattr(self, method_name) and method_name != 'ProcessSecondLevelNode'): getattr(self, method_name)(node) else: logging.warning('Second-level tag not recognized: %s', element_name)
def ProcessSecondLevelNode(self, node): element_name = xml_parser_utils.GetTag(node) if element_name in ['servlet', 'filter', 'display-name', 'taglib']: return camel_case_name = ''.join(part.title() for part in element_name.split('-')) method_name = 'Process%sNode' % camel_case_name if (hasattr(self, method_name) and method_name is not 'ProcessSecondLevelNode'): getattr(self, method_name)(node) else: self.errors.append('Second-level tag not recognized: %s' % element_name)
def ProcessNetworkNode(self, node): network = Network() for child in node: tag = xml_parser_utils.GetTag(child) if tag == 'instance-tag': text = child.text or '' setattr(network, tag.replace('-', '_'), text) elif tag == 'forwarded-port': if not hasattr(network, 'forwarded_ports'): network.forwarded_ports = [] network.forwarded_ports.append(child.text or '') else: self.errors.append( 'unrecognized element within <network>: <%s>' % tag) self.app_engine_web_xml.network = network
def ProcessStagingNode(self, node): """Process the local staging config node.""" staging = Staging() for child in node: tag = xml_parser_utils.GetTag(child) text = child.text or '' if tag in ('jar-splitting-excludes', 'compile-encoding'): setattr(staging, tag.replace('-', '_'), text) elif tag in ('enable-jar-splitting', 'disable-jar-jsps', 'enable-jar-classes', 'delete-jsps'): value = xml_parser_utils.BooleanValue(text) setattr(staging, tag.replace('-', '_'), value) else: self.errors.append( 'unrecognized element within <staging>: <%s>' % tag) self.app_engine_web_xml.staging = staging
def ProcessChildNode(self, child_node): """Processes second-level nodes one by one. According to the tag of the node passed in, processes it a certain way. Args: child_node: a "second-level" node in the appengine-web.xml tree Raises: AppEngineConfigException - in case tag is not recognized. """ element_name = xml_parser_utils.GetTag(child_node) camel_case_name = ''.join(part.title() for part in element_name.split('-')) method_name = 'Process%sNode' % camel_case_name if hasattr(self, method_name) and method_name is not 'ProcessChildNode': getattr(self, method_name)(child_node) else: self.errors.append('Second-level tag not recognized: <%s>' % element_name)
def ProcessLivenessCheckNode(self, node): """Processing a liveness check node.""" liveness_check = LivenessCheck() for child in node: tag = xml_parser_utils.GetTag(child) if tag in ('host', 'path'): setattr(liveness_check, tag, child.text) elif tag in ('check-interval-sec', 'success-threshold', 'initial-delay-sec', 'timeout-sec', 'failure-threshold'): text = child.text or '' try: value = self._PositiveInt(text) setattr(liveness_check, tag.replace('-', '_'), value) except ValueError: self.errors.append('value for %s must be a positive integer: "%s"' % (tag, text)) else: self.errors.append( 'unrecognized element within <liveness-check>: <%s>' % tag) self.app_engine_web_xml.liveness_check = liveness_check
def ProcessIndexNode(self, node): """Processes XML <datastore-index> nodes into Index objects. The following information is parsed out: kind: specifies the kind of entities to index. ancestor: true if the index supports queries that filter by ancestor-key to constraint results to a single entity group. property: represents the entity properties to index, with a name and direction attribute. Args: node: <datastore-index> XML node in datastore-indexes.xml. """ tag = xml_parser_utils.GetTag(node) if tag != 'datastore-index': self.errors.append('Unrecognized node: <%s>' % tag) return index = Index() index.kind = xml_parser_utils.GetAttribute(node, 'kind') if not index.kind: self.errors.append(MISSING_KIND) index.ancestor = xml_parser_utils.BooleanValue( xml_parser_utils.GetAttribute(node, 'ancestor')) index.properties = OrderedDict() for property_node in xml_parser_utils.GetNodes(node, 'property'): name = xml_parser_utils.GetAttribute(property_node, 'name') if not name: self.errors.append(NAME_MISSING % index.kind) continue direction = (xml_parser_utils.GetAttribute(property_node, 'direction') or 'asc') if direction not in ('asc', 'desc'): self.errors.append(BAD_DIRECTION % direction) continue index.properties[name] = direction self.indexes.append(index)