github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/state/upgrades.go (about) 1 // Copyright 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package state 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/mgo/v3/bson" 9 "github.com/juju/mgo/v3/txn" 10 ) 11 12 // Until we add 3.0 upgrade steps, keep static analysis happy. 13 var _ = func() { 14 _ = applyToAllModelSettings(nil, nil) 15 } 16 17 // runForAllModelStates will run runner function for every model passing a state 18 // for that model. 19 // 20 //nolint:unused 21 func runForAllModelStates(pool *StatePool, runner func(st *State) error) error { 22 st, err := pool.SystemState() 23 if err != nil { 24 return errors.Trace(err) 25 } 26 models, closer := st.db().GetCollection(modelsC) 27 defer closer() 28 29 var modelDocs []bson.M 30 err = models.Find(nil).Select(bson.M{"_id": 1}).All(&modelDocs) 31 if err != nil { 32 return errors.Annotate(err, "failed to read models") 33 } 34 35 for _, modelDoc := range modelDocs { 36 modelUUID := modelDoc["_id"].(string) 37 model, err := pool.Get(modelUUID) 38 if err != nil { 39 return errors.Annotatef(err, "failed to open model %q", modelUUID) 40 } 41 defer func() { 42 model.Release() 43 }() 44 if err := runner(model.State); err != nil { 45 return errors.Annotatef(err, "model UUID %q", modelUUID) 46 } 47 } 48 return nil 49 } 50 51 // applyToAllModelSettings iterates the model settings documents and applies the 52 // passed in function to them. If the function returns 'true' it indicates the 53 // settings have been modified, and they should be written back to the 54 // database. 55 // Note that if there are any problems with updating settings, then none of the 56 // changes will be applied, as they are all updated in a single transaction. 57 func applyToAllModelSettings(st *State, change func(*settingsDoc) (bool, error)) error { 58 uuids, err := st.AllModelUUIDs() 59 if err != nil { 60 return errors.Trace(err) 61 } 62 63 coll, closer := st.db().GetRawCollection(settingsC) 64 defer closer() 65 66 var ids []string 67 for _, uuid := range uuids { 68 ids = append(ids, uuid+":e") 69 } 70 71 iter := coll.Find(bson.M{"_id": bson.M{"$in": ids}}).Iter() 72 defer iter.Close() 73 74 var ops []txn.Op 75 var doc settingsDoc 76 for iter.Next(&doc) { 77 settingsChanged, err := change(&doc) 78 if err != nil { 79 return errors.Trace(err) 80 } 81 if settingsChanged { 82 ops = append(ops, txn.Op{ 83 C: settingsC, 84 Id: doc.DocID, 85 Assert: txn.DocExists, 86 Update: bson.M{"$set": bson.M{"settings": doc.Settings}}, 87 }) 88 } 89 } 90 if err := iter.Close(); err != nil { 91 return errors.Trace(err) 92 } 93 if len(ops) > 0 { 94 return errors.Trace(st.runRawTransaction(ops)) 95 } 96 return nil 97 }