github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/facades/controller/caasfirewaller/firewaller_test.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package caasfirewaller_test 5 6 import ( 7 "github.com/juju/charm/v12" 8 "github.com/juju/names/v5" 9 jc "github.com/juju/testing/checkers" 10 "github.com/juju/worker/v3/workertest" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/apiserver/common" 14 charmscommon "github.com/juju/juju/apiserver/common/charms" 15 "github.com/juju/juju/apiserver/facade" 16 "github.com/juju/juju/apiserver/facades/controller/caasfirewaller" 17 apiservertesting "github.com/juju/juju/apiserver/testing" 18 "github.com/juju/juju/core/life" 19 "github.com/juju/juju/core/network" 20 "github.com/juju/juju/rpc/params" 21 "github.com/juju/juju/state" 22 statetesting "github.com/juju/juju/state/testing" 23 coretesting "github.com/juju/juju/testing" 24 ) 25 26 type firewallerBaseSuite struct { 27 coretesting.BaseSuite 28 29 st *mockState 30 applicationsChanges chan []string 31 openPortsChanges chan []string 32 appExposedChanges chan struct{} 33 34 resources *common.Resources 35 authorizer *apiservertesting.FakeAuthorizer 36 facade facadeCommon 37 38 newFunc func(c *gc.C, resources facade.Resources, 39 authorizer facade.Authorizer, 40 st *mockState, 41 ) (facadeCommon, error) 42 } 43 44 type firewallerLegacySuite struct { 45 firewallerBaseSuite 46 } 47 48 var _ = gc.Suite(&firewallerLegacySuite{ 49 firewallerBaseSuite: firewallerBaseSuite{ 50 newFunc: func(c *gc.C, resources facade.Resources, 51 authorizer facade.Authorizer, 52 st *mockState, 53 ) (facadeCommon, error) { 54 commonState := &mockCommonStateShim{st} 55 commonCharmsAPI, err := charmscommon.NewCharmInfoAPI(commonState, authorizer) 56 c.Assert(err, jc.ErrorIsNil) 57 appCharmInfoAPI, err := charmscommon.NewApplicationCharmInfoAPI(commonState, authorizer) 58 c.Assert(err, jc.ErrorIsNil) 59 return caasfirewaller.NewFacadeLegacyForTest( 60 resources, 61 authorizer, 62 st, 63 commonCharmsAPI, 64 appCharmInfoAPI, 65 ) 66 }, 67 }, 68 }) 69 70 type firewallerSidecarSuite struct { 71 firewallerBaseSuite 72 73 facade facadeSidecar 74 } 75 76 var _ = gc.Suite(&firewallerSidecarSuite{ 77 firewallerBaseSuite: firewallerBaseSuite{ 78 newFunc: func(c *gc.C, resources facade.Resources, 79 authorizer facade.Authorizer, 80 st *mockState, 81 ) (facadeCommon, error) { 82 commonState := &mockCommonStateShim{st} 83 commonCharmsAPI, err := charmscommon.NewCharmInfoAPI(commonState, authorizer) 84 c.Assert(err, jc.ErrorIsNil) 85 appCharmInfoAPI, err := charmscommon.NewApplicationCharmInfoAPI(commonState, authorizer) 86 c.Assert(err, jc.ErrorIsNil) 87 return caasfirewaller.NewFacadeSidecarForTest( 88 resources, 89 authorizer, 90 st, 91 commonCharmsAPI, 92 appCharmInfoAPI, 93 ) 94 }, 95 }, 96 }) 97 98 func (s *firewallerSidecarSuite) SetUpTest(c *gc.C) { 99 s.firewallerBaseSuite.SetUpTest(c) 100 101 // charm.FormatV2. 102 s.st.application.charm.manifest.Bases = []charm.Base{ 103 { 104 Name: "ubuntu", 105 Channel: charm.Channel{ 106 Risk: "stable", 107 Track: "20.04", 108 }, 109 }, 110 } 111 112 var ok bool 113 s.facade, ok = s.firewallerBaseSuite.facade.(facadeSidecar) 114 c.Assert(ok, jc.IsTrue) 115 } 116 117 func (s *firewallerSidecarSuite) TestWatchOpenedPorts(c *gc.C) { 118 openPortsChanges := []string{"port1", "port2"} 119 s.openPortsChanges <- openPortsChanges 120 121 results, err := s.facade.WatchOpenedPorts(params.Entities{ 122 Entities: []params.Entity{{ 123 Tag: "model-deadbeef-0bad-400d-8000-4b1d0d06f00d", 124 }}, 125 }) 126 c.Assert(err, jc.ErrorIsNil) 127 result := results.Results[0] 128 c.Assert(result.Error, gc.IsNil) 129 c.Assert(result.StringsWatcherId, gc.Equals, "1") 130 c.Assert(result.Changes, jc.DeepEquals, openPortsChanges) 131 } 132 133 func (s *firewallerSidecarSuite) TestGetApplicationOpenedPorts(c *gc.C) { 134 s.st.application.appPortRanges = network.GroupedPortRanges{ 135 "": []network.PortRange{ 136 { 137 FromPort: 80, 138 ToPort: 80, 139 Protocol: "tcp", 140 }, 141 }, 142 "endport-1": []network.PortRange{ 143 { 144 FromPort: 8888, 145 ToPort: 8888, 146 Protocol: "tcp", 147 }, 148 }, 149 } 150 151 results, err := s.facade.GetOpenedPorts(params.Entity{ 152 Tag: "application-gitlab", 153 }) 154 c.Assert(err, jc.ErrorIsNil) 155 result := results.Results[0] 156 c.Assert(result.Error, gc.IsNil) 157 c.Assert(result.ApplicationPortRanges, gc.DeepEquals, []params.ApplicationOpenedPorts{ 158 { 159 PortRanges: []params.PortRange{ 160 {FromPort: 80, ToPort: 80, Protocol: "tcp"}, 161 }, 162 }, 163 { 164 Endpoint: "endport-1", 165 PortRanges: []params.PortRange{ 166 {FromPort: 8888, ToPort: 8888, Protocol: "tcp"}, 167 }, 168 }, 169 }) 170 } 171 172 type facadeCommon interface { 173 IsExposed(args params.Entities) (params.BoolResults, error) 174 ApplicationsConfig(args params.Entities) (params.ApplicationGetConfigResults, error) 175 WatchApplications() (params.StringsWatchResult, error) 176 Life(args params.Entities) (params.LifeResults, error) 177 Watch(args params.Entities) (params.NotifyWatchResults, error) 178 ApplicationCharmInfo(args params.Entity) (params.Charm, error) 179 } 180 181 type facadeSidecar interface { 182 facadeCommon 183 WatchOpenedPorts(args params.Entities) (params.StringsWatchResults, error) 184 GetOpenedPorts(arg params.Entity) (params.ApplicationOpenedPortsResults, error) 185 } 186 187 func (s *firewallerBaseSuite) SetUpTest(c *gc.C) { 188 s.BaseSuite.SetUpTest(c) 189 190 s.applicationsChanges = make(chan []string, 1) 191 s.appExposedChanges = make(chan struct{}, 1) 192 s.openPortsChanges = make(chan []string, 1) 193 appExposedWatcher := statetesting.NewMockNotifyWatcher(s.appExposedChanges) 194 s.st = &mockState{ 195 application: mockApplication{ 196 life: state.Alive, 197 watcher: appExposedWatcher, 198 charm: mockCharm{ 199 meta: &charm.Meta{ 200 Deployment: &charm.Deployment{}, 201 }, 202 manifest: &charm.Manifest{}, 203 url: "ch:gitlab", 204 }, 205 }, 206 applicationsWatcher: statetesting.NewMockStringsWatcher(s.applicationsChanges), 207 openPortsWatcher: statetesting.NewMockStringsWatcher(s.openPortsChanges), 208 appExposedWatcher: appExposedWatcher, 209 } 210 s.AddCleanup(func(c *gc.C) { workertest.DirtyKill(c, s.st.applicationsWatcher) }) 211 s.AddCleanup(func(c *gc.C) { workertest.DirtyKill(c, s.st.openPortsWatcher) }) 212 s.AddCleanup(func(c *gc.C) { workertest.DirtyKill(c, s.st.appExposedWatcher) }) 213 214 s.resources = common.NewResources() 215 s.authorizer = &apiservertesting.FakeAuthorizer{ 216 Tag: names.NewMachineTag("0"), 217 Controller: true, 218 } 219 220 facade, err := s.newFunc(c, s.resources, s.authorizer, s.st) 221 c.Assert(err, jc.ErrorIsNil) 222 s.facade = facade 223 } 224 225 func (s *firewallerBaseSuite) TestPermission(c *gc.C) { 226 s.authorizer = &apiservertesting.FakeAuthorizer{ 227 Tag: names.NewMachineTag("0"), 228 } 229 _, err := s.newFunc(c, s.resources, s.authorizer, s.st) 230 c.Assert(err, gc.ErrorMatches, "permission denied") 231 } 232 233 func (s *firewallerBaseSuite) TestWatchApplications(c *gc.C) { 234 applicationNames := []string{"db2", "hadoop"} 235 s.applicationsChanges <- applicationNames 236 result, err := s.facade.WatchApplications() 237 c.Assert(err, jc.ErrorIsNil) 238 c.Assert(result.Error, gc.IsNil) 239 c.Assert(result.StringsWatcherId, gc.Equals, "1") 240 c.Assert(result.Changes, jc.DeepEquals, applicationNames) 241 } 242 243 func (s *firewallerBaseSuite) TestWatchApplication(c *gc.C) { 244 s.appExposedChanges <- struct{}{} 245 246 results, err := s.facade.Watch(params.Entities{ 247 Entities: []params.Entity{ 248 {Tag: "application-gitlab"}, 249 {Tag: "unit-gitlab-0"}, 250 }, 251 }) 252 c.Assert(err, jc.ErrorIsNil) 253 c.Assert(results.Results, gc.HasLen, 2) 254 c.Assert(results.Results[0].Error, gc.IsNil) 255 c.Assert(results.Results[1].Error, jc.DeepEquals, ¶ms.Error{ 256 Message: "permission denied", 257 Code: "unauthorized access", 258 }) 259 260 c.Assert(results.Results[0].NotifyWatcherId, gc.Equals, "1") 261 resource := s.resources.Get("1") 262 c.Assert(resource, gc.Equals, s.st.appExposedWatcher) 263 } 264 265 func (s *firewallerBaseSuite) TestIsExposed(c *gc.C) { 266 s.st.application.exposed = true 267 results, err := s.facade.IsExposed(params.Entities{ 268 Entities: []params.Entity{ 269 {Tag: "application-gitlab"}, 270 {Tag: "unit-gitlab-0"}, 271 }, 272 }) 273 c.Assert(err, jc.ErrorIsNil) 274 c.Assert(results, jc.DeepEquals, params.BoolResults{ 275 Results: []params.BoolResult{{ 276 Result: true, 277 }, { 278 Error: ¶ms.Error{ 279 Message: `"unit-gitlab-0" is not a valid application tag`, 280 }, 281 }}, 282 }) 283 } 284 285 func (s *firewallerBaseSuite) TestLife(c *gc.C) { 286 results, err := s.facade.Life(params.Entities{ 287 Entities: []params.Entity{ 288 {Tag: "application-gitlab"}, 289 {Tag: "machine-0"}, 290 }, 291 }) 292 c.Assert(err, jc.ErrorIsNil) 293 c.Assert(results, jc.DeepEquals, params.LifeResults{ 294 Results: []params.LifeResult{{ 295 Life: life.Alive, 296 }, { 297 Error: ¶ms.Error{ 298 Code: "unauthorized access", 299 Message: "permission denied", 300 }, 301 }}, 302 }) 303 } 304 305 func (s *firewallerBaseSuite) TestApplicationConfig(c *gc.C) { 306 results, err := s.facade.ApplicationsConfig(params.Entities{ 307 Entities: []params.Entity{ 308 {Tag: "application-gitlab"}, 309 {Tag: "unit-gitlab-0"}, 310 }, 311 }) 312 c.Assert(err, jc.ErrorIsNil) 313 c.Assert(results.Results, gc.HasLen, 2) 314 c.Assert(results.Results[0].Error, gc.IsNil) 315 c.Assert(results.Results[1].Error, jc.DeepEquals, ¶ms.Error{ 316 Message: `"unit-gitlab-0" is not a valid application tag`, 317 }) 318 c.Assert(results.Results[0].Config, jc.DeepEquals, map[string]interface{}{"foo": "bar"}) 319 }