Skip to content

Commit

Permalink
add service option to all commands
Browse files Browse the repository at this point in the history
  • Loading branch information
kla committed Sep 8, 2024
1 parent 7a735e1 commit 55e0e38
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 38 deletions.
33 changes: 17 additions & 16 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ export default class App {
this.containers = containers.sort((a: Container, b: Container) => a.number - b.number)
}

get context(): string {
return this.primary.context
}

get composeFile(): string {
return this.primary.composeFile
}

get primary(): Container {
return this.containers[0]
}
Expand Down Expand Up @@ -86,36 +94,29 @@ export default class App {
}

async down() {
return Promise.all(this.containers.map(container => container.down()))
return docker.compose(this.context, 'stop', this.composeFile)
}

async up() {
return Promise.all(this.containers.map(container => container.up()))
return docker.compose(this.context, 'start', this.composeFile, { exit: true })
}

async remove() {
return Promise.all(this.containers.map(container => container.remove()))
return docker.compose(this.context, 'rm --stop --force --volumes', this.composeFile)
}

async exec(command: string) {
return this.primary.exec(command)
}

findContainer(options: FindContainerOptions): Container | null {
return this.containers.find(container => container.service == options.service)
}

async shell(options: FindContainerOptions) {
findContainer(options: FindContainerOptions): Container {
if (options.service) {
const container = this.findContainer(options)
if (!container) exit(1, `👿 No container found for a service named '${options.service}'. Valid services are: ${this.containers.map(container => container.service).join(', ')}`)
return container.shell()
const container = this.containers.find(container => container.service == options.service)
if (!container)
exit(1, `👿 No container found for a service named '${options.service}'. Valid services are: ${this.containers.map(container => container.service).join(', ')}`)
return container
}
return this.primary.shell()
}

async logs(options: { follow?: boolean, tail?: number } = {}) {
return this.primary.logs(options)
return this.primary
}

async rebuild(config: StaxConfig, options: SetupOptions = {}) {
Expand Down
56 changes: 41 additions & 15 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const DEFAULT_CONTEXT_NAME = 'stax'
const editor = process.env.STAX_EDITOR || 'code'
const stax = new Stax(DEFAULT_CONTEXT_NAME)
const program = new Command()

program.name('stax')

program.command('alias')
Expand All @@ -20,10 +21,11 @@ program.command('alias')
.action((name, alias) => stax.find(name).addAlias(alias))

program.command('config')
.argument('<name', 'Name of application')
.argument('<name>', 'Name of application')
.option('-s, --service <name>', 'Name of service to act on')
.description('Show config variables for the container.')
.action(name => {
const container = stax.find(name).primary
.action((name, options) => {
const container = stax.findContainer(name, options)
const attributes = { ...container.config, labels: container.labels }
console.log(attributes)
})
Expand All @@ -33,14 +35,19 @@ program.command('copy')
.argument('<name>', 'Name of application')
.argument('<source>', 'Path to a local file or directory')
.argument('<destination>', 'Path to a destination file or directory in the container')
.option('-s, --service <name>', 'Name of service to act on')
.option('-n, --dont-overwrite', 'Don\'t overwrite if file already exists')
.description('Copy a file to the container')
.action(async (name, source, destination, options) => stax.find(name).primary.copy(source, destination, options))
.action(async (name, source, destination, options) => stax.findContainer(name, options).copy(source, destination, options))

program.command('down')
.argument('<name>', 'Name of application')
.option('-s, --service <name>', 'Name of service to act on')
.description('Stop an application')
.action(async name => { await stax.find(name).down() })
.action(async (name, options) => {
const target = options.service ? stax.findContainer(name, options) : stax.find(name)
target.down()
})

program.command('edit')
.argument('<name>', 'Name of application')
Expand All @@ -62,9 +69,13 @@ program.command('edit')

program.command('exec')
.argument('<name>', 'Name of application')
.argument('<command>', 'Command to execute')
.argument('<command>', 'Command to execute. Use "--" before your command if it has more than one word.')
.option('-s, --service <name>', 'Name of service to act on')
.description('Execute a command in a running application')
.action(async (name, command) => { await stax.find(name).exec(command) })
.action(async (name, command, options) => {
console.log({name: name, command: command, options: options, args: args })
await stax.findContainer(name, options).exec(command)
})

program.command('inspect')
.argument('<name>', 'Name of application')
Expand Down Expand Up @@ -92,13 +103,16 @@ program.command('list')

program.command('logs')
.argument('<name>', 'Name of application')
.option('-s, --service <name>', 'Name of service to act on')
.option('-f, --follow', 'Follow log output')
.option('-t, --tail <number>', 'Number of lines to show from the end of the logs')
.option('--since <since>', 'A time or duration string accepted by \'docker container logs\'')
.description('Tail logs for an application')
.action(async (name, options) => {
const follow = options.follow || false
const tail = options.tail ? parseInt(options.tail) : undefined
await stax.find(name).logs({ follow, tail })
const since = options.since
await stax.findContainer(name, options).logs({ follow, tail, since })
})

program.command('rebuild')
Expand All @@ -122,8 +136,9 @@ program.command('get')
.argument('<name>', 'Name of application')
.argument('<source>', 'File to copy from the container')
.argument('<destination>', 'Local destination to copy the file to')
.option('-s, --service <name>', 'Name of service to act on')
.description('Copy a from the container')
.action(async (name, source, destination) => stax.find(name).primary.get(source, destination))
.action(async (name, source, destination, options) => stax.findContainer(name, options).get(source, destination))

program.command('setup')
.argument('<location>', 'Path to a local directory or git repo of application')
Expand All @@ -135,22 +150,33 @@ program.command('setup')
program.command('shell')
.alias('sh')
.argument('<name>', 'Name of application')
.option('-s, --service <name>', 'Service to shell into')
.option('-s, --service <name>', 'Name of service to act on')
.description('Shell into application\' primary container')
.action(async (name, options) => stax.find(name).shell(options))
.action(async (name, options) => stax.findContainer(name, options).shell())

program.command('up')
.argument('<name>', 'Name of application')
.option('-s, --service <name>', 'Name of service to act on')
.description('Start an application')
.action(async name => { await stax.find(name).up() })
.action(async (name, options) => {
const target = options.service ? stax.findContainer(name, options) : stax.find(name)
target.up()
})

let [ args, overrides ] = parseAndRemoveWildcardOptions(process.argv, '--stax.')
const commandSeparator = args.indexOf('--')

if (args[2] == 'exec' && process.argv.length > 5) {
args = process.argv.slice(0, 4)
args = args.concat(process.argv.slice(4, 9999).join(' '))
if (commandSeparator >= 0) {
const command = args.slice(commandSeparator+1).join(' ')
args = args.slice(0, commandSeparator)
args.push(command)
}

program.on('command:*', () => {
console.error('Unknown command or option')
process.exit(1)
})

tmp.setGracefulCleanup()
process.on('SIGINT', () => { tmp.setGracefulCleanup(); process.exit() })
process.chdir(process.env.WORKING_DIRECTORY)
Expand Down
13 changes: 7 additions & 6 deletions src/container.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { existsSync } from 'fs'
import { existsSync, readFileSync } from 'fs'
import { csvKeyValuePairs, exit } from '~/utils'
import { FindOptions, SetupOptions, StaxConfig } from '~/types'
import { run } from '~/shell'
Expand Down Expand Up @@ -112,20 +112,20 @@ export default class Container {

if (!c) {
if (options.warn)
console.warn(`🤷 Container '${name}@${context}' not found`)
console.warn(`🤷 Container '${context}/${containerName}' not found`)
else if (options.mustExist)
return exit(1, `👿 '${name}@${context}' is not a valid container name`)
return exit(1, `👿 '${context}/${containerName}' is not a valid container name`)
}

return c
}

async down() {
return docker.compose(this.context, 'stop', this.composeFile)
return docker.compose(this.context, `stop ${this.name}`, this.composeFile)
}

async up() {
return docker.compose(this.context, 'start', this.composeFile, { exit: true })
return docker.compose(this.context, `start ${this.name}`, this.composeFile, { exit: true })
}

async remove() {
Expand Down Expand Up @@ -163,10 +163,11 @@ export default class Container {
})
}

async logs(options: { follow?: boolean, tail?: number } = {}) {
async logs(options: { follow?: boolean, tail?: number, since?: string } = {}) {
let command = `logs ${this.name}`
if (options.follow) command += ' --follow'
if (options.tail) command += ` --tail=${options.tail}`
if (options.since) command += ` --since=${options.since}`
return docker.compose(this.context, command, this.composeFile)
}

Expand Down
7 changes: 6 additions & 1 deletion src/stax.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { exit } from '~/utils'
import { StaxConfig } from '~/types'
import { FindContainerOptions, StaxConfig } from '~/types'
import App from '~/app'
import Container from '~/container'
import settings from '~/settings'
import list from '~/app_list'

Expand Down Expand Up @@ -29,6 +30,10 @@ export default class Stax {
return app
}

findContainer(appName: string, options: FindContainerOptions): Container {
return this.find(appName).findContainer(options)
}

apps(): App[] {
return App.all(this.context)
}
Expand Down

0 comments on commit 55e0e38

Please sign in to comment.