Created
October 11, 2016 06:00
-
-
Save jimbaker/2ac685f97c5c08a8566783558d986ba7 to your computer and use it in GitHub Desktop.
Add host label PUT support
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/craton/api/v1/resources/inventory/hosts.py b/craton/api/v1/resources/inventory/hosts.py | |
| index 39264a5..39be56a 100644 | |
| --- a/craton/api/v1/resources/inventory/hosts.py | |
| +++ b/craton/api/v1/resources/inventory/hosts.py | |
| @@ -97,10 +97,10 @@ class HostsLabels(base.Resource): | |
| Update existing device label entirely, or add if it does | |
| not exist. | |
| """ | |
| - print(request.json) | |
| + import sys; print(request.json, file=sys.stderr) | |
| context = request.environ.get('context') | |
| - dbapi.hosts_labels_update(context, id, request.json) | |
| - return request.json, 200, None | |
| + labels_obj = dbapi.hosts_labels_update(context, id, request.json) | |
| + return jsonutils.to_primitive(labels_obj), 200, None | |
| @base.http_codes | |
| def delete(self, id): | |
| diff --git a/craton/db/sqlalchemy/alembic/versions/ffdc1a500db1_craton_inventory_init.py b/craton/db/sqlalchemy/alembic/versions/ffdc1a500db1_craton_inventory_init.py | |
| index 1308830..74350b4 100644 | |
| --- a/craton/db/sqlalchemy/alembic/versions/ffdc1a500db1_craton_inventory_init.py | |
| +++ b/craton/db/sqlalchemy/alembic/versions/ffdc1a500db1_craton_inventory_init.py | |
| @@ -55,6 +55,7 @@ def upgrade(): | |
| sa.Column('variable_association_id', sa.Integer), | |
| sa.Column('label', sa.String(length=255), nullable=True), | |
| sa.PrimaryKeyConstraint('id'), | |
| + sa.UniqueConstraint('label'), | |
| sa.ForeignKeyConstraint( | |
| ['variable_association_id'], ['variable_association.id'], | |
| 'fk_labels_variable_association') | |
| diff --git a/craton/db/sqlalchemy/api.py b/craton/db/sqlalchemy/api.py | |
| index 3827c97..aefdf4e 100644 | |
| --- a/craton/db/sqlalchemy/api.py | |
| +++ b/craton/db/sqlalchemy/api.py | |
| @@ -9,6 +9,7 @@ from oslo_db.sqlalchemy import utils as db_utils | |
| from oslo_log import log | |
| import sqlalchemy.orm.exc as sa_exc | |
| +from sqlalchemy.exc import IntegrityError | |
| from sqlalchemy.orm import with_polymorphic | |
| from craton import exceptions | |
| @@ -457,6 +458,7 @@ def hosts_data_delete(context, host_id, data): | |
| def hosts_labels_update(context, host_id, labels): | |
| """Update labels for host. Add the label if it is not present | |
| in host labels list, otherwise do nothing.""" | |
| + print('host_id', host_id) | |
| session = get_session() | |
| with session.begin(): | |
| host_devices = with_polymorphic(models.Device, '*') | |
| @@ -466,14 +468,32 @@ def hosts_labels_update(context, host_id, labels): | |
| query = query.filter_by(id=host_id) | |
| try: | |
| host = query.one() | |
| - except sa_exc.NoResultFound: | |
| - raise exceptions.NotFound() | |
| - | |
| - present_labels = [l.label for l in host.labels] | |
| - to_update = [i for i in labels["labels"] if i not in present_labels] | |
| - _labels = [models.Label(i) for i in to_update] | |
| - host.labels.update(_labels) | |
| + print('host', host) | |
| + except sa_exc.NoResultFound as e: | |
| + raise exceptions.NotFound() from e | |
| + | |
| + labels = set(labels) | |
| + add_to_host_labels = labels - set(host.associated_labels) | |
| + | |
| + if not add_to_host_labels: | |
| + return set() | |
| + | |
| + # Get existing labels from the database in the context of this | |
| + # transaction. NOTE: it is possible that another session could | |
| + # be updating simultaneously, in which case this query -- and | |
| + # corresponding REST API call -- would have to be re-applied | |
| + # again. | |
| + existing_label_objs = session.query(models.Label).filter( | |
| + models.Label.label.in_(add_to_host_labels)).all() | |
| + new_label_obs = set() | |
| + existing_labels = {label.label for label in existing_label_objs} | |
| + for label in add_to_host_labels: | |
| + if label not in existing_labels: | |
| + label_obj = models.Label(label) | |
| + host.labels.add(label_obj) | |
| + host.labels.update(existing_label_objs) | |
| host.save(session) | |
| + return add_to_host_labels | |
| def hosts_labels_delete(context, host_id, labels): | |
| diff --git a/craton/db/sqlalchemy/models.py b/craton/db/sqlalchemy/models.py | |
| index 920663e..ee0d2a8 100644 | |
| --- a/craton/db/sqlalchemy/models.py | |
| +++ b/craton/db/sqlalchemy/models.py | |
| @@ -425,7 +425,7 @@ class Label(Base, VariableMixin): | |
| """ | |
| __tablename__ = 'labels' | |
| id = Column(Integer, primary_key=True) | |
| - label = Column(String(255), unique=False) | |
| + label = Column(String(255), unique=True) | |
| _repr_columns = [label] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment