Skip to content

Commit cdff465

Browse files
committed
Remove config.ini configuration. Rely on .env files. Make shorter flags.
1 parent a8e912d commit cdff465

9 files changed

Lines changed: 82 additions & 60 deletions

File tree

.env.example

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
PAGERTREE_API_KEY=your_api_key_here
2+
# PAGERTREE_BASE_URL=https://api.pagertree.com/api/v4
3+
# PAGERTREE_VERBOSE=true

README.md

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,16 @@ export PAGERTREE_API_KEY=your_api_key_here
6363
Add it to your shell profile (e.g., `~/.bashrc`, `~/.zshrc`) for persistence.
6464

6565
### Option 2: Configuration File
66-
Create a `config.ini` file:
67-
```ini
68-
[DEFAULT]
69-
API_KEY = your_api_key_here
66+
Create a `.env` file in the current working directory or specify a custom path:
67+
68+
```env
69+
PAGERTREE_API_KEY = your_api_key_here
7070
```
71+
7172
Specify the config file when running commands:
7273
```bash
73-
pagertree --config config.ini alerts list
74-
```
75-
76-
### Option 3: .env File
77-
Create a `.env` file in the working directory:
78-
```env
79-
PAGERTREE_API_KEY=your_api_key_here
74+
pagertree --config ../other/path/.env alerts list
8075
```
81-
The CLI automatically loads the `.env` file.
8276

8377
## Usage
8478

api.py

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1+
import click
12
import requests
23
import os
34
import configparser
45
from typing import Optional, List, Dict, Any
56

67
class PagerTreeClient:
7-
def __init__(self, config_file: Optional[str] = None):
8+
def __init__(self):
89
"""Initialize PagerTree client with configuration."""
9-
# Load configuration
10-
self.config = self._load_config(config_file)
11-
1210
# Set up base URL and API key
13-
self.base_url = self.config.get('DEFAULT', 'BASE_URL', fallback=os.getenv('PAGERTREE_BASE_URL', 'https://api.pagertree.com/api/v4'))
14-
self.api_key = self.config.get('DEFAULT', 'API_KEY', fallback=os.getenv('PAGERTREE_API_KEY'))
11+
self.base_url = os.getenv('PAGERTREE_BASE_URL', 'https://api.pagertree.com/api/v4')
12+
self.api_key = os.getenv('PAGERTREE_API_KEY')
1513
self.user_agent = "PagerTree-Python-CLI-Client/1.0"
1614

1715
if not self.api_key:
18-
raise ValueError("API_KEY must be provided via environment variable or config file")
16+
raise click.UsageError("API_KEY must be provided via environment variable or .env config file")
1917

2018
# Set up default headers
2119
self.default_headers = {
@@ -28,13 +26,6 @@ def __init__(self, config_file: Optional[str] = None):
2826
self.session = requests.Session()
2927
self.session.headers.update(self.default_headers)
3028

31-
def _load_config(self, config_file: Optional[str]) -> configparser.ConfigParser:
32-
"""Load configuration from file or return empty config."""
33-
config = configparser.ConfigParser()
34-
if config_file and os.path.exists(config_file):
35-
config.read(config_file)
36-
return config
37-
3829
# ALERTS
3930
# =======
4031

commands/alerts.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import click
2+
import json
23
from utils import display_paginated_results, handle_api_error, format_item_details
34

45
@click.group()
@@ -17,7 +18,7 @@ def alerts():
1718
def create_alert_cmd(ctx, title, description, team_ids, urgency, tags, alias):
1819
"""Create a new alert in PagerTree."""
1920
try:
20-
client = ctx.obj # Get PagerTreeClient from context
21+
client = ctx.obj.client # Get PagerTreeClient from context
2122
result = client.create_alert(
2223
title=title,
2324
description=description,
@@ -39,15 +40,19 @@ def create_alert_cmd(ctx, title, description, team_ids, urgency, tags, alias):
3940
def list_alerts_cmd(ctx, limit, offset, status, search):
4041
"""List alerts in PagerTree with pagination."""
4142
try:
42-
client = ctx.obj # Get PagerTreeClient from context
43+
client = ctx.obj.client # Get PagerTreeClient from context
44+
logger = ctx.obj.logger # Get logger from context
45+
logger.debug(f"Listing alerts with limit={limit}, offset={offset}, status={status}, search={search}")
4346
result = client.list_alerts(limit=limit, offset=offset, status=status, search=search)
47+
logger.debug(f"Full response: {json.dumps(result, indent=2)}")
4448
alerts_list = result["data"]
4549
total = result["total"]
4650
# Prepare table data
4751
headers = ["ID", "Title", "Status"]
4852
table_data = [[alert.get("id"), alert.get("title"), alert.get("status")] for alert in alerts_list]
4953
display_paginated_results(alerts_list, total, limit, offset, "alert", headers, table_data)
5054
except Exception as e:
55+
logger.error(f"Error listing alerts: {str(e)}")
5156
handle_api_error(e, action="listing alerts")
5257

5358
@alerts.command(name="show")
@@ -56,7 +61,7 @@ def list_alerts_cmd(ctx, limit, offset, status, search):
5661
def show_alert_cmd(ctx, alert_id):
5762
"""Show details of a specific alert in PagerTree."""
5863
try:
59-
client = ctx.obj # Get PagerTreeClient from context
64+
client = ctx.obj.client # Get PagerTreeClient from context
6065
alert = client.show_alert(alert_id)
6166
fields = {
6267
"id": "ID",
@@ -85,7 +90,7 @@ def delete_alert_cmd(ctx, alert_id, force):
8590
click.echo("Deletion cancelled.")
8691
return
8792
try:
88-
client = ctx.obj # Get PagerTreeClient from context
93+
client = ctx.obj.client # Get PagerTreeClient from context
8994
result = client.delete_alert(alert_id)
9095
click.echo(f"Alert deleted successfully: {alert_id}")
9196
except Exception as e:
@@ -98,7 +103,7 @@ def delete_alert_cmd(ctx, alert_id, force):
98103
def acknowledge_alert_cmd(ctx, alert_id, alias):
99104
"""Acknowledge an alert in PagerTree."""
100105
try:
101-
client = ctx.obj # Get PagerTreeClient from context
106+
client = ctx.obj.client # Get PagerTreeClient from context
102107

103108
# Ensure at least one of alert_id or alias is provided
104109
if not alert_id and not alias:
@@ -130,7 +135,7 @@ def acknowledge_alert_cmd(ctx, alert_id, alias):
130135
def reject_alert_cmd(ctx, alert_id, alias):
131136
"""Reject an alert in PagerTree."""
132137
try:
133-
client = ctx.obj # Get PagerTreeClient from context
138+
client = ctx.obj.client # Get PagerTreeClient from context
134139

135140
# Ensure at least one of alert_id or alias is provided
136141
if not alert_id and not alias:
@@ -162,7 +167,7 @@ def reject_alert_cmd(ctx, alert_id, alias):
162167
def resolve_alert_cmd(ctx, alert_id, alias):
163168
"""Resolve an alert in PagerTree."""
164169
try:
165-
client = ctx.obj # Get PagerTreeClient from context
170+
client = ctx.obj.client # Get PagerTreeClient from context
166171

167172
# Ensure at least one of alert_id or alias is provided
168173
if not alert_id and not alias:
@@ -196,7 +201,7 @@ def resolve_alert_cmd(ctx, alert_id, alias):
196201
def list_alert_comment_cmd(ctx, alert_id, alias, limit, offset):
197202
"""List an alert's comments in PagerTree."""
198203
try:
199-
client = ctx.obj # Get PagerTreeClient from context
204+
client = ctx.obj.client # Get PagerTreeClient from context
200205

201206
# Ensure at least one of alert_id or alias is provided
202207
if not alert_id and not alias:
@@ -234,7 +239,7 @@ def list_alert_comment_cmd(ctx, alert_id, alias, limit, offset):
234239
def create_alert_comment_cmd(ctx, alert_id, alias, comment):
235240
"""Add a comment to an alert in PagerTree."""
236241
try:
237-
client = ctx.obj # Get PagerTreeClient from context
242+
client = ctx.obj.client # Get PagerTreeClient from context
238243

239244
# Ensure at least one of alert_id or alias is provided
240245
if not alert_id and not alias:

commands/broadcasts.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def create_broadcast_cmd(
1818
):
1919
"""Create a new broadcast in PagerTree."""
2020
try:
21-
client = ctx.obj # Get PagerTreeClient from context
21+
client = ctx.obj.client # Get PagerTreeClient from context
2222
result = client.create_broadcast(
2323
title=title,
2424
description=description,
@@ -36,7 +36,7 @@ def create_broadcast_cmd(
3636
def list_broadcasts_cmd(ctx, limit, offset):
3737
"""List broadcasts in PagerTree with pagination."""
3838
try:
39-
client = ctx.obj # Get PagerTreeClient from context
39+
client = ctx.obj.client # Get PagerTreeClient from context
4040
result = client.list_broadcasts(limit=limit, offset=offset)
4141
broadcasts_list = result["data"]
4242
total = result["total"]
@@ -61,7 +61,7 @@ def list_broadcasts_cmd(ctx, limit, offset):
6161
def show_broadcast_cmd(ctx, broadcast_id):
6262
"""Show details of a specific broadcast in PagerTree."""
6363
try:
64-
client = ctx.obj # Get PagerTreeClient from context
64+
client = ctx.obj.client # Get PagerTreeClient from context
6565
broadcast = client.show_broadcast(broadcast_id)
6666
fields = {
6767
"id": "Broadcast ID",
@@ -89,7 +89,7 @@ def delete_broadcast_cmd(ctx, broadcast_id, force):
8989
click.echo("Deletion cancelled.")
9090
return
9191
try:
92-
client = ctx.obj # Get PagerTreeClient from context
92+
client = ctx.obj.client # Get PagerTreeClient from context
9393
result = client.delete_broadcast(broadcast_id)
9494
click.echo(f"Broadcast deleted successfully: {broadcast_id}")
9595
except Exception as e:

commands/teams.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def teams():
1616
def create_team_cmd(ctx, name, notes, member_ids, admin_ids):
1717
"""Create a new team in PagerTree."""
1818
try:
19-
client = ctx.obj # Get PagerTreeClient from context
19+
client = ctx.obj.client # Get PagerTreeClient from context
2020
result = client.create_team(
2121
name=name,
2222
notes=notes,
@@ -35,7 +35,7 @@ def create_team_cmd(ctx, name, notes, member_ids, admin_ids):
3535
def list_teams_cmd(ctx, limit, offset, search):
3636
"""List teams in PagerTree with pagination."""
3737
try:
38-
client = ctx.obj # Get PagerTreeClient from context
38+
client = ctx.obj.client # Get PagerTreeClient from context
3939
result = client.list_teams(limit=limit, offset=offset, search=search)
4040
teams_list = result["data"]
4141
total = result["total"]
@@ -58,7 +58,7 @@ def list_teams_cmd(ctx, limit, offset, search):
5858
def show_team_cmd(ctx, team_id):
5959
"""Show details of a specific team in PagerTree."""
6060
try:
61-
client = ctx.obj # Get PagerTreeClient from context
61+
client = ctx.obj.client # Get PagerTreeClient from context
6262
team = client.show_team(team_id)
6363

6464
# Display team details
@@ -164,7 +164,7 @@ def show_team_cmd(ctx, team_id):
164164
def update_team_cmd(ctx, team_id, name, notes, member_ids, admin_ids):
165165
"""Update a team in PagerTree."""
166166
try:
167-
client = ctx.obj # Get PagerTreeClient from context
167+
client = ctx.obj.client # Get PagerTreeClient from context
168168
result = client.update_team(
169169
team_id=team_id,
170170
name=name,
@@ -186,7 +186,7 @@ def delete_team_cmd(ctx, team_id, force):
186186
click.echo("Deletion cancelled.")
187187
return
188188
try:
189-
client = ctx.obj # Get PagerTreeClient from context
189+
client = ctx.obj.client # Get PagerTreeClient from context
190190
result = client.delete_team(team_id)
191191
click.echo(f"Team deleted successfully: {team_id}")
192192
except Exception as e:
@@ -198,7 +198,7 @@ def delete_team_cmd(ctx, team_id, force):
198198
def current_oncall_cmd(ctx, team_id):
199199
"""Show current on-call users for a specific team in PagerTree."""
200200
try:
201-
client = ctx.obj # Get PagerTreeClient from context
201+
client = ctx.obj.client # Get PagerTreeClient from context
202202
result = client.get_team_current_oncall(team_id)
203203
if not result:
204204
click.echo(f"No one schedule oncall for team {team_id}")
@@ -258,7 +258,7 @@ def current_oncall_cmd(ctx, team_id):
258258
def team_alerts_cmd(ctx, team_id, limit, offset):
259259
"""List alerts for a specific team in PagerTree."""
260260
try:
261-
client = ctx.obj # Get PagerTreeClient from context
261+
client = ctx.obj.client # Get PagerTreeClient from context
262262
result = client.get_team_alerts(team_id, limit=limit, offset=offset)
263263
alerts_list = result["data"]
264264
total = result["total"]

commands/users.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def users():
1515
def create_user_cmd(ctx, name, email, role, team_ids):
1616
"""Create a new account user in PagerTree."""
1717
try:
18-
client = ctx.obj # Get PagerTreeClient from context
18+
client = ctx.obj.client # Get PagerTreeClient from context
1919
roles = {r: True for r in role} if role else {}
2020
result = client.create_user(name=name, email=email, roles=roles, team_ids=list(team_ids))
2121
click.echo(f"User created successfully: {result.get('id')}")
@@ -30,7 +30,7 @@ def create_user_cmd(ctx, name, email, role, team_ids):
3030
def list_users_cmd(ctx, limit, offset, search):
3131
"""List users in PagerTree with pagination."""
3232
try:
33-
client = ctx.obj # Get PagerTreeClient from context
33+
client = ctx.obj.client # Get PagerTreeClient from context
3434
result = client.list_users(limit=limit, offset=offset, search=search)
3535
users_list = result["data"]
3636
total = result["total"]
@@ -58,7 +58,7 @@ def list_users_cmd(ctx, limit, offset, search):
5858
def show_user_cmd(ctx, user_id):
5959
"""Show details of a specific user in PagerTree."""
6060
try:
61-
client = ctx.obj # Get PagerTreeClient from context
61+
client = ctx.obj.client # Get PagerTreeClient from context
6262
user = client.show_user(user_id)
6363
fields = {
6464
"user.id": "User ID",
@@ -95,7 +95,7 @@ def show_user_cmd(ctx, user_id):
9595
def update_user_cmd(ctx, user_id, name):
9696
"""Update an account user in PagerTree."""
9797
try:
98-
client = ctx.obj # Get PagerTreeClient from context
98+
client = ctx.obj.client # Get PagerTreeClient from context
9999
result = client.update_user(user_id=user_id, name=name)
100100
click.echo(f"User updated successfully: {result.get('id')}")
101101
except Exception as e:
@@ -111,7 +111,7 @@ def delete_user_cmd(ctx, user_id, force):
111111
click.echo("Deletion cancelled.")
112112
return
113113
try:
114-
client = ctx.obj # Get PagerTreeClient from context
114+
client = ctx.obj.client # Get PagerTreeClient from context
115115
result = client.delete_user(user_id)
116116
click.echo(f"User deleted successfully: {user_id}")
117117
except Exception as e:

config.ini

Lines changed: 0 additions & 3 deletions
This file was deleted.

pagertree.py

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,55 @@
44
import os
55
import importlib
66
import pkgutil
7+
import logging
78
from dotenv import load_dotenv
89
from api import PagerTreeClient
910

10-
load_dotenv()
11+
# Set up logging
12+
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
13+
logger = logging.getLogger(__name__)
14+
15+
class ContextObject:
16+
"""Context object to hold client and configuration."""
17+
def __init__(self, client, logger, verbose=False):
18+
self.client = client
19+
self.logger = logger
20+
self.verbose = verbose
1121

1222
@click.group()
1323
@click.option(
14-
"--config",
24+
"--config", "-c",
1525
type=click.Path(exists=True, dir_okay=False, readable=True),
16-
help="Path to configuration file (e.g., config.ini)",
26+
help="Path to .env file",
1727
envvar="PAGERTREE_CONFIG",
1828
)
29+
@click.option(
30+
"--verbose", "-v",
31+
is_flag=True,
32+
help="Enable verbose output"
33+
)
1934
@click.pass_context
20-
def cli(ctx, config):
35+
def cli(ctx, config, verbose):
2136
"""PagerTree CLI Tool - Manage alerts from the command line."""
22-
# Initialize PagerTreeClient and store it in the context
23-
ctx.obj = PagerTreeClient(config_file=config)
37+
38+
# Load .env file if provided or check for default .env
39+
config = config or ('.env' if os.path.exists('.env') else None)
40+
logger.info(f"Loading .env from {config}" if config else "No .env file provided; relying on system environment variables")
41+
load_dotenv(dotenv_path=config, verbose=True)
42+
43+
# Determine verbose setting: command-line flag takes precedence over env var
44+
env_verbose = os.getenv("PAGERTREE_VERBOSE", "false").lower() in ("true", "1", "t")
45+
verbose = verbose or env_verbose
46+
47+
# Set logging level based on verbose setting
48+
logger.setLevel(logging.DEBUG if verbose else logging.INFO)
49+
logger.debug("Verbose mode enabled")
50+
51+
# Initialize PagerTreeClient
52+
client = PagerTreeClient()
53+
54+
# Store context object
55+
ctx.obj = ContextObject(client=client, logger=logger, verbose=verbose)
2456

2557
# Dynamically register all command groups from the 'commands' package
2658
commands_dir = os.path.join(os.path.dirname(__file__), "commands")

0 commit comments

Comments
 (0)