Конфигурация NestJs TypeORM с использованием AWS Parameter Store - PullRequest
0 голосов
/ 30 апреля 2019

новичок в NestJS и столкнулся с проблемой. Для наших развертываний нам необходимо получить нашу конфигурацию из AWS Parameter Store (Systems Manager), включая строку подключения к базе данных. У меня есть ConfigModule и ConfigService, который извлекает все записи хранилища параметров для моей среды на основе пути хранилища параметров:

Вот мой сервис конфигурации:

import * as dotenv from 'dotenv';
import * as fs from 'fs';
import * as AWS from 'aws-sdk';

export class ConfigService {
    private readonly envConfig: { [key: string]: string };
    private awsParamStoreEntries: { [key: string]: string }[];

    constructor(awsParamStorePath: string, filePath: string) {
        this.envConfig = dotenv.parse(fs.readFileSync(filePath));

        this.loadAwsParameterStoreEntries(awsParamStorePath).then((data) => {
            this.awsParamStoreEntries = data;
        });
    }

    loadAwsParameterStoreEntries(pathPrefix: string) {
        const credentials = new AWS.SharedIniFileCredentials({ profile: 'grasshopper-parameter' });
        AWS.config.credentials = credentials;
        const ssm = new AWS.SSM({ region: 'us-west-2' });
        var params: { [key: string]: string }[] = [];

        return getParams({
            Path: '/app/v3/development/',
            Recursive: true,
            WithDecryption: true,
            MaxResults: 10,
        }).then(() => {
            return params;
        });

        function getParams(options) {
            return new Promise((resolve, reject) => {
                ssm.getParametersByPath(options, processParams(options, (err, data) => {
                    if (err) {
                        return reject(err);
                    }
                    resolve(data);
                }));
            });
        }

        function processParams(options, cb) {
            return function (err, data) {
                if (err) {
                    return cb(err)
                };
                data.Parameters.forEach(element => {
                    let key = element.Name.split('/').join(':')
                    params.push({ key: key, value: element.Value });
                });
                if (data.NextToken) {
                    const nextOptions = Object.assign({}, options);
                    nextOptions.NextToken = data.NextToken;
                    return ssm.getParametersByPath(nextOptions, processParams(options, cb));
                }
                return cb(null);
            };
        }
    }

    get(key: string): string {
        return this.envConfig[key];
    }

    getParamStoreValue(key: string): string {
        return this.awsParamStoreEntries.find(element => element.key === key)['value'];
    }

    getDatabase(): string {
        return this.awsParamStoreEntries.find(element => element.key === 'ConnectionStrings:CoreDb')['value'];
    }
}

Вот основной блок объявления модуля приложения:

@Module({
  imports: [ConfigModule, TypeOrmModule.forRootAsync({
    imports: [ConfigModule],
    useFactory: async (configService: ConfigService) => ({
      url: configService.getDatabase()
    }),
    inject: [ConfigService]
  }),
    CoreModule, AuthModule],
  controllers: [AppController],
  providers: [AppService],
})

Как вы можете видеть, я говорю TypeORM вызвать метод getDatabase () в ConfigService , но проблема в том, что для загрузки записей хранилища параметров требуется около 3-4 секунд, так что "undefined «ошибка возникает из-за того, что this.awsParamStoreEntries по-прежнему не определен, когда TypeORM пытается загрузить строку подключения.

Проверили в Интернете, чтобы убедиться, что это было сделано, но не смогли найти ничего, что использует хранилище параметров NestJS / TypeORM / AWS таким образом. Существует также (без ответа) вопрос здесь, на StackOverflow.

Спасибо!

1 Ответ

0 голосов
/ 02 мая 2019

Можете ли вы сделать что-то вроде этого.

import { TypeOrmOptionsFactory, TypeOrmModuleOptions } from '@nestjs/typeorm';
import { ConfigService } from './config.service';
import { Injectable } from '@nestjs/common';

@Injectable()
export class TypeOrmConfigService implements TypeOrmOptionsFactory {
    constructor(private readonly configService: ConfigService) {
    }

    async createTypeOrmOptions(): Promise<TypeOrmModuleOptions> {
        this.configService.awsParamStoreEntries = await this.configService.loadAwsParameterStoreEntries(this.configService.awsParamStorePath);

        return {
            url: this.configService.getDatabase(),
        };
    }
}
@Module({
  imports: [
    ConfigModule, 
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      useClass: TypeOrmConfigService,
    }),
    CoreModule, 
    AuthModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
import * as dotenv from 'dotenv';
import * as fs from 'fs';
import * as AWS from 'aws-sdk';
import { Injectable } from '@nestjs/common';

@Injectable()
export class ConfigService {
    private readonly envConfig: { [key: string]: string };
    awsParamStoreEntries: { [key: string]: string }[];
    private readonly awsParamStorePath: string;

    constructor(awsParamStorePath: string, filePath: string) {
        this.envConfig = dotenv.parse(fs.readFileSync(filePath));
        this.awsParamStorePath = awsParamStorePath;
    }

    loadAwsParameterStoreEntries(pathPrefix: string) {...

https://docs.nestjs.com/techniques/database

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...