From 99a478ee39a7777c24d98593b0fbb5e8676534bb Mon Sep 17 00:00:00 2001 From: Alexis Svinartchouk Date: Tue, 25 Aug 2020 13:45:39 +0200 Subject: [PATCH] Fix device UUID parsing for 'balena tunnel' Change-type: patch --- lib/actions-oclif/tunnel.ts | 2 -- lib/utils/patterns.ts | 25 +++++++++++++++++++++++-- lib/utils/validation.ts | 8 ++++++-- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/lib/actions-oclif/tunnel.ts b/lib/actions-oclif/tunnel.ts index 6feb1a43..6cd38845 100644 --- a/lib/actions-oclif/tunnel.ts +++ b/lib/actions-oclif/tunnel.ts @@ -28,7 +28,6 @@ import { getOnlineTargetUuid } from '../utils/patterns'; import * as _ from 'lodash'; import { tunnelConnectionToDevice } from '../utils/tunnel'; import { createServer, Server, Socket } from 'net'; -import { tryAsInteger } from '../utils/validation'; import { IArg } from '@oclif/parser/lib/args'; interface FlagsDef { @@ -78,7 +77,6 @@ export default class TunnelCmd extends Command { { name: 'deviceOrApplication', description: 'device uuid or application name/id', - parse: (x) => tryAsInteger(x), required: true, }, ]; diff --git a/lib/utils/patterns.ts b/lib/utils/patterns.ts index aad98c16..7ca54cdc 100644 --- a/lib/utils/patterns.ts +++ b/lib/utils/patterns.ts @@ -359,10 +359,31 @@ export function inferOrSelectDevice(preferredUuid: string) { }); } +async function getApplicationByIdOrName( + sdk: BalenaSdk.BalenaSDK, + idOrName: string, +) { + if (validation.looksLikeInteger(idOrName)) { + try { + return await sdk.models.application.get(Number(idOrName)); + } catch (error) { + const { BalenaApplicationNotFound } = await import('balena-errors'); + if (!instanceOf(error, BalenaApplicationNotFound)) { + throw error; + } + } + } + return await sdk.models.application.get(idOrName); +} + export async function getOnlineTargetUuid( sdk: BalenaSdk.BalenaSDK, applicationOrDevice: string, ) { + // applicationOrDevice can be: + // * an application name + // * an application ID (integer) + // * a device uuid const Logger = await import('../utils/logger'); const logger = Logger.getLogger(); const appTest = validation.validateApplicationName(applicationOrDevice); @@ -390,9 +411,9 @@ export async function getOnlineTargetUuid( // otherwise, it may be a device OR an application... try { logger.logDebug( - `Fetching application by name ${applicationOrDevice} (${typeof applicationOrDevice})`, + `Fetching application by ID or name ${applicationOrDevice} (${typeof applicationOrDevice})`, ); - const app = await sdk.models.application.get(applicationOrDevice); + const app = await getApplicationByIdOrName(sdk, applicationOrDevice); const devices = await sdk.models.device.getAllByApplication(app.id, { $filter: { is_online: true }, }); diff --git a/lib/utils/validation.ts b/lib/utils/validation.ts index 296d1964..05067ef9 100644 --- a/lib/utils/validation.ts +++ b/lib/utils/validation.ts @@ -75,9 +75,13 @@ export function validateUuid(input: string): boolean { return validateLongUuid(input) || validateShortUuid(input); } -export function parseAsInteger(input: string, paramName?: string) { +export function looksLikeInteger(input: string) { // Allow only digits, no leading 0 - if (!/^(0|[1-9][0-9]*)$/.test(input)) { + return /^(?:0|[1-9][0-9]*)$/.test(input); +} + +export function parseAsInteger(input: string, paramName?: string) { + if (!looksLikeInteger(input)) { const message = paramName == null ? 'The parameter must be an integer.'