phlo-rustfs 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.
- phlo_rustfs-0.1.0/PKG-INFO +15 -0
- phlo_rustfs-0.1.0/README.md +62 -0
- phlo_rustfs-0.1.0/pyproject.toml +45 -0
- phlo_rustfs-0.1.0/setup.cfg +4 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs/__init__.py +7 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs/plugin.py +136 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs/rustfs-setup.yaml +28 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs/rustfs-volume-setup.yaml +20 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs/service.yaml +53 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs/settings.py +30 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs.egg-info/PKG-INFO +15 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs.egg-info/SOURCES.txt +16 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs.egg-info/dependency_links.txt +1 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs.egg-info/entry_points.txt +6 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs.egg-info/requires.txt +6 -0
- phlo_rustfs-0.1.0/src/phlo_rustfs.egg-info/top_level.txt +1 -0
- phlo_rustfs-0.1.0/tests/test_rustfs_plugin.py +67 -0
- phlo_rustfs-0.1.0/tests/test_rustfs_settings.py +39 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: phlo-rustfs
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: RustFS service plugin for Phlo
|
|
5
|
+
Author-email: Phlo Team <team@phlo.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Description-Content-Type: text/plain
|
|
9
|
+
Requires-Dist: phlo>=0.1.0
|
|
10
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
13
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
14
|
+
|
|
15
|
+
RustFS S3-compatible object storage service plugin for Phlo.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# phlo-rustfs
|
|
2
|
+
|
|
3
|
+
RustFS S3-compatible object storage plugin for Phlo.
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
Provides S3-compatible object storage for the data lake using [RustFS](https://github.com/rustfs/rustfs), an Apache 2.0 licensed, Rust-built, 100% S3-compatible object storage server. Stores Iceberg table data, staging files, and backups.
|
|
8
|
+
|
|
9
|
+
## Installation
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install phlo-rustfs
|
|
13
|
+
# or
|
|
14
|
+
phlo plugin install rustfs
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Configuration
|
|
18
|
+
|
|
19
|
+
| Variable | Default | Description |
|
|
20
|
+
| -------------------------------- | ------------- | ---------------------------- |
|
|
21
|
+
| `RUSTFS_ACCESS_KEY` | `rustfsadmin` | Access key (username) |
|
|
22
|
+
| `RUSTFS_SECRET_KEY` | `rustfsadmin` | Secret key (password) |
|
|
23
|
+
| `RUSTFS_API_PORT` | `9000` | S3 API port |
|
|
24
|
+
| `RUSTFS_CONSOLE_PORT` | `9001` | Web console port |
|
|
25
|
+
| `RUSTFS_CORS_ALLOWED_ORIGINS` | `*` | CORS allowed origins (S3) |
|
|
26
|
+
| `RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS` | `*` | CORS allowed origins (console) |
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
phlo services start --service rustfs
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
This targeted start also prepares `./volumes/rustfs` for the non-root RustFS container and creates
|
|
35
|
+
the default `lake`, `warehouse/`, and `stage/` S3 layout automatically.
|
|
36
|
+
|
|
37
|
+
## Endpoints
|
|
38
|
+
|
|
39
|
+
- **S3 API**: `http://localhost:9000`
|
|
40
|
+
- **Console**: `http://localhost:9001`
|
|
41
|
+
|
|
42
|
+
## Migration from MinIO
|
|
43
|
+
|
|
44
|
+
If you're switching from MinIO to RustFS, update your environment variables:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
# Before (MinIO)
|
|
48
|
+
AWS_S3_ENDPOINT=http://minio:9000
|
|
49
|
+
AWS_ACCESS_KEY_ID=minio
|
|
50
|
+
AWS_SECRET_ACCESS_KEY=minio123
|
|
51
|
+
|
|
52
|
+
# After (RustFS)
|
|
53
|
+
AWS_S3_ENDPOINT=http://rustfs:9000
|
|
54
|
+
AWS_ACCESS_KEY_ID=rustfsadmin
|
|
55
|
+
AWS_SECRET_ACCESS_KEY=rustfsadmin
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
For data migration, see the [spec documentation](../../docs/architecture/specs/0015-phlo-rustfs.md).
|
|
59
|
+
|
|
60
|
+
## Entry Points
|
|
61
|
+
|
|
62
|
+
- `phlo.plugins.services` - Provides `RustfsServicePlugin`, `RustfsSetupServicePlugin`
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=45", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "phlo-rustfs"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "RustFS service plugin for Phlo"
|
|
9
|
+
readme = {text = "RustFS S3-compatible object storage service plugin for Phlo.", content-type = "text/plain"}
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
authors = [
|
|
12
|
+
{name = "Phlo Team", email = "team@phlo.dev"},
|
|
13
|
+
]
|
|
14
|
+
license = {text = "MIT"}
|
|
15
|
+
dependencies = [
|
|
16
|
+
"phlo>=0.1.0",
|
|
17
|
+
"pyyaml>=6.0.1",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.optional-dependencies]
|
|
21
|
+
dev = [
|
|
22
|
+
"pytest>=7.0",
|
|
23
|
+
"ruff>=0.1.0",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.entry-points."phlo.plugins.services"]
|
|
27
|
+
rustfs = "phlo_rustfs.plugin:RustfsServicePlugin"
|
|
28
|
+
rustfs-setup = "phlo_rustfs.plugin:RustfsSetupServicePlugin"
|
|
29
|
+
|
|
30
|
+
[project.entry-points."phlo.plugins.resources"]
|
|
31
|
+
rustfs = "phlo_rustfs.plugin:RustfsResourceProvider"
|
|
32
|
+
|
|
33
|
+
[tool.setuptools]
|
|
34
|
+
package-dir = {"" = "src"}
|
|
35
|
+
include-package-data = true
|
|
36
|
+
|
|
37
|
+
[tool.setuptools.packages.find]
|
|
38
|
+
where = ["src"]
|
|
39
|
+
|
|
40
|
+
[tool.setuptools.package-data]
|
|
41
|
+
phlo_rustfs = ["service.yaml", "rustfs-setup.yaml", "rustfs-volume-setup.yaml"]
|
|
42
|
+
|
|
43
|
+
[tool.ruff]
|
|
44
|
+
line-length = 100
|
|
45
|
+
target-version = "py311"
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
"""RustFS service plugin."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from importlib import resources
|
|
6
|
+
from time import perf_counter
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
import yaml
|
|
10
|
+
|
|
11
|
+
from phlo.capabilities import ObjectStoreSpec, ResourceSpec
|
|
12
|
+
from phlo.logging import get_logger
|
|
13
|
+
from phlo.plugins import PluginMetadata, ResourceProviderPlugin, ServicePlugin
|
|
14
|
+
|
|
15
|
+
logger = get_logger(__name__)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _load_service_definition(resource_name: str, service_name: str) -> dict[str, Any]:
|
|
19
|
+
start = perf_counter()
|
|
20
|
+
logger.info(
|
|
21
|
+
"rustfs_service_definition_load_started",
|
|
22
|
+
service_name=service_name,
|
|
23
|
+
resource_name=resource_name,
|
|
24
|
+
)
|
|
25
|
+
service_path = resources.files("phlo_rustfs").joinpath(resource_name)
|
|
26
|
+
try:
|
|
27
|
+
data = yaml.safe_load(service_path.read_text(encoding="utf-8"))
|
|
28
|
+
except Exception:
|
|
29
|
+
logger.error(
|
|
30
|
+
"rustfs_service_definition_load_failed",
|
|
31
|
+
service_name=service_name,
|
|
32
|
+
resource_name=resource_name,
|
|
33
|
+
elapsed_ms=round((perf_counter() - start) * 1000, 2),
|
|
34
|
+
exc_info=True,
|
|
35
|
+
)
|
|
36
|
+
raise
|
|
37
|
+
|
|
38
|
+
service_count = len(data.get("services", {})) if isinstance(data, dict) else None
|
|
39
|
+
logger.info(
|
|
40
|
+
"rustfs_service_definition_load_completed",
|
|
41
|
+
service_name=service_name,
|
|
42
|
+
resource_name=resource_name,
|
|
43
|
+
elapsed_ms=round((perf_counter() - start) * 1000, 2),
|
|
44
|
+
service_count=service_count,
|
|
45
|
+
)
|
|
46
|
+
return data
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class RustfsServicePlugin(ServicePlugin):
|
|
50
|
+
"""Service plugin for RustFS."""
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def metadata(self) -> PluginMetadata:
|
|
54
|
+
"""Return metadata describing the RustFS service plugin."""
|
|
55
|
+
return PluginMetadata(
|
|
56
|
+
name="rustfs",
|
|
57
|
+
version="0.1.0",
|
|
58
|
+
description="S3-compatible object storage for data lake (RustFS)",
|
|
59
|
+
author="Phlo Team",
|
|
60
|
+
tags=["core", "storage", "s3"],
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
@property
|
|
64
|
+
def service_definition(self) -> dict[str, Any]:
|
|
65
|
+
"""Load the RustFS service definition."""
|
|
66
|
+
return _load_service_definition("service.yaml", "rustfs")
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class RustfsSetupServicePlugin(ServicePlugin):
|
|
70
|
+
"""Service plugin for RustFS bucket initialization."""
|
|
71
|
+
|
|
72
|
+
@property
|
|
73
|
+
def metadata(self) -> PluginMetadata:
|
|
74
|
+
"""Return metadata describing the RustFS setup plugin."""
|
|
75
|
+
return PluginMetadata(
|
|
76
|
+
name="rustfs-setup",
|
|
77
|
+
version="0.1.0",
|
|
78
|
+
description="Initialize RustFS buckets for data lake",
|
|
79
|
+
author="Phlo Team",
|
|
80
|
+
tags=["core", "storage", "bootstrap"],
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
@property
|
|
84
|
+
def service_definition(self) -> dict[str, Any]:
|
|
85
|
+
"""Load the RustFS setup service definition."""
|
|
86
|
+
return _load_service_definition("rustfs-setup.yaml", "rustfs-setup")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class RustfsObjectStoreProvider:
|
|
90
|
+
"""Capability provider for RustFS-backed object storage."""
|
|
91
|
+
|
|
92
|
+
def to_sling_connection(self) -> dict[str, Any]:
|
|
93
|
+
"""Return a Sling-compatible S3 connection definition."""
|
|
94
|
+
from phlo_rustfs.settings import get_settings
|
|
95
|
+
|
|
96
|
+
settings = get_settings()
|
|
97
|
+
return {
|
|
98
|
+
"type": "s3",
|
|
99
|
+
"endpoint": f"http://{settings.rustfs_endpoint()}",
|
|
100
|
+
"access_key_id": settings.rustfs_access_key,
|
|
101
|
+
"secret_access_key": settings.rustfs_secret_key,
|
|
102
|
+
"region": settings.s3_region,
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class RustfsResourceProvider(ResourceProviderPlugin):
|
|
107
|
+
"""Resource provider plugin for RustFS capabilities."""
|
|
108
|
+
|
|
109
|
+
@property
|
|
110
|
+
def metadata(self) -> PluginMetadata:
|
|
111
|
+
"""Return plugin metadata for the RustFS resource provider."""
|
|
112
|
+
return PluginMetadata(
|
|
113
|
+
name="rustfs",
|
|
114
|
+
version="0.1.0",
|
|
115
|
+
description="RustFS object-store capability for Phlo",
|
|
116
|
+
tags=["core", "storage", "s3"],
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
def get_resources(self) -> list[ResourceSpec]:
|
|
120
|
+
"""Return resource specs exposed by this provider."""
|
|
121
|
+
return []
|
|
122
|
+
|
|
123
|
+
def get_object_stores(self) -> list[ObjectStoreSpec]:
|
|
124
|
+
"""Return object-store capability specs exposed by this provider."""
|
|
125
|
+
provider = RustfsObjectStoreProvider()
|
|
126
|
+
return [
|
|
127
|
+
ObjectStoreSpec(
|
|
128
|
+
name="rustfs",
|
|
129
|
+
provider=provider,
|
|
130
|
+
metadata={
|
|
131
|
+
"storage_system": "s3",
|
|
132
|
+
"type": "s3",
|
|
133
|
+
"endpoint": provider.to_sling_connection()["endpoint"],
|
|
134
|
+
},
|
|
135
|
+
)
|
|
136
|
+
]
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Companion service for rustfs - creates required buckets
|
|
2
|
+
name: rustfs-setup
|
|
3
|
+
description: Initialize RustFS buckets for data lake
|
|
4
|
+
category: core
|
|
5
|
+
default: false
|
|
6
|
+
|
|
7
|
+
image: amazon/aws-cli:2.15.40
|
|
8
|
+
|
|
9
|
+
depends_on:
|
|
10
|
+
- rustfs
|
|
11
|
+
|
|
12
|
+
compose:
|
|
13
|
+
restart: "no"
|
|
14
|
+
entrypoint: /bin/sh
|
|
15
|
+
command: >
|
|
16
|
+
-c "
|
|
17
|
+
until aws --endpoint-url http://rustfs:9000 s3api list-buckets --region us-east-1 >/dev/null 2>&1; do
|
|
18
|
+
echo 'Waiting for RustFS...' && sleep 2;
|
|
19
|
+
done &&
|
|
20
|
+
aws --endpoint-url http://rustfs:9000 s3 mb s3://lake --region us-east-1 || true &&
|
|
21
|
+
aws --endpoint-url http://rustfs:9000 s3api put-object --bucket lake --key warehouse/ --region us-east-1 >/dev/null &&
|
|
22
|
+
aws --endpoint-url http://rustfs:9000 s3api put-object --bucket lake --key stage/ --region us-east-1 >/dev/null &&
|
|
23
|
+
echo 'RustFS bucket prefixes created successfully'
|
|
24
|
+
"
|
|
25
|
+
environment:
|
|
26
|
+
AWS_ACCESS_KEY_ID: ${RUSTFS_ACCESS_KEY:-rustfsadmin}
|
|
27
|
+
AWS_SECRET_ACCESS_KEY: ${RUSTFS_SECRET_KEY:-rustfsadmin}
|
|
28
|
+
AWS_DEFAULT_REGION: us-east-1
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Companion service for rustfs - prepares writable bind mount ownership
|
|
2
|
+
name: rustfs-volume-setup
|
|
3
|
+
description: Initialize RustFS data volume permissions
|
|
4
|
+
category: core
|
|
5
|
+
default: false
|
|
6
|
+
|
|
7
|
+
image: alpine:3.20
|
|
8
|
+
|
|
9
|
+
compose:
|
|
10
|
+
restart: "no"
|
|
11
|
+
user: "0:0"
|
|
12
|
+
entrypoint: /bin/sh
|
|
13
|
+
command: >
|
|
14
|
+
-c "
|
|
15
|
+
mkdir -p /data &&
|
|
16
|
+
chown -R 10001:10001 /data &&
|
|
17
|
+
echo 'RustFS data volume ownership initialized'
|
|
18
|
+
"
|
|
19
|
+
volumes:
|
|
20
|
+
- ./volumes/rustfs:/data
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
name: rustfs
|
|
2
|
+
description: S3-compatible object storage for data lake (RustFS)
|
|
3
|
+
category: core
|
|
4
|
+
default: false
|
|
5
|
+
|
|
6
|
+
depends_on:
|
|
7
|
+
- rustfs-volume-setup
|
|
8
|
+
|
|
9
|
+
image: rustfs/rustfs:latest
|
|
10
|
+
|
|
11
|
+
compose:
|
|
12
|
+
restart: unless-stopped
|
|
13
|
+
user: "10001:10001"
|
|
14
|
+
environment:
|
|
15
|
+
RUSTFS_VOLUMES: /data
|
|
16
|
+
RUSTFS_ADDRESS: "0.0.0.0:9000"
|
|
17
|
+
RUSTFS_CONSOLE_ADDRESS: "0.0.0.0:9001"
|
|
18
|
+
RUSTFS_CONSOLE_ENABLE: "true"
|
|
19
|
+
RUSTFS_ACCESS_KEY: ${RUSTFS_ACCESS_KEY:-rustfsadmin}
|
|
20
|
+
RUSTFS_SECRET_KEY: ${RUSTFS_SECRET_KEY:-rustfsadmin}
|
|
21
|
+
RUSTFS_CORS_ALLOWED_ORIGINS: ${RUSTFS_CORS_ALLOWED_ORIGINS:-*}
|
|
22
|
+
RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS: ${RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS:-*}
|
|
23
|
+
ports:
|
|
24
|
+
- "${RUSTFS_API_PORT:-9000}:9000"
|
|
25
|
+
- "${RUSTFS_CONSOLE_PORT:-9001}:9001"
|
|
26
|
+
volumes:
|
|
27
|
+
- ./volumes/rustfs:/data
|
|
28
|
+
healthcheck:
|
|
29
|
+
test: ["CMD", "curl", "-f", "http://localhost:9000/health"]
|
|
30
|
+
interval: 10s
|
|
31
|
+
timeout: 5s
|
|
32
|
+
retries: 10
|
|
33
|
+
|
|
34
|
+
env_vars:
|
|
35
|
+
RUSTFS_ACCESS_KEY:
|
|
36
|
+
default: rustfsadmin
|
|
37
|
+
description: RustFS access key (username)
|
|
38
|
+
RUSTFS_SECRET_KEY:
|
|
39
|
+
default: rustfsadmin
|
|
40
|
+
description: RustFS secret key (password)
|
|
41
|
+
secret: true
|
|
42
|
+
RUSTFS_API_PORT:
|
|
43
|
+
default: 9000
|
|
44
|
+
description: RustFS S3 API host port
|
|
45
|
+
RUSTFS_CONSOLE_PORT:
|
|
46
|
+
default: 9001
|
|
47
|
+
description: RustFS web console host port
|
|
48
|
+
RUSTFS_CORS_ALLOWED_ORIGINS:
|
|
49
|
+
default: "*"
|
|
50
|
+
description: CORS allowed origins for S3 API
|
|
51
|
+
RUSTFS_CONSOLE_CORS_ALLOWED_ORIGINS:
|
|
52
|
+
default: "*"
|
|
53
|
+
description: CORS allowed origins for web console
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""RustFS settings."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from functools import lru_cache
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from phlo.config.base import BaseConfig
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class RustfsSettings(BaseConfig):
|
|
13
|
+
"""RustFS S3-compatible storage configuration."""
|
|
14
|
+
|
|
15
|
+
rustfs_host: str = Field(default="rustfs", description="RustFS service hostname")
|
|
16
|
+
rustfs_access_key: str = Field(default="rustfsadmin", description="RustFS access key")
|
|
17
|
+
rustfs_secret_key: str = Field(default="rustfsadmin", description="RustFS secret key")
|
|
18
|
+
rustfs_api_port: int = Field(default=9000, description="RustFS S3 API port")
|
|
19
|
+
rustfs_console_port: int = Field(default=9001, description="RustFS console port")
|
|
20
|
+
s3_region: str = Field(default="us-east-1", description="S3 region")
|
|
21
|
+
|
|
22
|
+
def rustfs_endpoint(self) -> str:
|
|
23
|
+
"""Return host:port endpoint for RustFS S3 API."""
|
|
24
|
+
return f"{self.rustfs_host}:{self.rustfs_api_port}"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@lru_cache(maxsize=1)
|
|
28
|
+
def get_settings() -> RustfsSettings:
|
|
29
|
+
"""Return cached RustFS settings."""
|
|
30
|
+
return RustfsSettings()
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: phlo-rustfs
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: RustFS service plugin for Phlo
|
|
5
|
+
Author-email: Phlo Team <team@phlo.dev>
|
|
6
|
+
License: MIT
|
|
7
|
+
Requires-Python: >=3.11
|
|
8
|
+
Description-Content-Type: text/plain
|
|
9
|
+
Requires-Dist: phlo>=0.1.0
|
|
10
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
11
|
+
Provides-Extra: dev
|
|
12
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
13
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
14
|
+
|
|
15
|
+
RustFS S3-compatible object storage service plugin for Phlo.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/phlo_rustfs/__init__.py
|
|
4
|
+
src/phlo_rustfs/plugin.py
|
|
5
|
+
src/phlo_rustfs/rustfs-setup.yaml
|
|
6
|
+
src/phlo_rustfs/rustfs-volume-setup.yaml
|
|
7
|
+
src/phlo_rustfs/service.yaml
|
|
8
|
+
src/phlo_rustfs/settings.py
|
|
9
|
+
src/phlo_rustfs.egg-info/PKG-INFO
|
|
10
|
+
src/phlo_rustfs.egg-info/SOURCES.txt
|
|
11
|
+
src/phlo_rustfs.egg-info/dependency_links.txt
|
|
12
|
+
src/phlo_rustfs.egg-info/entry_points.txt
|
|
13
|
+
src/phlo_rustfs.egg-info/requires.txt
|
|
14
|
+
src/phlo_rustfs.egg-info/top_level.txt
|
|
15
|
+
tests/test_rustfs_plugin.py
|
|
16
|
+
tests/test_rustfs_settings.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
phlo_rustfs
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"""Tests for RustFS service plugin."""
|
|
2
|
+
|
|
3
|
+
from phlo_rustfs.plugin import RustfsResourceProvider, RustfsServicePlugin, RustfsSetupServicePlugin
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_rustfs_service_definition():
|
|
7
|
+
"""Validate RustFS service definition fields."""
|
|
8
|
+
plugin = RustfsServicePlugin()
|
|
9
|
+
service_definition = plugin.service_definition
|
|
10
|
+
|
|
11
|
+
assert service_definition["name"] == "rustfs"
|
|
12
|
+
assert service_definition["category"] == "core"
|
|
13
|
+
assert service_definition["default"] is False
|
|
14
|
+
assert "rustfs/rustfs" in service_definition["image"]
|
|
15
|
+
assert "rustfs-volume-setup" in service_definition["depends_on"]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_rustfs_plugin_metadata():
|
|
19
|
+
"""Validate RustFS plugin metadata."""
|
|
20
|
+
plugin = RustfsServicePlugin()
|
|
21
|
+
metadata = plugin.metadata
|
|
22
|
+
|
|
23
|
+
assert metadata.name == "rustfs"
|
|
24
|
+
assert metadata.version == "0.1.0"
|
|
25
|
+
assert "storage" in metadata.tags
|
|
26
|
+
assert "s3" in metadata.tags
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def test_rustfs_setup_service_definition():
|
|
30
|
+
"""Validate RustFS setup service definition fields."""
|
|
31
|
+
plugin = RustfsSetupServicePlugin()
|
|
32
|
+
service_definition = plugin.service_definition
|
|
33
|
+
|
|
34
|
+
assert service_definition["name"] == "rustfs-setup"
|
|
35
|
+
assert service_definition["category"] == "core"
|
|
36
|
+
assert "rustfs" in service_definition["depends_on"]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def test_rustfs_setup_plugin_metadata():
|
|
40
|
+
"""Validate RustFS setup plugin metadata."""
|
|
41
|
+
plugin = RustfsSetupServicePlugin()
|
|
42
|
+
metadata = plugin.metadata
|
|
43
|
+
|
|
44
|
+
assert metadata.name == "rustfs-setup"
|
|
45
|
+
assert "bootstrap" in metadata.tags
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_rustfs_resource_provider_exposes_object_store(monkeypatch) -> None:
|
|
49
|
+
"""RustFS should expose an object_store capability."""
|
|
50
|
+
monkeypatch.setattr(
|
|
51
|
+
"phlo_rustfs.plugin.RustfsObjectStoreProvider.to_sling_connection",
|
|
52
|
+
lambda _self: {
|
|
53
|
+
"type": "s3",
|
|
54
|
+
"endpoint": "http://rustfs:9000",
|
|
55
|
+
"access_key_id": "rustfs",
|
|
56
|
+
"secret_access_key": "secret",
|
|
57
|
+
"region": "us-east-1",
|
|
58
|
+
},
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
provider = RustfsResourceProvider()
|
|
62
|
+
|
|
63
|
+
object_stores = provider.get_object_stores()
|
|
64
|
+
|
|
65
|
+
assert len(object_stores) == 1
|
|
66
|
+
assert object_stores[0].name == "rustfs"
|
|
67
|
+
assert object_stores[0].metadata["endpoint"] == "http://rustfs:9000"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Tests for RustFS settings."""
|
|
2
|
+
|
|
3
|
+
from phlo_rustfs.settings import RustfsSettings
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_rustfs_settings_defaults():
|
|
7
|
+
"""Validate default settings values."""
|
|
8
|
+
settings = RustfsSettings()
|
|
9
|
+
|
|
10
|
+
assert settings.rustfs_host == "rustfs"
|
|
11
|
+
assert settings.rustfs_access_key == "rustfsadmin"
|
|
12
|
+
assert settings.rustfs_secret_key == "rustfsadmin"
|
|
13
|
+
assert settings.rustfs_api_port == 9000
|
|
14
|
+
assert settings.rustfs_console_port == 9001
|
|
15
|
+
assert settings.s3_region == "us-east-1"
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_rustfs_endpoint():
|
|
19
|
+
"""Validate endpoint format."""
|
|
20
|
+
settings = RustfsSettings()
|
|
21
|
+
endpoint = settings.rustfs_endpoint()
|
|
22
|
+
|
|
23
|
+
assert endpoint == "rustfs:9000"
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_rustfs_endpoint_custom_port():
|
|
27
|
+
"""Validate endpoint with custom port."""
|
|
28
|
+
settings = RustfsSettings(rustfs_api_port=19000)
|
|
29
|
+
endpoint = settings.rustfs_endpoint()
|
|
30
|
+
|
|
31
|
+
assert endpoint == "rustfs:19000"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_rustfs_endpoint_custom_host():
|
|
35
|
+
"""Validate endpoint with custom host."""
|
|
36
|
+
settings = RustfsSettings(rustfs_host="storage.local")
|
|
37
|
+
endpoint = settings.rustfs_endpoint()
|
|
38
|
+
|
|
39
|
+
assert endpoint == "storage.local:9000"
|