gravi-cli 0.1.1__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.
- gravi_cli-0.1.1/.bumpversion.toml +27 -0
- gravi_cli-0.1.1/.gitignore +46 -0
- gravi_cli-0.1.1/LICENSE +31 -0
- gravi_cli-0.1.1/PKG-INFO +345 -0
- gravi_cli-0.1.1/README.md +315 -0
- gravi_cli-0.1.1/gravi_cli/__init__.py +9 -0
- gravi_cli-0.1.1/gravi_cli/api.py +49 -0
- gravi_cli-0.1.1/gravi_cli/auth.py +139 -0
- gravi_cli-0.1.1/gravi_cli/cli.py +401 -0
- gravi_cli-0.1.1/gravi_cli/client.py +286 -0
- gravi_cli-0.1.1/gravi_cli/config.py +134 -0
- gravi_cli-0.1.1/gravi_cli/exceptions.py +36 -0
- gravi_cli-0.1.1/pyproject.toml +71 -0
- gravi_cli-0.1.1/release.sh +66 -0
- gravi_cli-0.1.1/tests/__init__.py +1 -0
- gravi_cli-0.1.1/tests/conftest.py +49 -0
- gravi_cli-0.1.1/tests/test_api.py +106 -0
- gravi_cli-0.1.1/tests/test_auth.py +261 -0
- gravi_cli-0.1.1/tests/test_cli.py +622 -0
- gravi_cli-0.1.1/tests/test_client.py +251 -0
- gravi_cli-0.1.1/tests/test_config.py +111 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
[tool.bumpversion]
|
|
2
|
+
current_version = "0.1.1"
|
|
3
|
+
parse = "(?P<major>\\d+)\\.(?P<minor>\\d+)\\.(?P<patch>\\d+)"
|
|
4
|
+
serialize = ["{major}.{minor}.{patch}"]
|
|
5
|
+
search = "{current_version}"
|
|
6
|
+
replace = "{new_version}"
|
|
7
|
+
regex = false
|
|
8
|
+
ignore_missing_version = false
|
|
9
|
+
ignore_missing_files = false
|
|
10
|
+
tag = false
|
|
11
|
+
sign_tags = false
|
|
12
|
+
tag_name = "v{new_version}"
|
|
13
|
+
tag_message = "Bump version: {current_version} → {new_version}"
|
|
14
|
+
allow_dirty = false
|
|
15
|
+
commit = false
|
|
16
|
+
message = "Bump version: {current_version} → {new_version}"
|
|
17
|
+
commit_args = ""
|
|
18
|
+
|
|
19
|
+
[[tool.bumpversion.files]]
|
|
20
|
+
filename = "pyproject.toml"
|
|
21
|
+
search = 'version = "{current_version}"'
|
|
22
|
+
replace = 'version = "{new_version}"'
|
|
23
|
+
|
|
24
|
+
[[tool.bumpversion.files]]
|
|
25
|
+
filename = "gravi_cli/__init__.py"
|
|
26
|
+
search = '__version__ = "{current_version}"'
|
|
27
|
+
replace = '__version__ = "{new_version}"'
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
build/
|
|
8
|
+
develop-eggs/
|
|
9
|
+
dist/
|
|
10
|
+
downloads/
|
|
11
|
+
eggs/
|
|
12
|
+
.eggs/
|
|
13
|
+
lib/
|
|
14
|
+
lib64/
|
|
15
|
+
parts/
|
|
16
|
+
sdist/
|
|
17
|
+
var/
|
|
18
|
+
wheels/
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.installed.cfg
|
|
21
|
+
*.egg
|
|
22
|
+
|
|
23
|
+
# Virtual environments
|
|
24
|
+
venv/
|
|
25
|
+
env/
|
|
26
|
+
ENV/
|
|
27
|
+
|
|
28
|
+
# Testing
|
|
29
|
+
.pytest_cache/
|
|
30
|
+
.coverage
|
|
31
|
+
htmlcov/
|
|
32
|
+
.tox/
|
|
33
|
+
|
|
34
|
+
# IDE
|
|
35
|
+
.vscode/
|
|
36
|
+
.idea/
|
|
37
|
+
*.swp
|
|
38
|
+
*.swo
|
|
39
|
+
*~
|
|
40
|
+
|
|
41
|
+
# OS
|
|
42
|
+
.DS_Store
|
|
43
|
+
Thumbs.db
|
|
44
|
+
|
|
45
|
+
# Config (sensitive)
|
|
46
|
+
config.json
|
gravi_cli-0.1.1/LICENSE
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Gravitate
|
|
4
|
+
|
|
5
|
+
All rights reserved.
|
|
6
|
+
|
|
7
|
+
This software and associated documentation files (the "Software") are proprietary
|
|
8
|
+
and confidential to Gravitate.
|
|
9
|
+
|
|
10
|
+
The source code is made available for inspection and review purposes only.
|
|
11
|
+
|
|
12
|
+
RESTRICTIONS:
|
|
13
|
+
|
|
14
|
+
1. You may NOT use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
15
|
+
sell copies of the Software without explicit written permission from Gravitate.
|
|
16
|
+
|
|
17
|
+
2. You may NOT create derivative works based on the Software.
|
|
18
|
+
|
|
19
|
+
3. You may NOT reverse engineer, decompile, or disassemble the Software.
|
|
20
|
+
|
|
21
|
+
4. You may view the source code for informational purposes only.
|
|
22
|
+
|
|
23
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
24
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
25
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
26
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
27
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
28
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
29
|
+
SOFTWARE.
|
|
30
|
+
|
|
31
|
+
For licensing inquiries, please contact: Gravitate
|
gravi_cli-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gravi-cli
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: CLI tool for Gravitate infrastructure management
|
|
5
|
+
Project-URL: Homepage, https://github.com/gravitate/mom
|
|
6
|
+
Project-URL: Documentation, https://github.com/gravitate/mom/tree/main/cli
|
|
7
|
+
Project-URL: Repository, https://github.com/gravitate/mom
|
|
8
|
+
Author-email: Gravitate Engineering <engineering@gravitate.com>
|
|
9
|
+
License: Proprietary
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: cli,devops,gravitate,infrastructure
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: Other/Proprietary License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Requires-Dist: click>=8.1.0
|
|
22
|
+
Requires-Dist: pydantic>=2.0.0
|
|
23
|
+
Requires-Dist: requests>=2.31.0
|
|
24
|
+
Provides-Extra: test
|
|
25
|
+
Requires-Dist: pytest-cov>=4.1.0; extra == 'test'
|
|
26
|
+
Requires-Dist: pytest-mock>=3.11.0; extra == 'test'
|
|
27
|
+
Requires-Dist: pytest>=7.4.0; extra == 'test'
|
|
28
|
+
Requires-Dist: responses>=0.24.0; extra == 'test'
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
# Gravi CLI
|
|
32
|
+
|
|
33
|
+
Command-line tool for Gravitate infrastructure management. Provides CLI access to mom infrastructure, allowing developers to authenticate, manage tokens, and access instance configurations and credentials.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- **OAuth-style device authorization** - Secure browser-based authentication
|
|
38
|
+
- **Automatic token refresh** - Tokens auto-renew when <7 days remaining
|
|
39
|
+
- **Token management** - List, revoke, and manage CLI tokens
|
|
40
|
+
- **Instance access** - Get configurations and credentials for Gravitate instances
|
|
41
|
+
- **Python library API** - Use programmatically in scripts and applications
|
|
42
|
+
- **CI/CD support** - Environment variable-based authentication
|
|
43
|
+
|
|
44
|
+
## Installation
|
|
45
|
+
|
|
46
|
+
### From Source (Development)
|
|
47
|
+
|
|
48
|
+
Using `uv` (recommended):
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
cd /home/jvogel/src/work/tools/mom/cli
|
|
52
|
+
uv pip install -e ".[test]"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or with traditional pip:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
cd /home/jvogel/src/work/tools/mom/cli
|
|
59
|
+
pip install -e ".[test]"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### From PyPI (Future)
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
pip install gravi-cli
|
|
66
|
+
# or
|
|
67
|
+
uv pip install gravi-cli
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Quick Start
|
|
71
|
+
|
|
72
|
+
**Note:** If you installed with `uv pip install -e .`, you can run the CLI using `uvx --from . gravi` or just `gravi` if it's in your PATH.
|
|
73
|
+
|
|
74
|
+
### 1. Login
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
gravi login
|
|
78
|
+
# or with uvx:
|
|
79
|
+
uvx --from . gravi login
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
This will:
|
|
83
|
+
1. Open your browser to mom authorization page
|
|
84
|
+
2. Display a user code (e.g., `ABCD-1234`)
|
|
85
|
+
3. Wait for you to authorize in the browser
|
|
86
|
+
4. Save credentials to `~/.config/gravi/config.json`
|
|
87
|
+
|
|
88
|
+
### 2. Check Status
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
gravi status
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Shows:
|
|
95
|
+
- Current user email
|
|
96
|
+
- Mom URL
|
|
97
|
+
- Device name
|
|
98
|
+
- Token ID
|
|
99
|
+
- Token expiry
|
|
100
|
+
|
|
101
|
+
### 3. Get Instance Configuration
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Get config as JSON
|
|
105
|
+
gravi config dev
|
|
106
|
+
|
|
107
|
+
# Get config as environment variables
|
|
108
|
+
gravi config prod --format=env
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 4. Logout
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
gravi logout
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Revokes token on server and clears local credentials.
|
|
118
|
+
|
|
119
|
+
## CLI Commands
|
|
120
|
+
|
|
121
|
+
### Authentication
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
gravi login # Authenticate via browser
|
|
125
|
+
gravi logout # Clear credentials and revoke token
|
|
126
|
+
gravi status # Show login status and token expiry
|
|
127
|
+
gravi whoami # Show current user info
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Token Management
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
gravi tokens list # List all CLI tokens
|
|
134
|
+
gravi tokens revoke <token_id> # Revoke a specific token
|
|
135
|
+
gravi tokens revoke --all # Revoke all tokens
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### Instance Access
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
gravi config <instance_key> # Get instance configuration
|
|
142
|
+
gravi config <instance_key> --format=env # Get as environment variables
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Python Library API
|
|
146
|
+
|
|
147
|
+
Use gravi_cli programmatically in Python scripts:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from gravi_cli.api import get_instance_config, get_instance_token
|
|
151
|
+
|
|
152
|
+
# Get database credentials
|
|
153
|
+
config = get_instance_config("prod")
|
|
154
|
+
db_url = config["config"]["database_url"]
|
|
155
|
+
|
|
156
|
+
# Get ServiceNow access token
|
|
157
|
+
token_response = get_instance_token("dev")
|
|
158
|
+
sn_token = token_response["access_token"]
|
|
159
|
+
|
|
160
|
+
# Get mom access token directly
|
|
161
|
+
from gravi_cli.api import get_mom_token
|
|
162
|
+
mom_token = get_mom_token() # Auto-refreshes if needed
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### Example: Database Connection
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
from gravi_cli.api import get_instance_config
|
|
169
|
+
import psycopg2
|
|
170
|
+
|
|
171
|
+
# Get prod database credentials
|
|
172
|
+
config = get_instance_config("prod")
|
|
173
|
+
conn = psycopg2.connect(config["config"]["database_url"])
|
|
174
|
+
|
|
175
|
+
# Use database
|
|
176
|
+
cursor = conn.cursor()
|
|
177
|
+
cursor.execute("SELECT * FROM users LIMIT 10")
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Example: ServiceNow API
|
|
181
|
+
|
|
182
|
+
```python
|
|
183
|
+
from gravi_cli.api import get_instance_config, get_instance_token
|
|
184
|
+
import requests
|
|
185
|
+
|
|
186
|
+
# Get ServiceNow config and token
|
|
187
|
+
config = get_instance_config("dev")
|
|
188
|
+
token_response = get_instance_token("dev")
|
|
189
|
+
|
|
190
|
+
# Make ServiceNow API call
|
|
191
|
+
response = requests.get(
|
|
192
|
+
f"{config['api_url']}/api/now/table/incident",
|
|
193
|
+
headers={"Authorization": f"Bearer {token_response['access_token']}"}
|
|
194
|
+
)
|
|
195
|
+
incidents = response.json()
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## CI/CD Usage
|
|
199
|
+
|
|
200
|
+
For automated scripts and CI/CD pipelines:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
# Set refresh token as environment variable
|
|
204
|
+
export GRAVI_REFRESH_TOKEN="your_refresh_token_here"
|
|
205
|
+
|
|
206
|
+
# Commands will automatically use the env var
|
|
207
|
+
gravi config prod
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Getting a CI/CD token:**
|
|
211
|
+
1. Run `gravi login` on your local machine
|
|
212
|
+
2. Run `gravi tokens list` to see your token ID
|
|
213
|
+
3. Copy the refresh token from `~/.config/gravi/config.json`
|
|
214
|
+
4. Set as `GRAVI_REFRESH_TOKEN` in your CI/CD system
|
|
215
|
+
|
|
216
|
+
**Security Note:** Treat `GRAVI_REFRESH_TOKEN` like a password. Use secret management systems (GitHub Secrets, AWS Secrets Manager, etc.) to store it securely.
|
|
217
|
+
|
|
218
|
+
## Configuration
|
|
219
|
+
|
|
220
|
+
### Config File Location
|
|
221
|
+
|
|
222
|
+
`~/.config/gravi/config.json`
|
|
223
|
+
|
|
224
|
+
### Config File Format
|
|
225
|
+
|
|
226
|
+
```json
|
|
227
|
+
{
|
|
228
|
+
"version": 1,
|
|
229
|
+
"user_email": "john.doe@gravitate.com",
|
|
230
|
+
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
|
231
|
+
"refresh_token_expires_at": "2025-11-09T10:30:00Z",
|
|
232
|
+
"token_id": "507f1f77bcf86cd799439011",
|
|
233
|
+
"device_name": "John's MacBook"
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### Environment Variables
|
|
238
|
+
|
|
239
|
+
- `GRAVI_MOM_URL` - Override mom API URL (default: `https://mom.gravitate.energy`)
|
|
240
|
+
- `GRAVI_REFRESH_TOKEN` - CI/CD refresh token (bypasses config file)
|
|
241
|
+
|
|
242
|
+
### File Permissions
|
|
243
|
+
|
|
244
|
+
Config file is automatically set to `0600` (owner read/write only) for security.
|
|
245
|
+
|
|
246
|
+
## Token Auto-Renewal
|
|
247
|
+
|
|
248
|
+
Refresh tokens are automatically renewed when <7 days remaining:
|
|
249
|
+
- CLI checks expiry on each use
|
|
250
|
+
- If <7 days: requests new 14-day token
|
|
251
|
+
- Config file updated automatically
|
|
252
|
+
- Seamless for users - no re-login needed
|
|
253
|
+
|
|
254
|
+
## Development
|
|
255
|
+
|
|
256
|
+
### Setup
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
cd /home/jvogel/src/work/tools/mom/cli
|
|
260
|
+
pip install -e ".[test]"
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Run Tests
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
# All tests
|
|
267
|
+
pytest
|
|
268
|
+
|
|
269
|
+
# With coverage
|
|
270
|
+
pytest --cov=gravi_cli --cov-report=term-missing
|
|
271
|
+
|
|
272
|
+
# Specific test file
|
|
273
|
+
pytest tests/test_config.py
|
|
274
|
+
|
|
275
|
+
# Verbose
|
|
276
|
+
pytest -v
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### Project Structure
|
|
280
|
+
|
|
281
|
+
```
|
|
282
|
+
cli/
|
|
283
|
+
├── gravi_cli/
|
|
284
|
+
│ ├── __init__.py # Package metadata
|
|
285
|
+
│ ├── api.py # Public Python API
|
|
286
|
+
│ ├── auth.py # Token refresh and auth logic
|
|
287
|
+
│ ├── cli.py # CLI commands (Click)
|
|
288
|
+
│ ├── client.py # Mom API client
|
|
289
|
+
│ ├── config.py # Config file management
|
|
290
|
+
│ └── exceptions.py # Custom exceptions
|
|
291
|
+
├── tests/
|
|
292
|
+
│ ├── conftest.py # Pytest fixtures
|
|
293
|
+
│ ├── test_config.py # Config tests
|
|
294
|
+
│ └── test_client.py # API client tests
|
|
295
|
+
├── pyproject.toml # Package configuration
|
|
296
|
+
└── README.md # This file
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Troubleshooting
|
|
300
|
+
|
|
301
|
+
### "Not logged in" Error
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
gravi login
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
### "Token expired" Error
|
|
308
|
+
|
|
309
|
+
Tokens auto-renew, but if expired:
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
gravi login
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
### Rate Limiting
|
|
316
|
+
|
|
317
|
+
If you hit rate limits, wait and retry. Rate limits reset every minute.
|
|
318
|
+
|
|
319
|
+
### Mom URL Override (Development)
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
# Temporary override
|
|
323
|
+
GRAVI_MOM_URL=https://mom.dev gravi login
|
|
324
|
+
|
|
325
|
+
# Or with flag
|
|
326
|
+
gravi login --mom-url=https://mom.dev
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Security
|
|
330
|
+
|
|
331
|
+
- **Refresh tokens** stored in config file with `0600` permissions
|
|
332
|
+
- **Access tokens** never persisted (in-memory only)
|
|
333
|
+
- **No tokens in CLI arguments** (prevents shell history exposure)
|
|
334
|
+
- **HTTPS only** for all API calls
|
|
335
|
+
- **Audit logging** - All token operations logged in mom
|
|
336
|
+
|
|
337
|
+
## Support
|
|
338
|
+
|
|
339
|
+
For issues or questions:
|
|
340
|
+
- GitHub Issues: https://github.com/gravitate/mom/issues
|
|
341
|
+
- Internal Slack: #engineering
|
|
342
|
+
|
|
343
|
+
## License
|
|
344
|
+
|
|
345
|
+
MIT
|