-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathnodes-installer.js
200 lines (190 loc) · 5.74 KB
/
nodes-installer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
const request = require('request')
const path = require('path')
const { promisify } = require('util')
const { execFile } = require('child_process')
const execFileAsync = promisify(execFile)
const fs = require('fs')
const pgutil = require('./pgutil')
const npmCommand = process.platform === 'win32' ? 'npm.cmd' : 'npm'
let appname
const needDownloadFlow = async () => {
let data = await pgutil.loadConfig(appname)
if (!process.env.SECURE_LINK) {
console.log('***** SECURE_LINK', process.env.SECURE_LINK)
return false
}
if (data && data.secureLink && data.secureLink === process.env.SECURE_LINK) {
return false
} else {
return true
}
}
const savePrivateNodeFilesToPG = async (packages) => {
console.log('savePrivateNodeFilesToPG', packages)
if (!packages) {
return
}
for (let name in packages) {
if (
typeof packages[name] === 'object' &&
packages[name].type === 'privatenode'
) {
await downloadAndSavePrivateNode(name, packages[name].url)
}
}
}
const downloadAndSavePrivateNode = async (packageName, url) => {
console.log('downloadAndSavePrivateNode:', packageName, url)
const { err, res, body } = await new Promise((resolve, reject) => {
request.get(url, { encoding: null }, (err, res, body) => {
//console.log(`download ${packageName} `, err, res, body)
resolve({ err, res, body })
})
})
if (err) {
throw err
} else {
if (res.statusCode != 200) {
console.error('Failed to download privatenode' + res.statusCode)
throw new Error(
'Failed to download privatenode: status code:' + res.statusCode
)
} else {
let buffer = new Buffer.from(body)
let base64str = buffer.toString('base64')
await pgutil.savePrivateNodes(appname, {
appname,
packageName,
data: base64str
})
}
}
}
// npmを使ったインストールを行う
// packageは以下の2パタンのパッケージ文字列の配列
// ・<package name>@<version>
// ・<File(tgz) path>
const installNPMModule = async (packages) => {
let result = await execFileAsync(npmCommand, ['install', ...packages], {
cwd: path.resolve(__dirname)
})
return result
}
const getPrivateNodePackageStringForInstall = async (packageName) => {
console.log('installPrivateNodePackage:' + packageName)
const data = await pgutil.loadPrivateNodes(appname, packageName)
if (!data || !data.data) {
throw new Error(`Failed to find private node packages: ${packageName}`)
}
// Save decoded data to /tmp
let decoded = Buffer.from(data.data, 'base64')
let packageString = await new Promise((resolve, reject) => {
console.log(`save /tmp/${packageName}.tgz`)
fs.writeFile(`/tmp/${packageName}.tgz`, decoded, (err) => {
if (err) {
console.error('Failed to save privatenode file: ' + packageName)
return reject(err)
}
//Test check file
if (fs.existsSync(`/tmp/${packageName}.tgz`)) {
console.log('success save privatenode !')
} else {
console.log('fail save privatenode !')
}
// return package string
console.log(`install file:/tmp/${packageName}.tgz`)
resolve(`file:/tmp/${packageName}.tgz`)
})
})
return packageString
}
const installPackages = async (packages) => {
if (!packages) {
return
}
const names = Object.keys(packages)
let packageStrings = await Promise.all(
names.map((name) => {
if (
typeof packages[name] === 'object' &&
packages[name].type === 'privatenode'
) {
return getPrivateNodePackageStringForInstall(name)
} else {
// ユーザがインストールしたノードのパッケージ文字列取得
return `${name}@${packages[name]}`
}
})
)
await new Promise((resolve, reject) => {
console.log(`install nodes: ${packageStrings}`)
installNPMModule(packageStrings)
.then((result) => {
console.log(`install node packages success: ${packageStrings}`)
resolve(result)
})
.catch((err) => {
console.log(`install node packages fail: ${packageStrings}`, err)
reject(err)
})
})
}
// enebular
// Save flow/credentials/packages/secureLink information to PostgreSQL
// Save PrivateNode to PostgreSQL if exists
const prepareEnebularFlow = async () => {
var url = process.env.SECURE_LINK
if (!url) {
throw new Error('SECURE_LINK not defined')
}
await pgutil.removeConfig(appname)
await pgutil.removePrivateNodes(appname)
const data = await new Promise((resolve, reject) => {
request.get({ url: url, json: false }, (err, res, body) => {
if (err) {
return reject(err)
}
if (res.statusCode != 200) {
return resolve(null)
}
if (body) {
let data = JSON.parse(body)
resolve(data)
}
})
})
let flows = data && data.flow ? data.flow : []
let credentials = data && data.cred ? data.cred : {}
let packages = {}
if (data && data.packages) {
packages = data.packages
await savePrivateNodeFilesToPG(packages)
}
await pgutil.saveConfig(appname, {
appname,
flows,
credentials,
packages,
settings: {},
secureLink: url
})
}
const installNodes = async () => {
try {
appname = require('./settings').pgAppname || require('os').hostname()
console.log('Presigned URLからFlowの取得が必要か判定')
const need = await needDownloadFlow()
if (need) {
console.log('Download flow pack from S3')
await prepareEnebularFlow()
}
// Node-REDのノード(プライベートノード含む)のインストール
const data = await pgutil.loadConfig(appname)
if (data && data.packages) {
await installPackages(data.packages)
}
} catch (err) {
throw err
}
}
module.exports = installNodes