opencloudtool 0.5.1__cp312-cp312-macosx_11_0_arm64.whl
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.
- opencloudtool/__init__.py +3 -0
- opencloudtool/__pycache__/__init__.cpython-312.pyc +0 -0
- opencloudtool/__pycache__/py_api.cpython-312.pyc +0 -0
- opencloudtool/_internal.cpython-312-darwin.so +0 -0
- opencloudtool/py_api.py +142 -0
- opencloudtool-0.5.1.dist-info/METADATA +112 -0
- opencloudtool-0.5.1.dist-info/RECORD +8 -0
- opencloudtool-0.5.1.dist-info/WHEEL +4 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
opencloudtool/py_api.py
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import os
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from ._internal import deploy as _rust_deploy
|
|
5
|
+
from ._internal import destroy as _rust_destroy
|
|
6
|
+
from ._internal import init_logging as _rust_init_logging
|
|
7
|
+
|
|
8
|
+
# A flag to ensure we only initialize the logger once per session.
|
|
9
|
+
_logging_initialized = False
|
|
10
|
+
|
|
11
|
+
logger = logging.getLogger(name=__name__)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def init_logging():
|
|
15
|
+
"""
|
|
16
|
+
Initializes the Rust logging system to show logs in the console.
|
|
17
|
+
|
|
18
|
+
This is called automatically by other functions like `deploy`,
|
|
19
|
+
so you don't typically need to call it yourself.
|
|
20
|
+
"""
|
|
21
|
+
global _logging_initialized
|
|
22
|
+
if not _logging_initialized:
|
|
23
|
+
_rust_init_logging()
|
|
24
|
+
_logging_initialized = True
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def deploy(path: str = ".") -> None:
|
|
28
|
+
"""
|
|
29
|
+
Deploys the application using the Rust core orchestrator.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
path (str): The path to the project directory containing the
|
|
33
|
+
`oct.toml` file. Defaults to the current directory.
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
init_logging()
|
|
37
|
+
project_path = os.path.abspath(path)
|
|
38
|
+
logger.info("[Python] Triggering deployment")
|
|
39
|
+
|
|
40
|
+
try:
|
|
41
|
+
_rust_deploy(project_path)
|
|
42
|
+
logger.info("[Python] Deployment call completed successfully.")
|
|
43
|
+
except (RuntimeError, IOError) as e:
|
|
44
|
+
logger.exception(f"[Python] An error occurred during deployment: {e}")
|
|
45
|
+
raise
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def destroy(path: str = ".") -> None:
|
|
49
|
+
"""
|
|
50
|
+
Destroys the application using the Rust core orchestrator.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
path (str): The path to the project directory containing the
|
|
54
|
+
`oct.toml` file. Defaults to the current directory.
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
init_logging()
|
|
58
|
+
project_path = os.path.abspath(path)
|
|
59
|
+
logger.info("[Python] Triggering destroy")
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
_rust_destroy(project_path)
|
|
63
|
+
logger.info("[Python] Destroy call completed successfully.")
|
|
64
|
+
except (RuntimeError, IOError) as e:
|
|
65
|
+
logger.exception(f"[Python] An error occurred during destroy process: {e}")
|
|
66
|
+
raise
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def deploy_service(path: str) -> None:
|
|
70
|
+
"""
|
|
71
|
+
Automates the deployment of a standard FastAPI service.
|
|
72
|
+
|
|
73
|
+
This high-level function generates the necessary Dockerfile, requirements.txt,
|
|
74
|
+
and oct.toml, then calls the core deploy function.
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
path: The path to the FastAPI application's main.py file.
|
|
78
|
+
"""
|
|
79
|
+
if not os.path.isfile(path) or not path.endswith("main.py"):
|
|
80
|
+
raise ValueError("The path must point to a 'main.py' file.")
|
|
81
|
+
|
|
82
|
+
absolute_path = os.path.abspath(path)
|
|
83
|
+
app_dir = os.path.dirname(absolute_path)
|
|
84
|
+
project_root = os.path.dirname(app_dir)
|
|
85
|
+
project_name = os.path.basename(project_root)
|
|
86
|
+
|
|
87
|
+
logger.info(f"Detected project root: '{project_root}' with name '{project_name}'")
|
|
88
|
+
|
|
89
|
+
dockerfile_content = """# Generated by opencloudtool
|
|
90
|
+
FROM python:3.10-slim
|
|
91
|
+
WORKDIR /code
|
|
92
|
+
COPY ./requirements.txt /code/requirements.txt
|
|
93
|
+
RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
|
|
94
|
+
COPY ./app /code/app
|
|
95
|
+
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
|
96
|
+
"""
|
|
97
|
+
|
|
98
|
+
requirements_content = """# Generated by opencloudtool
|
|
99
|
+
fastapi
|
|
100
|
+
uvicorn[standard]
|
|
101
|
+
"""
|
|
102
|
+
|
|
103
|
+
oct_toml_content = f"""# Generated by opencloudtool
|
|
104
|
+
[project]
|
|
105
|
+
name = "{project_name}"
|
|
106
|
+
|
|
107
|
+
[project.state_backend.local]
|
|
108
|
+
path = "./state.json"
|
|
109
|
+
|
|
110
|
+
[project.user_state_backend.local]
|
|
111
|
+
path = "./user_state.json"
|
|
112
|
+
|
|
113
|
+
[project.services.app_1]
|
|
114
|
+
image = ""
|
|
115
|
+
dockerfile_path = "Dockerfile"
|
|
116
|
+
internal_port = 80
|
|
117
|
+
external_port = 80
|
|
118
|
+
cpus = 250
|
|
119
|
+
memory = 64
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
try:
|
|
123
|
+
dockerfile_path = os.path.join(project_root, "Dockerfile")
|
|
124
|
+
with open(dockerfile_path, "w") as f:
|
|
125
|
+
f.write(dockerfile_content)
|
|
126
|
+
logger.info(f"Generated Dockerfile at '{dockerfile_path}'")
|
|
127
|
+
|
|
128
|
+
reqs_path = os.path.join(project_root, "requirements.txt")
|
|
129
|
+
with open(reqs_path, "w") as f:
|
|
130
|
+
f.write(requirements_content)
|
|
131
|
+
logger.info(f"Generated requirements.txt at '{reqs_path}'")
|
|
132
|
+
|
|
133
|
+
toml_path = os.path.join(project_root, "oct.toml")
|
|
134
|
+
with open(toml_path, "w") as f:
|
|
135
|
+
f.write(oct_toml_content)
|
|
136
|
+
logger.info(f"Generated oct.toml at '{toml_path}'")
|
|
137
|
+
|
|
138
|
+
except IOError:
|
|
139
|
+
logger.exception("Error writing configuration files")
|
|
140
|
+
raise
|
|
141
|
+
|
|
142
|
+
deploy(project_root)
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: opencloudtool
|
|
3
|
+
Version: 0.5.1
|
|
4
|
+
Requires-Python: >=3.8
|
|
5
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
6
|
+
|
|
7
|
+
# Opencloudtool Python Library
|
|
8
|
+
|
|
9
|
+
A tool to hide the complexity of the cloud, now available as a Python library.
|
|
10
|
+
This library allows you to deploy services directly from your Python scripts.The core of this library is written in Rust
|
|
11
|
+
for high performance and reliability.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
You can install the library from PyPI using `pip`
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install opencloudtool
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Basic Usage
|
|
23
|
+
|
|
24
|
+
To use the library, you need an `oct.toml` configuration file in your project directory.
|
|
25
|
+
The library provides `deploy` and `destroy` functions to manage your stack.
|
|
26
|
+
|
|
27
|
+
Example `deploy.py`
|
|
28
|
+
|
|
29
|
+
```python
|
|
30
|
+
import opencloudtool as oct
|
|
31
|
+
|
|
32
|
+
# The path to the project directory containing oct.toml
|
|
33
|
+
project_path = "./my-app"
|
|
34
|
+
|
|
35
|
+
oct.deploy(path=project_path)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
To destroy infrastructure:
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
oct.destroy(path=project_path)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Main repo [opencloudtool](https://github.com/opencloudtool/opencloudtool)
|
|
45
|
+
|
|
46
|
+
### Dev
|
|
47
|
+
|
|
48
|
+
#### How it works: Python-Rust binding
|
|
49
|
+
|
|
50
|
+
#### The connection between Python and Rust is managed by `maturin` and `PyO3`
|
|
51
|
+
|
|
52
|
+
1. `maturin` compiles the Rust code in the `oct-py` crate into a native Python module.
|
|
53
|
+
2. We configure the name of this compiled module in `pyproject.toml` to be `opencloudtool._internal`.
|
|
54
|
+
3. The leading underscore (`_`) is a standard Python convention that signals that `_internal` is a low-level module not meant for direct use.
|
|
55
|
+
4. Our user-facing Python code in `opencloudtool/py_api.py` imports functions from `_internal` and presents them as a clean, stable API.
|
|
56
|
+
|
|
57
|
+
#### 1. Navigate to the Python Directory
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd crates/oct-py
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
#### 2. Create and activate the Virtual environment
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
uv venv
|
|
67
|
+
|
|
68
|
+
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### 3. Install dependencies
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
uv sync --group dev
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
#### 4. Build the Library
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
maturin develop
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### 5. Run the example
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cd ../../examples/projects/single-host-python-lib
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
You can now run `python deploy.py` or `python destroy.py` to test your changes.
|
|
90
|
+
|
|
91
|
+
### Releasing the Python Library
|
|
92
|
+
|
|
93
|
+
#### Bump the Version Number
|
|
94
|
+
|
|
95
|
+
1. Before releasing, you must increment the version number. PyPI will not accept a version that already exists.
|
|
96
|
+
|
|
97
|
+
- `crates/oct-py/pyproject.toml`
|
|
98
|
+
|
|
99
|
+
2. Build & upload the Release Packages:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
cd crates/oct-py
|
|
103
|
+
|
|
104
|
+
maturin sdist
|
|
105
|
+
|
|
106
|
+
maturin build --release
|
|
107
|
+
|
|
108
|
+
cd ../..
|
|
109
|
+
|
|
110
|
+
twine upload target/wheels/*
|
|
111
|
+
```
|
|
112
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
opencloudtool-0.5.1.dist-info/METADATA,sha256=0sDGv7SBEtfqNAPCNKky-G2e5dXTQ1KN54Fbd-2yrzA,2492
|
|
2
|
+
opencloudtool-0.5.1.dist-info/WHEEL,sha256=EhaWXx4fd8VOPM6W-6pxsePGk73OLk2gBi7fwS90pc8,104
|
|
3
|
+
opencloudtool/__init__.py,sha256=RzuIGV6BftKGFsuqfw1urrSufsxbxZnZn_CWEjAdGHA,103
|
|
4
|
+
opencloudtool/__pycache__/__init__.cpython-312.pyc,sha256=1Q_Q8xgrzm_g0_3OgIlKG0uFtOepaxHEs4KwkSAgu6c,304
|
|
5
|
+
opencloudtool/__pycache__/py_api.cpython-312.pyc,sha256=FMvwCuCgBgJpVzBCrCMucuF9y2kj6JCPNZE00OiyXlo,6261
|
|
6
|
+
opencloudtool/_internal.cpython-312-darwin.so,sha256=C0jwPMAdxHTj2MXF1oVSH7ceNxrO4vTfDkboirLaeKg,35447808
|
|
7
|
+
opencloudtool/py_api.py,sha256=q98gH-qmx5TRRUdewEkeoILrlcMmXfcK5kfCzRAfkZw,4179
|
|
8
|
+
opencloudtool-0.5.1.dist-info/RECORD,,
|