Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New enpoints and updated functionality #28

Merged
merged 61 commits into from
Aug 3, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
77031c4
Created dataset to run the tests.
Joscorbe Jun 2, 2016
1a484ac
Added postgREST and SQL imports to Travis.
Joscorbe Jun 2, 2016
de2fc9d
Start postgREST in background.
Joscorbe Jun 2, 2016
3901b7b
Very basic first test.
Joscorbe Jun 3, 2016
484fdd3
Added functions to the test dataset.
Joscorbe Jun 6, 2016
946bb24
Added views and some problems solved with the SQL Script.
Joscorbe Jun 7, 2016
f9575a3
First tests for metadata.
Joscorbe Jun 7, 2016
a007073
Execute PostgREST to the API Schema.
Joscorbe Jun 7, 2016
f06cb74
Added some temporal prints to see the error in Travis.
Joscorbe Jun 8, 2016
0594c21
Set DBOD database properly.
Joscorbe Jun 8, 2016
c6ba5ef
CONFIG: Added new options to config file.
Joscorbe Jun 10, 2016
0566f8a
HANDLERS: Removed deprecated code that was using connections to Postg…
Joscorbe Jun 10, 2016
0cfbd4b
CONFIG: Removed unneeded 'database' section.
Joscorbe Jun 10, 2016
5b8843f
CONFIG: Fixed api.pass option in config file.
Joscorbe Jun 10, 2016
da94737
HANDLERS: More work in the structure of handlers.
Joscorbe Jun 10, 2016
605f26f
HANDLERS: Split in different modules (rundeck, hostaliases, metadata).
Joscorbe Jun 10, 2016
6e354de
Set content to Json to ensure the correct type.
Joscorbe Jun 20, 2016
b673e21
Cleanup
Joscorbe Jun 21, 2016
eaea1ec
TEST: Separated classes in different files.
Joscorbe Jun 29, 2016
c2b3e16
TRAVIS: Added API install and execution.
Joscorbe Jun 29, 2016
e660258
TEST: Fixed tests, now nose will be able to find them.
Joscorbe Jun 30, 2016
e454af2
CONFIG: Added rundeck and removed ssl sections.
Joscorbe Jun 30, 2016
e0ebb3e
TRAVIS: Start dbod-api in background.
Joscorbe Jun 30, 2016
bd3557e
HANDLERS: Responses are sent in a 'response' object.
Joscorbe Jul 1, 2016
75f8e71
HANDLERS: HostAliases response packaged as object
icot Jul 1, 2016
4e091f7
SQL: Modified host_aliases to return a list of aliases
icot Jul 1, 2016
904989e
GITIGNORE: Added vim .swp files
icot Jul 1, 2016
ed1ab67
TEST: Added 5 metadata tests.
Joscorbe Jul 1, 2016
9cd43a0
Merge branch 'endpoints' of https://github.com/cerndb/dbod-api into e…
Joscorbe Jul 1, 2016
5546e57
TEST: Removed useless test in rundeck_test.py
Joscorbe Jul 1, 2016
6afecd3
TEST: Added timeout to tests.
Joscorbe Jul 1, 2016
86491d9
STRUCTURE: Changed the structure of the application to make the tests…
Joscorbe Jul 5, 2016
2efd733
FIX: Temporal solution to solve the problem with multiple 'localhost'…
Joscorbe Jul 5, 2016
928299b
TRAVIS: The API is not needed in Travis any more.
Joscorbe Jul 5, 2016
7f6a4a5
CONFIG: Changes in config file to use the json format and use authori…
Joscorbe Jul 6, 2016
fc24cea
TEST: Added test for invalid class in metadata.
Joscorbe Jul 6, 2016
4a7ee62
HANDLERS: Added handlers for Rundeck jobs.
Joscorbe Jul 7, 2016
c10aa09
Removed unneeded 'psycopg2' dependency.
Joscorbe Jul 19, 2016
6db4b37
SQL: Added instances with several volumes and some PKs.
Joscorbe Jul 20, 2016
a4e105f
CONFIG: Added instance PostgREST url.
Joscorbe Jul 22, 2016
88a3bb7
SQL: Added constraints and more test data to the test sql file.
Joscorbe Jul 25, 2016
280addc
HANDLERS: Added entity handler.
Joscorbe Jul 27, 2016
52e8e8a
HANDLERS: Fixed call to delete instance.
Joscorbe Jul 27, 2016
f9ad7bd
TESTS: Instance creation test.
Joscorbe Jul 28, 2016
0823efa
HANDLERS: Properly modification of port when the field was set in the…
Joscorbe Jul 28, 2016
3694d8e
HANDLERS: Added handler and tests for functional aliases
jforjohn Aug 1, 2016
b486c49
HANDLERS: Remove old volumes and replace by new ones in put handler.
Joscorbe Jul 29, 2016
3ebd0c1
HANDLERS: Check for missing parameters in the creation of new entities.
Joscorbe Jul 29, 2016
2fbb409
TESTS: Added more tests for entities.
Joscorbe Jul 29, 2016
a88bfb2
Merge branch 'endpoints' of https://github.com/cerndb/dbod-api into e…
Joscorbe Aug 1, 2016
6cc5f60
SQL:Add functional_alias table and view and insert data
jforjohn Aug 1, 2016
8a63bdd
CONFIG:Added functional alias PostgREST url.
jforjohn Aug 1, 2016
1bf48a6
HANDLERS:Adding missing import for functional alias
jforjohn Aug 2, 2016
3ed412f
HANDLERS: Changed invalid_request to bad_request.
Joscorbe Aug 2, 2016
f6c3388
SQL:Fixing functional aliases table
jforjohn Aug 2, 2016
b43e7e4
TESTS: Added comments to tests, and new test to edit volumes.
Joscorbe Aug 2, 2016
9cd2bfa
Merge branch 'endpoints' of https://github.com/cerndb/dbod-api into e…
Joscorbe Aug 2, 2016
b0789c9
HANDLERS: Fixed error codes in PUT entity. Add instance_id to volumes.
Joscorbe Aug 2, 2016
1fd2ab7
HANDLERS: Removed commented out handler.
Joscorbe Aug 2, 2016
6bd4498
HANDLERS: Added get handler to entity.
Joscorbe Aug 2, 2016
2f70536
CONFIG: Removed hardcoded urls and added to config file.
Joscorbe Aug 3, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ cover/
__pycache__/
*.py[cod]

