github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/scripts/juju-force-upgrade/main.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package main 5 6 import ( 7 "fmt" 8 "os" 9 "path/filepath" 10 11 "github.com/juju/clock" 12 "github.com/juju/errors" 13 "github.com/juju/gnuflag" 14 "github.com/juju/loggo" 15 "github.com/juju/version" 16 "gopkg.in/juju/names.v2" 17 18 "github.com/juju/juju/agent" 19 "github.com/juju/juju/mongo" 20 "github.com/juju/juju/state" 21 jversion "github.com/juju/juju/version" 22 ) 23 24 var logger = loggo.GetLogger("juju.forceupgrade") 25 26 func checkErr(label string, err error) { 27 if err != nil { 28 logger.Errorf("%s: %s", label, err) 29 os.Exit(1) 30 } 31 } 32 33 const dataDir = "/var/lib/juju" 34 35 func getState() (*state.StatePool, error) { 36 tag, err := getCurrentMachineTag(dataDir) 37 if err != nil { 38 return nil, errors.Annotate(err, "finding machine tag") 39 } 40 41 logger.Infof("current machine tag: %s", tag) 42 43 config, err := getConfig(tag) 44 if err != nil { 45 return nil, errors.Annotate(err, "loading agent config") 46 } 47 48 mongoInfo, available := config.MongoInfo() 49 if !available { 50 return nil, errors.New("mongo info not available from agent config") 51 } 52 session, err := mongo.DialWithInfo(*mongoInfo, mongo.DefaultDialOpts()) 53 if err != nil { 54 return nil, errors.Trace(err) 55 } 56 defer session.Close() 57 58 pool, err := state.OpenStatePool(state.OpenParams{ 59 Clock: clock.WallClock, 60 ControllerTag: config.Controller(), 61 ControllerModelTag: config.Model(), 62 MongoSession: session, 63 }) 64 if err != nil { 65 return nil, errors.Annotate(err, "opening state connection") 66 } 67 return pool, nil 68 } 69 70 func getCurrentMachineTag(datadir string) (names.MachineTag, error) { 71 var empty names.MachineTag 72 values, err := filepath.Glob(filepath.Join(datadir, "agents", "machine-*")) 73 if err != nil { 74 return empty, errors.Annotate(err, "problem globbing") 75 } 76 switch len(values) { 77 case 0: 78 return empty, errors.Errorf("no machines found") 79 case 1: 80 return names.ParseMachineTag(filepath.Base(values[0])) 81 default: 82 return empty, errors.Errorf("too many options: %v", values) 83 } 84 } 85 86 func getConfig(tag names.MachineTag) (agent.ConfigSetterWriter, error) { 87 path := agent.ConfigPath("/var/lib/juju", tag) 88 return agent.ReadConfig(path) 89 } 90 91 func main() { 92 loggo.GetLogger("").SetLogLevel(loggo.TRACE) 93 gnuflag.Usage = func() { 94 fmt.Printf("Usage: %s <model-uuid> <version>\n", os.Args[0]) 95 os.Exit(1) 96 } 97 98 gnuflag.Parse(true) 99 100 args := gnuflag.Args() 101 if len(args) < 2 { 102 gnuflag.Usage() 103 } 104 105 modelUUID := args[0] 106 agentVersion := version.MustParse(args[1]) 107 if agentVersion.Compare(jversion.Current) < 0 { 108 // Force the client to think it is at least as new as the desired version 109 jversion.Current = agentVersion 110 } 111 112 statePool, err := getState() 113 checkErr("getting state connection", err) 114 defer statePool.Close() 115 116 modelSt, err := statePool.Get(modelUUID) 117 checkErr("open model", err) 118 defer func() { 119 modelSt.Release() 120 statePool.Remove(modelUUID) 121 }() 122 123 checkErr("set model agent version", modelSt.SetModelAgentVersion(agentVersion, true)) 124 }