def transition_history_to_json(history_rec: ArchiveTransitionHistoryEntry): return { "transition_task_id": history_rec.transition_task_id, "rule_id": history_rec.rule_id, "imageDigest": history_rec.digest, "transition": history_rec.transition.value, "state": history_rec.transition_state, "created_at": epoch_to_rfc3339(history_rec.created_at), "last_updated": epoch_to_rfc3339(history_rec.last_updated), }
def archive_img_docker_to_msg(obj: ArchivedImageDocker): return { "pullstring": obj.registry + "/" + obj.repository + ":" + obj.tag, "registry": obj.registry, "repository": obj.repository, "tag": obj.tag, "detected_at": epoch_to_rfc3339(obj.tag_detected_at), "created_at": epoch_to_rfc3339(obj.created_at), "last_updated": epoch_to_rfc3339(obj.last_updated), }
def archive_img_docker_to_msg(obj: ArchivedImageDocker): return { 'pullstring': obj.registry + '/' + obj.repository + ':' + obj.tag, 'registry': obj.registry, 'repository': obj.repository, 'tag': obj.tag, 'detected_at': epoch_to_rfc3339(obj.tag_detected_at), 'created_at': epoch_to_rfc3339(obj.created_at), 'last_updated': epoch_to_rfc3339(obj.last_updated) }
def transition_history_to_json(history_rec: ArchiveTransitionHistoryEntry): return { 'transition_task_id': history_rec.transition_task_id, 'rule_id': history_rec.rule_id, 'imageDigest': history_rec.digest, 'transition': history_rec.transition.value, 'state': history_rec.transition_state, 'created_at': epoch_to_rfc3339(history_rec.created_at), 'last_updated': epoch_to_rfc3339(history_rec.last_updated) }
def archived_img_to_msg(obj: ArchivedImage): return { "imageDigest": obj.imageDigest, "parentDigest": obj.parentDigest, "annotations": json.loads(obj.annotations) if obj.annotations else {}, "status": obj.status, "analyzed_at": epoch_to_rfc3339(obj.analyzed_at), "archive_size_bytes": obj.archive_size_bytes, "image_detail": [archive_img_docker_to_msg(x) for x in obj.tags()], "created_at": epoch_to_rfc3339(obj.created_at), "last_updated": epoch_to_rfc3339(obj.last_updated), }
def archived_img_to_msg(obj: ArchivedImage): return { 'imageDigest': obj.imageDigest, 'parentDigest': obj.parentDigest, 'annotations': json.loads(obj.annotations) if obj.annotations else {}, 'status': obj.status, 'analyzed_at': epoch_to_rfc3339(obj.analyzed_at), 'archive_size_bytes': obj.archive_size_bytes, 'image_detail': [ archive_img_docker_to_msg(x) for x in obj.tags() ], 'created_at': epoch_to_rfc3339(obj.created_at), 'last_updated': epoch_to_rfc3339(obj.last_updated) }
def transition_rule_db_to_json(db_rule: ArchiveTransitionRule): return { 'rule_id': db_rule.rule_id, 'selector': { 'registry': db_rule.selector_registry, 'repository': db_rule.selector_repository, 'tag': db_rule.selector_tag }, 'analysis_age_days': db_rule.analysis_age_days, 'tag_versions_newer': db_rule.tag_versions_newer, 'transition': db_rule.transition.value, 'system_global': db_rule.system_global, 'created_at': epoch_to_rfc3339(db_rule.created_at), 'last_updated': epoch_to_rfc3339(db_rule.last_updated) }
def list_archives(): """ GET /archives :return: """ try: with session_scope() as session: imgs = db_archived_images.summarize(session) or [] rules = (session.query(ArchiveTransitionRule).filter_by( account=ApiRequestContextProxy.namespace()).all() or []) rule_count = len(rules) newest = None if rule_count > 0: newest = epoch_to_rfc3339( max(map(lambda x: x.last_updated, rules))) return { "images": imgs, "rules": { "count": rule_count, "last_updated": newest } } except Exception as ex: logger.exception("Failed to list archives") return make_response_error(ex, in_httpcode=500), 500
def test_rfc3339(): # parsing/validation and conversion symmetry for rfc_str, assert_targets in rfc3339_examples: print("testing input string: {}".format(rfc_str)) rc = utils.rfc3339str_to_epoch(rfc_str) print("\trfc3339_to_epoch: {}".format(rc)) assert (rc == assert_targets['epoch']) print("\tepoch assertion passed") rc = utils.rfc3339str_to_datetime(rfc_str) print("\trfc3339_to_datetime: {}".format(rc)) assert (rc == assert_targets['dt']) print("\tdatetime assertion passed") for epoch, assert_targets in epoch_examples: print("testing input epoch: {}".format(epoch)) rc = utils.epoch_to_rfc3339(epoch) print("\tepoch_to_rfc3339: {}".format(rc)) assert (rc == assert_targets['rfc3339']) print("\tdatetime assertion passed") for dt, assert_targets in dt_examples: print("testing input datetime: {}".format(dt)) rc = utils.datetime_to_rfc3339(dt) print("\tdatetime_to_rfc3339: {}".format(rc)) assert (rc == assert_targets['rfc3339']) print("\tdatetime assertion passed")
def summarize(session: Session): """ Return a summary dict of counts, sizes, and last updated :param session: :return: dict """ image_count = session.query(ArchivedImage).count() archive_bytes = 0 tag_count = 0 most_recent = '' if image_count > 0: logger.debug('Image Count: {}'.format(image_count)) archive_bytes = session.query( func.sum(ArchivedImage.archive_size_bytes)).scalar() tag_count = session.query(ArchivedImageDocker).count() most_recent_epoch = session.query(func.max( ArchivedImage.last_updated)).scalar() if most_recent_epoch: most_recent = epoch_to_rfc3339(most_recent_epoch) return { 'total_image_count': image_count, 'total_tag_count': tag_count, 'total_data_bytes': int(archive_bytes), 'last_updated': most_recent }
def transition_rule_db_to_json(db_rule: ArchiveTransitionRule): return { "rule_id": db_rule.rule_id, "selector": { "registry": db_rule.selector_registry, "repository": db_rule.selector_repository, "tag": db_rule.selector_tag, }, "exclude": { "expiration_days": db_rule.exclude_expiration_days, "selector": { "registry": db_rule.exclude_selector_registry, "repository": db_rule.exclude_selector_repository, "tag": db_rule.exclude_selector_tag, }, }, "analysis_age_days": db_rule.analysis_age_days, "tag_versions_newer": db_rule.tag_versions_newer, "transition": db_rule.transition.value, "system_global": db_rule.system_global, "max_images_per_account": db_rule.max_images_per_account, "created_at": epoch_to_rfc3339(db_rule.created_at), "last_updated": epoch_to_rfc3339(db_rule.last_updated), }
def summarize(session: Session): """ Return a summary dict of counts, sizes, and last updated :param session: :return: dict """ image_count = session.query(ArchivedImage).count() archive_bytes = session.query(func.sum(ArchivedImage.archive_size_bytes)).scalar() tag_count = session.query(ArchivedImageDocker).count() most_recent = session.query(func.max(ArchivedImage.last_updated)).scalar() return { 'total_image_count': image_count, 'total_tag_count': tag_count, 'total_data_bytes': int(archive_bytes), 'last_updated': epoch_to_rfc3339(most_recent) }
def list_archives(): """ GET /archives :return: """ try: with session_scope() as session: imgs = db_archived_images.summarize(session) rules = session.query(ArchiveTransitionRule).filter_by(account=ApiRequestContextProxy.namespace()).all() rule_count = len(rules) newest = max(map(lambda x: x.last_updated, rules)) return { 'images': imgs, 'rules': { 'count': rule_count, 'last_updated': epoch_to_rfc3339(newest) } } except Exception as ex: return make_response_error(ex, in_httpcode=500), 500