pingera-cli 0.1.11__tar.gz → 0.1.12__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.
Files changed (53) hide show
  1. {pingera_cli-0.1.11/pingera_cli.egg-info → pingera_cli-0.1.12}/PKG-INFO +2 -2
  2. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/__init__.py +1 -1
  3. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/commands/checks.py +17 -8
  4. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/formatters/__init__.py +3 -1
  5. pingera_cli-0.1.12/pingera_cli/formatters/dns_formatter.py +66 -0
  6. pingera_cli-0.1.12/pingera_cli/formatters/icmp_formatter.py +64 -0
  7. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/formatters/registry.py +4 -0
  8. {pingera_cli-0.1.11 → pingera_cli-0.1.12/pingera_cli.egg-info}/PKG-INFO +2 -2
  9. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli.egg-info/SOURCES.txt +2 -0
  10. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli.egg-info/requires.txt +1 -1
  11. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pyproject.toml +1 -1
  12. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/.gitignore +0 -0
  13. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/.replit +0 -0
  14. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/LICENSE +0 -0
  15. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/README.md +0 -0
  16. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/assert +0 -0
  17. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/docs/cli-commands.md +0 -0
  18. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/docs/example-check.yaml +0 -0
  19. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/docs/example-synthetic-screenshot.json +0 -0
  20. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/docs/example-web-check.json +0 -0
  21. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/__main__.py +0 -0
  22. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/commands/__init__.py +0 -0
  23. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/commands/auth.py +0 -0
  24. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/commands/base.py +0 -0
  25. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/commands/check_groups.py +0 -0
  26. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/commands/check_secrets.py +0 -0
  27. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/commands/on_demand_checks.py +0 -0
  28. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/commands/secrets.py +0 -0
  29. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/formatters/base_formatter.py +0 -0
  30. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/formatters/generic_formatter.py +0 -0
  31. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/formatters/multistep_formatter.py +0 -0
  32. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/formatters/ssl_formatter.py +0 -0
  33. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/formatters/synthetic_formatter.py +0 -0
  34. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/formatters/web_formatter.py +0 -0
  35. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/main.py +0 -0
  36. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/utils/__init__.py +0 -0
  37. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/utils/config.py +0 -0
  38. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/utils/console.py +0 -0
  39. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli/utils/file_utils.py +0 -0
  40. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli.egg-info/dependency_links.txt +0 -0
  41. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli.egg-info/entry_points.txt +0 -0
  42. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/pingera_cli.egg-info/top_level.txt +0 -0
  43. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/replit.md +0 -0
  44. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/run_tests.py +0 -0
  45. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/setup.cfg +0 -0
  46. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/setup.py +0 -0
  47. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/tests/__init__.py +0 -0
  48. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/tests/conftest.py +0 -0
  49. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/tests/requirements.txt +0 -0
  50. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/tests/test_auth.py +0 -0
  51. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/tests/test_checks.py +0 -0
  52. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/tests/test_config.py +0 -0
  53. {pingera_cli-0.1.11 → pingera_cli-0.1.12}/tests/test_on_demand_checks.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pingera-cli
3
- Version: 0.1.11
3
+ Version: 0.1.12
4
4
  Summary: A beautiful Python CLI tool built with typer and rich, distributed via pip and based on Pingera SDK
5
5
  Home-page: https://github.com/pingera/pingera-cli
6
6
  Author: PingeraCLI Team
@@ -31,7 +31,7 @@ Description-Content-Type: text/markdown
31
31
  License-File: LICENSE
32
32
  Requires-Dist: typer[all]>=0.9.0
33
33
  Requires-Dist: rich>=13.0.0
34
- Requires-Dist: pingera-sdk>=1.0.8
34
+ Requires-Dist: pingera-sdk>=1.0.10
35
35
  Requires-Dist: click>=8.0.0
36
36
  Provides-Extra: dev
37
37
  Requires-Dist: pytest>=6.0; extra == "dev"
@@ -2,7 +2,7 @@
2
2
  Pingera CLI - A beautiful CLI tool for Pingera Platform
