Add UnpackState and DownloadState
This commit is contained in:
parent
10bded1681
commit
2725f9eac2
@ -1,5 +1,6 @@
|
|||||||
const { Injectable } = require('flitter-di')
|
const { Injectable } = require('flitter-di')
|
||||||
const moment = require('moment')
|
const moment = require('moment')
|
||||||
|
const path = require('path')
|
||||||
|
|
||||||
class UniversalPath extends Injectable {
|
class UniversalPath extends Injectable {
|
||||||
static get services() {
|
static get services() {
|
||||||
@ -56,6 +57,12 @@ class UniversalPath extends Injectable {
|
|||||||
return this.is_file() || this.is_directory()
|
return this.is_file() || this.is_directory()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async directory() {
|
||||||
|
await this.classify()
|
||||||
|
if ( this.is_directory() ) return this.path
|
||||||
|
return path.dirname(this.path)
|
||||||
|
}
|
||||||
|
|
||||||
async classify() {
|
async classify() {
|
||||||
const dir_result = await this._host.execute(`${this._directory_classify_command} ${this._path}`)
|
const dir_result = await this._host.execute(`${this._directory_classify_command} ${this._path}`)
|
||||||
if ( dir_result.exit_code === 0 ) {
|
if ( dir_result.exit_code === 0 ) {
|
||||||
|
@ -23,6 +23,7 @@ class Host extends Injectable {
|
|||||||
_file_directory_delete_command = `rm -rf "%%RESOURCE%%"`
|
_file_directory_delete_command = `rm -rf "%%RESOURCE%%"`
|
||||||
_resolve_path_command = `readlink -f "%%PATH%%"`
|
_resolve_path_command = `readlink -f "%%PATH%%"`
|
||||||
_reboot_command = `reboot`
|
_reboot_command = `reboot`
|
||||||
|
_change_directory_command = `cd "%%PATH%%"`
|
||||||
|
|
||||||
constructor(config) {
|
constructor(config) {
|
||||||
super()
|
super()
|
||||||
@ -106,6 +107,11 @@ class Host extends Injectable {
|
|||||||
await this.execute(this._file_directory_delete_command.replace('%%RESOURCE%%', resource_path))
|
await this.execute(this._file_directory_delete_command.replace('%%RESOURCE%%', resource_path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_directory_change_command(path) {
|
||||||
|
if ( typeof path !== 'string' ) path = path.path
|
||||||
|
return this._change_directory_command.replace('%%PATH%%', path)
|
||||||
|
}
|
||||||
|
|
||||||
async resolve_path(resource_path) {
|
async resolve_path(resource_path) {
|
||||||
resource_path = typeof resource_path === 'string' ? resource_path : resource_path.path
|
resource_path = typeof resource_path === 'string' ? resource_path : resource_path.path
|
||||||
return this.run_line_result(this._resolve_path_command.replace('%%PATH%%', resource_path))
|
return this.run_line_result(this._resolve_path_command.replace('%%PATH%%', resource_path))
|
||||||
|
51
app/classes/state/fs/DownloadState.js
Normal file
51
app/classes/state/fs/DownloadState.js
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
const State = require('../State')
|
||||||
|
const axios = require('axios')
|
||||||
|
|
||||||
|
class DownloadState extends State {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'output']
|
||||||
|
}
|
||||||
|
|
||||||
|
async apply() {
|
||||||
|
if ( !(await this.check()) ) {
|
||||||
|
const path = await this._path()
|
||||||
|
if ( !this._config.method ) this._config.method = 'get'
|
||||||
|
else this._config.method = this._config.method.toLowerCase()
|
||||||
|
|
||||||
|
if ( !this._config.source ) throw new Error('Missing source config for DownloadState.')
|
||||||
|
try {
|
||||||
|
const res = await axios({
|
||||||
|
method: this._config.method,
|
||||||
|
url: this._config.source,
|
||||||
|
responseType: 'stream',
|
||||||
|
})
|
||||||
|
|
||||||
|
const write_stream = await path.open_write_stream()
|
||||||
|
await res.data.pipe(write_stream)
|
||||||
|
} catch(e) {
|
||||||
|
this.output.error('Error encountered while fetching data for DownloadState.')
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async check() {
|
||||||
|
const path = await this._path()
|
||||||
|
await path.classify()
|
||||||
|
return path.is_file()
|
||||||
|
}
|
||||||
|
|
||||||
|
async reverse() {
|
||||||
|
if ( await this.check() ) {
|
||||||
|
const path = await this._path()
|
||||||
|
await path.unlink()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _path() {
|
||||||
|
if ( !this._config.path ) throw new Error('Missing path config for DownloadState.')
|
||||||
|
return this._host.get_path(this._config.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = DownloadState
|
@ -28,6 +28,7 @@ class FileState extends State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _path() {
|
async _path() {
|
||||||
|
if ( !this._config.path ) throw new Error('Missing path config for FileState.')
|
||||||
return this._host.get_path(this._config.path)
|
return this._host.get_path(this._config.path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
63
app/classes/state/fs/UnpackState.js
Normal file
63
app/classes/state/fs/UnpackState.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
const State = require('../State')
|
||||||
|
|
||||||
|
class UnpackState extends State {
|
||||||
|
static get services() {
|
||||||
|
return [...super.services, 'output']
|
||||||
|
}
|
||||||
|
|
||||||
|
async apply() {
|
||||||
|
if ( !(await this.check()) ) {
|
||||||
|
const path = await this._path()
|
||||||
|
await path.classify()
|
||||||
|
if ( !path.is_file() ) throw new Error(`Invalid path for unpack: ${path}`)
|
||||||
|
const type = await this._get_type()
|
||||||
|
const destination = await this._destination()
|
||||||
|
const cd_cmd = await this._host.get_directory_change_command(await destination.directory())
|
||||||
|
|
||||||
|
if ( type === 'tar' ) {
|
||||||
|
const untar_cmd = `${cd_cmd} && tar -x -z -f "${path.path}"`
|
||||||
|
await this._host.run(untar_cmd)
|
||||||
|
|
||||||
|
} else if ( type === 'zip' ) {
|
||||||
|
const unzip_cmd = `${cd_cmd} && unzip "${path.path}"`
|
||||||
|
await this._host.run(unzip_cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async check() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
async reverse() {
|
||||||
|
this.output.warn(`Unpack state does not currently support reversal. (Host: ${this._host.name})`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async _get_type() {
|
||||||
|
if ( this._config.type ) {
|
||||||
|
if ( this._config.type === 'tar' ) return 'tar'
|
||||||
|
else if ( this._config.type === 'zip' ) return 'zip'
|
||||||
|
throw new Error('Invalid unpack type: ' + this._config.type)
|
||||||
|
} else {
|
||||||
|
const path = await this._path()
|
||||||
|
if ( path.path.endsWith('.tar.gz') || path.path.endsWith('.tgz') ) return 'tar'
|
||||||
|
else if ( path.path.endsWith('.zip') ) return 'zip'
|
||||||
|
throw new Error(`Unable to determine unpack type from archive: ${path}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async _path() {
|
||||||
|
if ( !this._config.path ) throw new Error('Missing path config for UnpackState.')
|
||||||
|
return this._host.get_path(this._config.path)
|
||||||
|
}
|
||||||
|
|
||||||
|
async _destination() {
|
||||||
|
if ( !this._config.destination ) throw new Error('Missing destination config for UnpackState.')
|
||||||
|
const path = await this._host.get_path(this._config.destination)
|
||||||
|
await path.classify()
|
||||||
|
if ( !path.is_directory() ) throw new Error(`Invalid extraction path. Must be a directory: ${path}`)
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = exports = UnpackState
|
@ -13,14 +13,14 @@ class StatesService extends Service {
|
|||||||
static #state_map = {
|
static #state_map = {
|
||||||
// TODO apache and nginx states - virtual host, reverse proxy
|
// TODO apache and nginx states - virtual host, reverse proxy
|
||||||
// TODO file/directory permissions state - chmod & chown
|
// TODO file/directory permissions state - chmod & chown
|
||||||
// TODO file download state
|
// TODO file pack state - zip, tarball
|
||||||
// TODO file unpack state - zips, tarballs
|
|
||||||
// TODO package repository states - import keys, install repository
|
// TODO package repository states - import keys, install repository
|
||||||
// TODO service manager states - service enabled, service installed
|
// TODO service manager states - service enabled, service installed
|
||||||
// TODO git states - clone repo, ref checked out
|
// TODO git states - clone repo, ref checked out
|
||||||
|
|
||||||
'fs.file': require('../classes/state/fs/FileState'),
|
'fs.file': require('../classes/state/fs/FileState'),
|
||||||
'fs.directory': require('../classes/state/fs/DirectoryState'),
|
'fs.directory': require('../classes/state/fs/DirectoryState'),
|
||||||
|
'fs.unpack': require('../classes/state/fs/UnpackState'),
|
||||||
|
|
||||||
'package.present': require('../classes/state/os/PackageState'),
|
'package.present': require('../classes/state/os/PackageState'),
|
||||||
'package.updates': require('../classes/state/os/UpdateState'),
|
'package.updates': require('../classes/state/os/UpdateState'),
|
||||||
@ -29,6 +29,8 @@ class StatesService extends Service {
|
|||||||
'service.running': require('../classes/state/os/ServiceState'),
|
'service.running': require('../classes/state/os/ServiceState'),
|
||||||
'service.restarted': require('../classes/state/os/ServiceRestartState'),
|
'service.restarted': require('../classes/state/os/ServiceRestartState'),
|
||||||
'service.daemon.reloaded': require('../classes/state/os/ServiceDaemonReloadState'),
|
'service.daemon.reloaded': require('../classes/state/os/ServiceDaemonReloadState'),
|
||||||
|
|
||||||
|
'web.download': require('../classes/state/fs/DownloadState'),
|
||||||
}
|
}
|
||||||
|
|
||||||
static get services() {
|
static get services() {
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"author": "Garrett Mills <garrett@glmdev.tech> (https://glmdev.tech/)",
|
"author": "Garrett Mills <garrett@glmdev.tech> (https://glmdev.tech/)",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"axios": "^0.19.2",
|
||||||
"cross-zip": "^2.1.6",
|
"cross-zip": "^2.1.6",
|
||||||
"flitter-agenda": "^0.5.0",
|
"flitter-agenda": "^0.5.0",
|
||||||
"flitter-auth": "^0.15.1",
|
"flitter-auth": "^0.15.1",
|
||||||
|
@ -208,6 +208,13 @@ axios@^0.19.0:
|
|||||||
follow-redirects "1.5.10"
|
follow-redirects "1.5.10"
|
||||||
is-buffer "^2.0.2"
|
is-buffer "^2.0.2"
|
||||||
|
|
||||||
|
axios@^0.19.2:
|
||||||
|
version "0.19.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
|
||||||
|
integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
|
||||||
|
dependencies:
|
||||||
|
follow-redirects "1.5.10"
|
||||||
|
|
||||||
babel-core@^5.4.7:
|
babel-core@^5.4.7:
|
||||||
version "5.8.38"
|
version "5.8.38"
|
||||||
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-5.8.38.tgz#1fcaee79d7e61b750b00b8e54f6dfc9d0af86558"
|
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-5.8.38.tgz#1fcaee79d7e61b750b00b8e54f6dfc9d0af86558"
|
||||||
|
Loading…
Reference in New Issue
Block a user