github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/apiserver/agent/agent_v0.go (about) 1 // Copyright 2013, 2014 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package agent 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names" 9 10 "github.com/juju/juju/apiserver/common" 11 "github.com/juju/juju/apiserver/params" 12 "github.com/juju/juju/mongo" 13 "github.com/juju/juju/state" 14 "github.com/juju/juju/state/multiwatcher" 15 ) 16 17 // AgentAPIV0 implements the version 0 of the API provided to an agent. 18 type AgentAPIV0 struct { 19 *common.PasswordChanger 20 *common.RebootFlagClearer 21 22 st *state.State 23 auth common.Authorizer 24 } 25 26 // NewAgentAPIV0 returns an object implementing version 0 of the Agent API 27 // with the given authorizer representing the currently logged in client. 28 func NewAgentAPIV0(st *state.State, resources *common.Resources, auth common.Authorizer) (*AgentAPIV0, error) { 29 // Agents are defined to be any user that's not a client user. 30 if !auth.AuthMachineAgent() && !auth.AuthUnitAgent() { 31 return nil, common.ErrPerm 32 } 33 getCanChange := func() (common.AuthFunc, error) { 34 return auth.AuthOwner, nil 35 } 36 return &AgentAPIV0{ 37 PasswordChanger: common.NewPasswordChanger(st, getCanChange), 38 RebootFlagClearer: common.NewRebootFlagClearer(st, getCanChange), 39 st: st, 40 auth: auth, 41 }, nil 42 } 43 44 func (api *AgentAPIV0) GetEntities(args params.Entities) params.AgentGetEntitiesResults { 45 results := params.AgentGetEntitiesResults{ 46 Entities: make([]params.AgentGetEntitiesResult, len(args.Entities)), 47 } 48 for i, entity := range args.Entities { 49 tag, err := names.ParseTag(entity.Tag) 50 if err != nil { 51 results.Entities[i].Error = common.ServerError(err) 52 continue 53 } 54 result, err := api.getEntity(tag) 55 result.Error = common.ServerError(err) 56 results.Entities[i] = result 57 } 58 return results 59 } 60 61 func (api *AgentAPIV0) getEntity(tag names.Tag) (result params.AgentGetEntitiesResult, err error) { 62 // Allow only for the owner agent. 63 // Note: having a bulk API call for this is utter madness, given that 64 // this check means we can only ever return a single object. 65 if !api.auth.AuthOwner(tag) { 66 err = common.ErrPerm 67 return 68 } 69 entity0, err := api.st.FindEntity(tag) 70 if err != nil { 71 return 72 } 73 entity, ok := entity0.(state.Lifer) 74 if !ok { 75 err = common.NotSupportedError(tag, "life cycles") 76 return 77 } 78 result.Life = params.Life(entity.Life().String()) 79 if machine, ok := entity.(*state.Machine); ok { 80 result.Jobs = stateJobsToAPIParamsJobs(machine.Jobs()) 81 result.ContainerType = machine.ContainerType() 82 } 83 return 84 } 85 86 func (api *AgentAPIV0) StateServingInfo() (result state.StateServingInfo, err error) { 87 if !api.auth.AuthEnvironManager() { 88 err = common.ErrPerm 89 return 90 } 91 return api.st.StateServingInfo() 92 } 93 94 // MongoIsMaster is called by the IsMaster API call 95 // instead of mongo.IsMaster. It exists so it can 96 // be overridden by tests. 97 var MongoIsMaster = mongo.IsMaster 98 99 func (api *AgentAPIV0) IsMaster() (params.IsMasterResult, error) { 100 if !api.auth.AuthEnvironManager() { 101 return params.IsMasterResult{}, common.ErrPerm 102 } 103 104 switch tag := api.auth.GetAuthTag().(type) { 105 case names.MachineTag: 106 machine, err := api.st.Machine(tag.Id()) 107 if err != nil { 108 return params.IsMasterResult{}, common.ErrPerm 109 } 110 111 session := api.st.MongoSession() 112 isMaster, err := MongoIsMaster(session, machine) 113 return params.IsMasterResult{Master: isMaster}, err 114 default: 115 return params.IsMasterResult{}, errors.Errorf("authenticated entity is not a Machine") 116 } 117 } 118 119 func stateJobsToAPIParamsJobs(jobs []state.MachineJob) []multiwatcher.MachineJob { 120 pjobs := make([]multiwatcher.MachineJob, len(jobs)) 121 for i, job := range jobs { 122 pjobs[i] = multiwatcher.MachineJob(job.String()) 123 } 124 return pjobs 125 }