3
3
  """
4
4
 
5
- __version__ = "0.1.11"
5
+ __version__ = "0.1.12"
6
6
  __author__ = "Pingera Team"
7
7
  __description__ = "A beautiful Python CLI tool built with typer and rich, distributed via pip and based on Pingera SDK"
8
8
 
@@ -194,8 +194,15 @@ class ChecksCommand(BaseCommand):
194
194
  check_url = "-"
195
195
  if hasattr(check, 'url') and check.url:
196
196
  check_url = str(check.url)
197
- elif hasattr(check, 'host') and hasattr(check, 'port') and check.host and check.port:
198
- check_url = f"{check.host}:{check.port}"
197
+ elif hasattr(check, 'host') and check.host:
198
+ # For ICMP and DNS checks, show just the host
199
+ # For TCP and other checks with ports, show host:port
200
+ if check_type in ["icmp", "dns"]:
201
+ check_url = str(check.host)
202
+ elif hasattr(check, 'port') and check.port:
203
+ check_url = f"{check.host}:{check.port}"
204
+ else:
205
+ check_url = str(check.host)
199
206
 
200
207
  # Handle active status
201
208
  active_status = "✅" if hasattr(check, 'active') and check.active else "❌"
@@ -537,7 +544,7 @@ class ChecksCommand(BaseCommand):
537
544
  self.display_error(f"URL is required for {actual_check_type} checks")
538
545
  raise typer.Exit(1)
539
546
 
540
- if actual_check_type in ['tcp'] and not host:
547
+ if actual_check_type in ['tcp', 'icmp', 'dns'] and not host:
541
548
  self.display_error(f"Host is required for {actual_check_type} checks")
542
549
  raise typer.Exit(1)
543
550
 
@@ -1118,7 +1125,7 @@ def get_output_format():
1118
1125
  def list_checks(
1119
1126
  page: int = typer.Option(1, "--page", "-p", help="Page number"),
1120
1127
  page_size: int = typer.Option(20, "--page-size", "-s", help="Items per page (max 100)"),
1121
- check_type: Optional[str] = typer.Option(None, "--type", "-t", help="Filter by check type (web, api, ssl, tcp, synthetic, multistep)"),
1128
+ check_type: Optional[str] = typer.Option(None, "--type", "-t", help="Filter by check type (web, api, ssl, tcp, icmp, dns, synthetic, multistep)"),
1122
1129
  status: Optional[str] = typer.Option(None, "--status", help="Filter by status. Multiple statuses can be separated by commas (e.g., 'ok,failed')"),
1123
1130
  name: Optional[str] = typer.Option(None, "--name", "-n", help="Filter by name using case-insensitive partial matching (max 100 chars)"),
1124
1131
  group_id: Optional[str] = typer.Option(None, "--group-id", "-g", help="Filter by group ID"),
@@ -1130,8 +1137,8 @@ def list_checks(
1130
1137
  raise typer.Exit(1)
1131
1138
 
1132
1139
  # Validate check type
1133
- if check_type and check_type not in ["web", "api", "ssl", "tcp", "synthetic", "multistep"]:
1134
- typer.echo("Error: Invalid check type. Must be one of: web, api, ssl, tcp, synthetic, multistep", err=True)
1140
+ if check_type and check_type not in ["web", "api", "ssl", "tcp", "icmp", "dns", "synthetic", "multistep"]:
1141
+ typer.echo("Error: Invalid check type. Must be one of: web, api, ssl, tcp, icmp, dns, synthetic, multistep", err=True)
1135
1142
  raise typer.Exit(1)
1136
1143
 
1137
1144
  # Validate status values if provided
@@ -1159,9 +1166,9 @@ def get_check(
1159
1166
  @app.command("create")
1160
1167
  def create_check(
1161
1168
  name: str = typer.Option("", "--name", "-n", help="Check name (required if not using --from-file)"),
1162
- check_type: str = typer.Option("web", "--type", "-t", help="Check type (web, api, tcp, ssl, synthetic, multistep)"),
1169
+ check_type: str = typer.Option("web", "--type", "-t", help="Check type (web, api, tcp, ssl, icmp, dns, synthetic, multistep)"),
1163
1170
  url: Optional[str] = typer.Option(None, "--url", "-u", help="URL to monitor (required for web, api, ssl checks)"),
1164
- host: Optional[str] = typer.Option(None, "--host", help="Hostname/IP for TCP/SSL checks (max 255 characters)"),
1171
+ host: Optional[str] = typer.Option(None, "--host", help="Hostname/IP for TCP/SSL/ICMP/DNS checks (max 255 characters)"),
1165
1172
  port: Optional[int] = typer.Option(None, "--port", help="Port number for TCP checks (1-65535)"),
1166
1173
  interval: int = typer.Option(300, "--interval", "-i", help="Check interval in seconds"),
1167
1174
  timeout: int = typer.Option(30, "--timeout", help="Timeout in seconds"),
@@ -1179,6 +1186,8 @@ def create_check(
1179
1186
  - web/api: --url required
1180
1187
  - tcp: --host required, --port optional
1181
1188
  - ssl: --url or --host required
1189
+ - icmp: --host required (hostname or IP to ping)
1190
+ - dns: --host required (domain name to query)
1182
1191
  - synthetic/multistep: --pw-script-file or --parameters with pw_script required"""
