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  }