github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/facades/controller/charmrevisionupdater/interface_test.go (about) 1 // Copyright 2020 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package charmrevisionupdater_test 5 6 import ( 7 "github.com/juju/charm/v12" 8 "github.com/juju/charm/v12/resource" 9 "github.com/juju/names/v5" 10 jc "github.com/juju/testing/checkers" 11 "go.uber.org/mock/gomock" 12 gc "gopkg.in/check.v1" 13 14 "github.com/juju/juju/apiserver/facade" 15 "github.com/juju/juju/apiserver/facades/controller/charmrevisionupdater" 16 "github.com/juju/juju/apiserver/facades/controller/charmrevisionupdater/mocks" 17 "github.com/juju/juju/charmhub" 18 charmmetrics "github.com/juju/juju/core/charm/metrics" 19 "github.com/juju/juju/state" 20 ) 21 22 func makeApplication(ctrl *gomock.Controller, schema, charmName, charmID, appID string, revision int) charmrevisionupdater.Application { 23 app := mocks.NewMockApplication(ctrl) 24 25 var source string 26 switch schema { 27 case "ch": 28 source = "charm-hub" 29 app.EXPECT().UnitCount().Return(2).AnyTimes() 30 } 31 32 curl := &charm.URL{ 33 Schema: schema, 34 Name: charmName, 35 Revision: revision, 36 } 37 str := curl.String() 38 app.EXPECT().CharmURL().Return(&str, false).AnyTimes() 39 app.EXPECT().CharmOrigin().Return(&state.CharmOrigin{ 40 Source: source, 41 Type: "charm", 42 ID: charmID, 43 Revision: &revision, 44 Channel: &state.Channel{ 45 Track: "latest", 46 Risk: "stable", 47 }, 48 Platform: &state.Platform{ 49 Architecture: "amd64", 50 OS: "ubuntu", 51 Channel: "20.04/stable", 52 }, 53 }).AnyTimes() 54 app.EXPECT().ApplicationTag().Return(names.ApplicationTag{Name: appID}).AnyTimes() 55 56 return app 57 } 58 59 func makeResource(c *gc.C, name string, revision, size int, hexFingerprint string) resource.Resource { 60 fingerprint, err := resource.ParseFingerprint(hexFingerprint) 61 c.Assert(err, jc.ErrorIsNil) 62 return resource.Resource{ 63 Meta: resource.Meta{ 64 Name: name, 65 Type: resource.TypeFile, 66 }, 67 Origin: resource.OriginStore, 68 Revision: revision, 69 Fingerprint: fingerprint, 70 Size: int64(size), 71 } 72 } 73 74 // charmhubConfigMatcher matches only the charm IDs and revisions of a 75 // charmhub.RefreshMany config. 76 type charmhubConfigMatcher struct { 77 expected []charmhubConfigExpected 78 } 79 80 type charmhubConfigExpected struct { 81 id string 82 revision int 83 relMetric string 84 } 85 86 func (m charmhubConfigMatcher) Matches(x interface{}) bool { 87 config, ok := x.(charmhub.RefreshConfig) 88 if !ok { 89 return false 90 } 91 request, err := config.Build() 92 if err != nil { 93 return false 94 } 95 if len(request.Context) != len(m.expected) || len(request.Actions) != len(m.expected) { 96 return false 97 } 98 for i, context := range request.Context { 99 if context.ID != m.expected[i].id { 100 return false 101 } 102 if context.Revision != m.expected[i].revision { 103 return false 104 } 105 r, ok := context.Metrics[string(charmmetrics.Relations)] 106 if m.expected[i].relMetric != "" && !ok { 107 return false 108 } 109 if m.expected[i].relMetric != "" && ok && r != m.expected[i].relMetric { 110 return false 111 } 112 action := request.Actions[i] 113 if *action.ID != m.expected[i].id { 114 return false 115 } 116 _, ok = context.Metrics[string(charmmetrics.NumUnits)] 117 if m.expected[i].relMetric != "" && !ok { 118 return false 119 } 120 } 121 return true 122 } 123 124 func (charmhubConfigMatcher) String() string { 125 return "matches config" 126 } 127 128 // charmhubMetricsMatcher matches the controller and model parts of the metrics, then 129 // a value within each part. 130 type charmhubMetricsMatcher struct { 131 c *gc.C 132 exist bool 133 } 134 135 func (m charmhubMetricsMatcher) Matches(x interface{}) bool { 136 switch y := x.(type) { 137 case map[charmmetrics.MetricKey]map[charmmetrics.MetricKey]string: 138 if len(y) != 2 { 139 if !m.exist { 140 return true 141 } 142 return false 143 } 144 for k := range y { 145 if k != charmmetrics.Controller && k != charmmetrics.Model { 146 return false 147 } 148 } 149 controller := y[charmmetrics.Controller] 150 uuid, ok := controller[charmmetrics.UUID] 151 if !ok { 152 return false 153 } 154 m.c.Assert(uuid, gc.Equals, "controller-1") 155 156 model := y[charmmetrics.Model] 157 cloud, ok := model[charmmetrics.Cloud] 158 if !ok { 159 return false 160 } 161 m.c.Assert(cloud, gc.Equals, "cloud") 162 default: 163 return false 164 } 165 return true 166 } 167 168 func (charmhubMetricsMatcher) String() string { 169 return "matches metrics" 170 } 171 172 type facadeContextShim struct { 173 facade.Context // Make it fulfil the interface, but we only define a couple of methods 174 state *state.State 175 authorizer facade.Authorizer 176 } 177 178 func (s facadeContextShim) Auth() facade.Authorizer { 179 return s.authorizer 180 } 181 182 func (s facadeContextShim) State() *state.State { 183 return s.state 184 }