def find_modified(self, previous=[], current=[], exception_map={}): """ Find any objects that have been changed since the last run of the watcher. Add these items to the changed_items list. """ prev_map = {item.location(): item for item in previous} curr_map = {item.location(): item for item in current} item_locations = list(set(curr_map).intersection(set(prev_map))) item_locations = [item_location for item_location in item_locations if not self.location_in_exception_map(item_location, exception_map)] for location in item_locations: prev_item = prev_map[location] curr_item = curr_map[location] # ChangeItem with and without ephemeral changes eph_change_item = None dur_change_item = None if not sub_dict(prev_item.config) == sub_dict(curr_item.config): eph_change_item = ChangeItem.from_items(old_item=prev_item, new_item=curr_item, source_watcher=self) if self.ephemerals_skipped(): # deepcopy configs before filtering dur_prev_item = deepcopy(prev_item) dur_curr_item = deepcopy(curr_item) # filter-out ephemeral paths in both old and new config dicts if self.ephemeral_paths: for path in self.ephemeral_paths: for cfg in [dur_prev_item.config, dur_curr_item.config]: try: dpath.util.delete(cfg, path, separator='$') except PathNotFound: pass # now, compare only non-ephemeral paths if not sub_dict(dur_prev_item.config) == sub_dict(dur_curr_item.config): dur_change_item = ChangeItem.from_items(old_item=dur_prev_item, new_item=dur_curr_item, source_watcher=self) # store all changes, divided in specific categories if eph_change_item: self.ephemeral_items.append(eph_change_item) app.logger.debug("%s: ephemeral changes in item %s/%s/%s" % (self.i_am_singular, eph_change_item.account, eph_change_item.region, eph_change_item.name)) if dur_change_item: self.changed_items.append(dur_change_item) app.logger.debug("%s: durable changes in item %s/%s/%s" % (self.i_am_singular, dur_change_item.account, dur_change_item.region, dur_change_item.name)) elif eph_change_item is not None: # store all changes, handle them all equally self.changed_items.append(eph_change_item) app.logger.debug("%s: changes in item %s/%s/%s" % (self.i_am_singular, eph_change_item.account, eph_change_item.region, eph_change_item.name))
def find_modified(self, previous=[], current=[], exception_map={}): """ Find any objects that have been changed since the last run of the watcher. Add these items to the changed_items list. """ prev_map = {item.location(): item for item in previous} curr_map = {item.location(): item for item in current} item_locations = list(set(curr_map).intersection(set(prev_map))) item_locations = [item_location for item_location in item_locations if not self.location_in_exception_map(item_location, exception_map)] for location in item_locations: prev_item = prev_map[location] curr_item = curr_map[location] # ChangeItem with and without ephemeral changes eph_change_item = None dur_change_item = None if not sub_dict(prev_item.config) == sub_dict(curr_item.config): eph_change_item = ChangeItem.from_items(old_item=prev_item, new_item=curr_item, source_watcher=self) if self.ephemerals_skipped(): # deepcopy configs before filtering dur_prev_item = deepcopy(prev_item) dur_curr_item = deepcopy(curr_item) # filter-out ephemeral paths in both old and new config dicts for path in self.ephemeral_paths: for cfg in [dur_prev_item.config, dur_curr_item.config]: try: dpath.util.delete(cfg, path, separator='$') except PathNotFound: pass # now, compare only non-ephemeral paths if not sub_dict(dur_prev_item.config) == sub_dict(dur_curr_item.config): dur_change_item = ChangeItem.from_items(old_item=dur_prev_item, new_item=dur_curr_item, source_watcher=self) # store all changes, divided in specific categories if eph_change_item: self.ephemeral_items.append(eph_change_item) app.logger.debug("%s: ephemeral changes in item %s/%s/%s" % (self.i_am_singular, eph_change_item.account, eph_change_item.region, eph_change_item.name)) if dur_change_item: self.changed_items.append(dur_change_item) app.logger.debug("%s: durable changes in item %s/%s/%s" % (self.i_am_singular, dur_change_item.account, dur_change_item.region, dur_change_item.name)) elif eph_change_item is not None: # store all changes, handle them all equally self.changed_items.append(eph_change_item) app.logger.debug("%s: changes in item %s/%s/%s" % (self.i_am_singular, eph_change_item.account, eph_change_item.region, eph_change_item.name))
def hash_config(self, config): """ Finds the hash for a config. Calls sub_dict, which is a recursive method which sorts lists which may be buried in the structure. Dumps the config to json with sort_keys set. Grabs an MD5 hash. :param config: dict describing item :return: 32 character string (MD5 Hash) """ item = sub_dict(config) item_str = json.dumps(item, sort_keys=True) item_hash = hashlib.md5(item_str) # nosec: not used for security return item_hash.hexdigest()
def hash_config(self, config): """ Finds the hash for a config. Calls sub_dict, which is a recursive method which sorts lists which may be buried in the structure. Dumps the config to json with sort_keys set. Grabs an MD5 hash. :param config: dict describing item :return: 32 character string (MD5 Hash) """ item = sub_dict(config) item_str = json.dumps(item, sort_keys=True) item_hash = hashlib.md5(item_str) # nosec: not used for security return item_hash.hexdigest()
def get(self, revision_id): """ .. http:get:: /api/1/revision/1234 Get a specific revision. **Example Request**: .. sourcecode:: http GET /api/1/revision/123 HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example Response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: application/json { "auth": { "authenticated": true, "user": "******" }, "item_id": 114, "comments": [], "active": false, "date_created": "2013-10-04 22:01:47", "config": {}, "id":123 } :statuscode 200: no error :statuscode 401: Authentication failure. Please login. """ query = ItemRevision.query.filter(ItemRevision.id == revision_id) result = query.first() comments = [] for comment in result.comments: comment_marshaled = marshal(comment, REVISION_COMMENT_FIELDS) comments.append( dict(comment_marshaled.items() + {'user': comment.user.email}.items())) cloudtrail_entries = [] for entry in result.cloudtrail_entries: cloudtrail_entries.append(entry.full_entry) revision_marshaled = marshal(result, REVISION_FIELDS) revision_marshaled = dict( revision_marshaled.items() + {'config': OrderedDict(sorted(sub_dict(result.config).items())) }.items() + {'auth': self.auth_dict}.items() + {'comments': comments}.items() + {'cloudtrail': cloudtrail_entries}.items()) self.reqparse.add_argument('compare', type=int, default=None, location='args') args = self.reqparse.parse_args() compare_id = args.pop('compare', None) if compare_id: query = ItemRevision.query.filter(ItemRevision.id == compare_id) compare_result = query.first() pdiff = PolicyDiff( OrderedDict(sorted(sub_dict(result.config).items())), OrderedDict(sorted(sub_dict(compare_result.config).items()))) revision_marshaled = dict( revision_marshaled.items() + {'diff_html': pdiff.produceDiffHTML()}.items()) return revision_marshaled, 200
def get(self, revision_id): """ .. http:get:: /api/1/revision/1234 Get a specific revision. **Example Request**: .. sourcecode:: http GET /api/1/revision/123 HTTP/1.1 Host: example.com Accept: application/json, text/javascript **Example Response**: .. sourcecode:: http HTTP/1.1 200 OK Vary: Accept Content-Type: application/json { "auth": { "authenticated": true, "user": "******" }, "item_id": 114, "comments": [], "active": false, "date_created": "2013-10-04 22:01:47", "config": {}, "id":123 } :statuscode 200: no error :statuscode 401: Authentication failure. Please login. """ query = ItemRevision.query.filter(ItemRevision.id == revision_id) result = query.first() comments = [] for comment in result.comments: comment_marshaled = marshal(comment, REVISION_COMMENT_FIELDS) comments.append(dict( comment_marshaled.items() + {'user': comment.user.email}.items() )) cloudtrail_entries = [] for entry in result.cloudtrail_entries: cloudtrail_entries.append(entry.full_entry) revision_marshaled = marshal(result, REVISION_FIELDS) revision_marshaled = dict( revision_marshaled.items() + {'config': OrderedDict(sorted(sub_dict(result.config).items()))}.items() + {'auth': self.auth_dict}.items() + {'comments': comments}.items() + {'cloudtrail': cloudtrail_entries}.items() ) self.reqparse.add_argument('compare', type=int, default=None, location='args') args = self.reqparse.parse_args() compare_id = args.pop('compare', None) if compare_id: query = ItemRevision.query.filter(ItemRevision.id == compare_id) compare_result = query.first() pdiff = PolicyDiff( OrderedDict(sorted(sub_dict(result.config).items())), OrderedDict(sorted(sub_dict(compare_result.config).items()))) revision_marshaled = dict( revision_marshaled.items() + {'diff_html': pdiff.produceDiffHTML()}.items() ) return revision_marshaled, 200