Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a1bdb2576d | |||
| a527f14a57 | |||
| 62dc0a0cd5 | |||
| 29904df87b |
@@ -80,7 +80,32 @@ cp .env.example .env
|
||||
# .envファイルを編集して実際の値を設定
|
||||
```
|
||||
|
||||
## 🚢 Agents `container_tools` へのデプロイ
|
||||
## 🚢 Knative へのデプロイ
|
||||
|
||||
Knativeサービスとしてデプロイするには、`knative-service.yaml` を使用します。
|
||||
|
||||
### 1. マニフェストの適用
|
||||
|
||||
環境変数に必要な情報を設定した上で、Knativeサービスを作成します。
|
||||
|
||||
```bash
|
||||
kubectl apply -f knative-service.yaml
|
||||
```
|
||||
|
||||
### 2. 環境変数の設定
|
||||
|
||||
`knative-service.yaml` 内の `env` セクションを、環境に応じて適切に更新してください。機密情報は Kubernetes Secret として管理し、マニフェストから参照するように構成することを強く推奨します。
|
||||
|
||||
```yaml
|
||||
# knative-service.yaml の env を更新例
|
||||
env:
|
||||
- name: EMAIL_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: email-secrets
|
||||
key: email-user
|
||||
```
|
||||
|
||||
|
||||
`container_tools` はイメージをビルドせず、レジストリからpullして起動します。このリポジトリでは、`main` へのpush時にGitea Actionsが次のイメージをHarborへ公開します。
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ from datetime import datetime, timezone
|
||||
from typing import Dict, List, Optional
|
||||
import signal
|
||||
import threading
|
||||
from http.server import HTTPServer, BaseHTTPRequestHandler
|
||||
from dataclasses import dataclass
|
||||
|
||||
# ログ設定
|
||||
@@ -28,6 +29,25 @@ logging.basicConfig(
|
||||
)
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
class HealthCheckHandler(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
if self.path == '/health':
|
||||
self.send_response(200)
|
||||
self.end_headers()
|
||||
self.wfile.write(b'OK')
|
||||
else:
|
||||
self.send_response(404)
|
||||
self.end_headers()
|
||||
|
||||
def log_message(self, format, *args):
|
||||
# ヘルスチェックのログがうるさいため抑制
|
||||
return
|
||||
|
||||
def run_http_server():
|
||||
server = HTTPServer(('0.0.0.0', 8080), HealthCheckHandler)
|
||||
logger.info("Health check server started on port 8080")
|
||||
server.serve_forever()
|
||||
|
||||
@dataclass
|
||||
class EmailMessage:
|
||||
"""メールメッセージのデータクラス"""
|
||||
@@ -445,9 +465,6 @@ class EmailMonitor:
|
||||
logger.debug(f"{self.check_interval}秒後に次のチェックを実行します")
|
||||
time.sleep(self.check_interval)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("キーボード割り込みを受信しました")
|
||||
break
|
||||
except Exception as e:
|
||||
logger.error(f"監視ループでエラーが発生しました: {str(e)}")
|
||||
self.disconnect_from_email()
|
||||
@@ -480,9 +497,13 @@ def main():
|
||||
signal.signal(signal.SIGINT, lambda s, f: signal_handler(s, f, monitor))
|
||||
signal.signal(signal.SIGTERM, lambda s, f: signal_handler(s, f, monitor))
|
||||
|
||||
# メール監視をバックグラウンドスレッドで開始
|
||||
monitor_thread = threading.Thread(target=monitor.start_monitoring, daemon=True)
|
||||
monitor_thread.start()
|
||||
|
||||
# メインスレッドでヘルスチェックサーバーを実行
|
||||
try:
|
||||
# 監視開始
|
||||
monitor.start_monitoring()
|
||||
run_http_server()
|
||||
except Exception as e:
|
||||
logger.error(f"アプリケーションエラー: {str(e)}")
|
||||
sys.exit(1)
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
apiVersion: serving.knative.dev/v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: email-to-discord
|
||||
namespace: default
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- image: harbor.mukan.0am.jp/knative-func/email-to-discord:latest
|
||||
env:
|
||||
- name: IMAP_SERVER
|
||||
value: "imap.gmail.com"
|
||||
- name: EMAIL_USER
|
||||
value: "your-email@gmail.com"
|
||||
- name: EMAIL_PASSWORD
|
||||
value: "your-app-password"
|
||||
- name: DISCORD_WEBHOOK_URL
|
||||
value: "https://discord.com/api/webhooks/..."
|
||||
- name: CHECK_INTERVAL
|
||||
value: "60"
|
||||
# Knative services are expected to listen on a port,
|
||||
# but this app is a worker. For now, we set it up as a service.
|
||||
# If it needs to be a web hook receiver, the app needs modification.
|
||||
# Assuming this runs as a worker periodically triggered or running in a loop.
|
||||
# In Knative, if it doesn't listen on a port, it might be terminated.
|
||||
# But let's assume it works for the user's intent.
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
@@ -1,4 +1,8 @@
|
||||
import os
|
||||
import signal
|
||||
|
||||
import app
|
||||
|
||||
import unittest
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
@@ -152,5 +156,23 @@ class EmailMonitorNotificationTests(unittest.TestCase):
|
||||
mark_read.assert_called_once_with("42")
|
||||
|
||||
|
||||
class ApplicationStartupTests(unittest.TestCase):
|
||||
@patch.dict(os.environ, {**EMAIL_ENV, "DISCORD_WEBHOOK_URL": "https://discord.example/webhook"}, clear=True)
|
||||
@patch("app.run_http_server")
|
||||
@patch("app.threading.Thread")
|
||||
@patch("app.signal.signal")
|
||||
def test_main_registers_signal_handlers_and_starts_services(
|
||||
self, register_signal, thread_class, run_http_server
|
||||
):
|
||||
monitor_thread = thread_class.return_value
|
||||
|
||||
app.main()
|
||||
|
||||
registered_signals = [call.args[0] for call in register_signal.call_args_list]
|
||||
self.assertEqual(registered_signals, [signal.SIGINT, signal.SIGTERM])
|
||||
monitor_thread.start.assert_called_once_with()
|
||||
run_http_server.assert_called_once_with()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user