martes, 5 de octubre de 2021

MODULE_NOT_FOUND using New Relic with Nest (NestJS) 8

When adding the newrelic.js file in the root of the NestJS project, and then building it and running it in prod mode:

> node dist/main

node:internal/modules/cjs/loader:936

  throw err;

  ^

Error: Cannot find module '/.../apps/backend/dist/main'

    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)

    at Function.Module._load (node:internal/modules/cjs/loader:778:27)

    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:79:12)

    at node:internal/main/run_main_module:17:47 {

  code: 'MODULE_NOT_FOUND',

  requireStack: []

}

In this case, tsc compiles just the newrelic.js file in your dist folder.


Move the newrelic.js to the same directory as your main.ts file (normally src/).

Complete installation instructions: https://discuss.newrelic.com/t/new-relic-for-nestjs/91812. I didn't follow all those for Nest 8 though. In my case:

  1. Same.
  2. Same.
  3. Same.
  4. Same. It didn't work with import _ from 'newrelic';. In that way, it got stripped from the compiled JS.
  5. 6. 7. I didn't need to. The newrelic.js automatically ended up in the dist/ folder.





jueves, 2 de septiembre de 2021

MongoDB Atlas notes

Notes

  • Remember to create a Project per environment (ref)
    • Every database user in a project has access to all the database deployments in the project (you can still restrict access to specific database names across all the deployments)
    • The VPC peering configuration is done per project, then at the AWS side, any peered VPC will have access to all the database deployments and databases)

martes, 31 de agosto de 2021

Stopped reason ResourceInitializationError: failed to download env files: file download command: non empty error stream: RequestCanceled: request context canceled caused by: context deadline exceeded

Error: Stopped reason ResourceInitializationError: failed to download env files: file download command: non empty error stream: RequestCanceled: request context canceled caused by: context deadline exceeded

Using: CloudFormation, ECS Fargate

For some reason, the public subnets where the ECS Fargate instances were deployed lost the explicit association to a route table that I also had in the same CloufFormation template. I had to comment the related AWS::EC2::SubnetRouteTableAssociation's, update the stack, uncomment them and update the stack again.

querySrv ENODATA checking a Mongo SRV record using Node

The Mongo driver prefix the "hostname" with "_mongodb._tcp.".

Reference https://github.com/mongodb/node-mongodb-native/blob/e69d9925713ede3bd80d7d23a6df60c6dd4542ef/src/connection_string.ts#L78

function getMongoSrvHostnameFromDbConnectionString(dbConnectionString: string) {
const startIndex = dbConnectionString.indexOf('@') + 1;
const endIndex = dbConnectionString.indexOf('/', startIndex);
const dbHostname = dbConnectionString.substring(startIndex, endIndex);
// Ref: https://github.com/mongodb/node-mongodb-native/blob/e69d9925713ede3bd80d7d23a6df60c6dd4542ef/src/connection_string.ts#L78
return `_mongodb._tcp.${dbHostname}`;
}

async function resolveSrvHostnamesOrError(
hostname: string,
): Promise<string[] | string> {
const resolveSrv = util.promisify(dns.resolveSrv);
const lookup = util.promisify(dns.lookup);
let ipsOrError: string[] | string = null;
try {
const resolvedHostnames = await resolveSrv(hostname);
const resolvedAddresses = await Promise.all(
resolvedHostnames.map(
async (resolvedHostname) => await lookup(resolvedHostname.name),
),
);

return await Promise.all(
resolvedAddresses.map(
async (resolvedAddress) => (await resolvedAddress).address,
),
);
} catch (err) {
console.log(err);
const e: Error = err;
ipsOrError = e.message;
return ipsOrError;
}
}

miércoles, 18 de agosto de 2021

CloudFormation: resource "already exists in stack" after updating logical names

After refactoring a CloudFormation to have better logical names, I got a bunch of "already exists in stack" errors. Example:

2021-08-18 15:22:20 UTC+1000 BackendEcsTaskRole CREATE_FAILED x-ecs-executtaskion-role already exists in stack arn:aws:cloudformation:us-east-1:y:stack/x/ff05-11eb-80bd
2021-08-18 15:22:20 UTC+1000 BackendLogGroup CREATE_FAILED /x/backend already exists in stack arn:aws:cloudformation:us-east-1:616020545883:stack/x/ff05-11eb-80bd
2021-08-18 15:22:20 UTC+1000 BackendEcsExecutionRole CREATE_FAILED x-ecs-execution-role already exists in stack arn:aws:cloudformation:us-east-1:x:stack/x/ff05-11eb-80bd
2021-08-18 15:22:20 UTC+1000 BackendEcsCluster CREATE_FAILED x-ecs-cluster already exists in stack arn:aws:cloudformation:us-east-1:x:stack/x/ff05-11eb-80bd

If the resources can be safely deleted, one option is to create a temporary template with those conflicting resources removed. Submit it and have CloudFormation delete the physical resources. Then, submit again the refactored template letting CloudFormation create them again succesfully.


viernes, 9 de julio de 2021

AWS ECS cli calls (update-service, create-service) hang on CI/CD (Buildkite, CircleCI)

The AWS CLI v2 tries to use a client-side pager by default. Then, in a lot of cases, it'll wait for interactive input before returning 🤷🏻‍♂️. You can "use the --no-cli-pager command-line option to disable the pager for a single command use" (or use any of the other options described there).

Some SO questions around this:


jueves, 21 de enero de 2021

Deploying cp100-bookshelf on GCP App Engine (sample Python bookshelf app)

In Google Cloud Shell, using Python 2 (the version I get in app.yml, runtime: python27)

mkdir src

cd src git clone https://github.com/GoogleCloudPlatformTraining/cp100-bookshelf.git

Edit cloud-storage/bookshelf/storage.py line 20, change


from werkzeug import secure_filename


to


from werkzeug.utils import secure_filename


Otherwise, you'll get:


ImportError: cannot import name secure_filename

at

<module> (/base/data/home/apps/.../bookshelf/storage.py:20)


Then:


cd cloud-storage

pip install -t lib -r requirements.txt

gcloud app deploy


cd app-engine

pip install -t lib -r requirements.txt

gcloud app deploy




If you don't pip install requirements, you'll get something like:

ValueError: virtualenv: cannot access lib: No such virtualenv or site directory
at add (/base/alloc/tmpfs/dynamic_runtimes/python27g/.../python27/python27_lib/versions/1/google/appengine/ext/vendor/__init__.py:44)