Action "lxc.file.push"
Push files into containers.
Example
const {$status} = await nikita.lxc.file.push({
container: 'my_container',
source: `#{scratch}/a_file`,
target: '/root/a_file'
})
console.info(`File was pushed: ${$status}`)
Todo
- Push recursive directories
- Handle unmatched target permissions
- Handle unmatched target ownerships
- Detect name from lxd_target
Schema definitions
definitions =
config:
type: 'object'
properties:
'algo':
default: 'md5'
$ref: 'module://@nikitajs/core/lib/actions/fs/hash#/definitions/config/properties/algo'
'container':
$ref: 'module://@nikitajs/lxd/src/init#/definitions/config/properties/container'
description: '''
Name of the container in lxd.
'''
'content':
type: 'string'
description: '''
Content of the target file.
'''
'create_dirs':
type: 'boolean'
default: false
description: '''
Create any directories necessary in the container.
'''
'gid':
type: ['integer', 'string']
description: '''
Set the file's gid on push, overwrite the `source` option.
'''
'lxd_target':
type: 'string'
description: '''
Path to the destination of the file inside the container as "<container>/<path>". Concatenation of the `container` property with the `target` property.
'''
'mode':
type: ['integer', 'string']
pattern: "^\\d+$"
filemode: true
description: '''
Set the file's perms on push. LXD only support the absolute
representation. When passing a string, an integer is casted to its
octal value and passing a symbolic value will throw an error.
'''
'source':
type: 'string'
description: '''
Path to the file to push to the container on your local machine.
'''
'target':
type: 'string'
description: '''
Path to the destination of the file once it has been pushed to the container.
'''
'uid':
type: ['integer', 'string']
description: '''
Set the file's uid on push.
'''
required: ['container', 'target']
oneOf: [
{required: ['content']}
{required: ['source']}
]
Handler
handler = ({config, metadata: {tmpdir}}) ->
# Make source file with content
if config.content?
tmpfile = path.join tmpdir, "nikita.#{Date.now()}#{Math.round(Math.random()*1000)}"
await @fs.base.writeFile
target: tmpfile
content: config.content
config.source = tmpfile
# note, name could be obtained from lxd_target
# throw Error "Invalid Option: target is required" if not config.target and not config.lxd_target
config.lxd_target ?= "#{path.join config.container, config.target}"
{$status} = await @lxc.running
container: config.container
status_running = $status
if $status
try
{$status} = await @execute
command: """
# Ensure source is a file
[ -f "#{config.source}" ] || exit 2
command -v openssl >/dev/null || exit 3
sourceDgst=`openssl dgst -#{config.algo} #{config.source} | sed 's/^.* \\([a-z0-9]*\\)$/\\1/g'`
# Get target hash
targetDgst=`cat <<EOF | lxc exec #{config.container} -- sh
# Ensure openssl is available
command -v openssl >/dev/null || exit 4
# Target does not exist
[ ! -f "#{config.target}" ] && exit 0
openssl dgst -#{config.algo} #{config.target} | sed 's/^.* \\([a-z0-9]*\\)$/\\1/g'
EOF`
[ "$sourceDgst" != "$targetDgst" ] || exit 42
"""
code: [0, 42]
trap: true
catch err
throw Error "Invalid Option: source is not a file, got #{JSON.stringify config.source}" if err.exit_code is 2
throw Error "Invalid Requirement: openssl not installed on host" if err.exit_code is 3
throw utils.error 'NIKITA_LXD_FILE_PUSH_MISSING_OPENSSL', [
'the openssl package must be installed in the container'
'and accessible from the `$PATH`.'
] if err.exit_code is 4
if not status_running or $status
await @execute
command: """
#{[
'lxc', 'file', 'push'
config.source
config.lxd_target
'--create-dirs' if config.create_dirs
'--gid' if config.gid? and typeof config.gid is 'number'
'--uid' if config.uid? and typeof config.uid is 'number'
"--mode #{config.mode}" if config.mode
].join ' '}
"""
trap: true
trim: true
if typeof config.gid is 'string'
await @lxc.exec
container: config.container
command: "chgrp #{config.gid} #{config.target}"
if typeof config.uid is 'string'
await @lxc.exec
container: config.container
command: "chown #{config.uid} #{config.target}"
Exports
module.exports =
handler: handler
metadata:
tmpdir: true
definitions: definitions
Dependencies
path = require 'path'
utils = require '../utils'