add usage API

Change-Id: Id6a688192277f9a58b13ca45d2596d375c5c187d
This commit is contained in:
Mohammed Naser 2020-09-04 15:21:49 -04:00
parent d5f060ad09
commit 84bc653862
10 changed files with 145 additions and 19 deletions

View File

@ -7,6 +7,9 @@
- context: .
repository: vexxhost/atmosphere-ingress
target: atmosphere-ingress
- context: .
repository: vexxhost/atmosphere-usage
target: atmosphere-usage
- job:
name: atmosphere:image:upload

View File

@ -27,3 +27,6 @@ ENV FLASK_APP=atmosphere.app \
FROM atmosphere AS atmosphere-ingress
ENV UWSGI_WSGI_FILE=/usr/local/bin/atmosphere-ingress-wsgi
FROM atmosphere AS atmosphere-usage
ENV UWSGI_WSGI_FILE=/usr/local/bin/atmosphere-usage-wsgi

62
atmosphere/api/usage.py Normal file
View File

@ -0,0 +1,62 @@
# Copyright 2020 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Usage API."""
from datetime import datetime
from flask import abort
from flask import Blueprint
from flask import request
from flask import jsonify
from keystonemiddleware import auth_token
from oslo_config import cfg
from atmosphere.app import create_app
from atmosphere import models
CONF = cfg.CONF
blueprint = Blueprint('usage', __name__)
def init_application(config=None):
"""Create usage API application."""
app = create_app(config)
app.register_blueprint(blueprint)
cfg.CONF([])
authtoken_config = dict(CONF.keystone_authtoken)
authtoken_config['log_name'] = app.name
app.wsgi_app = auth_token.AuthProtocol(app.wsgi_app, authtoken_config)
return app
@blueprint.route('/v1/resources')
def list_resources():
"""List all resources for a specific project."""
# Project ID from request (or allow override if admin)
project_id = request.headers['X-Project-Id']
if 'admin' in request.headers['X-Roles'] and 'project_id' in request.args:
project_id = request.args['project_id']
try:
start = datetime.fromisoformat(request.args['start'])
end = datetime.fromisoformat(request.args['end'])
except (KeyError, ValueError):
abort(400)
resources = models.Resource.get_all_by_time_range(start, end, project_id)
return jsonify(resources)

View File

@ -15,8 +15,25 @@
from dateutil.relativedelta import relativedelta
import pytest
from atmosphere.api import ingress
from atmosphere.tests.unit import fake
from atmosphere import models
from atmosphere.models import db
@pytest.fixture
def app():
app = ingress.init_application()
app.config['TESTING'] = True
app.config['SQLALCHEMY_ECHO'] = True
return app
@pytest.fixture
def _db(app):
db.init_app(app)
db.create_all()
return db
@pytest.mark.usefixtures("client", "db_session")

View File

@ -0,0 +1,37 @@
# Copyright 2020 VEXXHOST, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from dateutil.relativedelta import relativedelta
import pytest
from atmosphere.api import usage
from atmosphere.tests.unit import fake
from atmosphere import models
from atmosphere.models import db
@pytest.fixture
def app():
app = usage.init_application()
app.config['TESTING'] = True
app.config['SQLALCHEMY_ECHO'] = True
return app
@pytest.mark.usefixtures("client")
class TestResourceNoAuth:
def test_get_resources(self, client):
response = client.get('/v1/resources')
assert response.status_code == 401

View File

@ -18,7 +18,6 @@ from flask_sqlalchemy import SQLAlchemy
from atmosphere.app import create_app
from atmosphere.api import ingress
from atmosphere.models import db
@pytest.fixture(params=[
@ -36,19 +35,3 @@ from atmosphere.models import db
])
def ignored_event(request):
yield request.param
@pytest.fixture
def app():
app = create_app()
app.config['TESTING'] = True
app.config['SQLALCHEMY_ECHO'] = True
app.register_blueprint(ingress.blueprint)
return app
@pytest.fixture
def _db(app):
db.init_app(app)
db.create_all()
return db

View File

@ -22,11 +22,28 @@ from dateutil.relativedelta import relativedelta
from freezegun import freeze_time
import before_after
from atmosphere.api import ingress
from atmosphere import models
from atmosphere.models import db
from atmosphere import exceptions
from atmosphere.tests.unit import fake
@pytest.fixture
def app():
app = ingress.init_application()
app.config['TESTING'] = True
app.config['SQLALCHEMY_ECHO'] = True
return app
@pytest.fixture
def _db(app):
db.init_app(app)
db.create_all()
return db
class GetOrCreateTestMixin:
def test_with_existing_object(self):
event = fake.get_normalized_event()

View File

@ -2,5 +2,6 @@ ceilometer
Flask
Flask-Migrate
Flask-SQLAlchemy
keystonemiddleware
python-dateutil
PyMySQL

View File

@ -8,6 +8,7 @@ packages =
[entry_points]
wsgi_scripts =
atmosphere-ingress-wsgi = atmosphere.api.ingress:init_application
atmosphere-usage-wsgi = atmosphere.api.usage:init_application
[tool:pytest]
mocked-sessions=atmosphere.models.db.session

View File

@ -4,10 +4,12 @@ skipsdist = True
[testenv]
envdir = {toxworkdir}/shared
usedevelop = True
setenv =
FLASK_APP=atmosphere.app
passenv =
OS_*
FLASK_APP
DATABASE_URI
setenv =
FLASK_ENV=development
deps =
-r{toxinidir}/test-requirements.txt
-r{toxinidir}/requirements.txt