2025-04-22 20:21:38 +01:00
|
|
|
|
2025-07-30 23:18:38 +01:00
|
|
|
import logging
|
|
|
|
|
|
2025-04-22 20:21:38 +01:00
|
|
|
from trustgraph.schema import ConfigResponse
|
|
|
|
|
from trustgraph.schema import ConfigValue, Error
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
from ... tables.config import ConfigTableStore
|
2025-04-22 20:21:38 +01:00
|
|
|
|
2025-07-30 23:18:38 +01:00
|
|
|
# Module logger
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
class ConfigurationClass:
|
|
|
|
|
|
|
|
|
|
async def keys(self):
|
|
|
|
|
return await self.table_store.get_keys(self.type)
|
|
|
|
|
|
|
|
|
|
async def values(self):
|
|
|
|
|
vals = await self.table_store.get_values(self.type)
|
|
|
|
|
return {
|
|
|
|
|
v[0]: v[1]
|
|
|
|
|
for v in vals
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async def get(self, key):
|
|
|
|
|
return await self.table_store.get_value(self.type, key)
|
|
|
|
|
|
|
|
|
|
async def put(self, key, value):
|
|
|
|
|
return await self.table_store.put_config(self.type, key, value)
|
|
|
|
|
|
|
|
|
|
async def delete(self, key):
|
|
|
|
|
return await self.table_store.delete_key(self.type, key)
|
|
|
|
|
|
|
|
|
|
async def has(self, key):
|
|
|
|
|
val = await self.table_store.get_value(self.type, key)
|
|
|
|
|
return val is not None
|
|
|
|
|
|
|
|
|
|
class Configuration:
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
# FIXME: The state is held internally. This only works if there's
|
|
|
|
|
# one config service. Should be more than one, and use a
|
|
|
|
|
# back-end state store.
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
# FIXME: This has state now, but does it address all of the above?
|
|
|
|
|
# REVIEW: Above
|
|
|
|
|
|
|
|
|
|
# FIXME: Some version vs config race conditions
|
2025-04-22 20:21:38 +01:00
|
|
|
|
2025-09-04 00:58:11 +01:00
|
|
|
def __init__(self, push, host, username, password, keyspace):
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
# External function to respond to update
|
|
|
|
|
self.push = push
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
self.table_store = ConfigTableStore(
|
2025-09-04 00:58:11 +01:00
|
|
|
host, username, password, keyspace
|
2025-05-07 12:58:32 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
async def inc_version(self):
|
|
|
|
|
await self.table_store.inc_version()
|
|
|
|
|
|
|
|
|
|
async def get_version(self):
|
|
|
|
|
return await self.table_store.get_version()
|
|
|
|
|
|
|
|
|
|
def get(self, type):
|
|
|
|
|
|
|
|
|
|
c = ConfigurationClass()
|
|
|
|
|
c.table_store = self.table_store
|
|
|
|
|
c.type = type
|
|
|
|
|
|
|
|
|
|
return c
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
async def handle_get(self, v):
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
# for k in v.keys:
|
|
|
|
|
# if k.type not in self or k.key not in self[k.type]:
|
|
|
|
|
# return ConfigResponse(
|
|
|
|
|
# version = None,
|
|
|
|
|
# values = None,
|
|
|
|
|
# directory = None,
|
|
|
|
|
# config = None,
|
|
|
|
|
# error = Error(
|
|
|
|
|
# type = "key-error",
|
|
|
|
|
# message = f"Key error"
|
|
|
|
|
# )
|
|
|
|
|
# )
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
values = [
|
|
|
|
|
ConfigValue(
|
|
|
|
|
type = k.type,
|
|
|
|
|
key = k.key,
|
2025-05-07 12:58:32 +01:00
|
|
|
value = await self.table_store.get_value(k.type, k.key)
|
2025-04-22 20:21:38 +01:00
|
|
|
)
|
|
|
|
|
for k in v.keys
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
return ConfigResponse(
|
2025-05-07 12:58:32 +01:00
|
|
|
version = await self.get_version(),
|
2025-04-22 20:21:38 +01:00
|
|
|
values = values,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
async def handle_list(self, v):
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
# if v.type not in self:
|
2025-04-22 20:21:38 +01:00
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
# return ConfigResponse(
|
|
|
|
|
# version = None,
|
|
|
|
|
# values = None,
|
|
|
|
|
# directory = None,
|
|
|
|
|
# config = None,
|
|
|
|
|
# error = Error(
|
|
|
|
|
# type = "key-error",
|
|
|
|
|
# message = "No such type",
|
|
|
|
|
# ),
|
|
|
|
|
# )
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
return ConfigResponse(
|
2025-05-07 12:58:32 +01:00
|
|
|
version = await self.get_version(),
|
|
|
|
|
directory = await self.table_store.get_keys(v.type),
|
2025-04-22 20:21:38 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
async def handle_getvalues(self, v):
|
|
|
|
|
|
2025-05-08 00:41:45 +01:00
|
|
|
# if v.type not in self:
|
2025-04-22 20:21:38 +01:00
|
|
|
|
2025-05-08 00:41:45 +01:00
|
|
|
# return ConfigResponse(
|
|
|
|
|
# version = None,
|
|
|
|
|
# values = None,
|
|
|
|
|
# directory = None,
|
|
|
|
|
# config = None,
|
|
|
|
|
# error = Error(
|
|
|
|
|
# type = "key-error",
|
|
|
|
|
# message = f"Key error"
|
|
|
|
|
# )
|
|
|
|
|
# )
|
|
|
|
|
|
|
|
|
|
vals = await self.table_store.get_values(v.type)
|
2025-05-07 12:58:32 +01:00
|
|
|
|
|
|
|
|
values = map(
|
|
|
|
|
lambda x: ConfigValue(
|
|
|
|
|
type = v.type, key = x[0], value = x[1]
|
|
|
|
|
),
|
2025-05-08 00:41:45 +01:00
|
|
|
vals
|
2025-05-07 12:58:32 +01:00
|
|
|
)
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
return ConfigResponse(
|
2025-05-07 12:58:32 +01:00
|
|
|
version = await self.get_version(),
|
2025-05-08 00:41:45 +01:00
|
|
|
values = list(values),
|
2025-04-22 20:21:38 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
async def handle_delete(self, v):
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
# for k in v.keys:
|
|
|
|
|
# if k.type not in self or k.key not in self[k.type]:
|
|
|
|
|
# return ConfigResponse(
|
|
|
|
|
# version = None,
|
|
|
|
|
# values = None,
|
|
|
|
|
# directory = None,
|
|
|
|
|
# config = None,
|
|
|
|
|
# error = Error(
|
|
|
|
|
# type = "key-error",
|
|
|
|
|
# message = f"Key error"
|
|
|
|
|
# )
|
|
|
|
|
# )
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
for k in v.keys:
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
await self.table_store.delete_key(k.type, k.key)
|
|
|
|
|
|
|
|
|
|
await self.inc_version()
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
await self.push()
|
|
|
|
|
|
|
|
|
|
return ConfigResponse(
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
async def handle_put(self, v):
|
|
|
|
|
|
|
|
|
|
for k in v.values:
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
await self.table_store.put_config(k.type, k.key, k.value)
|
|
|
|
|
|
|
|
|
|
await self.inc_version()
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
await self.push()
|
|
|
|
|
|
|
|
|
|
return ConfigResponse(
|
|
|
|
|
)
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
async def get_config(self):
|
|
|
|
|
|
|
|
|
|
table = await self.table_store.get_all()
|
|
|
|
|
|
|
|
|
|
config = {}
|
|
|
|
|
|
|
|
|
|
for row in table:
|
|
|
|
|
if row[0] not in config:
|
|
|
|
|
config[row[0]] = {}
|
|
|
|
|
config[row[0]][row[1]] = row[2]
|
|
|
|
|
|
|
|
|
|
return config
|
|
|
|
|
|
2025-04-22 20:21:38 +01:00
|
|
|
async def handle_config(self, v):
|
|
|
|
|
|
2025-05-07 12:58:32 +01:00
|
|
|
config = await self.get_config()
|
|
|
|
|
|
2025-04-22 20:21:38 +01:00
|
|
|
return ConfigResponse(
|
2025-05-07 12:58:32 +01:00
|
|
|
version = await self.get_version(),
|
|
|
|
|
config = config,
|
2025-04-22 20:21:38 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
async def handle(self, msg):
|
|
|
|
|
|
2025-07-30 23:18:38 +01:00
|
|
|
logger.debug(f"Handling config message: {msg.operation}")
|
2025-04-22 20:21:38 +01:00
|
|
|
|
|
|
|
|
if msg.operation == "get":
|
|
|
|
|
|
|
|
|
|
resp = await self.handle_get(msg)
|
|
|
|
|
|
|
|
|
|
elif msg.operation == "list":
|
|
|
|
|
|
|
|
|
|
resp = await self.handle_list(msg)
|
|
|
|
|
|
|
|
|
|
elif msg.operation == "getvalues":
|
|
|
|
|
|
|
|
|
|
resp = await self.handle_getvalues(msg)
|
|
|
|
|
|
|
|
|
|
elif msg.operation == "delete":
|
|
|
|
|
|
|
|
|
|
resp = await self.handle_delete(msg)
|
|
|
|
|
|
|
|
|
|
elif msg.operation == "put":
|
|
|
|
|
|
|
|
|
|
resp = await self.handle_put(msg)
|
|
|
|
|
|
|
|
|
|
elif msg.operation == "config":
|
|
|
|
|
|
|
|
|
|
resp = await self.handle_config(msg)
|
|
|
|
|
|
|
|
|
|
else:
|
|
|
|
|
|
|
|
|
|
resp = ConfigResponse(
|
|
|
|
|
error=Error(
|
|
|
|
|
type = "bad-operation",
|
|
|
|
|
message = "Bad operation"
|
|
|
|
|
)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
return resp
|