Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
8dea2ef
MAGNUM: add necessary sections and files for magnum endpoint
jforjohn Jan 31, 2017
0cd4215
BASE: add http codes and authentication decorator for openstack
jforjohn Jan 31, 2017
79a13d1
API: add magnum endpoint
jforjohn Jan 31, 2017
83d425e
MAGNUM: magnum api integration for clusters and clustertemplates
jforjohn Jan 31, 2017
aad7171
API: magnum and kubernetes endpoints fixed and added
jforjohn Feb 24, 2017
b6c3baf
BASE: add authentication methods for magnum and kubernetes with certs
jforjohn Feb 24, 2017
d5f9daf
MAGNUM: changing variable names and breaking it into simpler pieces
jforjohn Feb 24, 2017
8dd0af9
MAGNUM: adding magnum client in the requirements
jforjohn Feb 24, 2017
55d6a52
STATIC: change the parts about the containers
jforjohn Feb 24, 2017
0aecaaa
KUBERNETES: adding kubernetes endpoint for get and post
jforjohn Feb 24, 2017
15a5af2
MAGNUM: add first tests for each method
jforjohn Feb 24, 2017
e2aaacc
KUBERNETES: add first tests for get and post
jforjohn Feb 24, 2017
5d15069
KUBERNETES: add a delete method
jforjohn Feb 27, 2017
eacb541
KUBERNETES: add a first test for the delete method
jforjohn Feb 27, 2017
d35e188
KUBERNETES: example kube conf file for the post test (secrets are not…
jforjohn Feb 27, 2017
de933a6
KUBERNETES: make post and delete methods to manage defined apps in pods
jforjohn Mar 24, 2017
8e84178
STATIC: add Jinja2 as a template engine
jforjohn Mar 24, 2017
7031770
STATIC: add volumes url for creating and deleting volumes
jforjohn Mar 24, 2017
0e31de7
KUBERNETES: file structure sample for using defined apps in pods
jforjohn Mar 24, 2017
47b2f10
KUBERNETES: change kube conf to mysql deployment
jforjohn Mar 24, 2017
558fb84
MAGNUM: file structure sample for magnum clusters
jforjohn Mar 24, 2017
e22f337
KUBERNETES: add capability to run postgres apps in kubernetes
jforjohn Mar 28, 2017
8338182
BASE: change variable names for checking kube certs
jforjohn Apr 3, 2017
f163268
KUBERNETES: fix typos and refactoring app configuration
jforjohn Apr 3, 2017
fcdae94
KUBERNETES: fix the answer from volume creation
jforjohn Apr 5, 2017
fbe79eb
KUBENRETES: better handling of use cases and add nfs support for exis…
jforjohn Apr 6, 2017
7e8a5f8
KUBENRETES: merge get_secrets and get_service function to get_resource
jforjohn Apr 6, 2017
9e1694f
KUBENRETES: minimize http calls to kube api during _config function
jforjohn Apr 6, 2017
cba923b
KUBERNETES: delete remained pods and replicasets if needed
jforjohn Apr 6, 2017
746b136
BASE: add certs capability for callung get_function
jforjohn Apr 6, 2017
d54cb66
MAGNUM: change to the new way of calling get_function
jforjohn Apr 6, 2017
22257c2
KUBERNETES: format the json for the detaching request
jforjohn Apr 25, 2017
5288219
KUBERNETES: separate nfs data and binlog servers and start documentation
jforjohn May 4, 2017
6feede1
BASE: add documentation for keystone decorator and get_function
jforjohn May 4, 2017
b6b0f86
DOC: add kubernetes and magnum rst files
jforjohn May 4, 2017
8e8dbf3
TEST: remove kubernetes and magnum incompleted tests
jforjohn May 4, 2017
f74bd94
KUBERNETES: add force param to delete
jforjohn May 4, 2017
4853f72
BASE: finalize documentation for keystone and get_function
jforjohn May 4, 2017
e345242
KUBERNETES: add docs for all the functions
jforjohn May 10, 2017
63462b1
TEST: kubernetes dummy tests
jforjohn May 11, 2017
5defa65
KUBERNETES: change name of the write function for the templates
jforjohn May 11, 2017
fbb2b62
STATIC: add missing apps_dir field in container-provider section
jforjohn May 11, 2017
775373b
STATIC: update all sample files and directories and examples to be al…
jforjohn May 12, 2017
efd2964
KUBERNETES: remove an unnecessary check of kube conf files
jforjohn May 12, 2017
30a8e4e
KUBERNETES: fix check of app conf files
jforjohn May 12, 2017
e370cc8
TEST: refactor and fix some basic tests for kubernetes
jforjohn May 12, 2017
e6d53cd
TRAVIS: add files for contenedor easier testing
jforjohn May 12, 2017
293f554
BASE: fix error message in keystone decorator
jforjohn May 12, 2017
ca91e26
TRAVIS: fix permission issue
jforjohn May 12, 2017
83b8728
KUBERNETES: add a TODO list in the code
jforjohn May 15, 2017
c7c071f
DOC: add documentation for the endpoints
jforjohn May 15, 2017
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
6 changes: 5 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@ services:
before_install:
# Remove IPv6 entry via https://github.com/travis-ci/travis-ci/issues/4978
- sudo sed -i '/^::1/d' /etc/hosts && sudo sed -i '/^127.0.1.1/d' /etc/hosts && sudo sed -i '/^fe80::4001:aff:fef0:2b/d' /etc/hosts
- sudo mkdir /etc/dbod
- sudo mkdir -p /etc/dbod/api
- sudo mkdir /var/log/dbod
- sudo chown travis /var/log/dbod
- sudo cp static/api.cfg /etc/dbod
- sudo cp static/auth_keystone.json /etc/dbod
- sudo cp -r static/clusters /etc/dbod/api
- sudo cp -r static/contenedor-apps /etc/dbod/api
- sudo chown -R travis /etc/dbod
- cp static/api_missing_section.cfg /tmp/
- cp static/api_missing_option.cfg /tmp/
- wget https://github.com/begriffs/postgrest/releases/download/v0.3.1.1/postgrest-0.3.1.1-ubuntu.tar.xz
Expand Down
7 changes: 6 additions & 1 deletion dbod/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
from dbod.api.instance import Instance
from dbod.api.attribute import Attribute
from dbod.api.fim import Fim
from dbod.api.magnum import MagnumClusters
from dbod.api.kubernetes import KubernetesClusters
from dbod.config import config, optionalConfig

# This list is a global object because in needs to be accessed
Expand All @@ -41,14 +43,17 @@
(r"/api/v1/instance/([^/]+)", Instance),
(r"/api/v1/host/aliases/([^/]+)", HostAliases),
(r"/api/v1/host/names/([^/]+)", Host),
(r"/api/v1/instance/alias/?(?P<db_name>[^\/]+)?", FunctionalAlias),
(r"/api/v1/instance/alias/(?P<db_name>[^\/]+)?", FunctionalAlias),
(r"/api/v1/(?P<class>[^\/]+)/(?P<name>[^\/]+)/metadata", Metadata),
(r"/api/v1/host/aliases/([^/]+)", HostAliases),
(r"/api/v1/rundeck/resources.xml", RundeckResources),
(r"/api/v1/rundeck/job/(?P<job>[^\/]+)/?(?P<node>[^\/]+)?", RundeckJobs),
# Deprecated, will be deleted in following versions
(r"/api/v1/metadata/(?P<class>[^\/]+)/?(?P<name>[^\/]+)?", Metadata),
(r"/api/v1/fim/([^/]+)", Fim),
(r"/api/v1/magnum/(?P<resource>[^/]+)/?(?P<name>[^/]+)?", MagnumClusters),
(r"/api/v1/kubernetes/(?P<cluster>[^/]+)/?(?P<resource>[^/]+)?/?(?P<name>[^/]+)?/?(?P<subresource>[^/]+)?/?(?P<subname>[^/]+)?", KubernetesClusters),
(r"/api/v1/beta/kubernetes/(?P<cluster>[^/]+)/?(?P<resource>[^/]+)?/?(?P<name>[^/]+)?/?(?P<subresource>[^/]+)?/?(?P<subname>[^/]+)?", KubernetesClusters),
]

