github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/caasmodeloperator/modeloperator_test.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package caasmodeloperator_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 jc "github.com/juju/testing/checkers" 10 "github.com/juju/version/v2" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/agent" 14 modeloperatorapi "github.com/juju/juju/api/controller/caasmodeloperator" 15 "github.com/juju/juju/caas" 16 "github.com/juju/juju/core/resources" 17 "github.com/juju/juju/core/watcher" 18 "github.com/juju/juju/core/watcher/watchertest" 19 "github.com/juju/juju/worker/caasmodeloperator" 20 ) 21 22 type dummyAPI struct { 23 provInfo func() (modeloperatorapi.ModelOperatorProvisioningInfo, error) 24 setPassword func(password string) error 25 watchProvInfo func() (watcher.NotifyWatcher, error) 26 } 27 28 type dummyBroker struct { 29 ensureModelOperator func(string, string, *caas.ModelOperatorConfig) error 30 modelOperator func() (*caas.ModelOperatorConfig, error) 31 modelOperatorExists func() (bool, error) 32 } 33 34 type ModelOperatorManagerSuite struct{} 35 36 var _ = gc.Suite(&ModelOperatorManagerSuite{}) 37 38 func (b *dummyBroker) EnsureModelOperator(modelUUID, agentPath string, c *caas.ModelOperatorConfig) error { 39 if b.ensureModelOperator == nil { 40 return nil 41 } 42 return b.ensureModelOperator(modelUUID, agentPath, c) 43 } 44 45 func (b *dummyBroker) ModelOperator() (*caas.ModelOperatorConfig, error) { 46 if b.modelOperator == nil { 47 return nil, nil 48 } 49 return b.modelOperator() 50 } 51 52 func (b *dummyBroker) ModelOperatorExists() (bool, error) { 53 if b.modelOperatorExists == nil { 54 return false, nil 55 } 56 return b.modelOperatorExists() 57 } 58 59 func (a *dummyAPI) ModelOperatorProvisioningInfo() (modeloperatorapi.ModelOperatorProvisioningInfo, error) { 60 if a.provInfo == nil { 61 return modeloperatorapi.ModelOperatorProvisioningInfo{}, nil 62 } 63 return a.provInfo() 64 } 65 66 func (a *dummyAPI) WatchModelOperatorProvisioningInfo() (watcher.NotifyWatcher, error) { 67 if a.watchProvInfo == nil { 68 return watcher.NewMultiNotifyWatcher(), nil 69 } 70 return a.watchProvInfo() 71 } 72 73 func (a *dummyAPI) SetPassword(p string) error { 74 if a.setPassword == nil { 75 return nil 76 } 77 return a.setPassword(p) 78 } 79 80 func (m *ModelOperatorManagerSuite) TestModelOperatorManagerApplying(c *gc.C) { 81 const n = 3 82 var ( 83 iteration = 0 // ... n 84 85 apiAddresses = [n][]string{{"fe80:abcd::1"}, {"fe80:abcd::2"}, {"fe80:abcd::3"}} 86 imagePath = [n]string{"juju/jujud:1", "juju/jujud:2", "juju/jujud:3"} 87 modelUUID = "deadbeef-0bad-400d-8000-4b1d0d06f00d" 88 ver = [n]version.Number{version.MustParse("2.8.2"), version.MustParse("2.9.1"), version.MustParse("2.9.99")} 89 90 password = "" 91 lastConfig = (*caas.ModelOperatorConfig)(nil) 92 ) 93 94 changed := make(chan struct{}) 95 api := &dummyAPI{ 96 provInfo: func() (modeloperatorapi.ModelOperatorProvisioningInfo, error) { 97 return modeloperatorapi.ModelOperatorProvisioningInfo{ 98 APIAddresses: apiAddresses[iteration], 99 ImageDetails: resources.DockerImageDetails{RegistryPath: imagePath[iteration]}, 100 Version: ver[iteration], 101 }, nil 102 }, 103 watchProvInfo: func() (watcher.NotifyWatcher, error) { 104 return watchertest.NewMockNotifyWatcher(changed), nil 105 }, 106 } 107 108 broker := &dummyBroker{ 109 ensureModelOperator: func(_, _ string, conf *caas.ModelOperatorConfig) error { 110 defer func() { 111 iteration++ 112 }() 113 lastConfig = conf 114 115 c.Check(conf.ImageDetails.RegistryPath, gc.Equals, imagePath[iteration]) 116 117 ac, err := agent.ParseConfigData(conf.AgentConf) 118 c.Check(err, jc.ErrorIsNil) 119 if err != nil { 120 return err 121 } 122 addresses, _ := ac.APIAddresses() 123 c.Check(addresses, gc.DeepEquals, apiAddresses[iteration]) 124 c.Check(ac.UpgradedToVersion(), gc.Equals, ver[iteration]) 125 126 if password == "" { 127 password = ac.OldPassword() 128 } 129 c.Check(ac.OldPassword(), gc.Equals, password) 130 c.Check(ac.OldPassword(), gc.HasLen, 24) 131 132 return nil 133 }, 134 modelOperatorExists: func() (bool, error) { 135 return iteration > 0, nil 136 }, 137 modelOperator: func() (*caas.ModelOperatorConfig, error) { 138 if iteration == 0 { 139 return nil, errors.NotFoundf("model operator") 140 } 141 return lastConfig, nil 142 }, 143 } 144 145 worker, err := caasmodeloperator.NewModelOperatorManager(loggo.Logger{}, 146 api, broker, modelUUID, &mockAgentConfig{}) 147 c.Assert(err, jc.ErrorIsNil) 148 149 for i := 0; i < n; i++ { 150 changed <- struct{}{} 151 } 152 153 worker.Kill() 154 err = worker.Wait() 155 c.Assert(err, jc.ErrorIsNil) 156 157 c.Assert(iteration, gc.Equals, n) 158 }