github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/caasoperatorprovisioner/provisioner.go (about) 1 // Copyright 2017 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package caasoperatorprovisioner 5 6 import ( 7 "fmt" 8 9 "github.com/juju/errors" 10 "gopkg.in/juju/names.v2" 11 12 "github.com/juju/juju/apiserver/common" 13 "github.com/juju/juju/apiserver/common/storagecommon" 14 "github.com/juju/juju/apiserver/facade" 15 "github.com/juju/juju/apiserver/params" 16 "github.com/juju/juju/caas" 17 "github.com/juju/juju/caas/kubernetes/provider" 18 "github.com/juju/juju/environs/tags" 19 "github.com/juju/juju/state" 20 "github.com/juju/juju/state/stateenvirons" 21 "github.com/juju/juju/state/watcher" 22 "github.com/juju/juju/storage" 23 "github.com/juju/juju/storage/poolmanager" 24 "github.com/juju/juju/version" 25 ) 26 27 type API struct { 28 *common.PasswordChanger 29 *common.LifeGetter 30 *common.APIAddresser 31 32 auth facade.Authorizer 33 resources facade.Resources 34 35 state CAASOperatorProvisionerState 36 storageProviderRegistry storage.ProviderRegistry 37 storagePoolManager poolmanager.PoolManager 38 } 39 40 // NewStateCAASOperatorProvisionerAPI provides the signature required for facade registration. 41 func NewStateCAASOperatorProvisionerAPI(ctx facade.Context) (*API, error) { 42 43 authorizer := ctx.Auth() 44 resources := ctx.Resources() 45 46 broker, err := stateenvirons.GetNewCAASBrokerFunc(caas.New)(ctx.State()) 47 if err != nil { 48 return nil, errors.Annotate(err, "getting caas client") 49 } 50 registry := stateenvirons.NewStorageProviderRegistry(broker) 51 pm := poolmanager.New(state.NewStateSettings(ctx.State()), registry) 52 53 return NewCAASOperatorProvisionerAPI(resources, authorizer, stateShim{ctx.State()}, registry, pm) 54 } 55 56 // NewCAASOperatorProvisionerAPI returns a new CAAS operator provisioner API facade. 57 func NewCAASOperatorProvisionerAPI( 58 resources facade.Resources, 59 authorizer facade.Authorizer, 60 st CAASOperatorProvisionerState, 61 storageProviderRegistry storage.ProviderRegistry, 62 storagePoolManager poolmanager.PoolManager, 63 ) (*API, error) { 64 if !authorizer.AuthController() { 65 return nil, common.ErrPerm 66 } 67 return &API{ 68 PasswordChanger: common.NewPasswordChanger(st, common.AuthFuncForTagKind(names.ApplicationTagKind)), 69 LifeGetter: common.NewLifeGetter(st, common.AuthFuncForTagKind(names.ApplicationTagKind)), 70 APIAddresser: common.NewAPIAddresser(st, resources), 71 auth: authorizer, 72 resources: resources, 73 state: st, 74 storageProviderRegistry: storageProviderRegistry, 75 storagePoolManager: storagePoolManager, 76 }, nil 77 } 78 79 // WatchApplications starts a StringsWatcher to watch CAAS applications 80 // deployed to this model. 81 func (a *API) WatchApplications() (params.StringsWatchResult, error) { 82 watch := a.state.WatchApplications() 83 // Consume the initial event and forward it to the result. 84 if changes, ok := <-watch.Changes(); ok { 85 return params.StringsWatchResult{ 86 StringsWatcherId: a.resources.Register(watch), 87 Changes: changes, 88 }, nil 89 } 90 return params.StringsWatchResult{}, watcher.EnsureErr(watch) 91 } 92 93 // OperatorProvisioningInfo returns the info needed to provision an operator. 94 func (a *API) OperatorProvisioningInfo() (params.OperatorProvisioningInfo, error) { 95 cfg, err := a.state.ControllerConfig() 96 if err != nil { 97 return params.OperatorProvisioningInfo{}, err 98 } 99 100 imagePath := cfg.CAASOperatorImagePath() 101 vers := version.Current 102 vers.Build = 0 103 if imagePath == "" { 104 imagePath = fmt.Sprintf("%s/caas-jujud-operator:%s", "jujusolutions", vers.String()) 105 } 106 charmStorageParams, err := charmStorageParams(a.storagePoolManager, a.storageProviderRegistry) 107 if err != nil { 108 return params.OperatorProvisioningInfo{}, errors.Annotatef(err, "getting operator storage parameters") 109 } 110 apiAddresses, err := a.APIAddresses() 111 if err == nil && apiAddresses.Error != nil { 112 err = apiAddresses.Error 113 } 114 if err != nil { 115 return params.OperatorProvisioningInfo{}, errors.Annotatef(err, "getting api addresses") 116 } 117 118 model, err := a.state.Model() 119 if err != nil { 120 return params.OperatorProvisioningInfo{}, errors.Trace(err) 121 } 122 modelConfig, err := model.ModelConfig() 123 if err != nil { 124 return params.OperatorProvisioningInfo{}, errors.Trace(err) 125 } 126 127 resourceTags := tags.ResourceTags( 128 names.NewModelTag(model.UUID()), 129 names.NewControllerTag(cfg.ControllerUUID()), 130 modelConfig, 131 ) 132 charmStorageParams.Tags = resourceTags 133 134 return params.OperatorProvisioningInfo{ 135 ImagePath: imagePath, 136 Version: vers, 137 APIAddresses: apiAddresses.Result, 138 CharmStorage: charmStorageParams, 139 Tags: resourceTags, 140 }, nil 141 } 142 143 func charmStorageParams( 144 poolManager poolmanager.PoolManager, 145 registry storage.ProviderRegistry, 146 ) (params.KubernetesFilesystemParams, error) { 147 148 // TODO(caas) - make these configurable via model config 149 var pool = caas.OperatorStoragePoolName 150 var size uint64 = 1024 151 152 result := params.KubernetesFilesystemParams{ 153 Size: size, 154 Provider: string(provider.K8s_ProviderType), 155 } 156 157 providerType, cfg, err := storagecommon.StoragePoolConfig(pool, poolManager, registry) 158 if err != nil && !errors.IsNotFound(err) { 159 return params.KubernetesFilesystemParams{}, errors.Trace(err) 160 } 161 if err == nil { 162 result.Provider = string(providerType) 163 result.Attributes = cfg.Attrs() 164 } 165 return result, nil 166 }