@@ -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 ,
@@ -1426,21 +1429,21 @@ func (s *composeService) resolveExternalNetwork(ctx context.Context, n *types.Ne
14261429 }
14271430}
14281431
1429- func (s * composeService ) ensureVolume (ctx context.Context , volume types.VolumeConfig , project string ) error {
1432+ func (s * composeService ) ensureVolume (ctx context.Context , volume types.VolumeConfig , project string ) ( string , error ) {
14301433 inspected , err := s .apiClient ().VolumeInspect (ctx , volume .Name )
14311434 if err != nil {
14321435 if ! errdefs .IsNotFound (err ) {
1433- return err
1436+ return "" , err
14341437 }
14351438 if volume .External {
1436- return fmt .Errorf ("external volume %q not found" , volume .Name )
1439+ return "" , fmt .Errorf ("external volume %q not found" , volume .Name )
14371440 }
1438- err : = s .createVolume (ctx , volume )
1439- return err
1441+ err = s .createVolume (ctx , volume )
1442+ return "" , err
14401443 }
14411444
14421445 if volume .External {
1443- return nil
1446+ return volume . Name , nil
14441447 }
14451448
14461449 // Volume exists with name, but let's double-check this is the expected one
@@ -1451,7 +1454,16 @@ func (s *composeService) ensureVolume(ctx context.Context, volume types.VolumeCo
14511454 if ok && p != project {
14521455 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 )
14531456 }
1454- return nil
1457+
1458+ expected , err := VolumeHash (volume )
1459+ if err != nil {
1460+ return "" , err
1461+ }
1462+ actual , ok := inspected .Labels [api .ConfigHashLabel ]
1463+ if ok && actual != expected {
1464+ logrus .Warnf ("volume %q exists but doesn't match configuration in compose file. You should remove it so it get recreated" , volume .Name )
1465+ }
1466+ return inspected .Name , nil
14551467}
14561468
14571469func (s * composeService ) createVolume (ctx context.Context , volume types.VolumeConfig ) error {
0 commit comments