1183
1192
 
1184
1193
  # Validate that we have either from_file or required parameters
@@ -7,7 +7,9 @@ from .ssl_formatter import SSLFormatter
7
7
  from .synthetic_formatter import SyntheticFormatter
8
8
  from .multistep_formatter import MultistepFormatter
9
9
  from .web_formatter import WebFormatter
10
+ from .icmp_formatter import ICMPFormatter
11
+ from .dns_formatter import DNSFormatter
10
12
  from .generic_formatter import GenericFormatter
11
13
  from .registry import FormatterRegistry
12
14
 
13
- __all__ = ['SSLFormatter', 'SyntheticFormatter', 'MultistepFormatter', 'WebFormatter', 'GenericFormatter', 'FormatterRegistry']
15
+ __all__ = ['SSLFormatter', 'SyntheticFormatter', 'MultistepFormatter', 'WebFormatter', 'ICMPFormatter', 'DNSFormatter', 'GenericFormatter', 'FormatterRegistry']
@@ -0,0 +1,66 @@
1
+
2
+ """
3
+ DNS check result formatter
4
+ """
5
+
6
+ from typing import Dict, Any, List
7
+ from .base_formatter import BaseFormatter
8
+
9
+
10
+ class DNSFormatter(BaseFormatter):
11
+ """Formatter for DNS check results"""
12
+
13
+ def can_format(self, metadata: Dict[str, Any]) -> bool:
14
+ """Check if this is DNS metadata"""
15
+ return 'record_type' in metadata and 'answers' in metadata
16
+
17
+ def format(self, metadata: Dict[str, Any]) -> str:
18
+ """Format DNS check metadata"""
19
+ info = "\n[bold cyan]DNS Query Results:[/bold cyan]"
20
+
21
+ # Query information
22
+ if 'domain' in metadata:
23
+ info += f"\n• Domain: [white]{metadata['domain']}[/white]"
24
+ if 'record_type' in metadata:
25
+ info += f"\n• Record Type: [blue]{metadata['record_type']}[/blue]"
26
+
27
+ # DNS servers used
28
+ if 'dns_servers_used' in metadata:
29
+ servers = metadata['dns_servers_used']
30
+ if servers == 'system_default':
31
+ info += f"\n• DNS Servers: [dim]System Default[/dim]"
32
+ elif isinstance(servers, list):
33
+ info += f"\n• DNS Servers: [white]{', '.join(servers)}[/white]"
34
+ else:
35
+ info += f"\n• DNS Servers: [white]{servers}[/white]"
36
+
37
+ # Validation mode
38
+ if 'validation_mode' in metadata and metadata['validation_mode'] != 'none':
39
+ info += f"\n• Validation Mode: [white]{metadata['validation_mode']}[/white]"
40
+
41
+ # DNS answers
42
+ if 'answers' in metadata and metadata['answers']:
43
+ info += "\n\n[bold cyan]DNS Answers:[/bold cyan]"
44
+ for answer in metadata['answers']:
45
+ info += f"\n• [green]{answer}[/green]"
46
+ elif 'answers' in metadata:
47
+ info += "\n\n[bold cyan]DNS Answers:[/bold cyan]"
48
+ info += f"\n• [yellow]No records found[/yellow]"
49
+
50
+ # Expected answers (if validation was performed)
51
+ if 'expected_answers' in metadata and metadata['expected_answers']:
52
+ info += "\n\n[bold cyan]Expected Answers:[/bold cyan]"
53
+ for expected in metadata['expected_answers']:
54
+ # Check if this expected answer is in the actual answers
55
+ is_present = 'answers' in metadata and expected in metadata['answers']
56
+ color = "green" if is_present else "red"
57
+ icon = "✅" if is_present else "❌"
58
+ info += f"\n• [{color}]{icon} {expected}[/{color}]"
59
+
60
+ # Authoritative nameservers in verbose mode
61
+ if self.verbose and 'authoritative_ns' in metadata and metadata['authoritative_ns']:
62
+ info += "\n\n[bold cyan]Authoritative Nameservers:[/bold cyan]"
63
+ for ns in metadata['authoritative_ns']:
64
+ info += f"\n• [dim]{ns}[/dim]"
65
+
66
+ return info
@@ -0,0 +1,64 @@
1
+
2
+ """
3
+ ICMP (Ping) check result formatter
4
+ """
5
+
6
+ from typing import Dict, Any
7
+ from .base_formatter import BaseFormatter
8
+
9
+
10
+ class ICMPFormatter(BaseFormatter):
11
+ """Formatter for ICMP/Ping check results"""
12
+
13
+ def can_format(self, metadata: Dict[str, Any]) -> bool:
14
+ """Check if this is ICMP metadata"""
15
+ return 'packet_loss_percent' in metadata or 'latency_avg_ms' in metadata
16
+
17
+ def format(self, metadata: Dict[str, Any]) -> str:
18
+ """Format ICMP check metadata"""
19
+ info = "\n[bold cyan]ICMP Ping Results:[/bold cyan]"
20
+
21
+ # Host and IP information
22
+ if 'original_host' in metadata:
23
+ info += f"\n• Target Host: [white]{metadata['original_host']}[/white]"
24
+ if 'resolved_ip' in metadata:
25
+ info += f"\n• Resolved IP: [white]{metadata['resolved_ip']}[/white]"
26
+ if 'ip_version_used' in metadata:
27
+ info += f"\n• IP Version: [white]{metadata['ip_version_used']}[/white]"
28
+
29
+ # Packet loss
30
+ if 'packet_loss_percent' in metadata:
31
+ loss = metadata['packet_loss_percent']
32
+ loss_color = "green" if loss == 0 else "yellow" if loss < 25 else "red"
33
+ info += f"\n• Packet Loss: [{loss_color}]{loss}%[/{loss_color}]"
34
+
35
+ # Latency statistics
36
+ if 'latency_avg_ms' in metadata:
37
+ info += f"\n• Average Latency: [yellow]{metadata['latency_avg_ms']:.3f}ms[/yellow]"
38
+ if 'latency_min_ms' in metadata:
39
+ info += f"\n• Min Latency: [green]{metadata['latency_min_ms']:.3f}ms[/green]"
40
+ if 'latency_max_ms' in metadata:
41
+ info += f"\n• Max Latency: [red]{metadata['latency_max_ms']:.3f}ms[/red]"
42
+ if 'latency_stddev_ms' in metadata:
43
+ info += f"\n• Std Deviation: [white]{metadata['latency_stddev_ms']:.3f}ms[/white]"
44
+
45
+ # Probe configuration
46
+ if 'probe_count' in metadata:
47
+ info += f"\n• Probes Sent: [white]{metadata['probe_count']}[/white]"
48
+ if 'probe_interval_seconds' in metadata:
49
+ info += f"\n• Probe Interval: [white]{metadata['probe_interval_seconds']}s[/white]"
50
+ if 'probe_timeout_seconds' in metadata:
51
+ info += f"\n• Probe Timeout: [white]{metadata['probe_timeout_seconds']}s[/white]"
52
+
53
+ # Individual latencies in verbose mode
54
+ if self.verbose and 'latencies_ms' in metadata and metadata['latencies_ms']:
55
+ info += "\n\n[bold cyan]Individual Probe Latencies:[/bold cyan]"
56
+ for i, latency in enumerate(metadata['latencies_ms'], 1):
57
+ info += f"\n• Probe {i}: [yellow]{latency:.3f}ms[/yellow]"
58
+
59
+ # Raw ping output in verbose mode
60
+ if self.verbose and 'raw_ping_output' in metadata:
61
+ info += "\n\n[bold cyan]Raw Ping Output:[/bold cyan]"
62
+ info += f"\n[dim]{metadata['raw_ping_output']}[/dim]"
63
+
64
+ return info
@@ -9,6 +9,8 @@ from .ssl_formatter import SSLFormatter
9
9
  from .synthetic_formatter import SyntheticFormatter
