fix import -resource flag
Some checks failed
Lint / golangci-lint (push) Failing after 9m50s
Declarative Tests / test (push) Failing after 1m7s

This commit is contained in:
Matthew Rich 2024-04-20 23:13:17 -07:00
parent a6ea2e8c8c
commit 9d58db522d
15 changed files with 109 additions and 39 deletions

View File

@ -18,7 +18,7 @@ func TestCli(t *testing.T) {
if _, e := os.Stat("./decl"); errors.Is(e, os.ErrNotExist) { if _, e := os.Stat("./decl"); errors.Is(e, os.ErrNotExist) {
t.Skip("cli not built") t.Skip("cli not built")
} }
yaml, cliErr := exec.Command("./decl", "-import-resource", "file://COPYRIGHT").Output() yaml, cliErr := exec.Command("./decl", "import", "file://COPYRIGHT").Output()
slog.Info("TestCli", "err", cliErr) slog.Info("TestCli", "err", cliErr)
assert.Nil(t, cliErr) assert.Nil(t, cliErr)
assert.NotEqual(t, "", string(yaml)) assert.NotEqual(t, "", string(yaml))

View File

@ -25,6 +25,7 @@ var GlobalOformat *string
var GlobalQuiet *bool var GlobalQuiet *bool
var ImportMerge *bool var ImportMerge *bool
var ImportResource *string
var ctx context.Context = context.Background() var ctx context.Context = context.Background()
@ -73,19 +74,24 @@ func LoadSourceURI(uri string) []*resource.Document {
if extractErr != nil { if extractErr != nil {
log.Fatal(extractErr) log.Fatal(extractErr)
} }
slog.Info("extract documents", "documents", extractDocuments)
return extractDocuments return extractDocuments
} }
return []*resource.Document{ resource.NewDocument() } return []*resource.Document{ resource.NewDocument() }
} }
func ImportSubCommand(cmd *flag.FlagSet, output io.Writer) (err error) { func ImportSubCommand(cmd *flag.FlagSet, output io.Writer) (err error) {
ImportResource = cmd.String("resource", "", "(uri) Add a resource to the document.")
ImportMerge = cmd.Bool("merge", false, "Merge resources into a single document.") ImportMerge = cmd.Bool("merge", false, "Merge resources into a single document.")
cmd.Parse(os.Args[2:]) cmd.Parse(os.Args[2:])
var encoder resource.Encoder var encoder resource.Encoder
merged := resource.NewDocument() merged := resource.NewDocument()
documents := make([]*resource.Document, 0, 100) documents := make([]*resource.Document, 0, 100)
for _,source := range cmd.Args() { for _,source := range cmd.Args() {
documents = append(documents, LoadSourceURI(source)...) loaded := LoadSourceURI(source)
if loaded != nil {
documents = append(documents, loaded...)
}
} }
switch *GlobalOformat { switch *GlobalOformat {
@ -95,8 +101,20 @@ func ImportSubCommand(cmd *flag.FlagSet, output io.Writer) (err error) {
encoder = resource.NewJSONEncoder(output) encoder = resource.NewJSONEncoder(output)
} }
if len(documents) == 0 {
documents = append(documents, resource.NewDocument())
}
for _,d := range documents { for _,d := range documents {
if d != nil { if d != nil {
if *ImportResource != "" {
slog.Info("ImportResource", "resource", ImportResource)
if addResourceErr := d.AddResource(*ImportResource); addResourceErr != nil {
log.Fatal(addResourceErr)
}
}
if *GlobalQuiet { if *GlobalQuiet {
for _, dr := range d.Resources() { for _, dr := range d.Resources() {
output.Write([]byte(dr.Resource().URI())) output.Write([]byte(dr.Resource().URI()))
@ -126,10 +144,15 @@ func ApplySubCommand(cmd *flag.FlagSet, output io.Writer) (err error) {
var encoder resource.Encoder var encoder resource.Encoder
documents := make([]*resource.Document, 0, 100) documents := make([]*resource.Document, 0, 100)
for _,source := range cmd.Args() { for _,source := range cmd.Args() {
documents = append(documents, LoadSourceURI(source)...) loaded := LoadSourceURI(source)
if loaded != nil {
documents = append(documents, loaded...)
}
} }
slog.Info("main.Apply()", "documents", documents)
for _,d := range documents { for _,d := range documents {
slog.Info("main.Appl()", "doc", d)
if e := d.Apply(); e != nil { if e := d.Apply(); e != nil {
return e return e
} }

1
go.mod
View File

@ -12,6 +12,7 @@ require (
) )
require ( require (
gitea.rosskeen.house/rosskeen.house/machine v0.0.0-20240404204346-6c7c3faf2814 // indirect
github.com/Microsoft/go-winio v0.4.14 // indirect github.com/Microsoft/go-winio v0.4.14 // indirect
github.com/containerd/log v0.1.0 // indirect github.com/containerd/log v0.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect

2
go.sum
View File

@ -1,3 +1,5 @@
gitea.rosskeen.house/rosskeen.house/machine v0.0.0-20240404204346-6c7c3faf2814 h1:nPMHPc3NB+jsd1OFQlrEiRKPXT7KHd6fYyWItt4jCVs=
gitea.rosskeen.house/rosskeen.house/machine v0.0.0-20240404204346-6c7c3faf2814/go.mod h1:5J2OFjFIBaCfsjcC9kSyycbIL8g/qAJH2A8BnbIig+Y=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU= github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=

View File

@ -23,6 +23,7 @@ import (
"path/filepath" "path/filepath"
_ "strings" _ "strings"
"encoding/json" "encoding/json"
"io"
) )
type ContainerClient interface { type ContainerClient interface {
@ -35,7 +36,6 @@ type ContainerClient interface {
} }
type Container struct { type Container struct {
loader YamlLoader
Id string `json:"ID,omitempty" yaml:"ID,omitempty"` Id string `json:"ID,omitempty" yaml:"ID,omitempty"`
Name string `json:"name" yaml:"name"` Name string `json:"name" yaml:"name"`
Path string `json:"path" yaml:"path"` Path string `json:"path" yaml:"path"`
@ -90,7 +90,6 @@ func NewContainer(containerClientApi ContainerClient) *Container {
} }
} }
return &Container{ return &Container{
loader: YamlLoadDecl,
apiClient: apiClient, apiClient: apiClient,
} }
} }
@ -162,8 +161,14 @@ func (c *Container) Apply() error {
return nil return nil
} }
func (c *Container) LoadDecl(yamlFileResourceDeclaration string) error { func (c *Container) Load(r io.Reader) error {
return c.loader(yamlFileResourceDeclaration, c) d := NewYAMLDecoder(r)
return d.Decode(c)
}
func (c *Container) LoadDecl(yamlResourceDeclaration string) error {
d := NewYAMLStringDecoder(yamlResourceDeclaration)
return d.Decode(c)
} }
func (c *Container) Create(ctx context.Context) error { func (c *Container) Create(ctx context.Context) error {

View File

@ -9,14 +9,18 @@ import (
"io" "io"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
"log/slog" "log/slog"
"gitea.rosskeen.house/rosskeen.house/machine"
) )
type DeclarationType struct { type DeclarationType struct {
Type TypeName `json:"type" yaml:"type"` Type TypeName `json:"type" yaml:"type"`
Transition string `json:"transition" yaml:"transition"`
} }
type Declaration struct { type Declaration struct {
StateMatchine machine.Stater `json:"-" yaml:"-"`
Type TypeName `json:"type" yaml:"type"` Type TypeName `json:"type" yaml:"type"`
Transition string `json:"transition,omitempty" yaml:"transition,omitempty"`
Attributes Resource `json:"attributes" yaml:"attributes"` Attributes Resource `json:"attributes" yaml:"attributes"`
} }
@ -28,15 +32,6 @@ type StateTransformer interface {
Apply() error Apply() error
} }
type YamlLoader func(string, any) error
func YamlLoadDecl(yamlFileResourceDeclaration string, resource any) error {
if err := yaml.Unmarshal([]byte(yamlFileResourceDeclaration), resource); err != nil {
return err
}
return nil
}
func NewDeclaration() *Declaration { func NewDeclaration() *Declaration {
return &Declaration{} return &Declaration{}
} }
@ -87,6 +82,7 @@ func (d *Declaration) UnmarshalYAML(value *yaml.Node) error {
} }
d.Type = t.Type d.Type = t.Type
d.Transition = t.Transition
newResource, resourceErr := ResourceTypes.New(fmt.Sprintf("%s://", d.Type)) newResource, resourceErr := ResourceTypes.New(fmt.Sprintf("%s://", d.Type))
if resourceErr != nil { if resourceErr != nil {
return resourceErr return resourceErr
@ -111,6 +107,7 @@ func (d *Declaration) UnmarshalJSON(data []byte) error {
} }
d.Type = t.Type d.Type = t.Type
d.Transition = t.Transition
newResource, resourceErr := ResourceTypes.New(fmt.Sprintf("%s://", d.Type)) newResource, resourceErr := ResourceTypes.New(fmt.Sprintf("%s://", d.Type))
if resourceErr != nil { if resourceErr != nil {

View File

@ -60,6 +60,10 @@ func (d *Document) Resources() []Declaration {
} }
func (d *Document) Apply() error { func (d *Document) Apply() error {
if d == nil {
panic("Undefined Document")
}
slog.Info("Document.Apply()", "declarations", d)
for i := range d.ResourceDecls { for i := range d.ResourceDecls {
if e := d.ResourceDecls[i].Resource().Apply(); e != nil { if e := d.ResourceDecls[i].Resource().Apply(); e != nil {
return e return e

View File

@ -11,11 +11,11 @@ import (
_ "os" _ "os"
_ "os/exec" _ "os/exec"
"path/filepath" "path/filepath"
_ "strings" _ "strings"
"io"
) )
type Exec struct { type Exec struct {
loader YamlLoader
Id string `yaml:"id" json:"id"` Id string `yaml:"id" json:"id"`
CreateTemplate Command `yaml:"create" json:"create"` CreateTemplate Command `yaml:"create" json:"create"`
ReadTemplate Command `yaml:"read" json:"read"` ReadTemplate Command `yaml:"read" json:"read"`
@ -34,7 +34,7 @@ func init() {
} }
func NewExec() *Exec { func NewExec() *Exec {
return &Exec{loader: YamlLoadDecl} return &Exec{}
} }
func (x *Exec) Clone() Resource { func (x *Exec) Clone() Resource {
@ -76,8 +76,14 @@ func (x *Exec) Apply() error {
return nil return nil
} }
func (x *Exec) LoadDecl(yamlFileResourceDeclaration string) error { func (x *Exec) Load(r io.Reader) error {
return x.loader(yamlFileResourceDeclaration, x) c := NewYAMLDecoder(r)
return c.Decode(x)
}
func (x *Exec) LoadDecl(yamlResourceDeclaration string) error {
c := NewYAMLStringDecoder(yamlResourceDeclaration)
return c.Decode(x)
} }
func (x *Exec) Type() string { return "exec" } func (x *Exec) Type() string { return "exec" }

View File

@ -16,6 +16,7 @@ import (
"strconv" "strconv"
"syscall" "syscall"
"time" "time"
"crypto/sha256"
) )
type FileType string type FileType string
@ -53,6 +54,7 @@ type File struct {
Mtime time.Time `json:"mtime,omitempty" yaml:"mtime,omitempty"` Mtime time.Time `json:"mtime,omitempty" yaml:"mtime,omitempty"`
Content string `json:"content,omitempty" yaml:"content,omitempty"` Content string `json:"content,omitempty" yaml:"content,omitempty"`
Sha256 string `json:"sha256,omitempty" yaml:"sha256,omitempty"`
Target string `json:"target,omitempty" yaml:"target,omitempty"` Target string `json:"target,omitempty" yaml:"target,omitempty"`
FileType FileType `json:"filetype" yaml:"filetype"` FileType FileType `json:"filetype" yaml:"filetype"`
State string `json:"state" yaml:"state"` State string `json:"state" yaml:"state"`
@ -90,7 +92,11 @@ func (f *File) SetURI(uri string) error {
resourceUri, e := url.Parse(uri) resourceUri, e := url.Parse(uri)
if e == nil { if e == nil {
if resourceUri.Scheme == "file" { if resourceUri.Scheme == "file" {
f.Path, e = filepath.Abs(filepath.Join(resourceUri.Hostname(), resourceUri.RequestURI())) if absFilePath, err := filepath.Abs(filepath.Join(resourceUri.Hostname(), resourceUri.RequestURI())); err != nil {
return err
} else {
f.Path = absFilePath
}
} else { } else {
e = fmt.Errorf("%w: %s is not a file", ErrInvalidResourceURI, uri) e = fmt.Errorf("%w: %s is not a file", ErrInvalidResourceURI, uri)
} }
@ -256,6 +262,7 @@ func (f *File) Read(ctx context.Context) ([]byte, error) {
panic(ioErr) panic(ioErr)
} }
f.Content = string(fileContent) f.Content = string(fileContent)
f.Sha256 = fmt.Sprintf("%x", sha256.Sum256(fileContent))
case SymbolicLinkFile: case SymbolicLinkFile:
linkTarget, pathErr := os.Readlink(f.Path) linkTarget, pathErr := os.Readlink(f.Path)
if pathErr != nil { if pathErr != nil {

View File

@ -9,11 +9,11 @@ import (
"errors" "errors"
"fmt" "fmt"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
_ "io" "io"
"net/url" "net/url"
"os/exec" "os/exec"
"regexp" "regexp"
_ "strconv" _ "strconv"
"strings" "strings"
) )
@ -159,8 +159,14 @@ func (n *NetworkRoute) Apply() error {
return nil return nil
} }
func (n *NetworkRoute) LoadDecl(yamlNetworkRouteResourceDeclaration string) error { func (n *NetworkRoute) Load(r io.Reader) error {
return YamlLoadDecl(yamlNetworkRouteResourceDeclaration, n) c := NewYAMLDecoder(r)
return c.Decode(n)
}
func (n *NetworkRoute) LoadDecl(yamlResourceDeclaration string) error {
c := NewYAMLStringDecoder(yamlResourceDeclaration)
return c.Decode(n)
} }
func (n *NetworkRoute) ResolveId(ctx context.Context) string { func (n *NetworkRoute) ResolveId(ctx context.Context) string {

View File

@ -200,6 +200,7 @@ func (p *PackageType) NewCRUD() (create *Command, read *Command, update *Command
case PackageTypeRpm: case PackageTypeRpm:
case PackageTypePip: case PackageTypePip:
case PackageTypeYum: case PackageTypeYum:
default:
} }
return nil, nil, nil, nil return nil, nil, nil, nil
} }

View File

@ -53,3 +53,14 @@ func NewResource(uri string) Resource {
} }
return nil return nil
} }
/*
func Machine() {
// start_destroy -> absent -> start_create -> present -> start_destroy
stater := machine.New("absent")
stater.AddStates("absent", "start_create", "present", "start_delete")
stater.AddTransition("creating", "absent", "start_create")
stater.AddTransition("created", "start_create", "present")
stater.AddTransition("deleting", "present", "start_delete")
stater.AddTransition("deleted", "start_delete", "absent")
}
*/

View File

@ -6,7 +6,9 @@
"required": [ "path", "filetype" ], "required": [ "path", "filetype" ],
"properties": { "properties": {
"path": { "path": {
"type": "string" "type": "string",
"description": "file path",
"minLength": 1
}, },
"owner": { "owner": {
"type": "string" "type": "string"

View File

@ -51,7 +51,7 @@ func (d *DeclFile) Type() string { return "decl" }
func (d *DeclFile) ExtractResources(filter ResourceSelector) ([]*resource.Document, error) { func (d *DeclFile) ExtractResources(filter ResourceSelector) ([]*resource.Document, error) {
documents := make([]*resource.Document, 0, 100) documents := make([]*resource.Document, 0, 100)
documents = append(documents, resource.NewDocument()) //documents = append(documents, resource.NewDocument())
GzipFileName := regexp.MustCompile(`^.*\.gz$`) GzipFileName := regexp.MustCompile(`^.*\.gz$`)
@ -72,28 +72,22 @@ func (d *DeclFile) ExtractResources(filter ResourceSelector) ([]*resource.Docume
fileReader = file fileReader = file
} }
decoder := resource.NewYAMLDecoder(fileReader) decoder := resource.NewYAMLDecoder(fileReader)
slog.Info("ExtractResources()", "documents", documents)
index := 0 index := 0
for { for {
doc := documents[index] doc := resource.NewDocument()
e := decoder.Decode(doc) e := decoder.Decode(doc)
if errors.Is(e, io.EOF) { if errors.Is(e, io.EOF) {
if len(documents) > 1 {
documents[index] = nil
}
break break
} }
if e != nil { if e != nil {
return documents, e return documents, e
} }
slog.Info("ExtractResources()", "res", doc.ResourceDecls[0].Attributes)
if validationErr := doc.Validate(); validationErr != nil { if validationErr := doc.Validate(); validationErr != nil {
return documents, validationErr return documents, validationErr
} }
/* documents = append(documents, doc)
if applyErr := doc.Apply(); applyErr != nil {
return documents, applyErr
}
*/
documents = append(documents, resource.NewDocument())
index++ index++
} }
return documents, nil return documents, nil

View File

@ -5,7 +5,7 @@ package source
import ( import (
_ "context" _ "context"
_ "encoding/json" _ "encoding/json"
_ "fmt" "fmt"
_ "gopkg.in/yaml.v3" _ "gopkg.in/yaml.v3"
"net/url" "net/url"
"net/http" "net/http"
@ -47,6 +47,17 @@ func (h *HTTP) ExtractResources(filter ResourceSelector) ([]*resource.Document,
} }
defer resp.Body.Close() defer resp.Body.Close()
documentSignature := resp.Header.Get("Signature") documentSignature := resp.Header.Get("Signature")
if documentSignature == "" {
signatureResp, signatureErr := http.Get(fmt.Sprintf("%s.sig", h.Endpoint))
if signatureErr == nil {
defer signatureResp.Body.Close()
readSignatureBody, readSignatureErr := io.ReadAll(resp.Body)
if readSignatureErr == nil {
documentSignature = string(readSignatureBody)
}
}
}
hash := sha256.New() hash := sha256.New()
sumReadData := iofilter.NewReader(resp.Body, func(p []byte, readn int, readerr error) (n int, err error) { sumReadData := iofilter.NewReader(resp.Body, func(p []byte, readn int, readerr error) (n int, err error) {
hash.Write(p) hash.Write(p)