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: