Compare commits

..

No commits in common. "5b33b76184beca59920ed70c63d1b33bd1a8e479" and "86c2fd5ce74edb6f06ca6309d0ecc69b195434cf" have entirely different histories.

16 changed files with 81 additions and 59 deletions

View File

@ -25,13 +25,40 @@
tox_install_siblings: false tox_install_siblings: false
tox_envlist: functional tox_envlist: functional
- job:
name: skyline-tox-py38
parent: openstack-tox-py38
description: |
Skyline py38 unittest tests
vars:
python_version: 3.8
tox_envlist: py38
- job:
name: skyline-tox-pep8-py38
parent: openstack-tox-py38
description: |
Skyline code static analysis
vars:
python_version: 3.8
tox_envlist: pep8
- project: - project:
templates: templates:
- openstack-python3-jobs
- release-notes-jobs-python3 - release-notes-jobs-python3
- publish-openstack-docs-pti - publish-openstack-docs-pti
check: check:
jobs: jobs:
- skyline-tox-py38:
irrelevant-files:
- ^container/.*$
- ^devstack/.*$
- ^docs/.*$
- ^tools/.*$
- ^.*\.rst$
- ^.*\.md$
- ^kolla/.*$
- skyline-tox-pep8-py38
- skyline-functional-devstack: - skyline-functional-devstack:
irrelevant-files: irrelevant-files:
- ^container/.*$ - ^container/.*$
@ -44,6 +71,16 @@
- ^releasenotes/.*$ - ^releasenotes/.*$
gate: gate:
jobs: jobs:
- skyline-tox-py38:
irrelevant-files:
- ^container/.*$
- ^devstack/.*$
- ^docs/.*$
- ^tools/.*$
- ^.*\.rst$
- ^.*\.md$
- ^kolla/.*$
- skyline-tox-pep8-py38
- skyline-functional-devstack: - skyline-functional-devstack:
irrelevant-files: irrelevant-files:
- ^container/.*$ - ^container/.*$

View File

@ -91,14 +91,14 @@ else
endif endif
build: skyline_console/skyline_console.tar.gz skyline_console/commit_id build: skyline_console/skyline_console.tar.gz skyline_console/commit_id
$(build_cmd) --no-cache --pull --force-rm \ $(build_cmd) --no-cache --pull --force-rm \
--build-arg GIT_CONSOLE_COMMIT=$(shell cat skyline_console/commit_id) \ --build-arg GIT_CONSOLE_COMMIT=$(file < skyline_console/commit_id) \
--build-arg GIT_BRANCH=$(GIT_BRANCH) \ --build-arg GIT_BRANCH=$(GIT_BRANCH) \
--build-arg GIT_COMMIT=$(GIT_COMMIT) \ --build-arg GIT_COMMIT=$(GIT_COMMIT) \
--build-arg RELEASE_VERSION=$(RELEASE_VERSION) \ --build-arg RELEASE_VERSION=$(RELEASE_VERSION) \
$(BUILD_ARGS) -f $(DOCKER_FILE) -t $(IMAGE):$(IMAGE_TAG) $(BUILD_CONTEXT) $(BUILD_ARGS) -f $(DOCKER_FILE) -t $(IMAGE):$(IMAGE_TAG) $(BUILD_CONTEXT)
devbuild: skyline_console/skyline_console.tar.gz skyline_console/commit_id devbuild: skyline_console/skyline_console.tar.gz skyline_console/commit_id
$(build_cmd) \ $(build_cmd) \
--build-arg GIT_CONSOLE_COMMIT=$(shell cat skyline_console/commit_id) \ --build-arg GIT_CONSOLE_COMMIT=$(file < skyline_console/commit_id) \
--build-arg GIT_BRANCH=devbuild \ --build-arg GIT_BRANCH=devbuild \
--build-arg GIT_COMMIT=devbuild \ --build-arg GIT_COMMIT=devbuild \
--build-arg RELEASE_VERSION=devbuild \ --build-arg RELEASE_VERSION=devbuild \

View File

@ -1,6 +0,0 @@
===========================
2024.1 Series Release Notes
===========================
.. release-notes::
:branch: stable/2024.1

View File

@ -1,6 +0,0 @@
===========================
2024.2 Series Release Notes
===========================
.. release-notes::
:branch: stable/2024.2

View File

@ -6,8 +6,6 @@ Skyline APIServer Release Notes
:maxdepth: 1 :maxdepth: 1
unreleased unreleased
2024.2
2024.1
2023.2 2023.2
2023.1 2023.1
zed zed

View File

@ -3,4 +3,4 @@ Zed Series Release Notes
======================== ========================
.. release-notes:: .. release-notes::
:branch: unmaintained/zed :branch: stable/zed

View File

@ -1,11 +1,11 @@
pbr>=5.8.0 # Apache-2.0 pbr>=5.8.0 # Apache-2.0
fastapi<=0.58.1 # MIT fastapi<=0.58.1 # MIT
pydantic<=1.10.0 # MIT pydantic<=1.8.2 # MIT
uvicorn<=0.17.6 # BSD License (3 clause) uvicorn<=0.17.6 # BSD License (3 clause)
gunicorn>=20.1.0 # MIT gunicorn>=20.1.0 # MIT
python-jose<=3.3.0 # MIT python-jose<=3.3.0 # MIT
databases>=0.9.0 # BSD License (3 clause) databases<=0.8.0 # BSD License (3 clause)
aiomysql>=0.2.0 # MIT aiomysql<=0.1.1 # MIT
aiosqlite<=0.17.0 # MIT aiosqlite<=0.17.0 # MIT
loguru<=0.5.3 # MIT loguru<=0.5.3 # MIT
PyYAML>=5.4.1 # MIT PyYAML>=5.4.1 # MIT

View File

@ -19,8 +19,6 @@ classifier =
Programming Language :: Python :: 3 Programming Language :: Python :: 3
Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9 Programming Language :: Python :: 3.9
Programming Language :: Python :: 3.10
Programming Language :: Python :: 3.11
project_urls: project_urls:
Source=https://opendev.org/openstack/skyline-apiserver Source=https://opendev.org/openstack/skyline-apiserver
Tracker=https://bugs.launchpad.net/skyline-apiserver Tracker=https://bugs.launchpad.net/skyline-apiserver

View File

@ -165,7 +165,7 @@ async def list_servers(
sort_dirs=[sort_dirs.value] if sort_dirs else None, sort_dirs=[sort_dirs.value] if sort_dirs else None,
) )
result: List = [] result = []
server_ids = [] server_ids = []
image_ids = [] image_ids = []
root_device_ids = [] root_device_ids = []
@ -752,13 +752,13 @@ async def list_volume_snapshots(
) )
except NotFound as ex: except NotFound as ex:
LOG.debug(f"Not found volume snapshot with id '{uuid}': {ex}") LOG.debug(f"Not found volume snapshot with id '{uuid}': {ex}")
return schemas.VolumeSnapshotsResponse(count=0, volume_snapshots=[]) return schemas.VolumeSnapshotsResponse(**{"count": 0, "volume_snapshots": []})
if volume_snapshot.project_id != profile.project.id: if volume_snapshot.project_id != profile.project.id:
LOG.debug( LOG.debug(
f"Volume snapshot with id '{uuid}' is in project " f"Volume snapshot with id '{uuid}' is in project "
f"'{volume_snapshot.project_id}', not in '{profile.project.id}'" f"'{volume_snapshot.project_id}', not in '{profile.project.id}'"
) )
return schemas.VolumeSnapshotsResponse(count=0, volume_snapshots=[]) return schemas.VolumeSnapshotsResponse(**{"count": 0, "volume_snapshots": []})
snapshot_session = get_system_session() snapshot_session = get_system_session()
search_opts["all_tenants"] = True search_opts["all_tenants"] = True

View File

