// Copyright 2024 Matthew Rich . All rights reserved. package resource import ( "context" "fmt" "gopkg.in/yaml.v3" "encoding/json" _ "log" "net/url" _ "os" _ "os/exec" "path/filepath" _ "strings" "io" "gitea.rosskeen.house/rosskeen.house/machine" "decl/internal/codec" "decl/internal/command" ) type Exec struct { stater machine.Stater `yaml:"-" json:"-"` Id string `yaml:"id,omitempty" json:"id,omitempty"` CreateTemplate *command.Command `yaml:"create,omitempty" json:"create,omitempty"` ReadTemplate *command.Command `yaml:"read,omitempty" json:"read,omitempty"` UpdateTemplate *command.Command `yaml:"update,omitempty" json:"update,omitempty"` DeleteTemplate *command.Command `yaml:"delete,omitempty" json:"delete,omitempty"` config ConfigurationValueGetter Resources ResourceMapper `yaml:"-" json:"-"` } func init() { ResourceTypes.Register([]string{"exec"}, func(u *url.URL) Resource { x := NewExec() return x }) } func NewExec() *Exec { return &Exec{} } func (x *Exec) SetResourceMapper(resources ResourceMapper) { x.Resources = resources } func (x *Exec) Clone() Resource { return &Exec { Id: x.Id, CreateTemplate: x.CreateTemplate, ReadTemplate: x.ReadTemplate, UpdateTemplate: x.UpdateTemplate, DeleteTemplate: x.DeleteTemplate, } } func (x *Exec) StateMachine() machine.Stater { if x.stater == nil { x.stater = ProcessMachine(x) } return x.stater } func (x *Exec) URI() string { return fmt.Sprintf("exec://%s", x.Id) } func (x *Exec) SetURI(uri string) error { resourceUri, e := url.Parse(uri) if e == nil { if resourceUri.Scheme == "exec" { x.Id = filepath.Join(resourceUri.Hostname(), resourceUri.RequestURI()) } else { e = fmt.Errorf("%w: %s is not an exec resource ", ErrInvalidResourceURI, uri) } } return e } func (x *Exec) UseConfig(config ConfigurationValueGetter) { x.config = config } func (x *Exec) ResolveId(ctx context.Context) string { return "" } func (x *Exec) Validate() (err error) { var execJson []byte if execJson, err = x.JSON(); err == nil { s := NewSchema(x.Type()) err = s.Validate(string(execJson)) } return err } func (x *Exec) Apply() error { return nil } func (x *Exec) Notify(m *machine.EventMessage) { ctx := context.Background() switch m.On { case machine.ENTERSTATEEVENT: switch m.Dest { case "start_create": if e := x.Create(ctx); e == nil { if triggerErr := x.stater.Trigger("created"); triggerErr == nil { return } } case "present": } case machine.EXITSTATEEVENT: } } func (x *Exec) Load(r io.Reader) error { return codec.NewYAMLDecoder(r).Decode(x) } func (x *Exec) LoadDecl(yamlResourceDeclaration string) error { return codec.NewYAMLStringDecoder(yamlResourceDeclaration).Decode(x) } func (x *Exec) JSON() ([]byte, error) { return json.Marshal(x) } func (x *Exec) Type() string { return "exec" } func (x *Exec) Create(ctx context.Context) (err error) { x.CreateTemplate.Defaults() _, err = x.CreateTemplate.Execute(x) return err } func (x *Exec) Read(ctx context.Context) ([]byte, error) { x.ReadTemplate.Defaults() return yaml.Marshal(x) }