diff --git a/README.md b/README.md index e883fab1..6fa6f852 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,4 @@ # shipyard Directed acyclic graph controller for Kubernetes and OpenStack control plane life cycle management + +## Testing 1 2 3 diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..6712db3d --- /dev/null +++ b/setup.py @@ -0,0 +1,30 @@ +# Copyright 2017 AT&T Intellectual Property. All other rights reserved. +# +# 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 setuptools import setup + +setup(name='shipyard_airflow', + version='0.1a1', + description='API for managing Airflow-based orchestration', + url='http://github.com/att-comdev/shipyard', + author='Anthony Lin - AT&T', + author_email='al498u@att.com', + license='Apache 2.0', + packages=['shipyard_airflow', + 'shipyard_airflow.control'], + install_requires=[ + 'falcon', + 'uwsgi>1.4' + ] + ) diff --git a/helm_shipyard/control/tasks.py b/shipyard_airflow/__init__.py similarity index 79% rename from helm_shipyard/control/tasks.py rename to shipyard_airflow/__init__.py index 7831d270..2a385a45 100644 --- a/helm_shipyard/control/tasks.py +++ b/shipyard_airflow/__init__.py @@ -10,11 +10,4 @@ # 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. -import falcon - -from .base import BaseResource - -class TasksResource(BaseResource): - -class TaskResource(BaseResource): +# limitations under the License. \ No newline at end of file diff --git a/helm_shipyard/control/__init__.py b/shipyard_airflow/control/__init__.py similarity index 100% rename from helm_shipyard/control/__init__.py rename to shipyard_airflow/control/__init__.py diff --git a/helm_shipyard/control/api.py b/shipyard_airflow/control/api.py similarity index 52% rename from helm_shipyard/control/api.py rename to shipyard_airflow/control/api.py index af905bb3..e57f6427 100644 --- a/helm_shipyard/control/api.py +++ b/shipyard_airflow/control/api.py @@ -12,18 +12,38 @@ # See the License for the specific language governing permissions and # limitations under the License. import falcon +import json + +from .regions import RegionsResource, RegionResource +from .base import ShipyardRequest, BaseResource -from .tasks import TasksResource -from .base import ShipyardRequest from .middleware import AuthMiddleware, ContextMiddleware, LoggingMiddleware -def start_api(state_manager): +def start_api(): control_api = falcon.API(request_type=ShipyardRequest, middleware=[AuthMiddleware(), ContextMiddleware(), LoggingMiddleware()]) - # API for managing region data - control_api.add_route('/region/{region_id}', TasksResource) - control_api.add_route('/region/{region_id}/server/{name}', TasksResource) - control_api.add_route('/region/{region_id}/service/{kind}', TasksResource) + control_api.add_route('/versions', VersionsResource()) + + # v1.0 of Drydock API + v1_0_routes = [ + # API for managing region data + ('/regions', RegionsResource()), + ('/regions/{region_id}', RegionResource()), + ] + + for path, res in v1_0_routes: + control_api.add_route('/api/v1.0' + path, res) return control_api + +class VersionsResource(BaseResource): + + authorized_roles = ['anyone'] + + def on_get(self, req, resp): + resp.body = json.dumps({'v1.0': { + 'path': '/api/v1.0', + 'status': 'stable' + }}) + resp.status = falcon.HTTP_200 \ No newline at end of file diff --git a/helm_shipyard/control/base.py b/shipyard_airflow/control/base.py similarity index 88% rename from helm_shipyard/control/base.py rename to shipyard_airflow/control/base.py index e380a995..bb7e051f 100644 --- a/helm_shipyard/control/base.py +++ b/shipyard_airflow/control/base.py @@ -16,6 +16,8 @@ import uuid class BaseResource(object): + authorized_roles = [] + def on_options(self, req, resp): self_attrs = dir(self) methods = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'PATCH'] @@ -30,7 +32,13 @@ class BaseResource(object): # By default, no one is authorized to use a resource def authorize_roles(self, role_list): - return False + authorized = set(self.authorized_roles) + applied = set(role_list) + + if authorized.isdisjoint(applied): + return False + else: + return True class ShipyardRequestContext(object): @@ -62,5 +70,5 @@ class ShipyardRequestContext(object): def set_external_marker(self, marker): self.external_marker = str(marker)[:32] -class ShipyardRequest(request.Request) +class ShipyardRequest(request.Request): context_type = ShipyardRequestContext diff --git a/helm_shipyard/control/middleware.py b/shipyard_airflow/control/middleware.py similarity index 79% rename from helm_shipyard/control/middleware.py rename to shipyard_airflow/control/middleware.py index 3a35370c..019053e2 100644 --- a/helm_shipyard/control/middleware.py +++ b/shipyard_airflow/control/middleware.py @@ -11,8 +11,8 @@ # 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. - import falcon +import logging class AuthMiddleware(object): @@ -31,7 +31,7 @@ class AuthMiddleware(object): ctx.add_role('anyone') # Authorization - def process_resource(self, req, resp, resource): + def process_resource(self, req, resp, resource, params): ctx = req.context if not resource.authorize_roles(ctx.roles): @@ -67,7 +67,22 @@ class ContextMiddleware(object): elif requested_logging == 'INFO': ctx.set_log_level('info') + ext_marker = req.get_header('X-Context-Marker') + ctx.set_external_marker(ext_marker if ext_marker is not None else '') + class LoggingMiddleware(object): + def __init__(self): + self.logger = logging.getLogger('shipyard.control') + def process_response(self, req, resp, resource, req_succeeded): ctx = req.context + + extra = { + 'user': ctx.user, + 'req_id': ctx.request_id, + 'external_ctx': ctx.external_marker, + } + + resp.append_header('X-Shipyard-Req', ctx.request_id) + self.logger.info("%s - %s" % (req.uri, resp.status), extra=extra) \ No newline at end of file diff --git a/shipyard_airflow/control/regions.py b/shipyard_airflow/control/regions.py new file mode 100644 index 00000000..32808528 --- /dev/null +++ b/shipyard_airflow/control/regions.py @@ -0,0 +1,30 @@ +# Copyright 2017 AT&T Intellectual Property. All other rights reserved. +# +# 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. +import falcon + +from .base import BaseResource + +class RegionsResource(BaseResource): + + authorized_roles = ['user'] + + def on_get(self, req, resp): + resp.status = falcon.HTTP_200 + +class RegionResource(BaseResource): + + authorized_roles = ['user'] + + def on_get(self, req, resp, region_id): + resp.status = falcon.HTTP_200 \ No newline at end of file diff --git a/shipyard_airflow/setup.py b/shipyard_airflow/setup.py new file mode 100644 index 00000000..d6fdf76c --- /dev/null +++ b/shipyard_airflow/setup.py @@ -0,0 +1,48 @@ +# Copyright 2017 AT&T Intellectual Property. All other rights reserved. +# +# 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 setuptools import setup + +setup(name='drydock_provisioner', + version='0.1a1', + description='Bootstrapper for Kubernetes infrastructure', + url='http://github.com/att-comdev/drydock', + author='Scott Hussey - AT&T', + author_email='sh8121@att.com', + license='Apache 2.0', + packages=['drydock_provisioner', + 'drydock_provisioner.objects', + 'drydock_provisioner.ingester', + 'drydock_provisioner.ingester.plugins', + 'drydock_provisioner.statemgmt', + 'drydock_provisioner.orchestrator', + 'drydock_provisioner.control', + 'drydock_provisioner.drivers', + 'drydock_provisioner.drivers.oob', + 'drydock_provisioner.drivers.oob.pyghmi_driver', + 'drydock_provisioner.drivers.node', + 'drydock_provisioner.drivers.node.maasdriver', + 'drydock_provisioner.drivers.node.maasdriver.models', + 'drydock_provisioner.control'], + install_requires=[ + 'PyYAML', + 'pyghmi>=1.0.18', + 'netaddr', + 'falcon', + 'oslo.versionedobjects>=1.23.0', + 'requests', + 'oauthlib', + 'uwsgi>1.4', + ] + ) diff --git a/shipyard_airflow/shipyard.py b/shipyard_airflow/shipyard.py new file mode 100644 index 00000000..5f95458b --- /dev/null +++ b/shipyard_airflow/shipyard.py @@ -0,0 +1,39 @@ +# Copyright 2017 AT&T Intellectual Property. All other rights reserved. +# +# 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. +import logging +import control.api as api + +def start_shipyard(): + + # Setup root logger + logger = logging.getLogger('shipyard') + + logger.setLevel('DEBUG') + ch = logging.StreamHandler() + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s') + ch.setFormatter(formatter) + logger.addHandler(ch) + + # Specalized format for API logging + logger = logging.getLogger('shipyard.control') + logger.propagate = False + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(user)s - %(req_id)s - %(external_ctx)s - %(message)s') + + ch = logging.StreamHandler() + ch.setFormatter(formatter) + logger.addHandler(ch) + + return api.start_api() + +shipyard = start_shipyard() \ No newline at end of file