@ -15,7 +15,7 @@
from __future__ import annotations from __future__ import annotations
from pathlib import PurePath from pathlib import PurePath
from typing import Any, Dict, List, Optional, Tuple, Union from typing import Any, List, Optional, Tuple, Union
from fastapi import APIRouter, Depends, Form, Header, HTTPException, Request, Response, status from fastapi import APIRouter, Depends, Form, Header, HTTPException, Request, Response, status
from fastapi.responses import RedirectResponse from fastapi.responses import RedirectResponse
@ -173,10 +173,9 @@ async def login(
regex=constants.INBOUND_HEADER_REGEX, regex=constants.INBOUND_HEADER_REGEX,
), ),
) -> schemas.Profile: ) -> schemas.Profile:
region = credential.region or CONF.openstack.default_region
try: try:
project_scope, unscope_token, default_project_id = await _get_projects_and_unscope_token( project_scope, unscope_token, default_project_id = await _get_projects_and_unscope_token(
region=region, region=credential.region,
domain=credential.domain, domain=credential.domain,
username=credential.username, username=credential.username,
password=credential.password, password=credential.password,
@ -187,13 +186,13 @@ async def login(
default_project_id = None default_project_id = None
project_scope_token = await get_project_scope_token( project_scope_token = await get_project_scope_token(
keystone_token=unscope_token, keystone_token=unscope_token,
region=region, region=credential.region,
project_id=default_project_id or project_scope[0].id, project_id=default_project_id or project_scope[0].id,
) )
profile = await generate_profile( profile = await generate_profile(
keystone_token=project_scope_token, keystone_token=project_scope_token,
region=region, region=credential.region,
) )
profile = await _patch_profile(profile, x_openstack_request_id) profile = await _patch_profile(profile, x_openstack_request_id)
@ -219,12 +218,12 @@ async def login(
response_description="OK", response_description="OK",
) )
async def get_sso(request: Request) -> schemas.SSO: async def get_sso(request: Request) -> schemas.SSO:
sso: Dict = { sso = {
"enable_sso": False, "enable_sso": False,
"protocols": [], "protocols": [],
} }
if CONF.openstack.sso_enabled: if CONF.openstack.sso_enabled:
protocols: List = [] protocols = []
ks_url = CONF.openstack.keystone_url.rstrip("/") ks_url = CONF.openstack.keystone_url.rstrip("/")
url_scheme = "https" if CONF.default.ssl_enabled else "http" url_scheme = "https" if CONF.default.ssl_enabled else "http"

View File

@ -14,7 +14,7 @@
from __future__ import annotations from __future__ import annotations
from typing import Dict, List from typing import Dict
from fastapi import APIRouter, Depends, HTTPException, status from fastapi import APIRouter, Depends, HTTPException, status
from keystoneauth1.exceptions.http import ( from keystoneauth1.exceptions.http import (
@ -113,7 +113,7 @@ async def list_policies(
LOG.debug("Keystone is not reachable. No privilege to access system scope.") LOG.debug("Keystone is not reachable. No privilege to access system scope.")
target = _generate_target(profile) target = _generate_target(profile)
results: List = [] results = []
services = constants.SUPPORTED_SERVICE_EPS.keys() services = constants.SUPPORTED_SERVICE_EPS.keys()
for service in services: for service in services:
try: try:
@ -176,7 +176,7 @@ async def check_policies(
target = _generate_target(profile) target = _generate_target(profile)
target.update(policy_rules.target if policy_rules.target else {}) target.update(policy_rules.target if policy_rules.target else {})
try: try:
result: List = [] result = []
for policy_rule in policy_rules.rules: for policy_rule in policy_rules.rules:
service = policy_rule.split(":", 1)[0] service = policy_rule.split(":", 1)[0]
rule = policy_rule.split(":", 1)[1] rule = policy_rule.split(":", 1)[1]

View File

@ -16,9 +16,9 @@ from __future__ import annotations
import time import time
from functools import wraps from functools import wraps
from typing import Any, Union from typing import Any
from sqlalchemy import Insert, Update, delete, func, insert, select, update from sqlalchemy import delete, func, insert, select, update
from skyline_apiserver.types import Fn from skyline_apiserver.types import Fn
@ -41,7 +41,7 @@ def check_db_connected(fn: Fn) -> Any:
async def check_token(token_id: str) -> bool: async def check_token(token_id: str) -> bool:
count_label = "revoked_count" count_label = "revoked_count"
query = ( query = (
select(func.count(RevokedToken.c.uuid).label(count_label)) select([func.count(RevokedToken.c.uuid).label(count_label)])
.select_from(RevokedToken) .select_from(RevokedToken)
.where(RevokedToken.c.uuid == token_id) .where(RevokedToken.c.uuid == token_id)
) )
@ -76,7 +76,7 @@ async def purge_revoked_token() -> Any:
@check_db_connected @check_db_connected
async def list_settings() -> Any: async def list_settings() -> Any:
query = select(Settings) query = select([Settings])
db = DB.get() db = DB.get()
async with db.transaction(): async with db.transaction():
result = await db.fetch_all(query) result = await db.fetch_all(query)
@ -86,7 +86,7 @@ async def list_settings() -> Any:
@check_db_connected @check_db_connected
async def get_setting(key: str) -> Any: async def get_setting(key: str) -> Any:
query = select(Settings).where(Settings.c.key == key) query = select([Settings]).where(Settings.c.key == key)
db = DB.get() db = DB.get()
async with db.transaction(): async with db.transaction():
result = await db.fetch_one(query) result = await db.fetch_one(query)
@ -97,17 +97,17 @@ async def get_setting(key: str) -> Any:
@check_db_connected @check_db_connected
async def update_setting(key: str, value: Any) -> Any: async def update_setting(key: str, value: Any) -> Any:
get_query = ( get_query = (
select(Settings.c.key, Settings.c.value).where(Settings.c.key == key).with_for_update() select([Settings.c.key, Settings.c.value]).where(Settings.c.key == key).with_for_update()
) )
db = DB.get() db = DB.get()
async with db.transaction(): async with db.transaction():
is_exist = await db.fetch_one(get_query) is_exist = await db.fetch_one(get_query)
stmt: Union[Insert, Update]
if is_exist is None: if is_exist is None:
stmt = insert(Settings).values(key=key, value=value) query = insert(Settings)
await db.execute(query, {"key": key, "value": value})
else: else:
stmt = update(Settings).where(Settings.c.key == key).values(value=value) query = update(Settings).where(Settings.c.key == key)
await db.execute(stmt) await db.execute(query, {"value": value})
result = await db.fetch_one(get_query) result = await db.fetch_one(get_query)
return result return result

View File

@ -24,7 +24,7 @@ from skyline_apiserver.types import constants
class Credential(BaseModel): class Credential(BaseModel):
region: Optional[str] = Field(None, description="Credential identity service region") region: str = Field(..., description="Credential user region")
domain: str = Field(..., description="Credential user domain") domain: str = Field(..., description="Credential user domain")
username: str = Field(..., description="Credential username") username: str = Field(..., description="Credential username")
password: str = Field(..., description="Credential password for user") password: str = Field(..., description="Credential password for user")

View File

@ -79,7 +79,7 @@ class TestOpt:
{ {
"name": FAKER.text.word(), "name": FAKER.text.word(),
"description": FAKER.text.word(), "description": FAKER.text.word(),
"schema": RuntimeError, "schema": object,
}, },
RuntimeError, RuntimeError,
), ),

View File

@ -2229,6 +2229,7 @@
"Credential": { "Credential": {
"title": "Credential", "title": "Credential",
"required": [ "required": [
"region",
"domain", "domain",
"username", "username",
"password" "password"
@ -2238,7 +2239,7 @@
"region": { "region": {
"title": "Region", "title": "Region",
"type": "string", "type": "string",
"description": "Credential identity service region" "description": "Credential user region"
}, },
"domain": { "domain": {
"title": "Domain", "title": "Domain",

21
tox.ini
View File

@ -2,19 +2,21 @@
minversion = 3.18.0 minversion = 3.18.0
requires = virtualenv>=20.4.2 requires = virtualenv>=20.4.2
skipsdist = True skipsdist = True
envlist = pep8,py3,functional # python runtimes: https://governance.openstack.org/tc/reference/project-testing-interface.html#tested-runtimes
envlist = pep8,py38,functional
# this allows tox to infer the base python from the environment name # this allows tox to infer the base python from the environment name
# and override any basepython configured in this file # and override any basepython configured in this file
ignore_basepython_conflict=true ignore_basepython_conflict=true
[testenv] [testenv]
usedevelop = true basepython = python3
setenv = setenv = VIRTUAL_ENV={envdir}
VIRTUAL_ENV={envdir} PYTHONWARNINGS=default::DeprecationWarning
OS_STDOUT_CAPTURE=1 OS_STDOUT_CAPTURE=1
OS_STDERR_CAPTURE=1 OS_STDERR_CAPTURE=1
usedevelop = True
deps = deps =
-c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -c{env:TOX_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master}
-r{toxinidir}/requirements.txt -r{toxinidir}/requirements.txt
-r{toxinidir}/test-requirements.txt -r{toxinidir}/test-requirements.txt
@ -66,9 +68,10 @@ commands =
black --check --diff --color skyline_apiserver --line-length 98 black --check --diff --color skyline_apiserver --line-length 98
flake8 {posargs} . flake8 {posargs} .
[testenv:py{3,38,39,310,311}] [testenv:py38]
description = description =
Run pytest. Run pytest.
envdir = {toxworkdir}/shared
deps = deps =
{[testenv]deps} {[testenv]deps}
extras = extras =
@ -106,7 +109,6 @@ commands =
description = description =
Generate swagger files. Generate swagger files.
envdir = {toxworkdir}/shared envdir = {toxworkdir}/shared
allowlist_externals = skyline-swagger-generator
commands = commands =
skyline-swagger-generator -o swagger.json skyline-swagger-generator -o swagger.json
@ -114,7 +116,6 @@ commands =
description = description =
Generate config files. Generate config files.
envdir = {toxworkdir}/shared envdir = {toxworkdir}/shared
allowlist_externals = skyline-sample-config-generator
commands = commands =
skyline-sample-config-generator -o etc/skyline.yaml.sample skyline-sample-config-generator -o etc/skyline.yaml.sample