docs: def add_resource_attribute(resource_type, resource_id, attr_id, is_var, error_on_duplicate=True, **kwargs):
      """
          Add a resource attribute attribute to a resource.
  
          attr_is_var indicates whether the attribute is a variable or not --
          this is used in simulation to indicate that this value is expected
          to be filled in by the simulator.
      """
  
      attr = db.DBSession.query(Attr).filter(Attr.id==attr_id).first()
  
      if attr is None:
          raise ResourceNotFoundError("Attribute with ID %s does not exist."%attr_id)
  
      resource_i = _get_resource(resource_type, resource_id)
  
      resourceattr_qry = db.DBSession.query(ResourceAttr).filter(ResourceAttr.ref_key==resource_type)
  
      if resource_type == 'NETWORK':
          resourceattr_qry = resourceattr_qry.filter(ResourceAttr.network_id==resource_id)
      elif resource_type == 'NODE':
          resourceattr_qry = resourceattr_qry.filter(ResourceAttr.node_id==resource_id)
      elif resource_type == 'LINK':
          resourceattr_qry = resourceattr_qry.filter(ResourceAttr.link_id==resource_id)
      elif resource_type == 'GROUP':
          resourceattr_qry = resourceattr_qry.filter(ResourceAttr.group_id==resource_id)
      elif resource_type == 'PROJECT':
          resourceattr_qry = resourceattr_qry.filter(ResourceAttr.project_id==resource_id)
      else:
          raise HydraError('Resource type "{}" not recognised.'.format(resource_type))
      resource_attrs = resourceattr_qry.all()
  
      for ra in resource_attrs:
          if ra.attr_id == attr_id:
              if not error_on_duplicate:
                  return ra
  
              raise HydraError("Duplicate attribute. %s %s already has attribute %s"
                               %(resource_type, resource_i.get_name(), attr.name))
  
      attr_is_var = 'Y' if is_var == 'Y' else 'N'
  
      new_ra = resource_i.add_attribute(attr_id, attr_is_var)
      db.DBSession.flush()
  
      return new_ra