py#dynamodb
Questo generatore crea un nuovo progetto Python supportato da Amazon DynamoDB, utilizzando PynamoDB per la modellazione delle entità. Genera il codice dell’applicazione e l’infrastruttura necessaria per il provisioning e la gestione di una tabella DynamoDB utilizzando AWS CDK o Terraform, con supporto per il design single-table e sviluppo locale integrato tramite DynamoDB Local.
Utilizzo
Sezione intitolata “Utilizzo”Genera un progetto DynamoDB
Sezione intitolata “Genera un progetto DynamoDB”- Installa il Nx Console VSCode Plugin se non l'hai già fatto
- Apri la console Nx in VSCode
- Clicca su
Generate (UI)nella sezione "Common Nx Commands" - Cerca
@aws/nx-plugin - py#dynamodb - Compila i parametri richiesti
- Clicca su
Generate
pnpm nx g @aws/nx-plugin:py#dynamodbyarn nx g @aws/nx-plugin:py#dynamodbnpx nx g @aws/nx-plugin:py#dynamodbbunx nx g @aws/nx-plugin:py#dynamodbPuoi anche eseguire una prova per vedere quali file verrebbero modificati
pnpm nx g @aws/nx-plugin:py#dynamodb --dry-runyarn nx g @aws/nx-plugin:py#dynamodb --dry-runnpx nx g @aws/nx-plugin:py#dynamodb --dry-runbunx nx g @aws/nx-plugin:py#dynamodb --dry-runOpzioni
Sezione intitolata “Opzioni”| Parametro | Tipo | Predefinito | Descrizione |
|---|---|---|---|
| name Obbligatorio | string | - | Nome del progetto DynamoDB da generare |
| directory | string | packages | La directory in cui memorizzare il progetto. |
| subDirectory | string | - | La sotto-directory in cui viene posizionato il progetto. Per impostazione predefinita corrisponde al nome del progetto. |
| framework | pynamodb | pynamodb | Il framework da utilizzare per le entità DynamoDB. |
| tableName | string | - | Il nome della tabella DynamoDB. Generato automaticamente se non specificato. |
| infra | dynamodb | none | dynamodb | Infrastruttura da fornire per la tabella DynamoDB. |
| iac | inherit | cdk | terraform | inherit | Il provider IaC preferito. Per impostazione predefinita viene ereditato dalla selezione iniziale. |
| preferInstallDependencies | boolean | true | Se preferire l'installazione delle dipendenze dopo l'esecuzione del generatore. Impostare su false per rimandare l'installazione quando si eseguono più generatori in batch (l'installazione viene comunque eseguita se necessaria affinché i generatori successivi possano calcolare il grafo dei progetti Nx); installare una volta alla fine. |
Output del generatore
Sezione intitolata “Output del generatore”Il generatore crea la seguente struttura di progetto nella directory <directory>/<name>:
Directory<name>
- __init__.py Esportazioni del package
- client.py Client DynamoDB e risoluzione del nome della tabella
Directoryentities
- base.py Modello PynamoDB base con dichiarazioni GSI
- example.py Definizione di entità di esempio
- __init__.py Esportazioni delle entità
- config.json Configurazione della tabella incluse le definizioni GSI e le impostazioni di sviluppo locale
- project.json Configurazione del progetto e target di build
Gli script di sviluppo locale sono condivisi tra tutti i progetti DynamoDB (sia TypeScript che Python) e generati una sola volta in:
Directorypackages/common/scripts/src/dynamodb
- create-local-table.ts Crea la tabella DynamoDB nell’istanza locale di DynamoDB Local
- pull-image.ts Scarica l’immagine di DynamoDB Local
- start-container.ts Avvia il container di DynamoDB Local
Infrastruttura
Sezione intitolata “Infrastruttura”Poiché questo generatore fornisce infrastruttura come codice basata sul tuo iacProvider selezionato, creerà un progetto in packages/common che include i relativi costrutti CDK o moduli Terraform.
Il progetto comune di infrastruttura come codice è strutturato come segue:
Directorypackages/common/constructs
Directorysrc
Directoryapp/ Construct per l’infrastruttura specifica di un progetto/generatore
- …
Directorycore/ Construct generici riutilizzati dai construct in
app- …
- index.ts Punto di ingresso che esporta i construct da
app
- project.json Target di build e configurazione del progetto
Directorypackages/common/terraform
Directorysrc
Directoryapp/ Moduli Terraform per l’infrastruttura specifica di un progetto/generatore
- …
Directorycore/ Moduli generici riutilizzati dai moduli in
app- …
- project.json Target di build e configurazione del progetto
Directorypackages/common/constructs/src
Directoryapp
Directorydynamodb
- <name>.ts Infrastruttura specifica per la tua tabella
Directorycore
- dynamodb.ts Costrutto generico per tabelle DynamoDB
Directorypackages/common/terraform/src
Directoryapp
Directorydynamodb
Directory<name>
- <name>.tf Modulo specifico per la tua tabella
Directorycore
Directorydynamodb
- dynamodb.tf Modulo generico DynamoDB
Sviluppo locale
Sezione intitolata “Sviluppo locale”Avvio di DynamoDB locale
Sezione intitolata “Avvio di DynamoDB locale”Il generatore configura un target dev che avvia un’istanza di DynamoDB Local e crea la tabella. Usa il target dev del progetto:
pnpm nx dev <project-name>yarn nx dev <project-name>npx nx dev <project-name>bunx nx dev <project-name>Questo automaticamente:
- Scarica l’immagine DynamoDB Local (target
pull-image) - Avvia un container
- Crea una tabella locale con gli indici definiti in
config.json
Modellazione dei dati
Sezione intitolata “Modellazione dei dati”Il progetto generato utilizza PynamoDB per la modellazione delle entità. Tutte le entità devono ereditare dal BaseModel generato — esso risolve il nome corretto della tabella DynamoDB a runtime, leggendo da AWS AppConfig quando distribuito o da config.json quando eseguito localmente tramite DynamoDB Local. Senza questo, PynamoDB non saprà quale tabella utilizzare. BaseModel utilizza anche il supporto al polimorfismo di PynamoDB per memorizzare più tipi di entità in una singola tabella, seguendo il design single-table di DynamoDB.
Aggiungi o aggiorna i file delle entità in <name>/entities/, utilizzando l’entità di esempio generata come punto di partenza:
from collections.abc import Iteratorfrom datetime import UTC, datetimefrom pynamodb.attributes import UnicodeAttributefrom .base import BaseModel
class ExampleModel(BaseModel, discriminator='ExampleModel'): """ Key design: pk=EXAMPLE#<id>, sk=EXAMPLE#<id> gsi1pk=CATEGORY#<cat>, gsi1sk=EXAMPLE#<id> <- list items by category gsi2pk=EXAMPLE, gsi2sk=<created_at> <- list all items by date """
name = UnicodeAttribute() category = UnicodeAttribute() created_at = UnicodeAttribute() updated_at = UnicodeAttribute()
@classmethod def make_pk(cls, id: str) -> str: return f'EXAMPLE#{id}'
@classmethod def create(cls, id: str, name: str, category: str) -> 'ExampleModel': now = datetime.now(UTC).isoformat() item = cls( pk=cls.make_pk(id), sk=cls.make_pk(id), gsi1pk=f'CATEGORY#{category}', gsi1sk=cls.make_pk(id), gsi2pk='EXAMPLE', gsi2sk=now, name=name, category=category, created_at=now, updated_at=now, ) item.save() return item
# ── Primary index ───────────────────────────────────────────────────────── @classmethod def get_by_id(cls, id: str) -> 'ExampleModel': return cls.get(cls.make_pk(id), cls.make_pk(id))
# ── gsi1_index: partition=category, sort=id ─────────────────────────────── @classmethod def list_by_category(cls, category: str) -> Iterator['ExampleModel']: return cls.gsi1_index.query(f'CATEGORY#{category}')
# ── gsi2_index: partition=type, sort=created_at ─────────────────────────── @classmethod def list_created_between(cls, start: datetime, end: datetime) -> Iterator['ExampleModel']: return cls.gsi2_index.query( 'EXAMPLE', range_key_condition=ExampleModel.gsi2sk.between( start.isoformat(), end.isoformat(), ), scan_index_forward=False, )Per maggiori dettagli, consulta il tutorial di PynamoDB.
Progettazione basata sui pattern di accesso
Sezione intitolata “Progettazione basata sui pattern di accesso”In DynamoDB, la progettazione dello schema inizia dalle tue query, non dalla forma dei dati. Prima di scrivere qualsiasi modello, elenca ogni pattern di accesso di cui la tua applicazione ha bisogno, quindi progetta i valori delle chiavi pk, sk e GSI in modo che ogni pattern sia soddisfatto da una singola richiesta alla tabella — niente JOIN, niente letture sequenziali.
L’ExampleModel generato dimostra questo per tre pattern:
- Get by ID — indice primario,
pk=EXAMPLE#<id>,sk=EXAMPLE#<id> - List by category —
gsi1,pk=CATEGORY#<category> - List by creation date —
gsi2,pk=EXAMPLE, sort key tra timestamp ISO
La convenzione del prefisso di tipo (es. EXAMPLE#, CATEGORY#) è deliberata: rende gli elementi auto-descrittivi quando si naviga nella tabella, previene collisioni accidentali di chiavi tra tipi di entità che condividono un indice e consente il filtraggio del prefisso della sort key usando begins_with.
Prima di scrivere una nuova entità, definisci i suoi pattern di chiavi in anticipo in una docstring. L’OrderModel nella prossima sezione segue questa convenzione:
class OrderModel(BaseModel, discriminator='OrderModel'): """ Key design: pk=ORDER#<order_id>, sk=ORDER#<order_id> gsi1pk=USER#<user_id>, gsi1sk=ORDER#<order_id> <- list orders for a user gsi2pk=ORDER, gsi2sk=<created_at> <- list all orders by date """Memorizzazione di più tipi di entità
Sezione intitolata “Memorizzazione di più tipi di entità”Il DiscriminatorAttribute di PynamoDB memorizza un’etichetta di tipo (entity_type) in ogni elemento. Quando si esegue una query tramite BaseModel, questa etichetta viene utilizzata per istanziare automaticamente ogni risultato come la sua sottoclasse corretta — quindi una singola query può restituire un mix di UserModel, OrderModel e qualsiasi altro tipo di entità registrato nella stessa tabella.
Di seguito è riportato un esempio completo con due entità — un UserModel con record OrderModel associati memorizzati nella stessa tabella:
from collections.abc import Iteratorfrom datetime import UTC, datetimefrom pynamodb.attributes import UnicodeAttributefrom .base import BaseModel
class UserModel(BaseModel, discriminator='UserModel'): """ Key design: pk=USER#<user_id>, sk=USER#<user_id> gsi2pk=USER, gsi2sk=<created_at> <- list all users by date """
username = UnicodeAttribute() email = UnicodeAttribute() created_at = UnicodeAttribute()
@classmethod def make_pk(cls, user_id: str) -> str: return f'USER#{user_id}'
@classmethod def create(cls, user_id: str, username: str, email: str) -> 'UserModel': now = datetime.now(UTC).isoformat() item = cls( pk=cls.make_pk(user_id), sk=cls.make_pk(user_id), gsi2pk='USER', gsi2sk=now, username=username, email=email, created_at=now, ) item.save() return item
@classmethod def get_by_id(cls, user_id: str) -> 'UserModel': return cls.get(cls.make_pk(user_id), cls.make_pk(user_id))
@classmethod def list_recent(cls, limit: int | None = None) -> Iterator['UserModel']: return cls.gsi2_index.query('USER', limit=limit, scan_index_forward=False)from collections.abc import Iteratorfrom datetime import UTC, datetimefrom pynamodb.attributes import UnicodeAttributefrom .base import BaseModel
class OrderModel(BaseModel, discriminator='OrderModel'): """ Key design: pk=ORDER#<order_id>, sk=ORDER#<order_id> gsi1pk=USER#<user_id>, gsi1sk=ORDER#<order_id> <- list orders by user gsi2pk=ORDER, gsi2sk=<created_at> <- list all orders by date """
user_id = UnicodeAttribute() total = UnicodeAttribute() created_at = UnicodeAttribute()
@classmethod def make_pk(cls, order_id: str) -> str: return f'ORDER#{order_id}'
@classmethod def create(cls, order_id: str, user_id: str, total: str) -> 'OrderModel': now = datetime.now(UTC).isoformat() item = cls( pk=cls.make_pk(order_id), sk=cls.make_pk(order_id), gsi1pk=f'USER#{user_id}', gsi1sk=cls.make_pk(order_id), gsi2pk='ORDER', gsi2sk=now, user_id=user_id, total=total, created_at=now, ) item.save() return item
@classmethod def get_by_id(cls, order_id: str) -> 'OrderModel': return cls.get(cls.make_pk(order_id), cls.make_pk(order_id))
# ── gsi1_index: partition=user, sort=order_id ──────────────────────────── @classmethod def list_by_user(cls, user_id: str) -> Iterator['OrderModel']: return cls.gsi1_index.query(f'USER#{user_id}')
# ── gsi2_index: partition=type, sort=created_at ─────────────────────────── @classmethod def list_recent(cls, limit: int | None = None) -> Iterator['OrderModel']: return cls.gsi2_index.query('ORDER', limit=limit, scan_index_forward=False)Esporta le nuove entità da __init__.py:
from .user import UserModelfrom .order import OrderModelfrom .example import ExampleModelOverloading dei GSI
Sezione intitolata “Overloading dei GSI”BaseModel fornisce due GSI condivisi (gsi1_index, gsi2_index). Sia UserModel che OrderModel sopra scrivono su gsi2 — ma con valori gsi2pk diversi (USER vs ORDER). Questo è l’overloading dei GSI: riutilizzare un singolo indice fisico per servire più pattern di accesso indipendenti senza consumare capacità GSI extra.
UserModel—gsi2pk=USER,gsi2sk=<created_at>→ elenca tutti gli utenti per dataOrderModel—gsi2pk=ORDER,gsi2sk=<created_at>→ elenca tutti gli ordini per data
Anche gsi1 può essere sovraccaricato quando più tipi di entità condividono lo stesso genitore. Se successivamente aggiungi un ReviewModel che appartiene anche a un utente, puoi assegnargli gsi1pk=USER#<user_id> con una sort key REVIEW#<id> — non è necessario un GSI aggiuntivo. Interrogare gsi1 tramite BaseModel restituisce quindi sia ordini che recensioni per quell’utente in una singola richiesta, con PynamoDB che istanzia ogni elemento come la sua sottoclasse corretta:
from .base import BaseModelfrom .order import OrderModelfrom .review import ReviewModel
user_id = 'user-123'items = list(BaseModel.gsi1_index.query(f'USER#{user_id}'))
orders = [i for i in items if isinstance(i, OrderModel)]reviews = [i for i in items if isinstance(i, ReviewModel)]Per recuperare solo un tipo di entità da un GSI sovraccaricato, usa una condizione di prefisso della sort key:
orders_only = list(BaseModel.gsi1_index.query( f'USER#{user_id}', range_key_condition=BaseModel.gsi1sk.startswith('ORDER#'),))Relazioni uno-a-molti
Sezione intitolata “Relazioni uno-a-molti”In una relazione uno-a-molti l’entità figlia memorizza un riferimento al suo genitore in una chiave di partizione GSI, rendendo la relazione attraversabile in entrambe le direzioni senza duplicare i dati. L’esempio UserModel / OrderModel sopra è esattamente questo pattern:
- Ottieni un singolo ordine per ID — tabella primaria:
pk=ORDER#<id>,sk=ORDER#<id> - Elenca tutti gli ordini per un utente —
gsi1:pk=USER#<user_id>
Un’alternativa alle ricerche basate su GSI è il pattern item collection: dai agli elementi figli lo stesso pk del loro genitore e usa la sort key per differenziarli. Questo ti permette di recuperare il genitore e tutti i suoi figli in una singola query sulla tabella primaria, senza un GSI:
class OrderModel(BaseModel, discriminator='OrderModel'): """ Key design (item collection): pk=USER#<user_id>, sk=ORDER#<order_id> <- co-located under the parent user """ ...# Recupera l'utente e tutti i suoi ordini in una singola query sulla tabella primaria# BaseModel invia ogni elemento alla sua sottoclasse corretta tramite DiscriminatorAttributeitems = list(BaseModel.query(f'USER#{user_id}'))user = next(i for i in items if isinstance(i, UserModel))orders = [i for i in items if isinstance(i, OrderModel)]Il compromesso: le item collection posizionano tutti i figli sotto una singola chiave di partizione, che è ottimale per la maggior parte dei carichi di lavoro ma può creare una partizione calda con throughput di scrittura estremo. L’approccio GSI (utilizzato negli esempi sopra) mantiene ogni entità nella propria partizione ed è generalmente più sicuro per iniziare.
Relazioni molti-a-molti
Sezione intitolata “Relazioni molti-a-molti”Le relazioni molti-a-molti richiedono un’entità di giunzione utilizzando il pattern adjacency list: un elemento dedicato che registra ogni collegamento, con la sua chiave GSI che inverte la direzione in modo che la relazione possa essere attraversata in entrambi i modi.
Considera ArticleModel e TagModel, dove un articolo può avere molti tag e un tag può applicarsi a molti articoli:
from collections.abc import Iteratorfrom pynamodb.attributes import UnicodeAttributefrom .base import BaseModel
class ArticleTagModel(BaseModel, discriminator='ArticleTag'): """ Junction entity for the Article ↔ Tag many-to-many relationship.
Key design: pk=ARTICLE#<article_id>, sk=TAG#<tag_name> <- list tags for an article gsi1pk=TAG#<tag_name>, gsi1sk=ARTICLE#<article_id> <- list articles for a tag """
article_id = UnicodeAttribute() tag_name = UnicodeAttribute()
@classmethod def add(cls, article_id: str, tag_name: str) -> 'ArticleTagModel': item = cls( pk=f'ARTICLE#{article_id}', sk=f'TAG#{tag_name}', gsi1pk=f'TAG#{tag_name}', gsi1sk=f'ARTICLE#{article_id}', article_id=article_id, tag_name=tag_name, ) item.save() return item
@classmethod def remove(cls, article_id: str, tag_name: str) -> None: cls.get(f'ARTICLE#{article_id}', f'TAG#{tag_name}').delete()
# ── Primary index: pk=article, sk=tag ───────────────────────────────────── @classmethod def list_tags_for_article(cls, article_id: str) -> Iterator['ArticleTagModel']: return cls.query(f'ARTICLE#{article_id}')
# ── gsi1_index: pk=tag, sk=article ──────────────────────────────────────── @classmethod def list_articles_for_tag(cls, tag_name: str) -> Iterator['ArticleTagModel']: return cls.gsi1_index.query(f'TAG#{tag_name}')Poiché ArticleTagModel utilizza pk=ARTICLE#<article_id> — la stessa partizione dell’articolo stesso — puoi recuperare un articolo e tutti i suoi tag in una singola query sulla tabella primaria:
from .base import BaseModelfrom .article import ArticleModelfrom .article_tag import ArticleTagModel
items = list(BaseModel.query('ARTICLE#article-123'))article = next(i for i in items if isinstance(i, ArticleModel))tags = [i.tag_name for i in items if isinstance(i, ArticleTagModel)]Per ulteriori letture sulla modellazione dei dati DynamoDB, consulta la guida alla modellazione dei dati DynamoDB e Creating a single-table design with Amazon DynamoDB.
Utilizzo del client DynamoDB
Sezione intitolata “Utilizzo del client DynamoDB”Il file client.py generato esporta due utility chiave:
is_local()— restituisceTruequandoLOCAL_DEV=true, utilizzato per passare dal comportamento locale a quello AWS.get_table_name()— restituisce il nome della tabella DynamoDB. QuandoLOCAL_DEV=true, legge il nome della tabella dalocalDev.tableNameinconfig.json; altrimenti recupera il nome da AWS AppConfig utilizzando la variabile d’ambienteRUNTIME_CONFIG_APP_IDe lo memorizza nella cache per le chiamate successive.
BaseModel in entities/base.py utilizza entrambe per configurare PynamoDB automaticamente:
- Connessione —
BaseModel.Metaimpostahostdaconfig.jsone codificaregion,aws_access_key_ideaws_secret_access_keyquandois_local()èTrue, puntando PynamoDB all’istanza locale di DynamoDB. In AWS, questi vengono lasciati non impostati in modo che PynamoDB utilizzi la catena di credenziali predefinita. - Nome della tabella —
BaseModel._get_connection()chiamaget_table_name()prima di ogni operazione, in modo che la tabella corretta venga risolta a runtime senza alcuna configurazione manuale.
Arresto di DynamoDB locale
Sezione intitolata “Arresto di DynamoDB locale”L’arresto di dev (ad es. con Ctrl+C) rimuove automaticamente il container DynamoDB Local, ma preserva il volume nominato in modo che i tuoi dati persistano tra i riavvii.
Aggiunta/Rimozione di Global Secondary Index
Sezione intitolata “Aggiunta/Rimozione di Global Secondary Index”I GSI sono definiti in config.json nella radice del progetto sotto la chiave tableConfig.globalSecondaryIndexes. Aggiungi una voce per ogni GSI, quindi rifletti la modifica in BaseModel aggiungendo o rimuovendo la corrispondente classe GlobalSecondaryIndex e gli attributi in <name>/entities/base.py:
{ ... "tableConfig": { "globalSecondaryIndexes": [ { "indexName": "gsi1pk-gsi1sk-index", "partitionKey": "gsi1pk", "sortKey": "gsi1sk" }, { "indexName": "gsi2pk-gsi2sk-index", "partitionKey": "gsi2pk", "sortKey": "gsi2sk" } ] }}Il campo sortKey è opzionale per i GSI con solo hash-key.
Questo file di configurazione è l’unica fonte di verità letta da tutti i consumatori:
- Sviluppo locale —
devleggeconfig.jsone crea o aggiorna la tabella locale per corrispondere all’elenco dei GSI - CDK — il costrutto legge
config.jsonal momento della sintesi, quindi le modifiche ai GSI si riflettono al prossimocdk deploy - Terraform — il modulo legge
config.jsonal momento del plan/apply
Un GSI per Deployment
Sezione intitolata “Un GSI per Deployment”Connessione alla tabella
Sezione intitolata “Connessione alla tabella”In qualsiasi progetto Python, aggiungi il package DynamoDB come dipendenza del workspace e importa direttamente le classi delle entità:
from my_db_package.entities import ExampleModel
item = ExampleModel.get_by_id('123')Generatori di connessione
Sezione intitolata “Generatori di connessione”Per tipi di progetto specifici, utilizza il generatore connection per collegare automaticamente le dipendenze di sviluppo locale in modo che DynamoDB Local si avvii automaticamente insieme al tuo progetto e aggiungi il package DynamoDB come dipendenza del workspace:
Distribuzione della tabella
Sezione intitolata “Distribuzione della tabella”Il generatore DynamoDB crea infrastruttura CDK o Terraform in base al tuo iac selezionato.
Il costrutto CDK viene creato in common/constructs. Esempio di utilizzo:
import { MyTable } from ':my-scope/common-constructs';
export class ApplicationStack extends Stack { constructor(scope: Construct, id: string, props?: StackProps) { super(scope, id, props);
const table = new MyTable(this, 'Table'); }}Questo esegue il provisioning di una tabella DynamoDB con:
pk(partition key) esk(sort key), entrambe di tipoString- Global Secondary Indexes come definiti in
config.json - Fatturazione on-demand (
PAY_PER_REQUEST) - Crittografia KMS gestita dal cliente con rotazione automatica delle chiavi
- Point-in-time recovery abilitato
- Protezione dalla cancellazione abilitata
- Nome della tabella registrato in Runtime Config sotto il namespace
dynamodbin AWS AppConfig
Il modulo Terraform viene creato in common/terraform. Esempio di utilizzo:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}Questo esegue il provisioning di una tabella DynamoDB con:
pk(partition key) esk(sort key), entrambe di tipoString- Global Secondary Indexes come definiti in
config.json - Fatturazione on-demand (
PAY_PER_REQUEST) - Crittografia KMS gestita dal cliente con rotazione automatica delle chiavi
- Point-in-time recovery abilitato
- Protezione dalla cancellazione abilitata
- Nome della tabella registrato in Runtime Config
Concessione dell’accesso
Sezione intitolata “Concessione dell’accesso”Per consentire alle funzioni Lambda di accedere alla tabella DynamoDB, concedi le autorizzazioni necessarie nella tua infrastruttura.
Chiama grantReadWriteData sul costrutto della tabella. Questo concede sia le autorizzazioni DynamoDB che KMS richieste dal ruolo di esecuzione Lambda:
import { MyTable } from ':my-scope/common-constructs';
const table = new MyTable(this, 'Table');
const api = new Api(this, 'Api', { integrations: Api.defaultIntegrations(this).build(),});
Object.entries(api.integrations).forEach(([, integration]) => { table.grantReadWriteData(integration.handler);});Concedi al ruolo di esecuzione Lambda l’autorizzazione per accedere alla tabella DynamoDB e alla sua chiave di crittografia KMS:
module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table"}
resource "aws_iam_role_policy" "dynamodb_access" { role = module.my_api.lambda_role_name
policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem", "dynamodb:Query", "dynamodb:Scan", "dynamodb:BatchGetItem", "dynamodb:BatchWriteItem", ] Resource = [ module.my_table.table_arn, "${module.my_table.table_arn}/index/*", ] }, { Effect = "Allow" Action = [ "kms:Encrypt", "kms:Decrypt", "kms:ReEncrypt*", "kms:GenerateDataKey*", "kms:DescribeKey" ] Resource = [module.my_table.kms_key_arn] }, ] })}Protezione dalla cancellazione
Sezione intitolata “Protezione dalla cancellazione”La protezione dalla cancellazione è abilitata per impostazione predefinita per prevenire la cancellazione accidentale della tabella.
Disabilitare la protezione dalla cancellazione
Sezione intitolata “Disabilitare la protezione dalla cancellazione”Disabilitala per ambienti in cui è prevista la cancellazione della tabella, come stack di sviluppo o preview di breve durata.
import { MyTable } from ':my-scope/common-constructs';
const table = new MyTable(this, 'Table', { deletionProtection: false,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" deletion_protection_enabled = false}Modalità di fatturazione
Sezione intitolata “Modalità di fatturazione”La tabella utilizza per impostazione predefinita la fatturazione on-demand (PAY_PER_REQUEST). Passa alla capacità con provisioning per carichi di lavoro prevedibili ad alto throughput.
import { BillingMode } from 'aws-cdk-lib/aws-dynamodb';import { MyTable } from ':my-scope/common-constructs';
const table = new MyTable(this, 'Table', { billingMode: BillingMode.PROVISIONED, readCapacity: 5, writeCapacity: 5,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" billing_mode = "PROVISIONED"}Point-in-time Recovery
Sezione intitolata “Point-in-time Recovery”Il Point-in-time recovery è abilitato per impostazione predefinita, consentendoti di ripristinare la tabella a qualsiasi punto negli ultimi 35 giorni.
Disabilitare il Point-in-time Recovery
Sezione intitolata “Disabilitare il Point-in-time Recovery”import { MyTable } from ':my-scope/common-constructs';
const table = new MyTable(this, 'Table', { pointInTimeRecoverySpecification: { pointInTimeRecoveryEnabled: false },});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" point_in_time_recovery_enabled = false}Rotazione della chiave di crittografia
Sezione intitolata “Rotazione della chiave di crittografia”La chiave KMS utilizzata per crittografare la tabella ha la rotazione automatica delle chiavi abilitata per impostazione predefinita. Disabilitala se la tua policy di sicurezza gestisce la rotazione esternamente.
Disabilitare la rotazione della chiave di crittografia
Sezione intitolata “Disabilitare la rotazione della chiave di crittografia”import { MyTable } from ':my-scope/common-constructs';
const table = new MyTable(this, 'Table', { enableKeyRotation: false,});module "my_table" { source = "../../common/terraform/src/app/dynamodb/my-table" enable_key_rotation = false}Connessioni
Sezione intitolata “Connessioni”Usa il generatore connection per integrare questo progetto con altri nel tuo workspace. Le seguenti connessioni coinvolgono questo progetto: