Commit aa0bc4ee authored by Jonas Waeber's avatar Jonas Waeber
Browse files

Merge branch 'remove-restful-flask'

# Conflicts:
#	deploy-prod.sh
#	deploy-test.sh
parents 976716db 3ff811f0
Pipeline #37212 passed with stage
in 51 seconds
*.sh
.gitlab-ci.yml
.pre-commit-config.yaml
helm-charts/
\ No newline at end of file
......@@ -7,13 +7,4 @@ include:
stages:
- test
- publish
test:
stage: test
image: python:3.8
before_script:
- pip install pip --upgrade
- pip install -r requirements.txt
script:
- flake8 ./autodeploy_service_app
- publish
\ No newline at end of file
......@@ -7,23 +7,20 @@ ENV FLASK_APP autodeploy_service_app
EXPOSE 5000
ENTRYPOINT ["gunicorn"]
CMD ["--bind", "0.0.0.0:5000", "wsgi:app", "--log-level", "info"]
CMD [ "wsgi:app", "--config", "/configs/gunicorn.conf.py"]
RUN cd /usr/bin \
&& wget -q https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl \
&& chmod +x ./kubectl \
&& wget -q https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz \
&& tar -xvzf helm-${HELM_VERSION}-linux-amd64.tar.gz \
&& mv linux-amd64/helm helm \
&& rm -rf linux-amd64
&& wget -q https://storage.googleapis.com/kubernetes-release/release/${K8S_VERSION}/bin/linux/amd64/kubectl \
&& chmod +x ./kubectl \
&& wget -q https://get.helm.sh/helm-${HELM_VERSION}-linux-amd64.tar.gz \
&& tar -xvzf helm-${HELM_VERSION}-linux-amd64.tar.gz \
&& mv linux-amd64/helm helm \
&& rm -rf linux-amd64
WORKDIR /
ADD setup.py /
RUN mkdir autodeploy_service_app \
&& pip install -e .
&& pip install --no-cache-dir -e .
WORKDIR /autodeploy_service_app
ADD requirements.txt .
RUN pip install -r requirements.txt
ADD autodeploy_service_app .
from flask import Flask
from autodeploy_service_app import configuration
app = Flask(__name__)
app.config.from_object(configuration)
app = Flask(__name__)
\ No newline at end of file
from flask_restful import Resource
from flask import request as flaskRequest
import json
import subprocess
from re import match
from os import environ, listdir, path, getenv
from re import match
from shutil import rmtree
from tempfile import mkdtemp
from flask import request as flask_request
from flask.views import MethodView
from autodeploy_service_app.app import app
class AutoDeploy(Resource):
class AutoDeploy(MethodView):
def post(self):
'''
Deploy on k8s
......@@ -46,7 +49,7 @@ class AutoDeploy(Resource):
output = []
try:
headers = flaskRequest.headers
headers = flask_request.headers
secure_token = getenv('SECURE_TOKEN')
if secure_token and not headers.get('X-Gitlab-Token'):
msg = 'Request does not have an X-Gitlab-Token in headers'
......@@ -56,7 +59,7 @@ class AutoDeploy(Resource):
msg = 'Request does not have a valid X-Gitlab-Token in headers'
app.logger.warning(msg)
return msg, 403
body = json.loads(flaskRequest.data.decode('utf-8'))
body = json.loads(flask_request.data.decode('utf-8'))
tag = ''
branch = ''
if body['object_attributes']['tag']:
......@@ -76,12 +79,12 @@ class AutoDeploy(Resource):
'commit with semver-tag detected: installing on prod+stage'
)
pullChartUri = (
environ['GITLAB_REGISTRY']
+ '/'
+ repositoryPath
+ ':'
+ tag
+ '-chart'
environ['GITLAB_REGISTRY']
+ '/'
+ repositoryPath
+ ':'
+ tag
+ '-chart'
)
msgs, status = installFromRepo(pullChartUri)
output.extend(msgs)
......@@ -249,10 +252,10 @@ def installFromRepo(pullChartUri):
)
except subprocess.CalledProcessError as ex:
msg = (
'removing helm chart from local repository'
+ 'failed with return code {} -- STDOUT: {} -- STDERR: {}'.format(
ex.returncode, ex.stdout, ex.stderr
)
'removing helm chart from local repository'
+ 'failed with return code {} -- STDOUT: {} -- STDERR: {}'.format(
ex.returncode, ex.stdout, ex.stderr
)
)
app.logger.warning(msg)
return output, status
......
import logging
from os import path, environ
from flasgger import Swagger
from flask import send_from_directory, redirect
from flask.logging import default_handler
from flask_restful import Api
from kubernetes import config
from os import path, environ
import logging
from autodeploy_service_app.app import app
from autodeploy_service_app.autodeploy import AutoDeploy
# TODO : maybe take that to a configuration (development vs pod running in
# k8s cluster)
try:
# to be used when inside a kubernetes cluster
config.load_incluster_config()
except BaseException:
try:
# use .kube directory
# for local development
config.load_kube_config()
except BaseException:
app.logger.error('No kubernetes cluster defined')
environ['HELM_EXPERIMENTAL_OCI'] = '1'
# If app is started via gunicorn
if __name__ != '__main__':
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(gunicorn_logger.level)
app.logger.removeHandler(default_handler)
app.logger = gunicorn_logger
app.logger.info('Starting production server')
api = Api(app)
app.config['SWAGGER'] = {
'title': 'autodeploy-service',
'version': 'dev',
......@@ -65,7 +45,7 @@ def favicon():
)
api.add_resource(AutoDeploy, '/v1/autodeploy')
app.add_url_rule('/v1/autodeploy', view_func=AutoDeploy.as_view('autodeploy'))
# If app is started with Flask
if __name__ == '__main__':
......
#!/usr/bin/env bash
helm upgrade --install -f ./helm-charts/helm-values/api-autodeploy-prod.yaml api-autodeploy-prod-deployment ./helm-charts
\ No newline at end of file
#!/usr/bin/env bash
helm upgrade --install -f ./helm-charts/helm-values/api-autodeploy-test.yaml api-autodeploy-test-deployment ./helm-charts
\ No newline at end of file
bind = "0.0.0.0:5000"
reload = True
accesslog = "/dev/stdout"
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
disable_redirect_access_to_syslog = True
errorlog = "/dev/stderr"
loglevel = 'info'
workers = 1
logconfig_dict = dict(
version=1,
disable_existing_loggers=True,
loggers={
"gunicorn.error": {
"level": "INFO",
"handlers": ["error_console"],
"propagate": False,
"qualname": "gunicorn.error"
}
},
formatters={
"generic": {
"format": "[%(levelname)s] [%(name)s] %(message)s",
"datefmt": "[%Y-%m-%d %H:%M:%S %z]",
"class": "logging.Formatter"
}
}
)
bind = "0.0.0.0:5000"
reload = True
accesslog = "/dev/stdout"
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"'
disable_redirect_access_to_syslog = True
errorlog = "/dev/stderr"
loglevel = 'debug'
workers = 1
logconfig_dict = dict(
version=1,
disable_existing_loggers=True,
loggers={
"gunicorn.error": {
"level": "DEBUG",
"handlers": ["error_console"],
"propagate": False,
"qualname": "gunicorn.error"
}
},
formatters={
"generic": {
"format": "[%(levelname)s] [%(name)s] %(message)s",
"datefmt": "[%Y-%m-%d %H:%M:%S %z]",
"class": "logging.Formatter"
}
}
)
tag: "secure-token"
tag: "remove-restful-flask"
k8sEnvironment: "test"
k8sReplicas: 1
......
......@@ -33,6 +33,9 @@ spec:
envFrom:
- configMapRef:
name: "{{ .Values.k8sGroupId }}-{{ .Values.k8sName }}-{{ .Values.k8sEnvironment }}-config-map"
volumeMounts:
- name: gunicorn-conf
mountPath: "/configs"
ports:
- containerPort: {{ .Values.k8sPort }}
name: http
......@@ -44,3 +47,7 @@ spec:
limits:
cpu: "{{ .Values.k8sLimitsCpu }}"
memory: "{{ .Values.k8sLimitsMemory }}"
volumes:
- name: gunicorn-conf
configMap:
name: "{{ .Values.k8sGroupId }}-{{ .Values.k8sName }}-{{ .Values.k8sEnvironment }}-gunicorn-config-map"
\ No newline at end of file
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Values.k8sGroupId }}-{{ .Values.k8sName }}-{{ .Values.k8sEnvironment }}-gunicorn-config-map"
namespace: "{{ .Values.k8sNamespace }}"
labels:
app: "{{ .Values.k8sGroupId }}-{{ .Values.k8sName }}-{{ .Values.k8sEnvironment }}-app"
group: "{{ .Values.k8sGroupName }}"
environment: "{{ .Values.k8sEnvironment }}"
data:
{{- if eq .Values.k8sEnvironment "test" }}
{{- (.Files.Glob "configmap/test/gunicorn.conf.py").AsConfig | nindent 2 }}
{{- else }}
{{- (.Files.Glob "configmap/prod/gunicorn.conf.py").AsConfig | nindent 2 }}
{{- end }}
\ No newline at end of file
......@@ -9,9 +9,9 @@ metadata:
name: "{{ .Values.k8sGroupId }}-{{ .Values.k8sName }}-{{ .Values.k8sEnvironment }}-role"
namespace: "{{ .Values.k8sNamespace }}"
rules:
- apiGroups: ["", "apps", "networking.k8s.io", "rbac.authorization.k8s.io"] # "" indicates the core API group
resources: ["deployments", "pods", "ingresses", "serviceaccounts", "roles", "rolebindings", "services", "secrets", "configmaps", "jobs"]
verbs: ["apply", "get", "list", "create", "watch", "create", "update", "patch", "delete", "bind"]
- apiGroups: ["", "apps", "batch", "networking.k8s.io", "rbac.authorization.k8s.io"] # "" indicates the core API group
resources: ["cronjobs", "deployments", "pods", "ingresses", "serviceaccounts", "roles", "rolebindings", "services", "secrets", "configmaps", "jobs"]
verbs: ["apply", "get", "list", "create", "watch", "update", "patch", "delete", "bind"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
......
......@@ -5,6 +5,6 @@ setup(
packages=["autodeploy_service_app"],
include_package_data=True,
install_requires=[
"flask",
"flask", "gunicorn", "flasgger"
],
)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment