add more state handling to exec resource
Some checks are pending
Lint / golangci-lint (push) Waiting to run
Declarative Tests / test (push) Waiting to run
Declarative Tests / build-fedora (push) Waiting to run
Declarative Tests / build-ubuntu-focal (push) Waiting to run

This commit is contained in:
Matthew Rich 2024-09-19 08:05:29 +00:00
parent c4afd77777
commit 69510991dc
2 changed files with 87 additions and 14 deletions

View File

@ -11,15 +11,23 @@ import (
"net/url"
_ "os"
_ "os/exec"
"path/filepath"
_ "strings"
"io"
"gitea.rosskeen.house/rosskeen.house/machine"
"decl/internal/codec"
"decl/internal/command"
"decl/internal/data"
"decl/internal/folio"
"errors"
"log/slog"
)
const (
ExecTypeName TypeName = "exec"
)
type Exec struct {
*Common `yaml:",inline" json:",inline"`
stater machine.Stater `yaml:"-" json:"-"`
Id string `yaml:"id,omitempty" json:"id,omitempty"`
CreateTemplate *command.Command `yaml:"create,omitempty" json:"create,omitempty"`
@ -27,27 +35,27 @@ type Exec struct {
UpdateTemplate *command.Command `yaml:"update,omitempty" json:"update,omitempty"`
DeleteTemplate *command.Command `yaml:"delete,omitempty" json:"delete,omitempty"`
config ConfigurationValueGetter
Resources ResourceMapper `yaml:"-" json:"-"`
Resources data.ResourceMapper `yaml:"-" json:"-"`
}
func init() {
ResourceTypes.Register([]string{"exec"}, func(u *url.URL) Resource {
folio.DocumentRegistry.ResourceTypes.Register([]string{"exec"}, func(u *url.URL) data.Resource {
x := NewExec()
return x
})
}
func NewExec() *Exec {
return &Exec{}
return &Exec{ Common: &Common{ includeQueryParamsInURI: true, resourceType: ExecTypeName } }
}
func (x *Exec) SetResourceMapper(resources ResourceMapper) {
func (x *Exec) SetResourceMapper(resources data.ResourceMapper) {
x.Resources = resources
}
func (x *Exec) Clone() Resource {
func (x *Exec) Clone() data.Resource {
return &Exec {
Common: x.Common,
Id: x.Id,
CreateTemplate: x.CreateTemplate,
ReadTemplate: x.ReadTemplate,
@ -67,6 +75,19 @@ func (x *Exec) URI() string {
return fmt.Sprintf("exec://%s", x.Id)
}
func (x *Exec) SetURI(uri string) (err error) {
err = x.Common.SetURI(uri)
x.Id = x.Common.Path
return
}
func (x *Exec) SetParsedURI(uri *url.URL) (err error) {
err = x.Common.SetParsedURI(uri)
x.Id = x.Common.Path
return
}
/*
func (x *Exec) SetURI(uri string) error {
resourceUri, e := url.Parse(uri)
if e == nil {
@ -79,13 +100,14 @@ func (x *Exec) SetURI(uri string) error {
return e
}
func (x *Exec) UseConfig(config ConfigurationValueGetter) {
func (x *Exec) UseConfig(config data.ConfigurationValueGetter) {
x.config = config
}
func (x *Exec) ResolveId(ctx context.Context) string {
return ""
}
*/
func (x *Exec) Validate() (err error) {
var execJson []byte
@ -102,27 +124,68 @@ func (x *Exec) Apply() error {
func (x *Exec) Notify(m *machine.EventMessage) {
ctx := context.Background()
slog.Info("Notify()", "exec", x, "m", m)
switch m.On {
case machine.ENTERSTATEEVENT:
switch m.Dest {
case "start_read":
if _, readErr := x.Read(ctx); readErr == nil {
if triggerErr := x.StateMachine().Trigger("state_read"); triggerErr == nil {
return
} else {
x.State = "absent"
panic(triggerErr)
}
} else {
x.State = "absent"
if ! errors.Is(readErr, ErrResourceStateAbsent) {
panic(readErr)
}
}
case "start_create":
if e := x.Create(ctx); e == nil {
if triggerErr := x.stater.Trigger("created"); triggerErr == nil {
return
}
}
case "present":
case "start_delete":
if deleteErr := x.Delete(ctx); deleteErr == nil {
if triggerErr := x.StateMachine().Trigger("deleted"); triggerErr == nil {
return
} else {
x.State = "present"
panic(triggerErr)
}
} else {
x.State = "present"
panic(deleteErr)
}
case "absent":
x.State = "absent"
case "present", "created", "read":
x.State = "present"
}
case machine.EXITSTATEEVENT:
}
}
func (x *Exec) Load(r io.Reader) error {
return codec.NewYAMLDecoder(r).Decode(x)
func (x *Exec) Load(docData []byte, f codec.Format) (err error) {
err = f.StringDecoder(string(docData)).Decode(x)
return
}
func (x *Exec) LoadReader(r io.ReadCloser, f codec.Format) (err error) {
err = f.Decoder(r).Decode(x)
return
}
func (x *Exec) LoadString(docData string, f codec.Format) (err error) {
err = f.StringDecoder(docData).Decode(x)
return
}
func (x *Exec) LoadDecl(yamlResourceDeclaration string) error {
return codec.NewYAMLStringDecoder(yamlResourceDeclaration).Decode(x)
return x.LoadString(yamlResourceDeclaration, codec.FormatYaml)
}
func (x *Exec) JSON() ([]byte, error) {
@ -134,10 +197,20 @@ func (x *Exec) Type() string { return "exec" }
func (x *Exec) Create(ctx context.Context) (err error) {
x.CreateTemplate.Defaults()
_, err = x.CreateTemplate.Execute(x)
slog.Info("Exec.Create()", "resource", x, "error", err)
return err
}
func (x *Exec) Read(ctx context.Context) ([]byte, error) {
if x.ReadTemplate != nil {
x.ReadTemplate.Defaults()
}
return yaml.Marshal(x)
}
func (x *Exec) Update(ctx context.Context) (err error) {
return
}
func (x *Exec) Delete(ctx context.Context) (err error) {
return
}

View File

@ -60,5 +60,5 @@ func TestExecSetURI(t *testing.T) {
e := x.SetURI("exec://" + "12345_key")
assert.Nil(t, e)
assert.Equal(t, "exec", x.Type())
assert.Equal(t, "12345_key", x.Id)
assert.Equal(t, "12345_key", x.Path)
}