From 1a74e3293829db216066e912ce9cf5fef7e08107 Mon Sep 17 00:00:00 2001 From: bhavanakarwade <137506897+bhavanakarwade@users.noreply.github.com> Date: Thu, 29 Aug 2024 22:25:20 +0530 Subject: [PATCH] merge: DEV to QA (#960) * fix: schema search during pahination issue Signed-off-by: Krishna Waske * chore: changes for tipu Signed-off-by: Krishna Waske * chore: changes for sahil Signed-off-by: Krishna Waske * refactor: Implemented white labeling in taskdef.json file Signed-off-by: sahil.kamble@ayanworks.com * fix: fetch schema name in credentials list (#959) * fix: fetch schema details Signed-off-by: bhavanakarwade * fix: applied validations for issuance using connection Signed-off-by: bhavanakarwade * fix: multiple schemas in verified proof details api Signed-off-by: bhavanakarwade * refactor: description Signed-off-by: bhavanakarwade * fix: schemanames not visible in credentials list Signed-off-by: bhavanakarwade --------- Signed-off-by: bhavanakarwade --------- Signed-off-by: Krishna Waske Signed-off-by: sahil.kamble@ayanworks.com Signed-off-by: bhavanakarwade Co-authored-by: Krishna Waske Co-authored-by: Krishna <74084119+GHkrishna@users.noreply.github.com> Co-authored-by: sahil.kamble@ayanworks.com Co-authored-by: KambleSahil3 <157386770+KambleSahil3@users.noreply.github.com> --- apps/issuance/src/issuance.repository.ts | 4 +- apps/issuance/src/issuance.service.ts | 44 ++++++++- .../schema/repositories/schema.repository.ts | 96 +++++++++++++------ .../src/interfaces/issuance.interface.ts | 16 +++- libs/prisma-service/prisma/seed.ts | 6 +- .../taskdef}/agent-provisioning-taskdef.json | 4 +- .../taskdef}/agent-service-taskdef.json | 4 +- .../taskdef}/api-gateway-taskdef.json | 4 +- .../taskdef}/connection-taskdef.json | 4 +- .../taskdef}/ecosystem-taskdef.json | 4 +- .../taskdef}/issuance-service-taskdef.json | 4 +- .../taskdef}/ledger-taskdef.json | 4 +- .../taskdef}/notification-taskdef.json | 4 +- .../taskdef}/organization-taskdef.json | 4 +- .../taskdef}/user-taskdef.json | 4 +- .../taskdef}/utility-taskdef.json | 4 +- .../taskdef}/verfication-taskdef.json | 4 +- .../taskdef}/webhook-taskdef.json | 4 +- 18 files changed, 156 insertions(+), 62 deletions(-) rename {taskdef => scripts/taskdef}/agent-provisioning-taskdef.json (93%) rename {taskdef => scripts/taskdef}/agent-service-taskdef.json (90%) rename {taskdef => scripts/taskdef}/api-gateway-taskdef.json (93%) rename {taskdef => scripts/taskdef}/connection-taskdef.json (89%) rename {taskdef => scripts/taskdef}/ecosystem-taskdef.json (89%) rename {taskdef => scripts/taskdef}/issuance-service-taskdef.json (92%) rename {taskdef => scripts/taskdef}/ledger-taskdef.json (89%) rename {taskdef => scripts/taskdef}/notification-taskdef.json (89%) rename {taskdef => scripts/taskdef}/organization-taskdef.json (88%) rename {taskdef => scripts/taskdef}/user-taskdef.json (89%) rename {taskdef => scripts/taskdef}/utility-taskdef.json (89%) rename {taskdef => scripts/taskdef}/verfication-taskdef.json (88%) rename {taskdef => scripts/taskdef}/webhook-taskdef.json (89%) diff --git a/apps/issuance/src/issuance.repository.ts b/apps/issuance/src/issuance.repository.ts index 092637b2e..29d41e1ec 100644 --- a/apps/issuance/src/issuance.repository.ts +++ b/apps/issuance/src/issuance.repository.ts @@ -183,8 +183,8 @@ export class IssuanceRepository { let schemaId = ''; - if (issueCredentialDto?.metadata?.['_anoncreds/credential']?.schemaId) { - schemaId = issueCredentialDto?.metadata?.['_anoncreds/credential']?.schemaId; + if (issueCredentialDto?.metadata?.['_anoncreds/credential']?.schemaId || issueCredentialDto?.['credentialData']?.offer?.jsonld?.credential?.['@context'][1]) { + schemaId = issueCredentialDto?.metadata?.['_anoncreds/credential']?.schemaId || issueCredentialDto?.['credentialData']?.offer?.jsonld?.credential?.['@context'][1]; } let credDefId = ''; diff --git a/apps/issuance/src/issuance.service.ts b/apps/issuance/src/issuance.service.ts index 8d2fe54b6..39758c244 100644 --- a/apps/issuance/src/issuance.service.ts +++ b/apps/issuance/src/issuance.service.ts @@ -28,7 +28,7 @@ import { FileUploadStatus, FileUploadType } from 'apps/api-gateway/src/enum'; import { AwsService } from '@credebl/aws'; import { io } from 'socket.io-client'; import { IIssuedCredentialSearchParams, IssueCredentialType } from 'apps/api-gateway/src/issuance/interfaces'; -import { ICredentialOfferResponse, IDeletedIssuanceRecords, IIssuedCredential, IJsonldCredential, IPrettyVc } from '@credebl/common/interfaces/issuance.interface'; +import { ICredentialOfferResponse, IDeletedIssuanceRecords, IIssuedCredential, IJsonldCredential, IPrettyVc, ISchemaObject } from '@credebl/common/interfaces/issuance.interface'; import { OOBIssueCredentialDto } from 'apps/api-gateway/src/issuance/dtos/issuance.dto'; import { RecordType, agent_invitations, organisation, user } from '@prisma/client'; import { createOobJsonldIssuancePayload, validateAndUpdateIssuanceDates, validateEmail } from '@credebl/common/cast.helper'; @@ -456,6 +456,30 @@ export class IssuanceService { orgId, issuedCredentialsSearchCriteria ); + + const getSchemaIds = getIssuedCredentialsList?.issuedCredentialsList?.map((schema) => schema?.schemaId); + + const getSchemaDetails = await this._getSchemaDetails(getSchemaIds); + + let responseWithSchemaName; + if (getSchemaDetails) { + responseWithSchemaName = getIssuedCredentialsList?.issuedCredentialsList.map(file => { + const schemaDetail = getSchemaDetails?.find(schema => schema.schemaLedgerId === file.schemaId); + return { + ...file, + schemaName: schemaDetail?.name + }; + }); + } else { + const getSchemaUrlDetails = await this.getSchemaUrlDetails(getSchemaIds); + responseWithSchemaName = getIssuedCredentialsList?.issuedCredentialsList.map(file => { + const schemaDetail = getSchemaUrlDetails?.find(schema => schema.title); + return { + ...file, + schemaName: schemaDetail?.title + }; + }); + } const issuedCredentialsResponse: IIssuedCredential = { totalItems: getIssuedCredentialsList.issuedCredentialsCount, hasNextPage: @@ -464,7 +488,7 @@ export class IssuanceService { nextPage: Number(issuedCredentialsSearchCriteria.pageNumber) + 1, previousPage: issuedCredentialsSearchCriteria.pageNumber - 1, lastPage: Math.ceil(getIssuedCredentialsList.issuedCredentialsCount / issuedCredentialsSearchCriteria.pageSize), - data: getIssuedCredentialsList.issuedCredentialsList + data: responseWithSchemaName }; if (0 === getIssuedCredentialsList?.issuedCredentialsCount) { @@ -478,6 +502,22 @@ export class IssuanceService { } } + async getSchemaUrlDetails(schemaUrls: string[]): Promise { + const results = []; + + for (const schemaUrl of schemaUrls) { + const schemaRequest = await this.commonService.httpGet(schemaUrl); + if (!schemaRequest) { + throw new NotFoundException(ResponseMessages.schema.error.W3CSchemaNotFOund, { + cause: new Error(), + description: ResponseMessages.errorMessages.notFound + }); + } + results.push(schemaRequest); + } + return results; +} + async _getIssueCredentials(url: string, apiKey: string): Promise<{ response: string; }> { diff --git a/apps/ledger/src/schema/repositories/schema.repository.ts b/apps/ledger/src/schema/repositories/schema.repository.ts index 0f6199193..40c83c21c 100644 --- a/apps/ledger/src/schema/repositories/schema.repository.ts +++ b/apps/ledger/src/schema/repositories/schema.repository.ts @@ -238,35 +238,71 @@ export class SchemaRepository { async getAllSchemaDetails(payload: ISchemaSearchCriteria): Promise { try { const { ledgerId, schemaType, searchByText, sortField, sortBy, pageSize, pageNumber } = payload; - const schemasResult = await this.prisma.schema.findMany({ - where: { - ledgerId, - type: schemaType, - OR: [ - { name: { contains: searchByText, mode: 'insensitive' } }, - { version: { contains: searchByText, mode: 'insensitive' } }, - { schemaLedgerId: { contains: searchByText, mode: 'insensitive' } }, - { issuerId: { contains: searchByText, mode: 'insensitive' } } - ] - }, - select: { - createDateTime: true, - name: true, - version: true, - attributes: true, - schemaLedgerId: true, - createdBy: true, - publisherDid: true, - orgId: true, // This field can be null - issuerId: true, - type: true - }, - orderBy: { - [sortField]: SortValue.DESC === sortBy ? SortValue.DESC : SortValue.ASC - }, - take: Number(pageSize), - skip: (pageNumber - 1) * pageSize - }); + let schemaResult; + /** + * This is made so because the default pageNumber is set to 1 in DTO, + * If there is any 'searchByText' field, we ignore the pageNumbers and search + * in all available records. + * + * Because in that case pageNumber would be insignificant. + */ + if (searchByText) { + schemaResult = await this.prisma.schema.findMany({ + where: { + ledgerId, + type: schemaType, + OR: [ + { name: { contains: searchByText, mode: 'insensitive' } }, + { version: { contains: searchByText, mode: 'insensitive' } }, + { schemaLedgerId: { contains: searchByText, mode: 'insensitive' } }, + { issuerId: { contains: searchByText, mode: 'insensitive' } } + ] + }, + select: { + createDateTime: true, + name: true, + version: true, + attributes: true, + schemaLedgerId: true, + createdBy: true, + publisherDid: true, + orgId: true, // This field can be null + issuerId: true, + type: true + }, + orderBy: { + [sortField]: SortValue.DESC === sortBy ? SortValue.DESC : SortValue.ASC + }, + take: Number(pageSize) + }); + } else { + /** + * Queries apart from the one containing searchText would go here + */ + schemaResult = await this.prisma.schema.findMany({ + where: { + ledgerId, + type: schemaType + }, + select: { + createDateTime: true, + name: true, + version: true, + attributes: true, + schemaLedgerId: true, + createdBy: true, + publisherDid: true, + orgId: true, // This field can be null + issuerId: true, + type: true + }, + orderBy: { + [sortField]: SortValue.DESC === sortBy ? SortValue.DESC : SortValue.ASC + }, + take: Number(pageSize), + skip: (pageNumber - 1) * pageSize + }); + } const schemasCount = await this.prisma.schema.count({ where: { @@ -276,7 +312,7 @@ export class SchemaRepository { }); // Handle null orgId in the response - const schemasWithDefaultOrgId = schemasResult.map(schema => ({ + const schemasWithDefaultOrgId = schemaResult.map(schema => ({ ...schema, orgId: schema.orgId || null // Replace null orgId with 'N/A' or any default value })); diff --git a/libs/common/src/interfaces/issuance.interface.ts b/libs/common/src/interfaces/issuance.interface.ts index ea8192510..593e0d1d8 100644 --- a/libs/common/src/interfaces/issuance.interface.ts +++ b/libs/common/src/interfaces/issuance.interface.ts @@ -112,4 +112,18 @@ export interface IIssuedCredential { credential?: ICredential; options?: IOptions; } - \ No newline at end of file + + export interface ISchemaObject { + '$schema': string; + '$id': string; + type: string; + required: string[]; + properties: { + [key: string]: object; + }; + definitions: { + [key: string]: object; + }; + title: string; + description: string; + } \ No newline at end of file diff --git a/libs/prisma-service/prisma/seed.ts b/libs/prisma-service/prisma/seed.ts index 2267f5fe1..a9910c101 100644 --- a/libs/prisma-service/prisma/seed.ts +++ b/libs/prisma-service/prisma/seed.ts @@ -409,9 +409,13 @@ const migrateOrgAgentDids = async (): Promise => { } }); + const filteredOrgAgents = orgAgents.filter( + (agent) => null !== agent.orgDid && '' !== agent.orgDid + ); + // If there are org DIDs that do not exist in org_dids table if (orgDids.length !== existingDids.length) { - const newOrgAgents = orgAgents.filter( + const newOrgAgents = filteredOrgAgents.filter( (agent) => !existingDids.some((did) => did.did === agent.orgDid) ); diff --git a/taskdef/agent-provisioning-taskdef.json b/scripts/taskdef/agent-provisioning-taskdef.json similarity index 93% rename from taskdef/agent-provisioning-taskdef.json rename to scripts/taskdef/agent-provisioning-taskdef.json index a96542327..292b15c74 100644 --- a/taskdef/agent-provisioning-taskdef.json +++ b/scripts/taskdef/agent-provisioning-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_AGENT-PROVISIONING_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "agent_provisioning", @@ -33,7 +33,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_AGENT-PROVISIONING_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/agent-service-taskdef.json b/scripts/taskdef/agent-service-taskdef.json similarity index 90% rename from taskdef/agent-service-taskdef.json rename to scripts/taskdef/agent-service-taskdef.json index 6f334aa4b..0fb698780 100644 --- a/taskdef/agent-service-taskdef.json +++ b/scripts/taskdef/agent-service-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_AGENT_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "agent", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_AGENT_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" } diff --git a/taskdef/api-gateway-taskdef.json b/scripts/taskdef/api-gateway-taskdef.json similarity index 93% rename from taskdef/api-gateway-taskdef.json rename to scripts/taskdef/api-gateway-taskdef.json index b32ae3605..34435749e 100644 --- a/taskdef/api-gateway-taskdef.json +++ b/scripts/taskdef/api-gateway-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_API-GATEWAY_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "api_gateway", @@ -34,7 +34,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_API-GATEWAY_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/connection-taskdef.json b/scripts/taskdef/connection-taskdef.json similarity index 89% rename from taskdef/connection-taskdef.json rename to scripts/taskdef/connection-taskdef.json index 228efd128..452d8fcff 100644 --- a/taskdef/connection-taskdef.json +++ b/scripts/taskdef/connection-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_CONNECTION_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "connection", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_CONNECTION_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/ecosystem-taskdef.json b/scripts/taskdef/ecosystem-taskdef.json similarity index 89% rename from taskdef/ecosystem-taskdef.json rename to scripts/taskdef/ecosystem-taskdef.json index ec8c9c853..a44912426 100644 --- a/taskdef/ecosystem-taskdef.json +++ b/scripts/taskdef/ecosystem-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_ECOSYSTEM_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "ecosystem", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_ECOSYSTEM_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/issuance-service-taskdef.json b/scripts/taskdef/issuance-service-taskdef.json similarity index 92% rename from taskdef/issuance-service-taskdef.json rename to scripts/taskdef/issuance-service-taskdef.json index 73414c4df..8d4832f22 100644 --- a/taskdef/issuance-service-taskdef.json +++ b/scripts/taskdef/issuance-service-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_ISSUANCE_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "issuance", @@ -28,7 +28,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_ISSUANCE_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/ledger-taskdef.json b/scripts/taskdef/ledger-taskdef.json similarity index 89% rename from taskdef/ledger-taskdef.json rename to scripts/taskdef/ledger-taskdef.json index aa090642f..23c9950a7 100644 --- a/taskdef/ledger-taskdef.json +++ b/scripts/taskdef/ledger-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_LEDGER_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "ledger", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_LEDGER_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/notification-taskdef.json b/scripts/taskdef/notification-taskdef.json similarity index 89% rename from taskdef/notification-taskdef.json rename to scripts/taskdef/notification-taskdef.json index 3c378b619..3ab1d2157 100644 --- a/taskdef/notification-taskdef.json +++ b/scripts/taskdef/notification-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_NOTIFICATION_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "notification", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_NOTIFICATION_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" } diff --git a/taskdef/organization-taskdef.json b/scripts/taskdef/organization-taskdef.json similarity index 88% rename from taskdef/organization-taskdef.json rename to scripts/taskdef/organization-taskdef.json index 70ae500d5..1738b09da 100644 --- a/taskdef/organization-taskdef.json +++ b/scripts/taskdef/organization-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_ORGANIZATION_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "organization", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_ORGANIZATION_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/user-taskdef.json b/scripts/taskdef/user-taskdef.json similarity index 89% rename from taskdef/user-taskdef.json rename to scripts/taskdef/user-taskdef.json index 61d9a3b23..bf291d698 100644 --- a/taskdef/user-taskdef.json +++ b/scripts/taskdef/user-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_USER_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "user", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_USER_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/utility-taskdef.json b/scripts/taskdef/utility-taskdef.json similarity index 89% rename from taskdef/utility-taskdef.json rename to scripts/taskdef/utility-taskdef.json index d8d640368..240cdb1a5 100644 --- a/taskdef/utility-taskdef.json +++ b/scripts/taskdef/utility-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_UTILITY_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "utility", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_UTILITY_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/verfication-taskdef.json b/scripts/taskdef/verfication-taskdef.json similarity index 88% rename from taskdef/verfication-taskdef.json rename to scripts/taskdef/verfication-taskdef.json index 2c7608541..e9aedf8cd 100644 --- a/taskdef/verfication-taskdef.json +++ b/scripts/taskdef/verfication-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_VERIFICATION_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "verification", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_VERIFICATION_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" }, diff --git a/taskdef/webhook-taskdef.json b/scripts/taskdef/webhook-taskdef.json similarity index 89% rename from taskdef/webhook-taskdef.json rename to scripts/taskdef/webhook-taskdef.json index ef536d63e..f831f8de3 100644 --- a/taskdef/webhook-taskdef.json +++ b/scripts/taskdef/webhook-taskdef.json @@ -1,5 +1,5 @@ { - "family": "DEV_WEBHOOK_SERVICE_TASKDEFINITION", + "family": "${FAMILY}", "containerDefinitions": [ { "name": "webhook", @@ -22,7 +22,7 @@ "logDriver": "awslogs", "options": { "awslogs-create-group": "true", - "awslogs-group": "/ecs/DEV_WEBHOOK_SERVICE_TASKDEFINITION", + "awslogs-group": "/ecs/${FAMILY}", "awslogs-region": "${AWS_REGION}", "awslogs-stream-prefix": "ecs" },