class Application():
Expand Down
164 changes: 160 additions & 4 deletions dbod/api/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@
import requests
import json
import urllib
from os import mkdir, path, listdir
from subprocess import check_output, CalledProcessError
import shlex

from dbod.config import config

# HTTP API status codes
OK = 200
CREATED = 201 # Request fulfilled resulting in creation of new resource
ACCEPTED = 202
NO_CONTENT = 204 # Succesfull delete
NOT_FOUND = 404
UNAUTHORIZED = 401
CONFLICT = 409
BAD_REQUEST = 400
BAD_GATEWAY = 502
SERVICE_UNAVAILABLE = 503
Expand All @@ -36,7 +41,7 @@
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
It will generate an HTTP UNAUTHORIZED (Error code 401) if the request is
not using HTTP basic authentication.

Example:
Expand All @@ -57,7 +62,7 @@ def wrapper(*args, **kwargs):
if user == config.get('api','user') and pwd == config.get('api','pass'):
return fun(*args, **kwargs)
else:
# Raise UNAUTHORIZED HTTP Error (401)
# Raise UNAUTHORIZED HTTP Error (401)
logging.error("Unauthorized access from: %s",
self.request.headers)
raise tornado.web.HTTPError(UNAUTHORIZED)
Expand All @@ -74,7 +79,158 @@ def wrapper(*args, **kwargs):
raise tornado.web.HTTPError(UNAUTHORIZED)

