diff --git a/lambda_config/lambda_config.py b/lambda_config/lambda_config.py index 060e6cc..0c30e60 100644 --- a/lambda_config/lambda_config.py +++ b/lambda_config/lambda_config.py @@ -1,9 +1,8 @@ import os import json import boto3 -from typing import Optional +from typing import Dict, Optional from pydantic import BaseModel -import pydantic_core from redirects_base import Content, Customer, Redirects, Tag s3_client = None @@ -55,7 +54,7 @@ def lambda_handler(event: dict, context): redirects = Redirects.model_validate_json(resp['Body'].read()) else: with open('/home/emanuele/dev/StandOut/lambda_config/redirects.json', 'r') as f: - redirects = Redirects.model_validate_json(f.read()) + redirects = Redirects.model_validate_json(f.read(), strict=False) except s3_client.exceptions.NoSuchKey as e: print(e) # Oppure pagina "siamo spiacenti ma il contenuto non e' disponibile" @@ -71,78 +70,117 @@ def lambda_handler(event: dict, context): print(f"Action: {record.eventName}") print(f"Object: {record.s3}") - - # splitta la chiave per capire la directory - keys = record.s3.object.key.split('/') - keys.reverse() match record.eventName: case "ObjectCreated:Put" | "ObjectCreated:CompleteMultipartUpload": - print(f"ObjectCreated: {record.s3.object.key}") + processAdd(record=record, redirects=redirects, client=s3_client) + + case "ObjectRemoved:Delete": + keys = getObjectKeys(record=record) - # crea il primo utente se necessario o selezionalo + if not redirects.customers: + return False cust_key = keys.pop() - if redirects.customers is None: - redirects.customers = {cust_key: Customer(status="active")} - if cust_key not in redirects.customers.keys(): - redirects.customers[cust_key] = Customer(status="active") - - # Aggiunto solo un cliente - if len(keys) == 0: + customer = redirects.customers.get(cust_key, None) + if len(keys) == 0 or not customer: + redirects.customers.pop(cust_key, None) break - c = redirects.customers[cust_key] - # crea un tag per l'utente, con contenuto nullo o selezionalo + if not customer.tags: + return False tag_key = keys.pop() - if c.tags is None: - c.tags = {tag_key: Tag(status="active", content=None)} - if tag_key not in c.tags.keys(): - c.tags[tag_key] = Tag(status="active", content=None) - - # Aggiunta anche una chiave - if len(keys) == 0: + tag = customer.tags.get(tag_key, None) + if len(keys) == 0 or not tag: + customer.tags.pop(tag_key, None) break - t = c.tags[tag_key] - # Crea un contenuto per il tag a seconda della lunghezza della chiave - file_name = keys[0] - if file_name == "url.txt": - with s3_client.get_object(Bucket=bucket_data, Key=record.s3.object.key)['Body'] as url_file: - content = Content(type='url', key=file_name, url=url_file.readline().decode().strip()) - else: - content = Content(type='s3', key=file_name, url=None) - - # Aggiungi il contenuto a una faccia o al tag a seconda della lunghezza del path match len(keys): case 2: - if t.content is None or isinstance(t.content, Content): - t.content = {keys[1]: content} - elif isinstance(t.content, dict): - t.content[keys[1]] = content + if not tag.content or not isinstance(tag.content, Dict): + return False + tag.content.pop(keys[1], None) case 1: - t.content = content + if isinstance(tag.content, Dict) and keys[0] in tag.content.keys(): + tag.content[keys[0]] = None + else: + tag.content = None case _: - print("Too long keys") + print("Unexpected") + return False + + print(f"Object remove: {record.s3.object.key}") case "ObjectCreated:Copy": print(f"Object copy: {record.s3.object.key}") - case "s3:ObjectRemoved:Delete": - print(f"Object remove: {record.s3.object.key}") - case _: print("Unknown action") - if context is not None: - resp = s3_client.put_object(Bucket=bucket_config, - Key='redirects.json', - Body=redirects.model_dump_json(indent=2)) - print(f"New redirects version: {resp['ETag']}") - else: - with open('/home/emanuele/dev/StandOut/lambda_config/redirects.json', 'w') as f: - f.write(redirects.model_dump_json(indent=2)) + if context is not None: + resp = s3_client.put_object(Bucket=bucket_config, + Key='redirects.json', + Body=redirects.model_dump_json(indent=2)) + print(f"New redirects version: {resp['ETag']}") + else: + with open('/home/emanuele/dev/StandOut/lambda_config/redirects.json', 'w') as f: + f.write(redirects.model_dump_json(indent=2)) - return True + return True + +def getObjectKeys(record: Record) -> list[str]: + keys = [v for v in record.s3.object.key.split('/') if v != ''] + keys.reverse() + return keys + +def processAdd(record: Record, redirects: Redirects, client) -> None: + # splitta la chiave per capire la directory + keys = getObjectKeys(record=record) + + # crea il primo utente se necessario o selezionalo + cust_key = keys.pop() + if redirects.customers is None: + redirects.customers = {cust_key: Customer(status="active", tags=None)} + if cust_key not in redirects.customers.keys(): + redirects.customers[cust_key] = Customer(status="active", tags=None) + + # Aggiunto solo un cliente + c = redirects.customers[cust_key] + if len(keys) == 0 or not c: + return + + # crea un tag per l'utente, con contenuto nullo o selezionalo + tag_key = keys.pop() + if c.tags is None: + c.tags = {tag_key: Tag(status="active", content=None)} + if tag_key not in c.tags.keys(): + c.tags[tag_key] = Tag(status="active", content=None) + + # Aggiunta anche una chiave + t = c.tags[tag_key] + if len(keys) == 0 or not t: + return + + # Crea un contenuto per il tag a seconda della lunghezza della chiave + file_name = keys[0] + if file_name == "url.txt": + with client.get_object(Bucket=bucket_data, Key=record.s3.object.key)['Body'] as url_file: + content = Content(type='url', key=file_name, url=url_file.readline().decode().strip()) + else: + content = Content(type='s3', key=file_name, url=None) + + # Aggiungi il contenuto a una faccia o al tag a seconda della lunghezza del path + match len(keys): + case 2: + if t.content is None or isinstance(t.content, Content): + t.content = {keys[1]: content} + elif isinstance(t.content, dict): + t.content[keys[1]] = content + case 1: + t.content = content + case _: + print("Too long keys") + + print(f"ObjectCreated: {record.s3.object.key}") if __name__ == "__main__": diff --git a/lambda_config/redirects.json b/lambda_config/redirects.json index 1902a21..d9e0320 100644 --- a/lambda_config/redirects.json +++ b/lambda_config/redirects.json @@ -1,49 +1,13 @@ { "customers": { - "customer1": { + "customer3": { "status": "active", "tags": { - "tag1": { - "status": "active", - "content": { - "type": "url", - "key": "url.txt", - "url": "https://grafana.etss.it/d/LbON5PkGz/power?orgId=1&from=now-12h&to=now&refresh=30s" - } - }, "tag2": { "status": "active", "content": { "type": "s3", - "key": "file.txt", - "url": null - } - } - } - }, - "customer2": { - "status": "active", - "tags": { - "tag1": { - "status": "active", - "content": { - "face1": { - "type": "s3", - "key": "file.txt", - "url": null - } - } - } - } - }, - "customer3": { - "status": "active", - "tags": { - "tag1": { - "status": "active", - "content": { - "type": "s3", - "key": "VID20240116160134.mp4", + "key": "foo.txt", "url": null } } diff --git a/lambda_config/redirects_base.py b/lambda_config/redirects_base.py index e41a2b6..ca4d8cb 100644 --- a/lambda_config/redirects_base.py +++ b/lambda_config/redirects_base.py @@ -4,52 +4,15 @@ from pydantic import BaseModel class Content(BaseModel): type: str key: str - url: Optional[str | None] = None + url: Optional[str | None] class Tag(BaseModel): status: str - content: Content | Dict[str, Content] | None = None + content: Optional[Content | Dict[str, Optional[Content]]] class Customer(BaseModel): status: str - tags: Dict[str, Tag] | None = None + tags: Optional[Dict[str, Optional[Tag]] ] class Redirects(BaseModel): - customers: Dict[str, Customer] | None = None - -if __name__ == "__main__": - r = Redirects ( - customers = { - "cust1": Customer( - status="active", - tags= { - "tag1" : Tag ( - status="active", - content= Content( - type="s3", - key="foo", - url=None - ) - ), - "tag2" : Tag( - status="active", - content = { - "face1" : Content( - type="s3", - key="contentface1", - url = "foo" - ), - "face2": Content( - type="s3", - key="contentface2", - url = "bar" - ), - } - ) - } - ) - } - ) - - r.customers['cust2'] = Customer(status="inactive", tags=None) - print(r.model_dump_json(indent=2)) \ No newline at end of file + customers: Dict[str, Optional[Customer]] | None = None diff --git a/lambda_config/test.json b/lambda_config/test.json index 6493d0a..1d891cb 100644 --- a/lambda_config/test.json +++ b/lambda_config/test.json @@ -27,7 +27,7 @@ "arn": "arn:aws:s3:::standout-data" }, "object": { - "key": "customer1/tag2/file.txt", + "key": "customer3/tag2/foo.txt", "size": 2844326, "eTag": "7039e5338840f289d0510dc9149bf0b5", "sequencer": "00662A206F99CD2E09"