github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/model/stack/main.go (about) 1 package stack 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 8 "github.com/cozy/cozy-stack/model/cloudery" 9 "github.com/cozy/cozy-stack/model/instance" 10 "github.com/cozy/cozy-stack/model/job" 11 "github.com/cozy/cozy-stack/model/session" 12 "github.com/cozy/cozy-stack/model/settings" 13 "github.com/cozy/cozy-stack/model/token" 14 "github.com/cozy/cozy-stack/pkg/assets/dynamic" 15 build "github.com/cozy/cozy-stack/pkg/config" 16 "github.com/cozy/cozy-stack/pkg/config/config" 17 "github.com/cozy/cozy-stack/pkg/couchdb" 18 "github.com/cozy/cozy-stack/pkg/emailer" 19 "github.com/cozy/cozy-stack/pkg/utils" 20 21 "github.com/google/gops/agent" 22 ) 23 24 // Options can be used to give options when starting the stack. 25 type Options int 26 27 const ( 28 // NoGops option can be used to disable gops support 29 NoGops Options = iota + 1 30 // NoDynAssets option can be used to initialize the dynamic assets 31 NoDynAssets 32 ) 33 34 func hasOptions(needle Options, haystack []Options) bool { 35 for _, opt := range haystack { 36 if opt == needle { 37 return true 38 } 39 } 40 return false 41 } 42 43 type gopAgent struct{} 44 45 func (g gopAgent) Shutdown(ctx context.Context) error { 46 fmt.Print(" shutting down gops...") 47 agent.Close() 48 fmt.Println("ok.") 49 return nil 50 } 51 52 type Services struct { 53 Emailer emailer.Emailer 54 Settings settings.Service 55 } 56 57 // Start is used to initialize all the 58 func Start(opts ...Options) (utils.Shutdowner, *Services, error) { 59 if build.IsDevRelease() { 60 fmt.Print(` !! DEVELOPMENT RELEASE !! 61 You are running a development release which may deactivate some very important 62 security features. Please do not use this binary as your production server. 63 64 `) 65 } 66 67 var shutdowners []utils.Shutdowner 68 69 ctx := context.Background() 70 71 if !hasOptions(NoGops, opts) { 72 err := agent.Listen(agent.Options{}) 73 if err != nil { 74 fmt.Fprintf(os.Stderr, "Error on gops agent: %s\n", err) 75 } 76 shutdowners = append(shutdowners, gopAgent{}) 77 } 78 79 if err := couchdb.InitGlobalDB(ctx); err != nil { 80 return nil, nil, fmt.Errorf("failed to init the global db: %w", err) 81 } 82 83 // Init the main global connection to the swift server 84 if err := config.InitDefaultSwiftConnection(); err != nil { 85 return nil, nil, fmt.Errorf("failed to init the swift connection: %w", err) 86 } 87 88 workersList, err := job.GetWorkersList() 89 if err != nil { 90 return nil, nil, fmt.Errorf("failed to get the workers list: %w", err) 91 } 92 93 var broker job.Broker 94 var schder job.Scheduler 95 jobsConfig := config.GetConfig().Jobs 96 if jobsConfig.Client != nil { 97 broker = job.NewRedisBroker(jobsConfig.Client) 98 schder = job.NewRedisScheduler(jobsConfig.Client) 99 } else { 100 broker = job.NewMemBroker() 101 schder = job.NewMemScheduler() 102 } 103 104 if err = job.SystemStart(broker, schder, workersList); err != nil { 105 return nil, nil, fmt.Errorf("failed to start the jobs: %w", err) 106 } 107 shutdowners = append(shutdowners, job.System()) 108 109 tokenSvc := token.NewService(config.GetConfig().CacheStorage) 110 emailerSvc := emailer.Init() 111 instanceSvc := instance.Init() 112 clouderySvc := cloudery.Init(config.GetConfig().Clouderies) 113 114 services := Services{ 115 Emailer: emailerSvc, 116 Settings: settings.Init(emailerSvc, instanceSvc, tokenSvc, clouderySvc), 117 } 118 119 // Initialize the dynamic assets FS. Can be OsFs, MemFs or Swift 120 if !hasOptions(NoDynAssets, opts) { 121 err = dynamic.InitDynamicAssetFS(config.FsURL().String()) 122 if err != nil { 123 return nil, nil, fmt.Errorf("failed to init the dynamic asset fs: %w", err) 124 } 125 } 126 127 sessionSweeper := session.SweepLoginRegistrations() 128 shutdowners = append(shutdowners, sessionSweeper) 129 130 // Global shutdowner that composes all the running processes of the stack 131 processes := utils.NewGroupShutdown(shutdowners...) 132 133 return processes, &services, nil 134 }