github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/ctrlgitops/orbiter.go (about) 1 package ctrlgitops 2 3 import ( 4 "context" 5 "runtime/debug" 6 "time" 7 8 orbcfg "github.com/caos/orbos/pkg/orb" 9 10 "github.com/caos/orbos/pkg/labels" 11 12 "github.com/caos/orbos/internal/executables" 13 "github.com/caos/orbos/internal/operator/orbiter" 14 "github.com/caos/orbos/internal/operator/orbiter/kinds/orb" 15 "github.com/caos/orbos/mntr" 16 "github.com/caos/orbos/pkg/git" 17 ) 18 19 type OrbiterConfig struct { 20 Recur bool 21 Deploy bool 22 Verbose bool 23 Version string 24 OrbConfigPath string 25 GitCommit string 26 } 27 28 func Orbiter(ctx context.Context, monitor mntr.Monitor, conf *OrbiterConfig, orbctlGit *git.Client) error { 29 30 go checks(monitor, orbctlGit) 31 32 finishedChan := make(chan struct{}) 33 takeoffChan := make(chan struct{}) 34 healthyChan := make(chan bool) 35 36 if conf.Recur { 37 go orbiter.Instrument(monitor, healthyChan) 38 } else { 39 go func() { 40 for range healthyChan { 41 } 42 }() 43 } 44 45 on := func() { takeoffChan <- struct{}{} } 46 go on() 47 var initialized bool 48 loop: 49 for { 50 select { 51 case <-finishedChan: 52 break loop 53 case <-takeoffChan: 54 iterate(conf, orbctlGit, !initialized, ctx, monitor, finishedChan, healthyChan, func(iterated bool) { 55 if iterated { 56 initialized = true 57 } 58 59 time.Sleep(time.Second * 30) 60 go on() 61 }) 62 } 63 } 64 return nil 65 } 66 67 func iterate(conf *OrbiterConfig, gitClient *git.Client, firstIteration bool, ctx context.Context, monitor mntr.Monitor, finishedChan chan struct{}, healthyChan chan bool, done func(iterated bool)) { 68 69 var err error 70 defer func() { 71 go func() { 72 if err != nil { 73 healthyChan <- false 74 return 75 } 76 }() 77 }() 78 79 orbFile, err := orbcfg.ParseOrbConfig(conf.OrbConfigPath) 80 if err != nil { 81 monitor.Error(err) 82 done(false) 83 return 84 } 85 86 if err := gitClient.Configure(orbFile.URL, []byte(orbFile.Repokey)); err != nil { 87 monitor.Error(err) 88 done(false) 89 return 90 } 91 92 if err := gitClient.Clone(); err != nil { 93 monitor.Error(err) 94 done(false) 95 return 96 } 97 98 if firstIteration { 99 100 started := float64(time.Now().UTC().Unix()) 101 102 go func() { 103 for range time.Tick(30 * time.Minute) { 104 monitor.WithField("since", started).CaptureMessage("ORBITER is running") 105 } 106 }() 107 108 executables.Populate() 109 110 monitor.WithFields(map[string]interface{}{ 111 "version": conf.Version, 112 "commit": conf.GitCommit, 113 "verbose": conf.Verbose, 114 "repoURL": orbFile.URL, 115 }).Info("Orbiter took off") 116 } 117 118 adaptFunc := orb.AdaptFunc( 119 labels.MustForOperator("ORBOS", "orbiter.caos.ch", conf.Version), 120 orbFile, 121 conf.GitCommit, 122 !conf.Recur, 123 conf.Deploy, 124 gitClient, 125 ) 126 127 takeoffConf := &orbiter.Config{ 128 OrbiterCommit: conf.GitCommit, 129 GitClient: gitClient, 130 Adapt: adaptFunc, 131 FinishedChan: finishedChan, 132 OrbConfig: *orbFile, 133 } 134 135 takeoff := orbiter.Takeoff(monitor, takeoffConf, healthyChan) 136 137 go func() { 138 defer func() { monitor.RecoverPanic(recover()) }() 139 started := time.Now() 140 takeoff() 141 142 monitor.WithFields(map[string]interface{}{ 143 "took": time.Since(started), 144 }).Info("Iteration done") 145 debug.FreeOSMemory() 146 done(true) 147 }() 148 }