github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/common/modelstatus_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common_test 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/loggo" 9 jc "github.com/juju/testing/checkers" 10 gc "gopkg.in/check.v1" 11 12 "github.com/juju/juju/apiserver/common" 13 "github.com/juju/juju/apiserver/facade/facadetest" 14 "github.com/juju/juju/apiserver/facades/client/controller" 15 "github.com/juju/juju/apiserver/params" 16 apiservertesting "github.com/juju/juju/apiserver/testing" 17 "github.com/juju/juju/core/constraints" 18 "github.com/juju/juju/core/instance" 19 "github.com/juju/juju/environs" 20 "github.com/juju/juju/environs/config" 21 "github.com/juju/juju/environs/context" 22 "github.com/juju/juju/provider/dummy" 23 "github.com/juju/juju/state" 24 statetesting "github.com/juju/juju/state/testing" 25 "github.com/juju/juju/storage" 26 "github.com/juju/juju/storage/provider" 27 "github.com/juju/juju/testing" 28 "github.com/juju/juju/testing/factory" 29 ) 30 31 type modelStatusSuite struct { 32 statetesting.StateSuite 33 34 controller *controller.ControllerAPI 35 resources *common.Resources 36 authorizer apiservertesting.FakeAuthorizer 37 } 38 39 var _ = gc.Suite(&modelStatusSuite{}) 40 41 func (s *modelStatusSuite) SetUpTest(c *gc.C) { 42 // Initial config needs to be set before the StateSuite SetUpTest. 43 s.InitialConfig = testing.CustomModelConfig(c, testing.Attrs{ 44 "name": "controller", 45 }) 46 s.NewPolicy = func(*state.State) state.Policy { 47 return statePolicy{} 48 } 49 50 s.StateSuite.SetUpTest(c) 51 s.resources = common.NewResources() 52 s.AddCleanup(func(_ *gc.C) { s.resources.StopAll() }) 53 54 s.authorizer = apiservertesting.FakeAuthorizer{ 55 Tag: s.Owner, 56 AdminTag: s.Owner, 57 } 58 59 controller, err := controller.NewControllerAPIv7( 60 facadetest.Context{ 61 State_: s.State, 62 Resources_: s.resources, 63 Auth_: s.authorizer, 64 StatePool_: s.StatePool, 65 }) 66 c.Assert(err, jc.ErrorIsNil) 67 s.controller = controller 68 69 loggo.GetLogger("juju.apiserver.controller").SetLogLevel(loggo.TRACE) 70 } 71 72 func (s *modelStatusSuite) TestModelStatusNonAuth(c *gc.C) { 73 // Set up the user making the call. 74 user := s.Factory.MakeUser(c, &factory.UserParams{NoModelUser: true}) 75 anAuthoriser := apiservertesting.FakeAuthorizer{ 76 Tag: user.Tag(), 77 } 78 endpoint, err := controller.NewControllerAPIv6( 79 facadetest.Context{ 80 State_: s.State, 81 Resources_: s.resources, 82 Auth_: anAuthoriser, 83 }) 84 c.Assert(err, jc.ErrorIsNil) 85 controllerModelTag := s.Model.ModelTag().String() 86 87 req := params.Entities{ 88 Entities: []params.Entity{{Tag: controllerModelTag}}, 89 } 90 result, err := endpoint.ModelStatus(req) 91 c.Assert(err, jc.ErrorIsNil) 92 c.Assert(result.Results[0].Error, gc.ErrorMatches, "permission denied") 93 } 94 95 func (s *modelStatusSuite) TestModelStatusOwnerAllowed(c *gc.C) { 96 // Set up the user making the call. 97 owner := s.Factory.MakeUser(c, nil) 98 anAuthoriser := apiservertesting.FakeAuthorizer{ 99 Tag: owner.Tag(), 100 } 101 st := s.Factory.MakeModel(c, &factory.ModelParams{Owner: owner.Tag()}) 102 defer st.Close() 103 endpoint, err := controller.NewControllerAPIv6( 104 facadetest.Context{ 105 State_: s.State, 106 Resources_: s.resources, 107 Auth_: anAuthoriser, 108 StatePool_: s.StatePool, 109 }) 110 c.Assert(err, jc.ErrorIsNil) 111 112 model, err := st.Model() 113 c.Assert(err, jc.ErrorIsNil) 114 req := params.Entities{ 115 Entities: []params.Entity{{Tag: model.ModelTag().String()}}, 116 } 117 _, err = endpoint.ModelStatus(req) 118 c.Assert(err, jc.ErrorIsNil) 119 } 120 121 func (s *modelStatusSuite) TestModelStatus(c *gc.C) { 122 otherModelOwner := s.Factory.MakeModelUser(c, nil) 123 otherSt := s.Factory.MakeModel(c, &factory.ModelParams{ 124 Name: "dummytoo", 125 Owner: otherModelOwner.UserTag, 126 ConfigAttrs: testing.Attrs{ 127 "controller": false, 128 }, 129 }) 130 defer otherSt.Close() 131 132 eight := uint64(8) 133 s.Factory.MakeMachine(c, &factory.MachineParams{ 134 Jobs: []state.MachineJob{state.JobManageModel}, 135 Characteristics: &instance.HardwareCharacteristics{CpuCores: &eight}, 136 InstanceId: "id-4", 137 DisplayName: "snowflake", 138 Volumes: []state.HostVolumeParams{{ 139 Volume: state.VolumeParams{ 140 Pool: "modelscoped", 141 Size: 123, 142 }, 143 }}, 144 }) 145 s.Factory.MakeMachine(c, &factory.MachineParams{ 146 Jobs: []state.MachineJob{state.JobHostUnits}, 147 InstanceId: "id-5", 148 Filesystems: []state.HostFilesystemParams{{ 149 Filesystem: state.FilesystemParams{ 150 Pool: "modelscoped", 151 Size: 123, 152 }, 153 }, { 154 Filesystem: state.FilesystemParams{ 155 Pool: "machinescoped", 156 Size: 123, 157 }, 158 }}, 159 }) 160 s.Factory.MakeApplication(c, &factory.ApplicationParams{ 161 Charm: s.Factory.MakeCharm(c, nil), 162 }) 163 164 otherFactory := factory.NewFactory(otherSt, s.StatePool) 165 otherFactory.MakeMachine(c, &factory.MachineParams{InstanceId: "id-8"}) 166 otherFactory.MakeMachine(c, &factory.MachineParams{InstanceId: "id-9"}) 167 otherFactory.MakeApplication(c, &factory.ApplicationParams{ 168 Charm: otherFactory.MakeCharm(c, nil), 169 }) 170 171 otherModel, err := otherSt.Model() 172 c.Assert(err, jc.ErrorIsNil) 173 174 controllerModelTag := s.Model.ModelTag().String() 175 hostedModelTag := otherModel.ModelTag().String() 176 177 req := params.Entities{ 178 Entities: []params.Entity{{Tag: controllerModelTag}, {Tag: hostedModelTag}}, 179 } 180 results, err := s.controller.ModelStatus(req) 181 c.Assert(err, jc.ErrorIsNil) 182 183 arch := "amd64" 184 mem := uint64(64 * 1024 * 1024 * 1024) 185 stdHw := ¶ms.MachineHardware{ 186 Arch: &arch, 187 Mem: &mem, 188 } 189 c.Assert(results.Results, jc.DeepEquals, []params.ModelStatus{ 190 { 191 ModelTag: controllerModelTag, 192 HostedMachineCount: 1, 193 ApplicationCount: 1, 194 OwnerTag: s.Owner.String(), 195 Life: params.Alive, 196 Machines: []params.ModelMachineInfo{ 197 {Id: "0", Hardware: ¶ms.MachineHardware{Cores: &eight}, InstanceId: "id-4", DisplayName: "snowflake", Status: "pending", WantsVote: true}, 198 {Id: "1", Hardware: stdHw, InstanceId: "id-5", Status: "pending"}, 199 }, 200 Volumes: []params.ModelVolumeInfo{{ 201 Id: "0", Status: "pending", Detachable: true, 202 }}, 203 Filesystems: []params.ModelFilesystemInfo{{ 204 Id: "0", Status: "pending", Detachable: true, 205 }, { 206 Id: "1/1", Status: "pending", Detachable: false, 207 }}, 208 }, 209 { 210 ModelTag: hostedModelTag, 211 HostedMachineCount: 2, 212 ApplicationCount: 1, 213 OwnerTag: otherModelOwner.UserTag.String(), 214 Life: params.Alive, 215 Machines: []params.ModelMachineInfo{ 216 {Id: "0", Hardware: stdHw, InstanceId: "id-8", Status: "pending"}, 217 {Id: "1", Hardware: stdHw, InstanceId: "id-9", Status: "pending"}, 218 }, 219 }, 220 }) 221 } 222 223 func (s *modelStatusSuite) TestModelStatusCAAS(c *gc.C) { 224 otherModelOwner := s.Factory.MakeModelUser(c, nil) 225 otherSt := s.Factory.MakeCAASModel(c, &factory.ModelParams{ 226 Owner: otherModelOwner.UserTag, 227 ConfigAttrs: testing.Attrs{ 228 "controller": false, 229 }, 230 }) 231 defer otherSt.Close() 232 233 otherFactory := factory.NewFactory(otherSt, s.StatePool) 234 otherFactory.MakeApplication(c, &factory.ApplicationParams{ 235 Charm: otherFactory.MakeCharm(c, &factory.CharmParams{Name: "gitlab", Series: "kubernetes"}), 236 }) 237 238 otherModel, err := otherSt.Model() 239 c.Assert(err, jc.ErrorIsNil) 240 241 controllerModelTag := s.Model.ModelTag().String() 242 hostedModelTag := otherModel.ModelTag().String() 243 244 req := params.Entities{ 245 Entities: []params.Entity{{Tag: controllerModelTag}, {Tag: hostedModelTag}}, 246 } 247 results, err := s.controller.ModelStatus(req) 248 c.Assert(err, jc.ErrorIsNil) 249 250 c.Assert(results.Results, jc.DeepEquals, []params.ModelStatus{ 251 { 252 ModelTag: controllerModelTag, 253 HostedMachineCount: 0, 254 ApplicationCount: 0, 255 OwnerTag: s.Owner.String(), 256 Life: params.Alive, 257 }, 258 { 259 ModelTag: hostedModelTag, 260 HostedMachineCount: 0, 261 ApplicationCount: 1, 262 OwnerTag: otherModelOwner.UserTag.String(), 263 Life: params.Alive, 264 }, 265 }) 266 } 267 268 func (s *modelStatusSuite) TestModelStatusRunsForAllModels(c *gc.C) { 269 req := params.Entities{ 270 Entities: []params.Entity{ 271 {Tag: "fail.me"}, 272 {Tag: s.Model.ModelTag().String()}, 273 }, 274 } 275 expected := params.ModelStatusResults{ 276 Results: []params.ModelStatus{ 277 { 278 Error: common.ServerError(errors.New(`"fail.me" is not a valid tag`))}, 279 { 280 ModelTag: s.Model.ModelTag().String(), 281 Life: params.Life(s.Model.Life().String()), 282 OwnerTag: s.Model.Owner().String(), 283 }, 284 }, 285 } 286 result, err := s.controller.ModelStatus(req) 287 c.Assert(err, jc.ErrorIsNil) 288 c.Assert(result, jc.DeepEquals, expected) 289 } 290 291 type statePolicy struct{} 292 293 func (statePolicy) Prechecker() (environs.InstancePrechecker, error) { 294 return nil, errors.NotImplementedf("Prechecker") 295 } 296 297 func (statePolicy) ConfigValidator() (config.Validator, error) { 298 return nil, errors.NotImplementedf("ConfigValidator") 299 } 300 301 func (statePolicy) ConstraintsValidator(context.ProviderCallContext) (constraints.Validator, error) { 302 return nil, errors.NotImplementedf("ConstraintsValidator") 303 } 304 305 func (statePolicy) InstanceDistributor() (context.Distributor, error) { 306 return nil, errors.NotImplementedf("InstanceDistributor") 307 } 308 309 func (statePolicy) StorageProviderRegistry() (storage.ProviderRegistry, error) { 310 return storage.ChainedProviderRegistry{ 311 dummy.StorageProviders(), 312 provider.CommonStorageProviders(), 313 }, nil 314 } 315 316 func (statePolicy) ProviderConfigSchemaSource() (config.ConfigSchemaSource, error) { 317 return nil, errors.NotImplementedf("ConfigSchemaSource") 318 }