github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/api/common/unitstate.go (about)

     1  // Copyright 2020 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  	"github.com/juju/juju/api/base"
    11  	"github.com/juju/juju/rpc/params"
    12  )
    13  
    14  // UnitStateAPI provides common agent-side API functions to
    15  // call into apiserver.common/UnitState
    16  type UnitStateAPI struct {
    17  	facade base.FacadeCaller
    18  	tag    names.UnitTag
    19  }
    20  
    21  // NewUniterStateAPI creates a UnitStateAPI that uses the provided FacadeCaller
    22  // for making calls.
    23  func NewUniterStateAPI(facade base.FacadeCaller, tag names.UnitTag) *UnitStateAPI {
    24  	return &UnitStateAPI{facade: facade, tag: tag}
    25  }
    26  
    27  // State returns the state persisted by the charm running in this unit
    28  // and the state internal to the uniter for this unit.
    29  func (u *UnitStateAPI) State() (params.UnitStateResult, error) {
    30  	var results params.UnitStateResults
    31  	args := params.Entities{
    32  		Entities: []params.Entity{{Tag: u.tag.String()}},
    33  	}
    34  	err := u.facade.FacadeCall("State", args, &results)
    35  	if err != nil {
    36  		return params.UnitStateResult{}, err
    37  	}
    38  	if len(results.Results) != 1 {
    39  		return params.UnitStateResult{}, errors.Errorf("expected 1 result, got %d", len(results.Results))
    40  	}
    41  	result := results.Results[0]
    42  	if result.Error != nil {
    43  		return params.UnitStateResult{}, result.Error
    44  	}
    45  	return result, nil
    46  }
    47  
    48  // SetState sets the state persisted by the charm running in this unit
    49  // and the state internal to the uniter for this unit.
    50  func (u *UnitStateAPI) SetState(unitState params.SetUnitStateArg) error {
    51  	unitState.Tag = u.tag.String()
    52  	var results params.ErrorResults
    53  	args := params.SetUnitStateArgs{
    54  		Args: []params.SetUnitStateArg{unitState},
    55  	}
    56  	err := u.facade.FacadeCall("SetState", args, &results)
    57  	if err != nil {
    58  		return errors.Trace(err)
    59  	}
    60  	// Make sure we correctly decode quota-related errors.
    61  	return maybeRestoreQuotaLimitError(results.OneError())
    62  }
    63  
    64  // maybeRestoreQuotaLimitError checks if the server emitted a quota limit
    65  // exceeded error and restores it back to a typed error from juju/errors.
    66  // Ideally, we would use apiserver/common.RestoreError but apparently, that
    67  // package imports worker/uniter/{operation, remotestate} causing an import
    68  // cycle when api/common is imported by api/uniter.
    69  func maybeRestoreQuotaLimitError(err error) error {
    70  	if params.IsCodeQuotaLimitExceeded(err) {
    71  		return errors.NewQuotaLimitExceeded(nil, err.Error())
    72  	}
    73  	return err
    74  }