2023-02-02 10:55:24 +01:00
|
|
|
package agent
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
|
2023-03-02 13:05:24 +01:00
|
|
|
"forge.cadoles.com/Cadoles/emissary/internal/datastore"
|
2023-02-02 10:55:24 +01:00
|
|
|
"forge.cadoles.com/Cadoles/emissary/internal/spec"
|
|
|
|
"github.com/mitchellh/mapstructure"
|
|
|
|
"github.com/pkg/errors"
|
|
|
|
)
|
|
|
|
|
|
|
|
var ErrSpecNotFound = errors.New("spec not found")
|
|
|
|
|
|
|
|
type Specs map[spec.Name]spec.Spec
|
|
|
|
|
|
|
|
type State struct {
|
2023-03-02 13:05:24 +01:00
|
|
|
agentID datastore.AgentID
|
|
|
|
specs Specs
|
2023-02-02 10:55:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
func NewState() *State {
|
|
|
|
return &State{
|
|
|
|
specs: make(map[spec.Name]spec.Spec),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) MarshalJSON() ([]byte, error) {
|
|
|
|
state := struct {
|
2023-03-02 13:05:24 +01:00
|
|
|
ID datastore.AgentID `json:"agentId"`
|
2023-02-02 10:55:24 +01:00
|
|
|
Specs map[spec.Name]*spec.RawSpec `json:"specs"`
|
|
|
|
}{
|
2023-03-02 13:05:24 +01:00
|
|
|
ID: s.agentID,
|
2023-02-02 10:55:24 +01:00
|
|
|
Specs: func(specs map[spec.Name]spec.Spec) map[spec.Name]*spec.RawSpec {
|
|
|
|
rawSpecs := make(map[spec.Name]*spec.RawSpec)
|
|
|
|
|
|
|
|
for name, sp := range specs {
|
|
|
|
rawSpecs[name] = &spec.RawSpec{
|
|
|
|
Name: sp.SpecName(),
|
|
|
|
Revision: sp.SpecRevision(),
|
|
|
|
Data: sp.SpecData(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return rawSpecs
|
|
|
|
}(s.specs),
|
|
|
|
}
|
|
|
|
|
|
|
|
data, err := json.Marshal(state)
|
|
|
|
if err != nil {
|
|
|
|
return nil, errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return data, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) UnmarshalJSON(data []byte) error {
|
|
|
|
state := struct {
|
2023-03-02 13:05:24 +01:00
|
|
|
AgentID datastore.AgentID `json:"agentId"`
|
|
|
|
Specs map[spec.Name]*spec.RawSpec `json:"specs"`
|
2023-02-02 10:55:24 +01:00
|
|
|
}{}
|
|
|
|
|
|
|
|
if err := json.Unmarshal(data, &state); err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
s.specs = func(rawSpecs map[spec.Name]*spec.RawSpec) Specs {
|
|
|
|
specs := make(Specs)
|
|
|
|
|
|
|
|
for name, raw := range rawSpecs {
|
|
|
|
specs[name] = spec.Spec(raw)
|
|
|
|
}
|
|
|
|
|
|
|
|
return specs
|
|
|
|
}(state.Specs)
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2023-03-02 13:05:24 +01:00
|
|
|
func (s *State) AgentID() datastore.AgentID {
|
|
|
|
return s.agentID
|
|
|
|
}
|
|
|
|
|
2023-02-02 10:55:24 +01:00
|
|
|
func (s *State) Specs() Specs {
|
|
|
|
return s.specs
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) ClearSpecs() *State {
|
|
|
|
s.specs = make(map[spec.Name]spec.Spec)
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) SetSpec(sp spec.Spec) *State {
|
|
|
|
if s.specs == nil {
|
|
|
|
s.specs = make(map[spec.Name]spec.Spec)
|
|
|
|
}
|
|
|
|
|
|
|
|
s.specs[sp.SpecName()] = sp
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
|
|
|
func (s *State) GetSpec(name spec.Name, dest any) error {
|
|
|
|
spec, exists := s.specs[name]
|
|
|
|
if !exists {
|
|
|
|
return errors.WithStack(ErrSpecNotFound)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := mapstructure.Decode(spec, dest); err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := mapstructure.Decode(spec.SpecData(), dest); err != nil {
|
|
|
|
return errors.WithStack(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|