private async buildTargetList()

in source/packages/services/commands/src/commands/workflow/workflow.startjob.ts [159:305]


    private async buildTargetList(
        commandId: string,
        targets: string[],
        targetQuery: SearchRequestModel
    ): Promise<string[]> {
        logger.debug(
            `workflow.startjob buildTargetList: commandId:${commandId}, targets:${targets}, targetQuery:${JSON.stringify(
                targetQuery
            )}`
        );

        ow(commandId, ow.string.nonEmpty);
        // ow(targets, ow.array.nonEmpty.minLength(1));

        let awsThingTargets: string[] = [];
        const awsGroupTargets: string[] = [];
        const cdfDeviceTargets: string[] = [];
        const cdfGroupTargets: string[] = [];

        // if we have a target query specified, retrieve all the asset library groups/devices it relates to
        if (targetQuery !== undefined) {
            let searchResults = await this.assetLibrarySearchClient.search(targetQuery);
            logger.verbose(
                `workflow.startjob buildTargetList: searchResults:${JSON.stringify(searchResults)}`
            );
            while (searchResults.results.length > 0) {
                for (const r of searchResults.results) {
                    if (this.isDevice(r)) {
                        const awsIotThingArn = (r as Device10Resource).awsIotThingArn;
                        if (awsIotThingArn !== undefined) {
                            awsThingTargets.push(awsIotThingArn);
                        }
                    } else {
                        cdfGroupTargets.push((r as Group10Resource).groupPath);
                    }
                }
                // possibly paginated results?
                if (searchResults.pagination !== undefined) {
                    const offset = searchResults.pagination.offset;
                    const count = searchResults.pagination.count;
                    searchResults = await this.assetLibrarySearchClient.search(
                        targetQuery,
                        offset + count
                    );
                } else {
                    searchResults.results = [];
                }
            }
        }

        // figure out the type of each target
        if (targets !== undefined) {
            for (const target of targets) {
                const targetType = this.getTargetType(target);
                switch (targetType) {
                    case TargetType.awsIotThing:
                        awsThingTargets.push(target);
                        break;
                    case TargetType.awsIotGroup:
                        awsGroupTargets.push(target);
                        break;
                    case TargetType.cdfDevice:
                        cdfDeviceTargets.push(target);
                        break;
                    case TargetType.cdfGroup:
                        cdfGroupTargets.push(target);
                        break;
                    default:
                }
            }
        }

        // if we have too many aws iot thing groups as targets, we can't proceed
        const maxGroups =
            awsThingTargets.length === 0 &&
            cdfDeviceTargets.length === 0 &&
            cdfGroupTargets.length === 0
                ? this.maxTargets
                : this.maxTargets - 1;
        if (awsGroupTargets.length > maxGroups) {
            throw new Error('MAX_GROUPS_EXCEEDED');
        }

        // for CDF groups, we need to get the thing arn of all devices related to the group
        if (cdfGroupTargets.length > 0) {
            logger.debug(
                `workflow.startjob buildTargetList: creating CDFGroupTargets cdfGroupTargets: ${JSON.stringify(
                    cdfGroupTargets
                )}`
            );
            for (const groupPath of cdfGroupTargets) {
                let result = await this.assetLibraryGroupClient.listGroupMembersDevices(groupPath);
                while (result.results !== undefined) {
                    for (const device of result.results) {
                        if (device.awsIotThingArn) {
                            awsThingTargets.push(device.awsIotThingArn);
                        }
                    }
                    if (result.pagination === undefined) {
                        break;
                    }
                    const offset = result.pagination.offset + result.pagination.count;
                    result = await this.assetLibraryGroupClient.listGroupMembersDevices(
                        groupPath,
                        null,
                        null,
                        offset,
                        result.pagination.count
                    );
                }
            }
        }

        // for CDF devices, we need to get its corresponding thing arn
        if (cdfDeviceTargets.length > 0) {
            logger.debug(
                `workflow.startjob buildTargetList: creating CDFDeviceTargets, cdfDeviceTargets: ${JSON.stringify(
                    cdfDeviceTargets
                )}`
            );
            const result = await this.assetLibraryDeviceClient.getDevicesByID(
                cdfDeviceTargets,
                false,
                [],
                []
            );
            for (const device of result.results) {
                if (device.awsIotThingArn) {
                    awsThingTargets.push(device.awsIotThingArn);
                }
            }
        }

        // if the no. devices is greater than the available slots we have, they need flattening into an ephemeral group
        const maxDevices = this.maxTargets - awsGroupTargets.length;
        if (awsThingTargets.length > maxDevices) {
            const ephemeralGroupArn = await this.buildEphemeralGroup(commandId, awsThingTargets);
            awsGroupTargets.push(ephemeralGroupArn);
            awsThingTargets = [];
        }

        // what we have left should be the list of thing and group arns.  one final step, make sure they're unique
        const jobTargets = [...new Set(awsThingTargets.concat(awsGroupTargets))];

        logger.debug(`workflow.startjob buildTargetList: exit:${jobTargets}`);
        return jobTargets;
    }