Permalink
Browse files

Merge pull request #234 from hsoft/robust-model

Make models resilient to new attributes in LXD
  • Loading branch information...
2 parents 34b6609 + fcc823d commit 17cdd3972bd6413d13c2fc5e4a675a7b8d77450f @javacruft javacruft committed Jul 4, 2017
Showing with 31 additions and 8 deletions.
  1. +27 −7 pylxd/models/_model.py
  2. +4 −1 pylxd/tests/mock_lxd.py
View
@@ -18,6 +18,9 @@
from pylxd import exceptions
+MISSING = object()
+
+
class Attribute(object):
"""A metadata class for model attributes."""
@@ -149,10 +152,23 @@ def sync(self, rollback=False):
# XXX: rockstar (25 Jun 2016) - This has the potential to step
# on existing attributes.
response = self.api.get()
- for key, val in response.json()['metadata'].items():
+ payload = response.json()['metadata']
+ for key, val in payload.items():
if key not in self.__dirty__ or rollback:
- setattr(self, key, val)
- self.__dirty__.remove(key)
+ try:
+ setattr(self, key, val)
+ self.__dirty__.remove(key)
+ except AttributeError:
+ # We have received an attribute from the server that we
+ # don't support in our model. Ignore this error, it
+ # doesn't hurt us.
+ pass
+
+ # Make sure that *all* supported attributes are set, even those that
+ # aren't supported by the server.
+ missing_attrs = set(self.__attributes__.keys()) - set(payload.keys())
+ for missing_attr in missing_attrs:
+ setattr(self, missing_attr, MISSING)
if rollback:
self.__dirty__.clear()
@@ -187,8 +203,12 @@ def delete(self, wait=False):
def marshall(self):
"""Marshall the object in preparation for updating to the server."""
marshalled = {}
- for key, val in self.__attributes__.items():
- if ((not val.readonly and not val.optional) or
- (val.optional and hasattr(self, key))):
- marshalled[key] = getattr(self, key)
+ for key, attr in self.__attributes__.items():
+ if ((not attr.readonly and not attr.optional) or
+ (attr.optional and hasattr(self, key))):
+ val = getattr(self, key)
+ # Don't send back to the server an attribute it doesn't
+ # support.
+ if val is not MISSING:
+ marshalled[key] = val
return marshalled
View
@@ -213,7 +213,10 @@ def profile_GET(request, context):
],
'stateful': False,
'status': "Running",
- 'status_code': 103
+ 'status_code': 103,
+ 'unsupportedbypylxd': "This attribute is not supported by "\
+ "pylxd. We want to test whether the mere presence of it "\
+ "makes it crash."
}},
'method': 'GET',
'url': r'^http://pylxd.test/1.0/containers/an-container$',

0 comments on commit 17cdd39

Please sign in to comment.