Compare commits
4 commits
b0f8adef2a
...
f0e27192c8
| Author | SHA1 | Date | |
|---|---|---|---|
| f0e27192c8 | |||
| 6480101484 | |||
| 42c8fd7c1a | |||
| dc6a141ca1 |
10 changed files with 155 additions and 22 deletions
|
|
@ -38,7 +38,7 @@ Start the server. The `--init` flag with create the default files and directory
|
||||||
makeshift serve --root $HOME/apps/makeshift/server --init
|
makeshift serve --root $HOME/apps/makeshift/server --init
|
||||||
```
|
```
|
||||||
|
|
||||||
From here, you might want to see what files are available by default.
|
From here, you might want to see what files, plugins, and profiles that are available by default.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# list the files in the root directory
|
# list the files in the root directory
|
||||||
|
|
@ -60,7 +60,7 @@ makeshift list profiles
|
||||||
makeshift list profiles default
|
makeshift list profiles default
|
||||||
```
|
```
|
||||||
|
|
||||||
Then, we can start downloading some files or directories (as archives).
|
Then, we can start downloading some files or directories (as archives) both with and without running plugins.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# download all data (notice --host and --port are not set here)
|
# download all data (notice --host and --port are not set here)
|
||||||
|
|
@ -158,7 +158,7 @@ type Example struct{}
|
||||||
func (p *Example) Name() string { return "example" }
|
func (p *Example) Name() string { return "example" }
|
||||||
func (p *Example) Version() string { return "v0.0.1-alpha" }
|
func (p *Example) Version() string { return "v0.0.1-alpha" }
|
||||||
func (p *Example) Description() string { return "An example plugin" }
|
func (p *Example) Description() string { return "An example plugin" }
|
||||||
func (p *Example) Metadata() map[string]string {
|
func (p *Example) Metadata() map[string]any {
|
||||||
return makeshift.Metadata{
|
return makeshift.Metadata{
|
||||||
"author": map[string]any{
|
"author": map[string]any{
|
||||||
"name": "John Smith",
|
"name": "John Smith",
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,16 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.towk2.me/towk/makeshift/internal/archive"
|
"git.towk2.me/towk/makeshift/internal/archive"
|
||||||
|
"git.towk2.me/towk/makeshift/internal/kwargs"
|
||||||
"git.towk2.me/towk/makeshift/pkg/client"
|
"git.towk2.me/towk/makeshift/pkg/client"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
pluginArgs []string
|
||||||
|
pluginKWArgs kwargs.KWArgs = kwargs.KWArgs{}
|
||||||
|
)
|
||||||
var downloadCmd = cobra.Command{
|
var downloadCmd = cobra.Command{
|
||||||
Use: "download",
|
Use: "download",
|
||||||
Example: `
|
Example: `
|
||||||
|
|
@ -64,6 +69,12 @@ var downloadCmd = cobra.Command{
|
||||||
if len(profileIDs) > 0 {
|
if len(profileIDs) > 0 {
|
||||||
query += "&profiles=" + url.QueryEscape(strings.Join(profileIDs, ","))
|
query += "&profiles=" + url.QueryEscape(strings.Join(profileIDs, ","))
|
||||||
}
|
}
|
||||||
|
if len(pluginArgs) > 0 {
|
||||||
|
query += "&args=" + url.QueryEscape(strings.Join(pluginArgs, ","))
|
||||||
|
}
|
||||||
|
if len(pluginKWArgs) > 0 {
|
||||||
|
query += "&kwargs=" + url.QueryEscape(pluginKWArgs.String())
|
||||||
|
}
|
||||||
|
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("host", host).
|
Str("host", host).
|
||||||
|
|
@ -287,6 +298,8 @@ func init() {
|
||||||
downloadCmd.Flags().StringP("path", "p", ".", "Set the path to list files (can be set with MAKESHIFT_PATH)")
|
downloadCmd.Flags().StringP("path", "p", ".", "Set the path to list files (can be set with MAKESHIFT_PATH)")
|
||||||
downloadCmd.Flags().StringSlice("profiles", []string{}, "Set the profile(s) to use to populate data store")
|
downloadCmd.Flags().StringSlice("profiles", []string{}, "Set the profile(s) to use to populate data store")
|
||||||
downloadCmd.Flags().StringSlice("plugins", []string{}, "Set the plugin(s) to run before downloading files")
|
downloadCmd.Flags().StringSlice("plugins", []string{}, "Set the plugin(s) to run before downloading files")
|
||||||
|
downloadCmd.Flags().StringSlice("plugin-args", []string{}, "Set the argument list to pass to plugin(s)")
|
||||||
|
downloadCmd.Flags().Var(&pluginKWArgs, "plugin-kwargs", "Set the argument map to pass to plugin(s)")
|
||||||
downloadCmd.Flags().BoolP("extract", "x", false, "Set whether to extract archive locally after downloading")
|
downloadCmd.Flags().BoolP("extract", "x", false, "Set whether to extract archive locally after downloading")
|
||||||
downloadCmd.Flags().BoolP("remove-archive", "r", false, "Set whether to remove the archive after extracting (used with '--extract' flag)")
|
downloadCmd.Flags().BoolP("remove-archive", "r", false, "Set whether to remove the archive after extracting (used with '--extract' flag)")
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,11 +36,11 @@ func (df DataFormat) Type() string {
|
||||||
return "DataFormat"
|
return "DataFormat"
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalData marshals arbitrary data into a byte slice formatted as outFormat.
|
// Marshal marshals arbitrary data into a byte slice formatted as outFormat.
|
||||||
// If a marshalling error occurs or outFormat is unknown, an error is returned.
|
// If a marshalling error occurs or outFormat is unknown, an error is returned.
|
||||||
//
|
//
|
||||||
// Supported values are: json, list, yaml
|
// Supported values are: json, list, yaml
|
||||||
func Marshal(data interface{}, outFormat DataFormat) ([]byte, error) {
|
func Marshal(data any, outFormat DataFormat) ([]byte, error) {
|
||||||
switch outFormat {
|
switch outFormat {
|
||||||
case JSON:
|
case JSON:
|
||||||
if bytes, err := json.MarshalIndent(data, "", " "); err != nil {
|
if bytes, err := json.MarshalIndent(data, "", " "); err != nil {
|
||||||
|
|
@ -61,12 +61,12 @@ func Marshal(data interface{}, outFormat DataFormat) ([]byte, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalData unmarshals a byte slice formatted as inFormat into an interface
|
// Unmarshal unmarshals a byte slice formatted as inFormat into an interface
|
||||||
// v. If an unmarshalling error occurs or inFormat is unknown, an error is
|
// v. If an unmarshalling error occurs or inFormat is unknown, an error is
|
||||||
// returned.
|
// returned.
|
||||||
//
|
//
|
||||||
// Supported values are: json, list, yaml
|
// Supported values are: json, list, yaml
|
||||||
func Unmarshal(data []byte, v interface{}, inFormat DataFormat) error {
|
func Unmarshal(data []byte, v any, inFormat DataFormat) error {
|
||||||
switch inFormat {
|
switch inFormat {
|
||||||
case JSON:
|
case JSON:
|
||||||
if err := json.Unmarshal(data, v); err != nil {
|
if err := json.Unmarshal(data, v); err != nil {
|
||||||
|
|
|
||||||
34
internal/kwargs/kwargs.go
Normal file
34
internal/kwargs/kwargs.go
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
package kwargs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.towk2.me/towk/makeshift/internal/format"
|
||||||
|
)
|
||||||
|
|
||||||
|
const RESERVED_KEY = "kwargs"
|
||||||
|
|
||||||
|
type KWArgs map[string]any
|
||||||
|
|
||||||
|
func (kw KWArgs) String() string {
|
||||||
|
b, _ := json.Marshal(kw)
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kw *KWArgs) Set(v string /* should be JSON object*/) error {
|
||||||
|
var (
|
||||||
|
newArgs KWArgs
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
err = format.Unmarshal([]byte(v), &newArgs, format.JSON)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to unmarshal value for %s: %w", kw.Type(), err)
|
||||||
|
}
|
||||||
|
*kw = newArgs
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (kw *KWArgs) Type() string {
|
||||||
|
return "KWArgs"
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,25 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "git.towk2.me/towk/makeshift/pkg/storage"
|
import (
|
||||||
|
makeshift "git.towk2.me/towk/makeshift/pkg"
|
||||||
|
"git.towk2.me/towk/makeshift/pkg/storage"
|
||||||
|
)
|
||||||
|
|
||||||
type Mapper struct{}
|
type Mapper struct{}
|
||||||
|
|
||||||
func (p *Mapper) Name() string { return "jinja2" }
|
func (p *Mapper) Name() string { return "mapper" }
|
||||||
func (p *Mapper) Version() string { return "test" }
|
func (p *Mapper) Version() string { return "v0.0.1-alpha" }
|
||||||
func (p *Mapper) Description() string { return "Renders Jinja 2 templates" }
|
func (p *Mapper) Description() string { return "Directly maps data to store" }
|
||||||
func (p *Mapper) Metadata() map[string]string {
|
func (p *Mapper) Metadata() makeshift.Metadata {
|
||||||
return map[string]string{
|
return makeshift.Metadata{
|
||||||
"author.name": "David J. Allen",
|
"author": map[string]any{
|
||||||
"author.email": "davidallendj@gmail.com",
|
"name": "David J. Allen",
|
||||||
|
"email": "davidallendj@gmail.com",
|
||||||
|
"links": []string{
|
||||||
|
"https://github.com/davidallendj",
|
||||||
|
"https://git.towk2.me/towk",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
36
pkg/plugins/user/user.go
Normal file
36
pkg/plugins/user/user.go
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
makeshift "git.towk2.me/towk/makeshift/pkg"
|
||||||
|
"git.towk2.me/towk/makeshift/pkg/storage"
|
||||||
|
)
|
||||||
|
|
||||||
|
type User struct{}
|
||||||
|
|
||||||
|
func (p *User) Name() string { return "user" }
|
||||||
|
func (p *User) Version() string { return "v0.0.1-alpha" }
|
||||||
|
func (p *User) Description() string { return "Get user information" }
|
||||||
|
func (p *User) Metadata() makeshift.Metadata {
|
||||||
|
return makeshift.Metadata{
|
||||||
|
"author": map[string]any{
|
||||||
|
"name": "David J. Allen",
|
||||||
|
"email": "davidallendj@gmail.com",
|
||||||
|
"links": []string{
|
||||||
|
"https://github.com/davidallendj",
|
||||||
|
"https://git.towk2.me/towk",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *User) Init() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *User) Run(store storage.KVStore, args []string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *User) Cleanup() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -11,8 +11,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"git.towk2.me/towk/makeshift/internal/archive"
|
"git.towk2.me/towk/makeshift/internal/archive"
|
||||||
|
"git.towk2.me/towk/makeshift/internal/kwargs"
|
||||||
makeshift "git.towk2.me/towk/makeshift/pkg"
|
makeshift "git.towk2.me/towk/makeshift/pkg"
|
||||||
"git.towk2.me/towk/makeshift/pkg/storage"
|
"git.towk2.me/towk/makeshift/pkg/storage"
|
||||||
|
"github.com/go-chi/chi/v5"
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -20,9 +22,12 @@ func (s *Service) Download() http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
var (
|
var (
|
||||||
path = s.PathForData() + strings.TrimPrefix(r.URL.Path, "/download")
|
path = s.PathForData() + strings.TrimPrefix(r.URL.Path, "/download")
|
||||||
|
pluginKWArgs = chi.URLParam(r, "kwargs")
|
||||||
|
pluginArgs = strings.Split(r.URL.Query().Get("args"), ",")
|
||||||
pluginNames = strings.Split(r.URL.Query().Get("plugins"), ",")
|
pluginNames = strings.Split(r.URL.Query().Get("plugins"), ",")
|
||||||
profileIDs = strings.Split(r.URL.Query().Get("profiles"), ",")
|
profileIDs = strings.Split(r.URL.Query().Get("profiles"), ",")
|
||||||
|
|
||||||
|
kw *kwargs.KWArgs
|
||||||
fileInfo os.FileInfo
|
fileInfo os.FileInfo
|
||||||
out *os.File
|
out *os.File
|
||||||
store *storage.MemoryStorage = new(storage.MemoryStorage)
|
store *storage.MemoryStorage = new(storage.MemoryStorage)
|
||||||
|
|
@ -32,8 +37,12 @@ func (s *Service) Download() http.HandlerFunc {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// parse the KWArgs from request
|
||||||
|
kw.Set(pluginKWArgs)
|
||||||
|
|
||||||
// initialize storage
|
// initialize storage
|
||||||
store.Init()
|
store.Init()
|
||||||
|
store.SetKWArgs(kw)
|
||||||
|
|
||||||
log.Debug().
|
log.Debug().
|
||||||
Str("path", path).
|
Str("path", path).
|
||||||
|
|
@ -78,7 +87,7 @@ func (s *Service) Download() http.HandlerFunc {
|
||||||
log.Debug().Strs("files", filenamesToArchive).Send()
|
log.Debug().Strs("files", filenamesToArchive).Send()
|
||||||
|
|
||||||
// prepare plugins
|
// prepare plugins
|
||||||
hooks, errs = s.loadPlugins(pluginNames, store, nil, errs)
|
hooks, errs = s.loadPlugins(pluginNames, store, pluginArgs, errs)
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
log.Error().Errs("errs", errs).Msg("errors occurred loading plugins")
|
log.Error().Errs("errs", errs).Msg("errors occurred loading plugins")
|
||||||
errs = []error{}
|
errs = []error{}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
|
import "git.towk2.me/towk/makeshift/internal/kwargs"
|
||||||
|
|
||||||
type DiskStorage struct{}
|
type DiskStorage struct{}
|
||||||
|
|
||||||
func (ds DiskStorage) Init() error {
|
func (ds DiskStorage) Init() error {
|
||||||
|
|
@ -10,8 +12,17 @@ func (ds DiskStorage) Cleanup() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds DiskStorage) Get(k string) error {
|
func (ds *DiskStorage) SetKWArgs(kw *kwargs.KWArgs) error {
|
||||||
return nil
|
return ds.Set(kwargs.RESERVED_KEY, kw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds *DiskStorage) GetKWArgs() (*kwargs.KWArgs, error) {
|
||||||
|
kw, err := ds.Get(kwargs.RESERVED_KEY)
|
||||||
|
return kw.(*kwargs.KWArgs), err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ds DiskStorage) Get(k string) (any, error) {
|
||||||
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ds DiskStorage) Set(k string, v any) error {
|
func (ds DiskStorage) Set(k string, v any) error {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"git.towk2.me/towk/makeshift/internal/kwargs"
|
||||||
|
)
|
||||||
|
|
||||||
type MemoryStorage struct {
|
type MemoryStorage struct {
|
||||||
Data map[string]any `json:"data"`
|
Data map[string]any `json:"data"`
|
||||||
|
|
@ -15,6 +19,15 @@ func (ms *MemoryStorage) Cleanup() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ms *MemoryStorage) SetKWArgs(kw *kwargs.KWArgs) error {
|
||||||
|
return ms.Set(kwargs.RESERVED_KEY, kw)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ms *MemoryStorage) GetKWArgs() (*kwargs.KWArgs, error) {
|
||||||
|
kw, err := ms.Get(kwargs.RESERVED_KEY)
|
||||||
|
return kw.(*kwargs.KWArgs), err
|
||||||
|
}
|
||||||
|
|
||||||
func (ms *MemoryStorage) Get(k string) (any, error) {
|
func (ms *MemoryStorage) Get(k string) (any, error) {
|
||||||
v, ok := ms.Data[k]
|
v, ok := ms.Data[k]
|
||||||
if ok {
|
if ok {
|
||||||
|
|
@ -24,6 +37,9 @@ func (ms *MemoryStorage) Get(k string) (any, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ms *MemoryStorage) Set(k string, v any) error {
|
func (ms *MemoryStorage) Set(k string, v any) error {
|
||||||
|
if k == "kwargs" {
|
||||||
|
return fmt.Errorf("cannot set reserved key '%s' (use SetKWArgs() instead)", k)
|
||||||
|
}
|
||||||
ms.Data[k] = v
|
ms.Data[k] = v
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
|
import "git.towk2.me/towk/makeshift/internal/kwargs"
|
||||||
|
|
||||||
type KVStore interface {
|
type KVStore interface {
|
||||||
Init() error
|
Init() error
|
||||||
Cleanup() error
|
Cleanup() error
|
||||||
|
|
||||||
|
SetKWArgs(kwargs *kwargs.KWArgs) error
|
||||||
|
GetKWArgs() (*kwargs.KWArgs, error)
|
||||||
|
|
||||||
Get(k string) (any, error)
|
Get(k string) (any, error)
|
||||||
Set(k string, v any) error
|
Set(k string, v any) error
|
||||||
GetData() any
|
GetData() any
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue