// npm import * as AWS from 'aws-sdk'; import dnsCache from 'dns-cache'; import * as fs from 'fs'; import * as _ from 'lodash'; import * as path from 'path'; import { v4 as uuid } from 'uuid'; // @ownzones import { LogLevel, OzLogger } from '@ownzones/ts-log'; // app import * as pkg from '../package.json'; import { CacheType } from '../lib/cache'; dnsCache(30 * 1000); const env = process.env.NODE_ENV || 'default'; const ebEnv = process.env.AWS_EB_ENV; const deploymentName = process.env.ENV_NAME; const namespacePath = '/var/run/secrets/kubernetes.io/serviceaccount/namespace'; let namespace = env; if (fs.existsSync(namespacePath)) { namespace = fs.readFileSync(namespacePath).toString(); } let versionFilePath = path.resolve(__dirname, '../VERSION'); let version = fs.readFileSync(versionFilePath, 'utf8'); try { versionFilePath = path.resolve(__dirname, '../VERSION.branch'); version = fs.readFileSync(versionFilePath, 'utf8'); } catch { /* nothing */ } version = version.trim(); const config = { app: pkg.name, envName: process.env.ENV_NAME || '', env, deploymentName, namespace, serviceName: process.env.POD_NAME ? process.env.POD_NAME.split('-').slice(0, -2).join('-') : null, mock: false, maxCache: 100 * 1024 * 1024 * 1024, // 100GiB apiHost: process.env.MV_API_HOST || '', graphQLEndpoint: process.env.MV_GRAPHQL_ENDPOINT || 'http://zypline-api/graphql', systemUserEmail: process.env.SYSTEM_USER_EMAIL || 'system.admin@onzones.com', jwtSecret: process.env.GATEWAY_JWT_SECRET || 'you-have-to-set-the-gateway-secret', logs: { json: (process.env.JSON_LOGS === 'true') || false, level: process.env.LOGS_LEVEL || 'info', sentry: { dsn: process.env.MV_SENTRY_DSN || '', }, }, logHiddenFields: [ 'email', 'passwordHash', 'roles', 'rights', 'username', 'triggeredByUsername', 'authorization', ], server: { keepAliveTimeout: process.env.SERVER_KEEP_ALIVE_TIMEOUT ? Number.parseInt(process.env.SERVER_KEEP_ALIVE_TIMEOUT, 10) : 35000, }, worker: { precache: { maxAllowedTasks: process.env.WORKER_PRECACHE_MAX_TASKS ? Number.parseInt(process.env.WORKER_PRECACHE_MAX_TASKS, 10) : undefined, }, extractChannels: { timeout: process.env.EXTRACT_CHANNELS_TIMEOUT ? Number.parseInt(process.env.EXTRACT_CHANNELS_TIMEOUT, 10) : 60 * 60 * 8, // 8 hours }, }, cors: { // Chrome - Response can be cached by the client's browser only for up to 600 seconds maxAge: process.env.CORS_MAX_AGE ? Number.parseInt(process.env.CORS_MAX_AGE, 10) : 600, origin: process.env.CORS_ORIGIN || '^(http|https):\\/\\/((.+.)?ownzones.com|localhost)((:)[0-9]{4})?$', allowMethods: 'GET,HEAD,OPTIONS', }, cachePrefix: process.env.ZL_MV_CACHE_PREFIX || 'mv-cache', podId: process.env.POD_UID || '', podName: process.env.POD_NAME || '', processId: uuid(), // TODO don't hardcode api key honeyComb: { writeKey: process.env.HONEYCOMB_WRITE_KEY || '66cd4350a59e496119d59274616e45fa', dataset: process.env.HONEYCOMB_DATASET || 'mediaview-test', }, AWS: { region: process.env.AWS_REGION || 'us-east-1', s3: { localstackEndpoint: process.env.AWS_S3_ENDPOINT, }, }, redis: { port: process.env.MV_REDIS_PORT ? Number.parseInt(process.env.MV_REDIS_PORT, 10) : 6379, host: process.env.MV_REDIS_HOST || 'localhost', database: process.env.MV_REDIS_DB ? Number.parseInt(process.env.MV_REDIS_DB, 10) : 0, }, cacheDynamo: { tableName: process.env.MV_CACHE_DYNAMO_TABLE_NAME, scoreIndexName: process.env.MV_CACHE_DYNAMO_SCORE_INDEX_NAME || 'pk_score', paginationLimit: process.env.MV_CACHE_DYNAMO_PAGINATION_LIMIT ? Number.parseInt(process.env.MV_CACHE_DYNAMO_PAGINATION_LIMIT, 10) : undefined, region: process.env.AWS_REGION || 'us-east-1', partitionSegmentsPerFiles: process.env.MV_CACHE_DYNAMO_PARTITION_SEGMENTS_PER_FILE === 'true' || false, endpoint: process.env.MV_CACHE_DYNAMO_ENDPOINT || undefined, }, cacheSelect: CacheType[process.env.MV_CACHE_SELECT as keyof typeof CacheType], cacheAutostart: (process.env.MV_CACHE_AUTOSTART !== 'false'), cacheCheckConcurrency: process.env.MV_CACHE_CHECK_CONCURRENCY ? Number.parseInt(process.env.MV_CACHE_CHECK_CONCURRENCY, 10) : 1, cacheCleanupInterval: process.env.MV_CACHE_CLEANUP_INTERVAL ? Number.parseInt(process.env.MV_CACHE_CLEANUP_INTERVAL, 10) : 60000, cacheRedis: { port: process.env.MV_CACHE_REDIS_PORT ? Number.parseInt(process.env.MV_CACHE_REDIS_PORT, 10) : 6379, host: process.env.MV_CACHE_REDIS_HOST || 'localhost', database: process.env.MV_CACHE_REDIS_DB ? Number.parseInt(process.env.MV_CACHE_REDIS_DB, 10) : 0, }, rrtq: { videoNamespace: process.env.MV_RRTQ_VIDEO_NAMESPACE || 'mediaviewVideo', audioNamespace: process.env.MV_RRTQ_AUDIO_NAMESPACE || 'mediaviewAudio', videoNamespacePreCache: 'mediaviewPreCacheVideo', audioNamespaceChannelExtract: 'mediaviewChannelExtract', driverNamespace: 'mediaviewDriver', uniqueTasks: true, taskTimeout: 16 * 1000, checkTaskVisibility: true, taskGCTimeout: 10 * 1000, expire: 5 * 1000, cleanupQueuesIntervalTimeout: process.env.RRTQ_CLEANUP_QUEUES_INTERVAL_TIMEOUT ? Number.parseInt(process.env.RRTQ_CLEANUP_QUEUES_INTERVAL_TIMEOUT, 10) : 10 * 1000, // 10s }, preCacheRrtq: { taskGCTimeout: process.env.PRECACHE_RRTQ_TASK_GC_TIMEOUT ? Number.parseInt(process.env.PRECACHE_RRTQ_TASK_GC_TIMEOUT, 10) : 7 * 24 * 60 * 60 * 1000, // 7 days of gc timeout gcTimeout: process.env.PRECACHE_RRTQ_GC_TIMEOUT ? Number.parseInt(process.env.PRECACHE_RRTQ_GC_TIMEOUT, 10) : 15 * 60 * 1000, // 15m maxRetries: process.env.PRECACHE_RETRIES ? Number.parseInt(process.env.PRECACHE_RETRIES, 10) : 16, checkTaskVisibility: false, taskTimeout: 60 * 1000, }, subsegmentsCount: process.env.MV_SUBSEGMENTS_COUNT ? Number.parseInt(process.env.MV_SUBSEGMENTS_COUNT, 10) : 4, acesTransformsPath: path.join(__dirname, '../aces-transforms'), mediaPath: path.join(__dirname, '../media'), sslEndpoints: process.env.MV_SSL_ENDPOINTS === 'true', prometheus: { url: process.env.PROMETHEUS_URL || 'https://prometheus-k8s.dev.ownzones.com', }, keda: { enabled: process.env.KEDA_ENABLED === 'true', }, monitoring: { eventLoopLatency: { enabled: process.env.MONITORING_EVENT_LOOP_LATENCY_ENABLED === 'true', threshold: process.env.MONITORING_EVENT_LOOP_LATENCY_THRESHOLD ? Number.parseInt(process.env.MONITORING_EVENT_LOOP_LATENCY_THRESHOLD, 10) : 500, interval: process.env.MONITORING_EVENT_LOOP_LATENCY_INTERVAL ? Number.parseInt(process.env.MONITORING_EVENT_LOOP_LATENCY_INTERVAL, 10) : 300, }, }, cognito: { appClientId: process.env.ZL_COGNITO_APP_CLIENT_ID!, customUserId: process.env.ZL_COGNITO_CUSTOM_ATTRIBUTE || 'custom:zl_user_id', customSysAdmin: process.env.ZL_COGNITO_CUSTOM_SYSADMIN || 'custom:zl_sysadmin', poolId: process.env.ZL_COGNITO_POOL_ID!, region: process.env.ZL_COGNITO_REGION || 'us-east-1', idpMetadataUrl: process.env.ZL_COGNITO_IDP_METADATA_URL!, idpProviderType: process.env.ZL_COGNITO_IDP_PROVIDER_TYPE || 'SAML', }, version, }; export type ConfigType = typeof config; if (process.env.NODE_ENV && process.env.NODE_ENV !== 'default') { // eslint-disable-next-line const overridingConfig = require(`./${process.env.NODE_ENV}`).config; _.merge(config, overridingConfig); } const logEnv = ebEnv ? `${env}-${ebEnv}` : env; export const log = new OzLogger({ level: config.logs.level as LogLevel || LogLevel.Info, meta: { app: config.app, version: pkg.version, env: logEnv, }, }); AWS.config.s3 = { ...AWS.config.s3, signatureVersion: process.env.AWS_S3_SIGNATURE_VERSION ? process.env.AWS_S3_SIGNATURE_VERSION : 's3', }; if (config.AWS.s3.localstackEndpoint) { AWS.config.s3 = { endpoint: config.AWS.s3.localstackEndpoint, s3ForcePathStyle: true, }; } log.info(`Loaded configuration '${config.env}' (log env is '${logEnv}').`); export { config };