github.com/juju/juju@v0.0.0-20240327075706-a90865de2538/worker/meterstatus/state.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package meterstatus 5 6 import ( 7 "os" 8 "time" 9 10 "github.com/juju/errors" 11 "github.com/juju/utils/v3" 12 "gopkg.in/yaml.v2" 13 14 "github.com/juju/juju/rpc/params" 15 ) 16 17 // State represents the worker's internal state. 18 type State struct { 19 Code string `yaml:"status-code"` 20 Info string `yaml:"status-info"` 21 Disconnected *Disconnected `yaml:"disconnected,omitempty"` 22 } 23 24 // Disconnected stores the information relevant to the inactive meter status worker. 25 type Disconnected struct { 26 Disconnected int64 `yaml:"disconnected-at,omitempty"` 27 State WorkerState `yaml:"disconnected-state,omitempty"` 28 } 29 30 // When returns the time when the unit was disconnected. 31 func (d Disconnected) When() time.Time { 32 return time.Unix(d.Disconnected, 0) 33 } 34 35 //go:generate go run go.uber.org/mock/mockgen -package mocks -destination mocks/interface_mock.go github.com/juju/juju/worker/meterstatus UnitStateAPI,StateReadWriter 36 37 // StateReadWriter is implemented by types that can read and write the meter 38 // worker's internal state. 39 type StateReadWriter interface { 40 Read() (*State, error) 41 Write(*State) error 42 } 43 44 // UnitStateAPI describes the API for reading/writing unit state data from/to 45 // the controller. 46 type UnitStateAPI interface { 47 State() (params.UnitStateResult, error) 48 SetState(params.SetUnitStateArg) error 49 } 50 51 var _ StateReadWriter = (*ControllerBackedState)(nil) 52 53 // ControllerBackedState is a StateReadWriter that uses the controller as its 54 // backing store. 55 type ControllerBackedState struct { 56 api UnitStateAPI 57 } 58 59 // NewControllerBackedState returns a new ControllerBackedState that uses the 60 // provided UnitStateAPI to communicate with the controller. 61 func NewControllerBackedState(api UnitStateAPI) *ControllerBackedState { 62 return &ControllerBackedState{api: api} 63 } 64 65 // Read the current meter status information from the controller. 66 func (cbs *ControllerBackedState) Read() (*State, error) { 67 ust, err := cbs.api.State() 68 if err != nil { 69 return nil, errors.Trace(err) 70 } 71 72 if ust.MeterStatusState == "" { 73 return nil, errors.NotFoundf("state") 74 } 75 76 var st State 77 if err := yaml.Unmarshal([]byte(ust.MeterStatusState), &st); err != nil { 78 return nil, errors.Trace(err) 79 } 80 81 return &st, nil 82 } 83 84 // Write the supplied status information to the controller. 85 func (cbs *ControllerBackedState) Write(st *State) error { 86 data, err := yaml.Marshal(st) 87 if err != nil { 88 return errors.Trace(err) 89 } 90 91 dataStr := string(data) 92 return errors.Trace( 93 cbs.api.SetState(params.SetUnitStateArg{ 94 MeterStatusState: &dataStr, 95 }), 96 ) 97 } 98 99 var _ StateReadWriter = (*DiskBackedState)(nil) 100 101 // DiskBackedState stores the meter status on disk. 102 type DiskBackedState struct { 103 path string 104 } 105 106 // NewDiskBackedState creates a DiskBackedState instance that uses path for 107 // reading/writing the meter status state. 108 func NewDiskBackedState(path string) *DiskBackedState { 109 return &DiskBackedState{path: path} 110 } 111 112 // Read the current meter status information from disk. 113 func (dbs *DiskBackedState) Read() (*State, error) { 114 var st State 115 if err := utils.ReadYaml(dbs.path, &st); err != nil { 116 if os.IsNotExist(err) { 117 return nil, errors.NotFoundf("state file") 118 } 119 return nil, errors.Trace(err) 120 } 121 122 return &st, nil 123 } 124 125 // Write the supplied status information to disk. 126 func (dbs *DiskBackedState) Write(st *State) error { 127 return errors.Trace(utils.WriteYaml(dbs.path, st)) 128 }