diff --git a/.github/workflows/publish.yaml b/.github/workflows/publish.yaml index 0a990d5..97a31b8 100644 --- a/.github/workflows/publish.yaml +++ b/.github/workflows/publish.yaml @@ -1,4 +1,4 @@ -name: Publish to GHCR +name: Publish tmp to GHCR env: RELEASE: edge @@ -8,10 +8,7 @@ concurrency: cancel-in-progress: true on: - push: - branches: - - 6-22.04 - workflow_dispatch: + pull_request: jobs: build: @@ -63,12 +60,13 @@ jobs: # push major version to edge major_tag_version="${version%%.*}-${{ env.RELEASE }}" + sudo skopeo \ --insecure-policy \ copy \ oci-archive:charmed-mongodb_${full_version}_amd64.rock \ - docker-daemon:ghcr.io/canonical/charmed-mongodb:${major_tag_version} - docker push ghcr.io/canonical/charmed-mongodb:${major_tag_version} + docker-daemon:ghcr.io/miaaltieri/charmed-mongodb:${major_tag_version} + docker push ghcr.io/miaaltieri/charmed-mongodb:${major_tag_version} ### push full version to edge tag_version="${version}-${base}_${{ env.RELEASE }}" @@ -77,5 +75,5 @@ jobs: --insecure-policy \ copy \ oci-archive:charmed-mongodb_${full_version}_amd64.rock \ - docker-daemon:ghcr.io/canonical/charmed-mongodb:${tag_version} - docker push ghcr.io/canonical/charmed-mongodb:${tag_version} + docker-daemon:ghcr.io/miaaltieri/charmed-mongodb:${tag_version} + docker push ghcr.io/miaaltieri/charmed-mongodb:${tag_version} diff --git a/app.py b/app.py new file mode 100644 index 0000000..d1dab96 --- /dev/null +++ b/app.py @@ -0,0 +1,119 @@ +# Copyright 2024 Canonical Ltd. +# See LICENSE file for licensing details. +from typing import Any +from flask import Flask, request, jsonify +import logging +import base64 +from pydantic import BaseModel, TypeAdapter +import os + +# Default to 1 year +YEAR = 31_556_952 +GRACE_PERIOD: int = int(os.getenv("GRACE_PERIOD_SECONDS", YEAR)) + + +class Patch(BaseModel): + op: str + path: str = "/spec/template/spec/terminationGracePeriodSeconds" + value: int + + +app = Flask(__name__) + +webhook = logging.getLogger(__name__) +webhook.setLevel(logging.INFO) +logging.basicConfig(format="[%(asctime)s] %(levelname)s: %(message)s") + +ADAPTER = TypeAdapter(list[Patch]) + + +def patch_termination(existing_value: bool) -> str: + op = "replace" if existing_value else "add" + webhook.info(f"Updating terminationGracePeriodSeconds, replacing it ({op = })") + patch_operations = [ + Patch( + op=op, + value=GRACE_PERIOD, + ) + ] + return base64.b64encode(ADAPTER.dump_json(patch_operations)).decode() + + +def admission_review(uid: str, message: str, existing_value: bool) -> dict: + print("admission_review - existing_value", existing_value) + if existing_value: + return { + "apiVersion": "admission.k8s.io/v1", + "kind": "AdmissionReview", + "response": { + "uid": uid, + "allowed": True, + "patchType": "JSONPatch", + "status": {"message": message}, + "patch": patch_termination(existing_value), + }, + } + return { + "apiVersion": "admission.k8s.io/v1", + "kind": "AdmissionReview", + "response": { + "uid": uid, + "allowed": True, + "status": {"message": "No value provided, continue."}, + }, + } + + +def admission_validation(uid: str, current_value: int | None): + if not current_value or current_value > 30: + print("current value", current_value) + return { + "apiVersion": "admission.k8s.io/v1", + "kind": "AdmissionReview", + "response": { + "uid": uid, + "allowed": True, + "status": {"message": f"Valid value has been provided ({current_value})"}, + }, + } + return { + "apiVersion": "admission.k8s.io/v1", + "kind": "AdmissionReview", + "response": { + "uid": uid, + "allowed": False, + "status": { + "code": 403, + "message": f"Termination period lower than 30s is not allowed (given {current_value})", + }, + }, + } + + +@app.route("/mutate", methods=["POST"]) +def mutate_request(): + req = request.get_json() + uid = req["request"]["uid"] + selector = req["request"]["object"]["spec"]["template"]["spec"] + + return jsonify( + admission_review( + uid, + "Successfully updated terminationGracePeriodSeconds.", + True if "terminationGracePeriodSeconds" in selector else False, + ) + ) + + +@app.route("/validate", methods=["POST"]) +def validate_request(): + req = request.get_json() + uid = req["request"]["uid"] + selector = req["request"]["object"]["spec"]["template"]["spec"] + period_value = selector.get("terminationGracePeriodSeconds") + + return jsonify(admission_validation(uid, period_value)) + + +if __name__ == "__main__": + app.run(host="0.0.0.0", port=8000) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..7424927 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,5 @@ +# Copyright 2024 Canonical Ltd. +# See LICENSE file for licensing details. +pydantic>=2.0,<3.0 +uvicorn +flask \ No newline at end of file