Skip to content

Commit

Permalink
wip: introduce app env migration when updating an app target
Browse files Browse the repository at this point in the history
Still a big WIP, a lot needs to be done before merging it
  • Loading branch information
YuukanOO committed Dec 23, 2024
1 parent 9a2b0a0 commit cadc280
Show file tree
Hide file tree
Showing 39 changed files with 663 additions and 668 deletions.
11 changes: 8 additions & 3 deletions cmd/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ const (
)

type (
// Configuration used to configure seelf commands.
// Configuration used to configure seelf commands exposed through an interface to prevent
// direct access to internal configuration structure.
Configuration interface {
serve.Options

Expand Down Expand Up @@ -126,7 +127,7 @@ func Default(builders ...ConfigurationBuilder) Configuration {
builder(conf)
}

if err := conf.PostLoad(); err != nil {
if err := conf.validate(); err != nil {
panic(err) // Should never happen since the default config is managed by us
}

Expand All @@ -140,6 +141,10 @@ func (c *configuration) Initialize(logger log.ConfigurableLogger, path string) e
return err
}

if err = c.validate(); err != nil {
return err
}

// Make sure the data path exists
if err = ostools.MkdirAll(c.Data.Path); err != nil {
return err
Expand Down Expand Up @@ -204,7 +209,7 @@ func (c *configuration) ListenAddress() string {
return c.Http.Host + ":" + strconv.Itoa(c.Http.Port)
}

func (c *configuration) PostLoad() error {
func (c *configuration) validate() error {
return validate.Struct(validate.Of{
"log.level": validate.Value(c.Log.Level, &c.logLevel, log.ParseLevel),
"log.format": validate.Value(c.Log.Format, &c.logFormat, log.ParseFormat),
Expand Down
2 changes: 1 addition & 1 deletion cmd/serve/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func Root(opts Options, logger log.Logger) *cobra.Command {

defer root.Cleanup()

return newHttpServer(opts, root).Listen()
return newHttpServer(opts, root.Bus(), root.Logger()).Listen()
},
}

Expand Down
7 changes: 3 additions & 4 deletions cmd/serve/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"syscall"
"time"

"github.com/YuukanOO/seelf/cmd/startup"
"github.com/YuukanOO/seelf/pkg/bus"
"github.com/YuukanOO/seelf/pkg/log"
"github.com/gin-contrib/sessions"
Expand Down Expand Up @@ -45,14 +44,14 @@ type (
}
)

func newHttpServer(options ServerOptions, root startup.ServerRoot) *server {
func newHttpServer(options ServerOptions, bus bus.Dispatcher, logger log.Logger) *server {
gin.SetMode(gin.ReleaseMode)

s := &server{
options: options,
router: gin.New(),
bus: root.Bus(),
logger: root.Logger(),
bus: bus,
logger: logger,
}

_ = s.router.SetTrustedProxies(nil)
Expand Down
27 changes: 10 additions & 17 deletions cmd/startup/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import (
"time"

"github.com/YuukanOO/seelf/internal/auth/app/create_first_account"
"github.com/YuukanOO/seelf/internal/auth/domain"
auth "github.com/YuukanOO/seelf/internal/auth/domain"
authinfra "github.com/YuukanOO/seelf/internal/auth/infra"
"github.com/YuukanOO/seelf/internal/deployment/app/cleanup_app"
"github.com/YuukanOO/seelf/internal/deployment/app/cleanup_target"
"github.com/YuukanOO/seelf/internal/deployment/app/configure_target"
"github.com/YuukanOO/seelf/internal/deployment/app/deploy"
"github.com/YuukanOO/seelf/internal/deployment/app/expose_seelf_container"
deploymentdomain "github.com/YuukanOO/seelf/internal/deployment/domain"
deployment "github.com/YuukanOO/seelf/internal/deployment/domain"
deploymentinfra "github.com/YuukanOO/seelf/internal/deployment/infra"
"github.com/YuukanOO/seelf/pkg/bus"
"github.com/YuukanOO/seelf/pkg/bus/embedded"
Expand All @@ -23,17 +23,10 @@ import (
)

type (
// Represents a services root containing every services used by a server.
ServerRoot interface {
Cleanup() error
Bus() bus.Dispatcher
Logger() log.Logger
}

ServerOptions interface {
deploymentinfra.Options

AppExposedUrl() monad.Maybe[deploymentdomain.Url]
AppExposedUrl() monad.Maybe[deployment.Url]
DefaultEmail() string
DefaultPassword() string
RunnersPollInterval() time.Duration
Expand All @@ -42,7 +35,7 @@ type (
ConnectionString() string
}

serverRoot struct {
ServerRoot struct {
bus bus.Bus
logger log.Logger
db *sqlite.Database
Expand All @@ -52,8 +45,8 @@ type (

// Instantiate a new server root, registering and initializing every services
// needed by the server.
func Server(options ServerOptions, logger log.Logger) (ServerRoot, error) {
s := &serverRoot{
func Server(options ServerOptions, logger log.Logger) (*ServerRoot, error) {
s := &ServerRoot{
logger: logger,
}

Expand Down Expand Up @@ -121,7 +114,7 @@ func Server(options ServerOptions, logger log.Logger) (ServerRoot, error) {
s.logger.Infow("exposing seelf container using the local target, creating it if needed, the container may restart once done",
"container", container)

if _, err := bus.Send(s.bus, domain.WithUserID(context.Background(), domain.UserID(uid)), expose_seelf_container.Command{
if _, err := bus.Send(s.bus, auth.WithUserID(context.Background(), auth.UserID(uid)), expose_seelf_container.Command{
Container: container,
Url: exposedUrl.WithoutUser().String(),
}); err != nil {
Expand All @@ -134,13 +127,13 @@ func Server(options ServerOptions, logger log.Logger) (ServerRoot, error) {
return s, nil
}

func (s *serverRoot) Cleanup() error {
func (s *ServerRoot) Cleanup() error {
s.logger.Debug("cleaning server services")

s.scheduler.Stop()

return s.db.Close()
}

func (s *serverRoot) Bus() bus.Dispatcher { return s.bus }
func (s *serverRoot) Logger() log.Logger { return s.logger }
func (s *ServerRoot) Bus() bus.Dispatcher { return s.bus }
func (s *ServerRoot) Logger() log.Logger { return s.logger }
53 changes: 34 additions & 19 deletions internal/deployment/app/cleanup_app/cleanup_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,17 +39,20 @@ func Handler(
return func(ctx context.Context, cmd Command) (result bus.AsyncResult, finalErr error) {
target, finalErr := reader.GetByID(ctx, domain.TargetID(cmd.TargetID))

var (
appid = domain.AppID(cmd.AppID)
env = domain.EnvironmentName(cmd.Environment)
)

if finalErr != nil {
if errors.Is(finalErr, apperr.ErrNotFound) {
finalErr = nil
finalErr = markAppCleanedUp(ctx, uow, appsReader, appsWriter, appid, target.ID(), env)
}

return
}

var (
appid = domain.AppID(cmd.AppID)
env = domain.Environment(cmd.Environment)
interval shared.TimeInterval
runningOrPending domain.HasRunningOrPendingDeploymentsOnAppTargetEnv
successful domain.HasSuccessfulDeploymentsOnAppTargetEnv
Expand Down Expand Up @@ -80,25 +83,37 @@ func Handler(
return
}

finalErr = uow.Create(ctx, func(ctx context.Context) error {
app, err := appsReader.GetByID(ctx, appid)

if err != nil {
// Application does not exist anymore, nothing specific to do
if errors.Is(err, apperr.ErrNotFound) {
return nil
}

return err
}

app.CleanedUp(env, target.ID())

return appsWriter.Write(ctx, &app)
})
finalErr = markAppCleanedUp(ctx, uow, appsReader, appsWriter, appid, target.ID(), env)
}()

finalErr = provider.Cleanup(ctx, appid, target, env, strategy)
return
}
}

func markAppCleanedUp(
ctx context.Context,
uow storage.UnitOfWorkFactory,
appsReader domain.AppsReader,
appsWriter domain.AppsWriter,
appid domain.AppID,
target domain.TargetID,
env domain.EnvironmentName,
) error {
return uow.Create(ctx, func(ctx context.Context) error {
app, err := appsReader.GetByID(ctx, appid)

if err != nil {
// Application does not exist anymore, nothing specific to do
if errors.Is(err, apperr.ErrNotFound) {
return nil
}

return err
}

_ = app.CleanedUp(env, target)

return appsWriter.Write(ctx, &app)
})
}
2 changes: 1 addition & 1 deletion internal/deployment/app/cleanup_app/cleanup_app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,7 @@ type mockProvider struct {
called bool
}

func (d *mockProvider) Cleanup(_ context.Context, _ domain.AppID, _ domain.Target, _ domain.Environment, s domain.CleanupStrategy) error {
func (d *mockProvider) Cleanup(_ context.Context, _ domain.AppID, _ domain.Target, _ domain.EnvironmentName, s domain.CleanupStrategy) error {
d.called = s != domain.CleanupStrategySkip
return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,15 @@ func OnAppCleanupRequestedHandler(scheduler bus.Scheduler) bus.SignalHandler[dom
Command{
AppID: string(evt.ID),
Environment: string(domain.Production),
TargetID: string(evt.ProductionConfig.Target()),
From: evt.ProductionConfig.Version(),
TargetID: string(evt.Production.Config().Target()),
From: evt.Production.Since(),
To: now,
},
Command{
AppID: string(evt.ID),
Environment: string(domain.Staging),
TargetID: string(evt.StagingConfig.Target()),
From: evt.StagingConfig.Version(),
TargetID: string(evt.Staging.Config().Target()),
From: evt.Staging.Since(),
To: now,
},
)
Expand Down
25 changes: 0 additions & 25 deletions internal/deployment/app/cleanup_app/on_app_env_changed.go

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package cleanup_app

import (
"context"

"github.com/YuukanOO/seelf/internal/deployment/domain"
"github.com/YuukanOO/seelf/pkg/bus"
)

func OnAppEnvMigrationStartedHandler(scheduler bus.Scheduler) bus.SignalHandler[domain.AppEnvMigrationStarted] {
return func(ctx context.Context, evt domain.AppEnvMigrationStarted) error {
return scheduler.Queue(ctx, Command{
AppID: string(evt.ID),
TargetID: string(evt.Migration.Target()),
Environment: string(evt.Environment),
From: evt.Migration.Interval().From(),
To: evt.Migration.Interval().To(),
})
}
}
2 changes: 1 addition & 1 deletion internal/deployment/app/cleanup_app/on_job_dismissed.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func OnJobDismissedHandler(
return err
}

app.CleanedUp(domain.Environment(cmd.Environment), domain.TargetID(cmd.TargetID))
_ = app.CleanedUp(domain.EnvironmentName(cmd.Environment), domain.TargetID(cmd.TargetID))

return writer.Write(ctx, &app)
}
Expand Down
1 change: 0 additions & 1 deletion internal/deployment/app/cleanup_target/cleanup_target.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ func Handler(

return writer.Write(ctx, &target)
})

}()

finalErr = provider.CleanupTarget(ctx, target, strategy)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ func OnAppCleanupRequestedHandler(
writer domain.TargetsWriter,
) bus.SignalHandler[domain.AppCleanupRequested] {
return func(ctx context.Context, evt domain.AppCleanupRequested) error {
if err := unExpose(ctx, reader, writer, evt.ProductionConfig.Target(), evt.ID); err != nil {
if err := unExpose(ctx, reader, writer, evt.Production.Config().Target(), evt.ID); err != nil {
return err
}

if evt.ProductionConfig.Target() == evt.StagingConfig.Target() {
if evt.Production.Config().Target() == evt.Staging.Config().Target() {
return nil
}

return unExpose(ctx, reader, writer, evt.StagingConfig.Target(), evt.ID)
return unExpose(ctx, reader, writer, evt.Staging.Config().Target(), evt.ID)
}
}

Expand Down
31 changes: 0 additions & 31 deletions internal/deployment/app/configure_target/on_app_env_changed.go

This file was deleted.

Loading

0 comments on commit cadc280

Please sign in to comment.