10
10
  from .multistep_formatter import MultistepFormatter
11
11
  from .web_formatter import WebFormatter
12
+ from .icmp_formatter import ICMPFormatter
13
+ from .dns_formatter import DNSFormatter
12
14
  from .generic_formatter import GenericFormatter
13
15
 
14
16
 
@@ -22,6 +24,8 @@ class FormatterRegistry:
22
24
  SyntheticFormatter(verbose),
23
25
  MultistepFormatter(verbose),
24
26
  WebFormatter(verbose),
27
+ ICMPFormatter(verbose),
28
+ DNSFormatter(verbose),
25
29
  GenericFormatter(verbose) # Generic formatter should be last
26
30
  ]
27
31
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pingera-cli
3
- Version: 0.1.11
3
+ Version: 0.1.12
4
4
  Summary: A beautiful Python CLI tool built with typer and rich, distributed via pip and based on Pingera SDK
5
5
  Home-page: https://github.com/pingera/pingera-cli
6
6
  Author: PingeraCLI Team
@@ -31,7 +31,7 @@ Description-Content-Type: text/markdown
31
31
  License-File: LICENSE
32
32
  Requires-Dist: typer[all]>=0.9.0
33
33
  Requires-Dist: rich>=13.0.0
34
- Requires-Dist: pingera-sdk>=1.0.8
34
+ Requires-Dist: pingera-sdk>=1.0.10
35
35
  Requires-Dist: click>=8.0.0
