-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
31 changed files
with
777 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
name: generic | ||
services: | ||
lok: lok_next | ||
rekuest: rekuest_next | ||
fluss: fluss_next |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
endpoint_url: "{{"https" if request.is_secure else "http" }}://{{"fluss" if request.host == "lok" else request.host + ":11090"}}/graphql" | ||
healthz: "{{"https" if request.is_secure else "http" }}://{{"fluss" if request.host == "lok" else request.host + ":11090"}}/ht" | ||
ws_endpoint_url: "{{"wss" if request.is_secure else "ws" }}://{{"fluss" if request.host == "lok" else request.host + ":11090"}}/graphql" | ||
__service: "live.arkitekt.fluss" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
base_url: "{{"https" if request.is_secure else "http" }}://{{"lok" if request.host == "lok" else request.host + ":12000"}}/o" | ||
userinfo_url: "{{"https" if request.is_secure else "http" }}://{{"lok" if request.host == "lok" else request.host + ":12000"}}/o/userinfo" | ||
endpoint_url: "{{"https" if request.is_secure else "http" }}://{{"lok" if request.host == "lok" else request.host + ":12000"}}/graphql" | ||
healthz: "{{"https" if request.is_secure else "http" }}://{{"lok" if request.host == "lok" else request.host + ":12000"}}/ht" | ||
secure: false | ||
ws_endpoint_url: "{{"wss" if request.is_secure else "ws" }}://{{"lok" if request.host == "lok" else request.host + ":12000"}}/graphql" | ||
client_id: "{{client.client_id}}" | ||
client_secret: "{{client.client_secret}}" | ||
grant_type: "{{client.authorization_grant_type}}" | ||
name: "{{client.name}}" | ||
scopes: | ||
{% for item in manifest.scopes %} | ||
- {{item}} | ||
{% endfor %} | ||
__service: "live.arkitekt.lok" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
agent: | ||
endpoint_url: "{{"wss" if request.is_secure else "ws" }}://{{"rekuest" if request.host == "lok" else request.host + ":11020"}}/agi" | ||
endpoint_url: "{{"https" if request.is_secure else "http" }}://{{"rekuest" if request.host == "lok" else request.host + ":11020"}}/graphql" | ||
healthz: "{{"https" if request.is_secure else "http" }}://{{"rekuest" if request.host == "lok" else request.host + ":11020"}}/ht" | ||
ws_endpoint_url: "{{"wss" if request.is_secure else "ws" }}://{{"rekuest" if request.host == "lok" else request.host + ":11020"}}/graphql" | ||
__service: "live.arkitekt.rekuest-next" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
key: fluss | ||
description: "The Next generation fluss" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
key: lok | ||
description: "The Next generation Lok" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
key: rekuest_next | ||
description: "The best service to have ever lived" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from .backend import ConfigBackend | ||
|
||
__all__ = ["ConfigBackend"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,164 @@ | ||
from fakts.backends.backend_registry import BackendBase, InstanceDescriptor, CompositionDescriptor, InstanceMap, ServiceDescriptor | ||
from fakts.base_models import LinkingContext, LinkingRequest, Manifest, LinkingClient | ||
from typing import Dict, Any | ||
from pathlib import Path | ||
import yaml | ||
from jinja2 import Template, TemplateSyntaxError, TemplateError | ||
|
||
|
||
class ConfigBackend(BackendBase): | ||
""" | ||
This class is used to store the configuration of the server. It is | ||
responsible for reading and writing the configuration to the file system. | ||
""" | ||
|
||
def __init__(self, config: dict) -> None: | ||
self.config = config | ||
self.service_dir = Path(self.config.get("SERVICE_DIR", "/workspace/config_backend/services")) | ||
self.instance_dr = Path(self.config.get("INSTANCE_DIR", "/workspace/config_backend/instances")) | ||
self.composition_dir = Path(self.config.get("COMPOSITION_DIR", "/workspace/config_backend/compositions")) | ||
|
||
assert self.service_dir.exists(), f"Service directory {self.service_dir} does not exist" | ||
assert self.composition_dir.exists(), f"Composition directory {self.composition_dir} does not exist" | ||
|
||
|
||
self.loaded_services = self._load_services() | ||
print(self.loaded_services) | ||
|
||
self.loaded_instances = self._load_instances() | ||
print(self.loaded_instances) | ||
|
||
self.loaded_compositions = self._load_compositions() | ||
print(self.loaded_compositions) | ||
|
||
|
||
def _load_instances(self) -> dict[str, InstanceDescriptor]: | ||
instances = {} | ||
|
||
for instance_file in self.instance_dr.iterdir(): | ||
if instance_file.is_file(): | ||
instances[instance_file.stem] = self.retrieve_instance(instance_file) | ||
|
||
return instances | ||
|
||
def _load_services(self) -> dict[str, ServiceDescriptor]: | ||
instances = {} | ||
|
||
for service_file in self.service_dir.iterdir(): | ||
if service_file.is_file(): | ||
instances[service_file.stem] = self.retrieve_serve(service_file) | ||
|
||
return instances | ||
|
||
def _load_compositions(self) -> dict[str, CompositionDescriptor]: | ||
|
||
compositions = {} | ||
|
||
for composition_file in self.composition_dir.iterdir(): | ||
if composition_file.is_file(): | ||
compositions[composition_file.stem] = self.retrieve_composition(composition_file) | ||
|
||
return compositions | ||
|
||
|
||
def retrieve_composition(self, composition_file: Path) -> CompositionDescriptor: | ||
with open(composition_file, "r") as file: | ||
context = yaml.load(file.read(), Loader=yaml.SafeLoader) | ||
|
||
assert context.get("name"), f"Composition file {composition_file} does not contain a name" | ||
assert context.get("services"), f"Composition file {composition_file} does not contain any services" | ||
|
||
service_dict = {} | ||
|
||
for service_name, instance_name in context.get("services").items(): | ||
assert self.loaded_instances.get(instance_name), f"Composition file {composition_file} contains an unknown service instance {instance_name}" | ||
service_dict[service_name] = InstanceMap(instance_identifier=instance_name, backend_identifier=self.get_name()) | ||
|
||
return CompositionDescriptor( | ||
name=context.get("name"), | ||
services=service_dict | ||
) | ||
|
||
def retrieve_serve(self, service_file: Path) -> ServiceDescriptor: | ||
with open(service_file, "r") as file: | ||
context = yaml.load(file.read(), Loader=yaml.SafeLoader) | ||
|
||
assert context.get("key"), f"Service file {service_file} does not contain a key" | ||
|
||
|
||
return ServiceDescriptor( | ||
identifier=service_file.stem, | ||
key=context.get("key"), | ||
logo=context.get("logo"), | ||
description=context.get("description"), | ||
) | ||
|
||
|
||
|
||
def retrieve_instance(self, service_file: Path) -> InstanceDescriptor: | ||
with open(service_file, "r") as file: | ||
template = file.read() | ||
|
||
|
||
fake_context = LinkingContext( | ||
request=LinkingRequest( | ||
host="example.com", | ||
port="443", | ||
is_secure=True, | ||
), | ||
manifest=Manifest( | ||
identifier="com.example.app", | ||
version="1.0", | ||
scopes=["scope1", "scope2"], | ||
redirect_uris=["https://example.com"], | ||
), | ||
client=LinkingClient( | ||
client_id="@client_id", | ||
client_secret="@client_secret", | ||
client_type="@client_type", | ||
authorization_grant_type="authorization_grant_type", | ||
name="@name", | ||
), | ||
) | ||
|
||
|
||
result = yaml.load(Template(template).render(fake_context), Loader=yaml.SafeLoader) | ||
|
||
assert result.get("__service"), f"Service file {service_file} does not contain an service identifier (\"__service\")" | ||
|
||
return InstanceDescriptor( | ||
backend_identifier=self.get_name(), | ||
instance_identifier=service_file.stem, | ||
service_identifier=result.get("__service"), | ||
) | ||
|
||
|
||
|
||
|
||
def render(self, instance_id: str, linking: LinkingContext) -> Dict[str, Any]: | ||
with open(self.instance_dr / f"{instance_id}.yaml", "r") as file: | ||
template = file.read() | ||
|
||
answer = yaml.load(Template(template).render(linking.dict()), Loader=yaml.SafeLoader) | ||
print(answer) | ||
return answer | ||
|
||
|
||
|
||
|
||
@classmethod | ||
def get_name(cls) -> str: | ||
return cls.__name__ | ||
|
||
|
||
def get_service_descriptors(self) -> list[ServiceDescriptor]: | ||
return self.loaded_services.values() | ||
|
||
def get_instance_descriptors(self) -> list[InstanceDescriptor]: | ||
return self.loaded_instances.values() | ||
|
||
def get_composition_descriptors(self) -> list[CompositionDescriptor]: | ||
return self.loaded_compositions.values() | ||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
from django.core.exceptions import ValidationError | ||
from fakts.base_models import LinkingContext, LinkingRequest, Manifest, LinkingClient | ||
from jinja2 import Template, TemplateSyntaxError, TemplateError, StrictUndefined | ||
import yaml | ||
|
||
def is_valid_jinja2_template(template_string, render_context=None): | ||
""" Checks if a template string is a valid Jinja2 template. And if it is, | ||
it checks if it is a valid YAML file, wher rendered with a fakt context If it is not, it raises a ValueError""" | ||
try: | ||
template = Template(template_string, undefined=StrictUndefined) | ||
try: | ||
rendered_template = template.render(render_context ) | ||
yaml.safe_load(rendered_template) | ||
except (TemplateError, yaml.YAMLError) as e: | ||
raise ValueError(f"Rendering error: {e}") from e | ||
except TemplateSyntaxError as e: | ||
raise ValueError(f"Template syntax error: {e}") from e | ||
|
||
|
||
|
||
def jinja2_yaml_template_validator(value): | ||
""" Validates that a string is a valid Jinja2 template. And if it is, | ||
it checks if it is a valid YAML file, wher rendered with a fakt context If it is not, it raises a ValidationError | ||
""" | ||
|
||
|
||
fake_context = LinkingContext( | ||
request=LinkingRequest( | ||
host="example.com", | ||
port="443", | ||
is_secure=True, | ||
), | ||
manifest=Manifest( | ||
identifier="com.example.app", | ||
version="1.0", | ||
scopes=["scope1", "scope2"], | ||
redirect_uris=["https://example.com"], | ||
), | ||
client=LinkingClient( | ||
client_id="@client_id", | ||
client_secret="@client_secret", | ||
client_type="@client_type", | ||
authorization_grant_type="authorization_grant_type", | ||
name="@name", | ||
), | ||
) | ||
|
||
|
||
try: | ||
is_valid_jinja2_template(value, fake_context.dict()) | ||
except ValidationError as e: | ||
raise ValueError(e) | ||
|
||
return value | ||
|
||
|
||
def fake_load_yaml(value): | ||
""" Loads a string as a YAML file. If it is not a valid YAML file, it raises a ValidationError""" | ||
|
||
|
||
|
||
try: | ||
return yaml.safe_load(value) | ||
except yaml.YAMLError as e: | ||
raise ValidationError(f"YAML error: {e}") from e |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
from fakts.backends.backend_registry import BackendBase, InstanceDescriptor, CompositionDescriptor, ServiceDescriptor | ||
from typing import Dict, Any | ||
from fakts.base_models import LinkingContext | ||
|
||
|
||
class DockerBackend(BackendBase): | ||
""" | ||
This class is used to store the configuration of the server. It is | ||
responsible for reading and writing the configuration to the file system. | ||
""" | ||
|
||
def __init__(self, config_file): | ||
self.config_file = config_file | ||
|
||
@classmethod | ||
def get_name(cls) -> str: | ||
return cls.__name__ | ||
|
||
def render(cls, service_instance: str, context: LinkingContext) -> Dict[str, Any]: | ||
pass | ||
|
||
def get_instance_descriptors(cls) -> list[InstanceDescriptor]: | ||
return [] | ||
|
||
def get_composition_descriptors(self) -> list[CompositionDescriptor]: | ||
return [] | ||
|
||
def get_service_descriptors(self) -> list[ServiceDescriptor]: | ||
return [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Oops, something went wrong.