def get_artifact(self, params): host, prop, *rest = params location = None remove = None if len(rest) == 1: location = rest[0] if len(rest) == 2: location, remove = rest if host == OperationHost.HOST.value: raise DataError("HOST is not yet supported in opera.") if host != OperationHost.SELF.value: raise DataError( "Artifact host should be set to '{}' which is the only valid value. This is needed to indicate that " "the artifact is referenced locally from something in the node itself. " "Was: {}".format(OperationHost.SELF.value, host)) if location == "LOCAL_FILE": raise DataError( "Location get_artifact property is not yet supported in opera." ) if remove: raise DataError( "Remove get_artifact property artifacts is not yet supported in opera." ) if prop in self.artifacts: self.artifacts[prop].eval(self, prop) return Path(self.artifacts[prop].data).name else: raise DataError("Cannot find artifact '{}'.".format(prop))
def get_artifact(self, params): host, prop, *rest = params location = None remove = None if len(rest) == 1: location = rest[0] if len(rest) == 2: location, remove = rest if host != "SELF": raise DataError( "Accessing non-local stuff is bad. Fix your service template.") if host == "HOST": raise DataError("HOST is not yet supported in opera.") if location == "LOCAL_FILE": raise DataError("Location get_artifact property is " "not yet supported in opera.") if remove: raise DataError("Remove get_artifact property artifacts is " "not yet supported in opera.") if prop in self.artifacts: self.artifacts[prop].eval(self, prop) return Path(self.artifacts[prop].data).name else: raise DataError("Cannot find artifact '{}'.".format(prop))
def get_property(self, params): host, prop, *_ = params if host == OperationHost.SELF.value: # TODO: Add support for nested property values. if prop not in self.properties: raise DataError(f"Template has no '{prop}' attribute") return self.properties[prop].eval(self, prop) elif host == OperationHost.HOST.value: raise DataError( f"{host} keyword can be only used within node template context." ) else: # try to find the property within the TOSCA nodes for node in self.topology.nodes.values(): if host == node.name or host in node.types: # TODO: Add support for nested property values. if prop in node.properties: return node.properties[prop].eval(self, prop) # try to find the property within the TOSCA relationships for rel in self.topology.relationships.values(): if host == rel.name or host in rel.types: # TODO: Add support for nested property values. if prop in rel.properties: return rel.properties[prop].eval(self, prop) raise DataError( f"We were unable to find the property: {prop} within the specified modelable entity or keyname: " f"{host} for node: {self.name}. The valid entities to get properties from are currently TOSCA nodes, " f"relationships and policies. But the best practice is that the property host is set to " f"'{OperationHost.SELF.value}'. This indicates that the property is referenced locally from something " f"in the relationship itself.")
def map_attribute(self, params, value): host, attr, *rest = params if host != OperationHost.SELF.value: raise DataError( f"Invalid attribute host for attribute mapping: {host} for node: {self.template.name}. For operation " f"outputs in interfaces on node templates, the only allowed keyname is: {OperationHost.SELF.value}. " f"This is because the output values must always be stored into attributes that belong to the node " f"template that has the interface for which the output values are returned." ) attribute_mapped = False # TODO: Add support for nested attribute values once we have data type support. if attr in self.attributes: self.set_attribute(attr, value) attribute_mapped = True # If we have no attribute, try searching for capability. capabilities = tuple(c for c in self.template.capabilities if c.name == attr) if len(capabilities) > 1: raise DataError(f"More than one capability is named '{attr}'.") if len(capabilities ) == 1 and capabilities[0].attributes and len(rest) != 0: if rest[0] in capabilities[0].attributes: capabilities[0].attributes[rest[0]] = value attribute_mapped = True if not attribute_mapped: raise DataError( f"Cannot find attribute '{attr}' among {', '.join(self.attributes.keys())}." )
def get_attribute(self, params): host, attr, *rest = params if host != "SELF": raise DataError( "Accessing non-local stuff is bad. Fix your service template.") if host == "HOST": raise DataError("HOST is not yet supported in opera.") # TODO(@tadeboro): Add support for nested attribute values once we # have data type support. if attr in self.attributes: return self.attributes[attr].eval(self) # TODO(@tadeboro): Add capability access. # If we have no attribute, try searching for requirement. relationships = self.out_edges.get(attr, {}) if len(relationships) == 0: raise DataError("Cannot find attribute '{}'.".format(attr)) if len(relationships) > 1: raise DataError( "Targeting more than one instance via '{}'.".format(attr), ) return next(iter(relationships.values())).target.get_attribute( ["SELF"] + rest, )
def map_attribute(self, params, value): host, *_ = params if host not in ("SELF", "SOURCE", "TARGET"): raise DataError("Attribute host should be set to 'SELF', 'SOURCE' or 'TARGET'.") if len(self.instances) != 1: raise DataError("Mapping an attribute for multiple instances not supported") next(iter(self.instances.values())).map_attribute(params, value)
def get_attribute(self, params): host, prop, *rest = params if host != "SELF": raise DataError( "Accessing non-local stuff is bad. Fix your service template.") if host == "HOST": raise DataError("HOST is not yet supported in opera.") if len(self.instances) != 1: raise DataError("Cannot get an attribute from multiple instances") return next(iter(self.instances.values())).get_attribute(params)
def get_attribute(self, params): host, *_ = params if host == "HOST": raise DataError("HOST is not yet supported in opera.") if host != "SELF": raise DataError( "Attribute host should be set to 'SELF' which is the only valid value. This is needed to indicate that " "the attribute is referenced locally from something in the node itself." ) if len(self.instances) != 1: raise DataError("Cannot get an attribute from multiple instances") return next(iter(self.instances.values())).get_attribute(params)
def map_attribute(self, params, value): host, *_ = params valid_hosts = [i.value for i in OperationHost] if host not in valid_hosts: raise DataError( "The attribute's 'host' should be set to one of {}.".format( ", ".join(valid_hosts))) if len(self.instances) != 1: raise DataError( "Mapping an attribute for multiple instances not supported") next(iter(self.instances.values())).map_attribute(params, value)
def get_property(self, params): host, prop, *rest = params if host != "SELF": raise DataError( "Accessing non-local stuff is bad. Fix your service template.") if host == "HOST": raise DataError("HOST is not yet supported in opera.") # TODO(@tadeboro): Add support for nested property values once we # have data type support. if prop not in self.properties: raise DataError("Template has no '{}' property".format(prop)) return self.properties[prop].eval(self)
def map_attribute(self, params, value): host, prop, *rest = params if host != "SELF": raise DataError( "Accessing non-local stuff is bad. Fix your service template.") if host == "HOST": raise DataError("HOST is not yet supported in opera.") if len(self.instances) != 1: raise DataError( "Mapping an attribute for multiple instances not supported") next(iter(self.instances.values())).map_attribute(params, value)
def map_attribute(self, params, value): host, attr, *rest = params if host != "SELF": raise DataError( "Accessing non-local stuff is bad. Fix your service template.") if host == "HOST": raise DataError("HOST is not yet supported in opera.") # TODO(@tadeboro): Add support for nested attribute values once we # have data type support. if attr not in self.attributes: raise DataError("Cannot find attribute '{}'.".format(attr)) self.set_attribute(attr, value)
def map_attribute(self, params, value): if len(self.instances) != 1: raise DataError( "Mapping an attribute for zero or multiple instances not supported" ) next(iter(self.instances.values())).map_attribute(params, value)
def find_node(self, node_name): if node_name not in self.nodes: raise DataError( "Node template '{}' does not exist.".format(node_name), ) return self.nodes[node_name]
def set_attribute(self, name, value): # TODO(@tadeboro): Add type validation. if name not in self.attributes: raise DataError( f"Instance has no '{name}' attribute. Available attributes: {', '.join(self.attributes.keys())}" ) self.attributes[name].set(value)
def set_attribute(self, name, value): # TODO(@tadeboro): Add type validation. if name not in self.attributes: raise DataError( "Instance has no '{}' attribute. Available attributes: " "{}".format(name, ", ".join(self.attributes.keys()))) self.attributes[name].set(value)
def concat(self, params, node=None): if not isinstance(params, list): raise DataError( "Concat intrinsic function parameters '{}' should be a list". format(params)) return self.join([params], node)
def eval(self, instance, key): if not self.present: raise DataError("Cannot use an unset value: {}".format(key)) if self.is_function: return self.eval_function(instance) return self.data
def resolve_requirements(self, topology): requirement_occurrences = Counter([r.name for r in self.requirements]) for r in self.requirements: occurrences_range = r.occurrences.data if r.occurrences else None min_occurrences = occurrences_range[0] if occurrences_range else 1 max_occurrences = occurrences_range[1] if occurrences_range else 1 if requirement_occurrences[r.name] < min_occurrences: raise DataError( "Not enough occurrences found for requirement '{}'. Minimum is: {}" .format(r.name, min_occurrences)) if requirement_occurrences[r.name] > max_occurrences: raise DataError( "Too many occurrences found for requirement '{}'. Maximum is: {}" .format(r.name, max_occurrences)) r.resolve(topology)
def eval(self, instance): if not self.present: raise DataError("Cannot use an unset value.") if self.is_function: return self.eval_function(instance) return self.data
def state(self): state_value = self.attributes["state"].data try: return next(s for s in NodeState if s.value == state_value) except StopIteration as e: raise DataError("Could not find state {} in {}".format( state_value, list(NodeState))) from e
def get_attribute(self, params): host, *_ = params if host == OperationHost.HOST.value: raise DataError( "{} as the attribute's 'host' is not yet supported in opera.". format(host)) if host != OperationHost.SELF.value: raise DataError( "The attribute's 'host' should be set to 'SELF' which is the only valid value. " "This is needed to indicate that the attribute is referenced locally from something in the node itself." " Was: {}".format(host)) if len(self.instances) != 1: raise DataError("Cannot get an attribute from multiple instances") return next(iter(self.instances.values())).get_attribute(params)
def map_attribute(self, params, value): host, attr, *_ = params if host == "HOST": raise DataError("HOST is not yet supported in opera.") if host != "SELF": raise DataError( "Attribute host should be set to 'SELF' which is the only valid value. " "This is needed to indicate that the attribute is referenced locally from something " "in the node itself.") # TODO(@tadeboro): Add support for nested attribute values once we # have data type support. if attr not in self.attributes: raise DataError("Cannot find attribute '{}'.".format(attr)) self.set_attribute(attr, value)
def map_attribute(self, params, value): host, attr, *_ = params if host == OperationHost.HOST.value: raise DataError( "{} as the attribute's 'host' is not yet supported in opera.".format(OperationHost.HOST.value)) if host != OperationHost.SELF.value: raise DataError("The attribute's 'host' should be set to '{}' which is the only valid value. " "This is needed to indicate that the attribute is referenced locally from something " "in the node itself. Was: {}".format(OperationHost.SELF.value, host)) # TODO(@tadeboro): Add support for nested attribute values once we # have data type support. if attr not in self.attributes: raise DataError("Cannot find attribute '{}' among {}.".format(attr, ", ".join(self.attributes.keys()))) self.set_attribute(attr, value)
def get_attribute(self, params): host, attr, *rest = params if host not in ("SELF", "SOURCE", "TARGET"): raise DataError( "Accessing non-local stuff is bad. Fix your service template.") if host == "SOURCE": return self.source.get_attribute(["SELF", attr] + rest) elif host == "TARGET": return self.target.get_attribute(["SELF", attr] + rest) # TODO(@tadeboro): Add support for nested attribute values once we # have data type support. if attr not in self.attributes: raise DataError("Instance has no '{}' attribute".format(attr)) return self.attributes[attr].eval(self, attr)
def map_attribute(self, params, value): host, attr, *rest = params valid_hosts = [i.value for i in OperationHost] if host == OperationHost.HOST.value: raise DataError( "{} as the attribute's 'host' is not yet supported in opera.".format(OperationHost.HOST.value)) if host not in valid_hosts: raise DataError("The attribute's 'host' should be set to one of {}. Was: " "{}".format(", ".join(valid_hosts), host)) if host == OperationHost.SOURCE.value: self.source.map_attribute([OperationHost.SELF.value, attr] + rest, value) elif host == OperationHost.TARGET.value: self.target.map_attribute([OperationHost.SELF.value, attr] + rest, value) else: self.set_attribute(attr, value)
def get_property(self, params): host, prop, *_ = params if host == "HOST": raise DataError("HOST is not yet supported in opera.") if host != "SELF": raise DataError( "Property host should be set to 'SELF' which is the only valid value. This is needed to indicate that " "the property is referenced locally from something in the node itself." ) # TODO(@tadeboro): Add support for nested property values once we # have data type support. if prop not in self.properties: raise DataError("Template has no '{}' property".format(prop)) return self.properties[prop].eval(self, prop)
def get_input(self, params): # TODO(@tadeboro): Allow nested data access. if not isinstance(params, list): params = [params] if params[0] not in self.inputs: raise DataError("Invalid input: '{}'".format(params[0])) return self.inputs[params[0]].eval(self, params[0])
def get_attribute(self, params): host, attr, *rest = params valid_hosts = [i.value for i in OperationHost] if host not in valid_hosts: raise DataError("The attribute's 'host' should be set to one of {}.".format(", ".join(valid_hosts))) if host == OperationHost.SOURCE.value: return self.source.get_attribute([OperationHost.SELF.value, attr] + rest) elif host == OperationHost.TARGET.value: return self.target.get_attribute([OperationHost.SELF.value, attr] + rest) # TODO(@tadeboro): Add support for nested attribute values once we # have data type support. if attr not in self.attributes: raise DataError( "Instance has no '{}' attribute. Available attributes: {}".format(attr, ", ".join(self.attributes))) return self.attributes[attr].eval(self, attr)
def get_attribute(self, params): host, attr, *rest = params if host not in ("SELF", "SOURCE", "TARGET"): raise DataError( "Attribute host should be set to 'SELF', 'SOURCE' or 'TARGET'." ) if host == "SOURCE": return self.source.get_attribute(["SELF", attr] + rest) elif host == "TARGET": return self.target.get_attribute(["SELF", attr] + rest) # TODO(@tadeboro): Add support for nested attribute values once we # have data type support. if attr not in self.attributes: raise DataError("Instance has no '{}' attribute".format(attr)) return self.attributes[attr].eval(self, attr)