terminology: rename route -> deployment
Signed-off-by: Andrea Luzzardi <aluzzardi@gmail.com>
This commit is contained in:
parent
e503e12cff
commit
f901918266
@ -10,35 +10,35 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
// getCurrentRoute returns the current selected route based on its abs path
|
// GetCurrentDeployment returns the current selected deployment based on its abs path
|
||||||
func GetCurrentRoute(ctx context.Context, store *dagger.Store) *dagger.Route {
|
func GetCurrentDeployment(ctx context.Context, store *dagger.Store) *dagger.Deployment {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
st := GetCurrentRouteState(ctx, store)
|
st := GetCurrentDeploymentState(ctx, store)
|
||||||
|
|
||||||
route, err := dagger.NewRoute(st)
|
deployment, err := dagger.NewDeployment(st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Interface("routeState", st).
|
Interface("deploymentState", st).
|
||||||
Msg("failed to init route")
|
Msg("failed to init deployment")
|
||||||
}
|
}
|
||||||
|
|
||||||
return route
|
return deployment
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCurrentRouteState(ctx context.Context, store *dagger.Store) *dagger.RouteState {
|
func GetCurrentDeploymentState(ctx context.Context, store *dagger.Store) *dagger.DeploymentState {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
routeName := viper.GetString("route")
|
deploymentName := viper.GetString("deployment")
|
||||||
if routeName != "" {
|
if deploymentName != "" {
|
||||||
st, err := store.LookupRouteByName(ctx, routeName)
|
st, err := store.LookupDeploymentByName(ctx, deploymentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("routeName", routeName).
|
Str("deploymentName", deploymentName).
|
||||||
Msg("failed to lookup route by name")
|
Msg("failed to lookup deployment by name")
|
||||||
}
|
}
|
||||||
return st
|
return st
|
||||||
}
|
}
|
||||||
@ -47,25 +47,25 @@ func GetCurrentRouteState(ctx context.Context, store *dagger.Store) *dagger.Rout
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("cannot get current working directory")
|
lg.Fatal().Err(err).Msg("cannot get current working directory")
|
||||||
}
|
}
|
||||||
st, err := store.LookupRouteByPath(ctx, wd)
|
st, err := store.LookupDeploymentByPath(ctx, wd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("routePath", wd).
|
Str("deploymentPath", wd).
|
||||||
Msg("failed to lookup route by path")
|
Msg("failed to lookup deployment by path")
|
||||||
}
|
}
|
||||||
return st
|
return st
|
||||||
}
|
}
|
||||||
|
|
||||||
func RouteUp(ctx context.Context, route *dagger.Route) {
|
func DeploymentUp(ctx context.Context, deployment *dagger.Deployment) {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
c, err := dagger.NewClient(ctx, "")
|
c, err := dagger.NewClient(ctx, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("unable to create client")
|
lg.Fatal().Err(err).Msg("unable to create client")
|
||||||
}
|
}
|
||||||
output, err := c.Up(ctx, route)
|
output, err := c.Up(ctx, deployment)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to compute")
|
lg.Fatal().Err(err).Msg("failed to compute")
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ var computeCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
st := &dagger.RouteState{
|
st := &dagger.DeploymentState{
|
||||||
ID: uuid.New().String(),
|
ID: uuid.New().String(),
|
||||||
Name: "FIXME",
|
Name: "FIXME",
|
||||||
LayoutSource: dagger.DirInput(args[0], []string{"*.cue", "cue.mod"}),
|
LayoutSource: dagger.DirInput(args[0], []string{"*.cue", "cue.mod"}),
|
||||||
@ -127,12 +127,12 @@ var computeCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
route, err := dagger.NewRoute(st)
|
deployment, err := dagger.NewDeployment(st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("unable to initialize route")
|
lg.Fatal().Err(err).Msg("unable to initialize deployment")
|
||||||
}
|
}
|
||||||
|
|
||||||
common.RouteUp(ctx, route)
|
common.DeploymentUp(ctx, deployment)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
var deleteCmd = &cobra.Command{
|
var deleteCmd = &cobra.Command{
|
||||||
Use: "delete",
|
Use: "delete",
|
||||||
Short: "Delete a route after taking it offline (WARNING: may destroy infrastructure)",
|
Short: "Delete a deployment after taking it offline (WARNING: may destroy infrastructure)",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
// Fix Viper bug for duplicate flags:
|
// Fix Viper bug for duplicate flags:
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
var downCmd = &cobra.Command{
|
var downCmd = &cobra.Command{
|
||||||
Use: "down",
|
Use: "down",
|
||||||
Short: "Take a route offline (WARNING: may destroy infrastructure)",
|
Short: "Take a deployment offline (WARNING: may destroy infrastructure)",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
// Fix Viper bug for duplicate flags:
|
// Fix Viper bug for duplicate flags:
|
||||||
@ -29,16 +29,16 @@ var downCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
route := common.GetCurrentRoute(ctx, store)
|
deployment := common.GetCurrentDeployment(ctx, store)
|
||||||
|
|
||||||
// TODO: Implement options: --no-cache
|
// TODO: Implement options: --no-cache
|
||||||
if err := route.Down(ctx, nil); err != nil {
|
if err := deployment.Down(ctx, nil); err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("routeName", route.Name()).
|
Str("deploymentName", deployment.Name()).
|
||||||
Str("routeId", route.ID()).
|
Str("deploymentId", deployment.ID()).
|
||||||
Msg("failed to up the route")
|
Msg("failed to up the deployment")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
var historyCmd = &cobra.Command{
|
var historyCmd = &cobra.Command{
|
||||||
Use: "history",
|
Use: "history",
|
||||||
Short: "List past changes to a route",
|
Short: "List past changes to a deployment",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
// Fix Viper bug for duplicate flags:
|
// Fix Viper bug for duplicate flags:
|
||||||
|
@ -22,7 +22,7 @@ var containerCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
updateRouteInput(ctx, args[0], dagger.DockerInput(args[1]))
|
updateDeploymentInput(ctx, args[0], dagger.DockerInput(args[1]))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ var dirCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
updateRouteInput(ctx, args[0], dagger.DirInput(args[1], []string{}))
|
updateDeploymentInput(ctx, args[0], dagger.DirInput(args[1], []string{}))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ var gitCmd = &cobra.Command{
|
|||||||
subDir = args[3]
|
subDir = args[3]
|
||||||
}
|
}
|
||||||
|
|
||||||
updateRouteInput(ctx, args[0], dagger.GitInput(args[1], args[2], subDir))
|
updateDeploymentInput(ctx, args[0], dagger.GitInput(args[1], args[2], subDir))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import (
|
|||||||
// Cmd exposes the top-level command
|
// Cmd exposes the top-level command
|
||||||
var Cmd = &cobra.Command{
|
var Cmd = &cobra.Command{
|
||||||
Use: "input",
|
Use: "input",
|
||||||
Short: "Manage a route's inputs",
|
Short: "Manage a deployment's inputs",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -25,7 +25,7 @@ func init() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateRouteInput(ctx context.Context, target string, input dagger.Input) {
|
func updateDeploymentInput(ctx context.Context, target string, input dagger.Input) {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
store, err := dagger.DefaultStore()
|
store, err := dagger.DefaultStore()
|
||||||
@ -33,11 +33,11 @@ func updateRouteInput(ctx context.Context, target string, input dagger.Input) {
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
st := common.GetCurrentRouteState(ctx, store)
|
st := common.GetCurrentDeploymentState(ctx, store)
|
||||||
st.AddInput(target, input)
|
st.AddInput(target, input)
|
||||||
|
|
||||||
if err := store.UpdateRoute(ctx, st, nil); err != nil {
|
if err := store.UpdateDeployment(ctx, st, nil); err != nil {
|
||||||
lg.Fatal().Err(err).Str("routeId", st.ID).Str("routeName", st.Name).Msg("cannot update route")
|
lg.Fatal().Err(err).Str("deploymentId", st.ID).Str("deploymentName", st.Name).Msg("cannot update deployment")
|
||||||
}
|
}
|
||||||
lg.Info().Str("routeId", st.ID).Str("routeName", st.Name).Msg("updated route")
|
lg.Info().Str("deploymentId", st.ID).Str("deploymentName", st.Name).Msg("updated deployment")
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ var textCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
updateRouteInput(ctx, args[0], dagger.TextInput(args[1]))
|
updateDeploymentInput(ctx, args[0], dagger.TextInput(args[1]))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import "github.com/spf13/cobra"
|
|||||||
// Cmd exposes the top-level command
|
// Cmd exposes the top-level command
|
||||||
var Cmd = &cobra.Command{
|
var Cmd = &cobra.Command{
|
||||||
Use: "layout",
|
Use: "layout",
|
||||||
Short: "Manage a route's layout",
|
Short: "Manage a deployment's layout",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
var listCmd = &cobra.Command{
|
var listCmd = &cobra.Command{
|
||||||
Use: "list",
|
Use: "list",
|
||||||
Short: "List available routes",
|
Short: "List available deployments",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
// Fix Viper bug for duplicate flags:
|
// Fix Viper bug for duplicate flags:
|
||||||
@ -28,15 +28,15 @@ var listCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
routes, err := store.ListRoutes(ctx)
|
deployments, err := store.ListDeployments(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("cannot list routes")
|
Msg("cannot list deployments")
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, r := range routes {
|
for _, r := range deployments {
|
||||||
fmt.Println(r.Name)
|
fmt.Println(r.Name)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
var newCmd = &cobra.Command{
|
var newCmd = &cobra.Command{
|
||||||
Use: "new",
|
Use: "new",
|
||||||
Short: "Create a new route",
|
Short: "Create a new deployment",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
// Fix Viper bug for duplicate flags:
|
// Fix Viper bug for duplicate flags:
|
||||||
@ -33,41 +33,41 @@ var newCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
st := &dagger.RouteState{
|
st := &dagger.DeploymentState{
|
||||||
Name: getNewRouteName(ctx),
|
Name: getNewDeploymentName(ctx),
|
||||||
LayoutSource: getLayoutSource(ctx),
|
LayoutSource: getLayoutSource(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.CreateRoute(ctx, st)
|
err = store.CreateDeployment(ctx, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to create route")
|
lg.Fatal().Err(err).Msg("failed to create deployment")
|
||||||
}
|
}
|
||||||
lg.
|
lg.
|
||||||
Info().
|
Info().
|
||||||
Str("routeId", st.ID).
|
Str("deploymentId", st.ID).
|
||||||
Str("routeName", st.Name).
|
Str("deploymentName", st.Name).
|
||||||
Msg("route created")
|
Msg("deployment created")
|
||||||
|
|
||||||
route, err := dagger.NewRoute(st)
|
deployment, err := dagger.NewDeployment(st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("failed to initialize route")
|
Msg("failed to initialize deployment")
|
||||||
}
|
}
|
||||||
|
|
||||||
if viper.GetBool("up") {
|
if viper.GetBool("up") {
|
||||||
common.RouteUp(ctx, route)
|
common.DeploymentUp(ctx, deployment)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNewRouteName(ctx context.Context) string {
|
func getNewDeploymentName(ctx context.Context) string {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
routeName := viper.GetString("route")
|
deploymentName := viper.GetString("deployment")
|
||||||
if routeName != "" {
|
if deploymentName != "" {
|
||||||
return routeName
|
return deploymentName
|
||||||
}
|
}
|
||||||
|
|
||||||
workDir, err := os.Getwd()
|
workDir, err := os.Getwd()
|
||||||
@ -99,8 +99,8 @@ func getLayoutSource(ctx context.Context) dagger.Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
newCmd.Flags().StringP("name", "n", "", "Specify a route name")
|
newCmd.Flags().StringP("name", "n", "", "Specify a deployment name")
|
||||||
newCmd.Flags().BoolP("up", "u", false, "Bring the route online")
|
newCmd.Flags().BoolP("up", "u", false, "Bring the deployment online")
|
||||||
|
|
||||||
newCmd.Flags().String("layout-dir", "", "Load layout from a local directory")
|
newCmd.Flags().String("layout-dir", "", "Load layout from a local directory")
|
||||||
newCmd.Flags().String("layout-git", "", "Load layout from a git repository")
|
newCmd.Flags().String("layout-git", "", "Load layout from a git repository")
|
||||||
|
@ -5,7 +5,7 @@ import "github.com/spf13/cobra"
|
|||||||
// Cmd exposes the top-level command
|
// Cmd exposes the top-level command
|
||||||
var Cmd = &cobra.Command{
|
var Cmd = &cobra.Command{
|
||||||
Use: "output",
|
Use: "output",
|
||||||
Short: "Manage a route's outputs",
|
Short: "Manage a deployment's outputs",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
|
|
||||||
var queryCmd = &cobra.Command{
|
var queryCmd = &cobra.Command{
|
||||||
Use: "query [EXPR] [flags]",
|
Use: "query [EXPR] [flags]",
|
||||||
Short: "Query the contents of a route",
|
Short: "Query the contents of a deployment",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
// Fix Viper bug for duplicate flags:
|
// Fix Viper bug for duplicate flags:
|
||||||
@ -31,18 +31,18 @@ var queryCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
route := common.GetCurrentRoute(ctx, store)
|
deployment := common.GetCurrentDeployment(ctx, store)
|
||||||
|
|
||||||
expr := args[0]
|
expr := args[0]
|
||||||
|
|
||||||
out, err := route.Query(ctx, expr, nil)
|
out, err := deployment.Query(ctx, expr, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("routeName", route.Name()).
|
Str("deploymentName", deployment.Name()).
|
||||||
Str("routeId", route.ID()).
|
Str("deploymentId", deployment.ID()).
|
||||||
Msg("failed to query route")
|
Msg("failed to query deployment")
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Println(out)
|
fmt.Println(out)
|
||||||
@ -52,7 +52,7 @@ var queryCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
queryCmd.Flags().String("revision", "latest", "Query a specific version of the route")
|
queryCmd.Flags().String("revision", "latest", "Query a specific version of the deployment")
|
||||||
queryCmd.Flags().StringP("format", "f", "", "Output format (json|yaml|cue|text|env)")
|
queryCmd.Flags().StringP("format", "f", "", "Output format (json|yaml|cue|text|env)")
|
||||||
|
|
||||||
queryCmd.Flags().BoolP("--no-input", "I", false, "Exclude inputs from query")
|
queryCmd.Flags().BoolP("--no-input", "I", false, "Exclude inputs from query")
|
||||||
|
@ -23,7 +23,7 @@ var rootCmd = &cobra.Command{
|
|||||||
func init() {
|
func init() {
|
||||||
rootCmd.PersistentFlags().String("log-format", "", "Log format (json, pretty). Defaults to json if the terminal is not a tty")
|
rootCmd.PersistentFlags().String("log-format", "", "Log format (json, pretty). Defaults to json if the terminal is not a tty")
|
||||||
rootCmd.PersistentFlags().StringP("log-level", "l", "debug", "Log level")
|
rootCmd.PersistentFlags().StringP("log-level", "l", "debug", "Log level")
|
||||||
rootCmd.PersistentFlags().StringP("route", "r", "", "Select a route")
|
rootCmd.PersistentFlags().StringP("deployment", "d", "", "Select a deployment")
|
||||||
|
|
||||||
rootCmd.AddCommand(
|
rootCmd.AddCommand(
|
||||||
computeCmd,
|
computeCmd,
|
||||||
|
@ -11,7 +11,7 @@ import (
|
|||||||
|
|
||||||
var upCmd = &cobra.Command{
|
var upCmd = &cobra.Command{
|
||||||
Use: "up",
|
Use: "up",
|
||||||
Short: "Bring a route online with latest layout and inputs",
|
Short: "Bring a deployment online with latest layout and inputs",
|
||||||
Args: cobra.NoArgs,
|
Args: cobra.NoArgs,
|
||||||
PreRun: func(cmd *cobra.Command, args []string) {
|
PreRun: func(cmd *cobra.Command, args []string) {
|
||||||
// Fix Viper bug for duplicate flags:
|
// Fix Viper bug for duplicate flags:
|
||||||
@ -28,10 +28,10 @@ var upCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
route := common.GetCurrentRoute(ctx, store)
|
deployment := common.GetCurrentDeployment(ctx, store)
|
||||||
|
|
||||||
// TODO: Implement options: --no-cache
|
// TODO: Implement options: --no-cache
|
||||||
common.RouteUp(ctx, route)
|
common.DeploymentUp(ctx, deployment)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func NewClient(ctx context.Context, host string) (*Client, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: return completed *Route, instead of *compiler.Value
|
// FIXME: return completed *Route, instead of *compiler.Value
|
||||||
func (c *Client) Up(ctx context.Context, route *Route) (*compiler.Value, error) {
|
func (c *Client) Up(ctx context.Context, deployment *Deployment) (*compiler.Value, error) {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
eg, gctx := errgroup.WithContext(ctx)
|
eg, gctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
@ -78,7 +78,7 @@ func (c *Client) Up(ctx context.Context, route *Route) (*compiler.Value, error)
|
|||||||
outr, outw := io.Pipe()
|
outr, outw := io.Pipe()
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
defer outw.Close()
|
defer outw.Close()
|
||||||
return c.buildfn(gctx, route, events, outw)
|
return c.buildfn(gctx, deployment, events, outw)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Spawn output retriever
|
// Spawn output retriever
|
||||||
@ -95,11 +95,11 @@ func (c *Client) Up(ctx context.Context, route *Route) (*compiler.Value, error)
|
|||||||
return out, compiler.Err(eg.Wait())
|
return out, compiler.Err(eg.Wait())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) buildfn(ctx context.Context, route *Route, ch chan *bk.SolveStatus, w io.WriteCloser) error {
|
func (c *Client) buildfn(ctx context.Context, deployment *Deployment, ch chan *bk.SolveStatus, w io.WriteCloser) error {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
// Scan local dirs to grant access
|
// Scan local dirs to grant access
|
||||||
localdirs := route.LocalDirs()
|
localdirs := deployment.LocalDirs()
|
||||||
for label, dir := range localdirs {
|
for label, dir := range localdirs {
|
||||||
abs, err := filepath.Abs(dir)
|
abs, err := filepath.Abs(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -132,24 +132,24 @@ func (c *Client) buildfn(ctx context.Context, route *Route, ch chan *bk.SolveSta
|
|||||||
s := NewSolver(c.c, gw, ch)
|
s := NewSolver(c.c, gw, ch)
|
||||||
|
|
||||||
lg.Debug().Msg("loading configuration")
|
lg.Debug().Msg("loading configuration")
|
||||||
if err := route.LoadLayout(ctx, s); err != nil {
|
if err := deployment.LoadLayout(ctx, s); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute output overlay
|
// Compute output overlay
|
||||||
lg.Debug().Msg("computing route")
|
lg.Debug().Msg("computing deployment")
|
||||||
if err := route.Up(ctx, s, nil); err != nil {
|
if err := deployment.Up(ctx, s, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export route to a cue directory
|
// Export deployment to a cue directory
|
||||||
// FIXME: this should be elsewhere
|
// FIXME: this should be elsewhere
|
||||||
lg.Debug().Msg("exporting route")
|
lg.Debug().Msg("exporting deployment")
|
||||||
span, _ := opentracing.StartSpanFromContext(ctx, "Route.Export")
|
span, _ := opentracing.StartSpanFromContext(ctx, "Deployment.Export")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
st := llb.Scratch().File(
|
st := llb.Scratch().File(
|
||||||
llb.Mkfile("state.cue", 0600, route.State().JSON()),
|
llb.Mkfile("state.cue", 0600, deployment.State().JSON()),
|
||||||
llb.WithCustomName("[internal] serializing state to JSON"),
|
llb.WithCustomName("[internal] serializing state to JSON"),
|
||||||
)
|
)
|
||||||
ref, err := s.Solve(ctx, st)
|
ref, err := s.Solve(ctx, st)
|
||||||
@ -178,7 +178,7 @@ func (c *Client) buildfn(ctx context.Context, route *Route, ch chan *bk.SolveSta
|
|||||||
func (c *Client) outputfn(ctx context.Context, r io.Reader) (*compiler.Value, error) {
|
func (c *Client) outputfn(ctx context.Context, r io.Reader) (*compiler.Value, error) {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
// FIXME: merge this into route output.
|
// FIXME: merge this into deployment output.
|
||||||
out := compiler.EmptyStruct()
|
out := compiler.EmptyStruct()
|
||||||
|
|
||||||
tr := tar.NewReader(r)
|
tr := tar.NewReader(r)
|
||||||
|
@ -18,17 +18,17 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Contents of a route serialized to a file
|
// Contents of a deployment serialized to a file
|
||||||
type RouteState struct {
|
type DeploymentState struct {
|
||||||
// Globally unique route ID
|
// Globally unique deployment ID
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
|
|
||||||
// Human-friendly route name.
|
// Human-friendly deployment name.
|
||||||
// A route may have more than one name.
|
// A deployment may have more than one name.
|
||||||
// FIXME: store multiple names?
|
// FIXME: store multiple names?
|
||||||
Name string `json:"name,omitempty"`
|
Name string `json:"name,omitempty"`
|
||||||
|
|
||||||
// Cue module containing the route layout
|
// Cue module containing the deployment layout
|
||||||
// The input's top-level artifact is used as a module directory.
|
// The input's top-level artifact is used as a module directory.
|
||||||
LayoutSource Input `json:"layout,omitempty"`
|
LayoutSource Input `json:"layout,omitempty"`
|
||||||
|
|
||||||
@ -40,34 +40,29 @@ type inputKV struct {
|
|||||||
Value Input `json:"value,omitempty"`
|
Value Input `json:"value,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *RouteState) AddInput(key string, value Input) error {
|
func (s *DeploymentState) AddInput(key string, value Input) error {
|
||||||
r.Inputs = append(r.Inputs, inputKV{Key: key, Value: value})
|
s.Inputs = append(s.Inputs, inputKV{Key: key, Value: value})
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove all inputs at the given key, including sub-keys.
|
// Remove all inputs at the given key, including sub-keys.
|
||||||
// For example RemoveInputs("foo.bar") will remove all inputs
|
// For example RemoveInputs("foo.bar") will remove all inputs
|
||||||
// at foo.bar, foo.bar.baz, etc.
|
// at foo.bar, foo.bar.baz, etc.
|
||||||
func (r *RouteState) RemoveInputs(key string) error {
|
func (s *DeploymentState) RemoveInputs(key string) error {
|
||||||
newInputs := make([]inputKV, 0, len(r.Inputs))
|
newInputs := make([]inputKV, 0, len(s.Inputs))
|
||||||
for _, i := range r.Inputs {
|
for _, i := range s.Inputs {
|
||||||
if i.Key == key {
|
if i.Key == key {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
newInputs = append(newInputs, i)
|
newInputs = append(newInputs, i)
|
||||||
}
|
}
|
||||||
r.Inputs = newInputs
|
s.Inputs = newInputs
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Route struct {
|
type Deployment struct {
|
||||||
st *RouteState
|
st *DeploymentState
|
||||||
|
|
||||||
// Env boot script, eg. `[{do:"local",dir:"."}]`
|
|
||||||
// FIXME: rename to 'update' (script to update the env config)
|
|
||||||
// FIXME: embed update script in base as '#update' ?
|
|
||||||
// FIXME: simplify Env by making it single layer? Each layer is one r.
|
|
||||||
|
|
||||||
// Layer 1: layout configuration
|
// Layer 1: layout configuration
|
||||||
layout *compiler.Value
|
layout *compiler.Value
|
||||||
@ -82,9 +77,9 @@ type Route struct {
|
|||||||
state *compiler.Value
|
state *compiler.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRoute(st *RouteState) (*Route, error) {
|
func NewDeployment(st *DeploymentState) (*Deployment, error) {
|
||||||
empty := compiler.EmptyStruct()
|
empty := compiler.EmptyStruct()
|
||||||
r := &Route{
|
d := &Deployment{
|
||||||
st: st,
|
st: st,
|
||||||
layout: empty,
|
layout: empty,
|
||||||
input: empty,
|
input: empty,
|
||||||
@ -98,55 +93,55 @@ func NewRoute(st *RouteState) (*Route, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if input.Key == "" {
|
if input.Key == "" {
|
||||||
r.input, err = r.input.Merge(v)
|
d.input, err = d.input.Merge(v)
|
||||||
} else {
|
} else {
|
||||||
r.input, err = r.input.MergeTarget(v, input.Key)
|
d.input, err = d.input.MergeTarget(v, input.Key)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := r.mergeState(); err != nil {
|
if err := d.mergeState(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return r, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) ID() string {
|
func (d *Deployment) ID() string {
|
||||||
return r.st.ID
|
return d.st.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) Name() string {
|
func (d *Deployment) Name() string {
|
||||||
return r.st.Name
|
return d.st.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) LayoutSource() Input {
|
func (d *Deployment) LayoutSource() Input {
|
||||||
return r.st.LayoutSource
|
return d.st.LayoutSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) Layout() *compiler.Value {
|
func (d *Deployment) Layout() *compiler.Value {
|
||||||
return r.layout
|
return d.layout
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) Input() *compiler.Value {
|
func (d *Deployment) Input() *compiler.Value {
|
||||||
return r.input
|
return d.input
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) Output() *compiler.Value {
|
func (d *Deployment) Output() *compiler.Value {
|
||||||
return r.output
|
return d.output
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) State() *compiler.Value {
|
func (d *Deployment) State() *compiler.Value {
|
||||||
return r.state
|
return d.state
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadLayout loads the layout
|
// LoadLayout loads the layout
|
||||||
func (r *Route) LoadLayout(ctx context.Context, s Solver) error {
|
func (d *Deployment) LoadLayout(ctx context.Context, s Solver) error {
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, "route.Update")
|
span, ctx := opentracing.StartSpanFromContext(ctx, "deployment.LoadLayout")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
layoutSource, err := r.st.LayoutSource.Compile()
|
layoutSource, err := d.st.LayoutSource.Compile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -166,17 +161,17 @@ func (r *Route) LoadLayout(ctx context.Context, s Solver) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("layout config: %w", err)
|
return fmt.Errorf("layout config: %w", err)
|
||||||
}
|
}
|
||||||
r.layout = layout
|
d.layout = layout
|
||||||
|
|
||||||
// Commit
|
// Commit
|
||||||
return r.mergeState()
|
return d.mergeState()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan all scripts in the environment for references to local directories (do:"local"),
|
// Scan all scripts in the deployment for references to local directories (do:"local"),
|
||||||
// and return all referenced directory names.
|
// and return all referenced directory names.
|
||||||
// This is used by clients to grant access to local directories when they are referenced
|
// This is used by clients to grant access to local directories when they are referenced
|
||||||
// by user-specified scripts.
|
// by user-specified scripts.
|
||||||
func (r *Route) LocalDirs() map[string]string {
|
func (d *Deployment) LocalDirs() map[string]string {
|
||||||
dirs := map[string]string{}
|
dirs := map[string]string{}
|
||||||
localdirs := func(code ...*compiler.Value) {
|
localdirs := func(code ...*compiler.Value) {
|
||||||
Analyze(
|
Analyze(
|
||||||
@ -185,7 +180,6 @@ func (r *Route) LocalDirs() map[string]string {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// FIXME: merge Env into Route, or fix the linter error
|
|
||||||
if do != "local" {
|
if do != "local" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -199,9 +193,9 @@ func (r *Route) LocalDirs() map[string]string {
|
|||||||
code...,
|
code...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// 1. Scan the environment state
|
// 1. Scan the deployment state
|
||||||
// FIXME: use a common `flow` instance to avoid rescanning the tree.
|
// FIXME: use a common `flow` instance to avoid rescanning the tree.
|
||||||
inst := r.state.CueInst()
|
inst := d.state.CueInst()
|
||||||
flow := cueflow.New(&cueflow.Config{}, inst, newTaskFunc(inst, noOpRunner))
|
flow := cueflow.New(&cueflow.Config{}, inst, newTaskFunc(inst, noOpRunner))
|
||||||
for _, t := range flow.Tasks() {
|
for _, t := range flow.Tasks() {
|
||||||
v := compiler.Wrap(t.Value(), inst)
|
v := compiler.Wrap(t.Value(), inst)
|
||||||
@ -209,7 +203,7 @@ func (r *Route) LocalDirs() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 2. Scan the layout
|
// 2. Scan the layout
|
||||||
layout, err := r.st.LayoutSource.Compile()
|
layout, err := d.st.LayoutSource.Compile()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -218,7 +212,7 @@ func (r *Route) LocalDirs() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this is just a 3-way merge. Add var args to compiler.Value.Merge.
|
// FIXME: this is just a 3-way merge. Add var args to compiler.Value.Merge.
|
||||||
func (r *Route) mergeState() error {
|
func (d *Deployment) mergeState() error {
|
||||||
// FIXME: make this cleaner in *compiler.Value by keeping intermediary instances
|
// FIXME: make this cleaner in *compiler.Value by keeping intermediary instances
|
||||||
// FIXME: state.CueInst() must return an instance with the same
|
// FIXME: state.CueInst() must return an instance with the same
|
||||||
// contents as state.v, for the purposes of cueflow.
|
// contents as state.v, for the purposes of cueflow.
|
||||||
@ -231,15 +225,15 @@ func (r *Route) mergeState() error {
|
|||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
|
|
||||||
stateInst, err = stateInst.Fill(r.layout.Cue())
|
stateInst, err = stateInst.Fill(d.layout.Cue())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("merge base & input: %w", err)
|
return fmt.Errorf("merge base & input: %w", err)
|
||||||
}
|
}
|
||||||
stateInst, err = stateInst.Fill(r.input.Cue())
|
stateInst, err = stateInst.Fill(d.input.Cue())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("merge base & input: %w", err)
|
return fmt.Errorf("merge base & input: %w", err)
|
||||||
}
|
}
|
||||||
stateInst, err = stateInst.Fill(r.output.Cue())
|
stateInst, err = stateInst.Fill(d.output.Cue())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("merge output with base & input: %w", err)
|
return fmt.Errorf("merge output with base & input: %w", err)
|
||||||
}
|
}
|
||||||
@ -247,24 +241,24 @@ func (r *Route) mergeState() error {
|
|||||||
state = compiler.Wrap(stateInst.Value(), stateInst)
|
state = compiler.Wrap(stateInst.Value(), stateInst)
|
||||||
|
|
||||||
// commit
|
// commit
|
||||||
r.state = state
|
d.state = state
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpOpts struct{}
|
type UpOpts struct{}
|
||||||
|
|
||||||
// Up missing values in env configuration, and write them to state.
|
// Up missing values in deployment configuration, and write them to state.
|
||||||
func (r *Route) Up(ctx context.Context, s Solver, _ *UpOpts) error {
|
func (d *Deployment) Up(ctx context.Context, s Solver, _ *UpOpts) error {
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, "r.Compute")
|
span, ctx := opentracing.StartSpanFromContext(ctx, "r.Compute")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
// Cueflow cue instance
|
// Cueflow cue instance
|
||||||
inst := r.state.CueInst()
|
inst := d.state.CueInst()
|
||||||
|
|
||||||
// Reset the output
|
// Reset the output
|
||||||
r.output = compiler.EmptyStruct()
|
d.output = compiler.EmptyStruct()
|
||||||
|
|
||||||
// Cueflow config
|
// Cueflow config
|
||||||
flowCfg := &cueflow.Config{
|
flowCfg := &cueflow.Config{
|
||||||
@ -284,7 +278,7 @@ func (r *Route) Up(ctx context.Context, s Solver, _ *UpOpts) error {
|
|||||||
}
|
}
|
||||||
// Merge task value into output
|
// Merge task value into output
|
||||||
var err error
|
var err error
|
||||||
r.output, err = r.output.MergePath(t.Value(), t.Path())
|
d.output, err = d.output.MergePath(t.Value(), t.Path())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Error().
|
Error().
|
||||||
@ -305,17 +299,17 @@ func (r *Route) Up(ctx context.Context, s Solver, _ *UpOpts) error {
|
|||||||
span, _ := opentracing.StartSpanFromContext(ctx, "merge state")
|
span, _ := opentracing.StartSpanFromContext(ctx, "merge state")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
return r.mergeState()
|
return d.mergeState()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type DownOpts struct{}
|
type DownOpts struct{}
|
||||||
|
|
||||||
func (r *Route) Down(ctx context.Context, _ *DownOpts) error {
|
func (d *Deployment) Down(ctx context.Context, _ *DownOpts) error {
|
||||||
panic("NOT IMPLEMENTED")
|
panic("NOT IMPLEMENTED")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Route) Query(ctx context.Context, expr interface{}, o *QueryOpts) (*compiler.Value, error) {
|
func (d *Deployment) Query(ctx context.Context, expr interface{}, o *QueryOpts) (*compiler.Value, error) {
|
||||||
panic("NOT IMPLEMENTED")
|
panic("NOT IMPLEMENTED")
|
||||||
}
|
}
|
||||||
|
|
@ -7,15 +7,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestInputDir(t *testing.T) {
|
func TestInputDir(t *testing.T) {
|
||||||
st := &RouteState{
|
st := &DeploymentState{
|
||||||
LayoutSource: DirInput("/tmp/source", []string{}),
|
LayoutSource: DirInput("/tmp/source", []string{}),
|
||||||
}
|
}
|
||||||
require.NoError(t, st.AddInput("www.source", DirInput(".", []string{})))
|
require.NoError(t, st.AddInput("www.source", DirInput(".", []string{})))
|
||||||
|
|
||||||
route, err := NewRoute(st)
|
deployment, err := NewDeployment(st)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
localdirs := route.LocalDirs()
|
localdirs := deployment.LocalDirs()
|
||||||
require.Len(t, localdirs, 2)
|
require.Len(t, localdirs, 2)
|
||||||
require.Contains(t, localdirs, ".")
|
require.Contains(t, localdirs, ".")
|
||||||
require.Contains(t, localdirs, "/tmp/source")
|
require.Contains(t, localdirs, "/tmp/source")
|
||||||
|
118
dagger/store.go
118
dagger/store.go
@ -13,12 +13,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrRouteExist = errors.New("route already exists")
|
ErrDeploymentExist = errors.New("deployment already exists")
|
||||||
ErrRouteNotExist = errors.New("route doesn't exist")
|
ErrDeploymentNotExist = errors.New("deployment doesn't exist")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultStoreRoot = "$HOME/.config/dagger/routes"
|
defaultStoreRoot = "$HOME/.config/dagger/deployments"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Store struct {
|
type Store struct {
|
||||||
@ -26,21 +26,21 @@ type Store struct {
|
|||||||
|
|
||||||
l sync.RWMutex
|
l sync.RWMutex
|
||||||
|
|
||||||
routes map[string]*RouteState
|
deployments map[string]*DeploymentState
|
||||||
|
|
||||||
// Various indices for fast lookups
|
// Various indices for fast lookups
|
||||||
routesByName map[string]*RouteState
|
deploymentsByName map[string]*DeploymentState
|
||||||
routesByPath map[string]*RouteState
|
deploymentsByPath map[string]*DeploymentState
|
||||||
pathsByRoute map[string][]string
|
pathsByDeployment map[string][]string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStore(root string) (*Store, error) {
|
func NewStore(root string) (*Store, error) {
|
||||||
store := &Store{
|
store := &Store{
|
||||||
root: root,
|
root: root,
|
||||||
routes: make(map[string]*RouteState),
|
deployments: make(map[string]*DeploymentState),
|
||||||
routesByName: make(map[string]*RouteState),
|
deploymentsByName: make(map[string]*DeploymentState),
|
||||||
routesByPath: make(map[string]*RouteState),
|
deploymentsByPath: make(map[string]*DeploymentState),
|
||||||
pathsByRoute: make(map[string][]string),
|
pathsByDeployment: make(map[string][]string),
|
||||||
}
|
}
|
||||||
return store, store.loadAll()
|
return store, store.loadAll()
|
||||||
}
|
}
|
||||||
@ -49,8 +49,8 @@ func DefaultStore() (*Store, error) {
|
|||||||
return NewStore(os.ExpandEnv(defaultStoreRoot))
|
return NewStore(os.ExpandEnv(defaultStoreRoot))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) routePath(name string) string {
|
func (s *Store) deploymentPath(name string) string {
|
||||||
return path.Join(s.root, name, "route.json")
|
return path.Join(s.root, name, "deployment.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) loadAll() error {
|
func (s *Store) loadAll() error {
|
||||||
@ -66,7 +66,7 @@ func (s *Store) loadAll() error {
|
|||||||
if !f.IsDir() {
|
if !f.IsDir() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := s.loadRoute(f.Name()); err != nil {
|
if err := s.loadDeployment(f.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -74,21 +74,21 @@ func (s *Store) loadAll() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) loadRoute(name string) error {
|
func (s *Store) loadDeployment(name string) error {
|
||||||
data, err := os.ReadFile(s.routePath(name))
|
data, err := os.ReadFile(s.deploymentPath(name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var st RouteState
|
var st DeploymentState
|
||||||
if err := json.Unmarshal(data, &st); err != nil {
|
if err := json.Unmarshal(data, &st); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.indexRoute(&st)
|
s.indexDeployment(&st)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) syncRoute(r *RouteState) error {
|
func (s *Store) syncDeployment(r *DeploymentState) error {
|
||||||
p := s.routePath(r.Name)
|
p := s.deploymentPath(r.Name)
|
||||||
|
|
||||||
if err := os.MkdirAll(path.Dir(p), 0755); err != nil {
|
if err := os.MkdirAll(path.Dir(p), 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -103,21 +103,21 @@ func (s *Store) syncRoute(r *RouteState) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.reindexRoute(r)
|
s.reindexDeployment(r)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) indexRoute(r *RouteState) {
|
func (s *Store) indexDeployment(r *DeploymentState) {
|
||||||
s.routes[r.ID] = r
|
s.deployments[r.ID] = r
|
||||||
s.routesByName[r.Name] = r
|
s.deploymentsByName[r.Name] = r
|
||||||
|
|
||||||
mapPath := func(i Input) {
|
mapPath := func(i Input) {
|
||||||
if i.Type != InputTypeDir {
|
if i.Type != InputTypeDir {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.routesByPath[i.Dir.Path] = r
|
s.deploymentsByPath[i.Dir.Path] = r
|
||||||
s.pathsByRoute[r.ID] = append(s.pathsByRoute[r.ID], i.Dir.Path)
|
s.pathsByDeployment[r.ID] = append(s.pathsByDeployment[r.ID], i.Dir.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
mapPath(r.LayoutSource)
|
mapPath(r.LayoutSource)
|
||||||
@ -126,101 +126,101 @@ func (s *Store) indexRoute(r *RouteState) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) deindexRoute(id string) {
|
func (s *Store) deindexDeployment(id string) {
|
||||||
r, ok := s.routes[id]
|
r, ok := s.deployments[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
delete(s.routes, r.ID)
|
delete(s.deployments, r.ID)
|
||||||
delete(s.routesByName, r.Name)
|
delete(s.deploymentsByName, r.Name)
|
||||||
|
|
||||||
for _, p := range s.pathsByRoute[r.ID] {
|
for _, p := range s.pathsByDeployment[r.ID] {
|
||||||
delete(s.routesByPath, p)
|
delete(s.deploymentsByPath, p)
|
||||||
}
|
}
|
||||||
delete(s.pathsByRoute, r.ID)
|
delete(s.pathsByDeployment, r.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) reindexRoute(r *RouteState) {
|
func (s *Store) reindexDeployment(r *DeploymentState) {
|
||||||
s.deindexRoute(r.ID)
|
s.deindexDeployment(r.ID)
|
||||||
s.indexRoute(r)
|
s.indexDeployment(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) CreateRoute(ctx context.Context, st *RouteState) error {
|
func (s *Store) CreateDeployment(ctx context.Context, st *DeploymentState) error {
|
||||||
s.l.Lock()
|
s.l.Lock()
|
||||||
defer s.l.Unlock()
|
defer s.l.Unlock()
|
||||||
|
|
||||||
if _, ok := s.routesByName[st.Name]; ok {
|
if _, ok := s.deploymentsByName[st.Name]; ok {
|
||||||
return fmt.Errorf("%s: %w", st.Name, ErrRouteExist)
|
return fmt.Errorf("%s: %w", st.Name, ErrDeploymentExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
st.ID = uuid.New().String()
|
st.ID = uuid.New().String()
|
||||||
return s.syncRoute(st)
|
return s.syncDeployment(st)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateOpts struct{}
|
type UpdateOpts struct{}
|
||||||
|
|
||||||
func (s *Store) UpdateRoute(ctx context.Context, r *RouteState, o *UpdateOpts) error {
|
func (s *Store) UpdateDeployment(ctx context.Context, r *DeploymentState, o *UpdateOpts) error {
|
||||||
s.l.Lock()
|
s.l.Lock()
|
||||||
defer s.l.Unlock()
|
defer s.l.Unlock()
|
||||||
|
|
||||||
return s.syncRoute(r)
|
return s.syncDeployment(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeleteOpts struct{}
|
type DeleteOpts struct{}
|
||||||
|
|
||||||
func (s *Store) DeleteRoute(ctx context.Context, r *RouteState, o *DeleteOpts) error {
|
func (s *Store) DeleteDeployment(ctx context.Context, r *DeploymentState, o *DeleteOpts) error {
|
||||||
s.l.Lock()
|
s.l.Lock()
|
||||||
defer s.l.Unlock()
|
defer s.l.Unlock()
|
||||||
|
|
||||||
if err := os.Remove(s.routePath(r.Name)); err != nil {
|
if err := os.Remove(s.deploymentPath(r.Name)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.deindexRoute(r.ID)
|
s.deindexDeployment(r.ID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) LookupRouteByID(ctx context.Context, id string) (*RouteState, error) {
|
func (s *Store) LookupDeploymentByID(ctx context.Context, id string) (*DeploymentState, error) {
|
||||||
s.l.RLock()
|
s.l.RLock()
|
||||||
defer s.l.RUnlock()
|
defer s.l.RUnlock()
|
||||||
|
|
||||||
st, ok := s.routes[id]
|
st, ok := s.deployments[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("%s: %w", id, ErrRouteNotExist)
|
return nil, fmt.Errorf("%s: %w", id, ErrDeploymentNotExist)
|
||||||
}
|
}
|
||||||
return st, nil
|
return st, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) LookupRouteByName(ctx context.Context, name string) (*RouteState, error) {
|
func (s *Store) LookupDeploymentByName(ctx context.Context, name string) (*DeploymentState, error) {
|
||||||
s.l.RLock()
|
s.l.RLock()
|
||||||
defer s.l.RUnlock()
|
defer s.l.RUnlock()
|
||||||
|
|
||||||
st, ok := s.routesByName[name]
|
st, ok := s.deploymentsByName[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("%s: %w", name, ErrRouteNotExist)
|
return nil, fmt.Errorf("%s: %w", name, ErrDeploymentNotExist)
|
||||||
}
|
}
|
||||||
return st, nil
|
return st, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) LookupRouteByPath(ctx context.Context, path string) (*RouteState, error) {
|
func (s *Store) LookupDeploymentByPath(ctx context.Context, path string) (*DeploymentState, error) {
|
||||||
s.l.RLock()
|
s.l.RLock()
|
||||||
defer s.l.RUnlock()
|
defer s.l.RUnlock()
|
||||||
|
|
||||||
st, ok := s.routesByPath[path]
|
st, ok := s.deploymentsByPath[path]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("%s: %w", path, ErrRouteNotExist)
|
return nil, fmt.Errorf("%s: %w", path, ErrDeploymentNotExist)
|
||||||
}
|
}
|
||||||
return st, nil
|
return st, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) ListRoutes(ctx context.Context) ([]*RouteState, error) {
|
func (s *Store) ListDeployments(ctx context.Context) ([]*DeploymentState, error) {
|
||||||
s.l.RLock()
|
s.l.RLock()
|
||||||
defer s.l.RUnlock()
|
defer s.l.RUnlock()
|
||||||
|
|
||||||
routes := make([]*RouteState, 0, len(s.routes))
|
deployments := make([]*DeploymentState, 0, len(s.deployments))
|
||||||
|
|
||||||
for _, st := range s.routes {
|
for _, st := range s.deployments {
|
||||||
routes = append(routes, st)
|
deployments = append(deployments, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
return routes, nil
|
return deployments, nil
|
||||||
}
|
}
|
||||||
|
@ -17,38 +17,38 @@ func TestStoreLoad(t *testing.T) {
|
|||||||
store, err := NewStore(root)
|
store, err := NewStore(root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
_, err = store.LookupRouteByName(ctx, "notexist")
|
_, err = store.LookupDeploymentByName(ctx, "notexist")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.True(t, errors.Is(err, ErrRouteNotExist))
|
require.True(t, errors.Is(err, ErrDeploymentNotExist))
|
||||||
|
|
||||||
st := &RouteState{
|
st := &DeploymentState{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
}
|
}
|
||||||
require.NoError(t, store.CreateRoute(ctx, st))
|
require.NoError(t, store.CreateDeployment(ctx, st))
|
||||||
|
|
||||||
checkRoutes := func(store *Store) {
|
checkDeployments := func(store *Store) {
|
||||||
r, err := store.LookupRouteByID(ctx, st.ID)
|
r, err := store.LookupDeploymentByID(ctx, st.ID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, r)
|
require.NotNil(t, r)
|
||||||
require.Equal(t, "test", r.Name)
|
require.Equal(t, "test", r.Name)
|
||||||
|
|
||||||
r, err = store.LookupRouteByName(ctx, "test")
|
r, err = store.LookupDeploymentByName(ctx, "test")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, r)
|
require.NotNil(t, r)
|
||||||
require.Equal(t, "test", r.Name)
|
require.Equal(t, "test", r.Name)
|
||||||
|
|
||||||
routes, err := store.ListRoutes(ctx)
|
deployments, err := store.ListDeployments(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, routes, 1)
|
require.Len(t, deployments, 1)
|
||||||
require.Equal(t, "test", routes[0].Name)
|
require.Equal(t, "test", deployments[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkRoutes(store)
|
checkDeployments(store)
|
||||||
|
|
||||||
// Reload the routes from disk and check again
|
// Reload the deployments from disk and check again
|
||||||
newStore, err := NewStore(root)
|
newStore, err := NewStore(root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
checkRoutes(newStore)
|
checkDeployments(newStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStoreLookupByPath(t *testing.T) {
|
func TestStoreLookupByPath(t *testing.T) {
|
||||||
@ -59,41 +59,41 @@ func TestStoreLookupByPath(t *testing.T) {
|
|||||||
store, err := NewStore(root)
|
store, err := NewStore(root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
st := &RouteState{
|
st := &DeploymentState{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
}
|
}
|
||||||
require.NoError(t, st.AddInput("foo", DirInput("/test/path", []string{})))
|
require.NoError(t, st.AddInput("foo", DirInput("/test/path", []string{})))
|
||||||
require.NoError(t, store.CreateRoute(ctx, st))
|
require.NoError(t, store.CreateDeployment(ctx, st))
|
||||||
|
|
||||||
// Lookup by path
|
// Lookup by path
|
||||||
r, err := store.LookupRouteByPath(ctx, "/test/path")
|
r, err := store.LookupDeploymentByPath(ctx, "/test/path")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.NotNil(t, r)
|
require.NotNil(t, r)
|
||||||
require.Equal(t, st.ID, r.ID)
|
require.Equal(t, st.ID, r.ID)
|
||||||
|
|
||||||
// Add a new path
|
// Add a new path
|
||||||
require.NoError(t, st.AddInput("bar", DirInput("/test/anotherpath", []string{})))
|
require.NoError(t, st.AddInput("bar", DirInput("/test/anotherpath", []string{})))
|
||||||
require.NoError(t, store.UpdateRoute(ctx, st, nil))
|
require.NoError(t, store.UpdateDeployment(ctx, st, nil))
|
||||||
|
|
||||||
// Lookup by the previous path
|
// Lookup by the previous path
|
||||||
r, err = store.LookupRouteByPath(ctx, "/test/path")
|
r, err = store.LookupDeploymentByPath(ctx, "/test/path")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, st.ID, r.ID)
|
require.Equal(t, st.ID, r.ID)
|
||||||
|
|
||||||
// Lookup by the new path
|
// Lookup by the new path
|
||||||
r, err = store.LookupRouteByPath(ctx, "/test/anotherpath")
|
r, err = store.LookupDeploymentByPath(ctx, "/test/anotherpath")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, st.ID, r.ID)
|
require.Equal(t, st.ID, r.ID)
|
||||||
|
|
||||||
// Remove a path
|
// Remove a path
|
||||||
require.NoError(t, st.RemoveInputs("foo"))
|
require.NoError(t, st.RemoveInputs("foo"))
|
||||||
require.NoError(t, store.UpdateRoute(ctx, st, nil))
|
require.NoError(t, store.UpdateDeployment(ctx, st, nil))
|
||||||
|
|
||||||
// Lookup by the removed path should fail
|
// Lookup by the removed path should fail
|
||||||
_, err = store.LookupRouteByPath(ctx, "/test/path")
|
_, err = store.LookupDeploymentByPath(ctx, "/test/path")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// Lookup by the other path should still work
|
// Lookup by the other path should still work
|
||||||
_, err = store.LookupRouteByPath(ctx, "/test/anotherpath")
|
_, err = store.LookupDeploymentByPath(ctx, "/test/anotherpath")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user