Initial commit
This commit is contained in:
		
							
								
								
									
										25
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								.drone.yml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					kind: pipeline
 | 
				
			||||||
 | 
					type: docker
 | 
				
			||||||
 | 
					name: default
 | 
				
			||||||
 | 
					steps:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - name: code-analysis
 | 
				
			||||||
 | 
					    image: aosapps/drone-sonar-plugin
 | 
				
			||||||
 | 
					    settings:
 | 
				
			||||||
 | 
					      sonar_host:
 | 
				
			||||||
 | 
					        from_secret: SONAR_HOST
 | 
				
			||||||
 | 
					      sonar_token:
 | 
				
			||||||
 | 
					        from_secret: SONAR_CODE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - name: kaniko
 | 
				
			||||||
 | 
					    image: banzaicloud/drone-kaniko
 | 
				
			||||||
 | 
					    settings:
 | 
				
			||||||
 | 
					      registry: registry.kmlabz.com
 | 
				
			||||||
 | 
					      repo: universalrobots/${DRONE_REPO_NAME}
 | 
				
			||||||
 | 
					      username:
 | 
				
			||||||
 | 
					        from_secret: DOCKER_USERNAME
 | 
				
			||||||
 | 
					      password:
 | 
				
			||||||
 | 
					        from_secret: DOCKER_PASSWORD
 | 
				
			||||||
 | 
					      tags:
 | 
				
			||||||
 | 
					        - latest
 | 
				
			||||||
 | 
					        - ${DRONE_BUILD_NUMBER}
 | 
				
			||||||
							
								
								
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					*.swp
 | 
				
			||||||
 | 
					venv
 | 
				
			||||||
 | 
					*.pyc
 | 
				
			||||||
 | 
					__pycache__/*
 | 
				
			||||||
 | 
					__pycache__
 | 
				
			||||||
 | 
					*.wpr
 | 
				
			||||||
 | 
					*.log
 | 
				
			||||||
 | 
					.idea
 | 
				
			||||||
							
								
								
									
										10
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								Dockerfile
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					FROM python:3.9
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ADD job_orchestrator_service requirements.txt /job_orchestrator_service/
 | 
				
			||||||
 | 
					WORKDIR /job_orchestrator_service/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					RUN pip3 install -r requirements.txt && pip3 install gunicorn
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					EXPOSE 8000
 | 
				
			||||||
 | 
					CMD ["gunicorn", "-b", "0.0.0.0:8000", "app:app"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										34
									
								
								job_orchestrator_service/app.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								job_orchestrator_service/app.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from config import Config
 | 
				
			||||||
 | 
					import sentry_sdk
 | 
				
			||||||
 | 
					from sentry_sdk.integrations.flask import FlaskIntegration
 | 
				
			||||||
 | 
					from flask import Flask
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from utils import register_all_error_handlers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# import views
 | 
				
			||||||
 | 
					from views import JobView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Setup sentry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if Config.SENTRY_DSN:
 | 
				
			||||||
 | 
					    sentry_sdk.init(
 | 
				
			||||||
 | 
					        dsn=Config.SENTRY_DSN,
 | 
				
			||||||
 | 
					        integrations=[FlaskIntegration()],
 | 
				
			||||||
 | 
					        send_default_pii=True,
 | 
				
			||||||
 | 
					        release=Config.RELEASE_ID,
 | 
				
			||||||
 | 
					        environment=Config.RELEASEMODE
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# create flask app
 | 
				
			||||||
 | 
					app = Flask(__name__)
 | 
				
			||||||
 | 
					app.config.from_object(Config)
 | 
				
			||||||
 | 
					register_all_error_handlers(app)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# register views
 | 
				
			||||||
 | 
					for view in [JobView]:
 | 
				
			||||||
 | 
					    view.register(app, trailing_slash=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# start debuggig if needed
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    app.run(debug=True)
 | 
				
			||||||
							
								
								
									
										15
									
								
								job_orchestrator_service/config.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								job_orchestrator_service/config.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					Configuration
 | 
				
			||||||
 | 
					"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Config:
 | 
				
			||||||
 | 
					    SECRET_KEY = os.environ.get("SECRET_KEY", os.urandom(12))
 | 
				
			||||||
 | 
					    CORS_ORIGINS = os.environ.get("ALLOWED_ORIGINS", "*")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SENTRY_DSN = os.environ.get("SENTRY_DSN")
 | 
				
			||||||
 | 
					    RELEASE_ID = os.environ.get("RELEASE_ID", "test")
 | 
				
			||||||
 | 
					    RELEASEMODE = os.environ.get("RELEASEMODE", "dev")
 | 
				
			||||||
							
								
								
									
										2
									
								
								job_orchestrator_service/schemas/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								job_orchestrator_service/schemas/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from .job_schema import JobSchema
 | 
				
			||||||
							
								
								
									
										22
									
								
								job_orchestrator_service/schemas/job_schema.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								job_orchestrator_service/schemas/job_schema.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
				
			|||||||
 | 
					from marshmallow import Schema, fields
 | 
				
			||||||
 | 
					from marshmallow.validate import Length
 | 
				
			||||||
 | 
					from marshmallow import RAISE
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from datetime import datetime
 | 
				
			||||||
 | 
					import uuid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ControlConfigurationSchema(Schema):
 | 
				
			||||||
 | 
					    pod_id = fields.UUID(required=False, missing=uuid.uuid4)
 | 
				
			||||||
 | 
					    robot_address = fields.Str(required=True)
 | 
				
			||||||
 | 
					    program_url = fields.Str(required=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class JobSchema(Schema):
 | 
				
			||||||
 | 
					    id = fields.UUID(required=False, missing=uuid.uuid4)
 | 
				
			||||||
 | 
					    created_at = fields.DateTime(required=False, missing=datetime.now)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    controllers = fields.Nested(ControlConfigurationSchema, many=True, required=True, validate=Length(min=1))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        unknown = RAISE
 | 
				
			||||||
							
								
								
									
										3
									
								
								job_orchestrator_service/utils/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								job_orchestrator_service/utils/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from .require_decorators import json_required
 | 
				
			||||||
 | 
					from .error_handlers import register_all_error_handlers
 | 
				
			||||||
							
								
								
									
										18
									
								
								job_orchestrator_service/utils/error_handlers.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								job_orchestrator_service/utils/error_handlers.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_standard_error_handler(code: int):
 | 
				
			||||||
 | 
					    def error_handler(err):
 | 
				
			||||||
 | 
					        return {"msg": str(err)}, code
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return error_handler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# function to register all handlers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def register_all_error_handlers(app):
 | 
				
			||||||
 | 
					    error_codes_to_override = [404, 403, 401, 405, 400, 409, 422]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for code in error_codes_to_override:
 | 
				
			||||||
 | 
					        app.register_error_handler(code, get_standard_error_handler(code))
 | 
				
			||||||
							
								
								
									
										16
									
								
								job_orchestrator_service/utils/require_decorators.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								job_orchestrator_service/utils/require_decorators.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from flask import request, current_app, abort
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from functools import wraps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def json_required(f):
 | 
				
			||||||
 | 
					    @wraps(f)
 | 
				
			||||||
 | 
					    def call(*args, **kwargs):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if request.is_json:
 | 
				
			||||||
 | 
					            return f(*args, **kwargs)
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            abort(400, "JSON required")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return call
 | 
				
			||||||
							
								
								
									
										3
									
								
								job_orchestrator_service/views/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								job_orchestrator_service/views/__init__.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from .job_view import JobView
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										31
									
								
								job_orchestrator_service/views/job_view.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								job_orchestrator_service/views/job_view.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env python3
 | 
				
			||||||
 | 
					from flask import request, jsonify, current_app, abort, Response
 | 
				
			||||||
 | 
					from flask_classful import FlaskView, route
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from utils import json_required
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from marshmallow.exceptions import ValidationError
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					from schemas import JobSchema
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class JobView(FlaskView):
 | 
				
			||||||
 | 
					    job_schema = JobSchema(many=False)
 | 
				
			||||||
 | 
					    jobs_schema = JobSchema(many=True, exclude=['controllers'])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def index(self):
 | 
				
			||||||
 | 
					        # List all jobs
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get(self, _id: str):
 | 
				
			||||||
 | 
					        # Get info about a job
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @json_required
 | 
				
			||||||
 | 
					    def post(self):
 | 
				
			||||||
 | 
					        # Start (schedule) a job
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def delete(self, _id: str):
 | 
				
			||||||
 | 
					        # stop a job
 | 
				
			||||||
 | 
					        pass
 | 
				
			||||||
							
								
								
									
										7
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								requirements.txt
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					pyyaml
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					blinker
 | 
				
			||||||
 | 
					Flask
 | 
				
			||||||
 | 
					marshmallow
 | 
				
			||||||
 | 
					Flask-Classful
 | 
				
			||||||
 | 
					sentry-sdk
 | 
				
			||||||
		Reference in New Issue
	
	Block a user