Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions apps/auth-cron/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,29 +35,30 @@
},
"dependencies": {
"@aws-sdk/client-s3": "catalog:",
"@godaddy/terminus": "^4.12.0",
"@godaddy/terminus": "catalog:",
"@map-colonies/auth-bundler": "workspace:^",
"@map-colonies/auth-core": "workspace:^",
"@map-colonies/config": "catalog:",
"@map-colonies/js-logger": "catalog:",
"@map-colonies/schemas": "catalog:",
"@map-colonies/telemetry": "^10.0.1",
"@opentelemetry/api": "^1.9.0",
"@map-colonies/prometheus": "catalog:",
"@map-colonies/tracing": "catalog:",
"@opentelemetry/api": "catalog:",
"croner": "6.0.3",
"express": "^5.1.0",
"express": "catalog:",
"http-status-codes": "^2.2.0",
"pg": "^8.10.0",
"prom-client": "^15.1.3",
"pg": "catalog:",
"prom-client": "catalog:",
"typeorm": "catalog:"
},
"devDependencies": {
"@types/node": "catalog:",
"@types/express": "^4.17.17",
"@types/express": "catalog:",
"jest-extended": "catalog:",
"test-utils": "workspace:^",
"ts-node": "^10.9.1",
"typescript": "catalog:",
"@types/lodash": "^4.17.24",
"@types/lodash": "catalog:",
"vitest": "catalog:",
"@vitest/coverage-v8": "catalog:",
"@vitest/ui": "catalog:",
Expand Down
6 changes: 3 additions & 3 deletions apps/auth-cron/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type ConfigInstance, config } from '@map-colonies/config';
import { infraOpalaCronV2, type infraOpalaCronV2Type } from '@map-colonies/schemas';
import { infraOpalaCronV3, type infraOpalaCronV3Type } from '@map-colonies/schemas';

type ConfigType = ConfigInstance<infraOpalaCronV2Type>;
type ConfigType = ConfigInstance<infraOpalaCronV3Type>;

let configInstance: ConfigType | undefined;

Expand All @@ -12,7 +12,7 @@ let configInstance: ConfigType | undefined;
*/
async function initConfig(offlineMode?: boolean): Promise<void> {
configInstance = await config({
schema: infraOpalaCronV2,
schema: infraOpalaCronV3,
offlineMode,
});
}
Expand Down
14 changes: 7 additions & 7 deletions apps/auth-cron/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import type { Environments } from '@map-colonies/auth-core';
import { Bundle, initConnection } from '@map-colonies/auth-core';
import type { commonDbFullV1Type } from '@map-colonies/schemas';
import { BundleDatabase } from '@map-colonies/auth-bundler';
import { collectMetricsExpressMiddleware } from '@map-colonies/telemetry/prom-metrics';
import { collectMetricsExpressMiddleware } from '@map-colonies/prometheus';
import { getJob } from './job';
import { getConfig } from './config';
import { emptyDir } from './util';
Expand All @@ -23,13 +23,13 @@ import { metricsRegistry } from './telemetry/metrics';
const SERVER_PORT = env['SERVER_PORT'] ?? 8080;

async function initDb(dbConfig: commonDbFullV1Type): Promise<[DataSource, BundleDatabase, Repository<Bundle>]> {
logger?.debug('initializing database connection');
logger.debug('initializing database connection');
const dataSource = await initConnection(dbConfig);
return [dataSource, new BundleDatabase(dataSource), dataSource.getRepository(Bundle)];
}

const errorHandler: CatchCallbackFn = (err, job) => {
logger?.error({ msg: 'failed running job', err, bundleEnv: job.name });
logger.error({ msg: 'failed running job', err, bundleEnv: job.name });
};

