-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #2 from mdgreenwald/matthew/poc1
Matthew/poc1
- Loading branch information
Showing
17 changed files
with
229 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,3 +33,7 @@ venv.bak/ | |
|
||
# macos | ||
.DS_Store | ||
|
||
# secrets | ||
*secrets* | ||
*credentials* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -105,3 +105,7 @@ venv.bak/ | |
|
||
# macos | ||
.DS_Store | ||
|
||
# secrets | ||
*secrets* | ||
*credentials* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,8 @@ | ||
# Push-Deploy # | ||
|
||
Push-Deploy is a Python application which helps to securely and simply enable communication between external tools (GitHub Actions, Circle CI, etc…) and Kubernetes without exposing credentials. | ||
Push-Deploy is a Python application which helps to securely and simply enable communication between external tools (GitHub Actions, Circle CI, etc…) and Kubernetes without exposing cluster credentials. | ||
|
||
In particular for projects which may not have semver inplace where other tools like keel and weave/flux make more sense. | ||
In particular for projects which may not have `semver` inplace where other tools like keel.sh and weave/flux would make more sense. | ||
|
||
-- | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
# one static YAML file | ||
k8s_yaml('./kubernetes/app.yaml') | ||
|
||
docker_build('docker.io/library/push-deploy', '.') | ||
docker_build('push-deploy', '.') | ||
|
||
k8s_resource('push-deploy', port_forwards='5000:5000') |
Empty file.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import os | ||
basedir = os.path.abspath(os.path.dirname(__file__)) | ||
|
||
PD_NAMESPACE = os.environ.get('PD_NAMESPACE') | ||
PD_DEPLOYMENT = os.environ.get('PD_DEPLOYMENT') | ||
PD_REGISTRY = os.environ.get('PD_REGISTRY') | ||
PD_USER = os.environ.get('PD_USER') | ||
PD_PASSWORD = os.environ.get('PD_PASSWORD') | ||
SECRET_KEY = os.environ.get('PD_SECRET_KEY') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
--- | ||
apiVersion: extensions/v1beta1 | ||
kind: Ingress | ||
metadata: | ||
name: push-deploy | ||
spec: | ||
rules: | ||
- host: pushdeploy.internal | ||
http: | ||
paths: | ||
- path: / | ||
backend: | ||
serviceName: push-deploy | ||
servicePort: 80 | ||
|
||
--- |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
from version import __version__ | ||
import os | ||
from kubernetes import client, config | ||
from flask import Flask, jsonify | ||
from flask_jwt_extended import ( | ||
JWTManager, jwt_required, jwt_optional, create_access_token, | ||
get_jwt_identity | ||
) | ||
from pushdeploy import apiv1 | ||
|
||
def create_app(test_config=None): | ||
"""Create and configure an instance of the Flask application.""" | ||
app = Flask(__name__, instance_relative_config=True) | ||
app.config.from_object('config') | ||
|
||
app.config['JWT_SECRET_KEY'] = app.config['SECRET_KEY'] | ||
jwt = JWTManager(app) | ||
|
||
@jwt.expired_token_loader | ||
def my_expired_token_callback(expired_token): | ||
token_type = expired_token['type'] | ||
return jsonify({ | ||
'status': 401, | ||
'sub_status': 42, | ||
'msg': 'The {} token has expired'.format(token_type) | ||
}), 401 | ||
|
||
if test_config is None: | ||
app.config.from_pyfile("config.py", silent=False) | ||
else: | ||
app.config.update(test_config) | ||
|
||
try: | ||
os.makedirs(app.instance_path) | ||
except OSError: | ||
pass | ||
|
||
@app.route('/health', methods=['GET']) | ||
@jwt_optional | ||
def health(): | ||
return jsonify( | ||
status='healthy', | ||
releaseId=__version__, | ||
), 200 | ||
|
||
@app.route('/', methods=['GET']) | ||
@jwt_required | ||
def index(): | ||
return jsonify(), 200 | ||
|
||
app.register_blueprint(apiv1.bp) | ||
|
||
return app |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import functools | ||
import json | ||
from kubernetes import client, config | ||
from datetime import timedelta | ||
from flask import Blueprint | ||
from flask import current_app | ||
from flask import flash | ||
from flask import g | ||
from flask import redirect | ||
from flask import render_template | ||
from flask import request | ||
from flask import session | ||
from flask import url_for | ||
from flask import jsonify | ||
|
||
from flask_jwt_extended import ( | ||
JWTManager, jwt_required, jwt_optional, create_access_token, | ||
get_jwt_identity | ||
) | ||
|
||
bp = Blueprint("apiv1", __name__, url_prefix="/api/v1") | ||
|
||
@bp.before_app_request | ||
def init_api(): | ||
"""Creates instances of the incluster config and client API | ||
and stores them in global""" | ||
g.configuration = config.load_incluster_config() | ||
g.api_instance = client.AppsV1Api(client.ApiClient(g.configuration)) | ||
g.PD_NAMESPACE = current_app.config['PD_NAMESPACE'] | ||
g.PD_DEPLOYMENT = current_app.config['PD_DEPLOYMENT'] | ||
g.PD_REGISTRY = current_app.config['PD_REGISTRY'] | ||
|
||
def read_deployment(): | ||
namespace = "%s" % str(g.PD_NAMESPACE) | ||
field = "metadata.name=%s" % str(g.PD_DEPLOYMENT) | ||
api_response = g.api_instance.list_namespaced_deployment( | ||
namespace=namespace, | ||
field_selector=field | ||
) | ||
if len(api_response.items) == 1: | ||
return api_response.items[0] | ||
else: | ||
return "Deployment selector not unique enough." | ||
|
||
def update_deployment(deployment, image_name, image_tag): | ||
image = "%s/%s:%s" % (g.PD_REGISTRY, image_name, image_tag) | ||
deployment.spec.template.spec.containers[0].image = image | ||
api_response = g.api_instance.patch_namespaced_deployment( | ||
name=g.PD_DEPLOYMENT, | ||
namespace=g.PD_NAMESPACE, | ||
body=deployment, | ||
field_manager="push-deploy") | ||
print("Deployment updated. status='%s'" % str(api_response.status)) | ||
|
||
@bp.route('/', methods=['GET']) | ||
@jwt_required | ||
def index(): | ||
return jsonify(), 200 | ||
|
||
@bp.route('/auth', methods=['POST']) | ||
def login(): | ||
if not request.is_json: | ||
return jsonify({"msg": "Missing JSON in request"}), 400 | ||
|
||
username = request.json.get('username', None) | ||
password = request.json.get('password', None) | ||
if not username: | ||
return jsonify({"msg": "Missing username parameter"}), 400 | ||
if not password: | ||
return jsonify({"msg": "Missing password parameter"}), 400 | ||
|
||
if username != current_app.config['PD_USER'] or password != current_app.config['PD_PASSWORD']: | ||
return jsonify({"msg": "Bad username or password"}), 401 | ||
|
||
# Identity can be any data that is json serializable | ||
access_token = create_access_token(identity=username, expires_delta=timedelta(seconds=90)) | ||
return jsonify(access_token=access_token), 200 | ||
|
||
@bp.route('/deploy', methods=['GET']) | ||
@jwt_required | ||
def deploy(): | ||
commit_sha = request.args['commit_sha'] | ||
image_name = request.args['image_name'] | ||
deploy = update_deployment(deployment=read_deployment(), image_name=image_name, image_tag=commit_sha) | ||
return jsonify(msg=deploy), 201 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
kubernetes==10.0.0 | ||
kubernetes==10.0.1 | ||
Flask==1.1.1 | ||
Flask-API==1.1 | ||
flask-jwt-extended==3.21.0 | ||
gunicorn==19.9.0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
__version__ = '0.0.1' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
import os | ||
from werkzeug.middleware.proxy_fix import ProxyFix | ||
from pushdeploy import create_app | ||
|
||
app = ProxyFix(create_app(), x_for=1, x_host=1) |