AWS - Parte II - Preparazione progetto

Introduzione

Nell’ultimo post abbiamo messo in piedi i nostri account, tra cui l’account Development dove andremo a fare i primi sviluppi.

Oggi invece vedremo come impostare un ipotetico progetto dove oltre all’applicativo andremo a definire anche l’infrastruttura, pratica comunemente chiamata IaC, Infrastructure as Code.

Download e setup AWS CLI

Per prima cosa scarichiamo e installiamo il programma AWS CLI versione 2 per il proprio sistema operativo. Una guida e’ fornita da AWS qui.

Setup credenziali

Installata la CLI di AWS impostiamo il nostro profilo Development.

Questo ci permettera’ di usare il nostro account Development direttamente da CLI senza andare ogni volta a fare copia e incolla delle credenziali.

aws configure sso
SSO session name (Recommended): Development
SSO start URL [None]: https://roberttimistest.awsapps.com/start#/
SSO region [None]: eu-central-1
SSO registration scopes [sso:account:access]: # Premere invio

Fatto cio’ vi verra’ aperta una schermata su browser dove andremo a confermare di avere lo stesso codice:

allow

Tornando sul terminale ora avremo due scelte:

There are 2 AWS accounts available to you.
> Administration, [email protected] (100530710461)
> Development, [email protected] (056415619219)

Scegliamo Development:

Using the account ID 056415619219
The only role available to you is: AdministratorAccess
Using the role name AdministratorAccess
CLI default client Region [None]: eu-central-1
CLI default output format [None]: json
CLI profile name [AdministratorAccess-056415619219]: Development

Fatto cio’ ora siamo pronti ad usare il nostro account direttamente da CLI specificando con il flag —profile l’account che vogliamo usare.

Se la sessione scade, dove secondo le impostazioni che abbiamo lasciato dovrebbe durare 1 ora, bastera’ fare aws sso login —profile .

Creazione e setup progetto

Iniziamo quindi a impostare il nostro progetto. In questo tutorial andremo ad utilizzare SST, un framework scritto in Typescript che semplifica notevolmente gli sviluppi su AWS tramite CDK, il Cloud Development Kit, ovvero la libreria che viene usata tipicamente per definire l’infrastruttura tramite codice.

Questo framework ci permette di usufruire di alcuni costrutti comodi, ma anche di utilizzare direttamente la CDK.

Io lo uso sempre anche se non ho bisogno dei costrutti proposti, perche’ organizza il codice in una maniera che personalmente apprezzo.

Un’altra cosa bella di SST e’ che ci permettera’ di fare debug direttamente nella console di lambda, container, tabelle dynamo DB e altro.

Per la gestione dei pacchetti node io utilizzero’ PNPM, ma comandi equivalenti esistono anche per Yarn, NPN e simili.

Mettiamoci quindi in una cartella a piacere e lanciamo i seguenti comandi:

pnpm create sst app
cd app
pnpm i
git init

Una volta terminata l’installazione ci troveremo diverse cartelle e file:

tree . -I 'node_modules'
.
├── package.json
├── packages
│   ├── core
│   │   ├── package.json
│   │   ├── src
│   │   │   ├── event.ts
│   │   │   └── todo.ts
│   │   ├── sst-env.d.ts
│   │   └── tsconfig.json
│   └── functions
│       ├── package.json
│       ├── src
│       │   ├── events
│       │   │   └── todo-created.ts
│       │   ├── lambda.ts
│       │   └── todo.ts
│       ├── sst-env.d.ts
│       └── tsconfig.json
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── sst.config.ts
├── stacks
│   └── MyStack.ts
└── tsconfig.json

All’interno di packages troviamo core e functions.

L’idea e’ quella di organizzare separando il nucleo della nostra logica in core, in modo da poterla riutilizzare su piu’ fronti: Lambda, Container Fargate, Jobs, ecc…

Dentro functions invece definiamo direttamente gli handler delle nostre lambda e SST tramite esbuild impacchettera’ il codice e le dipendenze e fara’ il deploy su AWS. All’interno di stacks invece andremo a definire i nostri stack CDK, ovvero unita’ di risorse e servizi da andare a creare su AWS.

Per prima cosa modifichiamo sst.config.ts per utilizzare il nostro profilo e la nostra regione:

import { SSTConfig } from "sst";
import { API } from "./stacks/MyStack";

export default {
  config(input) {
    const profiles: Record<string, string> = {
      dev: "Development",
    };

    return {
      name: "app",
      region: "eu-central-1", // modificare qui la regione
      // aggiungiamo il profilo
      profile: profiles[input.stage || "dev"] || profiles.dev,
    };
  },
  stacks(app) {
    // impostazioni di default per le lambda
    app.setDefaultFunctionProps({
      runtime: "nodejs18.x",
      architecture: "arm_64",
    });

    // facciamo in modo che alcune risorse tipo S3 e tabelle Dynamo
    // vengano rimosse in automatico su Development
    if (app.stage !== "prod") {
      app.setDefaultRemovalPolicy("destroy");
    }

    app.stack(API);
  },
} satisfies SSTConfig;

A questo punto possiamo provare a lanciare questo progetto di prova usando il comando pnpm sst dev

pnpm sst dev
Please enter a name you’d like to use for your personal stage. Or hit enter to use rob: # Premere invio
 Deploying bootstrap stack, this only needs to happen once
SST v2.25.1  ready!

  App:     app
   Stage:   rob
   Console: https://console.sst.dev

|  API PUBLISH_ASSETS_COMPLETE
   ...

  Deployed:
   API
   ApiEndpoint: https://tjqwcalfc4.execute-api.eu-central-1.amazonaws.com

Connessione console

Andando su https://console.sst.dev avremo la nostra console dalla quale possiamo interagire con lo stack.

Una volta fatto l’accesso inserendo l’email, creiamo un workspace e andiamo a cliccare su Connect an AWS Account nella schermata seguente:

SST

Spuntiamo I acknowledge that AWS CloudFormation might create IAM resources with custom names. e clicchiamo su Create stack.

SST stack

Una volta terminato sulla nostra console avremo questa vista, con tutte le risorse:

SST console

Sulla console clicchiamo sull’endpoint:

SST console get

E invochiamo la nostra lambda:

curl https://tjqwcalfc4.execute-api.eu-central-1.amazonaws.com
Hello world. The time is 2023-09-15T14:56:30.434Z%

Possiamo gia’ notare da terminale che avremo queste nuovi log:

|  Invoked packages/functions/src/lambda.handler
|  Built packages/functions/src/lambda.handler
|  Done in 177ms

E che nella console avremo il dettaglio dell’invocazione e della risposta:

SST console log

Modificando il codice della lambda, questo verra’ automaticamente caricato e sara’ pronto per la prossima invocazione:

// packages/functions/src/lambda.ts
import { ApiHandler } from "sst/node/api";

export const handler = ApiHandler(async (_evt) => {
  return {
    statusCode: 200,
    body: `Ciao Mondo. L'ora e' ${new Date().toISOString()}`,
  };
});

Invocando:

curl https://tjqwcalfc4.execute-api.eu-central-1.amazonaws.com
Ciao Mondo. L'ora e' 2023-09-15T15:06:03.208Z%

Conclusione

Una volta che avete finito potete distruggere lo stack con pnpm sst remove.

Se avete richieste particolari scrivetemi su [email protected]