Módulo 3: Infrastructure As Code For An Ai Endpoint
7. Manos a la obra: verificando lo que sí se puede aplicar de verdad
Descripción
bedrock.tf tiene dos piezas: un guardrail de Bedrock y un rol IAM. La lección 6 confirmó, con cita oficial, que la primera no se puede aplicar de verdad en ningún plan gratuito de LocalStack. Esta lección traza la frontera exacta con la segunda — y es más precisa de lo que "IAM es Hobby, así que esto sí aplica" sugiere a primera vista. Hay dos capas de honestidad que separar aquí, no una, y esta lección las separa con el mismo cuidado que el resto de la guía.
Conexión con el módulo
Esta lección cierra el argumento que la lección 1 abrió y la lección 6 confirmó desde el otro lado: dentro del mismo bedrock.tf, dos recursos pueden tener destinos completamente distintos frente a apply, y la razón de cada uno se explica por separado, con su propia evidencia — nunca una regla genérica de "esto es LocalStack, así que todo se comporta igual".
Las dos capas de esta frontera, separadas desde el principio
DOS PREGUNTAS DISTINTAS, NO UNA
Pregunta 1: ¿el SERVICIO (IAM, Bedrock) está en el plan Hobby?
│
├── IAM: SÍ, confirmado desde aws-core-services-guide.
└── Bedrock: NO, "Included in Plans: Ultimate" (lección 6).
Pregunta 2: ¿ESTE SANDBOX DE ESCRITURA tiene un LOCALSTACK_AUTH_TOKEN
exportado, para que el contenedor arranque en absoluto?
│
└── NO, para ningún servicio -- confirmado con el exit code 55
real del Módulo 1, lección 7, reproducido de nuevo en la
lección 6 de este módulo.
La Pregunta 1 es sobre el servicio: distingue qué es posible en principio, con cualquier cuenta de Hobby real, en cualquier máquina. La Pregunta 2 es sobre este entorno de escritura específico: incluso para un servicio que sí está en Hobby, aquí, hoy, el contenedor no arranca. Confundir estas dos preguntas —tratarlas como si fueran la misma— es exactamente el error que esta lección existe para prevenir.
Paso 1 — La respuesta a la Pregunta 1: IAM sí, Bedrock no, en principio
Esto ya lo estableció, con evidencia, la lección 6: Bedrock está documentado, oficialmente, como "Included in Plans: Ultimate" — ningún token de Hobby, sin importar de dónde venga, lo resuelve. IAM nunca tuvo esa restricción; es uno de los servicios centrales que aws-core-services-guide ya confirmó, con ejecución real, como parte del plan gratuito desde la primera guía de este ecosistema.
Lo que esto significa en la práctica, para alguien con su propia máquina y su propio token de Hobby, gratis, registrado:
docker run -d -p 4566:4566 -e LOCALSTACK_AUTH_TOKEN=$LOCALSTACK_AUTH_TOKEN localstack/localstack:latest
tflocal apply -target=module.bedrock_manifest_extractor_role -auto-approve
Qué esperar (representativo, pero construido con precisión sobre exactamente el JSON que terraform plan ya produjo en la lección 4 y 5 de este módulo — nunca un formato inventado):
module.bedrock_manifest_extractor_role.aws_iam_role.this: Creating...
module.bedrock_manifest_extractor_role.aws_iam_role.this: Creation complete after 1s [id=BedrockManifestExtractorRole]
module.bedrock_manifest_extractor_role.aws_iam_role_policy.this: Creating...
module.bedrock_manifest_extractor_role.aws_iam_role_policy.this: Creation complete after 0s [id=BedrockManifestExtractorRole:BedrockManifestExtractorRole-policy]
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
Outputs:
bedrock_manifest_extractor_role_arn = "arn:aws:iam::000000000000:role/BedrockManifestExtractorRole"
awslocal iam get-role-policy --role-name BedrockManifestExtractorRole --policy-name BedrockManifestExtractorRole-policy
Qué esperar (representativo, el mismo JSON exacto que la lección 4 ya mostró, ahora como resultado de una lectura contra un rol aplicado de verdad):
{
"RoleName": "BedrockManifestExtractorRole",
"PolicyName": "BedrockManifestExtractorRole-policy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeManifestExtractionModelOnly",
"Effect": "Allow",
"Action": "bedrock:InvokeModel",
"Resource": "arn:aws:bedrock:us-east-1::foundation-model/amazon.nova-lite-v1:0"
}
]
}
}
Esto sí sería una lectura completamente real —IAM es un servicio de Hobby, sin ninguna restricción de licencia por encima de eso— si este comando corriera contra un LocalStack arrancado de verdad. El ARN de cuenta 000000000000 es el mismo que LocalStack asigna, sin excepción, a cualquier cuenta emulada — el mismo que ya viste en aws-core-services-guide desde la primera guía de este ecosistema.
Paso 2 — La respuesta a la Pregunta 2: por qué, aun así, nada de esto corrió en este sandbox
Aquí es donde la frontera se vuelve fina. El Paso 1 completo —apply real, awslocal real, IAM funcionando de punta a punta— es exactamente lo que pasaría en tu máquina, no en la de este sandbox de escritura. La razón, ya confirmada por ejecución directa en el Módulo 1, lección 7 y reproducida en la lección 6 de este módulo, es específica de este entorno: no hay ningún LOCALSTACK_AUTH_TOKEN exportado aquí, así que el contenedor de LocalStack se apaga con exit code 55 antes de exponer un solo servicio — IAM incluido, aunque IAM en sí no tenga ninguna restricción de plan.
LA FRONTERA COMPLETA, LAS DOS CAPAS JUNTAS
bedrock.tf
│
┌───────────────┴───────────────┐
│ │
module.manifest_extractor_guardrail module.bedrock_manifest_extractor_role
(aws_bedrock_guardrail) (aws_iam_role + aws_iam_role_policy)
│ │
▼ ▼
¿Servicio en Hobby? NO ¿Servicio en Hobby? SÍ
("Ultimate" -- lección 6) (confirmado desde aws-core-services-guide)
│ │
▼ ▼
NUNCA aplica en Hobby, PODRÍA aplicar en Hobby --
con o sin token, en EN UNA MÁQUINA CON TOKEN REAL.
ninguna máquina. En ESTE sandbox: tampoco corre,
por el exit code 55 (Paso 1 de
la lección 6) -- un límite del
ENTORNO, no del servicio.
│ │
▼ ▼
REPRESENTATIVO REPRESENTATIVO en este
(límite del servicio, sandbox específico
permanente, cualquier (límite del entorno,
máquina) resoluble con un token)
El resultado práctico —ambos quedan representativos en esta guía— es el mismo, pero la razón detrás de cada uno es completamente distinta, y esa diferencia importa para cualquiera que use este mismo patrón en su propia máquina: quien exporte su propio LOCALSTACK_AUTH_TOKEN de Hobby real va a ver el rol IAM aplicarse de verdad, sin ningún cambio a bedrock.tf — pero seguirá sin poder aplicar el guardrail de Bedrock, sin importar qué token use, a menos que ese token sea de un plan Ultimate de pago.
Paso 3 — Confirmando la frontera con los comandos que sí corrieron: validate y plan, para ambos recursos, sin distinción
Lo único que no varía entre el guardrail y el rol es exactamente lo que las lecciones 3, 4 y 5 de este módulo ya confirmaron, con ejecución real: terraform validate y terraform plan corren de verdad para los dos, sin ninguna diferencia de tratamiento. Confírmalo una vez más, en un solo comando, sobre ambos:
terraform plan -input=false -no-color \
-target=module.manifest_extractor_guardrail \
-target=module.bedrock_manifest_extractor_role
Qué esperar (literal — ya ejecutado en la lección 5 de este módulo, reconfirmado aquí):
Plan: 3 to add, 0 to change, 0 to destroy.
Tres recursos, sin distinción de "cuál sí, cuál no" — porque, hasta este punto exacto (plan, no apply), ninguno de los dos necesita nada real. La frontera de esta lección entera es exclusiva de apply en adelante — la línea divisoria que la lección 1 de este módulo prometió desde el principio.
Errores comunes
Concluir que "el rol IAM de esta guía se aplicó de verdad" porque la lección lo describe con tanto detalle (de confundir precisión representativa con ejecución real). Qué pasa: alguien, leyendo el Paso 1 completo —con Apply complete! y un awslocal con salida JSON—, asume que estos comandos corrieron en este sandbox. Cómo detectarlo: si tu resumen de esta lección incluye la frase "el rol se aplicó en este entorno". Cómo corregirlo: el Paso 1 está marcado, explícitamente, como representativo — describe con precisión qué pasaría en una máquina con token real, construido sobre el JSON exacto que terraform plan ya produjo (nunca inventado), pero no corrió en este sandbox de escritura. La razón exacta —exit code 55, sin token— está en el Paso 2, inmediatamente después.
Pensar que, porque el rol IAM "podría aplicarse" en principio, eso lo hace más real o más confiable que el guardrail de Bedrock (de jerarquizar lo representativo). Qué pasa: alguien trata la distinción de esta lección como si un tipo de "representativo" fuera mejor que otro. Cómo detectarlo: si tu conclusión es "el rol IAM es casi real, el guardrail es totalmente representativo" como si hubiera grados de confianza distintos en la etiqueta misma. Cómo corregirlo: dentro de esta guía, ambos son igual de representativos —ninguno corrió de verdad aquí—; lo único que cambia es por qué, y esa razón sí importa para alguien que replique esta guía en su propia máquina (el rol se resuelve con un token gratis; el guardrail nunca, sin un plan de pago). La etiqueta "representativo" en sí no tiene grados dentro de esta guía — o corrió, o no corrió.
Asumir que, porque IAM está confirmado como Hobby, todos los futuros recursos IAM de esta guía (o de cualquier guía del ecosistema) se pueden aplicar en cualquier sandbox, sin volver a verificar el token (de generalización sobre el entorno, no solo sobre el servicio). Qué pasa: alguien, en una lección futura de esta guía o de otra, asume automáticamente que "es IAM, entonces aplica sin problema aquí". Cómo detectarlo: si tu expectativa por defecto, en cualquier lección nueva de este ecosistema, es que un apply real corre sin verificar primero si el sandbox específico tiene un token exportado. Cómo corregirlo: la Pregunta 2 de esta lección —¿tiene ESTE entorno un token?— es independiente de la Pregunta 1 —¿está el servicio en Hobby?— y hay que confirmarla cada vez, no asumirla una sola vez para todo el ecosistema. Este sandbox de escritura, específicamente, no tiene token — eso no cambia entre lecciones ni entre guías.
Ejercicios
Ejercicio 1 — Clasifica los siguientes tres comandos como "corrió de verdad en este módulo" o "representativo", y justifica cada uno con la razón exacta. (a) terraform validate sobre bedrock.tf completo. (b) tflocal apply sobre module.bedrock_manifest_extractor_role. (c) tflocal apply sobre module.manifest_extractor_guardrail.
Ver solución
(a) Corrió de verdad — confirmado en las lecciones 4 y 5 de este módulo, sin ninguna dependencia de LocalStack ni de ningún token, por el mecanismo que la lección 1 explicó. (b) Representativo, por el límite del entorno — el servicio (IAM) sí está en Hobby, pero este sandbox de escritura específico no tiene un LOCALSTACK_AUTH_TOKEN exportado, así que ni siquiera un servicio de Hobby puede aplicarse aquí; en una máquina con token real, este comando sí correría de verdad, sin cambios al HCL. (c) Representativo, por el límite del servicio — Bedrock está documentado como "Included in Plans: Ultimate" (lección 6); ningún token de Hobby, en ninguna máquina, resolvería este límite específico — solo un plan de pago Ultimate lo haría.
Ejercicio 2 — Explica por qué esta lección necesitó separar "¿el servicio está en Hobby?" de "¿este sandbox tiene un token?" en dos preguntas distintas, en vez de una sola pregunta de "¿esto aplica aquí?". ¿Qué se perdería si la guía solo contestara la pregunta combinada?
Ver solución
Se perdería la información más útil para cualquiera que replique esta guía en su propia máquina: si la respuesta fuera solo "no, no aplica aquí", sin distinguir la razón, un lector no sabría si su propio intento —en su propia máquina, quizás con un token real— tendría un resultado distinto. Separar las dos preguntas deja claro que el rol IAM es un límite temporal y resoluble (consigue un token, y corre de verdad), mientras que el guardrail de Bedrock es un límite estructural (ningún token de Hobby lo resuelve, sin importar de quién sea o cuándo se consiga). Fusionar ambas preguntas en una sola respuesta binaria habría escondido exactamente esa diferencia, la más útil de las dos.
Ejercicio 3 — Predice qué pasaría si alguien, en su propia máquina, exportara un LOCALSTACK_AUTH_TOKEN de Hobby real y corriera tflocal apply sin -target, sobre andes-cargo-infra/ completo (los diecisiete recursos de la lección 5). ¿Se aplicarían los diecisiete, o el apply fallaría en algún punto?
Ver solución
Los catorce recursos heredados (DynamoDB, Lambda, S3, IAM de las guías anteriores) y el rol BedrockManifestExtractorRole (dos recursos, IAM también) se aplicarían de verdad, sin problema —dieciséis en total—. El único que fallaría es module.manifest_extractor_guardrail.aws_bedrock_guardrail.this —el guardrail de Bedrock—, con el mismo error de licencia que la lección 6 documentó, deteniendo el apply en ese punto específico. Terraform no revertiría automáticamente lo que ya se aplicó exitosamente antes de llegar a ese recurso; el state quedaría con dieciséis recursos creados de verdad y uno pendiente, exactamente la clase de resultado parcial que hace valioso, en un flujo real de CI/CD, tener un plan revisado antes de cualquier apply — el mismo patrón que cicd-and-gitops-on-aws-guide ya construyó.
Resumen y siguiente paso
Esta lección separó, con precisión, dos preguntas que un vistazo superficial podría fusionar en una sola: si un servicio está en el plan Hobby de LocalStack, y si este sandbox de escritura específico tiene un token que permita siquiera arrancar el contenedor. IAM contesta sí a la primera y no a la segunda —un límite del entorno, resoluble con un token real—; Bedrock contesta no a la primera, un límite estructural que ningún token de Hobby resuelve. Ambos quedan representativos en esta guía, por razones completamente distintas, documentadas cada una con su propia evidencia — nunca una sola advertencia genérica cubriendo los dos casos.
Antes de avanzar deberías poder: explicar la diferencia entre un límite "del servicio" y un límite "del entorno de escritura"; predecir, sin ayuda, qué le pasaría a alguien con un token de Hobby real intentando aplicar cada uno de los dos recursos de bedrock.tf; y confirmar, de memoria, que validate y plan nunca tuvieron esta distinción — corrieron igual para ambos, sin excepción, en todo este módulo.
La lección 8 —el proyecto que cierra este módulo— reúne bedrock.tf y modules/bedrock-guardrail/ completos como una sola pieza de portfolio, con el ledger honesto de qué corrió de verdad y qué quedó representativo, y por qué, en un solo lugar.
Recursos
- Módulo 1, lección 7 de esta guía (
07-hands-on-the-honest-attempt-against-bedrock-on-localstack.md) — la fuente delexit code 55real, la base de la Pregunta 2 de esta lección. - Este módulo, lección 6 (
06-the-exact-limit-why-apply-does-not-run-against-localstack-hobby.md) — la fuente de la cita oficial de LocalStack sobre Bedrock, la base de la Pregunta 1 para ese recurso. aws-core-services-guide, Módulo 1 — la fuente original de la confirmación de IAM como servicio de Hobby.- LocalStack Docs — IAM — página de cobertura oficial de IAM, para comparar directamente contra el badge de Bedrock citado en la lección 6.