isitup-cli 0.1.2__tar.gz → 0.1.4__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.
@@ -1,11 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isitup-cli
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: A small CLI that periodically checks whether servers respond to ping, HTTP, and TCP ports
5
5
  Author: stefan.insam
6
6
  Author-email: stefan.insam <stefan.insam@netgo.de>
7
7
  License-Expression: GPL-3.0-only
8
8
  License-File: LICENSE
9
+ Classifier: Development Status :: 4 - Beta
9
10
  Classifier: Environment :: Console
10
11
  Classifier: Intended Audience :: System Administrators
11
12
  Classifier: Topic :: System :: Networking :: Monitoring
@@ -90,6 +91,14 @@ Either way, remove it later with `uv tool uninstall isitup`.
90
91
 
91
92
  ## Usage
92
93
 
94
+ ```bash
95
+ isitup example.com https://example.org db.internal:5432
96
+ ```
97
+
98
+ `--url`/`-u` work the same way and can be freely mixed with positional
99
+ targets: `isitup example.com -u https://example.org` is the same as
100
+ `isitup example.com https://example.org`:
101
+
93
102
  ```bash
94
103
  isitup --url example.com --url https://example.org --url db.internal:5432
95
104
  ```
@@ -102,16 +111,18 @@ cp config.example.yaml config.yaml
102
111
  isitup --config config.yaml
103
112
  ```
104
113
 
105
- Config files and `--url` flags can be combined; the tool watches the union of
106
- both. The config file is watched for changes and reloaded automatically:
107
- add, remove, or edit targets without restarting the tool (`--url` targets
108
- can't change at runtime, only what's in the file).
114
+ Config files and CLI-supplied targets (positional or `--url`) can be
115
+ combined; the tool watches the union of both. The config file is watched for
116
+ changes and reloaded automatically: add, remove, or edit targets without
117
+ restarting the tool (CLI-supplied targets can't change at runtime, only
118
+ what's in the file).
109
119
 
110
120
  ### Options
111
121
 
112
122
  | Flag | Description |
113
123
  | --- | --- |
114
124
  | `-c`, `--config PATH` | YAML file listing targets; reloaded automatically on change |
125
+ | `TARGET` (positional) | a target to monitor: same as `-u`/`--url`, just without the flag (repeatable) |
115
126
  | `-u`, `--url TARGET` | a target to monitor (repeatable): hostname, `hostname:port`, or a URL |
116
127
  | `-i`, `--interval SECONDS` | seconds between check rounds (default: 30) |
117
128
  | `--ping-timeout SECONDS` | ping reply timeout (default: 2) |
@@ -167,6 +178,10 @@ uv run mypy src tests # type check
167
178
  Every push and pull request runs this same lint/type-check/test suite via
168
179
  [GitHub Actions](.github/workflows/ci.yml), across Linux and Windows.
169
180
 
181
+ ## Changelog
182
+
183
+ See [CHANGELOG.md](CHANGELOG.md).
184
+
170
185
  ## License
171
186
 
172
187
  [GPL-3.0](LICENSE): see [LICENSE](LICENSE) for the full text.
@@ -70,6 +70,14 @@ Either way, remove it later with `uv tool uninstall isitup`.
70
70
 
71
71
  ## Usage
72
72
 
73
+ ```bash
74
+ isitup example.com https://example.org db.internal:5432
75
+ ```
76
+
77
+ `--url`/`-u` work the same way and can be freely mixed with positional
78
+ targets: `isitup example.com -u https://example.org` is the same as
79
+ `isitup example.com https://example.org`:
80
+
73
81
  ```bash
74
82
  isitup --url example.com --url https://example.org --url db.internal:5432
75
83
  ```
@@ -82,16 +90,18 @@ cp config.example.yaml config.yaml
82
90
  isitup --config config.yaml
83
91
  ```
84
92
 
85
- Config files and `--url` flags can be combined; the tool watches the union of
86
- both. The config file is watched for changes and reloaded automatically:
87
- add, remove, or edit targets without restarting the tool (`--url` targets
88
- can't change at runtime, only what's in the file).
93
+ Config files and CLI-supplied targets (positional or `--url`) can be
94
+ combined; the tool watches the union of both. The config file is watched for
95
+ changes and reloaded automatically: add, remove, or edit targets without
96
+ restarting the tool (CLI-supplied targets can't change at runtime, only
97
+ what's in the file).
89
98
 
90
99
  ### Options
91
100
 
92
101
  | Flag | Description |
93
102
  | --- | --- |
94
103
  | `-c`, `--config PATH` | YAML file listing targets; reloaded automatically on change |
104
+ | `TARGET` (positional) | a target to monitor: same as `-u`/`--url`, just without the flag (repeatable) |
95
105
  | `-u`, `--url TARGET` | a target to monitor (repeatable): hostname, `hostname:port`, or a URL |
96
106
  | `-i`, `--interval SECONDS` | seconds between check rounds (default: 30) |
97
107
  | `--ping-timeout SECONDS` | ping reply timeout (default: 2) |
@@ -147,6 +157,10 @@ uv run mypy src tests # type check
147
157
  Every push and pull request runs this same lint/type-check/test suite via
148
158
  [GitHub Actions](.github/workflows/ci.yml), across Linux and Windows.
149
159
 
160
+ ## Changelog
161
+
162
+ See [CHANGELOG.md](CHANGELOG.md).
163
+
150
164
  ## License
151
165
 
152
166
  [GPL-3.0](LICENSE): see [LICENSE](LICENSE) for the full text.
@@ -1,12 +1,13 @@
1
1
  [project]
2
2
  name = "isitup-cli"
3
- version = "0.1.2"
3
+ version = "0.1.4"
4
4
  description = "A small CLI that periodically checks whether servers respond to ping, HTTP, and TCP ports"
5
5
  readme = "README.md"
6
6
  license = "GPL-3.0-only"
7
7
  license-files = ["LICENSE"]
8
8
  requires-python = ">=3.14"
9
9
  classifiers = [
10
+ "Development Status :: 4 - Beta",
10
11
  "Environment :: Console",
11
12
  "Intended Audience :: System Administrators",
12
13
  "Topic :: System :: Networking :: Monitoring",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "isitup-cli"
3
- version = "0.1.2"
3
+ version = "0.1.4"
4
4
  description = "A small CLI that periodically checks whether servers respond to ping, HTTP, and TCP ports"
5
5
  readme = "README.md"
6
6
  license = "GPL-3.0-only"
@@ -10,6 +10,7 @@ authors = [
10
10
  ]
11
11
  requires-python = ">=3.14"
12
12
  classifiers = [
13
+ "Development Status :: 4 - Beta",
13
14
  "Environment :: Console",
14
15
  "Intended Audience :: System Administrators",
15
16
  "Topic :: System :: Networking :: Monitoring",
@@ -0,0 +1,3 @@
1
+ from .cli import __version__, main
2
+
3
+ __all__ = ["main", "__version__"]
@@ -1,7 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import argparse
4
+ import sys
4
5
  import time
6
+ from importlib.metadata import PackageNotFoundError, version
5
7
  from pathlib import Path
6
8
 
7
9
  from rich.console import Console, RenderableType
@@ -12,12 +14,23 @@ from .history import HistoryStore
12
14
  from .output import compute_exit_code, format_json_line, format_plain_line, run_checks
13
15
  from .render import build_table, countdown, framed, is_online, run_round, waiting_placeholder
14
16
 
17
+ try:
18
+ __version__ = version("isitup-cli")
19
+ except PackageNotFoundError:
20
+ __version__ = "0.0.0+unknown"
21
+
15
22
 
16
23
  def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
17
24
  parser = argparse.ArgumentParser(
18
25
  prog="isitup",
19
26
  description="Periodically check whether servers respond to ping, HTTP, and TCP ports.",
20
27
  )
28
+ parser.add_argument(
29
+ "-v",
30
+ "--version",
31
+ action="version",
32
+ version=f"%(prog)s {__version__}",
33
+ )
21
34
  parser.add_argument(
22
35
  "-c",
23
36
  "--config",
@@ -26,6 +39,14 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
26
39
  help="path to a YAML config file listing targets (see config.example.yaml); "
27
40
  "reloaded automatically whenever it changes",
28
41
  )
42
+ parser.add_argument(
43
+ "targets",
44
+ nargs="*",
45
+ default=[],
46
+ metavar="TARGET",
47
+ help="a target to monitor, same as --url (positional shorthand, e.g. "
48
+ "'isitup example.com https://example.org')",
49
+ )
29
50
  parser.add_argument(
30
51
  "-u",
31
52
  "--url",
@@ -82,6 +103,12 @@ def parse_args(argv: list[str] | None = None) -> argparse.Namespace:
82
103
  return parser.parse_args(argv)
83
104
 
84
105
 
106
+ def combined_targets(args: argparse.Namespace) -> list[str]:
107
+ """Positional targets and --url flags are equivalent; combine them into
108
+ one list wherever CLI-supplied targets are needed."""
109
+ return args.targets + args.urls
110
+
111
+
85
112
  def run_headless(
86
113
  console: Console,
87
114
  args: argparse.Namespace,
@@ -93,23 +120,29 @@ def run_headless(
93
120
  config_path = args.config
94
121
  mtime = config_mtime(config_path)
95
122
 
96
- while True:
97
- results = run_checks(targets, ping_enabled, args.ping_timeout, args.http_timeout)
98
- history.update(results, {r.target.raw: is_online(r) for r in results})
99
- for result in results:
100
- print(emit(result, history), flush=True)
101
-
102
- if args.once:
103
- return compute_exit_code(results)
104
-
105
- reload = reload_if_changed(config_path, args.urls, mtime)
106
- mtime = reload.mtime
107
- if reload.error:
108
- console.print(f"[yellow]warning:[/yellow] config reload failed: {reload.error}")
109
- if reload.targets is not None:
110
- targets = reload.targets
111
-
112
- time.sleep(args.interval)
123
+ try:
124
+ while True:
125
+ results = run_checks(targets, ping_enabled, args.ping_timeout, args.http_timeout)
126
+ history.update(results, {r.target.raw: is_online(r) for r in results})
127
+ for result in results:
128
+ print(emit(result, history), flush=True)
129
+
130
+ if args.once:
131
+ return compute_exit_code(results)
132
+
133
+ reload = reload_if_changed(config_path, combined_targets(args), mtime)
134
+ mtime = reload.mtime
135
+ if reload.error:
136
+ console.print(f"[yellow]warning:[/yellow] config reload failed: {reload.error}")
137
+ if reload.targets is not None:
138
+ targets = reload.targets
139
+
140
+ time.sleep(args.interval)
141
+ except KeyboardInterrupt:
142
+ # Plain-text/JSON output is meant for logs/pipes, so keep stdout
143
+ # clean and only note the interruption on stderr.
144
+ print("stopped", file=sys.stderr)
145
+ return 0
113
146
 
114
147
 
115
148
  def run_interactive(
@@ -154,7 +187,7 @@ def run_interactive(
154
187
  base = build_table(results, history)
155
188
  live.update(framed(base))
156
189
 
157
- reload = reload_if_changed(config_path, args.urls, mtime)
190
+ reload = reload_if_changed(config_path, combined_targets(args), mtime)
158
191
  mtime = reload.mtime
159
192
  if reload.error:
160
193
  console.print(f"[yellow]warning:[/yellow] config reload failed: {reload.error}")
@@ -173,7 +206,7 @@ def main(argv: list[str] | None = None) -> int:
173
206
  console = Console()
174
207
 
175
208
  try:
176
- targets = load_targets(args.config, args.urls)
209
+ targets = load_targets(args.config, combined_targets(args))
177
210
  except (FileNotFoundError, ValueError) as exc:
178
211
  console.print(f"[bold red]error:[/bold red] {exc}")
179
212
  return 1
@@ -1,3 +0,0 @@
1
- from .cli import main
2
-
3
- __all__ = ["main"]
File without changes