File tree Expand file tree Collapse file tree 7 files changed +157
-1
lines changed Expand file tree Collapse file tree 7 files changed +157
-1
lines changed Original file line number Diff line number Diff line change 1+ name : Deploy on AKS
2+
3+ on :
4+ push :
5+ branches :
6+ - ' **'
7+ workflow_dispatch :
8+ inputs :
9+ environment :
10+ required : true
11+ type : string
12+ default : dev
13+ description : env
14+
15+ env :
16+ NAMESPACE : afm
17+ APP_NAME : rtp-platform-qa
18+
19+ permissions :
20+ id-token : write
21+ contents : read
22+
23+ jobs :
24+ deploy :
25+ runs-on : [ self-hosted, self-hosted-job, "${{ github.event.inputs.environment || 'dev' }}" ]
26+ environment : ${{ github.event.inputs.environment || 'dev' }}
27+ steps :
28+ - uses : actions/checkout@v4
29+
30+ - name : Check runner environment
31+ run : |
32+ echo "🏃 Running on environment: ${{ github.event.inputs.environment || 'dev' }}"
33+ echo "📦 Namespace: ${{ env.NAMESPACE }}"
34+ echo "📦 App: ${{ env.APP_NAME }}"
Original file line number Diff line number Diff line change @@ -122,7 +122,7 @@ celerybeat.pid
122122* .sage.py
123123
124124# Environments
125- .env
125+ gpd-test / .env
126126.venv
127127env /
128128venv /
Original file line number Diff line number Diff line change 1+ from enum import Enum
2+ from pydantic import BaseModel , Field
3+
4+ class RTPOperationCode (str , Enum ):
5+ CREATE = "CREATE"
6+ UPDATE = "UPDATE"
7+ DELETE = "DELETE"
8+
9+ class PaymentPositionStatus (str , Enum ):
10+ CREATED = "CREATED"
11+ SENT = "SENT"
12+ ACCEPTED = "ACCEPTED"
13+
14+ class RTPMessage (BaseModel ):
15+ id : int
16+ operation : RTPOperationCode
17+ timestamp : int
18+ iuv : str
19+ subject : str
20+ description : str
21+ ec_tax_code : str = Field (..., alias = "ec_tax_code" )
22+ debtor_tax_code : str = Field (..., alias = "debtor_tax_code" )
23+ nav : str
24+ due_date : int = Field (..., alias = "due_date" )
25+ amount : int
26+ status : PaymentPositionStatus
27+ psp_code : str = Field (..., alias = "psp_code" )
28+ psp_tax_code : str = Field (..., alias = "psp_tax_code" )
29+ is_partial_payment : bool = Field (..., alias = "is_partial_payment" )
Original file line number Diff line number Diff line change 1+ # from azure.identity import AzureCliCredential
2+ # from azure.keyvault.secrets import SecretClient
3+ # import os
4+ #
5+ # def get_eventhub_connection_string():
6+ # keyvault_name = os.environ["KEYVAULT_NAME"]
7+ # secret_name = os.environ["EVENTHUB_SECRET_NAME"]
8+ #
9+ # keyvault_url = f"https://{keyvault_name}.vault.azure.net"
10+ # credential = AzureCliCredential()
11+ # client = SecretClient(vault_url=keyvault_url, credential=credential)
12+ #
13+ # secret = client.get_secret(secret_name)
14+ # print(f"[KeyVault] Retrieved secret '{secret_name}' from '{keyvault_name}'")
15+ # return secret.value
16+
17+ from azure .identity import DefaultAzureCredential
18+ from azure .keyvault .secrets import SecretClient
19+ import os
20+
21+ def get_eventhub_connection_string ():
22+ keyvault_name = os .environ ["KEYVAULT_NAME" ]
23+ secret_name = os .environ ["EVENTHUB_SECRET_NAME" ]
24+
25+ keyvault_url = f"https://{ keyvault_name } .vault.azure.net"
26+ credential = DefaultAzureCredential ()
27+ client = SecretClient (vault_url = keyvault_url , credential = credential )
28+
29+ secret = client .get_secret (secret_name )
30+ print (f"[KeyVault] Retrieved secret '{ secret_name } ' from '{ keyvault_name } '" )
31+ return secret .value
Original file line number Diff line number Diff line change 1+ from fastapi import FastAPI , HTTPException , Request
2+ from contextlib import asynccontextmanager
3+ from producer import setup_producer
4+ from dto import RTPMessage
5+ from dotenv import load_dotenv
6+ import os , json
7+
8+ load_dotenv ()
9+
10+ EVENTHUB_TOPIC = os .environ ["EVENTHUB_TOPIC" ]
11+
12+ @asynccontextmanager
13+ async def app_lifespan (fastapi_app : FastAPI ):
14+ kafka_producer = await setup_producer ()
15+ app .state .producer = kafka_producer
16+ yield
17+ await kafka_producer .stop ()
18+
19+ app = FastAPI (lifespan = app_lifespan )
20+
21+ @app .post ("/send/gpd/message" )
22+ async def send_msg (message : RTPMessage , request : Request ):
23+ try :
24+ producer = request .app .state .producer
25+ await producer .send_and_wait (
26+ EVENTHUB_TOPIC ,
27+ json .dumps (message .model_dump (by_alias = True )).encode ("utf-8" )
28+ )
29+ return {"status" : "ok" }
30+ except Exception as e :
31+ raise HTTPException (status_code = 500 , detail = str (e ))
Original file line number Diff line number Diff line change 1+ from aiokafka import AIOKafkaProducer
2+ import os , ssl
3+ from keyvault import get_eventhub_connection_string
4+
5+ async def setup_producer ():
6+ connection_string = get_eventhub_connection_string ()
7+ namespace = os .environ ["EVENTHUB_NAMESPACE" ]
8+
9+ ssl_context = ssl .create_default_context ()
10+ ssl_context .check_hostname = True
11+ ssl_context .verify_mode = ssl .CERT_REQUIRED
12+
13+ producer = AIOKafkaProducer (
14+ bootstrap_servers = f"{ namespace } .servicebus.windows.net:9093" ,
15+ security_protocol = "SASL_SSL" ,
16+ sasl_mechanism = "PLAIN" ,
17+ sasl_plain_username = "$ConnectionString" ,
18+ sasl_plain_password = connection_string ,
19+ ssl_context = ssl_context ,
20+ client_id = "python-producer"
21+ )
22+ await producer .start ()
23+ return producer
Original file line number Diff line number Diff line change @@ -7,3 +7,11 @@ faker==22.5.1
77requests == 2.32.4
88schwifty == 2025.1.0
99urllib3 == 2.5.0
10+
11+ python-dotenv ~= 1.1.1
12+ pydantic ~= 2.11.7
13+ pytest ~= 8.4.1
14+ fastapi ~= 0.116.1
15+ aiokafka ~= 0.12.0
16+ keyvault ~= 0.2.1
17+ azure-core ~= 1.35.0
You can’t perform that action at this time.
0 commit comments