mirror of
https://github.com/quay/quay.git
synced 2026-01-27 18:42:52 +03:00
* ui: add entry for robot federation config (PROJQUAY-8050) adding entry for showing description in the UI for robot federation config changes
269 lines
7.5 KiB
Python
269 lines
7.5 KiB
Python
import json
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
import requests
|
|
|
|
from data import model
|
|
from endpoints.api import api
|
|
from endpoints.api.robot import (
|
|
OrgRobot,
|
|
OrgRobotFederation,
|
|
OrgRobotList,
|
|
UserRobot,
|
|
UserRobotList,
|
|
)
|
|
from endpoints.api.test.shared import conduct_api_call
|
|
from endpoints.test.shared import client_with_identity
|
|
from test.fixtures import *
|
|
from test.test_ldap import mock_ldap
|
|
from util.names import parse_robot_username
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"endpoint",
|
|
[
|
|
UserRobot,
|
|
OrgRobot,
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"body",
|
|
[
|
|
None,
|
|
{},
|
|
{"description": "this is a description"},
|
|
{"unstructured_metadata": {"foo": "bar"}},
|
|
{"description": "this is a description", "unstructured_metadata": {"foo": "bar"}},
|
|
],
|
|
)
|
|
def test_create_robot_with_metadata(endpoint, body, app):
|
|
with client_with_identity("devtable", app) as cl:
|
|
# Create the robot with the specified body.
|
|
conduct_api_call(
|
|
cl,
|
|
endpoint,
|
|
"PUT",
|
|
{"orgname": "buynlarge", "robot_shortname": "somebot"},
|
|
body,
|
|
expected_code=201,
|
|
)
|
|
|
|
# Ensure the create succeeded.
|
|
resp = conduct_api_call(
|
|
cl,
|
|
endpoint,
|
|
"GET",
|
|
{
|
|
"orgname": "buynlarge",
|
|
"robot_shortname": "somebot",
|
|
},
|
|
)
|
|
|
|
body = body or {}
|
|
assert resp.json["description"] == (body.get("description") or "")
|
|
assert resp.json["unstructured_metadata"] == (body.get("unstructured_metadata") or {})
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"endpoint, params",
|
|
[
|
|
(UserRobot, {"robot_shortname": "dtrobot"}),
|
|
(OrgRobot, {"orgname": "buynlarge", "robot_shortname": "coolrobot"}),
|
|
],
|
|
)
|
|
def test_retrieve_robot(endpoint, params, app):
|
|
with client_with_identity("devtable", app) as cl:
|
|
result = conduct_api_call(cl, endpoint, "GET", params, None)
|
|
assert result.json["token"] is not None
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"endpoint, params, bot_endpoint",
|
|
[
|
|
(UserRobotList, {}, UserRobot),
|
|
(OrgRobotList, {"orgname": "buynlarge"}, OrgRobot),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"include_token",
|
|
[
|
|
True,
|
|
False,
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"limit",
|
|
[
|
|
None,
|
|
1,
|
|
5,
|
|
],
|
|
)
|
|
def test_retrieve_robots(endpoint, params, bot_endpoint, include_token, limit, app):
|
|
params["token"] = "true" if include_token else "false"
|
|
|
|
if limit is not None:
|
|
params["limit"] = limit
|
|
|
|
with client_with_identity("devtable", app) as cl:
|
|
result = conduct_api_call(cl, endpoint, "GET", params, None)
|
|
|
|
if limit is not None:
|
|
assert len(result.json["robots"]) <= limit
|
|
|
|
for robot in result.json["robots"]:
|
|
assert (robot.get("token") is not None) == include_token
|
|
if include_token:
|
|
bot_params = dict(params)
|
|
bot_params["robot_shortname"] = parse_robot_username(robot["name"])[1]
|
|
result = conduct_api_call(cl, bot_endpoint, "GET", bot_params, None)
|
|
assert robot.get("token") == result.json["token"]
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"username, is_admin",
|
|
[
|
|
("devtable", True),
|
|
("reader", False),
|
|
],
|
|
)
|
|
@pytest.mark.parametrize(
|
|
"with_permissions",
|
|
[
|
|
True,
|
|
False,
|
|
],
|
|
)
|
|
def test_retrieve_robots_token_permission(username, is_admin, with_permissions, app):
|
|
with client_with_identity(username, app) as cl:
|
|
params = {"orgname": "buynlarge", "token": "true"}
|
|
if with_permissions:
|
|
params["permissions"] = "true"
|
|
|
|
result = conduct_api_call(cl, OrgRobotList, "GET", params, None)
|
|
assert result.json["robots"]
|
|
for robot in result.json["robots"]:
|
|
assert (robot.get("token") is not None) == is_admin
|
|
assert (robot.get("repositories") is not None) == (is_admin and with_permissions)
|
|
|
|
|
|
def test_duplicate_robot_creation(app):
|
|
with client_with_identity("devtable", app) as cl:
|
|
resp = conduct_api_call(
|
|
cl,
|
|
UserRobot,
|
|
"PUT",
|
|
{"robot_shortname": "dtrobot"},
|
|
expected_code=400,
|
|
)
|
|
assert resp.json["error_message"] == "Existing robot with name: devtable+dtrobot"
|
|
|
|
resp = conduct_api_call(
|
|
cl,
|
|
OrgRobot,
|
|
"PUT",
|
|
{"orgname": "buynlarge", "robot_shortname": "coolrobot"},
|
|
expected_code=400,
|
|
)
|
|
assert resp.json["error_message"] == "Existing robot with name: buynlarge+coolrobot"
|
|
|
|
|
|
def test_robot_federation_create(app):
|
|
with client_with_identity("devtable", app) as cl:
|
|
# Create the robot with the specified body.
|
|
conduct_api_call(
|
|
cl,
|
|
OrgRobotFederation,
|
|
"POST",
|
|
{
|
|
"orgname": "buynlarge",
|
|
"robot_shortname": "coolrobot",
|
|
},
|
|
[{"issuer": "https://issuer1", "subject": "subject1"}],
|
|
expected_code=200,
|
|
)
|
|
|
|
# Ensure the create succeeded.
|
|
resp = conduct_api_call(
|
|
cl,
|
|
OrgRobotFederation,
|
|
"GET",
|
|
{
|
|
"orgname": "buynlarge",
|
|
"robot_shortname": "coolrobot",
|
|
},
|
|
expected_code=200,
|
|
)
|
|
|
|
assert len(resp.json) == 1
|
|
assert resp.json[0].get("issuer") == "https://issuer1"
|
|
assert resp.json[0].get("subject") == "subject1"
|
|
|
|
resp = conduct_api_call(
|
|
cl,
|
|
OrgRobotFederation,
|
|
"DELETE",
|
|
{
|
|
"orgname": "buynlarge",
|
|
"robot_shortname": "coolrobot",
|
|
},
|
|
expected_code=204,
|
|
)
|
|
|
|
resp = conduct_api_call(
|
|
cl,
|
|
OrgRobotFederation,
|
|
"GET",
|
|
{
|
|
"orgname": "buynlarge",
|
|
"robot_shortname": "coolrobot",
|
|
},
|
|
expected_code=200,
|
|
)
|
|
|
|
assert len(resp.json) == 0
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"fed_config, raises_error, error_message",
|
|
[
|
|
(
|
|
[{"issuer": "issuer1", "subject": "subject1"}],
|
|
True,
|
|
"Issuer must be a URL (http:// or https://)",
|
|
),
|
|
([{"issuer": "https://issuer1", "subject": "subject1"}], False, None),
|
|
(
|
|
[{"bad_key": "issuer1", "subject": "subject1"}],
|
|
True,
|
|
"Missing one or more required fields",
|
|
),
|
|
(
|
|
[{"issuer": "https://issuer1", "subject": "subject1"}, {}],
|
|
True,
|
|
"Missing one or more required fields",
|
|
),
|
|
(
|
|
[
|
|
{"issuer": "https://issuer1", "subject": "subject1"},
|
|
{"issuer": "https://issuer2", "subject": "subject1"},
|
|
{"issuer": "https://issuer1", "subject": "subject1"},
|
|
],
|
|
True,
|
|
"Duplicate federation config entry",
|
|
),
|
|
],
|
|
)
|
|
def test_parse_federation_config(app, fed_config, raises_error, error_message):
|
|
request = Mock(requests.Request)
|
|
request.json = fed_config
|
|
|
|
with app.app_context():
|
|
if raises_error:
|
|
with pytest.raises(Exception) as ex:
|
|
parsed = OrgRobotFederation()._parse_federation_config(request)
|
|
assert error_message in str(ex.value)
|
|
else:
|
|
parsed = OrgRobotFederation()._parse_federation_config(request)
|