36
36
  Provides-Extra: dev
37
37
  Requires-Dist: pytest>=6.0; extra == "dev"
@@ -30,7 +30,9 @@ pingera_cli/commands/on_demand_checks.py
30
30
  pingera_cli/commands/secrets.py
31
31
  pingera_cli/formatters/__init__.py
32
32
  pingera_cli/formatters/base_formatter.py
33
+ pingera_cli/formatters/dns_formatter.py
33
34
  pingera_cli/formatters/generic_formatter.py
35
+ pingera_cli/formatters/icmp_formatter.py
34
36
  pingera_cli/formatters/multistep_formatter.py
35
37
  pingera_cli/formatters/registry.py
36
38
  pingera_cli/formatters/ssl_formatter.py
@@ -1,6 +1,6 @@
1
1
  typer[all]>=0.9.0
2
2
  rich>=13.0.0
3
- pingera-sdk>=1.0.8
3
+ pingera-sdk>=1.0.10
4
4
  click>=8.0.0
5
5
 
6
6
  [dev]
@@ -35,7 +35,7 @@ requires-python = ">=3.7"
35
35
  dependencies = [
36
36
  "typer[all]>=0.9.0",
37
37
  "rich>=13.0.0",
38
- "pingera-sdk>=1.0.8",
38
+ "pingera-sdk>=1.0.10",
39
39
  "click>=8.0.0",
40
40
  ]
41
41
 
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes