runsentry-agent 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- runsentry_agent-1.0.0/MANIFEST.in +5 -0
- runsentry_agent-1.0.0/PKG-INFO +262 -0
- runsentry_agent-1.0.0/README.md +237 -0
- runsentry_agent-1.0.0/pyproject.toml +50 -0
- runsentry_agent-1.0.0/runsentry/__init__.py +4 -0
- runsentry_agent-1.0.0/runsentry/__main__.py +8 -0
- runsentry_agent-1.0.0/runsentry/auth.py +140 -0
- runsentry_agent-1.0.0/runsentry/cli.py +105 -0
- runsentry_agent-1.0.0/runsentry/config.py +86 -0
- runsentry_agent-1.0.0/runsentry/daemon.py +223 -0
- runsentry_agent-1.0.0/runsentry/discovery/__init__.py +6 -0
- runsentry_agent-1.0.0/runsentry/discovery/cron.py +109 -0
- runsentry_agent-1.0.0/runsentry/discovery/k8s.py +74 -0
- runsentry_agent-1.0.0/runsentry/exec.py +123 -0
- runsentry_agent-1.0.0/runsentry/storage/__init__.py +7 -0
- runsentry_agent-1.0.0/runsentry/storage/buffer.py +82 -0
- runsentry_agent-1.0.0/runsentry/storage/inventory.py +124 -0
- runsentry_agent-1.0.0/runsentry/transport/__init__.py +6 -0
- runsentry_agent-1.0.0/runsentry/transport/client.py +135 -0
- runsentry_agent-1.0.0/runsentry-agent.service +16 -0
- runsentry_agent-1.0.0/runsentry_agent.egg-info/PKG-INFO +262 -0
- runsentry_agent-1.0.0/runsentry_agent.egg-info/SOURCES.txt +26 -0
- runsentry_agent-1.0.0/runsentry_agent.egg-info/dependency_links.txt +1 -0
- runsentry_agent-1.0.0/runsentry_agent.egg-info/entry_points.txt +2 -0
- runsentry_agent-1.0.0/runsentry_agent.egg-info/requires.txt +5 -0
- runsentry_agent-1.0.0/runsentry_agent.egg-info/top_level.txt +1 -0
- runsentry_agent-1.0.0/scripts/install.sh +153 -0
- runsentry_agent-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: runsentry-agent
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: RunSentry Agent - Monitor and track scheduled job executions
|
|
5
|
+
Author-email: RunSentry <support@runsentry.io>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://runsentry.io
|
|
8
|
+
Project-URL: Documentation, https://docs.runsentry.io
|
|
9
|
+
Project-URL: Repository, https://github.com/runsentry/agent
|
|
10
|
+
Keywords: monitoring,cron,scheduled-jobs,observability
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: System Administrators
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: System :: Monitoring
|
|
19
|
+
Requires-Python: >=3.10
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
Requires-Dist: requests>=2.31.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0
|
|
23
|
+
Provides-Extra: k8s
|
|
24
|
+
Requires-Dist: kubernetes>=28.0.0; extra == "k8s"
|
|
25
|
+
|
|
26
|
+
# RunSentry Agent
|
|
27
|
+
|
|
28
|
+
The RunSentry agent monitors and tracks scheduled job executions on Linux systems. It discovers cron jobs and Kubernetes CronJobs, tracks their executions, and sends data to the RunSentry backend.
|
|
29
|
+
|
|
30
|
+
## Features
|
|
31
|
+
|
|
32
|
+
- 🔍 **Automatic Discovery**: Discovers cron jobs and Kubernetes CronJobs
|
|
33
|
+
- 📊 **Execution Tracking**: Tracks job start, finish, duration, and exit codes
|
|
34
|
+
- 🔒 **Secure**: Outbound-only HTTPS communication, no inbound ports
|
|
35
|
+
- 💾 **Resilient**: Local event buffering for offline operation
|
|
36
|
+
- 🚀 **Easy Installation**: One-line installer script
|
|
37
|
+
|
|
38
|
+
## Quick Start
|
|
39
|
+
|
|
40
|
+
### Installation
|
|
41
|
+
|
|
42
|
+
**One-line installation with automatic registration:**
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
RUNSENTRY_TOKEN=your_token_here curl -fsSL https://get.runsentry.io/install.sh | bash
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The installer will:
|
|
49
|
+
1. Validate Linux OS and Python 3.10+
|
|
50
|
+
2. Create isolated virtual environment at `/opt/runsentry/venv`
|
|
51
|
+
3. Install the RunSentry agent package
|
|
52
|
+
4. Automatically register agent with backend (if `RUNSENTRY_TOKEN` is provided)
|
|
53
|
+
5. Install and enable systemd service
|
|
54
|
+
6. Start the service automatically if registration succeeds
|
|
55
|
+
|
|
56
|
+
**Installation without token (for later registration):**
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
curl -fsSL https://get.runsentry.io/install.sh | bash
|
|
60
|
+
|
|
61
|
+
# Register manually later
|
|
62
|
+
RUNSENTRY_TOKEN=xxx /opt/runsentry/venv/bin/runsentry register --backend-url https://api.runsentry.io
|
|
63
|
+
systemctl start runsentry-agent
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**With custom backend URL:**
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
RUNSENTRY_TOKEN=xxx RUNSENTRY_BACKEND_URL=https://api.example.com curl -fsSL https://get.runsentry.io/install.sh | bash
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
### Daemon Mode
|
|
75
|
+
|
|
76
|
+
The agent runs as a systemd service automatically after installation:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Check status
|
|
80
|
+
systemctl status runsentry-agent
|
|
81
|
+
|
|
82
|
+
# View logs
|
|
83
|
+
journalctl -u runsentry-agent -f
|
|
84
|
+
|
|
85
|
+
# Restart
|
|
86
|
+
systemctl restart runsentry-agent
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The daemon will:
|
|
90
|
+
- Discover jobs on startup and periodically (every hour)
|
|
91
|
+
- Flush buffered events to the backend (every minute)
|
|
92
|
+
- Run continuously until stopped
|
|
93
|
+
|
|
94
|
+
### Execution Wrapper
|
|
95
|
+
|
|
96
|
+
Wrap your cron jobs to track executions:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Instead of:
|
|
100
|
+
0 * * * * /path/to/script.sh
|
|
101
|
+
|
|
102
|
+
# Use:
|
|
103
|
+
0 * * * * /opt/runsentry/venv/bin/runsentry exec /path/to/script.sh
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The wrapper will:
|
|
107
|
+
- Send execution start event
|
|
108
|
+
- Execute your command
|
|
109
|
+
- Capture exit code and duration
|
|
110
|
+
- Send execution finish event
|
|
111
|
+
- Works even if backend is temporarily unavailable (events are buffered)
|
|
112
|
+
|
|
113
|
+
### CLI Commands
|
|
114
|
+
|
|
115
|
+
The agent exposes three commands:
|
|
116
|
+
|
|
117
|
+
- **`runsentry daemon`** - Run agent daemon (used by systemd service)
|
|
118
|
+
- **`runsentry exec <command>`** - Execute and track a job execution
|
|
119
|
+
- **`runsentry register`** - Register agent with backend (internal, used by install.sh)
|
|
120
|
+
|
|
121
|
+
**Note:** The `register` command is internal and used automatically by `install.sh`. Manual registration can be done if needed:
|
|
122
|
+
```bash
|
|
123
|
+
/opt/runsentry/venv/bin/runsentry register --token xxx --backend-url https://api.runsentry.io
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Configuration
|
|
127
|
+
|
|
128
|
+
Configuration is stored at `/etc/runsentry/config.yaml`:
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
agent_id: agt_123
|
|
132
|
+
backend_url: https://api.runsentry.io
|
|
133
|
+
token: <signed-jwt>
|
|
134
|
+
agent_name: prod-vm-1
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Discovery
|
|
138
|
+
|
|
139
|
+
The agent automatically discovers:
|
|
140
|
+
|
|
141
|
+
- **Linux Cron**:
|
|
142
|
+
- User crontab (`crontab -l`)
|
|
143
|
+
- System crontab (`/etc/crontab`)
|
|
144
|
+
- Cron.d directory (`/etc/cron.d/*`)
|
|
145
|
+
|
|
146
|
+
- **Kubernetes CronJobs**:
|
|
147
|
+
- Requires `kubernetes` Python package
|
|
148
|
+
- Uses in-cluster config or kubeconfig
|
|
149
|
+
- Discovers all namespaces
|
|
150
|
+
|
|
151
|
+
## Systemd Service
|
|
152
|
+
|
|
153
|
+
The agent runs as a systemd service:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# Check status
|
|
157
|
+
systemctl status runsentry-agent
|
|
158
|
+
|
|
159
|
+
# View logs
|
|
160
|
+
journalctl -u runsentry-agent -f
|
|
161
|
+
|
|
162
|
+
# Restart
|
|
163
|
+
systemctl restart runsentry-agent
|
|
164
|
+
|
|
165
|
+
# Stop
|
|
166
|
+
systemctl stop runsentry-agent
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Upgrading
|
|
170
|
+
|
|
171
|
+
Upgrade the agent package manually:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
source /opt/runsentry/venv/bin/activate
|
|
175
|
+
pip install --upgrade runsentry-agent
|
|
176
|
+
systemctl restart runsentry-agent
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Configuration is preserved during upgrades.
|
|
180
|
+
|
|
181
|
+
## Development
|
|
182
|
+
|
|
183
|
+
### Local Development Setup
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
# Clone repository
|
|
187
|
+
git clone https://github.com/runsentry/agent.git
|
|
188
|
+
cd agent
|
|
189
|
+
|
|
190
|
+
# Create virtual environment
|
|
191
|
+
python3 -m venv venv
|
|
192
|
+
source venv/bin/activate
|
|
193
|
+
|
|
194
|
+
# Install in development mode
|
|
195
|
+
pip install -e .
|
|
196
|
+
|
|
197
|
+
# Install with Kubernetes support
|
|
198
|
+
pip install -e ".[k8s]"
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Running Tests
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
pytest
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Architecture
|
|
208
|
+
|
|
209
|
+
The agent operates in two modes:
|
|
210
|
+
|
|
211
|
+
1. **Daemon Mode**: Continuous background process for discovery and sync
|
|
212
|
+
2. **Exec Mode**: Wrapper for individual job executions
|
|
213
|
+
|
|
214
|
+
All communication is outbound-only HTTPS to the RunSentry backend.
|
|
215
|
+
|
|
216
|
+
## Security
|
|
217
|
+
|
|
218
|
+
- ✅ Outbound-only HTTPS
|
|
219
|
+
- ✅ Token-based authentication
|
|
220
|
+
- ✅ Signed agent JWT
|
|
221
|
+
- ✅ Read-only discovery permissions
|
|
222
|
+
- ✅ No inbound ports
|
|
223
|
+
- ✅ Secure configuration file (600 permissions)
|
|
224
|
+
|
|
225
|
+
## Requirements
|
|
226
|
+
|
|
227
|
+
- Python 3.10+
|
|
228
|
+
- Linux (Ubuntu, Debian, RHEL, etc.)
|
|
229
|
+
- Network access to RunSentry backend
|
|
230
|
+
- Root or sudo access for installation
|
|
231
|
+
|
|
232
|
+
## Troubleshooting
|
|
233
|
+
|
|
234
|
+
### Agent not discovering jobs
|
|
235
|
+
|
|
236
|
+
- Check that cron jobs exist: `crontab -l`
|
|
237
|
+
- Verify agent has read permissions to `/etc/crontab` and `/etc/cron.d/`
|
|
238
|
+
- Check daemon logs: `journalctl -u runsentry-agent`
|
|
239
|
+
|
|
240
|
+
### Events not reaching backend
|
|
241
|
+
|
|
242
|
+
- Check network connectivity to backend URL
|
|
243
|
+
- Verify agent token is valid
|
|
244
|
+
- Check buffered events: `/var/lib/runsentry/buffer/events.jsonl`
|
|
245
|
+
- Review logs for errors
|
|
246
|
+
|
|
247
|
+
### Service won't start
|
|
248
|
+
|
|
249
|
+
- Check Python version: `python3 --version`
|
|
250
|
+
- Verify virtual environment exists: `/opt/runsentry/venv`
|
|
251
|
+
- Check systemd logs: `journalctl -u runsentry-agent`
|
|
252
|
+
|
|
253
|
+
## License
|
|
254
|
+
|
|
255
|
+
MIT License
|
|
256
|
+
|
|
257
|
+
## Support
|
|
258
|
+
|
|
259
|
+
For issues and questions:
|
|
260
|
+
- Documentation: https://docs.runsentry.io
|
|
261
|
+
- Support: support@runsentry.io
|
|
262
|
+
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# RunSentry Agent
|
|
2
|
+
|
|
3
|
+
The RunSentry agent monitors and tracks scheduled job executions on Linux systems. It discovers cron jobs and Kubernetes CronJobs, tracks their executions, and sends data to the RunSentry backend.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔍 **Automatic Discovery**: Discovers cron jobs and Kubernetes CronJobs
|
|
8
|
+
- 📊 **Execution Tracking**: Tracks job start, finish, duration, and exit codes
|
|
9
|
+
- 🔒 **Secure**: Outbound-only HTTPS communication, no inbound ports
|
|
10
|
+
- 💾 **Resilient**: Local event buffering for offline operation
|
|
11
|
+
- 🚀 **Easy Installation**: One-line installer script
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
### Installation
|
|
16
|
+
|
|
17
|
+
**One-line installation with automatic registration:**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
RUNSENTRY_TOKEN=your_token_here curl -fsSL https://get.runsentry.io/install.sh | bash
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The installer will:
|
|
24
|
+
1. Validate Linux OS and Python 3.10+
|
|
25
|
+
2. Create isolated virtual environment at `/opt/runsentry/venv`
|
|
26
|
+
3. Install the RunSentry agent package
|
|
27
|
+
4. Automatically register agent with backend (if `RUNSENTRY_TOKEN` is provided)
|
|
28
|
+
5. Install and enable systemd service
|
|
29
|
+
6. Start the service automatically if registration succeeds
|
|
30
|
+
|
|
31
|
+
**Installation without token (for later registration):**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
curl -fsSL https://get.runsentry.io/install.sh | bash
|
|
35
|
+
|
|
36
|
+
# Register manually later
|
|
37
|
+
RUNSENTRY_TOKEN=xxx /opt/runsentry/venv/bin/runsentry register --backend-url https://api.runsentry.io
|
|
38
|
+
systemctl start runsentry-agent
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
**With custom backend URL:**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
RUNSENTRY_TOKEN=xxx RUNSENTRY_BACKEND_URL=https://api.example.com curl -fsSL https://get.runsentry.io/install.sh | bash
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
### Daemon Mode
|
|
50
|
+
|
|
51
|
+
The agent runs as a systemd service automatically after installation:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
# Check status
|
|
55
|
+
systemctl status runsentry-agent
|
|
56
|
+
|
|
57
|
+
# View logs
|
|
58
|
+
journalctl -u runsentry-agent -f
|
|
59
|
+
|
|
60
|
+
# Restart
|
|
61
|
+
systemctl restart runsentry-agent
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
The daemon will:
|
|
65
|
+
- Discover jobs on startup and periodically (every hour)
|
|
66
|
+
- Flush buffered events to the backend (every minute)
|
|
67
|
+
- Run continuously until stopped
|
|
68
|
+
|
|
69
|
+
### Execution Wrapper
|
|
70
|
+
|
|
71
|
+
Wrap your cron jobs to track executions:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Instead of:
|
|
75
|
+
0 * * * * /path/to/script.sh
|
|
76
|
+
|
|
77
|
+
# Use:
|
|
78
|
+
0 * * * * /opt/runsentry/venv/bin/runsentry exec /path/to/script.sh
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The wrapper will:
|
|
82
|
+
- Send execution start event
|
|
83
|
+
- Execute your command
|
|
84
|
+
- Capture exit code and duration
|
|
85
|
+
- Send execution finish event
|
|
86
|
+
- Works even if backend is temporarily unavailable (events are buffered)
|
|
87
|
+
|
|
88
|
+
### CLI Commands
|
|
89
|
+
|
|
90
|
+
The agent exposes three commands:
|
|
91
|
+
|
|
92
|
+
- **`runsentry daemon`** - Run agent daemon (used by systemd service)
|
|
93
|
+
- **`runsentry exec <command>`** - Execute and track a job execution
|
|
94
|
+
- **`runsentry register`** - Register agent with backend (internal, used by install.sh)
|
|
95
|
+
|
|
96
|
+
**Note:** The `register` command is internal and used automatically by `install.sh`. Manual registration can be done if needed:
|
|
97
|
+
```bash
|
|
98
|
+
/opt/runsentry/venv/bin/runsentry register --token xxx --backend-url https://api.runsentry.io
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Configuration
|
|
102
|
+
|
|
103
|
+
Configuration is stored at `/etc/runsentry/config.yaml`:
|
|
104
|
+
|
|
105
|
+
```yaml
|
|
106
|
+
agent_id: agt_123
|
|
107
|
+
backend_url: https://api.runsentry.io
|
|
108
|
+
token: <signed-jwt>
|
|
109
|
+
agent_name: prod-vm-1
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Discovery
|
|
113
|
+
|
|
114
|
+
The agent automatically discovers:
|
|
115
|
+
|
|
116
|
+
- **Linux Cron**:
|
|
117
|
+
- User crontab (`crontab -l`)
|
|
118
|
+
- System crontab (`/etc/crontab`)
|
|
119
|
+
- Cron.d directory (`/etc/cron.d/*`)
|
|
120
|
+
|
|
121
|
+
- **Kubernetes CronJobs**:
|
|
122
|
+
- Requires `kubernetes` Python package
|
|
123
|
+
- Uses in-cluster config or kubeconfig
|
|
124
|
+
- Discovers all namespaces
|
|
125
|
+
|
|
126
|
+
## Systemd Service
|
|
127
|
+
|
|
128
|
+
The agent runs as a systemd service:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
# Check status
|
|
132
|
+
systemctl status runsentry-agent
|
|
133
|
+
|
|
134
|
+
# View logs
|
|
135
|
+
journalctl -u runsentry-agent -f
|
|
136
|
+
|
|
137
|
+
# Restart
|
|
138
|
+
systemctl restart runsentry-agent
|
|
139
|
+
|
|
140
|
+
# Stop
|
|
141
|
+
systemctl stop runsentry-agent
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Upgrading
|
|
145
|
+
|
|
146
|
+
Upgrade the agent package manually:
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
source /opt/runsentry/venv/bin/activate
|
|
150
|
+
pip install --upgrade runsentry-agent
|
|
151
|
+
systemctl restart runsentry-agent
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Configuration is preserved during upgrades.
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
### Local Development Setup
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Clone repository
|
|
162
|
+
git clone https://github.com/runsentry/agent.git
|
|
163
|
+
cd agent
|
|
164
|
+
|
|
165
|
+
# Create virtual environment
|
|
166
|
+
python3 -m venv venv
|
|
167
|
+
source venv/bin/activate
|
|
168
|
+
|
|
169
|
+
# Install in development mode
|
|
170
|
+
pip install -e .
|
|
171
|
+
|
|
172
|
+
# Install with Kubernetes support
|
|
173
|
+
pip install -e ".[k8s]"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Running Tests
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
pytest
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Architecture
|
|
183
|
+
|
|
184
|
+
The agent operates in two modes:
|
|
185
|
+
|
|
186
|
+
1. **Daemon Mode**: Continuous background process for discovery and sync
|
|
187
|
+
2. **Exec Mode**: Wrapper for individual job executions
|
|
188
|
+
|
|
189
|
+
All communication is outbound-only HTTPS to the RunSentry backend.
|
|
190
|
+
|
|
191
|
+
## Security
|
|
192
|
+
|
|
193
|
+
- ✅ Outbound-only HTTPS
|
|
194
|
+
- ✅ Token-based authentication
|
|
195
|
+
- ✅ Signed agent JWT
|
|
196
|
+
- ✅ Read-only discovery permissions
|
|
197
|
+
- ✅ No inbound ports
|
|
198
|
+
- ✅ Secure configuration file (600 permissions)
|
|
199
|
+
|
|
200
|
+
## Requirements
|
|
201
|
+
|
|
202
|
+
- Python 3.10+
|
|
203
|
+
- Linux (Ubuntu, Debian, RHEL, etc.)
|
|
204
|
+
- Network access to RunSentry backend
|
|
205
|
+
- Root or sudo access for installation
|
|
206
|
+
|
|
207
|
+
## Troubleshooting
|
|
208
|
+
|
|
209
|
+
### Agent not discovering jobs
|
|
210
|
+
|
|
211
|
+
- Check that cron jobs exist: `crontab -l`
|
|
212
|
+
- Verify agent has read permissions to `/etc/crontab` and `/etc/cron.d/`
|
|
213
|
+
- Check daemon logs: `journalctl -u runsentry-agent`
|
|
214
|
+
|
|
215
|
+
### Events not reaching backend
|
|
216
|
+
|
|
217
|
+
- Check network connectivity to backend URL
|
|
218
|
+
- Verify agent token is valid
|
|
219
|
+
- Check buffered events: `/var/lib/runsentry/buffer/events.jsonl`
|
|
220
|
+
- Review logs for errors
|
|
221
|
+
|
|
222
|
+
### Service won't start
|
|
223
|
+
|
|
224
|
+
- Check Python version: `python3 --version`
|
|
225
|
+
- Verify virtual environment exists: `/opt/runsentry/venv`
|
|
226
|
+
- Check systemd logs: `journalctl -u runsentry-agent`
|
|
227
|
+
|
|
228
|
+
## License
|
|
229
|
+
|
|
230
|
+
MIT License
|
|
231
|
+
|
|
232
|
+
## Support
|
|
233
|
+
|
|
234
|
+
For issues and questions:
|
|
235
|
+
- Documentation: https://docs.runsentry.io
|
|
236
|
+
- Support: support@runsentry.io
|
|
237
|
+
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "runsentry-agent"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "RunSentry Agent - Monitor and track scheduled job executions"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "RunSentry", email = "support@runsentry.io"}
|
|
14
|
+
]
|
|
15
|
+
keywords = ["monitoring", "cron", "scheduled-jobs", "observability"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 4 - Beta",
|
|
18
|
+
"Intended Audience :: System Administrators",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: System :: Monitoring",
|
|
25
|
+
]
|
|
26
|
+
|
|
27
|
+
dependencies = [
|
|
28
|
+
"requests>=2.31.0",
|
|
29
|
+
"pyyaml>=6.0",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
k8s = [
|
|
34
|
+
"kubernetes>=28.0.0",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.scripts]
|
|
38
|
+
runsentry = "runsentry.cli:main"
|
|
39
|
+
|
|
40
|
+
[project.urls]
|
|
41
|
+
Homepage = "https://runsentry.io"
|
|
42
|
+
Documentation = "https://docs.runsentry.io"
|
|
43
|
+
Repository = "https://github.com/runsentry/agent"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools]
|
|
46
|
+
packages = ["runsentry", "runsentry.discovery", "runsentry.storage", "runsentry.transport"]
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.package-data]
|
|
49
|
+
runsentry = ["*.yaml", "*.yml"]
|
|
50
|
+
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""Authentication and agent registration.
|
|
2
|
+
|
|
3
|
+
Internal module used by install.sh for agent registration.
|
|
4
|
+
Not intended for direct user use.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import sys
|
|
9
|
+
import os
|
|
10
|
+
import time
|
|
11
|
+
import platform
|
|
12
|
+
import socket
|
|
13
|
+
import requests
|
|
14
|
+
from typing import Optional
|
|
15
|
+
from runsentry.config import get_config, CONFIG_PATH
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def register_agent(token: str, backend_url: str, agent_name: Optional[str] = None, retries: int = 3, retry_delay: int = 5) -> bool:
|
|
21
|
+
"""
|
|
22
|
+
Register agent with RunSentry backend.
|
|
23
|
+
|
|
24
|
+
Internal function used by install.sh. Handles registration with retries
|
|
25
|
+
and saves configuration.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
token: Registration token (required)
|
|
29
|
+
backend_url: Backend URL (required)
|
|
30
|
+
agent_name: Agent name (optional, defaults to hostname)
|
|
31
|
+
retries: Number of registration retry attempts (default: 3)
|
|
32
|
+
retry_delay: Delay between retries in seconds (default: 5)
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
True if registration successful, False otherwise
|
|
36
|
+
"""
|
|
37
|
+
if not token:
|
|
38
|
+
logger.error("Registration token is required")
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
if not backend_url:
|
|
42
|
+
logger.error("Backend URL is required")
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
config = get_config()
|
|
46
|
+
|
|
47
|
+
# Check if already configured (idempotency)
|
|
48
|
+
if config.is_configured():
|
|
49
|
+
logger.info(f"Agent is already configured (ID: {config.agent_id})")
|
|
50
|
+
return True
|
|
51
|
+
|
|
52
|
+
# Detect agent name if not provided
|
|
53
|
+
if not agent_name:
|
|
54
|
+
agent_name = os.environ.get("RUNSENTRY_AGENT_NAME") or socket.gethostname()
|
|
55
|
+
|
|
56
|
+
# Detect host information
|
|
57
|
+
hostname = socket.gethostname()
|
|
58
|
+
os_name = platform.system().lower()
|
|
59
|
+
arch = platform.machine()
|
|
60
|
+
|
|
61
|
+
# Detect agent type
|
|
62
|
+
agent_type = "linux-cron"
|
|
63
|
+
if os.path.exists("/var/run/secrets/kubernetes.io"):
|
|
64
|
+
agent_type = "kubernetes"
|
|
65
|
+
|
|
66
|
+
payload = {
|
|
67
|
+
"agentName": agent_name,
|
|
68
|
+
"agentType": agent_type,
|
|
69
|
+
"version": "1.0.0",
|
|
70
|
+
"host": {
|
|
71
|
+
"hostname": hostname,
|
|
72
|
+
"os": os_name,
|
|
73
|
+
"arch": arch,
|
|
74
|
+
},
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
# Retry logic for registration
|
|
78
|
+
logger.info(f"Registering agent with backend: {backend_url}")
|
|
79
|
+
logger.info(f"Agent name: {agent_name}")
|
|
80
|
+
|
|
81
|
+
for attempt in range(1, retries + 1):
|
|
82
|
+
try:
|
|
83
|
+
response = requests.post(
|
|
84
|
+
f"{backend_url}/api/v1/agents/register",
|
|
85
|
+
json=payload,
|
|
86
|
+
headers={
|
|
87
|
+
"Content-Type": "application/json",
|
|
88
|
+
"X-Registration-Token": token,
|
|
89
|
+
},
|
|
90
|
+
timeout=30,
|
|
91
|
+
)
|
|
92
|
+
response.raise_for_status()
|
|
93
|
+
|
|
94
|
+
data = response.json()
|
|
95
|
+
agent_id = data.get("agentId")
|
|
96
|
+
agent_token = data.get("token") # Non-expiring token for all API calls
|
|
97
|
+
workspace_id = data.get("workspaceId")
|
|
98
|
+
backend_url_from_response = data.get("backendUrl", backend_url)
|
|
99
|
+
|
|
100
|
+
if not agent_id or not agent_token:
|
|
101
|
+
raise ValueError("Invalid response from backend: missing agentId or token")
|
|
102
|
+
|
|
103
|
+
# Save configuration
|
|
104
|
+
config.agent_id = agent_id
|
|
105
|
+
config.token = agent_token # This token never expires, use for all API calls
|
|
106
|
+
config.backend_url = backend_url_from_response # Use backend URL from response
|
|
107
|
+
config.agent_name = agent_name
|
|
108
|
+
if workspace_id:
|
|
109
|
+
config.workspace_id = workspace_id
|
|
110
|
+
config.save()
|
|
111
|
+
|
|
112
|
+
logger.info(f"Successfully registered agent: {agent_name} ({agent_id})")
|
|
113
|
+
logger.info(f"Configuration saved to {CONFIG_PATH}")
|
|
114
|
+
|
|
115
|
+
return True
|
|
116
|
+
|
|
117
|
+
except requests.exceptions.RequestException as e:
|
|
118
|
+
if attempt < retries:
|
|
119
|
+
logger.warning(f"Registration attempt {attempt}/{retries} failed: {e}")
|
|
120
|
+
logger.info(f"Retrying in {retry_delay} seconds...")
|
|
121
|
+
time.sleep(retry_delay)
|
|
122
|
+
else:
|
|
123
|
+
logger.error(f"Failed to register agent after {retries} attempts")
|
|
124
|
+
if hasattr(e, "response") and e.response is not None:
|
|
125
|
+
try:
|
|
126
|
+
error_data = e.response.json()
|
|
127
|
+
logger.error(f"Backend error: {error_data}")
|
|
128
|
+
except:
|
|
129
|
+
logger.error(f"Response: {e.response.text}")
|
|
130
|
+
else:
|
|
131
|
+
logger.error(f"Error details: {e}")
|
|
132
|
+
continue
|
|
133
|
+
except Exception as e:
|
|
134
|
+
logger.error(f"Unexpected error during registration: {e}", exc_info=True)
|
|
135
|
+
if attempt < retries:
|
|
136
|
+
time.sleep(retry_delay)
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
return False
|
|
140
|
+
|