UNPKG

mecano

Version:

Common functions for system deployment.

203 lines (184 loc) 7.41 kB
# `service(options, callback)` Install a service. For now, only yum over SSH. ## Options * `name` (string) Package name, optional. * `startup` Run service daemon on startup. If true, startup will be set to '2345', use an empty string to not define any run level. * `yum_name` (string) Name used by the yum utility, default to "name". * `chk_name` (string) Name used by the chkconfig utility, default to "srv_name" and "name". * `srv_name` (string) Name used by the service utility, default to "name". * `cache` Run entirely from system cache to list installed and outdated packages. * `action` Execute the service with the provided action argument. * `installed` Cache a list of installed services. If an object, the service will be installed if a key of the same name exists; if anything else (default), no caching will take place. * `updates` Cache a list of outdated services. If an object, the service will be updated if a key of the same name exists; If true, the option will be converted to an object with all the outdated service names as keys; if anything else (default), no caching will take place. * `ssh` (object|ssh2) Run the action on a remote server using SSH, an ssh2 instance or an configuration object used to initialize the SSH connection. * `stdout` (stream.Writable) Writable EventEmitter in which the standard output of executed commands will be piped. * `stderr` (stream.Writable) Writable EventEmitter in which the standard error output of executed command will be piped. ## Callback parameters * `err` Error object if any. * `modified` Number of action taken (installed, updated, started or stopped). * `installed` List of installed services. * `updates` List of services to update. ## Example ```js require('mecano').service([{ ssh: ssh, name: 'ganglia-gmetad-3.5.0-99', srv_name: 'gmetad', action: 'stop', startup: false },{ ssh: ssh, name: 'ganglia-web-3.5.7-99' }], function(err, installed){ console.log(err ? err.message : 'Service installed: ' + !!installed); }); ``` ## Source Code module.exports = (options, callback) -> installed = updates = null # Validate parameters # return callback new Error 'Missing service name' unless options.name # return callback new Error 'Restricted to Yum over SSH' unless options.ssh # return callback new Error 'Invalid configuration, start conflict with stop' if options.start? and options.start is options.stop pkgname = options.yum_name or options.name chkname = options.chk_name or options.srv_name or options.name srvname = options.srv_name or options.chk_name or options.name modified = false if options.cache options.db ?= {} installed = options.db['mecano:execute:installed'] updates = options.db['mecano:execute:updates'] options.action = options.action.split(',') if typeof options.action is 'string' # Start real work do_installed = => # option name and yum_name are optional, skill installation if not present return do_startuped() unless pkgname cache = => options.log? "Mecano `service: list installed [DEBUG]" c = if options.cache then '-C' else '' @execute ssh: options.ssh cmd: "yum #{c} list installed" code_skipped: 1 stdout: null stderr: null , (err, executed, stdout) -> return callback err if err stdout = string.lines stdout start = false installed = [] for pkg in stdout start = true if pkg.trim() is 'Installed Packages' continue unless start installed.push pkg[1] if pkg = /^([^\. ]+?)\./.exec pkg decide() decide = -> if installed.indexOf(pkgname) isnt -1 then do_updates() else do_install() if installed then decide() else cache() do_updates = => cache = => options.log? "Mecano `service`: list available updates [DEBUG]" c = if options.cache then '-C' else '' @execute cmd: "yum #{c} list updates" code_skipped: 1 , (err, executed, stdout) -> return callback err if err stdout = string.lines stdout start = false updates = [] for pkg in stdout start = true if pkg.trim() is 'Updated Packages' continue unless start updates.push pkg[1] if pkg = /^([^\. ]+?)\./.exec pkg decide() decide = -> if updates.indexOf(pkgname) isnt -1 then do_install() else options.log? "Mecano `service`: No available update for '#{pkgname}' [INFO]" do_startuped() if updates then decide() else cache() do_install = => options.log? "Mecano `service`: install '#{pkgname}' [INFO]" @execute ssh: options.ssh cmd: "yum install -y #{pkgname}" , (err, succeed) -> return callback err if err installedIndex = installed.indexOf pkgname installed.push pkgname if installedIndex is -1 if updates updatesIndex = updates.indexOf pkgname updates.splice updatesIndex, 1 unless updatesIndex is -1 # Those 2 lines seems all wrong unless succeed options.log? "Mecano `service`: No package available for '#{pkgname}' [ERROR]" return callback new Error "No package available for '#{pkgname}'." modified = true if installedIndex isnt -1 do_startuped() do_startuped = => return do_started() unless options.startup? @service_startup name: chkname startup: options.startup if: options.startup? , (err, startuped) -> return callback err if err modified = startuped do_started() do_started = => return do_finish() unless options.action options.log? "Mecano `service`: check if started" @execute cmd: "service #{srvname} status" code_skipped: [3, 1] # ntpd return 1 if pidfile exists without a matching process , (err, started) -> return callback err if err if started return do_action 'stop' if 'stop' in options.action return do_action 'restart' if 'restart' in options.action else return do_action 'start' if 'start' in options.action do_finish() do_action = (action) => return do_finish() unless options.action options.log? "Mecano `service`: #{action} service" @execute cmd: "service #{srvname} #{action}" , (err, executed) -> return callback err if err modified = true do_finish() do_finish = -> if options.cache options.db['mecano:execute:installed'] = installed options.db['mecano:execute:updates'] = updates callback null, modified do_installed() ## Dependencies service_startup = require './service_startup' string = require './misc/string'