Skip to content

Commit

Permalink
refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy Razon committed Apr 27, 2024
1 parent 827d26c commit 2b98e38
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 47 deletions.
89 changes: 47 additions & 42 deletions packages/cli/src/commands/env/metadata.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import { Flags, ux } from '@oclif/core'
import { envIdFlags, parseTunnelServerFlags, tableFlags, text, tunnelServerFlags, urlFlags } from '@preevy/cli-common'
import { AgentFetchError, TunnelOpts, addBaseComposeTunnelAgentService, findComposeTunnelAgentUrl, findEnvId, getTunnelNamesToServicePorts, getUserCredentials, jwtGenerator, profileStore, queryEnvMetadata, readMetadata } from '@preevy/core'
import { envIdFlags, parseTunnelServerFlags, text, tunnelServerFlags } from '@preevy/cli-common'
import { TunnelOpts, addBaseComposeTunnelAgentService, findComposeTunnelAgentUrl, findEnvId, getTunnelNamesToServicePorts, getUserCredentials, jwtGenerator, profileStore, queryEnvMetadata, readMetadata } from '@preevy/core'
import { tunnelNameResolver } from '@preevy/common'
import { inspect } from 'util'
import DriverCommand from '../../driver-command.js'
import { connectToTunnelServerSsh } from '../../tunnel-server-client.js'

type MetadataSource = 'agent' | 'driver'
type UnknownMetadata = Record<string, unknown>

// eslint-disable-next-line no-use-before-define
export default class EnvMetadataCommand extends DriverCommand<typeof EnvMetadataCommand> {
static description = 'Show metadata for a preview environment'
Expand All @@ -14,9 +17,12 @@ export default class EnvMetadataCommand extends DriverCommand<typeof EnvMetadata
static flags = {
...envIdFlags,
...tunnelServerFlags,
from: Flags.custom<'driver' | 'agent' | 'agent-or-driver'>({
source: Flags.custom<'driver' | 'agent'>({
summary: 'Show metadata from the driver, the agent, or the driver if the agent is not available',
default: 'agent-or-driver',
default: ['agent', 'driver'],
multiple: true,
delimiter: ',',
multipleNonGreedy: true,
})(),
'fetch-timeout': Flags.integer({
default: 2500,
Expand Down Expand Up @@ -80,60 +86,59 @@ export default class EnvMetadataCommand extends DriverCommand<typeof EnvMetadata
tunnelingKey,
)
const credentials = await getUserCredentials(jwtGenerator(tunnelingKey))
try {
// eslint-disable-next-line @typescript-eslint/return-await
return await queryEnvMetadata({
composeTunnelServiceUrl,
credentials,
fetchTimeout: this.flags['fetch-timeout'],
retryOpts: { retries: 2 },
})
} catch (err) {
this.logger.debug('Failed to fetch metadata from agent', inspect(err))
if (!(err instanceof AgentFetchError)) {
throw err
}
return undefined
}
// eslint-disable-next-line @typescript-eslint/return-await
return await queryEnvMetadata({
composeTunnelServiceUrl,
credentials,
fetchTimeout: this.flags['fetch-timeout'],
retryOpts: { retries: 2 },
})
}

async getMetatdata() {
const { flags: { from } } = this
if (from === 'agent' || from === 'agent-or-driver') {
const metadata = await this.getMetadataFromAgent()
if (metadata) {
return {
metadata,
source: 'agent',
}
}
}
metadataFactories: Record<MetadataSource, () => Promise<UnknownMetadata>> = {
driver: this.getMetadataFromDriver.bind(this),
agent: this.getMetadataFromAgent.bind(this),
}

if ((from === 'driver' || from === 'agent-or-driver')) {
const metadata = await this.getMetadataFromDriver()
if (metadata) {
async getMetatdata() {
const { flags: { source: sources } } = this
const errors: { source: MetadataSource; error: unknown }[] = []
for (const source of sources) {
try {
this.logger.debug(`Fetching metadata from ${source}`)
return {
metadata,
source: 'driver',
// eslint-disable-next-line no-await-in-loop
metadata: await this.metadataFactories[source](),
errors,
source,
}
} catch (err) {
errors.push({ source, error: err })
}
}

return undefined
return { errors }
}

async run(): Promise<unknown> {
const result = await this.getMetatdata()
if (!result) {
throw new Error('Could not get metadata. See debug logs for more information')
const { metadata, source: metadataSource, errors } = await this.getMetatdata()

if (!metadata) {
throw new Error(`Could not get metadata: ${inspect(errors)}`)
}

if (errors.length) {
for (const { source: errorSource, error } of errors) {
this.logger.warn(`Error fetching metadata from ${errorSource}: ${error}`)
}
}

if (this.jsonEnabled()) {
return { ...result.metadata, _source: result.source }
return { ...metadata, _source: metadataSource }
}

ux.info(`Metadata from ${text.code(result.source)}`)
ux.styledObject(result.metadata)
this.logger.info(`Metadata from ${text.code(metadataSource)}`)
this.logger.info(inspect(metadata, { depth: null, colors: text.supportsColor !== false }))
return undefined
}
}
4 changes: 2 additions & 2 deletions packages/core/src/compose-tunnel-agent-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ export const queryTunnels = async ({
}))
}

export const queryEnvMetadata = async (fetchOpts: ComposeTunnelAgentFetchOpts): Promise<unknown> => {
export const queryEnvMetadata = async (fetchOpts: ComposeTunnelAgentFetchOpts): Promise<EnvMetadata> => {
const r = await fetchFromComposeTunnelAgent({ ...fetchOpts, pathAndQuery: 'env-metadata' })
return await r.json()
return await r.json() as EnvMetadata
}
6 changes: 3 additions & 3 deletions packages/core/src/driver/machine-operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,9 @@ const writeMetadata = async (
})
}

export const readMetadata = async (connection: MachineConnection): Promise<Pick<EnvMetadata, 'machine'> | undefined> => {
const { stdout } = await connection.exec(`[ -f "${REMOTE_DIR_BASE}/${driverMetadataFilename}" ] && cat "${REMOTE_DIR_BASE}/${driverMetadataFilename}"`)
return stdout && JSON.parse(stdout)
export const readMetadata = async (connection: MachineConnection): Promise<Pick<EnvMetadata, 'machine'>> => {
const { stdout } = await connection.exec(`cat "${REMOTE_DIR_BASE}/${driverMetadataFilename}"`)
return JSON.parse(stdout)
}

export const getUserAndGroup = async (connection: Pick<MachineConnection, 'exec'>) => (
Expand Down

0 comments on commit 2b98e38

Please sign in to comment.