*.swp

# C extensions
*.so

Expand Down
12 changes: 11 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@ addons:
services:
- postgresql
before_install:
- sudo [ $(ip addr show | grep "inet6 ::1" | wc -l) -lt "1" ] && sudo sed -i '/^::1/d' /etc/hosts && sudo sed -i '/^127.0.1.1/d' /etc/hosts
- sudo mkdir /etc/dbod
- sudo mkdir /var/log/dbod
- sudo chown travis /var/log/dbod
- sudo cp static/api.cfg /etc/dbod
- wget https://github.com/begriffs/postgrest/releases/download/v0.3.1.1/postgrest-0.3.1.1-ubuntu.tar.xz
- tar xf postgrest-0.3.1.1-ubuntu.tar.xz
install:
- pip install -r requirements.txt
- pip install coveralls
- python setup.py install
before_script:
- psql -c 'CREATE DATABASE dbod;' -U postgres
- psql -d dbod -f dbod/tests/db_test.sql -U postgres
- ./postgrest postgres://postgres@localhost/dbod -a postgres -s api &
- sleep 5
script:
- nosetests --with-coverage --cover-package=dbod --cover-html
- curl -g http://localhost:3000
- nosetests --with-coverage --cover-package=dbod --cover-html -s
after_success:
coveralls
47 changes: 3 additions & 44 deletions bin/dbod-api
Original file line number Diff line number Diff line change
Expand Up @@ -12,49 +12,8 @@
DB On Demand metadata REST API server
"""

import ConfigParser
import sys, traceback
from tornado.options import parse_command_line, options
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from dbod.api.handlers import *
from dbod.config import config

import logging

def main():
""" Main body """

# Set up log file and level.
options.log_file_prefix = config.get('logging','path')
options.logging = 'debug'
options.log_to_stderr = False

# Parse server command line and set up logging defaults, if necessary
parse_command_line()

logging.info("Defining application (url, handler) pairs")
application = tornado.web.Application([
(r"/", DocHandler),
(r"/api/v1/entity/([^/]+)", EntityHandler),
(r"/api/v1/entity/alias/([^/]+)", FunctionalAliasHandler),
(r"/api/v1/host/([^/]+)", HostHandler),
(r"/api/v1/host/aliases/([^/]+)", HostAliases),
(r"/api/v1/metadata/(?P<class>[^\/]+)/?(?P<name>[^\/]+)?", Metadata),
(r"/api/v1/rundeck/resources.xml", RundeckResources),
], debug=True)

logging.info("Configuring HTTP server")
http_server = HTTPServer(application,
ssl_options = {
"certfile" : config.get('ssl', 'hostcert') ,
"keyfile" : config.get('ssl', 'hostkey'),
})

http_server.listen(config.get('server', 'port'))

logging.info("Starting application")
IOLoop.instance().start()
from dbod.api.api import Application

if __name__ == "__main__":
main()
Application()

71 changes: 71 additions & 0 deletions dbod/api/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (C) 2015, CERN
# This software is distributed under the terms of the GNU General Public
# Licence version 3 (GPL Version 3), copied verbatim in the file "LICENSE".
# In applying this license, CERN does not waive the privileges and immunities
# granted to it by virtue of its status as Intergovernmental Organization
# or submit itself to any jurisdiction.

import ConfigParser
import sys, traceback
import tornado.web
import logging

from tornado.options import parse_command_line, options, define
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop

from dbod.api.base import DocHandler
from dbod.api.rundeck import RundeckResources, RundeckJobs
from dbod.api.metadata import Metadata
from dbod.api.functionalalias import FunctionalAliasHandler
from dbod.api.hostaliases import HostAliases
from dbod.api.entity import Entity
from dbod.config import config

handlers = [
(r"/", DocHandler),
(r"/api/v1/entity/([^/]+)", Entity),
(r"/api/v1/host/aliases/([^/]+)", HostAliases),
(r"/api/v1/entity/alias/([^/]*)", FunctionalAliasHandler),
(r"/api/v1/metadata/(?P<class>[^\/]+)/?(?P<name>[^\/]+)?", Metadata),
(r"/api/v1/rundeck/resources.xml", RundeckResources),
(r"/api/v1/rundeck/job/(?P<job>[^\/]+)/?(?P<entity>[^\/]+)?", RundeckJobs),
]

class Application():
def __init__(self):
# Set up log file and level.
options.log_file_prefix = config.get('logging', 'path')
options.logging = config.get('logging', 'level')
options.log_to_stderr = config.getboolean('logging', 'stderr')

# Port and arguments
port = config.get('server', 'port')
define('port', default=port, help='Port to be used')
parse_command_line()

# Defining handlers
logging.info("Defining application (url, handler) pairs")
application = tornado.web.Application(handlers, debug=config.getboolean('tornado', 'debug'))

# Configuring server and SSL
logging.info("Configuring HTTP server")
if (config.has_section('ssl')):
http_server = HTTPServer(application,
ssl_options = {
"certfile" : config.get('ssl', 'hostcert') ,
"keyfile" : config.get('ssl', 'hostkey'),
})
else:
http_server = HTTPServer(application)
logging.info("Host certificate undefined, SSL is DISABLED")

# Listening port
http_server.listen(options.port)

# Starting
logging.info("Starting application")
tornado.ioloop.IOLoop.instance().start()
80 changes: 80 additions & 0 deletions dbod/api/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

# Copyright (C) 2015, CERN
# This software is distributed under the terms of the GNU General Public
# Licence version 3 (GPL Version 3), copied verbatim in the file "LICENSE".
# In applying this license, CERN does not waive the privileges and immunities
# granted to it by virtue of its status as Intergovernmental Organization
# or submit itself to any jurisdiction.

"""
REST API Server for the DB On Demand System
"""

import tornado.web
import base64
import functools
import logging

from dbod.config import config

# HTTP API status codes
OK = 200
CREATED = 201 # Request fulfilled resulting in creation of new resource
NO_CONTENT = 204 # Succesfull delete
NOT_FOUND = 404
UNAUTHORIZED = 401
BAD_REQUEST = 400

# Basic HTTP Authentication decorator
def http_basic_auth(fun):
"""Decorator for extracting HTTP basic authentication user/password pairs
from the request headers and matching them to configurated credentials.
It will generate an HTTP UNAUTHORIZED (Error code 401) if the request is
not using HTTP basic authentication.

