github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/apiserver/common/controllerconfig.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package common 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/names/v5" 9 10 apiservererrors "github.com/juju/juju/apiserver/errors" 11 "github.com/juju/juju/core/crossmodel" 12 "github.com/juju/juju/rpc/params" 13 ) 14 15 // ControllerConfigAPI implements two common methods for use by various 16 // facades - eg Provisioner and ControllerConfig. 17 type ControllerConfigAPI struct { 18 st ControllerConfigState 19 } 20 21 // NewStateControllerConfig returns a new NewControllerConfigAPI. 22 func NewStateControllerConfig(st ControllerConfigState) *ControllerConfigAPI { 23 return &ControllerConfigAPI{ 24 st: st, 25 } 26 } 27 28 // ControllerConfig returns the controller's configuration. 29 func (s *ControllerConfigAPI) ControllerConfig() (params.ControllerConfigResult, error) { 30 result := params.ControllerConfigResult{} 31 config, err := s.st.ControllerConfig() 32 if err != nil { 33 return result, err 34 } 35 result.Config = params.ControllerConfig(config) 36 return result, nil 37 } 38 39 // ControllerAPIInfoForModels returns the controller api connection details for the specified models. 40 func (s *ControllerConfigAPI) ControllerAPIInfoForModels(args params.Entities) (params.ControllerAPIInfoResults, error) { 41 var result params.ControllerAPIInfoResults 42 result.Results = make([]params.ControllerAPIInfoResult, len(args.Entities)) 43 for i, entity := range args.Entities { 44 info, err := s.getModelControllerInfo(entity) 45 if err != nil { 46 result.Results[i].Error = apiservererrors.ServerError(err) 47 continue 48 } 49 result.Results[i] = info 50 } 51 return result, nil 52 } 53 54 // GetModelControllerInfo returns the external controller details for the specified model. 55 func (s *ControllerConfigAPI) getModelControllerInfo(model params.Entity) (params.ControllerAPIInfoResult, error) { 56 modelTag, err := names.ParseModelTag(model.Tag) 57 if err != nil { 58 return params.ControllerAPIInfoResult{}, errors.Trace(err) 59 } 60 // First see if the requested model UUID is hosted by this controller. 61 modelExists, err := s.st.ModelExists(modelTag.Id()) 62 if err != nil { 63 return params.ControllerAPIInfoResult{}, errors.Trace(err) 64 } 65 if modelExists { 66 addrs, caCert, err := StateControllerInfo(s.st) 67 if err != nil { 68 return params.ControllerAPIInfoResult{}, errors.Trace(err) 69 } 70 return params.ControllerAPIInfoResult{ 71 Addresses: addrs, 72 CACert: caCert, 73 }, nil 74 } 75 76 ec := s.st.NewExternalControllers() 77 ctrl, err := ec.ControllerForModel(modelTag.Id()) 78 if err == nil { 79 return params.ControllerAPIInfoResult{ 80 Addresses: ctrl.ControllerInfo().Addrs, 81 CACert: ctrl.ControllerInfo().CACert, 82 }, nil 83 } 84 if !errors.IsNotFound(err) { 85 return params.ControllerAPIInfoResult{}, errors.Trace(err) 86 } 87 88 // The model may have been migrated from this controller to another. 89 // If so, save the target as an external controller. 90 // This will preserve cross-model relation consumers for models that were 91 // on the same controller as migrated model, but not for consumers on other 92 // controllers. 93 // They will have to follow redirects and update their own relation data. 94 mig, err := s.st.CompletedMigrationForModel(modelTag.Id()) 95 if err != nil { 96 return params.ControllerAPIInfoResult{}, errors.Trace(err) 97 } 98 target, err := mig.TargetInfo() 99 if err != nil { 100 return params.ControllerAPIInfoResult{}, errors.Trace(err) 101 } 102 103 logger.Debugf("found migrated model on another controller, saving the information") 104 _, err = ec.Save(crossmodel.ControllerInfo{ 105 ControllerTag: target.ControllerTag, 106 Alias: target.ControllerAlias, 107 Addrs: target.Addrs, 108 CACert: target.CACert, 109 }, modelTag.Id()) 110 if err != nil { 111 return params.ControllerAPIInfoResult{}, errors.Trace(err) 112 } 113 return params.ControllerAPIInfoResult{ 114 Addresses: target.Addrs, 115 CACert: target.CACert, 116 }, nil 117 } 118 119 // StateControllerInfo returns the local controller details for the given State. 120 func StateControllerInfo(st controllerInfoState) (addrs []string, caCert string, _ error) { 121 addr, err := apiAddresses(st) 122 if err != nil { 123 return nil, "", errors.Trace(err) 124 } 125 controllerConfig, err := st.ControllerConfig() 126 if err != nil { 127 return nil, "", errors.Trace(err) 128 } 129 caCert, _ = controllerConfig.CACert() 130 return addr, caCert, nil 131 }