@@ -92,7 +92,8 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt
9292 return err
9393 }
9494
95- if err := s .ensureProjectVolumes (ctx , project ); err != nil {
95+ volumes , err := s .ensureProjectVolumes (ctx , project )
96+ if err != nil {
9697 return err
9798 }
9899
@@ -115,7 +116,7 @@ func (s *composeService) create(ctx context.Context, project *types.Project, opt
115116 "--remove-orphans flag to clean it up." , orphans .names ())
116117 }
117118 }
118- return newConvergence (options .Services , observedState , networks , s ).apply (ctx , project , options )
119+ return newConvergence (options .Services , observedState , networks , volumes , s ).apply (ctx , project , options )
119120}
120121
121122func prepareNetworks (project * types.Project ) {
@@ -141,15 +142,17 @@ func (s *composeService) ensureNetworks(ctx context.Context, project *types.Proj
141142 return networks , nil
142143}
143144
144- func (s * composeService ) ensureProjectVolumes (ctx context.Context , project * types.Project ) error {
145+ func (s * composeService ) ensureProjectVolumes (ctx context.Context , project * types.Project ) (map [string ]string , error ) {
146+ ids := map [string ]string {}
145147 for k , volume := range project .Volumes {
146148 volume .Labels = volume .Labels .Add (api .VolumeLabel , k )
147149 volume .Labels = volume .Labels .Add (api .ProjectLabel , project .Name )
148150 volume .Labels = volume .Labels .Add (api .VersionLabel , api .ComposeVersion )
149- err := s .ensureVolume (ctx , volume , project .Name )
151+ id , err := s .ensureVolume (ctx , volume , project .Name )
150152 if err != nil {
151- return err
153+ return nil , err
152154 }
155+ ids [k ] = id
153156 }
154157
155158 err := func () error {
@@ -205,7 +208,7 @@ func (s *composeService) ensureProjectVolumes(ctx context.Context, project *type
205208 if err != nil {
206209 progress .ContextWriter (ctx ).TailMsgf ("Failed to prepare Synchronized file shares: %v" , err )
207210 }
208- return nil
211+ return ids , nil
209212}
210213
211214func (s * composeService ) getCreateConfigs (ctx context.Context ,
@@ -1431,21 +1434,21 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne
14311434 }
14321435}
14331436
1434- func (s * composeService ) ensureVolume (ctx context.Context , volume types.VolumeConfig , project string ) error {
1437+ func (s * composeService ) ensureVolume (ctx context.Context , volume types.VolumeConfig , project string ) ( string , error ) {
14351438 inspected , err := s .apiClient ().VolumeInspect (ctx , volume .Name )
14361439 if err != nil {
14371440 if ! errdefs .IsNotFound (err ) {
1438- return err
1441+ return "" , err
14391442 }
14401443 if volume .External {
1441- return fmt .Errorf ("external volume %q not found" , volume .Name )
1444+ return "" , fmt .Errorf ("external volume %q not found" , volume .Name )
14421445 }
1443- err : = s .createVolume (ctx , volume )
1444- return err
1446+ err = s .createVolume (ctx , volume )
1447+ return "" , err
14451448 }
14461449
14471450 if volume .External {
1448- return nil
1451+ return volume . Name , nil
14491452 }
14501453
14511454 // Volume exists with name, but let's double-check this is the expected one
@@ -1456,7 +1459,16 @@ func (s *composeService) ensureVolume(ctx context.Context, volume types.VolumeCo
14561459 if ok && p != project {
14571460 logrus .Warnf ("volume %q already exists but was created for project %q (expected %q). Use `external: true` to use an existing volume" , volume .Name , p , project )
14581461 }
1459- return nil
1462+
1463+ expected , err := VolumeHash (volume )
1464+ if err != nil {
1465+ return "" , err
1466+ }
1467+ actual , ok := inspected .Labels [api .ConfigHashLabel ]
1468+ if ok && actual != expected {
1469+ logrus .Warnf ("volume %q exists but doesn't match configuration in compose file. You should remove it so it get recreated" , volume .Name )
1470+ }
1471+ return inspected .Name , nil
14601472}
14611473
14621474func (s * composeService ) createVolume (ctx context.Context , volume types.VolumeConfig ) error {
0 commit comments