2024-04-18 00:07:12 +00:00
|
|
|
// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
|
|
|
|
|
|
|
|
package source
|
|
|
|
|
|
|
|
import (
|
|
|
|
_ "context"
|
|
|
|
_ "encoding/json"
|
|
|
|
_ "fmt"
|
|
|
|
_ "gopkg.in/yaml.v3"
|
|
|
|
"net/url"
|
|
|
|
"regexp"
|
|
|
|
_ "strings"
|
|
|
|
"os"
|
|
|
|
"io"
|
|
|
|
"compress/gzip"
|
|
|
|
"archive/tar"
|
|
|
|
"errors"
|
|
|
|
"path/filepath"
|
|
|
|
"decl/internal/resource"
|
2024-05-14 18:26:05 +00:00
|
|
|
"decl/internal/codec"
|
2024-04-18 00:07:12 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type ResourceSelector func(r resource.Resource) bool
|
|
|
|
|
|
|
|
type DocSource interface {
|
|
|
|
Type() string
|
|
|
|
|
|
|
|
ExtractResources(filter ResourceSelector) ([]*resource.Document, error)
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewDocSource(uri string) DocSource {
|
|
|
|
s, e := SourceTypes.New(uri)
|
|
|
|
if e == nil {
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func ExtractResources(uri string, filter ResourceSelector) ([]*resource.Document, error) {
|
|
|
|
documents := make([]*resource.Document, 0, 100)
|
|
|
|
d := resource.NewDocument()
|
|
|
|
documents = append(documents, d)
|
|
|
|
|
|
|
|
TarGzipFileName := regexp.MustCompile(`^.*\.(tar\.gz|tgz)$`)
|
|
|
|
TarFileName := regexp.MustCompile(`^.*\.tar$`)
|
|
|
|
|
|
|
|
u,e := url.Parse(uri)
|
|
|
|
if e != nil {
|
|
|
|
return nil, e
|
|
|
|
}
|
|
|
|
switch u.Scheme {
|
|
|
|
case "file":
|
|
|
|
fileAbsolutePath, _ := filepath.Abs(filepath.Join(u.Hostname(), u.RequestURI()))
|
|
|
|
file, fileErr := os.Open(fileAbsolutePath)
|
|
|
|
if fileErr != nil {
|
|
|
|
return documents, fileErr
|
|
|
|
}
|
|
|
|
var gzipReader io.Reader
|
|
|
|
switch u.Path {
|
|
|
|
case TarGzipFileName.FindString(u.Path):
|
|
|
|
zr, err := gzip.NewReader(file)
|
|
|
|
if err != nil {
|
|
|
|
return documents, err
|
|
|
|
}
|
|
|
|
gzipReader = zr
|
|
|
|
fallthrough
|
|
|
|
case TarFileName.FindString(u.Path):
|
|
|
|
var fileReader io.Reader
|
|
|
|
if gzipReader == nil {
|
|
|
|
fileReader = file
|
|
|
|
} else {
|
|
|
|
fileReader = gzipReader
|
|
|
|
}
|
|
|
|
tarReader := tar.NewReader(fileReader)
|
|
|
|
for {
|
|
|
|
hdr, err := tarReader.Next()
|
|
|
|
if err == io.EOF {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return documents, err
|
|
|
|
}
|
|
|
|
f := resource.NewFile()
|
|
|
|
if fiErr := f.UpdateAttributesFromFileInfo(hdr.FileInfo()); fiErr != nil {
|
|
|
|
return documents, fiErr
|
|
|
|
}
|
|
|
|
readFileData, readErr := io.ReadAll(tarReader)
|
|
|
|
if readErr != nil {
|
|
|
|
return documents, readErr
|
|
|
|
}
|
|
|
|
f.Content = string(readFileData)
|
|
|
|
d.AddResourceDeclaration("file", f)
|
|
|
|
}
|
|
|
|
default:
|
2024-05-14 18:26:05 +00:00
|
|
|
decoder := codec.NewYAMLDecoder(file)
|
2024-04-18 00:07:12 +00:00
|
|
|
index := 0
|
|
|
|
for {
|
|
|
|
doc := documents[index]
|
|
|
|
e := decoder.Decode(doc)
|
|
|
|
if errors.Is(e, io.EOF) {
|
|
|
|
if len(documents) > 1 {
|
|
|
|
documents[index] = nil
|
|
|
|
}
|
|
|
|
break
|
|
|
|
}
|
|
|
|
if e != nil {
|
|
|
|
return documents, e
|
|
|
|
}
|
|
|
|
if validationErr := doc.Validate(); validationErr != nil {
|
|
|
|
return documents, validationErr
|
|
|
|
}
|
|
|
|
if applyErr := doc.Apply(); applyErr != nil {
|
|
|
|
return documents, applyErr
|
|
|
|
}
|
|
|
|
documents = append(documents, resource.NewDocument())
|
|
|
|
index++
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return documents, nil
|
|
|
|
}
|