github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/daemon/headless/daemon.go (about)

     1  package headless
     2  
     3  import (
     4  	"context"
     5  	"path"
     6  	"strings"
     7  
     8  	"github.com/go-kit/kit/log"
     9  	"github.com/go-kit/kit/log/level"
    10  	"github.com/mitchellh/cli"
    11  	"github.com/pkg/errors"
    12  	"github.com/replicatedhq/ship/pkg/api"
    13  	"github.com/replicatedhq/ship/pkg/constants"
    14  	"github.com/replicatedhq/ship/pkg/lifecycle/daemon/daemontypes"
    15  	"github.com/replicatedhq/ship/pkg/lifecycle/render/config/resolve"
    16  	"github.com/replicatedhq/ship/pkg/state"
    17  	"github.com/spf13/afero"
    18  	"github.com/spf13/viper"
    19  )
    20  
    21  var _ daemontypes.Daemon = &HeadlessDaemon{}
    22  
    23  type HeadlessDaemon struct {
    24  	StateManager   state.Manager
    25  	Logger         log.Logger
    26  	UI             cli.Ui
    27  	ConfigRenderer *resolve.APIConfigRenderer
    28  	FS             afero.Afero
    29  	ResolvedConfig map[string]interface{}
    30  
    31  	YesApplyTerraform bool
    32  }
    33  
    34  func (d *HeadlessDaemon) AwaitShutdown() error {
    35  	return nil
    36  }
    37  
    38  func NewHeadlessDaemon(
    39  	ui cli.Ui,
    40  	logger log.Logger,
    41  	renderer *resolve.APIConfigRenderer,
    42  	stateManager state.Manager,
    43  	fs afero.Afero,
    44  	v *viper.Viper,
    45  ) daemontypes.Daemon {
    46  	return &HeadlessDaemon{
    47  		StateManager:      stateManager,
    48  		Logger:            logger,
    49  		UI:                ui,
    50  		ConfigRenderer:    renderer,
    51  		FS:                fs,
    52  		YesApplyTerraform: v.GetBool("terraform-apply-yes"),
    53  	}
    54  }
    55  
    56  func (d *HeadlessDaemon) PushKustomizeStep(context.Context, daemontypes.Kustomize)                   {}
    57  func (d *HeadlessDaemon) PushMessageStep(context.Context, daemontypes.Message, []daemontypes.Action) {}
    58  func (d *HeadlessDaemon) PushRenderStep(context.Context, daemontypes.Render)                         {}
    59  
    60  func (d *HeadlessDaemon) KustomizeSavedChan() chan interface{} {
    61  	ch := make(chan interface{}, 1)
    62  	level.Debug(d.Logger).Log("event", "kustomize.skip", "detail", "running in automation, not waiting for kustomize")
    63  	ch <- nil
    64  	return ch
    65  }
    66  
    67  func (d *HeadlessDaemon) UnforkSavedChan() chan interface{} {
    68  	ch := make(chan interface{}, 1)
    69  	ch <- nil
    70  	return ch
    71  }
    72  
    73  func (d *HeadlessDaemon) PushHelmIntroStep(context.Context, daemontypes.HelmIntro, []daemontypes.Action) {
    74  }
    75  
    76  func (d *HeadlessDaemon) PushHelmValuesStep(ctx context.Context, helmValues daemontypes.HelmValues, actions []daemontypes.Action) {
    77  	warn := level.Warn(log.With(d.Logger, "struct", "HeadlessDaemon", "method", "PushHelmValuesStep"))
    78  
    79  	defaultValues := helmValues.DefaultValues
    80  	if defaultValues == "" {
    81  		v, err := d.FS.ReadFile(path.Join(constants.HelmChartPath, "values.yaml"))
    82  		if err != nil {
    83  			warn.Log("event", "push helm values fail while reading defaults", "err", err)
    84  		} else {
    85  			defaultValues = string(v)
    86  		}
    87  	}
    88  
    89  	if err := d.HeadlessSaveHelmValues(ctx, helmValues.Values, defaultValues); err != nil {
    90  		warn.Log("event", "push helm values step fail", "err", err)
    91  	}
    92  }
    93  
    94  func (d *HeadlessDaemon) HeadlessSaveHelmValues(ctx context.Context, helmValues, defaultValues string) error {
    95  	warn := level.Warn(log.With(d.Logger, "struct", "HeadlessDaemon", "method", "HeadlessSaveHelmValues"))
    96  	err := d.StateManager.SerializeHelmValues(helmValues, defaultValues)
    97  	if err != nil {
    98  		warn.Log("event", "headless save helm values fail", "err", err)
    99  		return errors.Wrap(err, "write new values")
   100  	}
   101  
   102  	return nil
   103  }
   104  
   105  func (d *HeadlessDaemon) PushStreamStep(context.Context, <-chan daemontypes.Message) {}
   106  
   107  func (d *HeadlessDaemon) CleanPreviousStep() {}
   108  
   109  func (d *HeadlessDaemon) TerraformConfirmedChan() chan bool {
   110  	ch := make(chan bool, 1)
   111  
   112  	if !d.YesApplyTerraform {
   113  		level.Info(d.Logger).Log("event", "terraform.skip", "detail", "skipping running terraform because --terraform-apply-yes was not set")
   114  		ch <- false
   115  		return ch
   116  	}
   117  
   118  	level.Info(d.Logger).Log("event", "terraform.apply", "detail", "running terraform because --terraform-apply-yes was set")
   119  	ch <- true
   120  	return ch
   121  }
   122  
   123  func (d *HeadlessDaemon) EnsureStarted(ctx context.Context, release *api.Release) chan error {
   124  	warn := level.Warn(log.With(d.Logger, "struct", "fakeDaemon", "method", "EnsureStarted"))
   125  
   126  	chanerrors := make(chan error)
   127  
   128  	if err := d.HeadlessResolve(ctx, release); err != nil {
   129  		warn.Log("event", "headless resolved failed", "err", err)
   130  		go func() {
   131  			chanerrors <- err
   132  			close(chanerrors)
   133  		}()
   134  	}
   135  
   136  	return chanerrors
   137  }
   138  
   139  func (d *HeadlessDaemon) SetStepName(context.Context, string) {}
   140  
   141  func (d *HeadlessDaemon) AllStepsDone(context.Context) {}
   142  
   143  func (d *HeadlessDaemon) MessageConfirmedChan() chan string {
   144  	ch := make(chan string)
   145  	close(ch)
   146  	return ch
   147  }
   148  
   149  func (d *HeadlessDaemon) ConfigSavedChan() chan interface{} {
   150  	ch := make(chan interface{})
   151  	close(ch)
   152  	return ch
   153  }
   154  
   155  func (d *HeadlessDaemon) GetCurrentConfig() (map[string]interface{}, error) {
   156  	if d.ResolvedConfig != nil {
   157  		return d.ResolvedConfig, nil
   158  	}
   159  
   160  	warn := level.Warn(log.With(d.Logger, "struct", "fakeDaemon", "method", "getCurrentConfig"))
   161  	currentConfig, err := d.StateManager.CachedState()
   162  	if err != nil {
   163  		warn.Log("event", "state missing", "err", err)
   164  		return nil, err
   165  	}
   166  
   167  	config, err := currentConfig.CurrentConfig()
   168  	if err != nil {
   169  		warn.Log("event", "get config", "err", err)
   170  		return nil, err
   171  	}
   172  
   173  	return config, nil
   174  }
   175  
   176  func (d *HeadlessDaemon) HeadlessResolve(ctx context.Context, release *api.Release) error {
   177  	warn := level.Warn(log.With(d.Logger, "struct", "fakeDaemon", "method", "HeadlessResolve"))
   178  	currentConfig, err := d.GetCurrentConfig()
   179  	if err != nil {
   180  		warn.Log("event", "get config failed", "err", err)
   181  		return err
   182  	}
   183  
   184  	resolved, err := d.ConfigRenderer.ResolveConfig(ctx, release, currentConfig, make(map[string]interface{}), false)
   185  	if err != nil {
   186  		warn.Log("event", "resolveconfig failed", "err", err)
   187  		return err
   188  	}
   189  
   190  	if validateState := resolve.ValidateConfig(resolved); validateState != nil {
   191  		var invalidItemNames []string
   192  		for _, invalidConfigItems := range validateState {
   193  			invalidItemNames = append(invalidItemNames, invalidConfigItems.Name)
   194  		}
   195  
   196  		err := errors.Errorf(
   197  			"validate config failed. missing config values: %s",
   198  			strings.Join(invalidItemNames, ","),
   199  		)
   200  		warn.Log("event", "state invalid", "err", err)
   201  		return err
   202  	}
   203  
   204  	templateContext := make(map[string]interface{})
   205  	for _, configGroup := range resolved {
   206  		for _, configItem := range configGroup.Items {
   207  			templateContext[configItem.Name] = configItem.Value
   208  		}
   209  	}
   210  
   211  	d.ResolvedConfig = templateContext
   212  	return nil
   213  }
   214  
   215  func (d *HeadlessDaemon) SetProgress(progress daemontypes.Progress) {
   216  	if progress.Type == "string" {
   217  		d.UI.Output(progress.Detail)
   218  	}
   219  }
   220  
   221  func (d *HeadlessDaemon) ClearProgress() {}