@@ -66,7 +66,8 @@ type ContainerManager struct {
6666
6767func NewContainerManager (logger * types.Logger , app * App , containerFile string ,
6868 systemConfig * types.SystemConfig , configPort int64 , lifetime , scheme , health , buildDir string , sourceFS appfs.ReadableFS ,
69- paramMap map [string ]string , containerConfig types.Container , stripAppPath bool ) (* ContainerManager , error ) {
69+ paramMap map [string ]string , containerConfig types.Container , stripAppPath bool ,
70+ containerVolumes []string ) (* ContainerManager , error ) {
7071
7172 image := ""
7273 volumes := []string {}
@@ -138,6 +139,7 @@ func NewContainerManager(logger *types.Logger, app *App, containerFile string,
138139 command : container.ContainerCommand {Logger : logger },
139140 paramMap : paramMap ,
140141 volumes : volumes ,
142+ extraVolumes : containerVolumes ,
141143 containerConfig : containerConfig ,
142144 stateLock : sync.RWMutex {},
143145 currentState : ContainerStateUnknown ,
@@ -268,6 +270,46 @@ func (m *ContainerManager) GetHealthUrl(appHealthUrl string) string {
268270 return healthUrl
269271}
270272
273+ func getMapHash (input map [string ]string ) (string , error ) {
274+ keys := []string {}
275+ for k := range input {
276+ keys = append (keys , k )
277+ }
278+ slices .Sort (keys ) // Sort the keys to ensure consistent hash
279+
280+ hashBuilder := strings.Builder {}
281+ for _ , paramName := range keys {
282+ paramVal := input [paramName ]
283+ // Default to string
284+ hashBuilder .WriteString (paramName )
285+ hashBuilder .WriteByte (0 )
286+ hashBuilder .WriteString (paramVal )
287+ hashBuilder .WriteByte (0 )
288+ }
289+
290+ sha := sha256 .New ()
291+ if _ , err := sha .Write ([]byte (hashBuilder .String ())); err != nil {
292+ return "" , err
293+ }
294+ return hex .EncodeToString (sha .Sum (nil )), nil
295+ }
296+
297+ func getSliceHash (input []string ) (string , error ) {
298+ slices .Sort (input ) // Sort the keys to ensure consistent hash
299+
300+ hashBuilder := strings.Builder {}
301+ for _ , v := range input {
302+ hashBuilder .WriteString (v )
303+ hashBuilder .WriteByte (0 )
304+ }
305+
306+ sha := sha256 .New ()
307+ if _ , err := sha .Write ([]byte (hashBuilder .String ())); err != nil {
308+ return "" , err
309+ }
310+ return hex .EncodeToString (sha .Sum (nil )), nil
311+ }
312+
271313func (m * ContainerManager ) GetEnvMap () (map [string ]string , string ) {
272314 paramKeys := []string {}
273315 for k := range m .paramMap {
@@ -327,15 +369,8 @@ func (m *ContainerManager) createSpecFiles() ([]string, error) {
327369 return created , nil
328370}
329371
330- func (m * ContainerManager ) getVolumes () []string {
331- allVolumes := append (m .volumes , m .extraVolumes ... )
332- slices .Sort (allVolumes )
333- return slices .Compact (allVolumes )
334- }
335-
336372func (m * ContainerManager ) createVolumes () error {
337- allVolumes := m .getVolumes ()
338- for _ , v := range allVolumes {
373+ for _ , v := range m .volumes {
339374 volumeName := container .GenVolumeName (m .app .Id , v )
340375 if ! m .command .VolumeExists (m .systemConfig , volumeName ) {
341376 err := m .command .VolumeCreate (m .systemConfig , volumeName )
@@ -344,19 +379,62 @@ func (m *ContainerManager) createVolumes() error {
344379 }
345380 }
346381 }
382+
383+ for _ , volArg := range m .extraVolumes {
384+ parsedName := m .parseVolumeName (volArg )
385+ if parsedName == "" {
386+ continue
387+ }
388+ genVolumeName := container .GenVolumeName (m .app .Id , parsedName )
389+ if ! m .command .VolumeExists (m .systemConfig , genVolumeName ) {
390+ err := m .command .VolumeCreate (m .systemConfig , genVolumeName )
391+ if err != nil {
392+ return fmt .Errorf ("error creating volume %s: %w" , genVolumeName , err )
393+ }
394+ }
395+ }
347396 return nil
348397}
349398
350399func (m * ContainerManager ) getMountArgs () []string {
351- allVolumes := m .getVolumes ()
352400 args := []string {}
353- for _ , v := range allVolumes {
401+ for _ , v := range m . volumes {
354402 volumeName := container .GenVolumeName (m .app .Id , v )
355403 args = append (args , fmt .Sprintf ("--mount=type=volume,source=%s,target=%s" , volumeName , v ))
356404 }
405+
406+ for _ , volArg := range m .extraVolumes {
407+ parsedName := m .parseVolumeName (volArg )
408+ if parsedName == "" {
409+ args = append (args , fmt .Sprintf ("--volume=%s" , volArg ))
410+ } else {
411+ genVolumeName := container .GenVolumeName (m .app .Id , parsedName )
412+ split := strings .Split (volArg , ":" )
413+ var volString string
414+ if len (split ) > 1 {
415+ split [0 ] = string (genVolumeName )
416+ volString = strings .Join (split , ":" )
417+ } else {
418+ volString = string (genVolumeName ) + ":" + volArg
419+ }
420+ args = append (args , fmt .Sprintf ("--volume=%s" , volString ))
421+ }
422+ }
357423 return args
358424}
359425
426+ // parseVolumeName gets the first part of the volume definition. It returns "" for a bind
427+ // mount. Otherwise it returns the volume name
428+ func (m * ContainerManager ) parseVolumeName (arg string ) string {
429+ split := strings .Split (arg , ":" )
430+ firstPart := split [0 ]
431+ if len (split ) > 1 && len (firstPart ) > 0 && firstPart [:1 ] == "/" {
432+ return ""
433+ }
434+
435+ return firstPart
436+ }
437+
360438func (m * ContainerManager ) DevReload (dryRun bool ) error {
361439 var imageName container.ImageName = container .ImageName (m .image )
362440 if imageName == "" {
@@ -485,13 +563,27 @@ func (m *ContainerManager) getAppHash() (string, error) {
485563 }
486564
487565 _ , envHash := m .GetEnvMap ()
488- fullHashVal := fmt .Sprintf ("%s-%s" , sourceHash , envHash )
566+
567+ coptHash , err := getMapHash (m .app .Metadata .ContainerOptions )
568+ if err != nil {
569+ return "" , fmt .Errorf ("error getting copt hash: %w" , err )
570+ }
571+ cargHash , err := getMapHash (m .app .Metadata .ContainerArgs )
572+ if err != nil {
573+ return "" , fmt .Errorf ("error getting carg hash: %w" , err )
574+ }
575+ cvolHash , err := getSliceHash (m .app .Metadata .ContainerVolumes )
576+ if err != nil {
577+ return "" , fmt .Errorf ("error getting cvol hash: %w" , err )
578+ }
579+ fullHashVal := fmt .Sprintf ("%s-%s-%s-%s-%s" , sourceHash , envHash , coptHash , cargHash , cvolHash )
489580 sha := sha256 .New ()
490581 if _ , err := sha .Write ([]byte (fullHashVal )); err != nil {
491582 return "" , err
492583 }
493584 fullHash := hex .EncodeToString (sha .Sum (nil ))
494- m .Debug ().Msgf ("Source hash %s Env hash %s Full hash %s" , sourceHash , envHash , fullHash )
585+ m .Debug ().Msgf ("Source hash %s Env hash %s copt hash %s args hash %s cvol hash %s Full hash %s" ,
586+ sourceHash , envHash , coptHash , cargHash , cvolHash , fullHash )
495587 return fullHash , nil
496588}
497589
0 commit comments