Example:
@http_basic_auth
def get(self, user, pwd)
"""
@functools.wraps(fun)
def wrapper(*args, **kwargs):
""" Decorator wrapper """
self = args[0]
try:
# Try
auth = self.request.headers.get('Authorization')
scheme, _, token = auth.partition(' ')
if scheme.lower() == 'basic':
# Decode user and password
user, _, pwd = base64.decodestring(token).partition(':')
if user == config.get('api','user') and pwd == config.get('api','pass'):
return fun(*args, **kwargs)
else:
# Raise UNAUTHORIZED HTTP Error (401)
logging.error("Unauthorized access from: %s",
self.request.headers)
raise tornado.web.HTTPError(UNAUTHORIZED)

else:
# We only support basic authentication
logging.error("Authentication scheme not recognized")
return "Authentication scheme not recognized"
except AttributeError:
# Raise UNAUTHORIZED HTTP Error (401) if the request is not
# using autentication (auth will be None and partition() will fail
logging.error("Unauthorized access from: %s",
self.request.headers)
raise tornado.web.HTTPError(UNAUTHORIZED)

return wrapper

class DocHandler(tornado.web.RequestHandler):
"""Generates the API endpoint documentation"""
def get(self):
logging.info("Generating API endpoints doc")
response = """Please use :
<p>http://hostname:port/api/v1/entity/NAME</p>
<p>http://hostname:port/api/v1/host/HOSTNAME</p>"""
self.write(response)
Loading