Rename "deployment" to "environment": code
Signed-off-by: Solomon Hykes <sh.github.6811@hykes.org>
This commit is contained in:
parent
d1853f9e4b
commit
e6e8ab390d
@ -9,18 +9,18 @@ import (
|
|||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetCurrentDeploymentState(ctx context.Context, store *dagger.Store) *dagger.DeploymentState {
|
func GetCurrentEnvironmentState(ctx context.Context, store *dagger.Store) *dagger.EnvironmentState {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
deploymentName := viper.GetString("deployment")
|
environmentName := viper.GetString("environment")
|
||||||
if deploymentName != "" {
|
if environmentName != "" {
|
||||||
st, err := store.LookupDeploymentByName(ctx, deploymentName)
|
st, err := store.LookupEnvironmentByName(ctx, environmentName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("deploymentName", deploymentName).
|
Str("environmentName", environmentName).
|
||||||
Msg("failed to lookup deployment by name")
|
Msg("failed to lookup environment by name")
|
||||||
}
|
}
|
||||||
return st
|
return st
|
||||||
}
|
}
|
||||||
@ -29,50 +29,50 @@ func GetCurrentDeploymentState(ctx context.Context, store *dagger.Store) *dagger
|
|||||||
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.LookupDeploymentByPath(ctx, wd)
|
st, err := store.LookupEnvironmentByPath(ctx, wd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("deploymentPath", wd).
|
Str("environmentPath", wd).
|
||||||
Msg("failed to lookup deployment by path")
|
Msg("failed to lookup environment by path")
|
||||||
}
|
}
|
||||||
if len(st) == 0 {
|
if len(st) == 0 {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("deploymentPath", wd).
|
Str("environmentPath", wd).
|
||||||
Msg("no deployments match the current directory")
|
Msg("no environments match the current directory")
|
||||||
}
|
}
|
||||||
if len(st) > 1 {
|
if len(st) > 1 {
|
||||||
deployments := []string{}
|
environments := []string{}
|
||||||
for _, s := range st {
|
for _, s := range st {
|
||||||
deployments = append(deployments, s.Name)
|
environments = append(environments, s.Name)
|
||||||
}
|
}
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Str("deploymentPath", wd).
|
Str("environmentPath", wd).
|
||||||
Strs("deployments", deployments).
|
Strs("environments", environments).
|
||||||
Msg("multiple deployments match the current directory, select one with `--deployment`")
|
Msg("multiple environments match the current directory, select one with `--environment`")
|
||||||
}
|
}
|
||||||
return st[0]
|
return st[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-compute a deployment (equivalent to `dagger up`).
|
// Re-compute an environment (equivalent to `dagger up`).
|
||||||
func DeploymentUp(ctx context.Context, state *dagger.DeploymentState, noCache bool) *dagger.Deployment {
|
func EnvironmentUp(ctx context.Context, state *dagger.EnvironmentState, noCache bool) *dagger.Environment {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
c, err := dagger.NewClient(ctx, "", noCache)
|
c, err := dagger.NewClient(ctx, "", noCache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("unable to create client")
|
lg.Fatal().Err(err).Msg("unable to create client")
|
||||||
}
|
}
|
||||||
result, err := c.Do(ctx, state, func(ctx context.Context, deployment *dagger.Deployment, s dagger.Solver) error {
|
result, err := c.Do(ctx, state, func(ctx context.Context, environment *dagger.Environment, s dagger.Solver) error {
|
||||||
log.Ctx(ctx).Debug().Msg("bringing deployment up")
|
log.Ctx(ctx).Debug().Msg("bringing environment up")
|
||||||
return deployment.Up(ctx, s)
|
return environment.Up(ctx, s)
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to up deployment")
|
lg.Fatal().Err(err).Msg("failed to up environment")
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ var computeCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
st := &dagger.DeploymentState{
|
st := &dagger.EnvironmentState{
|
||||||
ID: uuid.New().String(),
|
ID: uuid.New().String(),
|
||||||
Name: "FIXME",
|
Name: "FIXME",
|
||||||
PlanSource: dagger.DirInput(args[0], []string{"*.cue", "cue.mod"}),
|
PlanSource: dagger.DirInput(args[0], []string{"*.cue", "cue.mod"}),
|
||||||
@ -149,16 +149,16 @@ var computeCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deployment := common.DeploymentUp(ctx, st, viper.GetBool("no-cache"))
|
environment := common.EnvironmentUp(ctx, st, viper.GetBool("no-cache"))
|
||||||
|
|
||||||
v := compiler.NewValue()
|
v := compiler.NewValue()
|
||||||
if err := v.FillPath(cue.MakePath(), deployment.Plan()); err != nil {
|
if err := v.FillPath(cue.MakePath(), environment.Plan()); err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to merge")
|
lg.Fatal().Err(err).Msg("failed to merge")
|
||||||
}
|
}
|
||||||
if err := v.FillPath(cue.MakePath(), deployment.Input()); err != nil {
|
if err := v.FillPath(cue.MakePath(), environment.Input()); err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to merge")
|
lg.Fatal().Err(err).Msg("failed to merge")
|
||||||
}
|
}
|
||||||
if err := v.FillPath(cue.MakePath(), deployment.Computed()); err != nil {
|
if err := v.FillPath(cue.MakePath(), environment.Computed()); err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to merge")
|
lg.Fatal().Err(err).Msg("failed to merge")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
var deleteCmd = &cobra.Command{
|
var deleteCmd = &cobra.Command{
|
||||||
Use: "delete",
|
Use: "delete",
|
||||||
Short: "Delete a deployment after taking it offline (WARNING: may destroy infrastructure)",
|
Short: "Delete an environment 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:
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
var downCmd = &cobra.Command{
|
var downCmd = &cobra.Command{
|
||||||
Use: "down",
|
Use: "down",
|
||||||
Short: "Take a deployment offline (WARNING: may destroy infrastructure)",
|
Short: "Take an environment 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:
|
||||||
|
@ -7,7 +7,7 @@ import (
|
|||||||
|
|
||||||
var historyCmd = &cobra.Command{
|
var historyCmd = &cobra.Command{
|
||||||
Use: "history",
|
Use: "history",
|
||||||
Short: "List past changes to a deployment",
|
Short: "List past changes to an environment",
|
||||||
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())
|
||||||
|
|
||||||
updateDeploymentInput(ctx, args[0], dagger.DockerInput(args[1]))
|
updateEnvironmentInput(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())
|
||||||
|
|
||||||
updateDeploymentInput(ctx, args[0], dagger.DirInput(args[1], []string{}))
|
updateEnvironmentInput(ctx, args[0], dagger.DirInput(args[1], []string{}))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ var gitCmd = &cobra.Command{
|
|||||||
subDir = args[3]
|
subDir = args[3]
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDeploymentInput(ctx, args[0], dagger.GitInput(args[1], ref, subDir))
|
updateEnvironmentInput(ctx, args[0], dagger.GitInput(args[1], ref, subDir))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ var jsonCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
updateDeploymentInput(
|
updateEnvironmentInput(
|
||||||
ctx,
|
ctx,
|
||||||
args[0],
|
args[0],
|
||||||
dagger.JSONInput(readInput(ctx, args[1])),
|
dagger.JSONInput(readInput(ctx, args[1])),
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
var listCmd = &cobra.Command{
|
var listCmd = &cobra.Command{
|
||||||
Use: "list [TARGET] [flags]",
|
Use: "list [TARGET] [flags]",
|
||||||
Short: "List for the inputs of a deployment",
|
Short: "List for the inputs of an environment",
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(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:
|
||||||
@ -35,12 +35,12 @@ var listCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
deployment := common.GetCurrentDeploymentState(ctx, store)
|
environment := common.GetCurrentEnvironmentState(ctx, store)
|
||||||
|
|
||||||
// print any persisted inputs
|
// print any persisted inputs
|
||||||
if len(deployment.Inputs) > 0 {
|
if len(environment.Inputs) > 0 {
|
||||||
fmt.Println("Saved Inputs:")
|
fmt.Println("Saved Inputs:")
|
||||||
for _, input := range deployment.Inputs {
|
for _, input := range environment.Inputs {
|
||||||
// Todo, how to pull apart an input to print relevant information
|
// Todo, how to pull apart an input to print relevant information
|
||||||
fmt.Printf("%s: %v\n", input.Key, input.Value)
|
fmt.Printf("%s: %v\n", input.Key, input.Value)
|
||||||
}
|
}
|
||||||
@ -49,8 +49,8 @@ var listCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
lg = lg.With().
|
lg = lg.With().
|
||||||
Str("deploymentName", deployment.Name).
|
Str("environmentName", environment.Name).
|
||||||
Str("deploymentId", deployment.ID).
|
Str("environmentId", environment.ID).
|
||||||
Logger()
|
Logger()
|
||||||
|
|
||||||
c, err := dagger.NewClient(ctx, "", false)
|
c, err := dagger.NewClient(ctx, "", false)
|
||||||
@ -58,7 +58,7 @@ var listCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("unable to create client")
|
lg.Fatal().Err(err).Msg("unable to create client")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.Do(ctx, deployment, func(lCtx context.Context, lDeploy *dagger.Deployment, lSolver dagger.Solver) error {
|
_, err = c.Do(ctx, environment, func(lCtx context.Context, lDeploy *dagger.Environment, lSolver dagger.Solver) error {
|
||||||
inputs, err := lDeploy.ScanInputs()
|
inputs, err := lDeploy.ScanInputs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -105,7 +105,7 @@ var listCmd = &cobra.Command{
|
|||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to query deployment")
|
lg.Fatal().Err(err).Msg("failed to query environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
@ -15,7 +15,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 deployment's inputs",
|
Short: "Manage an environment's inputs",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -31,7 +31,7 @@ func init() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateDeploymentInput(ctx context.Context, target string, input dagger.Input) {
|
func updateEnvironmentInput(ctx context.Context, target string, input dagger.Input) {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
store, err := dagger.DefaultStore()
|
store, err := dagger.DefaultStore()
|
||||||
@ -39,13 +39,13 @@ func updateDeploymentInput(ctx context.Context, target string, input dagger.Inpu
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
st := common.GetCurrentDeploymentState(ctx, store)
|
st := common.GetCurrentEnvironmentState(ctx, store)
|
||||||
st.SetInput(target, input)
|
st.SetInput(target, input)
|
||||||
|
|
||||||
if err := store.UpdateDeployment(ctx, st, nil); err != nil {
|
if err := store.UpdateEnvironment(ctx, st, nil); err != nil {
|
||||||
lg.Fatal().Err(err).Str("deploymentId", st.ID).Str("deploymentName", st.Name).Msg("cannot update deployment")
|
lg.Fatal().Err(err).Str("environmentId", st.ID).Str("environmentName", st.Name).Msg("cannot update environment")
|
||||||
}
|
}
|
||||||
lg.Info().Str("deploymentId", st.ID).Str("deploymentName", st.Name).Msg("updated deployment")
|
lg.Info().Str("environmentId", st.ID).Str("environmentName", st.Name).Msg("updated environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
func readInput(ctx context.Context, source string) string {
|
func readInput(ctx context.Context, source string) string {
|
||||||
|
@ -22,7 +22,7 @@ var textCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
updateDeploymentInput(
|
updateEnvironmentInput(
|
||||||
ctx,
|
ctx,
|
||||||
args[0],
|
args[0],
|
||||||
dagger.TextInput(readInput(ctx, args[1])),
|
dagger.TextInput(readInput(ctx, args[1])),
|
||||||
|
@ -22,7 +22,7 @@ var yamlCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
updateDeploymentInput(
|
updateEnvironmentInput(
|
||||||
ctx,
|
ctx,
|
||||||
args[0],
|
args[0],
|
||||||
dagger.YAMLInput(readInput(ctx, args[1])),
|
dagger.YAMLInput(readInput(ctx, args[1])),
|
||||||
|
@ -18,7 +18,7 @@ import (
|
|||||||
|
|
||||||
var listCmd = &cobra.Command{
|
var listCmd = &cobra.Command{
|
||||||
Use: "list",
|
Use: "list",
|
||||||
Short: "List available deployments",
|
Short: "List available environments",
|
||||||
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:
|
||||||
@ -35,20 +35,20 @@ var listCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
deployments, err := store.ListDeployments(ctx)
|
environments, err := store.ListEnvironments(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Err(err).
|
Err(err).
|
||||||
Msg("cannot list deployments")
|
Msg("cannot list environments")
|
||||||
}
|
}
|
||||||
|
|
||||||
deploymentID := getCurrentDeploymentID(ctx, store)
|
environmentID := getCurrentEnvironmentID(ctx, store)
|
||||||
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.TabIndent)
|
w := tabwriter.NewWriter(os.Stdout, 0, 0, 1, ' ', tabwriter.TabIndent)
|
||||||
for _, r := range deployments {
|
for _, r := range environments {
|
||||||
line := fmt.Sprintf("%s\t%s\t", r.Name, formatPlanSource(r.PlanSource))
|
line := fmt.Sprintf("%s\t%s\t", r.Name, formatPlanSource(r.PlanSource))
|
||||||
if r.ID == deploymentID {
|
if r.ID == environmentID {
|
||||||
line = fmt.Sprintf("%s- active deployment", line)
|
line = fmt.Sprintf("%s- active environment", line)
|
||||||
}
|
}
|
||||||
fmt.Fprintln(w, line)
|
fmt.Fprintln(w, line)
|
||||||
}
|
}
|
||||||
@ -62,7 +62,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCurrentDeploymentID(ctx context.Context, store *dagger.Store) string {
|
func getCurrentEnvironmentID(ctx context.Context, store *dagger.Store) string {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
wd, err := os.Getwd()
|
wd, err := os.Getwd()
|
||||||
@ -71,7 +71,7 @@ func getCurrentDeploymentID(ctx context.Context, store *dagger.Store) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
st, err := store.LookupDeploymentByPath(ctx, wd)
|
st, err := store.LookupEnvironmentByPath(ctx, wd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Ignore error
|
// Ignore error
|
||||||
return ""
|
return ""
|
||||||
|
@ -17,7 +17,7 @@ import (
|
|||||||
|
|
||||||
var newCmd = &cobra.Command{
|
var newCmd = &cobra.Command{
|
||||||
Use: "new",
|
Use: "new",
|
||||||
Short: "Create a new deployment",
|
Short: "Create a new environment",
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(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:
|
||||||
@ -34,41 +34,41 @@ var newCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
if viper.GetString("deployment") != "" {
|
if viper.GetString("environment") != "" {
|
||||||
lg.
|
lg.
|
||||||
Fatal().
|
Fatal().
|
||||||
Msg("cannot use option -d,--deployment for this command")
|
Msg("cannot use option -d,--environment for this command")
|
||||||
}
|
}
|
||||||
|
|
||||||
name := ""
|
name := ""
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
name = args[0]
|
name = args[0]
|
||||||
} else {
|
} else {
|
||||||
name = getNewDeploymentName(ctx)
|
name = getNewEnvironmentName(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
st := &dagger.DeploymentState{
|
st := &dagger.EnvironmentState{
|
||||||
Name: name,
|
Name: name,
|
||||||
PlanSource: getPlanSource(ctx),
|
PlanSource: getPlanSource(ctx),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.CreateDeployment(ctx, st)
|
err = store.CreateEnvironment(ctx, st)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to create deployment")
|
lg.Fatal().Err(err).Msg("failed to create environment")
|
||||||
}
|
}
|
||||||
lg.
|
lg.
|
||||||
Info().
|
Info().
|
||||||
Str("deploymentId", st.ID).
|
Str("environmentId", st.ID).
|
||||||
Str("deploymentName", st.Name).
|
Str("environmentName", st.Name).
|
||||||
Msg("deployment created")
|
Msg("environment created")
|
||||||
|
|
||||||
if viper.GetBool("up") {
|
if viper.GetBool("up") {
|
||||||
common.DeploymentUp(ctx, st, false)
|
common.EnvironmentUp(ctx, st, false)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func getNewDeploymentName(ctx context.Context) string {
|
func getNewEnvironmentName(ctx context.Context) string {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
workDir, err := os.Getwd()
|
workDir, err := os.Getwd()
|
||||||
@ -133,7 +133,7 @@ func getPlanSource(ctx context.Context) dagger.Input {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
newCmd.Flags().BoolP("up", "u", false, "Bring the deployment online")
|
newCmd.Flags().BoolP("up", "u", false, "Bring the environment online")
|
||||||
|
|
||||||
newCmd.Flags().String("plan-dir", "", "Load plan from a local directory")
|
newCmd.Flags().String("plan-dir", "", "Load plan from a local directory")
|
||||||
newCmd.Flags().String("plan-git", "", "Load plan from a git repository")
|
newCmd.Flags().String("plan-git", "", "Load plan 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 deployment's outputs",
|
Short: "Manage an environment's outputs",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -22,7 +22,7 @@ var dirCmd = &cobra.Command{
|
|||||||
lg := logger.New()
|
lg := logger.New()
|
||||||
ctx := lg.WithContext(cmd.Context())
|
ctx := lg.WithContext(cmd.Context())
|
||||||
|
|
||||||
updateDeploymentPlan(ctx, dagger.DirInput(args[0], []string{"*.cue", "cue.mod"}))
|
updateEnvironmentPlan(ctx, dagger.DirInput(args[0], []string{"*.cue", "cue.mod"}))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ var gitCmd = &cobra.Command{
|
|||||||
subDir = args[2]
|
subDir = args[2]
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDeploymentPlan(ctx, dagger.GitInput(args[0], ref, subDir))
|
updateEnvironmentPlan(ctx, dagger.GitInput(args[0], ref, 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: "plan",
|
Use: "plan",
|
||||||
Short: "Manage a deployment's plan",
|
Short: "Manage an environment's plan",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -24,7 +24,7 @@ func init() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateDeploymentPlan(ctx context.Context, planSource dagger.Input) {
|
func updateEnvironmentPlan(ctx context.Context, planSource dagger.Input) {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
store, err := dagger.DefaultStore()
|
store, err := dagger.DefaultStore()
|
||||||
@ -32,11 +32,11 @@ func updateDeploymentPlan(ctx context.Context, planSource dagger.Input) {
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
st := common.GetCurrentDeploymentState(ctx, store)
|
st := common.GetCurrentEnvironmentState(ctx, store)
|
||||||
st.PlanSource = planSource
|
st.PlanSource = planSource
|
||||||
|
|
||||||
if err := store.UpdateDeployment(ctx, st, nil); err != nil {
|
if err := store.UpdateEnvironment(ctx, st, nil); err != nil {
|
||||||
lg.Fatal().Err(err).Str("deploymentId", st.ID).Str("deploymentName", st.Name).Msg("cannot update deployment")
|
lg.Fatal().Err(err).Str("environmentId", st.ID).Str("environmentName", st.Name).Msg("cannot update environment")
|
||||||
}
|
}
|
||||||
lg.Info().Str("deploymentId", st.ID).Str("deploymentName", st.Name).Msg("updated deployment")
|
lg.Info().Str("environmentId", st.ID).Str("environmentName", st.Name).Msg("updated environment")
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
var queryCmd = &cobra.Command{
|
var queryCmd = &cobra.Command{
|
||||||
Use: "query [TARGET] [flags]",
|
Use: "query [TARGET] [flags]",
|
||||||
Short: "Query the contents of a deployment",
|
Short: "Query the contents of an environment",
|
||||||
Args: cobra.MaximumNArgs(1),
|
Args: cobra.MaximumNArgs(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:
|
||||||
@ -35,11 +35,11 @@ var queryCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
state := common.GetCurrentDeploymentState(ctx, store)
|
state := common.GetCurrentEnvironmentState(ctx, store)
|
||||||
|
|
||||||
lg = lg.With().
|
lg = lg.With().
|
||||||
Str("deploymentName", state.Name).
|
Str("environmentName", state.Name).
|
||||||
Str("deploymentId", state.ID).
|
Str("environmentId", state.ID).
|
||||||
Logger()
|
Logger()
|
||||||
|
|
||||||
cuePath := cue.MakePath()
|
cuePath := cue.MakePath()
|
||||||
@ -52,21 +52,21 @@ var queryCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("unable to create client")
|
lg.Fatal().Err(err).Msg("unable to create client")
|
||||||
}
|
}
|
||||||
|
|
||||||
deployment, err := c.Do(ctx, state, nil)
|
environment, err := c.Do(ctx, state, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to query deployment")
|
lg.Fatal().Err(err).Msg("failed to query environment")
|
||||||
}
|
}
|
||||||
|
|
||||||
cueVal := compiler.NewValue()
|
cueVal := compiler.NewValue()
|
||||||
|
|
||||||
if !viper.GetBool("no-plan") {
|
if !viper.GetBool("no-plan") {
|
||||||
if err := cueVal.FillPath(cue.MakePath(), deployment.Plan()); err != nil {
|
if err := cueVal.FillPath(cue.MakePath(), environment.Plan()); err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to merge plan")
|
lg.Fatal().Err(err).Msg("failed to merge plan")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !viper.GetBool("no-input") {
|
if !viper.GetBool("no-input") {
|
||||||
if err := cueVal.FillPath(cue.MakePath(), deployment.Input()); err != nil {
|
if err := cueVal.FillPath(cue.MakePath(), environment.Input()); err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to merge plan with output")
|
lg.Fatal().Err(err).Msg("failed to merge plan with output")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +139,7 @@ func init() {
|
|||||||
queryCmd.Flags().BoolP("show-attributes", "A", false, "Display field attributes (cue format only)")
|
queryCmd.Flags().BoolP("show-attributes", "A", false, "Display field attributes (cue format only)")
|
||||||
|
|
||||||
// FIXME: implement the flags below
|
// FIXME: implement the flags below
|
||||||
// queryCmd.Flags().String("revision", "latest", "Query a specific version of the deployment")
|
// queryCmd.Flags().String("revision", "latest", "Query a specific version of the environment")
|
||||||
queryCmd.Flags().StringP("format", "f", "json", "Output format (json|yaml|cue|text|env)")
|
queryCmd.Flags().StringP("format", "f", "json", "Output format (json|yaml|cue|text|env)")
|
||||||
queryCmd.Flags().BoolP("no-plan", "P", false, "Exclude plan from query")
|
queryCmd.Flags().BoolP("no-plan", "P", false, "Exclude plan from query")
|
||||||
queryCmd.Flags().BoolP("no-input", "I", false, "Exclude inputs from query")
|
queryCmd.Flags().BoolP("no-input", "I", false, "Exclude inputs from query")
|
||||||
|
@ -17,13 +17,13 @@ import (
|
|||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "dagger",
|
Use: "dagger",
|
||||||
Short: "A programmable deployment system",
|
Short: "A programmable environment system",
|
||||||
}
|
}
|
||||||
|
|
||||||
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", "info", "Log level")
|
rootCmd.PersistentFlags().StringP("log-level", "l", "info", "Log level")
|
||||||
rootCmd.PersistentFlags().StringP("deployment", "d", "", "Select a deployment")
|
rootCmd.PersistentFlags().StringP("environment", "e", "", "Select an environment")
|
||||||
|
|
||||||
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 deployment online with latest plan and inputs",
|
Short: "Bring an environment online with latest plan 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,11 +28,11 @@ var upCmd = &cobra.Command{
|
|||||||
lg.Fatal().Err(err).Msg("failed to load store")
|
lg.Fatal().Err(err).Msg("failed to load store")
|
||||||
}
|
}
|
||||||
|
|
||||||
state := common.GetCurrentDeploymentState(ctx, store)
|
state := common.GetCurrentEnvironmentState(ctx, store)
|
||||||
result := common.DeploymentUp(ctx, state, viper.GetBool("no-cache"))
|
result := common.EnvironmentUp(ctx, state, viper.GetBool("no-cache"))
|
||||||
state.Computed = result.Computed().JSON().String()
|
state.Computed = result.Computed().JSON().String()
|
||||||
if err := store.UpdateDeployment(ctx, state, nil); err != nil {
|
if err := store.UpdateEnvironment(ctx, state, nil); err != nil {
|
||||||
lg.Fatal().Err(err).Msg("failed to update deployment")
|
lg.Fatal().Err(err).Msg("failed to update environment")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
64
cmd/spec.cue
64
cmd/spec.cue
@ -29,27 +29,27 @@ import (
|
|||||||
description: "Write code to deploy your code"
|
description: "Write code to deploy your code"
|
||||||
|
|
||||||
doc: """
|
doc: """
|
||||||
A Dagger deployment is a continuously running workflow delivering a specific application in a specific way.
|
A Dagger environment is a continuously running workflow delivering a specific application in a specific way.
|
||||||
|
|
||||||
The same application can be delivered via different deployments, each with a different configuration.
|
The same application can be delivered via different environments, each with a different configuration.
|
||||||
For example a production deployment might include manual validation and addition performance testing,
|
For example a production environment might include manual validation and addition performance testing,
|
||||||
while a staging deployment might automatically deploy from a git branch, load test data into the database,
|
while a staging environment might automatically deploy from a git branch, load test data into the database,
|
||||||
and run on a separate cluster.
|
and run on a separate cluster.
|
||||||
|
|
||||||
A deployment is made of 3 parts: a deployment plan, inputs, and outputs.
|
An environment is made of 3 parts: a plan, inputs, and outputs.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
flag: {
|
flag: {
|
||||||
"--deployment": {
|
"--environment": {
|
||||||
alt: "-d"
|
alt: "-d"
|
||||||
description:
|
description:
|
||||||
"""
|
"""
|
||||||
Select a deployment
|
Select an environment
|
||||||
|
|
||||||
If no deployment is specified, dagger searches for deployments using the current
|
If no environment is specified, dagger searches for environments using the current
|
||||||
directory as input.
|
directory as input.
|
||||||
|
|
||||||
* If exactly one deployment matches the search, it is selected.
|
* If exactly one environment matches the search, it is selected.
|
||||||
* If there is more than one match, the user is prompted to select one.
|
* If there is more than one match, the user is prompted to select one.
|
||||||
* If there is no match, the command returns an error.
|
* If there is no match, the command returns an error.
|
||||||
"""
|
"""
|
||||||
@ -69,25 +69,25 @@ import (
|
|||||||
|
|
||||||
command: {
|
command: {
|
||||||
new: {
|
new: {
|
||||||
description: "Create a new deployment"
|
description: "Create a new environment"
|
||||||
flag: {
|
flag: {
|
||||||
"--name": {
|
"--name": {
|
||||||
alt: "-n"
|
alt: "-n"
|
||||||
description: "Specify a deployment name"
|
description: "Specify an environment name"
|
||||||
default: "name of current directory"
|
default: "name of current directory"
|
||||||
}
|
}
|
||||||
|
|
||||||
"--plan-dir": description: "Load deployment plan from a local directory"
|
"--plan-dir": description: "Load plan from a local directory"
|
||||||
|
|
||||||
"--plan-git": description: "Load deployment plan from a git repository"
|
"--plan-git": description: "Load plan from a git repository"
|
||||||
|
|
||||||
"--plan-package": description: "Load deployment plan from a cue package"
|
"--plan-package": description: "Load plan from a cue package"
|
||||||
|
|
||||||
"--plan-file": description: "Load deployment plan from a cue or json file"
|
"--plan-file": description: "Load plan from a cue or json file"
|
||||||
|
|
||||||
"--up": {
|
"--up": {
|
||||||
alt: "-u"
|
alt: "-u"
|
||||||
description: "Bring the deployment online"
|
description: "Bring the environment online"
|
||||||
}
|
}
|
||||||
|
|
||||||
"--setup": {
|
"--setup": {
|
||||||
@ -97,26 +97,26 @@ import (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
list: description: "List available deployments"
|
list: description: "List available environments"
|
||||||
|
|
||||||
query: {
|
query: {
|
||||||
arg: "[EXPR] [flags]"
|
arg: "[EXPR] [flags]"
|
||||||
description: "Query the contents of a deployment"
|
description: "Query the contents of an environment"
|
||||||
doc:
|
doc:
|
||||||
"""
|
"""
|
||||||
EXPR may be any valid CUE expression. The expression is evaluated against the deployment contents. The deployment is not changed.
|
EXPR may be any valid CUE expression. The expression is evaluated against the environment contents. The environment is not changed.
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
# Print the entire deployment plan with inputs merged in (but no outputs)
|
# Print the entire plan with inputs merged in (but no outputs)
|
||||||
$ dagger query --no-output
|
$ dagger query --no-output
|
||||||
|
|
||||||
# Print the deployment plan, inputs and outputs of a particular step
|
# Print the plan, inputs and outputs of a particular step
|
||||||
$ dagger query www.build
|
$ dagger query www.build
|
||||||
|
|
||||||
# Print the URL of a deployed service
|
# Print the URL of a deployed service
|
||||||
$ dagger query api.url
|
$ dagger query api.url
|
||||||
|
|
||||||
# Export environment variables from a deployment
|
# Export environment variables from an environment
|
||||||
$ dagger query -f json api.environment
|
$ dagger query -f json api.environment
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -127,7 +127,7 @@ import (
|
|||||||
// Use --revision or --change or --change-id instead?
|
// Use --revision or --change or --change-id instead?
|
||||||
"--version": {
|
"--version": {
|
||||||
alt: "-v"
|
alt: "-v"
|
||||||
description: "Query a specific version of the deployment"
|
description: "Query a specific version of the environment"
|
||||||
default: "latest"
|
default: "latest"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,29 +147,29 @@ import (
|
|||||||
}
|
}
|
||||||
"--no-plan": {
|
"--no-plan": {
|
||||||
alt: "-L"
|
alt: "-L"
|
||||||
description: "Exclude deployment plan from query"
|
description: "Exclude plan from query"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
up: {
|
up: {
|
||||||
description: "Bring a deployment online with latest deployment plan and inputs"
|
description: "Bring an environment online with latest plan and inputs"
|
||||||
flag: "--no-cache": description: "Disable all run cache"
|
flag: "--no-cache": description: "Disable all run cache"
|
||||||
}
|
}
|
||||||
|
|
||||||
down: {
|
down: {
|
||||||
description: "Take a deployment offline (WARNING: may destroy infrastructure)"
|
description: "Take an environment offline (WARNING: may destroy infrastructure)"
|
||||||
flag: "--no-cache": description: "Disable all run cache"
|
flag: "--no-cache": description: "Disable all run cache"
|
||||||
}
|
}
|
||||||
|
|
||||||
history: description: "List past changes to a deployment"
|
history: description: "List past changes to an environment"
|
||||||
|
|
||||||
delete: {
|
delete: {
|
||||||
description: "Delete a deployment after taking it offline (WARNING: may destroy infrastructure)"
|
description: "Delete an environment after taking it offline (WARNING: may destroy infrastructure)"
|
||||||
}
|
}
|
||||||
|
|
||||||
plan: {
|
plan: {
|
||||||
description: "Manage a deployment plan"
|
description: "Manage an environment plan"
|
||||||
|
|
||||||
command: {
|
command: {
|
||||||
package: {
|
package: {
|
||||||
@ -216,7 +216,7 @@ import (
|
|||||||
}
|
}
|
||||||
|
|
||||||
input: {
|
input: {
|
||||||
description: "Manage a deployment's inputs"
|
description: "Manage an environment's inputs"
|
||||||
|
|
||||||
command: {
|
command: {
|
||||||
// FIXME: details of individual input commands
|
// FIXME: details of individual input commands
|
||||||
@ -229,10 +229,10 @@ import (
|
|||||||
}
|
}
|
||||||
|
|
||||||
output: {
|
output: {
|
||||||
description: "Manage a deployment's outputs"
|
description: "Manage an environment's outputs"
|
||||||
// FIXME: bind output values or artifacts
|
// FIXME: bind output values or artifacts
|
||||||
// to local dir or file
|
// to local dir or file
|
||||||
// BONUS: bind a deployment output to another deployment's input?
|
// BONUS: bind an environment output to another environment's input?
|
||||||
}
|
}
|
||||||
|
|
||||||
login: description: "Login to Dagger Cloud"
|
login: description: "Login to Dagger Cloud"
|
||||||
|
@ -60,14 +60,14 @@ func NewClient(ctx context.Context, host string, noCache bool) (*Client, error)
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClientDoFunc func(context.Context, *Deployment, Solver) error
|
type ClientDoFunc func(context.Context, *Environment, Solver) error
|
||||||
|
|
||||||
// FIXME: return completed *Route, instead of *compiler.Value
|
// FIXME: return completed *Route, instead of *compiler.Value
|
||||||
func (c *Client) Do(ctx context.Context, state *DeploymentState, fn ClientDoFunc) (*Deployment, error) {
|
func (c *Client) Do(ctx context.Context, state *EnvironmentState, fn ClientDoFunc) (*Environment, error) {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
eg, gctx := errgroup.WithContext(ctx)
|
eg, gctx := errgroup.WithContext(ctx)
|
||||||
|
|
||||||
deployment, err := NewDeployment(state)
|
environment, err := NewEnvironment(state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -83,17 +83,17 @@ func (c *Client) Do(ctx context.Context, state *DeploymentState, fn ClientDoFunc
|
|||||||
|
|
||||||
// Spawn build function
|
// Spawn build function
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
return c.buildfn(gctx, deployment, fn, events)
|
return c.buildfn(gctx, environment, fn, events)
|
||||||
})
|
})
|
||||||
|
|
||||||
return deployment, eg.Wait()
|
return environment, eg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) buildfn(ctx context.Context, deployment *Deployment, fn ClientDoFunc, ch chan *bk.SolveStatus) error {
|
func (c *Client) buildfn(ctx context.Context, environment *Environment, fn ClientDoFunc, ch chan *bk.SolveStatus) error {
|
||||||
lg := log.Ctx(ctx)
|
lg := log.Ctx(ctx)
|
||||||
|
|
||||||
// Scan local dirs to grant access
|
// Scan local dirs to grant access
|
||||||
localdirs := deployment.LocalDirs()
|
localdirs := environment.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 {
|
||||||
@ -121,24 +121,24 @@ func (c *Client) buildfn(ctx context.Context, deployment *Deployment, fn ClientD
|
|||||||
s := NewSolver(c.c, gw, ch, auth, c.noCache)
|
s := NewSolver(c.c, gw, ch, auth, c.noCache)
|
||||||
|
|
||||||
lg.Debug().Msg("loading configuration")
|
lg.Debug().Msg("loading configuration")
|
||||||
if err := deployment.LoadPlan(ctx, s); err != nil {
|
if err := environment.LoadPlan(ctx, s); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute output overlay
|
// Compute output overlay
|
||||||
if fn != nil {
|
if fn != nil {
|
||||||
if err := fn(ctx, deployment, s); err != nil {
|
if err := fn(ctx, environment, s); err != nil {
|
||||||
return nil, compiler.Err(err)
|
return nil, compiler.Err(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export deployment to a cue directory
|
// Export environment to a cue directory
|
||||||
// FIXME: this should be elsewhere
|
// FIXME: this should be elsewhere
|
||||||
lg.Debug().Msg("exporting deployment")
|
lg.Debug().Msg("exporting environment")
|
||||||
span, _ := opentracing.StartSpanFromContext(ctx, "Deployment.Export")
|
span, _ := opentracing.StartSpanFromContext(ctx, "Environment.Export")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
computed := deployment.Computed().JSON().PrettyString()
|
computed := environment.Computed().JSON().PrettyString()
|
||||||
st := llb.
|
st := llb.
|
||||||
Scratch().
|
Scratch().
|
||||||
File(
|
File(
|
||||||
|
@ -19,8 +19,8 @@ import (
|
|||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Deployment struct {
|
type Environment struct {
|
||||||
state *DeploymentState
|
state *EnvironmentState
|
||||||
|
|
||||||
// Layer 1: plan configuration
|
// Layer 1: plan configuration
|
||||||
plan *compiler.Value
|
plan *compiler.Value
|
||||||
@ -32,8 +32,8 @@ type Deployment struct {
|
|||||||
computed *compiler.Value
|
computed *compiler.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDeployment(st *DeploymentState) (*Deployment, error) {
|
func NewEnvironment(st *EnvironmentState) (*Environment, error) {
|
||||||
d := &Deployment{
|
d := &Environment{
|
||||||
state: st,
|
state: st,
|
||||||
|
|
||||||
plan: compiler.NewValue(),
|
plan: compiler.NewValue(),
|
||||||
@ -60,33 +60,33 @@ func NewDeployment(st *DeploymentState) (*Deployment, error) {
|
|||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deployment) ID() string {
|
func (d *Environment) ID() string {
|
||||||
return d.state.ID
|
return d.state.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deployment) Name() string {
|
func (d *Environment) Name() string {
|
||||||
return d.state.Name
|
return d.state.Name
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deployment) PlanSource() Input {
|
func (d *Environment) PlanSource() Input {
|
||||||
return d.state.PlanSource
|
return d.state.PlanSource
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deployment) Plan() *compiler.Value {
|
func (d *Environment) Plan() *compiler.Value {
|
||||||
return d.plan
|
return d.plan
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deployment) Input() *compiler.Value {
|
func (d *Environment) Input() *compiler.Value {
|
||||||
return d.input
|
return d.input
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deployment) Computed() *compiler.Value {
|
func (d *Environment) Computed() *compiler.Value {
|
||||||
return d.computed
|
return d.computed
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadPlan loads the plan
|
// LoadPlan loads the plan
|
||||||
func (d *Deployment) LoadPlan(ctx context.Context, s Solver) error {
|
func (d *Environment) LoadPlan(ctx context.Context, s Solver) error {
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, "deployment.LoadPlan")
|
span, ctx := opentracing.StartSpanFromContext(ctx, "environment.LoadPlan")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
planSource, err := d.state.PlanSource.Compile()
|
planSource, err := d.state.PlanSource.Compile()
|
||||||
@ -114,11 +114,11 @@ func (d *Deployment) LoadPlan(ctx context.Context, s Solver) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Scan all scripts in the deployment for references to local directories (do:"local"),
|
// Scan all scripts in the environment 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 (d *Deployment) LocalDirs() map[string]string {
|
func (d *Environment) LocalDirs() map[string]string {
|
||||||
dirs := map[string]string{}
|
dirs := map[string]string{}
|
||||||
localdirs := func(code ...*compiler.Value) {
|
localdirs := func(code ...*compiler.Value) {
|
||||||
Analyze(
|
Analyze(
|
||||||
@ -140,7 +140,7 @@ func (d *Deployment) LocalDirs() map[string]string {
|
|||||||
code...,
|
code...,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// 1. Scan the deployment state
|
// 1. Scan the environment state
|
||||||
// FIXME: use a common `flow` instance to avoid rescanning the tree.
|
// FIXME: use a common `flow` instance to avoid rescanning the tree.
|
||||||
src, err := compiler.InstanceMerge(d.plan, d.input)
|
src, err := compiler.InstanceMerge(d.plan, d.input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -165,9 +165,9 @@ func (d *Deployment) LocalDirs() map[string]string {
|
|||||||
return dirs
|
return dirs
|
||||||
}
|
}
|
||||||
|
|
||||||
// Up missing values in deployment configuration, and write them to state.
|
// Up missing values in environment configuration, and write them to state.
|
||||||
func (d *Deployment) Up(ctx context.Context, s Solver) error {
|
func (d *Environment) Up(ctx context.Context, s Solver) error {
|
||||||
span, ctx := opentracing.StartSpanFromContext(ctx, "deployment.Up")
|
span, ctx := opentracing.StartSpanFromContext(ctx, "environment.Up")
|
||||||
defer span.Finish()
|
defer span.Finish()
|
||||||
|
|
||||||
// Reset the computed values
|
// Reset the computed values
|
||||||
@ -194,7 +194,7 @@ func (d *Deployment) Up(ctx context.Context, s Solver) error {
|
|||||||
|
|
||||||
type DownOpts struct{}
|
type DownOpts struct{}
|
||||||
|
|
||||||
func (d *Deployment) Down(ctx context.Context, _ *DownOpts) error {
|
func (d *Environment) Down(ctx context.Context, _ *DownOpts) error {
|
||||||
panic("NOT IMPLEMENTED")
|
panic("NOT IMPLEMENTED")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +292,7 @@ func newPipelineRunner(inst *cue.Instance, computed *compiler.Value, s Solver) c
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Deployment) ScanInputs() ([]cue.Value, error) {
|
func (d *Environment) ScanInputs() ([]cue.Value, error) {
|
||||||
vals, err := cuetils.ScanForInputs(d.plan.Cue())
|
vals, err := cuetils.ScanForInputs(d.plan.Cue())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -7,15 +7,15 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestInputDir(t *testing.T) {
|
func TestInputDir(t *testing.T) {
|
||||||
st := &DeploymentState{
|
st := &EnvironmentState{
|
||||||
PlanSource: DirInput("/tmp/source", []string{}),
|
PlanSource: DirInput("/tmp/source", []string{}),
|
||||||
}
|
}
|
||||||
require.NoError(t, st.SetInput("www.source", DirInput("/", []string{})))
|
require.NoError(t, st.SetInput("www.source", DirInput("/", []string{})))
|
||||||
|
|
||||||
deployment, err := NewDeployment(st)
|
environment, err := NewEnvironment(st)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
localdirs := deployment.LocalDirs()
|
localdirs := environment.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")
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
package dagger
|
package dagger
|
||||||
|
|
||||||
// Contents of a deployment serialized to a file
|
// Contents of an environment serialized to a file
|
||||||
type DeploymentState struct {
|
type EnvironmentState struct {
|
||||||
// Globally unique deployment ID
|
// Globally unique environment ID
|
||||||
ID string `json:"id,omitempty"`
|
ID string `json:"id,omitempty"`
|
||||||
|
|
||||||
// Human-friendly deployment name.
|
// Human-friendly environment name.
|
||||||
// A deployment may have more than one name.
|
// A environment 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 deployment plan
|
// Cue module containing the environment plan
|
||||||
// The input's top-level artifact is used as a module directory.
|
// The input's top-level artifact is used as a module directory.
|
||||||
PlanSource Input `json:"plan,omitempty"`
|
PlanSource Input `json:"plan,omitempty"`
|
||||||
|
|
||||||
@ -26,7 +26,7 @@ type inputKV struct {
|
|||||||
Value Input `json:"value,omitempty"`
|
Value Input `json:"value,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *DeploymentState) SetInput(key string, value Input) error {
|
func (s *EnvironmentState) SetInput(key string, value Input) error {
|
||||||
for i, inp := range s.Inputs {
|
for i, inp := range s.Inputs {
|
||||||
if inp.Key != key {
|
if inp.Key != key {
|
||||||
continue
|
continue
|
||||||
@ -42,7 +42,7 @@ func (s *DeploymentState) SetInput(key string, value Input) error {
|
|||||||
// 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 (s *DeploymentState) RemoveInputs(key string) error {
|
func (s *EnvironmentState) RemoveInputs(key string) error {
|
||||||
newInputs := make([]inputKV, 0, len(s.Inputs))
|
newInputs := make([]inputKV, 0, len(s.Inputs))
|
||||||
for _, i := range s.Inputs {
|
for _, i := range s.Inputs {
|
||||||
if i.Key == key {
|
if i.Key == key {
|
||||||
|
134
dagger/store.go
134
dagger/store.go
@ -13,8 +13,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrDeploymentExist = errors.New("deployment already exists")
|
ErrEnvironmentExist = errors.New("environment already exists")
|
||||||
ErrDeploymentNotExist = errors.New("deployment doesn't exist")
|
ErrEnvironmentNotExist = errors.New("environment doesn't exist")
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -26,26 +26,26 @@ type Store struct {
|
|||||||
|
|
||||||
l sync.RWMutex
|
l sync.RWMutex
|
||||||
|
|
||||||
// ID -> Deployment
|
// ID -> Environment
|
||||||
deployments map[string]*DeploymentState
|
environments map[string]*EnvironmentState
|
||||||
|
|
||||||
// Name -> Deployment
|
// Name -> Environment
|
||||||
deploymentsByName map[string]*DeploymentState
|
environmentsByName map[string]*EnvironmentState
|
||||||
|
|
||||||
// Path -> (ID->Deployment)
|
// Path -> (ID->Environment)
|
||||||
deploymentsByPath map[string]map[string]*DeploymentState
|
environmentsByPath map[string]map[string]*EnvironmentState
|
||||||
|
|
||||||
// ID -> (Path->{})
|
// ID -> (Path->{})
|
||||||
pathsByDeploymentID map[string]map[string]struct{}
|
pathsByEnvironmentID map[string]map[string]struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStore(root string) (*Store, error) {
|
func NewStore(root string) (*Store, error) {
|
||||||
store := &Store{
|
store := &Store{
|
||||||
root: root,
|
root: root,
|
||||||
deployments: make(map[string]*DeploymentState),
|
environments: make(map[string]*EnvironmentState),
|
||||||
deploymentsByName: make(map[string]*DeploymentState),
|
environmentsByName: make(map[string]*EnvironmentState),
|
||||||
deploymentsByPath: make(map[string]map[string]*DeploymentState),
|
environmentsByPath: make(map[string]map[string]*EnvironmentState),
|
||||||
pathsByDeploymentID: make(map[string]map[string]struct{}),
|
pathsByEnvironmentID: make(map[string]map[string]struct{}),
|
||||||
}
|
}
|
||||||
return store, store.loadAll()
|
return store, store.loadAll()
|
||||||
}
|
}
|
||||||
@ -58,8 +58,8 @@ func DefaultStore() (*Store, error) {
|
|||||||
return NewStore(os.ExpandEnv(defaultStoreRoot))
|
return NewStore(os.ExpandEnv(defaultStoreRoot))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) deploymentPath(name string) string {
|
func (s *Store) environmentPath(name string) string {
|
||||||
return path.Join(s.root, name, "deployment.json")
|
return path.Join(s.root, name, "environment.json")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) loadAll() error {
|
func (s *Store) loadAll() error {
|
||||||
@ -75,7 +75,7 @@ func (s *Store) loadAll() error {
|
|||||||
if !f.IsDir() {
|
if !f.IsDir() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if err := s.loadDeployment(f.Name()); err != nil {
|
if err := s.loadEnvironment(f.Name()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,21 +83,21 @@ func (s *Store) loadAll() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) loadDeployment(name string) error {
|
func (s *Store) loadEnvironment(name string) error {
|
||||||
data, err := os.ReadFile(s.deploymentPath(name))
|
data, err := os.ReadFile(s.environmentPath(name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var st DeploymentState
|
var st EnvironmentState
|
||||||
if err := json.Unmarshal(data, &st); err != nil {
|
if err := json.Unmarshal(data, &st); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.indexDeployment(&st)
|
s.indexEnvironment(&st)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) syncDeployment(r *DeploymentState) error {
|
func (s *Store) syncEnvironment(r *EnvironmentState) error {
|
||||||
p := s.deploymentPath(r.Name)
|
p := s.environmentPath(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
|
||||||
@ -112,28 +112,28 @@ func (s *Store) syncDeployment(r *DeploymentState) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.reindexDeployment(r)
|
s.reindexEnvironment(r)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) indexDeployment(r *DeploymentState) {
|
func (s *Store) indexEnvironment(r *EnvironmentState) {
|
||||||
s.deployments[r.ID] = r
|
s.environments[r.ID] = r
|
||||||
s.deploymentsByName[r.Name] = r
|
s.environmentsByName[r.Name] = r
|
||||||
|
|
||||||
mapPath := func(i Input) {
|
mapPath := func(i Input) {
|
||||||
if i.Type != InputTypeDir {
|
if i.Type != InputTypeDir {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.deploymentsByPath[i.Dir.Path] == nil {
|
if s.environmentsByPath[i.Dir.Path] == nil {
|
||||||
s.deploymentsByPath[i.Dir.Path] = make(map[string]*DeploymentState)
|
s.environmentsByPath[i.Dir.Path] = make(map[string]*EnvironmentState)
|
||||||
}
|
}
|
||||||
s.deploymentsByPath[i.Dir.Path][r.ID] = r
|
s.environmentsByPath[i.Dir.Path][r.ID] = r
|
||||||
|
|
||||||
if s.pathsByDeploymentID[r.ID] == nil {
|
if s.pathsByEnvironmentID[r.ID] == nil {
|
||||||
s.pathsByDeploymentID[r.ID] = make(map[string]struct{})
|
s.pathsByEnvironmentID[r.ID] = make(map[string]struct{})
|
||||||
}
|
}
|
||||||
s.pathsByDeploymentID[r.ID][i.Dir.Path] = struct{}{}
|
s.pathsByEnvironmentID[r.ID][i.Dir.Path] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapPath(r.PlanSource)
|
mapPath(r.PlanSource)
|
||||||
@ -142,108 +142,108 @@ func (s *Store) indexDeployment(r *DeploymentState) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) deindexDeployment(id string) {
|
func (s *Store) deindexEnvironment(id string) {
|
||||||
r, ok := s.deployments[id]
|
r, ok := s.environments[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
delete(s.deployments, r.ID)
|
delete(s.environments, r.ID)
|
||||||
delete(s.deploymentsByName, r.Name)
|
delete(s.environmentsByName, r.Name)
|
||||||
|
|
||||||
for p := range s.pathsByDeploymentID[r.ID] {
|
for p := range s.pathsByEnvironmentID[r.ID] {
|
||||||
delete(s.deploymentsByPath[p], r.ID)
|
delete(s.environmentsByPath[p], r.ID)
|
||||||
}
|
}
|
||||||
delete(s.pathsByDeploymentID, r.ID)
|
delete(s.pathsByEnvironmentID, r.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) reindexDeployment(r *DeploymentState) {
|
func (s *Store) reindexEnvironment(r *EnvironmentState) {
|
||||||
s.deindexDeployment(r.ID)
|
s.deindexEnvironment(r.ID)
|
||||||
s.indexDeployment(r)
|
s.indexEnvironment(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) CreateDeployment(ctx context.Context, st *DeploymentState) error {
|
func (s *Store) CreateEnvironment(ctx context.Context, st *EnvironmentState) error {
|
||||||
s.l.Lock()
|
s.l.Lock()
|
||||||
defer s.l.Unlock()
|
defer s.l.Unlock()
|
||||||
|
|
||||||
if _, ok := s.deploymentsByName[st.Name]; ok {
|
if _, ok := s.environmentsByName[st.Name]; ok {
|
||||||
return fmt.Errorf("%s: %w", st.Name, ErrDeploymentExist)
|
return fmt.Errorf("%s: %w", st.Name, ErrEnvironmentExist)
|
||||||
}
|
}
|
||||||
|
|
||||||
st.ID = uuid.New().String()
|
st.ID = uuid.New().String()
|
||||||
return s.syncDeployment(st)
|
return s.syncEnvironment(st)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UpdateOpts struct{}
|
type UpdateOpts struct{}
|
||||||
|
|
||||||
func (s *Store) UpdateDeployment(ctx context.Context, r *DeploymentState, o *UpdateOpts) error {
|
func (s *Store) UpdateEnvironment(ctx context.Context, r *EnvironmentState, o *UpdateOpts) error {
|
||||||
s.l.Lock()
|
s.l.Lock()
|
||||||
defer s.l.Unlock()
|
defer s.l.Unlock()
|
||||||
|
|
||||||
return s.syncDeployment(r)
|
return s.syncEnvironment(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
type DeleteOpts struct{}
|
type DeleteOpts struct{}
|
||||||
|
|
||||||
func (s *Store) DeleteDeployment(ctx context.Context, r *DeploymentState, o *DeleteOpts) error {
|
func (s *Store) DeleteEnvironment(ctx context.Context, r *EnvironmentState, o *DeleteOpts) error {
|
||||||
s.l.Lock()
|
s.l.Lock()
|
||||||
defer s.l.Unlock()
|
defer s.l.Unlock()
|
||||||
|
|
||||||
if err := os.Remove(s.deploymentPath(r.Name)); err != nil {
|
if err := os.Remove(s.environmentPath(r.Name)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
s.deindexDeployment(r.ID)
|
s.deindexEnvironment(r.ID)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) LookupDeploymentByID(ctx context.Context, id string) (*DeploymentState, error) {
|
func (s *Store) LookupEnvironmentByID(ctx context.Context, id string) (*EnvironmentState, error) {
|
||||||
s.l.RLock()
|
s.l.RLock()
|
||||||
defer s.l.RUnlock()
|
defer s.l.RUnlock()
|
||||||
|
|
||||||
st, ok := s.deployments[id]
|
st, ok := s.environments[id]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("%s: %w", id, ErrDeploymentNotExist)
|
return nil, fmt.Errorf("%s: %w", id, ErrEnvironmentNotExist)
|
||||||
}
|
}
|
||||||
return st, nil
|
return st, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) LookupDeploymentByName(ctx context.Context, name string) (*DeploymentState, error) {
|
func (s *Store) LookupEnvironmentByName(ctx context.Context, name string) (*EnvironmentState, error) {
|
||||||
s.l.RLock()
|
s.l.RLock()
|
||||||
defer s.l.RUnlock()
|
defer s.l.RUnlock()
|
||||||
|
|
||||||
st, ok := s.deploymentsByName[name]
|
st, ok := s.environmentsByName[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("%s: %w", name, ErrDeploymentNotExist)
|
return nil, fmt.Errorf("%s: %w", name, ErrEnvironmentNotExist)
|
||||||
}
|
}
|
||||||
return st, nil
|
return st, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) LookupDeploymentByPath(ctx context.Context, path string) ([]*DeploymentState, error) {
|
func (s *Store) LookupEnvironmentByPath(ctx context.Context, path string) ([]*EnvironmentState, error) {
|
||||||
s.l.RLock()
|
s.l.RLock()
|
||||||
defer s.l.RUnlock()
|
defer s.l.RUnlock()
|
||||||
|
|
||||||
res := []*DeploymentState{}
|
res := []*EnvironmentState{}
|
||||||
|
|
||||||
deployments, ok := s.deploymentsByPath[path]
|
environments, ok := s.environmentsByPath[path]
|
||||||
if !ok {
|
if !ok {
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, d := range deployments {
|
for _, d := range environments {
|
||||||
res = append(res, d)
|
res = append(res, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Store) ListDeployments(ctx context.Context) ([]*DeploymentState, error) {
|
func (s *Store) ListEnvironments(ctx context.Context) ([]*EnvironmentState, error) {
|
||||||
s.l.RLock()
|
s.l.RLock()
|
||||||
defer s.l.RUnlock()
|
defer s.l.RUnlock()
|
||||||
|
|
||||||
deployments := make([]*DeploymentState, 0, len(s.deployments))
|
environments := make([]*EnvironmentState, 0, len(s.environments))
|
||||||
|
|
||||||
for _, st := range s.deployments {
|
for _, st := range s.environments {
|
||||||
deployments = append(deployments, st)
|
environments = append(environments, st)
|
||||||
}
|
}
|
||||||
|
|
||||||
return deployments, nil
|
return environments, 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.LookupDeploymentByName(ctx, "notexist")
|
_, err = store.LookupEnvironmentByName(ctx, "notexist")
|
||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
require.True(t, errors.Is(err, ErrDeploymentNotExist))
|
require.True(t, errors.Is(err, ErrEnvironmentNotExist))
|
||||||
|
|
||||||
st := &DeploymentState{
|
st := &EnvironmentState{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
}
|
}
|
||||||
require.NoError(t, store.CreateDeployment(ctx, st))
|
require.NoError(t, store.CreateEnvironment(ctx, st))
|
||||||
|
|
||||||
checkDeployments := func(store *Store) {
|
checkEnvironments := func(store *Store) {
|
||||||
r, err := store.LookupDeploymentByID(ctx, st.ID)
|
r, err := store.LookupEnvironmentByID(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.LookupDeploymentByName(ctx, "test")
|
r, err = store.LookupEnvironmentByName(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)
|
||||||
|
|
||||||
deployments, err := store.ListDeployments(ctx)
|
environments, err := store.ListEnvironments(ctx)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, deployments, 1)
|
require.Len(t, environments, 1)
|
||||||
require.Equal(t, "test", deployments[0].Name)
|
require.Equal(t, "test", environments[0].Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDeployments(store)
|
checkEnvironments(store)
|
||||||
|
|
||||||
// Reload the deployments from disk and check again
|
// Reload the environments from disk and check again
|
||||||
newStore, err := NewStore(root)
|
newStore, err := NewStore(root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
checkDeployments(newStore)
|
checkEnvironments(newStore)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStoreLookupByPath(t *testing.T) {
|
func TestStoreLookupByPath(t *testing.T) {
|
||||||
@ -59,65 +59,65 @@ func TestStoreLookupByPath(t *testing.T) {
|
|||||||
store, err := NewStore(root)
|
store, err := NewStore(root)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
st := &DeploymentState{
|
st := &EnvironmentState{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
}
|
}
|
||||||
require.NoError(t, st.SetInput("foo", DirInput("/test/path", []string{})))
|
require.NoError(t, st.SetInput("foo", DirInput("/test/path", []string{})))
|
||||||
require.NoError(t, store.CreateDeployment(ctx, st))
|
require.NoError(t, store.CreateEnvironment(ctx, st))
|
||||||
|
|
||||||
// Lookup by path
|
// Lookup by path
|
||||||
deployments, err := store.LookupDeploymentByPath(ctx, "/test/path")
|
environments, err := store.LookupEnvironmentByPath(ctx, "/test/path")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, deployments, 1)
|
require.Len(t, environments, 1)
|
||||||
require.Equal(t, st.ID, deployments[0].ID)
|
require.Equal(t, st.ID, environments[0].ID)
|
||||||
|
|
||||||
// Add a new path
|
// Add a new path
|
||||||
require.NoError(t, st.SetInput("bar", DirInput("/test/anotherpath", []string{})))
|
require.NoError(t, st.SetInput("bar", DirInput("/test/anotherpath", []string{})))
|
||||||
require.NoError(t, store.UpdateDeployment(ctx, st, nil))
|
require.NoError(t, store.UpdateEnvironment(ctx, st, nil))
|
||||||
|
|
||||||
// Lookup by the previous path
|
// Lookup by the previous path
|
||||||
deployments, err = store.LookupDeploymentByPath(ctx, "/test/path")
|
environments, err = store.LookupEnvironmentByPath(ctx, "/test/path")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, deployments, 1)
|
require.Len(t, environments, 1)
|
||||||
require.Equal(t, st.ID, deployments[0].ID)
|
require.Equal(t, st.ID, environments[0].ID)
|
||||||
|
|
||||||
// Lookup by the new path
|
// Lookup by the new path
|
||||||
deployments, err = store.LookupDeploymentByPath(ctx, "/test/anotherpath")
|
environments, err = store.LookupEnvironmentByPath(ctx, "/test/anotherpath")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, deployments, 1)
|
require.Len(t, environments, 1)
|
||||||
require.Equal(t, st.ID, deployments[0].ID)
|
require.Equal(t, st.ID, environments[0].ID)
|
||||||
|
|
||||||
// Remove a path
|
// Remove a path
|
||||||
require.NoError(t, st.RemoveInputs("foo"))
|
require.NoError(t, st.RemoveInputs("foo"))
|
||||||
require.NoError(t, store.UpdateDeployment(ctx, st, nil))
|
require.NoError(t, store.UpdateEnvironment(ctx, st, nil))
|
||||||
|
|
||||||
// Lookup by the removed path should fail
|
// Lookup by the removed path should fail
|
||||||
deployments, err = store.LookupDeploymentByPath(ctx, "/test/path")
|
environments, err = store.LookupEnvironmentByPath(ctx, "/test/path")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, deployments, 0)
|
require.Len(t, environments, 0)
|
||||||
|
|
||||||
// Lookup by the other path should still work
|
// Lookup by the other path should still work
|
||||||
deployments, err = store.LookupDeploymentByPath(ctx, "/test/anotherpath")
|
environments, err = store.LookupEnvironmentByPath(ctx, "/test/anotherpath")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, deployments, 1)
|
require.Len(t, environments, 1)
|
||||||
|
|
||||||
// Add another deployment using the same path
|
// Add another environment using the same path
|
||||||
otherSt := &DeploymentState{
|
otherSt := &EnvironmentState{
|
||||||
Name: "test2",
|
Name: "test2",
|
||||||
}
|
}
|
||||||
require.NoError(t, otherSt.SetInput("foo", DirInput("/test/anotherpath", []string{})))
|
require.NoError(t, otherSt.SetInput("foo", DirInput("/test/anotherpath", []string{})))
|
||||||
require.NoError(t, store.CreateDeployment(ctx, otherSt))
|
require.NoError(t, store.CreateEnvironment(ctx, otherSt))
|
||||||
|
|
||||||
// Lookup by path should return both deployments
|
// Lookup by path should return both environments
|
||||||
deployments, err = store.LookupDeploymentByPath(ctx, "/test/anotherpath")
|
environments, err = store.LookupEnvironmentByPath(ctx, "/test/anotherpath")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, deployments, 2)
|
require.Len(t, environments, 2)
|
||||||
|
|
||||||
// Remove the first deployment. Lookup by path should still return the
|
// Remove the first environment. Lookup by path should still return the
|
||||||
// second deployment.
|
// second environment.
|
||||||
require.NoError(t, store.DeleteDeployment(ctx, st, nil))
|
require.NoError(t, store.DeleteEnvironment(ctx, st, nil))
|
||||||
deployments, err = store.LookupDeploymentByPath(ctx, "/test/anotherpath")
|
environments, err = store.LookupEnvironmentByPath(ctx, "/test/anotherpath")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, deployments, 1)
|
require.Len(t, environments, 1)
|
||||||
require.Equal(t, otherSt.ID, deployments[0].ID)
|
require.Equal(t, otherSt.ID, environments[0].ID)
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user