github.com/replicatedhq/ship@v0.55.0/pkg/lifecycle/render/planner/planner.go (about)

     1  package planner
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/go-kit/kit/log"
     7  	"github.com/mitchellh/cli"
     8  	"github.com/replicatedhq/libyaml"
     9  	"github.com/replicatedhq/ship/pkg/api"
    10  	"github.com/replicatedhq/ship/pkg/lifecycle/daemon/daemontypes"
    11  	"github.com/replicatedhq/ship/pkg/lifecycle/render/amazoneks"
    12  	"github.com/replicatedhq/ship/pkg/lifecycle/render/azureaks"
    13  	"github.com/replicatedhq/ship/pkg/lifecycle/render/docker"
    14  	"github.com/replicatedhq/ship/pkg/lifecycle/render/dockerlayer"
    15  	"github.com/replicatedhq/ship/pkg/lifecycle/render/github"
    16  	"github.com/replicatedhq/ship/pkg/lifecycle/render/googlegke"
    17  	"github.com/replicatedhq/ship/pkg/lifecycle/render/helm"
    18  	"github.com/replicatedhq/ship/pkg/lifecycle/render/inline"
    19  	"github.com/replicatedhq/ship/pkg/lifecycle/render/local"
    20  	"github.com/replicatedhq/ship/pkg/lifecycle/render/terraform"
    21  	"github.com/replicatedhq/ship/pkg/lifecycle/render/web"
    22  	"github.com/replicatedhq/ship/pkg/templates"
    23  	"github.com/spf13/afero"
    24  	"github.com/spf13/viper"
    25  )
    26  
    27  // A Plan is a list of PlanSteps to execute
    28  type Plan []Step
    29  
    30  // A Execute describes a single unit of work that Ship will do
    31  // to render the application
    32  type Step struct {
    33  	Description string `json:"description" yaml:"description" hcl:"description"`
    34  	Dest        string `json:"dest" yaml:"dest" hcl:"dest"`
    35  	Execute     func(ctx context.Context) error
    36  	Err         error
    37  }
    38  
    39  // Planner is a thing that can plan and execute rendering
    40  type Planner interface {
    41  	Build(
    42  		string,
    43  		[]api.Asset,
    44  		[]libyaml.ConfigGroup,
    45  		api.ReleaseMetadata,
    46  		map[string]interface{},
    47  	) (Plan, []string, error)
    48  
    49  	Execute(context.Context, Plan) error
    50  
    51  	WithStatusReceiver(receiver daemontypes.StatusReceiver) Planner
    52  }
    53  
    54  type Factory func() *CLIPlanner
    55  
    56  func (f Factory) WithStatusReceiver(receiver daemontypes.StatusReceiver) Planner {
    57  	return Factory(func() *CLIPlanner {
    58  		planner := f()
    59  		return &CLIPlanner{
    60  			Status: receiver,
    61  
    62  			Logger:         planner.Logger,
    63  			Fs:             planner.Fs,
    64  			UI:             planner.UI,
    65  			Viper:          planner.Viper,
    66  			BuilderBuilder: planner.BuilderBuilder,
    67  
    68  			Inline:      planner.Inline,
    69  			Helm:        planner.Helm,
    70  			Local:       planner.Local,
    71  			Docker:      planner.Docker,
    72  			DockerLayer: planner.DockerLayer,
    73  			GitHub:      planner.GitHub,
    74  			Terraform:   planner.Terraform,
    75  			Web:         planner.Web,
    76  			AmazonEKS:   planner.AmazonEKS,
    77  			GoogleGKE:   planner.GoogleGKE,
    78  			AzureAKS:    planner.AzureAKS,
    79  		}
    80  
    81  	})
    82  }
    83  
    84  func (f Factory) Build(
    85  	root string,
    86  	assets []api.Asset,
    87  	configGroups []libyaml.ConfigGroup,
    88  	releaseMeta api.ReleaseMetadata,
    89  	templateContext map[string]interface{},
    90  ) (Plan, []string, error) {
    91  	planner := f()
    92  	return planner.Build(root, assets, configGroups, releaseMeta, templateContext)
    93  }
    94  
    95  func (f Factory) Execute(ctx context.Context, p Plan) error {
    96  	planner := f()
    97  	return planner.Execute(ctx, p)
    98  }
    99  
   100  // CLIPlanner is the default Planner
   101  type CLIPlanner struct {
   102  	Logger         log.Logger
   103  	Fs             afero.Afero
   104  	UI             cli.Ui
   105  	Viper          *viper.Viper
   106  	Status         daemontypes.StatusReceiver
   107  	BuilderBuilder *templates.BuilderBuilder
   108  
   109  	Inline      inline.Renderer
   110  	Helm        helm.Renderer
   111  	Local       local.Renderer
   112  	Docker      docker.Renderer
   113  	DockerLayer *dockerlayer.Unpacker
   114  	Web         web.Renderer
   115  	GitHub      github.Renderer
   116  	Terraform   terraform.Renderer
   117  	AmazonEKS   amazoneks.Renderer
   118  	GoogleGKE   googlegke.Renderer
   119  	AzureAKS    azureaks.Renderer
   120  }
   121  
   122  // Use a factory so we can create instances and override the StatusReceiver on those instances.
   123  func NewFactory(
   124  	v *viper.Viper,
   125  	logger log.Logger,
   126  	fs afero.Afero,
   127  	ui cli.Ui,
   128  	builderBuilder *templates.BuilderBuilder,
   129  	inlineRenderer inline.Renderer,
   130  	dockerRenderer docker.Renderer,
   131  	helmRenderer helm.Renderer,
   132  	localRenderer local.Renderer,
   133  	dockerlayers *dockerlayer.Unpacker,
   134  	gh github.Renderer,
   135  	tf terraform.Renderer,
   136  	webRenderer web.Renderer,
   137  	amazonEKS amazoneks.Renderer,
   138  	googleGKE googlegke.Renderer,
   139  	azureAKS azureaks.Renderer,
   140  	status daemontypes.StatusReceiver,
   141  ) Planner {
   142  	return Factory(func() *CLIPlanner {
   143  		return &CLIPlanner{
   144  			Logger:         logger,
   145  			Fs:             fs,
   146  			UI:             ui,
   147  			Viper:          v,
   148  			BuilderBuilder: builderBuilder,
   149  
   150  			Inline:      inlineRenderer,
   151  			Helm:        helmRenderer,
   152  			Local:       localRenderer,
   153  			Docker:      dockerRenderer,
   154  			DockerLayer: dockerlayers,
   155  			GitHub:      gh,
   156  			Terraform:   tf,
   157  			Web:         webRenderer,
   158  			AmazonEKS:   amazonEKS,
   159  			GoogleGKE:   googleGKE,
   160  			AzureAKS:    azureAKS,
   161  			Status:      status,
   162  		}
   163  	})
   164  
   165  }