Commit 9c28af45 authored by Michael Moss's avatar Michael Moss Committed by LUCI CQ

Add ability to generically call most Gerrit APIs.

This will make it easier to call new or uncommon Gerrit APIs, without
needing to add dedicated methods for each one. This also makes it easier
to debug API calls by exposing the raw response data, which is often
processed or filtered in the existing wrapper methods.

BUG=1052179
R=linxinan@chromium.org

Change-Id: I0b594a9fdaabae4b0ebb379dc5473f4d6de67a13
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/tools/depot_tools/+/3235714
Auto-Submit: Michael Moss <mmoss@chromium.org>
Reviewed-by: 's avatarDirk Pranke <dpranke@google.com>
Reviewed-by: 's avatarXinan Lin <linxinan@chromium.org>
Commit-Queue: Dirk Pranke <dpranke@google.com>
parent 8093a3e1
......@@ -80,6 +80,33 @@ def CMDbranchinfo(parser, args):
write_result(result, opt)
@subcommand.usage('[args ...]')
def CMDrawapi(parser, args):
"""Call an arbitrary Gerrit REST API endpoint."""
parser.add_option('--path', dest='path', help='HTTP path of the API endpoint')
parser.add_option('--method', dest='method',
help='HTTP method for the API (default: GET)')
parser.add_option('--body', dest='body', help='API JSON body contents')
parser.add_option('--accept_status',
dest='accept_status',
help='Comma-delimited list of status codes for success.')
(opt, args) = parser.parse_args(args)
assert opt.path, "--path not defined"
host = urlparse.urlparse(opt.host).netloc
kwargs = {}
if opt.method:
kwargs['reqtype'] = opt.method.upper()
if opt.body:
kwargs['body'] = json.loads(opt.body)
if opt.accept_status:
kwargs['accept_statuses'] = [int(x) for x in opt.accept_status.split(',')]
result = gerrit_util.CallGerritApi(host, opt.path, **kwargs)
logging.info(result)
write_result(result, opt)
@subcommand.usage('[args ...]')
def CMDbranch(parser, args):
"""Create a branch in a gerrit project."""
......
......@@ -502,6 +502,17 @@ def ReadHttpJsonResponse(conn, accept_statuses=frozenset([200])):
return json.loads(s)
def CallGerritApi(host, path, **kwargs):
"""Helper for calling a Gerrit API that returns a JSON response."""
conn_kwargs = {}
conn_kwargs.update(
(k, kwargs[k]) for k in ['reqtype', 'headers', 'body'] if k in kwargs)
conn = CreateHttpConn(host, path, **conn_kwargs)
read_kwargs = {}
read_kwargs.update((k, kwargs[k]) for k in ['accept_statuses'] if k in kwargs)
return ReadHttpJsonResponse(conn, **read_kwargs)
def QueryChanges(host, params, first_param=None, limit=None, o_params=None,
start=None):
"""
......
......@@ -253,23 +253,30 @@ Module for interact with Gerrit endpoints
Wrapper for easy calling of gerrit_utils steps.
&mdash; **def [abandon\_change](/recipes/recipe_modules/gerrit/api.py#228)(self, host, change, message=None, name=None, step_test_data=None):**
&mdash; **def [abandon\_change](/recipes/recipe_modules/gerrit/api.py#257)(self, host, change, message=None, name=None, step_test_data=None):**
&mdash; **def [create\_gerrit\_branch](/recipes/recipe_modules/gerrit/api.py#32)(self, host, project, branch, commit, \*\*kwargs):**
&mdash; **def [call\_raw\_api](/recipes/recipe_modules/gerrit/api.py#32)(self, host, path, method=None, body=None, accept_statuses=None, name=None, \*\*kwargs):**
Call an arbitrary Gerrit API that returns a JSON response.
Returns:
The JSON response data.
&mdash; **def [create\_gerrit\_branch](/recipes/recipe_modules/gerrit/api.py#61)(self, host, project, branch, commit, \*\*kwargs):**
Creates a new branch from given project and commit
Returns:
The ref of the branch created
&mdash; **def [create\_gerrit\_tag](/recipes/recipe_modules/gerrit/api.py#51)(self, host, project, tag, commit, \*\*kwargs):**
&mdash; **def [create\_gerrit\_tag](/recipes/recipe_modules/gerrit/api.py#80)(self, host, project, tag, commit, \*\*kwargs):**
Creates a new tag at the given commit.
Returns:
The ref of the tag created.
&mdash; **def [get\_change\_description](/recipes/recipe_modules/gerrit/api.py#90)(self, host, change, patchset, timeout=None, step_test_data=None):**
&mdash; **def [get\_change\_description](/recipes/recipe_modules/gerrit/api.py#119)(self, host, change, patchset, timeout=None, step_test_data=None):**
Gets the description for a given CL and patchset.
......@@ -281,7 +288,7 @@ Args:
Returns:
The description corresponding to given CL and patchset.
&mdash; **def [get\_changes](/recipes/recipe_modules/gerrit/api.py#150)(self, host, query_params, start=None, limit=None, o_params=None, step_test_data=None, \*\*kwargs):**
&mdash; **def [get\_changes](/recipes/recipe_modules/gerrit/api.py#179)(self, host, query_params, start=None, limit=None, o_params=None, step_test_data=None, \*\*kwargs):**
Queries changes for the given host.
......@@ -300,14 +307,14 @@ Returns:
A list of change dicts as documented here:
https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-changes
&mdash; **def [get\_gerrit\_branch](/recipes/recipe_modules/gerrit/api.py#72)(self, host, project, branch, \*\*kwargs):**
&mdash; **def [get\_gerrit\_branch](/recipes/recipe_modules/gerrit/api.py#101)(self, host, project, branch, \*\*kwargs):**
Gets a branch from given project and commit
Returns:
The revision of the branch
&mdash; **def [get\_related\_changes](/recipes/recipe_modules/gerrit/api.py#192)(self, host, change, revision='current', step_test_data=None):**
&mdash; **def [get\_related\_changes](/recipes/recipe_modules/gerrit/api.py#221)(self, host, change, revision='current', step_test_data=None):**
Queries related changes for a given host, change, and revision.
......@@ -326,7 +333,7 @@ Returns:
A related changes dictionary as documented here:
https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#related-changes-info
&mdash; **def [get\_revision\_info](/recipes/recipe_modules/gerrit/api.py#109)(self, host, change, patchset, timeout=None, step_test_data=None):**
&mdash; **def [get\_revision\_info](/recipes/recipe_modules/gerrit/api.py#138)(self, host, change, patchset, timeout=None, step_test_data=None):**
Returns the info for a given patchset of a given change.
......@@ -339,11 +346,11 @@ Returns:
A dict for the target revision as documented here:
https://gerrit-review.googlesource.com/Documentation/rest-api-changes.html#list-changes
&mdash; **def [move\_changes](/recipes/recipe_modules/gerrit/api.py#266)(self, host, project, from_branch, to_branch, step_test_data=None):**
&mdash; **def [move\_changes](/recipes/recipe_modules/gerrit/api.py#295)(self, host, project, from_branch, to_branch, step_test_data=None):**
&mdash; **def [set\_change\_label](/recipes/recipe_modules/gerrit/api.py#248)(self, host, change, label_name, label_value, name=None, step_test_data=None):**
&mdash; **def [set\_change\_label](/recipes/recipe_modules/gerrit/api.py#277)(self, host, change, label_name, label_value, name=None, step_test_data=None):**
&mdash; **def [update\_files](/recipes/recipe_modules/gerrit/api.py#290)(self, host, project, branch, new_contents_by_file_path, commit_msg, params=frozenset(['status=NEW']), submit=False, submit_later=False):**
&mdash; **def [update\_files](/recipes/recipe_modules/gerrit/api.py#319)(self, host, project, branch, new_contents_by_file_path, commit_msg, params=frozenset(['status=NEW']), submit=False, submit_later=False):**
Update a set of files by creating and submitting a Gerrit CL.
......
......@@ -29,6 +29,35 @@ class GerritApi(recipe_api.RecipeApi):
venv=True,
**kwargs)
def call_raw_api(self,
host,
path,
method=None,
body=None,
accept_statuses=None,
name=None,
**kwargs):
"""Call an arbitrary Gerrit API that returns a JSON response.
Returns:
The JSON response data.
"""
args = [
'rawapi', '--host', host, '--path', path, '--json_file',
self.m.json.output()
]
if method:
args.extend(['--method', method])
if body:
args.extend(['--body', self.m.json.dumps(body)])
if accept_statuses:
args.extend(
['--accept_status', ','.join(str(i) for i in accept_statuses)])
step_name = name or 'call_raw_api (%s)' % path
step_result = self(step_name, args, **kwargs)
return step_result.json.output
def create_gerrit_branch(self, host, project, branch, commit, **kwargs):
"""Creates a new branch from given project and commit
......
......@@ -89,6 +89,39 @@
"@@@STEP_LOG_END@json.output@@@"
]
},
{
"cmd": [
"vpython",
"-u",
"RECIPE_REPO[depot_tools]/gerrit_client.py",
"rawapi",
"--host",
"https://chromium-review.googlesource.com",
"--path",
"/projects/v8/v8/tags/1.0",
"--json_file",
"/path/to/tmp/json",
"--method",
"PUT",
"--body",
"{\"revision\": \"67ebf73496383c6777035e374d2d664009e2aa5c\"}",
"--accept_status",
"201"
],
"env": {
"PATH": "<PATH>:RECIPE_REPO[depot_tools]"
},
"infra_step": true,
"name": "gerrit raw_create_tag",
"~followup_annotations": [
"@@@STEP_LOG_LINE@json.output@{@@@",
"@@@STEP_LOG_LINE@json.output@ \"can_delete\": true, @@@",
"@@@STEP_LOG_LINE@json.output@ \"ref\": \"refs/tags/1.0\", @@@",
"@@@STEP_LOG_LINE@json.output@ \"revision\": \"67ebf73496383c6777035e374d2d664009e2aa5c\"@@@",
"@@@STEP_LOG_LINE@json.output@}@@@",
"@@@STEP_LOG_END@json.output@@@"
]
},
{
"cmd": [
"vpython",
......
......@@ -26,6 +26,17 @@ def RunSteps(api):
data = api.gerrit.create_gerrit_tag(host, project, '1.0', commit)
assert data == 'refs/tags/1.0'
tag_body = {
"revision": "67ebf73496383c6777035e374d2d664009e2aa5c",
}
json_data = api.gerrit.call_raw_api(host,
'/projects/%s/tags/1.0' % project,
method='PUT',
body=tag_body,
accept_statuses=[201],
name='raw_create_tag')
assert json_data['ref'] == 'refs/tags/1.0'
api.gerrit.move_changes(host, project, 'master', 'main')
change_info = api.gerrit.update_files(host,
......@@ -87,6 +98,8 @@ def GenTests(api):
api.gerrit.make_gerrit_create_branch_response_data()) +
api.step_data('gerrit create_gerrit_tag (v8/v8 1.0)',
api.gerrit.make_gerrit_create_tag_response_data()) +
api.step_data('gerrit raw_create_tag',
api.gerrit.make_gerrit_create_tag_response_data()) +
api.step_data('gerrit create change at (v8/v8 main)',
api.gerrit.update_files_response_data()) +
api.step_data('gerrit submit change 91827',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment