diff --git a/iib/web/api_v1.py b/iib/web/api_v1.py index 338abfcf..aa427ce3 100644 --- a/iib/web/api_v1.py +++ b/iib/web/api_v1.py @@ -367,6 +367,7 @@ def get_builds() -> flask.Response: user = flask.request.args.get('user') index_image = flask.request.args.get('index_image') from_index = flask.request.args.get('from_index') + from_index_startswith = flask.request.args.get('from_index_startswith') query_params = {} # Create an alias class to load the polymorphic classes @@ -397,7 +398,7 @@ def get_builds() -> flask.Response: query_params['user'] = user query = query.join(Request.user).filter(User.username == user) - if index_image or from_index: + if index_image or from_index or from_index_startswith: # https://sqlalche.me/e/20/xaj2 - Create aliases for self-join (Sqlalchemy 2.0) request_create_empty_index_alias = aliased(RequestCreateEmptyIndex, flat=True) request_add_alias = aliased(RequestAdd, flat=True) @@ -432,6 +433,30 @@ def get_builds() -> flask.Response: ) ) + if from_index_startswith: + query_params['from_index_startswith'] = from_index_startswith + from_index_startswith_results = Image.query.filter( + Image.pull_specification.startswith(from_index_startswith) + ).all() + + if not from_index_startswith_results: + # if index_image is not found in image table, then raise an error + raise ValidationError( + f'Can\'t find any from_index starting with {from_index_startswith}' + ) + + # Get id of the images to be searched + from_index_result_ids = [fir.id for fir in from_index_startswith_results] + + query = query.filter( + or_( + request_create_empty_index_alias.from_index_id.in_(from_index_result_ids), + request_add_alias.from_index_id.in_(from_index_result_ids), + request_rm_alias.from_index_id.in_(from_index_result_ids), + request_fbc_operations_alias.from_index_id.in_(from_index_result_ids), + ) + ) + if index_image: # Get the image id of the image to be searched for image_result = Image.query.filter_by(pull_specification=index_image).first() diff --git a/iib/web/static/api_v1.yaml b/iib/web/static/api_v1.yaml index ed264e6b..c6d78166 100644 --- a/iib/web/static/api_v1.yaml +++ b/iib/web/static/api_v1.yaml @@ -68,7 +68,21 @@ paths: description: The index image to filter the build requests by schema: type: string - example: pull speci of the index image + example: pull specification of the index image + default: null + - name: from_index + in: query + description: The from index image to filter the build requests by + schema: + type: string + example: pull specification of the index image + default: null + - name: from_index_startswith + in: query + description: The beginning of pull specification of from index image to filter the build requests by + schema: + type: string + example: pull specification of the from index image. Can be used to search from index without tag. default: null responses: '200': diff --git a/tests/test_web/test_api_v1.py b/tests/test_web/test_api_v1.py index efaa3cdf..274c552d 100644 --- a/tests/test_web/test_api_v1.py +++ b/tests/test_web/test_api_v1.py @@ -248,6 +248,38 @@ def test_from_index_filter( } +def test_from_index_startswith_filter( + app, client, db, minimal_request_add, minimal_request_rm, minimal_request_fbc_operations +): + _request_add_state_and_from_index( + minimal_request_add, 'quay.io/namespace/index@sha256:from_index' + ) + _request_add_state_and_from_index( + minimal_request_rm, 'quay.io/namespace/from_index@sha256:123456' + ) + _request_add_state_and_from_index( + minimal_request_fbc_operations, + 'quay.io/namespace/from_index@sha256:fbcop', + ) + db.session.commit() + + rv_json = client.get('/api/v1/builds?from_index_startswith=quay.io/namespace/from_index').json + assert rv_json['meta']['total'] == 2 + + rv_json = client.get( + '/api/v1/builds?from_index_startswith=quay.io/namespace/index@sha256:from_index' + ).json + assert rv_json['meta']['total'] == 1 + + rv_json = client.get('/api/v1/builds?from_index_startswith=quay.io/namespace').json + assert rv_json['meta']['total'] == 3 + + rv = client.get('/api/v1/builds?from_index_startswith=quay.io/namespace/index@sha256:abc') + assert rv.json == { + 'error': "Can\'t find any from_index starting with quay.io/namespace/index@sha256:abc" + } + + def test_get_builds_invalid_state(app, client, db): rv = client.get('/api/v1/builds?state=is_it_lunch_yet%3F') assert rv.status_code == 400