Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.
Construcciones de capa 2
El repositorio de código AWS CDK abiertoaws-cdk-lib
, denominada, se divide aproximadamente en un paquete por AWS servicio, aunque no siempre es así. Como se mencionó anteriormente, las construcciones L1 se generan automáticamente durante el proceso de compilación, entonces, ¿qué es todo ese código que ves cuando miras dentro del repositorio? Se trata de construcciones L2, que son abstracciones de las construcciones de L1.
Los paquetes también contienen una colección de TypeScript tipos, enumeraciones e interfaces, así como clases auxiliares que añaden más funcionalidad, pero todos esos elementos sirven para construcciones de L2. Todas las construcciones de L2 llaman a sus correspondientes construcciones de L1 en sus constructores tras la instanciación, y se puede acceder a la construcción de L1 resultante que se crea desde la capa 2 de la siguiente manera:
const role = new Bucket(this, "amzn-s3-demo-bucket", {/*...BucketProps*/}); const cfnBucket = role.node.defaultChild;
La construcción L2 toma las propiedades predeterminadas, los métodos prácticos y otros elementos sintácticos y los aplica a la construcción L1. Esto elimina gran parte de la repetición y la verbosidad necesarias para aprovisionar recursos directamente. CloudFormation
Todos los constructos L2 construyen sus correspondientes constructos L1 bajo el capó. Sin embargo, las construcciones L2 en realidad no amplían las construcciones L1. Tanto las construcciones L1 como las L2 heredan una clase especial denominada Construct. En la versión 1, AWS CDK la Construct
clase estaba integrada en el kit de desarrollo, pero en la versión 2 es un paquete independiente independiente.Construct
clase es una construcción L1, L2 o L3. Las construcciones L2 amplían esta clase directamente, mientras que las construcciones L1 extienden una clase denominadaCfnResource
, como se muestra en la siguiente tabla.
Árbol de herencia de L1 |
Árbol de herencia de L2 |
---|---|
Construcción L1 → clase CfnResource → clase abstracta CfnRefElement →→→ clase abstracta CfnElement |
Construcción L2 |
Si tanto las construcciones L1 como las L2 heredan la Construct
clase, ¿por qué las construcciones L2 no amplían simplemente L1? Bueno, las clases entre la Construct
clase y la capa 1 bloquean la construcción L1 como una imagen reflejada del recurso. CloudFormation Contienen métodos abstractos (métodos que deben incluir las clases posteriores)_toCloudFormation
, que obligan a la construcción a generar directamente la sintaxis de salida CloudFormation. Las construcciones de L2 omiten esas clases y las Construct
amplían directamente. Esto les da la flexibilidad de abstraer gran parte del código necesario para las construcciones de L1 al crearlas por separado dentro de sus constructores.
En la sección anterior, se side-by-side comparó un depósito de S3 a partir de una CloudFormation plantilla y ese mismo depósito de S3 renderizado como una construcción de L1. Esa comparación mostró que las propiedades y la sintaxis son casi idénticas, y que la construcción L1 guarda solo tres o cuatro líneas en comparación con la CloudFormation construcción. Ahora comparemos la construcción L1 con la construcción L2 para el mismo segmento de S3:
Construcción L1 para el cubo S3 |
Construcción L2 para cubo S3 |
---|---|
|
|
Como puede ver, la construcción L2 tiene menos de la mitad del tamaño de la construcción L1. Las construcciones L2 utilizan numerosas técnicas para lograr esta consolidación. Algunas de estas técnicas se aplican a un solo constructo L2, pero otras se pueden reutilizar en varios constructos para separarlos en su propia clase para su reutilización. Las construcciones de L2 consolidan la CloudFormation sintaxis de varias maneras, como se explica en las siguientes secciones.
Propiedades predeterminadas
La forma más sencilla de consolidar el código para aprovisionar un recurso es convertir la configuración de propiedades más común en valores predeterminados. AWS CDK Tiene acceso a potentes lenguajes de programación y CloudFormation no los tiene, por lo que estos valores predeterminados suelen ser de naturaleza condicional. A veces, se pueden eliminar varias líneas de CloudFormation configuración del AWS CDK código porque esas configuraciones se pueden deducir de los valores de otras propiedades que se pasan a la construcción.
Estructuras, tipos e interfaces
Aunque AWS CDK está disponible en varios lenguajes de programación, está escrito de forma nativa TypeScript, por lo que el sistema de tipos de ese lenguaje se utiliza para definir los tipos que componen las construcciones L2. Profundizar en ese sistema de tipos va más allá del alcance de esta guía; consulte la TypeScriptdocumentacióntype
describe qué tipo de datos contiene una variable en particular. Pueden ser datos básicos, como unstring
, o datos más complejos, como unobject
. A TypeScript interface
es otra forma de expresar el tipo de TypeScript objeto y a struct
es otro nombre para una interfaz.
TypeScript no usa el término estructura, pero si consulta la referencia de la AWS CDK API, verá que una estructura es en realidad solo otra TypeScript interfaz dentro del código. La referencia de la API también se refiere a determinadas interfaces como interfaces. Si las estructuras y las interfaces son lo mismo, ¿por qué la AWS CDK documentación hace una distinción entre ellas?
Lo que AWS CDK se denomina estructuras son interfaces que representan cualquier objeto utilizado por una construcción L2. Esto incluye los tipos de objetos de los argumentos de propiedad que se pasan a la construcción L2 durante la instanciación, como BucketProps
la construcción S3 Bucket y TableProps
la construcción Tabla de DynamoDB, así como otras TypeScript interfaces que se utilizan en. AWS CDKEn resumen, si se trata de una TypeScript interfaz dentro de AWS CDK y su nombre no lleva el prefijo de la letraI
, se denomina estructura. AWS CDK
Por el contrario, AWS CDK utiliza el término interfaz para representar los elementos básicos; un objeto simple debería considerarse una representación adecuada de una construcción o clase auxiliar en particular. Es decir, una interfaz describe cuáles deben ser las propiedades públicas de una construcción L2. Todos los nombres de las AWS CDK interfaces son los nombres de las construcciones o clases auxiliares existentes con el prefijo de la letra. I
Todas las construcciones de L2 amplían la Construct
clase, pero también implementan su interfaz correspondiente. Por lo tanto, la construcción L2 Bucket
implementa la interfaz. IBucket
Métodos estáticos
Cada instancia de una construcción L2 también es una instancia de su interfaz correspondiente, pero no ocurre lo contrario. Esto es importante a la hora de analizar una estructura para ver qué tipos de datos son necesarios. Si una estructura tiene una propiedad llamadabucket
, que requiere el tipo de datosIBucket
, puede pasar un objeto que contenga las propiedades enumeradas en la IBucket
interfaz o una instancia de una capa 2. Bucket
Cualquiera de las dos funcionaría. Sin embargo, si esa bucket
propiedad requiriera una L2Bucket
, solo podrías pasar una Bucket
instancia en ese campo.
Esta distinción se vuelve muy importante cuando importas recursos preexistentes a tu pila. Puedes crear una construcción de L2 para cualquier recurso que sea nativo de tu pila, pero si necesitas hacer referencia a un recurso que se creó fuera de la pila, tienes que usar la interfaz de esa construcción de L2. Esto se debe a que al crear una construcción de L2 se crea un recurso nuevo si aún no existe uno dentro de esa pila. Las referencias a los recursos existentes deben ser objetos simples que se ajusten a la interfaz de esa construcción de L2.
Para facilitar esto en la práctica, la mayoría de las construcciones de L2 tienen un conjunto de métodos estáticos asociados que devuelven la interfaz de esa construcción de L2. Estos métodos estáticos suelen empezar con la palabra. from
Los dos primeros argumentos que se pasan a estos métodos son los mismos scope
y id
son necesarios para una construcción L2 estándar. Sin embargo, el tercer argumento no props
es más que un pequeño subconjunto de propiedades (o, a veces, solo una propiedad) que define una interfaz. Por esta razón, cuando se pasa una construcción L2, en la mayoría de los casos solo se requieren los elementos de la interfaz. Esto permite utilizar también los recursos importados, siempre que sea posible.
// Example of referencing an external S3 bucket const preExistingBucket = Bucket.fromBucketName(this, "external-bucket", "name-of-bucket-that-already-exists");
Sin embargo, no debes confiar demasiado en las interfaces. Debe importar los recursos y usar las interfaces directamente solo cuando sea absolutamente necesario, ya que las interfaces no proporcionan muchas de las propiedades (como los métodos de ayuda) que hacen que una construcción de L2 sea tan potente.
Métodos auxiliares
Una construcción L2 es una clase programática y no un objeto simple, por lo que puede exponer métodos de clase que permiten manipular la configuración de los recursos una vez realizada la instanciación. Un buen ejemplo de ello es la construcción de roles L2 AWS Identity and Access Management (IAM). Los siguientes fragmentos muestran dos formas de crear el mismo rol de IAM mediante la construcción L2. Role
Sin un método auxiliar:
const role = new Role(this, "my-iam-role", { assumedBy: new FederatedPrincipal('my-identity-provider.com'), managedPolicies: [ ManagedPolicy.fromAwsManagedPolicyName("ReadOnlyAccess") ], inlinePolicies: { lambdaPolicy: new PolicyDocument({ statements: [ new PolicyStatement({ effect: Effect.ALLOW, actions: [ 'lambda:UpdateFunctionCode' ], resources: [ 'arn:aws:lambda:us-east-1:123456789012:function:my-function' ] }) ] }) } });
Con un método auxiliar:
const role = new Role(this, "my-iam-role", { assumedBy: new FederatedPrincipal('my-identity-provider.com') }); role.addManagedPolicy(ManagedPolicy.fromAwsManagedPolicyName("ReadOnlyAccess")); role.attachInlinePolicy(new Policy(this, "lambda-policy", { policyName: "lambdaPolicy", statements: [ new PolicyStatement({ effect: Effect.ALLOW, actions: [ 'lambda:UpdateFunctionCode' ], resources: [ 'arn:aws:lambda:us-east-1:123456789012:function:my-function' ] }) ] }));
La capacidad de utilizar métodos de instancia para manipular la configuración de los recursos después de la instanciación proporciona a las construcciones de L2 mucha flexibilidad adicional con respecto a la capa anterior. Las construcciones de nivel 1 también heredan algunos métodos de recursos (por ejemploaddPropertyOverride
), pero no se obtienen métodos diseñados específicamente para ese recurso y sus propiedades hasta la segunda capa.
Enums
CloudFormation La sintaxis suele requerir que se especifiquen muchos detalles para poder aprovisionar un recurso correctamente. Sin embargo, la mayoría de los casos de uso suelen estar cubiertos por solo un puñado de configuraciones. La representación de esas configuraciones mediante una serie de valores enumerados puede reducir considerablemente la cantidad de código necesaria.
Por ejemplo, en el ejemplo de código L2 del bucket S3 descrito anteriormente en esta sección, debe usar la bucketEncryption
propiedad de la CloudFormation plantilla para proporcionar todos los detalles, incluido el nombre del algoritmo de cifrado que se va a utilizar. En su lugar, AWS CDK
proporciona la BucketEncryption
enumeración, que utiliza las cinco formas más comunes de cifrado por cubos y permite expresar cada una de ellas mediante nombres de variables individuales.
¿Qué pasa con los casos extremos que no están incluidos en las enumeraciones? Uno de los objetivos de una construcción de nivel 2 es simplificar la tarea de aprovisionamiento de un recurso de capa 1, por lo que es posible que algunos casos extremos que se utilizan con menos frecuencia no se admitan en la capa 2. Para respaldar estos casos extremos, AWS CDK permite manipular las propiedades de los CloudFormation recursos subyacentes directamente mediante el addPropertyOverridemétodo. Para obtener más información sobre las anulaciones de propiedades, consulte la sección de prácticas recomendadas de esta guía y la sección Abstracciones y trampillas de escape de la documentación. AWS CDK
Clases auxiliares
A veces, una enumeración no puede cumplir con la lógica programática necesaria para configurar un recurso para un caso de uso determinado. En estas situaciones, AWS CDK a menudo se ofrece una clase auxiliar en su lugar. Una enumeración es un objeto simple que ofrece una serie de pares clave-valor, mientras que una clase auxiliar ofrece todas las capacidades de una clase. TypeScript Una clase auxiliar aún puede actuar como una enumeración al exponer propiedades estáticas, pero esas propiedades podrían tener sus valores establecidos internamente con lógica condicional en el constructor de la clase auxiliar o en un método auxiliar.
Por lo tanto, aunque la BucketEncryption
enumeración puede reducir la cantidad de código necesaria para configurar un algoritmo de cifrado en un bucket de S3, esa misma estrategia no funcionaría para establecer la duración del tiempo, ya que hay demasiados valores posibles entre los que elegir. Crear una enumeración para cada valor sería mucho más difícil de lo que vale la pena. Por este motivo, se utiliza una clase auxiliar para los ajustes de configuración predeterminados de S3 Object Lock de un bucket de S3, tal como los representa la ObjectLockRetentionclase. ObjectLockRetention
contiene dos métodos estáticos: uno para la retención de la conformidad y otro para la retención de la gobernanza. Ambos métodos utilizan una instancia de la clase auxiliar Duration como argumento para expresar el tiempo durante el que se debe configurar el bloqueo.
Otro ejemplo es la clase AWS Lambda auxiliar Runtime. A primera vista, puede parecer que las propiedades estáticas asociadas a esta clase podrían gestionarse mediante una enumeración. Sin embargo, a simple vista, el valor de cada propiedad representa una instancia de la propia Runtime
clase, por lo que la lógica utilizada en el constructor de la clase no podría lograrse dentro de una enumeración.