From c052b9a86974a91876233e3c8f59e176170383f1 Mon Sep 17 00:00:00 2001 From: Davide Marro <131177412+drmarro@users.noreply.github.com> Date: Tue, 27 Jun 2023 16:03:29 +0200 Subject: [PATCH] [IOPLT-25] Fixing io-functions-app configuration in order to be launched on local env (#280) * Updating docker-compose and Dockerfile * Fixing fixtures, docker-compose and README * Fixing readme and Dockerfile functions-node-18 * Fixing fixtures dockerfile --- README.md | 31 +++++++++++++- docker-compose.yml | 32 +++++++------- docker/fixtures/Dockerfile | 7 +++- docker/fixtures/index.ts | 35 ++++++++-------- docker/functions-node-18/Dockerfile | 3 +- env.example | 65 ++++++++++++++++++++++------- 6 files changed, 119 insertions(+), 54 deletions(-) diff --git a/README.md b/README.md index 5c56da80..71977012 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,6 @@ following contents: "ConnectionStrings": {} } ``` - ### Starting the functions runtime ``` @@ -54,3 +53,33 @@ $ yarn start ``` The server should reload automatically when the code changes. + +### Starting the io-functinos-app docker image +If you are trying to run the docker images on your local environment (through the docker-compose) you must set the following variables in the `local.settings.json` file: + * AzureWebJobsStorage + * QueueStorageConnection + * AssetsStorageConnection +With this **connection string** as value: + * DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite:10000/devstoreaccount1;QueueEndpoint=http://azurite:10001/devstoreaccount1;TableEndpoint=http://azurite:10002/devstoreaccount1; + +The **connection string** has a default value needed to connect to Azurite, a local emulator used to provide a free local environment for testing an Azure Blob, Queue Storage, and Table Storage application. +As for docker-compose instructions, the Azurite docker image runs the Blob service on port 10000, the Queue service on port 10001 and the Table service on port 10002. +If Azurite is executed on different address or ports, the **connection string** must be changed according to the service. + +These must be the other variables values for the `local.settings.json` file: + * COSMOSDB_URI=https://cosmosdb:3000/ + * COSMOSDB_KEY=dummykey + * COSMOSDB_NAME=testdb + +The COSMOSDB_URI must be the address of the cosmos db instance specified in the docker-compose.yml file while the COSMOSDB_KEY and COSMOSDB_NAME could be totally randomic. + +Then, copy `.env.example` to `.env` and fill the variables with the following mandatory variables: + * LogsStorageConnection=**connection string** + * NOTIFICATIONS_STORAGE_CONNECTION_STRING=**connection string** + * EventsQueueStorageConnection=**connection string** + * FN_APP_STORAGE_CONNECTION_STRING=**connection string** + * DURABLE_FUNCTION_STORAGE_CONNECTION_STRING=**connection string** + +The **connection string** is the same used for the AzureWebJobsStorage in the `local.settings.json` file. + +Then you can run `docker-compose up -d` to start the containers. diff --git a/docker-compose.yml b/docker-compose.yml index 6eb55174..39a7c0db 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,7 +9,7 @@ services: dockerfile: docker/functions/Dockerfile # environment: # - languageWorkers__node__arguments=--inspect=0.0.0.0:5858 - env_file: + env_file: - .env working_dir: /usr/src/app ports: @@ -18,7 +18,8 @@ services: networks: - io-fn depends_on: - - fnstorage + - azurite + - functions-node-18 volumes: - .:/usr/src/app labels: @@ -37,11 +38,19 @@ services: # apply middleware to route - "traefik.http.routers.functions.middlewares=testHeader" - fnstorage: - image: azurite + functions-node-18: + image: functions-node-18 build: context: ./ - dockerfile: docker/azurite/Dockerfile + dockerfile: docker/functions-node-18/Dockerfile + command: /bin/true + + azurite: + image: mcr.microsoft.com/azure-storage/azurite + container_name: azurite + hostname: azurite + restart: always + command: "azurite --blobHost 0.0.0.0 --blobPort 10000 --queueHost 0.0.0.0 --queuePort 10001 --tableHost 0.0.0.0 --tablePort 10002" ports: - "10000:10000" - "10001:10001" @@ -49,20 +58,9 @@ services: networks: - io-fn - storage: - image: azurite - command: ["sh", "-c", "node bin/azurite -l /opt/azurite/folder --blobPort 10003 --queuePort 10004 --tablePort 10005"] - ports: - - "10003:10003" - - "10004:10004" - - "10005:10005" - depends_on: - - fnstorage - networks: - - io-fn - cosmosdb: image: cosmosdb + container_name: cosmosdb env_file: - .env build: diff --git a/docker/fixtures/Dockerfile b/docker/fixtures/Dockerfile index 94451580..c66e540e 100644 --- a/docker/fixtures/Dockerfile +++ b/docker/fixtures/Dockerfile @@ -4,9 +4,12 @@ WORKDIR /opt/cosmosdb RUN apk add git RUN npm install -g ts-node typescript && \ - npm install documentdb @types/documentdb io-functions-commons \ - io-ts@1.8.5 fp-ts@1.12.0 @pagopa/ts-commons + npm install documentdb @types/documentdb @pagopa/io-functions-commons \ + io-ts@2.2.20 fp-ts@2.16.0 @pagopa/ts-commons +COPY ./utils /utils +COPY ./node_modules /node_modules +COPY ./tsconfig.json /tsconfig.json COPY docker/fixtures/index.ts /opt/cosmosdb CMD ["sh", "-c", "ts-node index"] diff --git a/docker/fixtures/index.ts b/docker/fixtures/index.ts index 7b754c2d..9876fd0e 100644 --- a/docker/fixtures/index.ts +++ b/docker/fixtures/index.ts @@ -4,21 +4,21 @@ import { ContainerResponse, CosmosClient, Database } from "@azure/cosmos"; import { NewProfile, - Profile, PROFILE_COLLECTION_NAME, + Profile, ProfileModel } from "@pagopa/io-functions-commons/dist/src/models/profile"; import { NewService, - Service, SERVICE_COLLECTION_NAME, + Service, ServiceModel } from "@pagopa/io-functions-commons/dist/src/models/service"; +import { pipe } from "fp-ts/function"; import { sequenceT } from "fp-ts/lib/Apply"; +import * as E from "fp-ts/lib/Either"; import { toError } from "fp-ts/lib/Either"; import * as TE from "fp-ts/lib/TaskEither"; -import * as E from "fp-ts/lib/Either"; -import { pipe } from "fp-ts/function"; import { getConfigOrThrow } from "../../utils/config"; const config = getConfigOrThrow(); @@ -37,7 +37,7 @@ const createDatabase = (databaseName: string): TE.TaskEither => () => cosmosdbClient.databases.create({ id: databaseName }), toError ), - TE.map(response => response.database) + TE.map(response => response.database), ) const createCollection = ( @@ -46,8 +46,9 @@ const createCollection = ( partitionKey: string ): TE.TaskEither => TE.tryCatch( - () => db.containers.createIfNotExists({ id: collectionName, partitionKey }), + () => db.containers.createIfNotExists({ id: collectionName, partitionKey: `/${partitionKey}` }), toError + ); const aService: Service = pipe( @@ -63,7 +64,7 @@ const aService: Service = pipe( serviceId: config.REQ_SERVICE_ID, serviceName: "MyServiceName" }), - E.getOrElse(() => { + E.getOrElseW(() => { throw new Error("Cannot decode service payload."); }) ) @@ -73,7 +74,7 @@ const aNewService = pipe( ...aService, kind: "INewService" }), - E.getOrElse(() => { + E.getOrElseW(() => { throw new Error("Cannot decode new service."); })) @@ -87,7 +88,7 @@ const aProfile: Profile = pipe( isInboxEnabled: true, isWebhookEnabled: true }), - E.getOrElse(() => { + E.getOrElseW(() => { throw new Error("Cannot decode profile payload."); })) @@ -95,7 +96,7 @@ const aNewProfile = pipe( NewProfile.decode({ ...aProfile, kind: "INewProfile" - }), E.getOrElse(() => { + }), E.getOrElseW(() => { throw new Error("Cannot decode new profile."); }) ) @@ -122,12 +123,12 @@ pipe( aNewProfile ) ), - TE.mapLeft(_ => new Error(`CosmosError: ${_.kind}`)) + TE.bimap(err => { + console.log(`Failure during the fixtures generation: ${JSON.stringify(err)}`); + return new Error("Failure during the fixtures generation"); + }, + result => console.log(`Fixtures generated: ${JSON.stringify(result)}`) + ) ) ) -)().then( - // eslint-disable-next-line no-console - _ => console.log(`Successfully created fixtures`), - // eslint-disable-next-line no-console - _ => console.error(`Failed generate fixtures ${_.message}`) -) +)() \ No newline at end of file diff --git a/docker/functions-node-18/Dockerfile b/docker/functions-node-18/Dockerfile index 294b59a8..4eaabe86 100644 --- a/docker/functions-node-18/Dockerfile +++ b/docker/functions-node-18/Dockerfile @@ -2,6 +2,7 @@ FROM node:18.13.0 WORKDIR /usr/src/app +RUN apt-key update RUN apt-get update RUN apt-get install -y lsb-release RUN curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg @@ -12,7 +13,7 @@ RUN apt-get update RUN apt-get install -y azure-functions-core-tools-4 RUN apt-get install -y apt-transport-https RUN apt-get update -RUN apt-get install -y dotnet-sdk-3.1 +RUN apt-get install -y --no-install-recommends dotnet-sdk-6.0 ENV AzureWebJobsScriptRoot=/usr/src/app \ AzureFunctionsJobHost__Logging__Console__IsEnabled=true diff --git a/env.example b/env.example index adbb31a0..de14360c 100644 --- a/env.example +++ b/env.example @@ -1,22 +1,55 @@ +NODE_ENV=dev +NODE_TLS_REJECT_UNAUTHORIZED=0 + +FUNCTIONS_WORKER_RUNTIME=node +WEBSITE_NODE_DEFAULT_VERSION=14.16.0 APPINSIGHTS_INSTRUMENTATIONKEY=foo -COSMOSDB_KEY=key -COSMOSDB_NAME=cosmoname -COSMOSDB_URI=uri -FUNCTIONS_PUBLIC_URL=url +MESSAGE_CONTAINER_NAME=message-content +SUBSCRIPTIONS_FEED_TABLE=SubscriptionsFeedByDay + +LogsStorageConnection=storageConnectionString +NOTIFICATIONS_STORAGE_CONNECTION_STRING=storageConnectionString +EventsQueueStorageConnection=storageConnectionString +FN_APP_STORAGE_CONNECTION_STRING=storageConnectionString +DURABLE_FUNCTION_STORAGE_CONNECTION_STRING=storageConnectionString + +MAIL_FROM=sender@example.com +FUNCTIONS_PUBLIC_URL=http://functions-public.localhost +PUBLIC_API_URL=http://host.docker.internal:80/functions-services +PUBLIC_API_KEY=api_key +SPID_LOGS_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhiXpvLD8UMMUy1T2JCzo/Sj5E\nl09Fs0z2U4aA37BrXlSo1DwQ2O9i2XFxXGJmE83siSWEfRlMWlabMu7Yj6dkZvmj\ndGIO4gotO33TgiAQcwRo+4pwjoCN7Td47yssCcj9C727zBt+Br+XK7B1bRcqjc0J\nYdF4yiVtD7G4RDXmRQIDAQAB\n-----END PUBLIC KEY-----" +DPO_EMAIL_ADDRESS=dpo@example.com +SLOT_TASK_HUBNAME=IoFunctionApp MAILHOG_HOSTNAME=mailhog -MAIL_FROM=mail@example.it -MESSAGE_CONTAINER_NAME=msg -NODE_ENV=dev -PUBLIC_API_KEY=key -PUBLIC_API_URL=url -QueueStorageConnection=foobar -EventsQueueStorageConnection=foobar + +NOTIFICATIONS_QUEUE_NAME=push-notifications +AZURE_NH_HUB_NAME=io-notification-hub-mock +AZURE_NH_ENDPOINT=Endpoint=sb://host.docker.internal:30000;SharedAccessKeyName=DefaultFullSharedAccessSignature;SharedAccessKey=foobar +AZURE_ENABLE_STRICT_SSL=false + REQ_SERVICE_ID=req_id_dev +MIGRATE_SERVICES_PREFERENCES_PROFILE_QUEUE_NAME=profile-migrate-services-preferences-from-legacy + +EUCOVIDCERT_PROFILE_CREATED_QUEUE_NAME=eucovidcert-profile-created +FF_NEW_USERS_EUCOVIDCERT_ENABLED=true + +EventsQueueName=events + +COSMOSDB_URI=https://cosmosdb:3000/ +COSMOSDB_KEY=dummykey +COSMOSDB_NAME=testdb +CUSTOMCONNSTR_COSMOSDB_KEY=dummykey +CUSTOMCONNSTR_COSMOSDB_URI=https://cosmosdb:3000/ +COSMOSDB_PORT=3000 + SPID_BLOB_CONTAINER_NAME=spidblob SPID_BLOB_STORAGE_CONNECTION_STRING=foobar -SPID_LOGS_PUBLIC_KEY="-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDhiXpvLD8UMMUy1T2JCzo/Sj5E\nl09Fs0z2U4aA37BrXlSo1DwQ2O9i2XFxXGJmE83siSWEfRlMWlabMu7Yj6dkZvmj\ndGIO4gotO33TgiAQcwRo+4pwjoCN7Td47yssCcj9C727zBt+Br+XK7B1bRcqjc0J\nYdF4yiVtD7G4RDXmRQIDAQAB\n-----END PUBLIC KEY-----" -SUBSCRIPTIONS_FEED_TABLE=feed -MIGRATE_SERVICES_PREFERENCES_PROFILE_QUEUE_NAME=migratequeue -FN_APP_STORAGE_CONNECTION_STRING=foobar BETA_USERS=[] -FF_TEMPLATE_EMAIL=NONE \ No newline at end of file +FF_TEMPLATE_EMAIL=NONE + +API_GATEWAY_PORT=80 +REQ_USER_GROUPS=req_groups + +FUNCTION_PORT=7071 +WAIT_MS=5000 +SHOW_LOGS=false \ No newline at end of file