@@ -3,6 +3,39 @@ const tar = require('tar-fs');
33const path = require ( 'path' ) ;
44const stream = require ( 'stream' ) ;
55
6+ /**
7+ * if host path in the volume string (e.g. `./mylocal/file:/container/file`) is not absolute path,
8+ * this function will convert it to an absolute path using `cwd` (current working directory) parameter.
9+ * Otherwise, it will return volume string as it is.
10+ *
11+ * @param {* } volumeStr
12+ * @param {* } cwd
13+ */
14+ function standardizeVolumeStr ( volumeStr , cwd ) {
15+ if ( typeof volumeStr !== 'string' || volumeStr . length < 1 ) {
16+ return volumeStr ;
17+ }
18+ volumeStr = volumeStr . trim ( ) ;
19+ if (
20+ volumeStr . substring ( 0 , 2 ) !== './' &&
21+ volumeStr . substring ( 0 , 3 ) !== '../'
22+ ) {
23+ return volumeStr ;
24+ }
25+ const parts = volumeStr . split ( ':' ) ;
26+ if ( parts . length !== 2 ) {
27+ return volumeStr ;
28+ }
29+ if ( ! cwd ) {
30+ throw new Error (
31+ 'Current working dir path not available when local path is a relative path: ' +
32+ parts [ 0 ]
33+ ) ;
34+ }
35+ const localPath = parts [ 0 ] ;
36+ return path . resolve ( cwd , localPath ) + ':' + parts [ 1 ] ;
37+ }
38+
639module . exports = {
740 buildPorts : function ( servicePorts , output ) {
841 var ports = { } ;
@@ -41,15 +74,19 @@ module.exports = {
4174
4275 for ( let index in split_port_split0_array ) {
4376 ports [ split_port_split1_array [ index ] + '/tcp' ] = [
44- { HostPort : split_port_split0_array [ index ] . toString ( ) } ,
77+ {
78+ HostPort : split_port_split0_array [ index ] . toString ( ) ,
79+ } ,
4580 ] ;
4681 }
4782 } else if ( port_split [ 0 ] . includes ( '-' ) ) {
4883 // "3000-3005"
4984 let split_port_split = port_split [ 0 ] . split ( '-' ) ;
5085 ports [ port_split [ 1 ] + '/tcp' ] = [ ] ;
5186 for ( let i = split_port_split [ 0 ] ; i <= split_port_split [ 1 ] ; i ++ ) {
52- ports [ port_split [ 1 ] + '/tcp' ] . push ( { HostPort : i . toString ( ) } ) ;
87+ ports [ port_split [ 1 ] + '/tcp' ] . push ( {
88+ HostPort : i . toString ( ) ,
89+ } ) ;
5390 }
5491 } else if ( port_split [ 1 ] . includes ( '/' ) ) {
5592 // "6060:6060/udp"
@@ -114,7 +151,7 @@ module.exports = {
114151 } ,
115152
116153 //ToDo: complete the compose specification
117- buildHostConfig : function ( projectName , service , recipe ) {
154+ buildHostConfig : function ( projectName , service , recipe , cwd ) {
118155 var output = {
119156 RestartPolicy : { Name : service . restart } ,
120157 } ;
@@ -123,12 +160,24 @@ module.exports = {
123160 for ( var volume_from of service . volumes_from ) {
124161 var vf = volume_from . split ( ':' ) ;
125162 var svf = recipe . services [ vf [ 0 ] ] ;
126- this . buildVolumesHostconfig ( projectName , svf . volumes , output , vf [ 1 ] ) ;
163+ this . buildVolumesHostconfig (
164+ projectName ,
165+ svf . volumes ,
166+ output ,
167+ vf [ 1 ] ,
168+ cwd
169+ ) ;
127170 }
128171 }
129172
130173 if ( service . volumes !== undefined ) {
131- this . buildVolumesHostconfig ( projectName , service . volumes , output ) ;
174+ this . buildVolumesHostconfig (
175+ projectName ,
176+ service . volumes ,
177+ output ,
178+ undefined ,
179+ cwd
180+ ) ;
132181 }
133182
134183 if ( service . ports !== undefined ) {
@@ -334,22 +383,46 @@ module.exports = {
334383 return output ;
335384 } ,
336385
337- buildVolumesHostconfig : function ( projectName , volumes , output , type ) {
386+ buildVolumesHostconfig : function ( projectName , volumes , output , type , cwd ) {
338387 if ( output [ 'Binds' ] === undefined ) {
339388 output [ 'Binds' ] = [ ] ;
340389 }
341390 for ( var volume of volumes ) {
342391 if ( typeof volume === 'string' || volume instanceof String ) {
343- var aux = projectName + '_' + volume ;
344- if ( type == 'ro' ) {
345- aux += ':ro' ;
392+ if (
393+ volume . substring ( 0 , 2 ) === './' ||
394+ volume . substring ( 0 , 3 ) === '../' ||
395+ volume [ 0 ] === '/'
396+ ) {
397+ const stdVolume = standardizeVolumeStr ( volume , cwd ) ;
398+ const aux = stdVolume ;
399+ if ( type == 'ro' ) {
400+ aux += ':ro' ;
401+ }
402+ output [ 'Binds' ] . push ( aux ) ;
403+ } else {
404+ var aux = projectName + '_' + volume ;
405+ if ( type == 'ro' ) {
406+ aux += ':ro' ;
407+ }
408+ output [ 'Binds' ] . push ( aux ) ;
346409 }
347- output [ 'Binds' ] . push ( aux ) ;
348410 } else {
349411 var volumestr = '' ;
350412 if ( volume . source && volume . target ) {
351- volumestr +=
352- projectName + '_' + volume . source + ':' + volume . target + ':' ;
413+ if (
414+ volume . source . substring ( 0 , 2 ) === './' ||
415+ volume . source . substring ( 0 , 3 ) === '../' ||
416+ volume . source [ 0 ] === '/'
417+ ) {
418+ volumestr += standardizeVolumeStr (
419+ volume . source + ':' + volume . target ,
420+ cwd
421+ ) ;
422+ } else {
423+ volumestr +=
424+ projectName + '_' + volume . source + ':' + volume . target + ':' ;
425+ }
353426 }
354427 if ( volume . read_only || type == 'ro' ) {
355428 volumestr += 'ro,' ;
@@ -371,6 +444,9 @@ module.exports = {
371444 opts [ 'Volumes' ] = { } ;
372445 }
373446 for ( var volume of volumes ) {
447+ if ( volume . substring ( 0 , 2 ) === './' || volume [ 0 ] === '/' ) {
448+ continue ;
449+ }
374450 if ( typeof volume === 'string' || volume instanceof String ) {
375451 var v = volume . split ( ':' ) ;
376452 opts [ 'Volumes' ] [ v [ 1 ] ] = { } ;
0 commit comments