separate Store from State

Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
This commit is contained in:
Andrea Luzzardi 2021-03-24 18:07:52 -07:00 committed by Solomon Hykes
parent cba524eb0f
commit 43956e38cc
7 changed files with 145 additions and 140 deletions

View File

@ -42,7 +42,7 @@ var computeCmd = &cobra.Command{
for _, input := range viper.GetStringSlice("input-string") { for _, input := range viper.GetStringSlice("input-string") {
parts := strings.SplitN(input, "=", 2) parts := strings.SplitN(input, "=", 2)
k, v := parts[0], parts[1] k, v := parts[0], parts[1]
err := st.AddInput(ctx, k, dagger.TextInput(v)) err := st.AddInput(k, dagger.TextInput(v))
if err != nil { if err != nil {
lg.Fatal().Err(err).Str("input", k).Msg("failed to add input") lg.Fatal().Err(err).Str("input", k).Msg("failed to add input")
} }
@ -51,7 +51,7 @@ var computeCmd = &cobra.Command{
for _, input := range viper.GetStringSlice("input-dir") { for _, input := range viper.GetStringSlice("input-dir") {
parts := strings.SplitN(input, "=", 2) parts := strings.SplitN(input, "=", 2)
k, v := parts[0], parts[1] k, v := parts[0], parts[1]
err := st.AddInput(ctx, k, dagger.DirInput(v, []string{})) err := st.AddInput(k, dagger.DirInput(v, []string{}))
if err != nil { if err != nil {
lg.Fatal().Err(err).Str("input", k).Msg("failed to add input") lg.Fatal().Err(err).Str("input", k).Msg("failed to add input")
} }
@ -60,7 +60,7 @@ var computeCmd = &cobra.Command{
for _, input := range viper.GetStringSlice("input-git") { for _, input := range viper.GetStringSlice("input-git") {
parts := strings.SplitN(input, "=", 2) parts := strings.SplitN(input, "=", 2)
k, v := parts[0], parts[1] k, v := parts[0], parts[1]
err := st.AddInput(ctx, k, dagger.GitInput(v, "", "")) err := st.AddInput(k, dagger.GitInput(v, "", ""))
if err != nil { if err != nil {
lg.Fatal().Err(err).Str("input", k).Msg("failed to add input") lg.Fatal().Err(err).Str("input", k).Msg("failed to add input")
} }
@ -87,7 +87,7 @@ var computeCmd = &cobra.Command{
lg.Fatal().Msg("invalid json") lg.Fatal().Msg("invalid json")
} }
err = st.AddInput(ctx, "", dagger.JSONInput(string(content))) err = st.AddInput("", dagger.JSONInput(string(content)))
if err != nil { if err != nil {
lg.Fatal().Err(err).Msg("failed to add input") lg.Fatal().Err(err).Msg("failed to add input")
} }
@ -110,7 +110,7 @@ var computeCmd = &cobra.Command{
content = plaintext content = plaintext
} }
err = st.AddInput(ctx, "", dagger.YAMLInput(string(content))) err = st.AddInput("", dagger.YAMLInput(string(content)))
if err != nil { if err != nil {
lg.Fatal().Err(err).Msg("failed to add input") lg.Fatal().Err(err).Msg("failed to add input")
} }

View File

@ -26,7 +26,7 @@ var downCmd = &cobra.Command{
ctx := lg.WithContext(cmd.Context()) ctx := lg.WithContext(cmd.Context())
routeName := getRouteName(lg, cmd) routeName := getRouteName(lg, cmd)
route, err := dagger.LookupRoute(routeName, nil) route, err := dagger.LookupRoute(ctx, routeName, nil)
if err != nil { if err != nil {
lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route") lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route")
} }

View File

@ -27,7 +27,7 @@ var queryCmd = &cobra.Command{
ctx := lg.WithContext(cmd.Context()) ctx := lg.WithContext(cmd.Context())
routeName := getRouteName(lg, cmd) routeName := getRouteName(lg, cmd)
route, err := dagger.LookupRoute(routeName, nil) route, err := dagger.LookupRoute(ctx, routeName, nil)
if err != nil { if err != nil {
lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route") lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route")
} }

View File

@ -26,7 +26,7 @@ var upCmd = &cobra.Command{
ctx := lg.WithContext(cmd.Context()) ctx := lg.WithContext(cmd.Context())
routeName := getRouteName(lg, cmd) routeName := getRouteName(lg, cmd)
route, err := dagger.LookupRoute(routeName, nil) route, err := dagger.LookupRoute(ctx, routeName, nil)
if err != nil { if err != nil {
lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route") lg.Fatal().Err(err).Str("route-name", routeName).Msg("failed to lookup route")
} }

View File

@ -19,6 +19,40 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
// Contents of a route serialized to a file
type RouteState struct {
// Globally unique route ID
ID string `json:"id,omitempty"`
// Human-friendly route name.
// A route may have more than one name.
// FIXME: store multiple names?
Name string `json:"name,omitempty"`
// Cue module containing the route layout
// The input's top-level artifact is used as a module directory.
LayoutSource Input `json:"layout,omitempty"`
Inputs []inputKV `json:"inputs,omitempty"`
}
type inputKV struct {
Key string `json:"key,omitempty"`
Value Input `json:"value,omitempty"`
}
func (r *RouteState) AddInput(key string, value Input) error {
r.Inputs = append(r.Inputs, inputKV{Key: key, Value: value})
return nil
}
// Remove all inputs at the given key, including sub-keys.
// For example RemoveInputs("foo.bar") will remove all inputs
// at foo.bar, foo.bar.baz, etc.
func (r *RouteState) RemoveInputs(key string) error {
panic("NOT IMPLEMENTED")
}
type Route struct { type Route struct {
st *RouteState st *RouteState

View File

@ -1,132 +0,0 @@
package dagger
import (
"context"
"encoding/json"
"errors"
"os"
"path"
"github.com/google/uuid"
)
const (
routeLocation = "$HOME/.config/dagger/routes"
)
// Contents of a route serialized to a file
type RouteState struct {
// Globally unique route ID
ID string `json:"id,omitempty"`
// Human-friendly route name.
// A route may have more than one name.
// FIXME: store multiple names?
Name string `json:"name,omitempty"`
// Cue module containing the route layout
// The input's top-level artifact is used as a module directory.
LayoutSource Input `json:"layout,omitempty"`
Inputs []inputKV `json:"inputs,omitempty"`
}
type inputKV struct {
Key string `json:"key,omitempty"`
Value Input `json:"value,omitempty"`
}
func (r *RouteState) SetLayoutSource(ctx context.Context, src Input) error {
r.LayoutSource = src
return nil
}
func (r *RouteState) AddInput(ctx context.Context, key string, value Input) error {
r.Inputs = append(r.Inputs, inputKV{Key: key, Value: value})
return nil
}
// Remove all inputs at the given key, including sub-keys.
// For example RemoveInputs("foo.bar") will remove all inputs
// at foo.bar, foo.bar.baz, etc.
func (r *RouteState) RemoveInputs(ctx context.Context, key string) error {
panic("NOT IMPLEMENTED")
}
func routePath(name string) string {
return path.Join(os.ExpandEnv(routeLocation), name+".json")
}
func syncRoute(r *Route) error {
p := routePath(r.st.Name)
if err := os.MkdirAll(path.Dir(p), 0755); err != nil {
return err
}
data, err := json.MarshalIndent(r.st, "", " ")
if err != nil {
return err
}
return os.WriteFile(p, data, 0644)
}
func loadRoute(name string) (*RouteState, error) {
data, err := os.ReadFile(routePath(name))
if err != nil {
return nil, err
}
var st *RouteState
if err := json.Unmarshal(data, st); err != nil {
return nil, err
}
return st, nil
}
func CreateRoute(ctx context.Context, name string, o *CreateOpts) (*Route, error) {
r, err := LookupRoute(name, &LookupOpts{})
if err != nil && !errors.Is(err, os.ErrNotExist) {
return nil, err
}
if r != nil {
return nil, os.ErrExist
}
r, err = NewRoute(
&RouteState{
ID: uuid.New().String(),
Name: name,
},
)
if err != nil {
return nil, err
}
return r, syncRoute(r)
}
type CreateOpts struct{}
func DeleteRoute(ctx context.Context, o *DeleteOpts) (*Route, error) {
panic("NOT IMPLEMENTED")
}
type DeleteOpts struct{}
func LookupRoute(name string, o *LookupOpts) (*Route, error) {
st, err := loadRoute(name)
if err != nil {
return nil, err
}
return &Route{
st: st,
}, nil
}
type LookupOpts struct{}
func LoadRoute(ctx context.Context, id string, o *LoadOpts) (*Route, error) {
panic("NOT IMPLEMENTED")
}
type LoadOpts struct{}

103
dagger/store.go Normal file
View File

@ -0,0 +1,103 @@
package dagger
import (
"context"
"encoding/json"
"errors"
"os"
"path"
"github.com/google/uuid"
)
const (
storeLocation = "$HOME/.config/dagger/routes"
)
type CreateOpts struct{}
func CreateRoute(ctx context.Context, name string, o *CreateOpts) (*Route, error) {
r, err := LookupRoute(ctx, name, &LookupOpts{})
if err != nil && !errors.Is(err, os.ErrNotExist) {
return nil, err
}
if r != nil {
return nil, os.ErrExist
}
r, err = NewRoute(
&RouteState{
ID: uuid.New().String(),
Name: name,
},
)
if err != nil {
return nil, err
}
return r, syncRoute(r)
}
type UpdateOpts struct{}
func UpdateRoute(ctx context.Context, r *Route, o *UpdateOpts) error {
return syncRoute(r)
}
type DeleteOpts struct{}
func DeleteRoute(ctx context.Context, r *Route, o *DeleteOpts) error {
return deleteRoute(r)
}
type LookupOpts struct{}
func LookupRoute(ctx context.Context, name string, o *LookupOpts) (*Route, error) {
st, err := loadRoute(name)
if err != nil {
return nil, err
}
return &Route{
st: st,
}, nil
}
type LoadOpts struct{}
func LoadRoute(ctx context.Context, id string, o *LoadOpts) (*Route, error) {
panic("NOT IMPLEMENTED")
}
func routePath(name string) string {
return path.Join(os.ExpandEnv(storeLocation), name+".json")
}
func syncRoute(r *Route) error {
p := routePath(r.st.Name)
if err := os.MkdirAll(path.Dir(p), 0755); err != nil {
return err
}
data, err := json.MarshalIndent(r.st, "", " ")
if err != nil {
return err
}
return os.WriteFile(p, data, 0644)
}
func deleteRoute(r *Route) error {
return os.Remove(routePath(r.st.Name))
}
func loadRoute(name string) (*RouteState, error) {
data, err := os.ReadFile(routePath(name))
if err != nil {
return nil, err
}
var st *RouteState
if err := json.Unmarshal(data, st); err != nil {
return nil, err
}
return st, nil
}