arkitekt-next 0.7.50__py3-none-any.whl → 0.7.51__py3-none-any.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.
Potentially problematic release.
This version of arkitekt-next might be problematic. Click here for more details.
- arkitekt_next/bloks/base.py +216 -0
- arkitekt_next/bloks/fluss.py +5 -25
- arkitekt_next/bloks/kabinet.py +7 -22
- arkitekt_next/bloks/lok.py +1 -4
- arkitekt_next/bloks/mikro.py +2 -25
- arkitekt_next/bloks/orkestrator.py +10 -7
- arkitekt_next/bloks/rekuest.py +2 -25
- arkitekt_next/bloks/services/db.py +3 -7
- arkitekt_next/bloks/services/gateway.py +1 -1
- arkitekt_next/bloks/services/redis.py +1 -1
- arkitekt_next/bloks/services/socket.py +1 -4
- {arkitekt_next-0.7.50.dist-info → arkitekt_next-0.7.51.dist-info}/METADATA +8 -8
- {arkitekt_next-0.7.50.dist-info → arkitekt_next-0.7.51.dist-info}/RECORD +16 -16
- arkitekt_next/bloks/funcs.py +0 -187
- {arkitekt_next-0.7.50.dist-info → arkitekt_next-0.7.51.dist-info}/LICENSE +0 -0
- {arkitekt_next-0.7.50.dist-info → arkitekt_next-0.7.51.dist-info}/WHEEL +0 -0
- {arkitekt_next-0.7.50.dist-info → arkitekt_next-0.7.51.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
from blok import blok, InitContext, Option
|
|
2
|
+
from blok.tree import YamlFile, Repo
|
|
3
|
+
from typing import Any, Protocol
|
|
4
|
+
from blok.utils import check_protocol_compliance
|
|
5
|
+
from dataclasses import asdict
|
|
6
|
+
from arkitekt_next.bloks.services import (
|
|
7
|
+
GatewayService,
|
|
8
|
+
DBService,
|
|
9
|
+
RedisService,
|
|
10
|
+
S3Service,
|
|
11
|
+
ConfigService,
|
|
12
|
+
MountService,
|
|
13
|
+
AdminService,
|
|
14
|
+
SecretService,
|
|
15
|
+
LokService,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from blok.bloks.services.dns import DnsService
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class DefaultService(Protocol):
|
|
22
|
+
dev: bool
|
|
23
|
+
repo: str
|
|
24
|
+
command: str
|
|
25
|
+
service_name: str
|
|
26
|
+
host: str
|
|
27
|
+
buckets: list[str]
|
|
28
|
+
scopes: dict[str, str]
|
|
29
|
+
secret_key: str
|
|
30
|
+
mount_repo: bool
|
|
31
|
+
build_repo: bool
|
|
32
|
+
|
|
33
|
+
def get_blok_meta(self) -> str: ...
|
|
34
|
+
|
|
35
|
+
def get_builder(self) -> str: ...
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def create_default_service_dependencies():
|
|
39
|
+
return [
|
|
40
|
+
DnsService,
|
|
41
|
+
GatewayService,
|
|
42
|
+
DBService,
|
|
43
|
+
RedisService,
|
|
44
|
+
S3Service,
|
|
45
|
+
ConfigService,
|
|
46
|
+
MountService,
|
|
47
|
+
AdminService,
|
|
48
|
+
SecretService,
|
|
49
|
+
LokService,
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class BaseArkitektService:
|
|
54
|
+
def get_additional_config(self):
|
|
55
|
+
return {}
|
|
56
|
+
|
|
57
|
+
def preflight(
|
|
58
|
+
self,
|
|
59
|
+
init: InitContext,
|
|
60
|
+
lok: LokService,
|
|
61
|
+
dns: DnsService,
|
|
62
|
+
db: DBService,
|
|
63
|
+
gateway: GatewayService,
|
|
64
|
+
redis: RedisService,
|
|
65
|
+
s3: S3Service,
|
|
66
|
+
config: ConfigService,
|
|
67
|
+
mount: MountService,
|
|
68
|
+
admin: AdminService,
|
|
69
|
+
secret: SecretService,
|
|
70
|
+
mount_repo: bool = False,
|
|
71
|
+
host: str = "",
|
|
72
|
+
image: str = "",
|
|
73
|
+
secret_key: str = "",
|
|
74
|
+
build_repo: bool = False,
|
|
75
|
+
command: str = "",
|
|
76
|
+
repo: str = "",
|
|
77
|
+
disable: bool = False,
|
|
78
|
+
dev: bool = False,
|
|
79
|
+
):
|
|
80
|
+
deps = init.dependencies
|
|
81
|
+
|
|
82
|
+
lok.register_scopes(self.scopes)
|
|
83
|
+
|
|
84
|
+
path_name = self.host
|
|
85
|
+
|
|
86
|
+
gateway_access = gateway.expose(path_name, 80, self.host)
|
|
87
|
+
|
|
88
|
+
postgress_access = db.register_db(self.host)
|
|
89
|
+
redis_access = redis.register()
|
|
90
|
+
lok_access = lok.retrieve_credentials()
|
|
91
|
+
admin_access = admin.retrieve()
|
|
92
|
+
minio_access = s3.create_buckets(self.buckets)
|
|
93
|
+
lok_labels = lok.retrieve_labels(
|
|
94
|
+
self.get_blok_meta().service_identifier, self.get_builder()
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
dns_result = init.get_service(DnsService).get_dns_result()
|
|
98
|
+
|
|
99
|
+
csrf_trusted_origins = []
|
|
100
|
+
for hostname in dns_result.hostnames:
|
|
101
|
+
csrf_trusted_origins.append(f"http://{hostname}")
|
|
102
|
+
csrf_trusted_origins.append(f"https://{hostname}")
|
|
103
|
+
|
|
104
|
+
configuration = YamlFile(
|
|
105
|
+
**{
|
|
106
|
+
"db": asdict(postgress_access),
|
|
107
|
+
"django": {
|
|
108
|
+
"admin": asdict(admin_access),
|
|
109
|
+
"debug": True,
|
|
110
|
+
"hosts": ["*"],
|
|
111
|
+
"secret_key": self.secret_key,
|
|
112
|
+
},
|
|
113
|
+
"redis": asdict(redis_access),
|
|
114
|
+
"lok": asdict(lok_access),
|
|
115
|
+
"s3": asdict(minio_access),
|
|
116
|
+
"scopes": self.scopes,
|
|
117
|
+
"force_script_name": path_name,
|
|
118
|
+
"csrf_trusted_origins": csrf_trusted_origins,
|
|
119
|
+
**self.get_additional_config(),
|
|
120
|
+
}
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
config_mount = init.get_service(ConfigService).register_config(
|
|
124
|
+
f"{self.host}.yaml", configuration
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
depends_on = []
|
|
128
|
+
|
|
129
|
+
if redis_access.dependency:
|
|
130
|
+
depends_on.append(redis_access.dependency)
|
|
131
|
+
|
|
132
|
+
if postgress_access.dependency:
|
|
133
|
+
depends_on.append(postgress_access.dependency)
|
|
134
|
+
|
|
135
|
+
if minio_access.dependency:
|
|
136
|
+
depends_on.append(minio_access.dependency)
|
|
137
|
+
|
|
138
|
+
service = {
|
|
139
|
+
"labels": lok_labels,
|
|
140
|
+
"volumes": [f"{config_mount}:/workspace/config.yaml"],
|
|
141
|
+
"depends_on": depends_on,
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if mount_repo or dev:
|
|
145
|
+
mount = init.get_service(MountService).register_mount(self.host, Repo(repo))
|
|
146
|
+
service["volumes"].extend([f"{mount}:/workspace"])
|
|
147
|
+
|
|
148
|
+
if build_repo or dev:
|
|
149
|
+
mount = init.get_service(MountService).register_mount(self.host, Repo(repo))
|
|
150
|
+
service["build"] = mount
|
|
151
|
+
else:
|
|
152
|
+
service["image"] = image
|
|
153
|
+
|
|
154
|
+
service["command"] = command
|
|
155
|
+
|
|
156
|
+
self.service = service
|
|
157
|
+
|
|
158
|
+
def get_additional_options(self):
|
|
159
|
+
return []
|
|
160
|
+
|
|
161
|
+
def get_options(self):
|
|
162
|
+
return [
|
|
163
|
+
Option(
|
|
164
|
+
subcommand="dev",
|
|
165
|
+
help="Shoud we run the service in development mode (includes withrepo, mountrepo)?",
|
|
166
|
+
default=self.dev,
|
|
167
|
+
),
|
|
168
|
+
Option(
|
|
169
|
+
subcommand="host",
|
|
170
|
+
help="The name we should use for the host?",
|
|
171
|
+
default=self.host,
|
|
172
|
+
),
|
|
173
|
+
Option(
|
|
174
|
+
subcommand="disable",
|
|
175
|
+
help="Shoud we disable the service?",
|
|
176
|
+
default=False,
|
|
177
|
+
),
|
|
178
|
+
Option(
|
|
179
|
+
subcommand="repo",
|
|
180
|
+
help="Which repo should we use when building the service? Only active if build_repo or mount_repo is active",
|
|
181
|
+
default=self.repo,
|
|
182
|
+
),
|
|
183
|
+
Option(
|
|
184
|
+
subcommand="command",
|
|
185
|
+
help="Which command should we use when building the service?",
|
|
186
|
+
default=self.command,
|
|
187
|
+
),
|
|
188
|
+
Option(
|
|
189
|
+
subcommand="mount_repo",
|
|
190
|
+
help="Should we mount the repo into the container?",
|
|
191
|
+
type=bool,
|
|
192
|
+
default=self.mount_repo,
|
|
193
|
+
),
|
|
194
|
+
Option(
|
|
195
|
+
subcommand="build_repo",
|
|
196
|
+
help="Should we build the container from the repo?",
|
|
197
|
+
type=bool,
|
|
198
|
+
default=self.build_repo,
|
|
199
|
+
),
|
|
200
|
+
Option(
|
|
201
|
+
subcommand="host",
|
|
202
|
+
help="How should the service be named inside the docker-compose file?",
|
|
203
|
+
default=self.host,
|
|
204
|
+
),
|
|
205
|
+
Option(
|
|
206
|
+
subcommand="secret_key",
|
|
207
|
+
help="The secret key to use for the django service",
|
|
208
|
+
default=self.secret_key,
|
|
209
|
+
),
|
|
210
|
+
Option(
|
|
211
|
+
subcommand="image",
|
|
212
|
+
help="The image to use for the service",
|
|
213
|
+
default=self.image,
|
|
214
|
+
),
|
|
215
|
+
*self.get_additional_options(),
|
|
216
|
+
]
|
arkitekt_next/bloks/fluss.py
CHANGED
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import secrets
|
|
2
|
-
|
|
3
|
-
build_default_service_options,
|
|
4
|
-
create_default_service_dependencies,
|
|
5
|
-
create_default_service_yaml,
|
|
6
|
-
)
|
|
2
|
+
|
|
7
3
|
from blok import blok, InitContext, ExecutionContext, Option
|
|
8
4
|
from blok.tree import YamlFile, Repo
|
|
5
|
+
from arkitekt_next.bloks.base import BaseArkitektService
|
|
6
|
+
from typing import List
|
|
9
7
|
|
|
10
8
|
|
|
11
9
|
DEFAULT_ARKITEKT_URL = "http://localhost:8000"
|
|
12
10
|
|
|
13
11
|
|
|
14
12
|
@blok("live.arkitekt.fluss")
|
|
15
|
-
class FlussBlok:
|
|
13
|
+
class FlussBlok(BaseArkitektService):
|
|
16
14
|
def __init__(self) -> None:
|
|
17
15
|
self.dev = False
|
|
18
16
|
self.host = "fluss"
|
|
@@ -24,28 +22,10 @@ class FlussBlok:
|
|
|
24
22
|
self.build_repo = False
|
|
25
23
|
self.buckets = ["media"]
|
|
26
24
|
self.secret_key = secrets.token_hex(16)
|
|
27
|
-
self.ensured_repos = []
|
|
25
|
+
self.ensured_repos: List[str] = []
|
|
28
26
|
|
|
29
27
|
def get_builder(self):
|
|
30
28
|
return "arkitekt.generic"
|
|
31
29
|
|
|
32
|
-
def get_dependencies(self):
|
|
33
|
-
return create_default_service_dependencies()
|
|
34
|
-
|
|
35
|
-
def preflight(self, init: InitContext):
|
|
36
|
-
for key, value in init.kwargs.items():
|
|
37
|
-
setattr(self, key, value)
|
|
38
|
-
|
|
39
|
-
self.service = create_default_service_yaml(init, self)
|
|
40
|
-
|
|
41
|
-
self.initialized = True
|
|
42
|
-
|
|
43
30
|
def build(self, context: ExecutionContext):
|
|
44
31
|
context.docker_compose.set_nested("services", self.host, self.service)
|
|
45
|
-
|
|
46
|
-
def get_options(self):
|
|
47
|
-
def_options = build_default_service_options(self)
|
|
48
|
-
|
|
49
|
-
return [
|
|
50
|
-
*def_options,
|
|
51
|
-
]
|
arkitekt_next/bloks/kabinet.py
CHANGED
|
@@ -1,17 +1,14 @@
|
|
|
1
1
|
from typing import Dict, Any
|
|
2
2
|
import secrets
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
create_default_service_yaml,
|
|
6
|
-
create_default_service_dependencies,
|
|
7
|
-
build_default_service_options,
|
|
8
|
-
)
|
|
4
|
+
|
|
9
5
|
from blok import blok, InitContext, ExecutionContext, Option
|
|
10
6
|
from blok.tree import Repo, YamlFile
|
|
7
|
+
from arkitekt_next.bloks.base import BaseArkitektService
|
|
11
8
|
|
|
12
9
|
|
|
13
10
|
@blok("live.arkitekt.kabinet")
|
|
14
|
-
class KabinetBlok:
|
|
11
|
+
class KabinetBlok(BaseArkitektService):
|
|
15
12
|
def __init__(self) -> None:
|
|
16
13
|
self.dev = False
|
|
17
14
|
self.host = "kabinet"
|
|
@@ -28,27 +25,16 @@ class KabinetBlok:
|
|
|
28
25
|
self.ensured_repos = ["jhnnsrs/ome:main", "jhnnsrs/renderer:main"]
|
|
29
26
|
self.image = "jhnnsrs/kabinet:next"
|
|
30
27
|
|
|
28
|
+
def get_additional_config(self):
|
|
29
|
+
return {"ensured_repos": self.ensured_repos}
|
|
30
|
+
|
|
31
31
|
def get_builder(self):
|
|
32
32
|
return "arkitekt.generic"
|
|
33
33
|
|
|
34
|
-
def get_dependencies(self):
|
|
35
|
-
return create_default_service_dependencies()
|
|
36
|
-
|
|
37
|
-
def preflight(self, init: InitContext):
|
|
38
|
-
for key, value in init.kwargs.items():
|
|
39
|
-
setattr(self, key, value)
|
|
40
|
-
|
|
41
|
-
self.service = create_default_service_yaml(
|
|
42
|
-
init, self, {"ensured_repos": self.ensured_repos}
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
self.initialized = True
|
|
46
|
-
|
|
47
34
|
def build(self, context: ExecutionContext):
|
|
48
35
|
context.docker_compose.set_nested("services", self.host, self.service)
|
|
49
36
|
|
|
50
|
-
def
|
|
51
|
-
def_options = build_default_service_options(self)
|
|
37
|
+
def get_additional_options(self):
|
|
52
38
|
with_repos = Option(
|
|
53
39
|
subcommand="repos",
|
|
54
40
|
help="The default repos to enable for the service",
|
|
@@ -56,6 +42,5 @@ class KabinetBlok:
|
|
|
56
42
|
)
|
|
57
43
|
|
|
58
44
|
return [
|
|
59
|
-
*def_options,
|
|
60
45
|
with_repos,
|
|
61
46
|
]
|
arkitekt_next/bloks/lok.py
CHANGED
|
@@ -5,7 +5,6 @@ from cryptography.hazmat.primitives import serialization as crypto_serialization
|
|
|
5
5
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
6
6
|
from cryptography.hazmat.backends import default_backend as crypto_default_backend
|
|
7
7
|
from typing import Dict
|
|
8
|
-
from arkitekt_next.bloks.funcs import build_default_service_options
|
|
9
8
|
from arkitekt_next.bloks.secret import SecretBlok
|
|
10
9
|
from arkitekt_next.bloks.services.admin import AdminService
|
|
11
10
|
from arkitekt_next.bloks.services.db import DBService
|
|
@@ -283,8 +282,6 @@ class LokBlok:
|
|
|
283
282
|
.decode()
|
|
284
283
|
)
|
|
285
284
|
|
|
286
|
-
def_options = build_default_service_options(self)
|
|
287
|
-
|
|
288
285
|
with_dev = Option(
|
|
289
286
|
subcommand="dev",
|
|
290
287
|
help="Run the service in development mode",
|
|
@@ -331,7 +328,7 @@ class LokBlok:
|
|
|
331
328
|
)
|
|
332
329
|
|
|
333
330
|
return [
|
|
334
|
-
|
|
331
|
+
with_dev,
|
|
335
332
|
with_fakts_url,
|
|
336
333
|
with_users,
|
|
337
334
|
with_groups,
|
arkitekt_next/bloks/mikro.py
CHANGED
|
@@ -7,12 +7,7 @@ from blok import blok, InitContext
|
|
|
7
7
|
|
|
8
8
|
from blok import blok, InitContext, ExecutionContext, Option
|
|
9
9
|
from blok.tree import YamlFile, Repo
|
|
10
|
-
from arkitekt_next.bloks.
|
|
11
|
-
build_default_service_options,
|
|
12
|
-
create_default_service_dependencies,
|
|
13
|
-
create_default_service_yaml,
|
|
14
|
-
DefaultService,
|
|
15
|
-
)
|
|
10
|
+
from arkitekt_next.bloks.base import BaseArkitektService
|
|
16
11
|
|
|
17
12
|
|
|
18
13
|
class AccessCredentials(BaseModel):
|
|
@@ -24,7 +19,7 @@ class AccessCredentials(BaseModel):
|
|
|
24
19
|
|
|
25
20
|
|
|
26
21
|
@blok("live.arkitekt.mikro")
|
|
27
|
-
class MikroBlok:
|
|
22
|
+
class MikroBlok(BaseArkitektService):
|
|
28
23
|
def __init__(self) -> None:
|
|
29
24
|
self.dev = False
|
|
30
25
|
self.host = "mikro"
|
|
@@ -40,26 +35,8 @@ class MikroBlok:
|
|
|
40
35
|
self.buckets = ["media", "zarr", "parquet"]
|
|
41
36
|
self.secret_key = secrets.token_hex(16)
|
|
42
37
|
|
|
43
|
-
def get_dependencies(self):
|
|
44
|
-
return create_default_service_dependencies()
|
|
45
|
-
|
|
46
38
|
def get_builder(self):
|
|
47
39
|
return "arkitekt.generic"
|
|
48
40
|
|
|
49
|
-
def preflight(self, init: InitContext):
|
|
50
|
-
for key, value in init.kwargs.items():
|
|
51
|
-
setattr(self, key, value)
|
|
52
|
-
|
|
53
|
-
self.service = create_default_service_yaml(init, self)
|
|
54
|
-
|
|
55
|
-
self.initialized = True
|
|
56
|
-
|
|
57
41
|
def build(self, context: ExecutionContext):
|
|
58
42
|
context.docker_compose.set_nested("services", self.host, self.service)
|
|
59
|
-
|
|
60
|
-
def get_options(self):
|
|
61
|
-
def_options = build_default_service_options(self)
|
|
62
|
-
|
|
63
|
-
return [
|
|
64
|
-
*def_options,
|
|
65
|
-
]
|
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
from typing import Dict, Any
|
|
2
2
|
import secrets
|
|
3
|
-
|
|
4
|
-
from arkitekt_next.bloks.funcs import (
|
|
5
|
-
create_default_service_yaml,
|
|
6
|
-
create_default_service_dependencies,
|
|
7
|
-
build_default_service_options,
|
|
8
|
-
)
|
|
9
3
|
from arkitekt_next.bloks.services.mount import MountService
|
|
10
4
|
from blok import blok, InitContext, ExecutionContext, Option, Command
|
|
5
|
+
from blok.bloks.services.vscode import VsCodeService
|
|
11
6
|
from blok.tree import Repo, YamlFile
|
|
12
7
|
|
|
13
8
|
|
|
@@ -20,7 +15,7 @@ class OrkestratorBlok:
|
|
|
20
15
|
self.build_command = ["yarn"]
|
|
21
16
|
self.up_command = ["yarn", "start"]
|
|
22
17
|
|
|
23
|
-
def preflight(self, init: InitContext, mount: MountService):
|
|
18
|
+
def preflight(self, init: InitContext, mount: MountService, vscode: VsCodeService | None = None) :
|
|
24
19
|
for key, value in init.kwargs.items():
|
|
25
20
|
setattr(self, key, value)
|
|
26
21
|
|
|
@@ -28,6 +23,14 @@ class OrkestratorBlok:
|
|
|
28
23
|
return
|
|
29
24
|
self.mount = mount.register_mount("orkestrator", Repo(self.repo))
|
|
30
25
|
|
|
26
|
+
vscode.register_task(
|
|
27
|
+
"Run Orkestrator",
|
|
28
|
+
"shell",
|
|
29
|
+
"yarn",
|
|
30
|
+
["start"],
|
|
31
|
+
{"cwd": f"{self.mount}"},
|
|
32
|
+
)
|
|
33
|
+
|
|
31
34
|
self.initialized = True
|
|
32
35
|
|
|
33
36
|
def build(self, context: ExecutionContext):
|
arkitekt_next/bloks/rekuest.py
CHANGED
|
@@ -1,17 +1,13 @@
|
|
|
1
1
|
from typing import Dict, Any
|
|
2
2
|
import secrets
|
|
3
3
|
|
|
4
|
-
from arkitekt_next.bloks.funcs import (
|
|
5
|
-
build_default_service_options,
|
|
6
|
-
create_default_service_dependencies,
|
|
7
|
-
create_default_service_yaml,
|
|
8
|
-
)
|
|
9
4
|
from blok import blok, InitContext, ExecutionContext, Option
|
|
10
5
|
from blok.tree import Repo, YamlFile
|
|
6
|
+
from arkitekt_next.bloks.base import BaseArkitektService
|
|
11
7
|
|
|
12
8
|
|
|
13
9
|
@blok("live.arkitekt.rekuest")
|
|
14
|
-
class RekuestBlok:
|
|
10
|
+
class RekuestBlok(BaseArkitektService):
|
|
15
11
|
def __init__(self) -> None:
|
|
16
12
|
self.dev = False
|
|
17
13
|
self.host = "rekuest"
|
|
@@ -25,29 +21,10 @@ class RekuestBlok:
|
|
|
25
21
|
self.build_repo = False
|
|
26
22
|
self.buckets = ["media"]
|
|
27
23
|
self.secret_key = secrets.token_hex(16)
|
|
28
|
-
self.ensured_repos = []
|
|
29
24
|
self.image = "jhnnsrs/rekuest:next"
|
|
30
25
|
|
|
31
|
-
def get_dependencies(self):
|
|
32
|
-
return create_default_service_dependencies()
|
|
33
|
-
|
|
34
26
|
def get_builder(self):
|
|
35
27
|
return "arkitekt.rekuest"
|
|
36
28
|
|
|
37
|
-
def preflight(self, init: InitContext):
|
|
38
|
-
for key, value in init.kwargs.items():
|
|
39
|
-
setattr(self, key, value)
|
|
40
|
-
|
|
41
|
-
self.service = create_default_service_yaml(init, self)
|
|
42
|
-
|
|
43
|
-
self.initialized = True
|
|
44
|
-
|
|
45
29
|
def build(self, context: ExecutionContext):
|
|
46
30
|
context.docker_compose.set_nested("services", self.host, self.service)
|
|
47
|
-
|
|
48
|
-
def get_options(self):
|
|
49
|
-
def_options = build_default_service_options(self)
|
|
50
|
-
|
|
51
|
-
return [
|
|
52
|
-
*def_options,
|
|
53
|
-
]
|
|
@@ -6,6 +6,7 @@ from typing import Dict, Any, Protocol, Optional
|
|
|
6
6
|
from blok import blok, InitContext, service
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
|
|
9
|
+
|
|
9
10
|
@dataclass
|
|
10
11
|
class DBCredentials:
|
|
11
12
|
password: str
|
|
@@ -17,11 +18,6 @@ class DBCredentials:
|
|
|
17
18
|
dependency: Optional[str] = None
|
|
18
19
|
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
@blok("live.arkitekt.postgres")
|
|
21
|
+
@service("live.arkitekt.postgres")
|
|
22
22
|
class DBService(Protocol):
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
def register_db(self, db_name: str) -> DBCredentials:
|
|
26
|
-
...
|
|
27
|
-
|
|
23
|
+
def register_db(self, db_name: str) -> DBCredentials: ...
|
|
@@ -6,7 +6,7 @@ from typing import Dict, Any, Protocol
|
|
|
6
6
|
from blok import blok, InitContext, service
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
@
|
|
9
|
+
@service("live.arkitekt.gateway")
|
|
10
10
|
class GatewayService(Protocol):
|
|
11
11
|
def expose(
|
|
12
12
|
self, path_name: str, port: int, host: str, strip_prefix: bool = True
|
|
@@ -6,11 +6,8 @@ from typing import Dict, Any, Protocol
|
|
|
6
6
|
from blok import blok, InitContext, service
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
@
|
|
9
|
+
@service("live.arkitekt.docker_socket")
|
|
10
10
|
class DockerSocketService(Protocol):
|
|
11
|
-
|
|
12
11
|
def register_socket(self, name: str) -> str:
|
|
13
12
|
self.registered_configs[name] = name
|
|
14
13
|
return self.docker_socket
|
|
15
|
-
|
|
16
|
-
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: arkitekt-next
|
|
3
|
-
Version: 0.7.
|
|
3
|
+
Version: 0.7.51
|
|
4
4
|
Summary: client for the arkitekt_next platform
|
|
5
5
|
License: MIT
|
|
6
6
|
Author: jhnnsrs
|
|
@@ -16,23 +16,23 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
16
16
|
Provides-Extra: all
|
|
17
17
|
Provides-Extra: blok
|
|
18
18
|
Provides-Extra: cli
|
|
19
|
-
Requires-Dist: blok (>=0.0.
|
|
19
|
+
Requires-Dist: blok (>=0.0.15) ; (python_version >= "3.8" and python_version < "4.0") and (extra == "blok")
|
|
20
20
|
Requires-Dist: cryptography (>=40.0.8) ; (python_version >= "3.8" and python_version < "4.0") and (extra == "blok")
|
|
21
21
|
Requires-Dist: dokker (>=0.1.21)
|
|
22
22
|
Requires-Dist: fakts (>=0.5.0)
|
|
23
|
-
Requires-Dist: fluss-next (>=0.1.
|
|
23
|
+
Requires-Dist: fluss-next (>=0.1.73) ; extra == "all"
|
|
24
24
|
Requires-Dist: herre (>=0.4.3)
|
|
25
|
-
Requires-Dist: kabinet (>=0.1.
|
|
25
|
+
Requires-Dist: kabinet (>=0.1.11) ; (python_version >= "3.9" and python_version < "4.0") and (extra == "all")
|
|
26
26
|
Requires-Dist: koil (>=0.3.6)
|
|
27
|
-
Requires-Dist: mikro-next (>=0.1.
|
|
27
|
+
Requires-Dist: mikro-next (>=0.1.28) ; (python_version >= "3.10" and python_version < "4.0") and (extra == "all")
|
|
28
28
|
Requires-Dist: namegenerator (>=1.0.6) ; (python_version >= "3.8" and python_version < "4.0") and (extra == "blok")
|
|
29
29
|
Requires-Dist: netifaces (>=0.11.0) ; (python_version >= "3.8" and python_version < "4.0") and (extra == "blok")
|
|
30
|
-
Requires-Dist: reaktion-next (>=0.1.
|
|
31
|
-
Requires-Dist: rekuest-next (>=0.2.
|
|
30
|
+
Requires-Dist: reaktion-next (>=0.1.63) ; (python_version >= "3.8" and python_version < "4.0") and (extra == "all")
|
|
31
|
+
Requires-Dist: rekuest-next (>=0.2.18) ; (python_version >= "3.8" and python_version < "4.0") and (extra == "cli" or extra == "all")
|
|
32
32
|
Requires-Dist: rich-click (>=1.6.1) ; extra == "cli" or extra == "all"
|
|
33
33
|
Requires-Dist: semver (>=3.0.1) ; extra == "cli" or extra == "all"
|
|
34
34
|
Requires-Dist: turms (>=0.5.0) ; (python_version >= "3.9" and python_version < "4.0") and (extra == "cli" or extra == "all")
|
|
35
|
-
Requires-Dist: unlok-next (>=0.1.
|
|
35
|
+
Requires-Dist: unlok-next (>=0.1.67) ; python_version >= "3.8" and python_version < "4.0"
|
|
36
36
|
Requires-Dist: watchfiles (>=0.18.1) ; extra == "cli" or extra == "all"
|
|
37
37
|
Description-Content-Type: text/markdown
|
|
38
38
|
|
|
@@ -15,36 +15,36 @@ arkitekt_next/apps/types.py,sha256=cKRqHyKlNcGamPUxzvY0wyz0sEI4sBPa4CnvFnT1sTo,1
|
|
|
15
15
|
arkitekt_next/bloks/__init__.py,sha256=gXny6-WJ3alV1__xveI_0wcvgDuglR1WB7v7-8h1Olo,30
|
|
16
16
|
arkitekt_next/bloks/admin.py,sha256=MlUQUYCHxCWtSD75mVHgs3DcDa0s8_D6_AIBslnYjZw,1300
|
|
17
17
|
arkitekt_next/bloks/arkitekt.py,sha256=N0WcdEr_x2TzDdpIW_WP8lVodYxRbOU4I5IP-aKGLLQ,1417
|
|
18
|
+
arkitekt_next/bloks/base.py,sha256=6gsDc9sVYDqY4El2hhH32QiYHcYUd6eZQRgvhAuY2a0,6341
|
|
18
19
|
arkitekt_next/bloks/config.py,sha256=SqJg9kB0AQ62b_WpIKgJ8Jpcqpc-AKN7gdEj87O-UGY,1268
|
|
19
|
-
arkitekt_next/bloks/fluss.py,sha256=
|
|
20
|
-
arkitekt_next/bloks/funcs.py,sha256=IdiMNUkQN5frHpgsiXJJfJib1lFhUEVwGYjJugpSlds,5350
|
|
20
|
+
arkitekt_next/bloks/fluss.py,sha256=b9hBV0nMy_0ctQIEQntGGaee3oDZy1lQKO1Eacc0zVs,997
|
|
21
21
|
arkitekt_next/bloks/gateway.py,sha256=Qfw_SkJbyMe5GrZ8YJaaLVyZ2ZlKpacJjUFLBk97vbg,6692
|
|
22
22
|
arkitekt_next/bloks/internal_docker.py,sha256=4jhKwfVKPCZzhkuEVq1iw4gIpc6_R0Cco-_s0L8PiZI,2891
|
|
23
|
-
arkitekt_next/bloks/kabinet.py,sha256=
|
|
23
|
+
arkitekt_next/bloks/kabinet.py,sha256=a_NA9psOvwypZm_FqIs3Yn6L-G1R8EMOUApJMSiBnPA,1432
|
|
24
24
|
arkitekt_next/bloks/livekit.py,sha256=yhre3PkIQwKGdGPFC-DhTID3rIbRQMts_UsAX9tw6-A,2561
|
|
25
|
-
arkitekt_next/bloks/lok.py,sha256
|
|
26
|
-
arkitekt_next/bloks/mikro.py,sha256=
|
|
25
|
+
arkitekt_next/bloks/lok.py,sha256=-OoCFzf2ci8sBrYBnnmni-cJoAxuynUSj0kzWYpJznw,11444
|
|
26
|
+
arkitekt_next/bloks/mikro.py,sha256=r7wc56pvFkPkxigx70xEu31dgpO6q3TviDQUM9oyQwM,1223
|
|
27
27
|
arkitekt_next/bloks/minio.py,sha256=k7t1J46lO3eaBO9KdP7iYF--Go-m25dEmOwisbbOoVQ,5496
|
|
28
28
|
arkitekt_next/bloks/mount.py,sha256=d14w7bMiaWbl5wgvanh4PwfIqEYsDEsw91360xfX0fU,1031
|
|
29
29
|
arkitekt_next/bloks/namegen.py,sha256=0k4PYya5J4EQyt3XZ3UKhDlO_k29pmUEQSaklZGN8MA,1035
|
|
30
|
-
arkitekt_next/bloks/orkestrator.py,sha256=
|
|
30
|
+
arkitekt_next/bloks/orkestrator.py,sha256=26dEhBqlKP_ujM1bNyFiuXiy2Fl-yhwwsJjYcsoAo60,2078
|
|
31
31
|
arkitekt_next/bloks/postgres.py,sha256=FRUF2fobUlU6OmK1VC7aN_WuX1NctLmZhzJJA1uOOeY,2773
|
|
32
32
|
arkitekt_next/bloks/redis.py,sha256=_ddmcD3WwX7VA7zzzQ7-yjSM7f4reV0C8Pl70s7R2k8,2130
|
|
33
|
-
arkitekt_next/bloks/rekuest.py,sha256=
|
|
33
|
+
arkitekt_next/bloks/rekuest.py,sha256=6mxRK1M5ua14rEeF2Wr0QjqV0eUgOLvdDJAuDpRDRUk,993
|
|
34
34
|
arkitekt_next/bloks/secret.py,sha256=P4Z56FhcgVD0KbokhcMNAXwDjo_86rI99nWh3gUGXSQ,1014
|
|
35
35
|
arkitekt_next/bloks/services/__init__.py,sha256=i9vGNd1lFBem3O2PblTouRzFVQkdwOYoUmqqU43dIWQ,592
|
|
36
36
|
arkitekt_next/bloks/services/admin.py,sha256=OXMAHph5lABNPFsXm8aboWffJ7CzSSNvke7xpmj9raI,463
|
|
37
37
|
arkitekt_next/bloks/services/config.py,sha256=BLtbKXRRWmuZxvaaksuxt9EiDcazYwKL_IUIRhXBin8,393
|
|
38
|
-
arkitekt_next/bloks/services/db.py,sha256=
|
|
39
|
-
arkitekt_next/bloks/services/gateway.py,sha256=
|
|
38
|
+
arkitekt_next/bloks/services/db.py,sha256=Lc8uL8xibz99-16YPxtB_ls6CP3dN_jCaOzJ9uZ8b_0,588
|
|
39
|
+
arkitekt_next/bloks/services/gateway.py,sha256=X7ghhLXZ9hDQIMXMTkfBMcS9o9oc16y0C-b_3r3uwCo,847
|
|
40
40
|
arkitekt_next/bloks/services/livekit.py,sha256=5u-GThgKsgXiiobEL4arm3JJOgNTZae15Q-75i-4D8g,366
|
|
41
41
|
arkitekt_next/bloks/services/lok.py,sha256=fzOGum0VmcVaONUhTv4jHYky4WrFq2ygDAYJjBv2vAI,500
|
|
42
42
|
arkitekt_next/bloks/services/mount.py,sha256=MDlwHl5cTfBO8IgkofuFjQBbfIMKDm_R9suWkiyVG48,289
|
|
43
43
|
arkitekt_next/bloks/services/name.py,sha256=ZMDlZwnSaoIUj7STlpFo32nHKMuOibKzetYWSjh-t-c,254
|
|
44
|
-
arkitekt_next/bloks/services/redis.py,sha256=
|
|
44
|
+
arkitekt_next/bloks/services/redis.py,sha256=W9CraIZJztFE1vQVCfxCxY4T_gBPRTM84VwFR8Hwtp8,472
|
|
45
45
|
arkitekt_next/bloks/services/s3.py,sha256=_mk_9NdaeHRVZ__1M9CL1Ec1gSQKkzlOiQXse7MSx94,485
|
|
46
46
|
arkitekt_next/bloks/services/secret.py,sha256=iUG1ZH_dR0tL48rueNOK2ILjEnyqNJjQCY-4KKrB_Zg,342
|
|
47
|
-
arkitekt_next/bloks/services/socket.py,sha256=
|
|
47
|
+
arkitekt_next/bloks/services/socket.py,sha256=3MbENiJrwQbFKrpWxax56F24elnSD7S-olgycfuOX7s,423
|
|
48
48
|
arkitekt_next/bloks/socket.py,sha256=YIrSKfQezrsKwRKDPdT1aXhlQzjgnx_UaNaQ9LiEfGY,1008
|
|
49
49
|
arkitekt_next/bloks/tailscale.py,sha256=IkMBA1CwslMTOF1m2UUmE6qH_gbaEet2eXsPDgBxcew,2915
|
|
50
50
|
arkitekt_next/builders.py,sha256=8HeQsNqyxpbFsnTrA9AAm0_BqxGjU1_ylS1Z-hbjAFw,6074
|
|
@@ -136,8 +136,8 @@ arkitekt_next/qt/utils.py,sha256=MgBPtPmCSBkIuATov3UgREESwxAHh77lWNNxyE7Qs48,773
|
|
|
136
136
|
arkitekt_next/service_registry.py,sha256=pczUuP_Nve7OYwB7-oDBLIw6bkjZPnzL3xFca5TF1io,3405
|
|
137
137
|
arkitekt_next/tqdm.py,sha256=DlrxPluHao7TvW-Cqgt0UokRS-fM2_ZNiWiddqvCqCc,1488
|
|
138
138
|
arkitekt_next/utils.py,sha256=gmKWy9M51vimohmmaoIpAJ0CaB22TFP0w3JszRrwiak,2379
|
|
139
|
-
arkitekt_next-0.7.
|
|
140
|
-
arkitekt_next-0.7.
|
|
141
|
-
arkitekt_next-0.7.
|
|
142
|
-
arkitekt_next-0.7.
|
|
143
|
-
arkitekt_next-0.7.
|
|
139
|
+
arkitekt_next-0.7.51.dist-info/LICENSE,sha256=YZ2oRjC248t-GpoEyw7J13vwKYNG6zhYMaEAix6EzF0,1089
|
|
140
|
+
arkitekt_next-0.7.51.dist-info/METADATA,sha256=2ZYi33bz7qSRGM8nwbp19YaZ68Olpr2aOKjs_mPK6-c,5975
|
|
141
|
+
arkitekt_next-0.7.51.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
142
|
+
arkitekt_next-0.7.51.dist-info/entry_points.txt,sha256=-hxikQx4xZ6TiOnWVDOlTN_kcAISgGFvTHXIchsCHSc,60
|
|
143
|
+
arkitekt_next-0.7.51.dist-info/RECORD,,
|
arkitekt_next/bloks/funcs.py
DELETED
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
from blok import blok, InitContext, Option
|
|
2
|
-
from blok.tree import YamlFile, Repo
|
|
3
|
-
from typing import Any, Protocol
|
|
4
|
-
from blok.utils import check_protocol_compliance
|
|
5
|
-
from dataclasses import asdict
|
|
6
|
-
from arkitekt_next.bloks.services import (
|
|
7
|
-
GatewayService,
|
|
8
|
-
DBService,
|
|
9
|
-
RedisService,
|
|
10
|
-
S3Service,
|
|
11
|
-
ConfigService,
|
|
12
|
-
MountService,
|
|
13
|
-
AdminService,
|
|
14
|
-
SecretService,
|
|
15
|
-
LokService,
|
|
16
|
-
)
|
|
17
|
-
|
|
18
|
-
from blok.bloks.services.dns import DnsService
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class DefaultService(Protocol):
|
|
22
|
-
dev: bool
|
|
23
|
-
repo: str
|
|
24
|
-
command: str
|
|
25
|
-
service_name: str
|
|
26
|
-
host: str
|
|
27
|
-
buckets: list[str]
|
|
28
|
-
scopes: dict[str, str]
|
|
29
|
-
secret_key: str
|
|
30
|
-
mount_repo: bool
|
|
31
|
-
build_repo: bool
|
|
32
|
-
|
|
33
|
-
def get_identifier(self) -> str: ...
|
|
34
|
-
|
|
35
|
-
def get_builder(self) -> str: ...
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def create_default_service_dependencies():
|
|
39
|
-
return [
|
|
40
|
-
DnsService,
|
|
41
|
-
GatewayService,
|
|
42
|
-
DBService,
|
|
43
|
-
RedisService,
|
|
44
|
-
S3Service,
|
|
45
|
-
ConfigService,
|
|
46
|
-
MountService,
|
|
47
|
-
AdminService,
|
|
48
|
-
SecretService,
|
|
49
|
-
LokService,
|
|
50
|
-
]
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def build_default_service_options(self: DefaultService) -> list[Option]:
|
|
54
|
-
return [
|
|
55
|
-
Option(
|
|
56
|
-
subcommand="dev",
|
|
57
|
-
help="Shoud we run the service in development mode (includes withrepo, mountrepo)?",
|
|
58
|
-
default=self.dev,
|
|
59
|
-
),
|
|
60
|
-
Option(
|
|
61
|
-
subcommand="disable",
|
|
62
|
-
help="Shoud we disable the service?",
|
|
63
|
-
default=False,
|
|
64
|
-
),
|
|
65
|
-
Option(
|
|
66
|
-
subcommand="with_repo",
|
|
67
|
-
help="Which repo should we use when building the service? Only active if build_repo or mount_repo is active",
|
|
68
|
-
default=self.repo,
|
|
69
|
-
),
|
|
70
|
-
Option(
|
|
71
|
-
subcommand="with_command",
|
|
72
|
-
help="Which command should we use when building the service?",
|
|
73
|
-
default=self.command,
|
|
74
|
-
),
|
|
75
|
-
Option(
|
|
76
|
-
subcommand="mount_repo",
|
|
77
|
-
help="Should we mount the repo into the container?",
|
|
78
|
-
type=bool,
|
|
79
|
-
default=self.mount_repo,
|
|
80
|
-
),
|
|
81
|
-
Option(
|
|
82
|
-
subcommand="build_repo",
|
|
83
|
-
help="Should we build the container from the repo?",
|
|
84
|
-
type=bool,
|
|
85
|
-
default=self.build_repo,
|
|
86
|
-
),
|
|
87
|
-
Option(
|
|
88
|
-
subcommand="host",
|
|
89
|
-
help="How should the service be named inside the docker-compose file?",
|
|
90
|
-
default=self.host,
|
|
91
|
-
),
|
|
92
|
-
Option(
|
|
93
|
-
subcommand="secret_key",
|
|
94
|
-
help="The secret key to use for the django service",
|
|
95
|
-
default=self.secret_key,
|
|
96
|
-
),
|
|
97
|
-
]
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
def create_default_service_yaml(
|
|
101
|
-
init: InitContext,
|
|
102
|
-
self: DefaultService,
|
|
103
|
-
additional_keys: dict[str, Any] = None,
|
|
104
|
-
) -> YamlFile:
|
|
105
|
-
check_protocol_compliance(self, DefaultService)
|
|
106
|
-
deps = init.dependencies
|
|
107
|
-
additional_keys = additional_keys or {}
|
|
108
|
-
|
|
109
|
-
init.get_service(LokService).register_scopes(self.scopes)
|
|
110
|
-
|
|
111
|
-
path_name = self.host
|
|
112
|
-
|
|
113
|
-
gateway_access = init.get_service(GatewayService).expose(path_name, 80, self.host)
|
|
114
|
-
|
|
115
|
-
postgress_access = init.get_service(DBService).register_db(self.host)
|
|
116
|
-
redis_access = init.get_service(RedisService).register()
|
|
117
|
-
lok_access = init.get_service(LokService).retrieve_credentials()
|
|
118
|
-
admin_access = init.get_service(AdminService).retrieve()
|
|
119
|
-
minio_access = init.get_service(S3Service).create_buckets(self.buckets)
|
|
120
|
-
lok_labels = init.get_service(LokService).retrieve_labels(
|
|
121
|
-
self.get_identifier(), self.get_builder()
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
dns_result = init.get_service(DnsService).get_dns_result()
|
|
125
|
-
|
|
126
|
-
csrf_trusted_origins = []
|
|
127
|
-
for hostname in dns_result.hostnames:
|
|
128
|
-
csrf_trusted_origins.append(f"http://{hostname}")
|
|
129
|
-
csrf_trusted_origins.append(f"https://{hostname}")
|
|
130
|
-
|
|
131
|
-
configuration = YamlFile(
|
|
132
|
-
**{
|
|
133
|
-
"db": asdict(postgress_access),
|
|
134
|
-
"django": {
|
|
135
|
-
"admin": asdict(admin_access),
|
|
136
|
-
"debug": True,
|
|
137
|
-
"hosts": ["*"],
|
|
138
|
-
"secret_key": self.secret_key,
|
|
139
|
-
},
|
|
140
|
-
"redis": asdict(redis_access),
|
|
141
|
-
"lok": asdict(lok_access),
|
|
142
|
-
"s3": asdict(minio_access),
|
|
143
|
-
"scopes": self.scopes,
|
|
144
|
-
"force_script_name": path_name,
|
|
145
|
-
"csrf_trusted_origins": csrf_trusted_origins,
|
|
146
|
-
**additional_keys,
|
|
147
|
-
}
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
config_mount = init.get_service(ConfigService).register_config(
|
|
151
|
-
f"{self.host}.yaml", configuration
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
depends_on = []
|
|
155
|
-
|
|
156
|
-
if redis_access.dependency:
|
|
157
|
-
depends_on.append(redis_access.dependency)
|
|
158
|
-
|
|
159
|
-
if postgress_access.dependency:
|
|
160
|
-
depends_on.append(postgress_access.dependency)
|
|
161
|
-
|
|
162
|
-
if minio_access.dependency:
|
|
163
|
-
depends_on.append(minio_access.dependency)
|
|
164
|
-
|
|
165
|
-
service = {
|
|
166
|
-
"labels": lok_labels,
|
|
167
|
-
"volumes": [f"{config_mount}:/workspace/config.yaml"],
|
|
168
|
-
"depends_on": depends_on,
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
if self.mount_repo or self.dev:
|
|
172
|
-
mount = init.get_service(MountService).register_mount(
|
|
173
|
-
self.host, Repo(self.repo)
|
|
174
|
-
)
|
|
175
|
-
service["volumes"].extend([f"{mount}:/workspace"])
|
|
176
|
-
|
|
177
|
-
if self.build_repo or self.dev:
|
|
178
|
-
mount = init.get_service(MountService).register_mount(
|
|
179
|
-
self.host, Repo(self.repo)
|
|
180
|
-
)
|
|
181
|
-
service["build"] = mount
|
|
182
|
-
else:
|
|
183
|
-
service["image"] = self.image
|
|
184
|
-
|
|
185
|
-
service["command"] = self.command
|
|
186
|
-
|
|
187
|
-
return service
|
|
File without changes
|
|
File without changes
|
|
File without changes
|