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  }