Netdata.cloud bot for Zulip
1"""Main entry point for the Netdata Zulip bot."""
2
3import argparse
4import sys
5from pathlib import Path
6
7import structlog
8
9from .config import load_config, load_zuliprc_config
10from .models import ServerConfig
11from .server import NetdataWebhookServer
12
13
14def setup_logging():
15 """Configure structured logging."""
16 structlog.configure(
17 processors=[
18 structlog.stdlib.filter_by_level,
19 structlog.stdlib.add_logger_name,
20 structlog.stdlib.add_log_level,
21 structlog.stdlib.PositionalArgumentsFormatter(),
22 structlog.processors.TimeStamper(fmt="iso"),
23 structlog.processors.StackInfoRenderer(),
24 structlog.processors.format_exc_info,
25 structlog.processors.UnicodeDecoder(),
26 structlog.processors.JSONRenderer()
27 ],
28 context_class=dict,
29 logger_factory=structlog.stdlib.LoggerFactory(),
30 wrapper_class=structlog.stdlib.BoundLogger,
31 cache_logger_on_first_use=True,
32 )
33
34
35def create_sample_configs():
36 """Create sample configuration files."""
37
38 # Sample .env file
39 env_content = """# Zulip Configuration
40ZULIP_SITE=https://yourorg.zulipchat.com
41ZULIP_EMAIL=netdata-bot@yourorg.zulipchat.com
42ZULIP_API_KEY=your-api-key-here
43ZULIP_STREAM=netdata-alerts
44
45# Server Configuration
46SERVER_HOST=0.0.0.0
47SERVER_PORT=8443
48SERVER_DOMAIN=your-domain.com
49SERVER_ENABLE_MTLS=true
50
51# Automated SSL Certificate Configuration (Recommended)
52SERVER_AUTO_CERT=true
53SERVER_CERT_EMAIL=admin@example.com
54SERVER_CERT_PATH=./certs
55# Use Let's Encrypt staging server for testing
56SERVER_CERT_STAGING=false
57# Port for ACME HTTP-01 challenge (must be accessible from internet)
58SERVER_ACME_PORT=80
59
60# Manual SSL Certificate Configuration (if not using auto-cert)
61# SERVER_AUTO_CERT=false
62# SERVER_CERT_PATH=/etc/letsencrypt/live
63"""
64
65 with open(".env.sample", 'w') as f:
66 f.write(env_content)
67
68 # Sample zuliprc file
69 zuliprc_content = """[api]
70site=https://yourorg.zulipchat.com
71email=netdata-bot@yourorg.zulipchat.com
72key=your-api-key-here
73stream=netdata-alerts
74"""
75
76 with open(".zuliprc.sample", 'w') as f:
77 f.write(zuliprc_content)
78
79 print("Created sample configuration files:")
80 print(" - .env.sample")
81 print(" - .zuliprc.sample")
82 print()
83 print("Copy and customize these files:")
84 print(" cp .env.sample .env")
85 print(" cp .zuliprc.sample ~/.zuliprc")
86
87
88def main():
89 """Main entry point."""
90 parser = argparse.ArgumentParser(
91 description="Netdata Zulip Bot - Webhook service for Netdata Cloud notifications"
92 )
93 parser.add_argument(
94 "--zuliprc",
95 help="Path to zuliprc configuration file (default: ~/.zuliprc)"
96 )
97 parser.add_argument(
98 "--create-config",
99 action="store_true",
100 help="Create sample configuration files and exit"
101 )
102 parser.add_argument(
103 "--env-config",
104 action="store_true",
105 help="Use environment variables for configuration instead of zuliprc"
106 )
107
108 args = parser.parse_args()
109
110 setup_logging()
111 logger = structlog.get_logger()
112
113 if args.create_config:
114 create_sample_configs()
115 return
116
117 try:
118 # Load configuration
119 if args.env_config:
120 zulip_config, server_config = load_config()
121 else:
122 zulip_config = load_zuliprc_config(args.zuliprc)
123 # Still need server config from environment
124 _, server_config = load_config()
125
126 # Create and start the webhook server
127 server = NetdataWebhookServer(zulip_config, server_config)
128 server.run()
129
130 except KeyboardInterrupt:
131 logger.info("Shutting down webhook server")
132 except Exception as e:
133 logger.error("Failed to start webhook server", error=str(e))
134 sys.exit(1)
135
136
137if __name__ == "__main__":
138 main()