github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/apiserver/facades/controller/undertaker/undertaker.go (about)

     1  // Copyright 2015 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package undertaker
     5  
     6  import (
     7  	"github.com/juju/errors"
     8  	"gopkg.in/juju/names.v2"
     9  
    10  	"github.com/juju/juju/apiserver/common"
    11  	"github.com/juju/juju/apiserver/facade"
    12  	"github.com/juju/juju/apiserver/params"
    13  	"github.com/juju/juju/state"
    14  	"github.com/juju/juju/state/watcher"
    15  )
    16  
    17  // UndertakerAPI implements the API used by the model undertaker worker.
    18  type UndertakerAPI struct {
    19  	st        State
    20  	resources facade.Resources
    21  	*common.StatusSetter
    22  }
    23  
    24  // NewUndertakerAPI creates a new instance of the undertaker API.
    25  func NewUndertakerAPI(st *state.State, resources facade.Resources, authorizer facade.Authorizer) (*UndertakerAPI, error) {
    26  	m, err := st.Model()
    27  	if err != nil {
    28  		return nil, errors.Trace(err)
    29  	}
    30  
    31  	return newUndertakerAPI(&stateShim{st, m}, resources, authorizer)
    32  }
    33  
    34  func newUndertakerAPI(st State, resources facade.Resources, authorizer facade.Authorizer) (*UndertakerAPI, error) {
    35  	if !authorizer.AuthController() {
    36  		return nil, common.ErrPerm
    37  	}
    38  	model, err := st.Model()
    39  	if err != nil {
    40  		return nil, errors.Trace(err)
    41  	}
    42  	getCanModifyModel := func() (common.AuthFunc, error) {
    43  		return func(tag names.Tag) bool {
    44  			if st.IsController() {
    45  				return true
    46  			}
    47  			// Only the agent's model can be modified.
    48  			modelTag, ok := tag.(names.ModelTag)
    49  			if !ok {
    50  				return false
    51  			}
    52  			return modelTag.Id() == model.UUID()
    53  		}, nil
    54  	}
    55  	return &UndertakerAPI{
    56  		st:           st,
    57  		resources:    resources,
    58  		StatusSetter: common.NewStatusSetter(st, getCanModifyModel),
    59  	}, nil
    60  }
    61  
    62  // ModelInfo returns information on the model needed by the undertaker worker.
    63  func (u *UndertakerAPI) ModelInfo() (params.UndertakerModelInfoResult, error) {
    64  	result := params.UndertakerModelInfoResult{}
    65  	model, err := u.st.Model()
    66  
    67  	if err != nil {
    68  		return result, errors.Trace(err)
    69  	}
    70  
    71  	result.Result = params.UndertakerModelInfo{
    72  		UUID:       model.UUID(),
    73  		GlobalName: model.Owner().String() + "/" + model.Name(),
    74  		Name:       model.Name(),
    75  		IsSystem:   u.st.IsController(),
    76  		Life:       params.Life(model.Life().String()),
    77  	}
    78  
    79  	return result, nil
    80  }
    81  
    82  // ProcessDyingModel checks if a dying model has any machines or applications.
    83  // If there are none, the model's life is changed from dying to dead.
    84  func (u *UndertakerAPI) ProcessDyingModel() error {
    85  	return u.st.ProcessDyingModel()
    86  }
    87  
    88  // RemoveModel removes any records of this model from Juju.
    89  func (u *UndertakerAPI) RemoveModel() error {
    90  	return u.st.RemoveDyingModel()
    91  }
    92  
    93  func (u *UndertakerAPI) modelEntitiesWatcher() params.NotifyWatchResult {
    94  	var nothing params.NotifyWatchResult
    95  	watch := u.st.WatchModelEntityReferences(u.st.ModelUUID())
    96  	if _, ok := <-watch.Changes(); ok {
    97  		return params.NotifyWatchResult{
    98  			NotifyWatcherId: u.resources.Register(watch),
    99  		}
   100  	}
   101  	nothing.Error = common.ServerError(watcher.EnsureErr(watch))
   102  	return nothing
   103  }
   104  
   105  // WatchModelResources creates watchers for changes to the lifecycle of an
   106  // model's machines and services.
   107  func (u *UndertakerAPI) WatchModelResources() params.NotifyWatchResults {
   108  	return params.NotifyWatchResults{
   109  		Results: []params.NotifyWatchResult{
   110  			u.modelEntitiesWatcher(),
   111  		},
   112  	}
   113  }
   114  
   115  // ModelConfig returns the model's configuration.
   116  func (u *UndertakerAPI) ModelConfig() (params.ModelConfigResult, error) {
   117  	result := params.ModelConfigResult{}
   118  
   119  	config, err := u.st.ModelConfig()
   120  	if err != nil {
   121  		return result, err
   122  	}
   123  	allAttrs := config.AllAttrs()
   124  	result.Config = allAttrs
   125  	return result, nil
   126  }