return wrapper


# Openstack authentication through keystone
def cloud_auth(component):
"""
This function can be used as a decorator.
It is used for authenticating with the container providers and the orchestrators.
In this case the container provider is *magnum* and the orchestrator *kubernetes*.

:param component: magnum or kubernetes
:type component: str
:return: The calling function with the auth header or the certificates' paths as function parameters
:raises: HTTPError - 401 UNAUTHORIZED - when the password of the *auth_keystone.json* which is used to authenticate with the cloud provider (Mangum) or the orchestrator (Kubernetes) is invalid
"""
def keystone_decorator(fun):
@functools.wraps(fun)
def wrapper(*args, **kwargs):
if component == "magnum":
# header from keystone
token_header = 'X-Subject-Token'
keystone_url = config.get(component, 'auth_id_url')
auth_url = keystone_url + '/auth' + '/tokens'
auth_json_file = config.get(component,'auth_json')
try:
auth_json = json.load(open(auth_json_file, 'r'))

header = {'Content-Type': 'application/json'}
response = requests.post(auth_url,
json=auth_json,
headers=header)
xtoken = response.headers.get(token_header)
if response.ok and xtoken:
logging.debug("Token collected for DBoD Pilot Project")
kwargs.update({token_header: xtoken})
return fun(*args, **kwargs)
else:
logging.error("No Token or not all the fields provided to access %s with status code: %s" %(component, response.status_code))
raise tornado.web.HTTPError(response.status_code)
except ValueError:
logging.error("No JSON format of the authentication file provided for %s." %(component))
raise tornado.web.HTTPError(UNAUTHORIZED)
except KeyError:
logging.error("No X-Subject-Token available in headers")
logging.debug("Headers of the response from %s: %s" %(component, response.headers))
raise tornado.web.HTTPError(UNAUTHORIZED)

if component == 'kubernetes' and config.get('containers-provider', 'cloud') == 'magnum':
force = False
cloud = config.get('containers-provider', 'cloud')
cluster = kwargs.get('cluster')
cluster_certs_dir = config.get(cloud, 'cluster_certs_dir') + '/' + cluster

