appliku 0.1.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.
- appliku-0.1.0/.gitignore +36 -0
- appliku-0.1.0/CLAUDE.md +117 -0
- appliku-0.1.0/LICENSE +21 -0
- appliku-0.1.0/PKG-INFO +277 -0
- appliku-0.1.0/README.md +241 -0
- appliku-0.1.0/pyproject.toml +64 -0
- appliku-0.1.0/spec.md +11 -0
- appliku-0.1.0/src/appliku/__init__.py +108 -0
- appliku-0.1.0/src/appliku/_auth.py +167 -0
- appliku-0.1.0/src/appliku/_client.py +142 -0
- appliku-0.1.0/src/appliku/_exceptions.py +84 -0
- appliku-0.1.0/src/appliku/_main.py +122 -0
- appliku-0.1.0/src/appliku/_models.py +356 -0
- appliku-0.1.0/src/appliku/cli/__init__.py +93 -0
- appliku-0.1.0/src/appliku/cli/apps.py +217 -0
- appliku-0.1.0/src/appliku/cli/auth.py +126 -0
- appliku-0.1.0/src/appliku/cli/clusters.py +89 -0
- appliku-0.1.0/src/appliku/cli/cron_jobs.py +90 -0
- appliku-0.1.0/src/appliku/cli/datastores.py +117 -0
- appliku-0.1.0/src/appliku/cli/deployments.py +83 -0
- appliku-0.1.0/src/appliku/cli/domains.py +53 -0
- appliku-0.1.0/src/appliku/cli/invites.py +85 -0
- appliku-0.1.0/src/appliku/cli/migrations.py +52 -0
- appliku-0.1.0/src/appliku/cli/servers.py +182 -0
- appliku-0.1.0/src/appliku/cli/teams.py +78 -0
- appliku-0.1.0/src/appliku/cli/volumes.py +82 -0
- appliku-0.1.0/src/appliku/resources/__init__.py +0 -0
- appliku-0.1.0/src/appliku/resources/apps.py +166 -0
- appliku-0.1.0/src/appliku/resources/clusters.py +56 -0
- appliku-0.1.0/src/appliku/resources/cron_jobs.py +51 -0
- appliku-0.1.0/src/appliku/resources/datastores.py +62 -0
- appliku-0.1.0/src/appliku/resources/deployments.py +84 -0
- appliku-0.1.0/src/appliku/resources/domains.py +42 -0
- appliku-0.1.0/src/appliku/resources/invites.py +46 -0
- appliku-0.1.0/src/appliku/resources/migrations.py +45 -0
- appliku-0.1.0/src/appliku/resources/servers.py +59 -0
- appliku-0.1.0/src/appliku/resources/teams.py +41 -0
- appliku-0.1.0/src/appliku/resources/volumes.py +53 -0
- appliku-0.1.0/tests/conftest.py +45 -0
- appliku-0.1.0/tests/test_apps.py +197 -0
- appliku-0.1.0/tests/test_auth.py +76 -0
- appliku-0.1.0/tests/test_client.py +169 -0
- appliku-0.1.0/tests/test_clusters.py +74 -0
- appliku-0.1.0/tests/test_cron_jobs.py +67 -0
- appliku-0.1.0/tests/test_datastores.py +99 -0
- appliku-0.1.0/tests/test_deployments.py +106 -0
- appliku-0.1.0/tests/test_domains.py +45 -0
- appliku-0.1.0/tests/test_invites.py +64 -0
- appliku-0.1.0/tests/test_migrations.py +70 -0
- appliku-0.1.0/tests/test_servers.py +76 -0
- appliku-0.1.0/tests/test_teams.py +71 -0
- appliku-0.1.0/tests/test_volumes.py +59 -0
- appliku-0.1.0/uv.lock +657 -0
appliku-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Byte-compiled / optimized
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
dist/
|
|
8
|
+
build/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
|
|
11
|
+
# Virtual environments
|
|
12
|
+
.venv/
|
|
13
|
+
venv/
|
|
14
|
+
|
|
15
|
+
# Environment variables
|
|
16
|
+
.env
|
|
17
|
+
.env.*
|
|
18
|
+
|
|
19
|
+
# IDE
|
|
20
|
+
.idea/
|
|
21
|
+
.vscode/
|
|
22
|
+
*.swp
|
|
23
|
+
*.swo
|
|
24
|
+
|
|
25
|
+
# OS
|
|
26
|
+
.DS_Store
|
|
27
|
+
Thumbs.db
|
|
28
|
+
|
|
29
|
+
# Test artifacts
|
|
30
|
+
.pytest_cache/
|
|
31
|
+
htmlcov/
|
|
32
|
+
.coverage
|
|
33
|
+
coverage.xml
|
|
34
|
+
|
|
35
|
+
# Type checking
|
|
36
|
+
.mypy_cache/
|
appliku-0.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
`appliku-cli` is a Python CLI and SDK for the [Appliku](https://api.appliku.com) platform. It wraps the Appliku OpenAPI spec (`https://api.appliku.com/api/schema/`) and is published to PyPI. The project uses **UV** for all Python environment and dependency management.
|
|
8
|
+
|
|
9
|
+
## Environment & Tooling
|
|
10
|
+
|
|
11
|
+
- **Python package manager**: UV exclusively. Never use `pip install` directly. Use `uv add` for dependencies, `uv run` to execute commands within the project environment.
|
|
12
|
+
- **Project config**: `pyproject.toml` is the single source of truth for metadata, dependencies, scripts, and tool configuration.
|
|
13
|
+
- **Build backend**: `hatchling` as specified in `pyproject.toml`.
|
|
14
|
+
|
|
15
|
+
## Common Commands
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Create/sync the environment
|
|
19
|
+
uv sync
|
|
20
|
+
|
|
21
|
+
# Run the CLI
|
|
22
|
+
uv run appliku --help
|
|
23
|
+
|
|
24
|
+
# Run tests
|
|
25
|
+
uv run pytest
|
|
26
|
+
|
|
27
|
+
# Run a single test file or test by keyword
|
|
28
|
+
uv run pytest tests/test_apps.py
|
|
29
|
+
uv run pytest -k "test_create_app"
|
|
30
|
+
|
|
31
|
+
# Lint and format (assuming ruff is configured)
|
|
32
|
+
uv run ruff check .
|
|
33
|
+
uv run ruff format .
|
|
34
|
+
|
|
35
|
+
# Type check (if mypy is configured)
|
|
36
|
+
uv run mypy src/
|
|
37
|
+
|
|
38
|
+
# Build the package for PyPI
|
|
39
|
+
uv build
|
|
40
|
+
|
|
41
|
+
# Publish to PyPI (dry run first)
|
|
42
|
+
uv publish --dry-run
|
|
43
|
+
uv publish
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Architecture & Code Organization
|
|
47
|
+
|
|
48
|
+
The project follows a **src layout**:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
src/appliku/
|
|
52
|
+
├── __init__.py # Public SDK exports (Appliku class + all models + exceptions)
|
|
53
|
+
├── _main.py # Appliku class — SDK entry point with lazy resource properties
|
|
54
|
+
├── _client.py # AplikuClient — HTTP client with retry, pagination, error handling
|
|
55
|
+
├── _auth.py # Token resolution (env/config/param) + login flow + config persistence
|
|
56
|
+
├── _exceptions.py # Exception hierarchy: AplikuError → typed subclasses
|
|
57
|
+
├── _models.py # All Pydantic v2 models (PaginatedResponse, Team, App, Deployment, etc.)
|
|
58
|
+
├── resources/ # Resource classes — one per API domain
|
|
59
|
+
│ ├── teams.py # TeamsResource: list, get, create, update, delete
|
|
60
|
+
│ ├── apps.py # AppsResource: list, get, create, update, delete, deploy, config vars
|
|
61
|
+
│ ├── deployments.py # DeploymentsResource: list, get, latest, logs, stream_logs
|
|
62
|
+
│ ├── datastores.py # DatastoresResource: list, get, create, delete, start, stop, restart
|
|
63
|
+
│ ├── domains.py # DomainsResource: list, get, create, delete
|
|
64
|
+
│ ├── volumes.py # VolumesResource: list, get, create, update, delete
|
|
65
|
+
│ ├── cron_jobs.py # CronJobsResource: list, get, create, update, delete
|
|
66
|
+
│ ├── clusters.py # ClustersResource: list, get, create, delete
|
|
67
|
+
│ ├── servers.py # ServersResource: list, get, create_digitalocean, create_ec2, create_custom
|
|
68
|
+
│ ├── invites.py # InvitesResource: list, create, delete, accept, decline
|
|
69
|
+
│ └── migrations.py # MigrationsResource: list, get, run, logs
|
|
70
|
+
└── cli/ # Typer CLI layer
|
|
71
|
+
├── __init__.py # Root Typer app + shared helpers (get_client, render_output, render_table)
|
|
72
|
+
├── auth.py # Root commands: login, logout, whoami
|
|
73
|
+
├── teams.py # teams sub-app
|
|
74
|
+
├── apps.py # apps sub-app (list, get, create, update, delete, deploy, config, set-config)
|
|
75
|
+
├── deployments.py # deployments sub-app (list, latest, logs --stream)
|
|
76
|
+
├── datastores.py # datastores sub-app (list, create, delete, start, stop, restart)
|
|
77
|
+
├── domains.py # domains sub-app (list, create, delete)
|
|
78
|
+
├── volumes.py # volumes sub-app (list, create, update, delete)
|
|
79
|
+
├── cron_jobs.py # crons sub-app (list, create, update, delete)
|
|
80
|
+
├── clusters.py # clusters sub-app (list, create, delete)
|
|
81
|
+
├── servers.py # servers sub-app (list, create-do, create-ec2, create-custom)
|
|
82
|
+
├── invites.py # invites sub-app (list, create, delete, accept, decline)
|
|
83
|
+
└── migrations.py # migrations sub-app (list, run, logs)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Key Architectural Decisions
|
|
87
|
+
|
|
88
|
+
1. **API surface is driven by the OpenAPI spec at `https://api.appliku.com/api/schema/`**. The resource model maps to:
|
|
89
|
+
- **Auth**: Token + JWT authentication, API key management
|
|
90
|
+
- **Teams**: Team CRUD, member invitations, cloud credential storage (AWS, DigitalOcean)
|
|
91
|
+
- **Apps**: Application lifecycle — deploy, scale processes, manage domains/SSL, config vars
|
|
92
|
+
- **Infrastructure**: Clusters, build servers, EC2/DigitalOcean instance provisioning
|
|
93
|
+
- **Data Services**: Datastores (databases), backups, volumes, replica promotion
|
|
94
|
+
- **Monitoring**: Logs (app, nginx, deployment, DB migration), stats/metrics
|
|
95
|
+
- **Integrations**: GitHub/GitLab repos, cron jobs, webhooks, one-off commands
|
|
96
|
+
|
|
97
|
+
2. **CLI commands mirror SDK client methods.** Each top-level resource maps to a Typer sub-app. The SDK client is usable independently of the CLI.
|
|
98
|
+
|
|
99
|
+
3. **Authentication flow**: Token resolution priority: explicit param → `APPLIKU_TOKEN` env → `~/.config/appliku/config.toml`. Login does a two-step flow: POST `/api/sign_up/` for JWT, then POST `/api/obtain_user_api_key/` for persistent API key.
|
|
100
|
+
|
|
101
|
+
4. **Output formatting**: CLI commands default to Rich tables. All list commands support `--output json` for scripting.
|
|
102
|
+
|
|
103
|
+
5. **Error handling**: Typed exception hierarchy with auto-retry on 429 (respect Retry-After) and 5xx (exponential backoff, up to 3 attempts).
|
|
104
|
+
|
|
105
|
+
6. **Pagination**: `AplikuClient.paginate()` for single page, `paginate_all()` for auto-following next links.
|
|
106
|
+
|
|
107
|
+
## OpenAPI Schema
|
|
108
|
+
|
|
109
|
+
The canonical schema is at `https://api.appliku.com/api/schema/`. When adding new endpoints or updating models, fetch the latest schema to verify field names and types.
|
|
110
|
+
|
|
111
|
+
## Testing
|
|
112
|
+
|
|
113
|
+
- Tests live in `tests/` and use **pytest**.
|
|
114
|
+
- `conftest.py` provides `mock_client` fixture using `httpx.MockTransport` — no network calls.
|
|
115
|
+
- Push `httpx.Response` objects onto the responses list to define mock behavior.
|
|
116
|
+
- `paginated_response` fixture factory wraps results in standard pagination envelope.
|
|
117
|
+
- Integration/e2e tests (if any) should be gated behind `@pytest.mark.integration`.
|
appliku-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Appliku
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
appliku-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: appliku
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python CLI and SDK for Appliku
|
|
5
|
+
Project-URL: Homepage, https://github.com/appliku/appliku-cli
|
|
6
|
+
Project-URL: Documentation, https://github.com/appliku/appliku-cli#readme
|
|
7
|
+
Project-URL: Issues, https://github.com/appliku/appliku-cli/issues
|
|
8
|
+
Author-email: Appliku <dev@appliku.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: appliku,cli,deployment,paas,sdk
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Topic :: Internet
|
|
22
|
+
Requires-Python: >=3.10
|
|
23
|
+
Requires-Dist: httpx>=0.27.0
|
|
24
|
+
Requires-Dist: pydantic>=2.6.0
|
|
25
|
+
Requires-Dist: rich>=13.7.0
|
|
26
|
+
Requires-Dist: tomli-w>=1.0.0
|
|
27
|
+
Requires-Dist: tomli>=2.0.0; python_version < '3.11'
|
|
28
|
+
Requires-Dist: typer>=0.12.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: httpx>=0.27.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: mypy>=1.8.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-httpx>=0.30.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=8.0.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.3.0; extra == 'dev'
|
|
35
|
+
Description-Content-Type: text/markdown
|
|
36
|
+
|
|
37
|
+
# appliku
|
|
38
|
+
|
|
39
|
+
[](https://pypi.org/project/appliku/)
|
|
40
|
+
[](https://opensource.org/licenses/MIT)
|
|
41
|
+
[](https://www.python.org/downloads/)
|
|
42
|
+
|
|
43
|
+
Python CLI and SDK for the [Appliku](https://appliku.com) cloud deployment platform.
|
|
44
|
+
|
|
45
|
+
Appliku is a PaaS that lets you deploy applications, manage infrastructure, and scale services — all from a single unified interface. This package provides both a programmatic Python SDK and a fully-featured command-line interface.
|
|
46
|
+
|
|
47
|
+
## Installation
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
pip install appliku
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
UV users:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uv add appliku
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Quick Start (SDK)
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from appliku import Appliku
|
|
63
|
+
|
|
64
|
+
client = Appliku(token="your-api-token")
|
|
65
|
+
|
|
66
|
+
# List apps in a team
|
|
67
|
+
apps = client.apps.list("my-team")
|
|
68
|
+
for app in apps.results:
|
|
69
|
+
print(f"{app.name} — {app.status}")
|
|
70
|
+
|
|
71
|
+
# Trigger a deployment
|
|
72
|
+
deployment = client.apps.deploy("my-team", app_id=42)
|
|
73
|
+
print(f"Deployment {deployment.id} is {deployment.status}")
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Authentication
|
|
77
|
+
|
|
78
|
+
There are three ways to authenticate:
|
|
79
|
+
|
|
80
|
+
1. **Constructor parameter**: `Appliku(token="tok_...")`
|
|
81
|
+
2. **Environment variable**: `export APPLIKU_TOKEN=tok_...`
|
|
82
|
+
3. **CLI login** (saves token to `~/.config/appliku/config.toml`):
|
|
83
|
+
```bash
|
|
84
|
+
appliku login --email you@example.com --password secret
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The SDK checks these sources in order: explicit token → `APPLIKU_TOKEN` env var → config file.
|
|
88
|
+
|
|
89
|
+
## SDK Usage
|
|
90
|
+
|
|
91
|
+
### Teams
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# List teams
|
|
95
|
+
teams = client.teams.list()
|
|
96
|
+
|
|
97
|
+
# Create a team
|
|
98
|
+
team = client.teams.create("my-team-slug", "My Team")
|
|
99
|
+
|
|
100
|
+
# Update and delete
|
|
101
|
+
client.teams.update("my-team-slug", name="Renamed Team")
|
|
102
|
+
client.teams.delete("my-team-slug")
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Apps
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
# List apps
|
|
109
|
+
apps = client.apps.list("my-team")
|
|
110
|
+
|
|
111
|
+
# Create an app
|
|
112
|
+
app = client.apps.create(
|
|
113
|
+
"my-team",
|
|
114
|
+
name="web-app",
|
|
115
|
+
branch="main",
|
|
116
|
+
git_url="https://github.com/user/repo.git",
|
|
117
|
+
build_pack="dockerfile",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# Deploy
|
|
121
|
+
deployment = client.apps.deploy("my-team", app.id)
|
|
122
|
+
|
|
123
|
+
# Config vars
|
|
124
|
+
vars = client.apps.get_config_vars("my-team", app.id)
|
|
125
|
+
client.apps.set_config_vars("my-team", app.id, {"DATABASE_URL": "postgres://...", "DEBUG": "false"})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### Deployments
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
# List deployments
|
|
132
|
+
deployments = client.deployments.list("my-team", app_id=42)
|
|
133
|
+
|
|
134
|
+
# Get latest
|
|
135
|
+
latest = client.deployments.latest("my-team", app_id=42)
|
|
136
|
+
|
|
137
|
+
# Stream logs in real-time
|
|
138
|
+
for log in client.deployments.stream_logs("my-team", app_id=42, deployment_id=latest.id):
|
|
139
|
+
print(f"[{log.timestamp}] {log.message}")
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Datastores
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
# Create a database
|
|
146
|
+
db = client.datastores.create("my-team", app_id=42, name="primary-db", engine="postgres", version="15")
|
|
147
|
+
|
|
148
|
+
# Lifecycle management
|
|
149
|
+
client.datastores.stop("my-team", 42, db.id)
|
|
150
|
+
client.datastores.start("my-team", 42, db.id)
|
|
151
|
+
client.datastores.restart("my-team", 42, db.id)
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Domains & Volumes
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
# Domains
|
|
158
|
+
domain = client.domains.create("my-team", app_id=42, domain="app.example.com")
|
|
159
|
+
client.domains.delete("my-team", 42, domain.id)
|
|
160
|
+
|
|
161
|
+
# Volumes
|
|
162
|
+
vol = client.volumes.create("my-team", app_id=42, name="data", container_path="/data")
|
|
163
|
+
client.volumes.update("my-team", 42, vol.id, name="user-data")
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Cron Jobs
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
cron = client.cron_jobs.create(
|
|
170
|
+
"my-team", app_id=42,
|
|
171
|
+
name="cleanup", schedule="0 2 * * *", command="python manage.py cleanup"
|
|
172
|
+
)
|
|
173
|
+
client.cron_jobs.update("my-team", 42, cron.id, is_disabled=True)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Clusters & Servers
|
|
177
|
+
|
|
178
|
+
```python
|
|
179
|
+
# Create a cluster
|
|
180
|
+
cluster = client.clusters.create("my-team", name="production")
|
|
181
|
+
|
|
182
|
+
# Provision servers
|
|
183
|
+
do_server = client.servers.create_digitalocean("my-team", name="web-1", region="nyc1", size="s-2vcpu-2gb")
|
|
184
|
+
ec2_server = client.servers.create_ec2("my-team", name="worker-1", region="us-east-1", instance_type="t3.large")
|
|
185
|
+
custom_server = client.servers.create_custom("my-team", name="bare-metal", host="203.0.113.1")
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
## CLI Usage
|
|
189
|
+
|
|
190
|
+
### Authentication
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
appliku login --email you@example.com --password secret
|
|
194
|
+
appliku whoami
|
|
195
|
+
appliku logout
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Apps
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
appliku apps list --team my-team
|
|
202
|
+
appliku apps create --team my-team --name web-app --branch main --git-url https://github.com/user/repo.git
|
|
203
|
+
appliku apps deploy --team my-team --app 42
|
|
204
|
+
appliku apps config --team my-team --app 42
|
|
205
|
+
appliku apps set-config --team my-team --app 42 --var FOO=bar --var BAZ=qux
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Deployments
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
appliku deployments list --team my-team --app 42
|
|
212
|
+
appliku deployments latest --team my-team --app 42
|
|
213
|
+
appliku deployments logs --team my-team --app 42 --deployment 7 --stream
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Datastores
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
appliku datastores create --team my-team --app 42 --name primary-db --engine postgres --version 15
|
|
220
|
+
appliku datastores start --team my-team --app 42 1
|
|
221
|
+
appliku datastores stop --team my-team --app 42 1
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### All commands support `--output json` for scripting:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
appliku apps list --team my-team --output json
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
## CLI Reference
|
|
231
|
+
|
|
232
|
+
| Command Group | Subcommands |
|
|
233
|
+
|-----------------|--------------------------------------------------|
|
|
234
|
+
| *(root)* | `login`, `logout`, `whoami` |
|
|
235
|
+
| `teams` | `list`, `get`, `create`, `update`, `delete` |
|
|
236
|
+
| `apps` | `list`, `get`, `create`, `update`, `delete`, `deploy`, `config`, `set-config` |
|
|
237
|
+
| `deployments` | `list`, `latest`, `logs` |
|
|
238
|
+
| `datastores` | `list`, `create`, `delete`, `start`, `stop`, `restart` |
|
|
239
|
+
| `domains` | `list`, `create`, `delete` |
|
|
240
|
+
| `volumes` | `list`, `create`, `update`, `delete` |
|
|
241
|
+
| `crons` | `list`, `create`, `update`, `delete` |
|
|
242
|
+
| `clusters` | `list`, `create`, `delete` |
|
|
243
|
+
| `servers` | `list`, `create-do`, `create-ec2`, `create-custom` |
|
|
244
|
+
| `invites` | `list`, `create`, `delete`, `accept`, `decline` |
|
|
245
|
+
| `migrations` | `list`, `run`, `logs` |
|
|
246
|
+
|
|
247
|
+
## Error Handling
|
|
248
|
+
|
|
249
|
+
The SDK raises typed exceptions so you can handle specific failure modes:
|
|
250
|
+
|
|
251
|
+
```python
|
|
252
|
+
from appliku import Appliku, NotFoundError, AuthenticationError, RateLimitError
|
|
253
|
+
|
|
254
|
+
client = Appliku()
|
|
255
|
+
|
|
256
|
+
try:
|
|
257
|
+
app = client.apps.get("my-team", app_id=999)
|
|
258
|
+
except NotFoundError as e:
|
|
259
|
+
print(f"App not found: {e}")
|
|
260
|
+
except AuthenticationError:
|
|
261
|
+
print("Invalid or expired token")
|
|
262
|
+
except RateLimitError:
|
|
263
|
+
print("Too many requests — retried automatically")
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Exception hierarchy:
|
|
267
|
+
- `AplikuError` (base)
|
|
268
|
+
- `AuthenticationError` — 401
|
|
269
|
+
- `AuthorizationError` — 403
|
|
270
|
+
- `NotFoundError` — 404
|
|
271
|
+
- `ValidationError` — 400 (field-level errors)
|
|
272
|
+
- `RateLimitError` — 429 (auto-retried)
|
|
273
|
+
- `ServerError` — 5xx (auto-retried with backoff)
|
|
274
|
+
|
|
275
|
+
## License
|
|
276
|
+
|
|
277
|
+
MIT
|
appliku-0.1.0/README.md
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
# appliku
|
|
2
|
+
|
|
3
|
+
[](https://pypi.org/project/appliku/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.python.org/downloads/)
|
|
6
|
+
|
|
7
|
+
Python CLI and SDK for the [Appliku](https://appliku.com) cloud deployment platform.
|
|
8
|
+
|
|
9
|
+
Appliku is a PaaS that lets you deploy applications, manage infrastructure, and scale services — all from a single unified interface. This package provides both a programmatic Python SDK and a fully-featured command-line interface.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install appliku
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
UV users:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv add appliku
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start (SDK)
|
|
24
|
+
|
|
25
|
+
```python
|
|
26
|
+
from appliku import Appliku
|
|
27
|
+
|
|
28
|
+
client = Appliku(token="your-api-token")
|
|
29
|
+
|
|
30
|
+
# List apps in a team
|
|
31
|
+
apps = client.apps.list("my-team")
|
|
32
|
+
for app in apps.results:
|
|
33
|
+
print(f"{app.name} — {app.status}")
|
|
34
|
+
|
|
35
|
+
# Trigger a deployment
|
|
36
|
+
deployment = client.apps.deploy("my-team", app_id=42)
|
|
37
|
+
print(f"Deployment {deployment.id} is {deployment.status}")
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Authentication
|
|
41
|
+
|
|
42
|
+
There are three ways to authenticate:
|
|
43
|
+
|
|
44
|
+
1. **Constructor parameter**: `Appliku(token="tok_...")`
|
|
45
|
+
2. **Environment variable**: `export APPLIKU_TOKEN=tok_...`
|
|
46
|
+
3. **CLI login** (saves token to `~/.config/appliku/config.toml`):
|
|
47
|
+
```bash
|
|
48
|
+
appliku login --email you@example.com --password secret
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The SDK checks these sources in order: explicit token → `APPLIKU_TOKEN` env var → config file.
|
|
52
|
+
|
|
53
|
+
## SDK Usage
|
|
54
|
+
|
|
55
|
+
### Teams
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
# List teams
|
|
59
|
+
teams = client.teams.list()
|
|
60
|
+
|
|
61
|
+
# Create a team
|
|
62
|
+
team = client.teams.create("my-team-slug", "My Team")
|
|
63
|
+
|
|
64
|
+
# Update and delete
|
|
65
|
+
client.teams.update("my-team-slug", name="Renamed Team")
|
|
66
|
+
client.teams.delete("my-team-slug")
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Apps
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
# List apps
|
|
73
|
+
apps = client.apps.list("my-team")
|
|
74
|
+
|
|
75
|
+
# Create an app
|
|
76
|
+
app = client.apps.create(
|
|
77
|
+
"my-team",
|
|
78
|
+
name="web-app",
|
|
79
|
+
branch="main",
|
|
80
|
+
git_url="https://github.com/user/repo.git",
|
|
81
|
+
build_pack="dockerfile",
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
# Deploy
|
|
85
|
+
deployment = client.apps.deploy("my-team", app.id)
|
|
86
|
+
|
|
87
|
+
# Config vars
|
|
88
|
+
vars = client.apps.get_config_vars("my-team", app.id)
|
|
89
|
+
client.apps.set_config_vars("my-team", app.id, {"DATABASE_URL": "postgres://...", "DEBUG": "false"})
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Deployments
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
# List deployments
|
|
96
|
+
deployments = client.deployments.list("my-team", app_id=42)
|
|
97
|
+
|
|
98
|
+
# Get latest
|
|
99
|
+
latest = client.deployments.latest("my-team", app_id=42)
|
|
100
|
+
|
|
101
|
+
# Stream logs in real-time
|
|
102
|
+
for log in client.deployments.stream_logs("my-team", app_id=42, deployment_id=latest.id):
|
|
103
|
+
print(f"[{log.timestamp}] {log.message}")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Datastores
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
# Create a database
|
|
110
|
+
db = client.datastores.create("my-team", app_id=42, name="primary-db", engine="postgres", version="15")
|
|
111
|
+
|
|
112
|
+
# Lifecycle management
|
|
113
|
+
client.datastores.stop("my-team", 42, db.id)
|
|
114
|
+
client.datastores.start("my-team", 42, db.id)
|
|
115
|
+
client.datastores.restart("my-team", 42, db.id)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Domains & Volumes
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
# Domains
|
|
122
|
+
domain = client.domains.create("my-team", app_id=42, domain="app.example.com")
|
|
123
|
+
client.domains.delete("my-team", 42, domain.id)
|
|
124
|
+
|
|
125
|
+
# Volumes
|
|
126
|
+
vol = client.volumes.create("my-team", app_id=42, name="data", container_path="/data")
|
|
127
|
+
client.volumes.update("my-team", 42, vol.id, name="user-data")
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Cron Jobs
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
cron = client.cron_jobs.create(
|
|
134
|
+
"my-team", app_id=42,
|
|
135
|
+
name="cleanup", schedule="0 2 * * *", command="python manage.py cleanup"
|
|
136
|
+
)
|
|
137
|
+
client.cron_jobs.update("my-team", 42, cron.id, is_disabled=True)
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### Clusters & Servers
|
|
141
|
+
|
|
142
|
+
```python
|
|
143
|
+
# Create a cluster
|
|
144
|
+
cluster = client.clusters.create("my-team", name="production")
|
|
145
|
+
|
|
146
|
+
# Provision servers
|
|
147
|
+
do_server = client.servers.create_digitalocean("my-team", name="web-1", region="nyc1", size="s-2vcpu-2gb")
|
|
148
|
+
ec2_server = client.servers.create_ec2("my-team", name="worker-1", region="us-east-1", instance_type="t3.large")
|
|
149
|
+
custom_server = client.servers.create_custom("my-team", name="bare-metal", host="203.0.113.1")
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## CLI Usage
|
|
153
|
+
|
|
154
|
+
### Authentication
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
appliku login --email you@example.com --password secret
|
|
158
|
+
appliku whoami
|
|
159
|
+
appliku logout
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Apps
|
|
163
|
+
|
|
164
|
+
```bash
|
|
165
|
+
appliku apps list --team my-team
|
|
166
|
+
appliku apps create --team my-team --name web-app --branch main --git-url https://github.com/user/repo.git
|
|
167
|
+
appliku apps deploy --team my-team --app 42
|
|
168
|
+
appliku apps config --team my-team --app 42
|
|
169
|
+
appliku apps set-config --team my-team --app 42 --var FOO=bar --var BAZ=qux
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Deployments
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
appliku deployments list --team my-team --app 42
|
|
176
|
+
appliku deployments latest --team my-team --app 42
|
|
177
|
+
appliku deployments logs --team my-team --app 42 --deployment 7 --stream
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Datastores
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
appliku datastores create --team my-team --app 42 --name primary-db --engine postgres --version 15
|
|
184
|
+
appliku datastores start --team my-team --app 42 1
|
|
185
|
+
appliku datastores stop --team my-team --app 42 1
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### All commands support `--output json` for scripting:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
appliku apps list --team my-team --output json
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## CLI Reference
|
|
195
|
+
|
|
196
|
+
| Command Group | Subcommands |
|
|
197
|
+
|-----------------|--------------------------------------------------|
|
|
198
|
+
| *(root)* | `login`, `logout`, `whoami` |
|
|
199
|
+
| `teams` | `list`, `get`, `create`, `update`, `delete` |
|
|
200
|
+
| `apps` | `list`, `get`, `create`, `update`, `delete`, `deploy`, `config`, `set-config` |
|
|
201
|
+
| `deployments` | `list`, `latest`, `logs` |
|
|
202
|
+
| `datastores` | `list`, `create`, `delete`, `start`, `stop`, `restart` |
|
|
203
|
+
| `domains` | `list`, `create`, `delete` |
|
|
204
|
+
| `volumes` | `list`, `create`, `update`, `delete` |
|
|
205
|
+
| `crons` | `list`, `create`, `update`, `delete` |
|
|
206
|
+
| `clusters` | `list`, `create`, `delete` |
|
|
207
|
+
| `servers` | `list`, `create-do`, `create-ec2`, `create-custom` |
|
|
208
|
+
| `invites` | `list`, `create`, `delete`, `accept`, `decline` |
|
|
209
|
+
| `migrations` | `list`, `run`, `logs` |
|
|
210
|
+
|
|
211
|
+
## Error Handling
|
|
212
|
+
|
|
213
|
+
The SDK raises typed exceptions so you can handle specific failure modes:
|
|
214
|
+
|
|
215
|
+
```python
|
|
216
|
+
from appliku import Appliku, NotFoundError, AuthenticationError, RateLimitError
|
|
217
|
+
|
|
218
|
+
client = Appliku()
|
|
219
|
+
|
|
220
|
+
try:
|
|
221
|
+
app = client.apps.get("my-team", app_id=999)
|
|
222
|
+
except NotFoundError as e:
|
|
223
|
+
print(f"App not found: {e}")
|
|
224
|
+
except AuthenticationError:
|
|
225
|
+
print("Invalid or expired token")
|
|
226
|
+
except RateLimitError:
|
|
227
|
+
print("Too many requests — retried automatically")
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Exception hierarchy:
|
|
231
|
+
- `AplikuError` (base)
|
|
232
|
+
- `AuthenticationError` — 401
|
|
233
|
+
- `AuthorizationError` — 403
|
|
234
|
+
- `NotFoundError` — 404
|
|
235
|
+
- `ValidationError` — 400 (field-level errors)
|
|
236
|
+
- `RateLimitError` — 429 (auto-retried)
|
|
237
|
+
- `ServerError` — 5xx (auto-retried with backoff)
|
|
238
|
+
|
|
239
|
+
## License
|
|
240
|
+
|
|
241
|
+
MIT
|