UNPKG

10.5 kBJavaScriptView Raw
1'use strict';
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10const { generateDockerDebugOpts } = require('./debug');
11const debug = require('debug')('docker-opts');
12const nestedObjectAssign = require('nested-object-assign');
13const { addEnv } = require('./install/env');
14const definition = require('./definition');
15const _ = require('lodash');
16const { red } = require('colors');
17const httpx = require('httpx');
18const getVisitor = require('../lib/visitor').getVisitor;
19const pkg = require('../package.json');
20const NAS_UID = 10003;
21const NAS_GID = 10003;
22const DEFAULT_REGISTRY = pkg['fc-docker'].registry_default || 'registry.hub.docker.com';
23const DOCKER_REGISTRIES = pkg['fc-docker'].registry_mirrors || ['registry.hub.docker.com'];
24let DOCKER_REGISTRY_CACHE;
25const runtimeImageMap = {
26 'nodejs6': 'nodejs6',
27 'nodejs8': 'nodejs8',
28 'python2.7': 'python2.7',
29 'python3': 'python3.6',
30 'java8': 'java8',
31 'php7.2': 'php7.2',
32 'nodejs10': 'nodejs10',
33 'dotnetcore2.1': 'dotnetcore2.1',
34 'custom': 'custom'
35};
36function resolveDockerEnv(envs = {}) {
37 return _.map(addEnv(envs || {}), (v, k) => `${k}=${v}`);
38}
39function doImageRegisterEventTag(el) {
40 return __awaiter(this, void 0, void 0, function* () {
41 const visitor = yield getVisitor();
42 visitor.event({
43 ec: 'imageRegistry',
44 ea: 'resolve',
45 el
46 }).send();
47 });
48}
49function resolveDockerRegistry() {
50 return __awaiter(this, void 0, void 0, function* () {
51 yield doImageRegisterEventTag('start');
52 if (DOCKER_REGISTRY_CACHE) {
53 return DOCKER_REGISTRY_CACHE;
54 }
55 const promises = DOCKER_REGISTRIES.map(r => httpx.request(`https://${r}/v2/aliyunfc/runtime-nodejs8/tags/list`, { timeout: 3000 }).then(() => r));
56 try {
57 DOCKER_REGISTRY_CACHE = yield Promise.race(promises);
58 }
59 catch (error) {
60 DOCKER_REGISTRY_CACHE = DEFAULT_REGISTRY;
61 }
62 yield doImageRegisterEventTag(DOCKER_REGISTRY_CACHE);
63 return DOCKER_REGISTRY_CACHE;
64 });
65}
66const IMAGE_VERSION = pkg['fc-docker'].version || '1.9.2';
67function resolveRuntimeToDockerImage(runtime, isBuild) {
68 return __awaiter(this, void 0, void 0, function* () {
69 if (runtimeImageMap[runtime]) {
70 const name = runtimeImageMap[runtime];
71 var imageName;
72 if (isBuild) {
73 imageName = `aliyunfc/runtime-${name}:build-${IMAGE_VERSION}`;
74 }
75 else {
76 imageName = `aliyunfc/runtime-${name}:${IMAGE_VERSION}`;
77 }
78 debug('imageName: ' + imageName);
79 return imageName;
80 }
81 throw new Error(red(`invalid runtime name ${runtime}`));
82 });
83}
84function resolveImageNameForPull(imageName) {
85 return __awaiter(this, void 0, void 0, function* () {
86 const dockerImageRegistry = yield resolveDockerRegistry();
87 if (dockerImageRegistry) {
88 imageName = `${dockerImageRegistry}/${imageName}`;
89 }
90 return imageName;
91 });
92}
93function generateInstallOpts(imageName, mounts, envs) {
94 return {
95 Image: imageName,
96 Tty: true,
97 Env: resolveDockerEnv(envs),
98 Cmd: ['/bin/bash'],
99 HostConfig: {
100 AutoRemove: true,
101 Mounts: mounts
102 }
103 };
104}
105function generateContainerName(serviceName, functionName, debugPort) {
106 return `fun-local-${serviceName}-${functionName}`.replace(/ /g, '')
107 + (debugPort ? '-debug' : '-run');
108}
109function generateContainerNameFilter(containerName, inited) {
110 if (inited) {
111 return `{"name": ["${containerName}-inited"]}`;
112 }
113 return `{"name": ["${containerName}"]}`;
114}
115function generateSboxOpts({ imageName, hostname, mounts, envs, cmd = [], isTty, isInteractive }) {
116 return {
117 Image: imageName,
118 Hostname: hostname,
119 AttachStdin: isInteractive,
120 AttachStdout: true,
121 AttachStderr: true,
122 User: resolveDockerUser({ stage: 'sbox' }),
123 Tty: isTty,
124 OpenStdin: isInteractive,
125 StdinOnce: true,
126 Env: resolveDockerEnv(envs),
127 Cmd: cmd.length ? cmd : ['/bin/bash'],
128 HostConfig: {
129 AutoRemove: true,
130 Mounts: mounts
131 }
132 };
133}
134function transformPathForVirtualBox(source) {
135 // C:\\Users\\image_crawler\\code -> /c/Users/image_crawler/code
136 const sourcePath = source.split(':').join('');
137 const lowerFirstAndReplace = _.lowerFirst(sourcePath.split('\\').join('/'));
138 return '/' + lowerFirstAndReplace;
139}
140function transformMountsForToolbox(mounts) {
141 console.warn(red(`We detected that you are using docker toolbox. For a better experience, please upgrade 'docker for windows'.\nYou can refer to Chinese doc https://github.com/alibaba/funcraft/blob/master/docs/usage/installation-zh.md#windows-%E5%AE%89%E8%A3%85-docker or English doc https://github.com/alibaba/funcraft/blob/master/docs/usage/installation.md.\n`));
142 if (Array.isArray(mounts)) {
143 return mounts.map(m => {
144 return transformSourcePathOfMount(m);
145 });
146 }
147 return transformSourcePathOfMount(mounts);
148}
149function transformSourcePathOfMount(mountsObj) {
150 if (!_.isEmpty(mountsObj)) {
151 const replaceMounts = Object.assign({}, mountsObj);
152 replaceMounts.Source = transformPathForVirtualBox(mountsObj.Source);
153 return replaceMounts;
154 }
155 return {};
156}
157function generateContainerBuildOpts(runtime, containerName, mounts, cmd, envs, preferredImage) {
158 return __awaiter(this, void 0, void 0, function* () {
159 const hostOpts = {
160 HostConfig: {
161 AutoRemove: true,
162 Mounts: mounts
163 }
164 };
165 const ioOpts = {
166 OpenStdin: true,
167 Tty: false,
168 StdinOnce: true,
169 AttachStdin: true,
170 AttachStdout: true,
171 AttachStderr: true
172 };
173 const imageName = yield resolveRuntimeToDockerImage(runtime, true);
174 const opts = nestedObjectAssign({
175 Env: resolveDockerEnv(envs),
176 Image: preferredImage || imageName,
177 name: containerName,
178 Cmd: cmd,
179 User: resolveDockerUser({ stage: 'build' })
180 }, ioOpts, hostOpts);
181 debug('fc-docker docker options: %j', opts);
182 return opts;
183 });
184}
185function generateLocalInvokeOpts(runtime, containerName, mounts, cmd, debugPort, envs, dockerUser, debugIde) {
186 return __awaiter(this, void 0, void 0, function* () {
187 const hostOpts = {
188 HostConfig: {
189 AutoRemove: true,
190 Mounts: mounts
191 }
192 };
193 let debugOpts = {};
194 if (debugPort) {
195 debugOpts = generateDockerDebugOpts(runtime, debugPort, debugIde);
196 }
197 const ioOpts = {
198 OpenStdin: true,
199 Tty: false,
200 StdinOnce: true,
201 AttachStdin: true,
202 AttachStdout: true,
203 AttachStderr: true
204 };
205 const imageName = yield resolveRuntimeToDockerImage(runtime);
206 const opts = nestedObjectAssign({
207 Env: resolveDockerEnv(envs),
208 Image: imageName,
209 name: containerName,
210 Cmd: cmd,
211 User: dockerUser
212 }, ioOpts, hostOpts, debugOpts);
213 debug('fc-docker docker options: %j', opts);
214 return opts;
215 });
216}
217function resolveMockScript(runtime) {
218 return `/var/fc/runtime/${runtime}/mock`;
219}
220function generateLocalStartOpts(runtime, name, mounts, cmd, debugPort, envs, dockerUser, debugIde) {
221 return __awaiter(this, void 0, void 0, function* () {
222 const hostOpts = {
223 HostConfig: {
224 AutoRemove: true,
225 Mounts: mounts
226 }
227 };
228 let debugOpts = {};
229 if (debugPort) {
230 debugOpts = generateDockerDebugOpts(runtime, debugPort, debugIde);
231 }
232 const imageName = yield resolveRuntimeToDockerImage(runtime);
233 const opts = nestedObjectAssign({
234 Env: resolveDockerEnv(envs),
235 Image: imageName,
236 name,
237 Cmd: cmd,
238 User: dockerUser,
239 Entrypoint: [resolveMockScript(runtime)]
240 }, hostOpts, debugOpts);
241 debug('docker options: %j', opts);
242 return opts;
243 });
244}
245// Not Run stage:
246// for linux platform, it will always use process.uid and process.gid
247// for mac and windows platform, it will always use 0
248// Run stage:
249// for linux platform, it will always use process.uid and process.gid
250// for mac and windows platform, it will use 10003 if no nasConfig, otherwise it will use nasConfig userId
251function resolveDockerUser({ nasConfig, stage = 'run' }) {
252 let { userId, groupId } = definition.getUserIdAndGroupId(nasConfig);
253 if (process.platform === 'linux') {
254 console.log(red('Warning: for linux platform, Fun will use host userId and groupId to build or run your functions'));
255 userId = process.getuid();
256 groupId = process.getgid();
257 }
258 else {
259 if (stage === 'run') {
260 if (userId === -1 || userId === undefined) {
261 userId = NAS_UID;
262 }
263 if (groupId === -1 || groupId === undefined) {
264 groupId = NAS_GID;
265 }
266 }
267 else {
268 userId = 0;
269 groupId = 0;
270 }
271 }
272 return `${userId}:${groupId}`;
273}
274module.exports = {
275 generateLocalInvokeOpts, resolveRuntimeToDockerImage,
276 generateInstallOpts, generateSboxOpts,
277 generateLocalStartOpts,
278 resolveMockScript, resolveDockerEnv, transformPathForVirtualBox,
279 resolveDockerRegistry, transformMountsForToolbox, transformSourcePathOfMount,
280 DOCKER_REGISTRIES, generateContainerBuildOpts,
281 IMAGE_VERSION, resolveImageNameForPull, generateContainerName,
282 generateContainerNameFilter, resolveDockerUser
283};