if path.isdir(cluster_certs_dir):
certFiles = set(listdir(cluster_certs_dir))
certRequired = set(['config', 'ca.pem', 'key.pem', 'cert.pem'])
if certRequired <= certFiles:
return fun(*args, **kwargs)
else:
force = True
logging.error("There are certificates missing in %s" %(cluster_certs_dir))
else:
try:
# create a directory with all the certificates for future use
mkdir(cluster_certs_dir)
logging.debug("Creating certs dir in " + cluster_certs_dir)
except OSError, e:
logging.error("Error while creating certificates directory")
logging.error("Error: %s" %(e))
raise tornado.web.HTTPError(UNAUTHORIZED)

# take the necessary information from the authentication json file
auth_json_file = config.get(cloud,'auth_json')
auth_json = json.load(open(auth_json_file, 'r'))['auth']

os_user_base = auth_json.get('identity').get('password').get('user')
username = os_user_base.get('name')
user_domain_name = os_user_base.get('domain').get('name')
password = os_user_base.get('password')

os_project_base = auth_json.get('scope').get('project')
project_name = os_project_base.get('name')
project_domain_name = os_project_base.get('domain').get('name')

auth_url = config.get(cloud,'auth_id_url')
cmd_prefix = 'magnum --os-username ' + username + \
' --os-user-domain-name ' + user_domain_name + \
' --os-password ' + password + \
' --os-project-name ' + '"'+project_name+'"' + \
' --os-project-domain-name ' + project_domain_name + \
' --os-auth-url ' + auth_url

cmd = "cluster-config " + cluster
#cmd_args = ' '.join(args)
cmd_args = "--dir " + cluster_certs_dir
if force:
cmd_args = cmd_args + " --force"
cmd_final = cmd_prefix + ' ' + cmd + ' ' + cmd_args
try:
# No way to run this kind of command through the Openstack API
check_output(shlex.split(cmd_final))
logging.debug("Command %s with args %s ran successfully" %(cmd, cmd_args))
return fun(*args, **kwargs)
except CalledProcessError as e:
logging.error("Command %s with args %s failed with return code %s" %(cmd, cmd_args, e.returncode))
logging.error("Command failed with output: %s" %(e.output))
#return callback(auth_json, cmd, args)
raise tornado.web.HTTPError(UNAUTHORIZED)

return wrapper
return keystone_decorator

def get_function(composed_url, **auth):
"""
This function is used to do easily GET requests without checking the results every time.

:param url: The url the request will be sent to

:param headers: The value is a *dict*, the token in the header which is used to access openstack through keystone
:type headers: dict

or

:param url: The url the request will be sent to
:param cert: The value is a *str*, the path to the certificate which is usually used to access kubernetes
:type cert: dict
:param key: The value is a str, the path to the private key
:type key: dict
:param ca: The value is a str, the path to the certificate authority
:type ca: dict

:return: The json data and the status_code
:rtype: json, int

"""
if auth.get('headers'):
response = requests.get(composed_url,
headers=auth.get('headers'))
elif auth.get('cert') and auth.get('key') and auth.get('ca'):
response = requests.get(composed_url,
cert=(auth.get('cert'), auth.get('key')),
verify=auth.get('ca'))
else:
return {}, 401

if response.ok:
try:
data = response.json()
except ValueError:
return {}, 500
if data:
return data, response.status_code
return {}, response.status_code,

def get_instance_id_by_name(name):
"""Common function to get the ID of an instance by its name."""
response = requests.get(config.get('postgrest', 'instance_url') + "?db_name=eq." + name)
Expand All @@ -83,7 +239,7 @@ def get_instance_id_by_name(name):
if data:
return data[0]["id"]
return None

class DocHandler(tornado.web.RequestHandler):
"""Shows the list of endpoints available in the API"""
def get(self):
Expand Down
Loading