Skip to content

Commit

Permalink
add --skip-volume flag to up command
Browse files Browse the repository at this point in the history
  • Loading branch information
Roy Razon committed Dec 12, 2023
1 parent bd7d0f1 commit 998b44b
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 13 deletions.
9 changes: 8 additions & 1 deletion packages/cli/src/commands/up.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
ProfileStore,
TunnelOpts,
addBaseComposeTunnelAgentService,
commands, ensureMachine, findComposeTunnelAgentUrl,
commands, defaultVolumeSkipList, ensureMachine, findComposeTunnelAgentUrl,
findEnvId,
findProjectName, getTunnelNamesToServicePorts, jwkThumbprint, profileStore,
telemetryEmitter,
Expand Down Expand Up @@ -82,6 +82,12 @@ export default class Up extends MachineCreationDriverCommand<typeof Up> {
...envIdFlags,
...tunnelServerFlags,
...buildFlags,
'skip-volume': Flags.string({
description: 'Additional volume glob patterns to skip copying',
multiple: true,
singleValue: true,
default: [],
}),
'skip-unchanged-files': Flags.boolean({
description: 'Detect and skip unchanged files when copying (default: true)',
default: true,
Expand Down Expand Up @@ -181,6 +187,7 @@ export default class Up extends MachineCreationDriverCommand<typeof Up> {
projectName,
expectedServiceUrls,
userSpecifiedServices: restArgs,
volumeSkipList: [...defaultVolumeSkipList, ...flags['skip-volume']],
debug: flags.debug,
userSpecifiedProjectName: flags.project,
composeFiles: this.config.composeFiles,
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"jose": "^4.14.4",
"jsonwebtoken": "^9.0.0",
"lodash": "^4.17.21",
"minimatch": "^9.0.3",
"node-fetch": "2.6.9",
"node-forge": "^1.3.1",
"open": "^8.4.2",
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/commands/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const composeModel = async ({
tunnelOpts,
userSpecifiedProjectName,
userSpecifiedServices,
volumeSkipList,
scriptInjections,
composeFiles,
log,
Expand All @@ -33,6 +34,7 @@ const composeModel = async ({
tunnelOpts: TunnelOpts
userSpecifiedProjectName: string | undefined
userSpecifiedServices: string[]
volumeSkipList: string[]
composeFiles: string[]
log: Logger
dataDir: string
Expand All @@ -55,6 +57,7 @@ const composeModel = async ({
debug,
userSpecifiedProjectName,
userSpecifiedServices,
volumeSkipList,
composeFiles,
log,
cwd,
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/commands/up.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const up = async ({
tunnelOpts,
userSpecifiedProjectName,
userSpecifiedServices,
volumeSkipList,
scriptInjections,
composeFiles,
log,
Expand All @@ -67,6 +68,7 @@ const up = async ({
tunnelOpts: TunnelOpts
userSpecifiedProjectName: string | undefined
userSpecifiedServices: string[]
volumeSkipList: string[]
composeFiles: string[]
log: Logger
dataDir: string
Expand All @@ -87,6 +89,7 @@ const up = async ({
const {
model,
filesToCopy,
skippedVolumes,
projectLocalDataDir,
createCopiedFile,
} = await modelCommand({
Expand All @@ -98,6 +101,7 @@ const up = async ({
tunnelOpts,
userSpecifiedProjectName,
userSpecifiedServices,
volumeSkipList,
scriptInjections,
version,
envId,
Expand Down Expand Up @@ -128,6 +132,10 @@ const up = async ({
})).deployModel
}

skippedVolumes.forEach(({ service, source, matchingRule }) => {
log.info(`Not copying volume "${source}" for service "${service}" because it matched skip glob "${matchingRule}"`)
})

const modelStr = yaml.stringify(composeModel)
log.debug('model', modelStr)
const composeFilePath = await createCopiedFile(composeModelFilename, modelStr)
Expand Down
47 changes: 36 additions & 11 deletions packages/core/src/compose/remote.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import yaml from 'yaml'
import path from 'path'
import { mapValues } from 'lodash'
import { MMRegExp, makeRe } from 'minimatch'
import { asyncMap, asyncToArray } from 'iter-tools-es'
import { COMPOSE_TUNNEL_AGENT_SERVICE_NAME, MachineStatusCommand, ScriptInjection, formatPublicKey } from '@preevy/common'
import { MachineConnection } from '../driver'
import { ComposeModel, ComposeSecretOrConfig, composeModelFilename } from './model'
import { ComposeBindVolume, ComposeModel, ComposeSecretOrConfig, composeModelFilename } from './model'
import { REMOTE_DIR_BASE, remoteProjectDir } from '../remote-files'
import { TunnelOpts } from '../ssh'
import { addComposeTunnelAgentService } from '../compose-tunnel-agent-client'
Expand All @@ -28,23 +29,42 @@ const serviceLinkEnvVars = (
.map(({ name, port, url }) => [`PREEVY_BASE_URI_${name.replace(/[^a-zA-Z0-9_]/g, '_')}_${port}`.toUpperCase(), url])
)

const volumeSkipList = [
/^\/var\/log(\/|$)/,
/^\/var\/run(\/|$)/,
/^\/$/,
export const defaultVolumeSkipList: string[] = [
'/var/log',
'/var/log/**',
'/var/run',
'/var/run/**',
'/',
]

const toPosix = (x:string) => x.split(path.sep).join(path.posix.sep)

export type SkippedVolume = { service: string; source: string; matchingRule: string }

const fixModelForRemote = async (
{ skipServices = [], cwd, remoteBaseDir }: {
{ skipServices = [], cwd, remoteBaseDir, volumeSkipList = defaultVolumeSkipList }: {
skipServices?: string[]
cwd: string
remoteBaseDir: string
volumeSkipList: string[]
},
model: ComposeModel,
): Promise<{ model: Required<Omit<ComposeModel, 'x-preevy' | 'version'>>; filesToCopy: FileToCopy[] }> => {
): Promise<{
model: Required<Omit<ComposeModel, 'x-preevy' | 'version'>>
filesToCopy: FileToCopy[]
skippedVolumes: SkippedVolume[]
}> => {
const volumeSkipRes = volumeSkipList
.map(s => makeRe(path.resolve(cwd, s)))
.map((r, i) => {
if (!r) {
throw new Error(`Invalid glob pattern in volumeSkipList: "${volumeSkipList[i]}"`)
}
return r as MMRegExp
})

const filesToCopy: FileToCopy[] = []
const skippedVolumes: SkippedVolume[] = []

const remotePath = (absolutePath: string) => {
if (!path.isAbsolute(absolutePath)) {
Expand Down Expand Up @@ -86,7 +106,9 @@ const fixModelForRemote = async (
if (volume.type !== 'bind') {
throw new Error(`Unsupported volume type: ${volume.type} in service ${serviceName}`)
}
if (volumeSkipList.some(re => re.test(volume.source))) {
const matchingVolumeSkipIndex = volumeSkipRes.findIndex(re => re.test(volume.source))
if (matchingVolumeSkipIndex !== -1) {
skippedVolumes.push({ service: serviceName, source: volume.source, matchingRule: volumeSkipList[matchingVolumeSkipIndex] })
return volume
}

Expand Down Expand Up @@ -117,6 +139,7 @@ const fixModelForRemote = async (
networks: model.networks ?? {},
},
filesToCopy,
skippedVolumes,
}
}

Expand All @@ -136,6 +159,7 @@ export const remoteComposeModel = async ({
debug,
userSpecifiedProjectName,
userSpecifiedServices,
volumeSkipList,
composeFiles,
log,
cwd,
Expand All @@ -147,6 +171,7 @@ export const remoteComposeModel = async ({
debug: boolean
userSpecifiedProjectName: string | undefined
userSpecifiedServices: string[]
volumeSkipList: string[]
composeFiles: string[]
log: Logger
cwd: string
Expand All @@ -172,8 +197,8 @@ export const remoteComposeModel = async ({
? [...userSpecifiedServices].concat(COMPOSE_TUNNEL_AGENT_SERVICE_NAME)
: []

const { model: fixedModel, filesToCopy } = await fixModelForRemote(
{ cwd, remoteBaseDir: remoteDir },
const { model: fixedModel, filesToCopy, skippedVolumes } = await fixModelForRemote(
{ cwd, remoteBaseDir: remoteDir, volumeSkipList },
await modelFilter(await composeClientWithInjectedArgs.getModel(services)),
)

Expand Down Expand Up @@ -215,5 +240,5 @@ export const remoteComposeModel = async ({
filesToCopy.push(sshPrivateKeyFile, knownServerPublicKey)
}

return { model, filesToCopy, linkEnvVars }
return { model, filesToCopy, skippedVolumes, linkEnvVars }
}
7 changes: 6 additions & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@ export {
} from './profile'
export { telemetryEmitter, registerEmitter, wireProcessExit, createTelemetryEmitter, machineId } from './telemetry'
export { fsTypeFromUrl, Store, VirtualFS, localFsFromUrl, localFs } from './store'
export { localComposeClient, ComposeModel, resolveComposeFiles, getExposedTcpServicePorts, fetchRemoteUserModel as remoteUserModel, NoComposeFilesError, addScriptInjectionsToServices as addScriptInjectionsToModel } from './compose'
export {
localComposeClient, ComposeModel, resolveComposeFiles, getExposedTcpServicePorts,
fetchRemoteUserModel as remoteUserModel, NoComposeFilesError,
addScriptInjectionsToServices as addScriptInjectionsToModel,
defaultVolumeSkipList,
} from './compose'
export { withSpinner } from './spinner'
export { findEnvId, findProjectName, findEnvIdByProjectName, validateEnvId, normalize as normalizeEnvId, EnvId } from './env-id'
export { sshKeysStore } from './state'
Expand Down

0 comments on commit 998b44b

Please sign in to comment.