0.0.5 add source to exclude from when only file supplied

add quiet and 'additional' to ssh options
add some logging
added remote config to example
master
David Kebler 2019-02-16 18:55:44 -08:00
parent bed36111ff
commit 7cd943422e
11 changed files with 76 additions and 43 deletions

View File

@ -4,8 +4,8 @@ import onDeath from 'ondeath'
(async () => { (async () => {
const sync = new Sync({jobsDir:'./example/jobs'}) // look for job files here const sync = new Sync({jobsDir:'./example/jobs'}) // look for job files here
await sync.loadJob('example') await sync.runJob('remote')
sync.live() // await sync.loadJob('local')
sync.watch('on') sync.watch('on')
console.log('ready and waiting') console.log('ready and waiting')

23
example/jobs/remote.yaml Normal file
View File

@ -0,0 +1,23 @@
source: ./example/source/ # be sure to add trailing / to avoid making a subdirectory under destination
destination: /opt/example
flags: 'av'
runOpts:
cli: true
excludeFrom:
- .gitignore
- example/source/.npmignore
exclude:
- .gitignore
- .npmignore
set:
- delete
- delete-excluded
- stats
watch: # true
wait: 200
immediate: true
ssh:
host: relays.kebler.net
username: sysadmin
# quiet: true
# additional: ''

View File

@ -1,3 +1,3 @@
node_modules/** node_modules/
**/node_modules/** **/node_modules/**
coverage/ coverage/

View File

View File

@ -1,10 +1,10 @@
{ {
"name": "@uci-utils/sync", "name": "@uci-utils/sync",
"version": "0.0.4", "version": "0.0.5",
"description": "module to copy, maintain, and launch hardware modules on other machines", "description": "module to copy, maintain, and launch hardware modules on other machines",
"main": "src/index.js", "main": "src/index.js",
"bin": { "bin": {
"ssh": "./bin/ssh.js" "ssh": "./bin/sync.js"
}, },
"scripts": { "scripts": {
"sync": "node -r esm ./bin/sync", "sync": "node -r esm ./bin/sync",
@ -33,12 +33,12 @@
"dependencies": { "dependencies": {
"@uci-utils/logger": "0.0.13", "@uci-utils/logger": "0.0.13",
"@uci-utils/read-lines": "^0.2.1", "@uci-utils/read-lines": "^0.2.1",
"@uci-utils/watcher": "^0.2.1", "@uci-utils/watcher": "^0.2.3",
"aggregation": "^1.2.5", "aggregation": "^1.2.5",
"await-to-js": "^2.1.1", "await-to-js": "^2.1.1",
"conf": "^2.2.0", "conf": "^2.2.0",
"debounce-fn": "^1.0.0", "debounce-fn": "^1.0.0",
"esm": "^3.2.4", "esm": "^3.2.5",
"fs-read-data": "^1.0.4", "fs-read-data": "^1.0.4",
"path-exists": "^3.0.0", "path-exists": "^3.0.0",
"yargs": "^13.1.0" "yargs": "^13.1.0"

View File

@ -315,8 +315,8 @@ Rsync.prototype.exclude = function(patterns) {
/** /**
* Exclude a file of globs/patterns. The file path will to a list * Exclude a file of globs/patterns. The file path will to a list
* of file paths to be used with --exclude-from. * of file paths to be used with --exclude-from.
* * dgk added this
* @param {String|Array} patterns * @param {String|Array} filePaths
* @return Rsync * @return Rsync
*/ */
Rsync.prototype.excludeFrom = function(filePaths) { Rsync.prototype.excludeFrom = function(filePaths) {
@ -327,9 +327,9 @@ Rsync.prototype.excludeFrom = function(filePaths) {
filePaths = [ filePaths ] filePaths = [ filePaths ]
} }
// TODO if it's not a path just a file try prepending the source directory
// TODO only add to list if file exsists
filePaths.forEach(function(filePath) { filePaths.forEach(function(filePath) {
if (filePath.indexOf('/') < 0) filePath=path.normalize(`${this._sources[0]}/${filePath}`)
// TODO only add to list if file exsists
this._excludeFiles.push(filePath) this._excludeFiles.push(filePath)
}, this) }, this)

View File

@ -13,6 +13,7 @@ import to from 'await-to-js'
// uci imports // uci imports
import logger from '@uci-utils/logger' import logger from '@uci-utils/logger'
import Watcher from '@uci-utils/watcher' import Watcher from '@uci-utils/watcher'
// import Watcher from '../../watcher/src/watcher'
let log = {} // declare module wide log to be set during construction let log = {} // declare module wide log to be set during construction
class Sync extends merge(Rsync, Emitter) { class Sync extends merge(Rsync, Emitter) {
@ -61,7 +62,7 @@ class Sync extends merge(Rsync, Emitter) {
async runJob(options) { async runJob(options) {
await this.loadJob(options) await this.loadJob(options)
this.live() this.live()
this.execute(options) await this.execute(this.opts)
} }
async loadJob (options) { async loadJob (options) {
@ -81,7 +82,10 @@ class Sync extends merge(Rsync, Emitter) {
} }
} // end loop } // end loop
this.dry() // dry run by default must .live() .unset('n') this.dry() // dry run by default must .live() .unset('n')
} let success = {options:options, cwd:__dirname,msg: 'job options processed sucessfully'}
log.info(success)
return success
} return new Error(options) // options is error
} }
@ -95,7 +99,7 @@ class Sync extends merge(Rsync, Emitter) {
if (err) { if (err) {
[err,res] = await to(readFile(filePath)) [err,res] = await to(readFile(filePath))
if (err) { if (err) {
err = {filePath:filePath, error:err, type:type, dir:dir[type], msg:`unable to read ${filePath} options file`} err = {filePath:filePath, cwd:__dirname, error:err, type:type, dir:dir[type], msg:`unable to read ${filePath} options file`}
log.warn(err) log.warn(err)
return err return err
} }
@ -117,6 +121,10 @@ class Sync extends merge(Rsync, Emitter) {
this.unset('n') this.unset('n')
} }
runOpts(options) {
this.opts = Object.assign(this.opts,options)
}
set (option=[],value) { set (option=[],value) {
if (typeof option === 'string') super.set(option,value) // pass through if (typeof option === 'string') super.set(option,value) // pass through
else { else {
@ -172,7 +180,7 @@ class Sync extends merge(Rsync, Emitter) {
function syncHandler(log) { function syncHandler(log) {
function sync (change) { function sync (change) {
log.info({file:change.file, type:change.type, msg:`file ${change.file} was ${change.type}`}) log.info({file:change.file, type:change.type, msg:`file ${change.file} was ${change.type}`})
this.execute() this.execute(this.opts)
} }
log.debug(`in sync make Handler, ${this._debounce}, ${sync}`) log.debug(`in sync make Handler, ${this._debounce}, ${sync}`)
if (this._debounce==null) return sync.bind(this) if (this._debounce==null) return sync.bind(this)
@ -214,18 +222,20 @@ class Sync extends merge(Rsync, Emitter) {
// TODO allow all openssh client options // TODO allow all openssh client options
if (options.privateKeyPath) cmd.push(`-i ${options.privateKeyPath}`) if (options.privateKeyPath) cmd.push(`-i ${options.privateKeyPath}`)
if (options.port) cmd.push(`-p ${options.port}`) if (options.port) cmd.push(`-p ${options.port}`)
if (options.configFile) cmd.push(`-F ${options.privateKeyPath}`) if (options.configFile) cmd.push(`-F ${options.configFile}`)
if (cmd) this.shell(cmd.join(' ')) if (options.quiet) cmd.push('-q')
if (options.additional) cmd.push(options.additional)
if (cmd.length !== 0) this.shell(`ssh ${cmd.join(' ')}`)
return this return this
} }
async execute(opts={}) { async execute(opts={}) {
// log.info({cmd:this.command(), msg:'running rsync command'}) log.info({cmd:this.command(), opts:opts, msg:'running rsync command'})
const superexecute = super.execute.bind(this) const superexecute = super.execute.bind(this)
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let status let status=''
let errors let errors=''
this.rsyncpid = superexecute( this.rsyncpid = superexecute(
function(err, code, cmd) { function(err, code, cmd) {
if (err) { if (err) {
@ -233,7 +243,7 @@ class Sync extends merge(Rsync, Emitter) {
reject ({error:err, code:code, cmd:cmd, msg:'error during sync'}) reject ({error:err, code:code, cmd:cmd, msg:'error during sync'})
} }
if (errors) log.warn({errors: errors, cmd:cmd, msg:'sync ran but with with errors'}) if (errors) log.warn({errors: errors, cmd:cmd, msg:'sync ran but with with errors'})
log.debug({cmd:cmd, status:status, msg:'sync run'}) log.info({cmd:cmd, status:status, msg:'sync run'})
resolve({cmd:cmd, errors:errors, status:status, msg:'sync run'}) resolve({cmd:cmd, errors:errors, status:status, msg:'sync run'})
}, function(data) { }, function(data) {
status += data.toString() status += data.toString()

18
test/jobs/remote.yaml Normal file
View File

@ -0,0 +1,18 @@
source: ./test/source/ # be sure to add trailing / to avoid making a subdirectory under destination
destination: /opt/destination
flags: 'av'
excludeFrom:
- ./test/source/.gitignore
# - ./hardware/i2c/bus/.npmignore
exclude:
- .gitignore
- .npmignore
set:
- delete
- delete-excluded
ssh:
host: relays.kebler.net
username: sysadmin
# watch: # true
# wait: 200
# immediate: true

View File

@ -1,12 +0,0 @@
source: ./test/repo
destination: /opt/
# optionsFile: 'mirror'
flags: 'av'
ssh:
host: switches.kebler.net
username: sysadmin
excludeFrom:
- ./test/repo/.gitignore
set:
- delete
- delete-excluded

View File

@ -2,7 +2,7 @@ import Sync from '../src/sync'
import to from 'await-to-js' import to from 'await-to-js'
import { expect } from 'chai' import { expect } from 'chai'
import { it } from 'mocha' import { it } from 'mocha'
import logger from '@uci/logger' import logger from '@uci-utils/logger'
// pause = require('@uci/utils').pPause // pause = require('@uci/utils').pPause
describe('Sync Class Testing ',async ()=> { describe('Sync Class Testing ',async ()=> {
@ -10,14 +10,8 @@ describe('Sync Class Testing ',async ()=> {
let log = logger({}) let log = logger({})
before(async () => { before(async () => {
// log = logger({ package:'@uci/sync', id: 'sync-test' }) // log = logger({ package:'@uci/sync', id: 'sync-test' })
let sync = new Sync() let sync = new Sync({jobsDir:'./test/jobs'})
// await sync.loadJob('local') await sync.loadJob('remote')
// console.log('command to be run',sync.command())
// console.log('===',sync.cwd())
// // sync.execute({cli:true})
// sync.live()
// sync.execute({cli:true})
await sync.loadJob('local')
console.log('command to be run',sync.command()) console.log('command to be run',sync.command())
sync.live() sync.live()
sync.execute({cli:true}) sync.execute({cli:true})
@ -39,7 +33,7 @@ describe('Sync Class Testing ',async ()=> {
// return // return
// } // }
// log.info(`result of remote command ${res.command} => ${res.reply.toString().trim()}`) // log.info(`result of remote command ${res.command} => ${res.reply.toString().trim()}`)
expect('test', 'test failed').to.equal('/opt') expect('test', 'test failed').to.equal('test')
}) })
}) })