const main = async (): Promise<void> => {
Expand All @@ -39,13 +39,13 @@ const main = async (): Promise<void> => {
const [dataSource, bundleDatabase, bundleRepository] = await initDb(dbConfig);

Object.entries(cronConfig).map(([env, value]) => {
logger?.info({ msg: 'initializing new update bundle job', bundleEnv: env });
logger.info({ msg: 'initializing new update bundle job', bundleEnv: env });

const workdir = mkdtempSync(path.join(tmpdir(), `authbundler-${env}-`));
const job = getJob(bundleRepository, bundleDatabase, env as Environments, workdir);

return Cron(value.pattern, { unref: false, protect: true, catch: errorHandler, name: env }, async () => {
logger?.info({ msg: 'running new update job', bundleEnv: env });
logger.info({ msg: 'running new update job', bundleEnv: env });

await job();
await emptyDir(workdir);
Expand All @@ -64,8 +64,8 @@ const main = async (): Promise<void> => {
});

server.listen(SERVER_PORT, () => {
logger?.info(`liveness and metrics are up at port ${SERVER_PORT}`);
logger.info(`liveness and metrics are up at port ${SERVER_PORT}`);
});
};

main().catch((err) => logger?.error({ msg: 'program terminated with an error', err }));
main().catch((err) => logger.error({ msg: 'program terminated with an error', err }));
3 changes: 3 additions & 0 deletions apps/auth-cron/src/instrumentation.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// Because this file is a module it should imported using the `--import` flag in the `node` command, and should not be imported by any other file.
import { tracingFactory } from './telemetry/tracing.js';
import { getConfig, initConfig } from './config.js';
import { initializeLogger } from './telemetry/logger.js';

await initConfig();

Expand All @@ -14,3 +15,5 @@ const sharedConfig = config.get('telemetry.shared');
const tracing = tracingFactory({ ...tracingConfig, ...sharedConfig });

tracing.start();

await initializeLogger();
18 changes: 9 additions & 9 deletions apps/auth-cron/src/job.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,27 @@ export function getJob(
workdir: string
): () => Promise<void> {
return async () => {
logger?.debug({ msg: 'fetching bundle information from the database', bundleEnv: environment });
logger.debug({ msg: 'fetching bundle information from the database', bundleEnv: environment });
const latestBundle = await bundleRepository.findOne({ where: { environment }, order: { id: 'DESC' } });
const latestVersions = await bundleDatabase.getLatestVersions(environment);
const currentOpaVersion = await getVersionCommand();

logger?.debug({ msg: 'latest bundle from db', bundleEnv: environment, latestBundle, latestVersions });
logger.debug({ msg: 'latest bundle from db', bundleEnv: environment, latestBundle, latestVersions });

logger?.debug({ msg: 'checking if bundle is up to date', bundleEnv: environment, currentOpaVersion });
logger.debug({ msg: 'checking if bundle is up to date', bundleEnv: environment, currentOpaVersion });

let shouldSaveBundleToDb = true;
if (latestBundle !== null && currentOpaVersion === latestBundle.opaVersion && compareVersionsToBundle(latestBundle, latestVersions)) {
logger?.info({ msg: 'bundle is up to date with the database, checking s3', bundleEnv: environment });
logger.info({ msg: 'bundle is up to date with the database, checking s3', bundleEnv: environment });
if (latestBundle.hash === (await getS3Client(environment).getObjectHash())) {
logger?.info({ msg: 's3 bundle is up to date with the database', bundleEnv: environment });
logger.info({ msg: 's3 bundle is up to date with the database', bundleEnv: environment });
return;
}
logger?.info({ msg: 's3 bundle is not up to date with the database, creating new bundle', bundleEnv: environment });
logger.info({ msg: 's3 bundle is not up to date with the database, creating new bundle', bundleEnv: environment });
shouldSaveBundleToDb = false;
}

logger?.debug({ msg: 'creating new bundle as ', bundleEnv: environment });
logger.debug({ msg: 'creating new bundle as ', bundleEnv: environment });

const bundleContent = await bundleDatabase.getBundleFromVersions(latestVersions);

Expand All @@ -43,10 +43,10 @@ export function getJob(
const hash = await getS3Client(environment).uploadFile(path.join(workdir, 'bundle.tar.gz'));

if (shouldSaveBundleToDb) {
logger?.debug({ msg: 'saving bundle metadata to the database', bundleEnv: environment });
logger.debug({ msg: 'saving bundle metadata to the database', bundleEnv: environment });
await bundleDatabase.saveBundle(latestVersions, hash);
}

logger?.info({ msg: 'created new bundle successfully', bundleEnv: environment });
logger.info({ msg: 'created new bundle successfully', bundleEnv: environment });
};
}
10 changes: 5 additions & 5 deletions apps/auth-cron/src/s3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class S3client {
try {
// eslint-disable-next-line @typescript-eslint/naming-convention
const command = new HeadObjectCommand({ Bucket: this.bucket, Key: this.key });
logger?.debug({ msg: 'fetching object metadata from s3', bucket: this.bucket, key: this.key, endpoint: this.endpoint });
logger.debug({ msg: 'fetching object metadata from s3', bucket: this.bucket, key: this.key, endpoint: this.endpoint });
const res = await this.s3client.send(command);

return res.ETag;
Expand All @@ -46,7 +46,7 @@ class S3client {
try {
// eslint-disable-next-line @typescript-eslint/naming-convention
const command = new HeadBucketCommand({ Bucket: this.bucket });
logger?.debug({ msg: 'fetching bucket metadata from s3', bucket: this.bucket, endpoint: this.endpoint });
logger.debug({ msg: 'fetching bucket metadata from s3', bucket: this.bucket, endpoint: this.endpoint });
const res = await this.s3client.send(command);
return res.$metadata.httpStatusCode === StatusCodes.OK;
} catch (error) {
Expand All @@ -60,7 +60,7 @@ class S3client {
public async uploadFile(filePath: string): Promise<string> {
const file = readFileSync(filePath);

logger?.debug({ msg: 'uploading object to s3', bucket: this.bucket, key: this.key, endpoint: this.endpoint });
logger.debug({ msg: 'uploading object to s3', bucket: this.bucket, key: this.key, endpoint: this.endpoint });
// eslint-disable-next-line @typescript-eslint/naming-convention
const command = new PutObjectCommand({ Body: file, Bucket: this.bucket, Key: this.key, ContentType: 'application/gzip' });

Expand All @@ -78,11 +78,11 @@ export function getS3Client(env: Environments): S3client {
if (!client) {
if (cronConfig !== undefined) {
const s3Config = cronConfig.s3;
logger?.debug({ msg: 'initializing new s3 connection', s3Env: env, endpoint: s3Config.endpoint });
logger.debug({ msg: 'initializing new s3 connection', s3Env: env, endpoint: s3Config.endpoint });
client = new S3client(s3Config);
s3Clients.set(env, client);
} else {
logger?.warn({ msg: 'failed initializing s3 client for undefined env', s3Env: env });
logger.warn({ msg: 'failed initializing s3 client for undefined env', s3Env: env });
throw new Error();
}
}
Expand Down
9 changes: 7 additions & 2 deletions apps/auth-cron/src/telemetry/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ import { getConfig } from '../config';

const loggerConfig = getConfig().get('telemetry.logger');

const logger: Logger | undefined = jsLogger({ ...loggerConfig, prettyPrint: loggerConfig.prettyPrint });
let logger: Logger;

export async function initializeLogger(): Promise<void> {
logger = await jsLogger({ ...loggerConfig, prettyPrint: loggerConfig.prettyPrint });

setLogger(logger);
}

setLogger(logger);
export { logger };
2 changes: 1 addition & 1 deletion apps/auth-cron/src/telemetry/tracing.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Tracing } from '@map-colonies/telemetry';
import { Tracing } from '@map-colonies/tracing';

let tracing: Tracing | undefined;
const IGNORED_OUTGOING_TRACE_ROUTES = [/^.*\/v1\/metrics.*$/];
Expand Down
6 changes: 3 additions & 3 deletions apps/auth-cron/src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { logger } from './telemetry/logger';

export function compareVersionsToBundle(bundle: Bundle, versions: BundleContentVersions): boolean {
try {
logger?.debug({ msg: 'comparing connections', bundleEnv: versions.environment });
logger.debug({ msg: 'comparing connections', bundleEnv: versions.environment });
assert.deepStrictEqual(bundle.connections, versions.connections);
logger?.debug({ msg: 'comparing assets', bundleEnv: versions.environment });
logger.debug({ msg: 'comparing assets', bundleEnv: versions.environment });
assert.deepStrictEqual(bundle.assets, versions.assets);

logger?.debug({ msg: 'comparing key version', bundleEnv: versions.environment });
logger.debug({ msg: 'comparing key version', bundleEnv: versions.environment });

// Added the check because keyVersion can be null in the database
// and we want a new bundle to be created in that case
Expand Down
2 changes: 1 addition & 1 deletion apps/auth-cron/src/validators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { logger } from './telemetry/logger';

export async function validateS3(envs: Environments[]): Promise<void> {
for (const env of envs) {
logger?.debug({ msg: 'checking if bucket exists', s3Env: env });
logger.debug({ msg: 'checking if bucket exists', s3Env: env });
const doesExist = await getS3Client(env).doesBucketExist();
if (!doesExist) {
throw new Error('The bucket does not exist');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ import { vi, describe, beforeEach, afterEach, afterAll, it, expect, beforeAll }
import { jsLogger } from '@map-colonies/js-logger';
import type { infraOpalaCronV1Type } from '@map-colonies/schemas';
import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
import { getJob } from '@src/job';
import { getConfig, initConfig } from '@src/config';
import { getJob } from '@src/job.js';
import { getConfig, initConfig } from '@src/config.js';

vi.mock('@map-colonies/auth-bundler');
vi.mock('../src/telemetry/logger', () => {
vi.mock('../src/telemetry/logger', async () => {
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
__esModule: true,
logger: jsLogger({ enabled: false }),
logger: await jsLogger({ enabled: false }),
};
});

Expand Down
4 changes: 2 additions & 2 deletions apps/auth-cron/tests/s3.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import { initConfig, getConfig } from '@src/config.js';
import { getS3Client } from '@src/s3.js';
import type * as appConfig from '@src/config.js';

vi.mock('../src/telemetry/logger', () => {
vi.mock('../src/telemetry/logger', async () => {
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
__esModule: true,
logger: jsLogger({ enabled: false }),
logger: await jsLogger({ enabled: false }),
};
});

Expand Down
4 changes: 2 additions & 2 deletions apps/auth-cron/tests/util.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import { getFakeBundle, getTempDir } from 'test-utils';
import { jsLogger } from '@map-colonies/js-logger';
import { compareVersionsToBundle, emptyDir } from '@src/util.js';

vi.mock('../src/telemetry/logger', () => {
vi.mock('../src/telemetry/logger', async () => {
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
__esModule: true,
logger: jsLogger({ enabled: false }),
logger: await jsLogger({ enabled: false }),
};
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { Environment } from '@map-colonies/auth-core';
import { jsLogger } from '@map-colonies/js-logger';
import { beforeAll, describe, expect, it, vi } from 'vitest';
import { initConfig } from '@src/config';
import { validateS3 } from '@src/validators';
import { initConfig } from '@src/config.js';
import { validateS3 } from '@src/validators.js';

vi.mock('../src/telemetry/logger', () => {
vi.mock('../src/telemetry/logger', async () => {
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
__esModule: true,
logger: jsLogger({ enabled: false }),
logger: await jsLogger({ enabled: false }),
};
});

Expand Down
Loading
Loading