get.porter.sh/porter@v1.3.0/pkg/porter/invoke.go (about)

     1  package porter
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  
     8  	"get.porter.sh/porter/pkg/storage"
     9  )
    10  
    11  var _ BundleAction = NewInvokeOptions()
    12  
    13  // InvokeOptions that may be specified when invoking a bundle.
    14  // Porter handles defaulting any missing values.
    15  type InvokeOptions struct {
    16  	*BundleExecutionOptions
    17  
    18  	// Action name to invoke
    19  	Action string
    20  }
    21  
    22  func NewInvokeOptions() InvokeOptions {
    23  	return InvokeOptions{
    24  		BundleExecutionOptions: NewBundleExecutionOptions(),
    25  	}
    26  }
    27  
    28  func (o InvokeOptions) GetAction() string {
    29  	return o.Action
    30  }
    31  
    32  func (o InvokeOptions) GetActionVerb() string {
    33  	return "invoking"
    34  }
    35  
    36  func (o InvokeOptions) Validate(ctx context.Context, args []string, p *Porter) error {
    37  	if o.Action == "" {
    38  		return errors.New("--action is required")
    39  	}
    40  
    41  	return o.BundleExecutionOptions.Validate(ctx, args, p)
    42  }
    43  
    44  // InvokeBundle accepts a set of pre-validated InvokeOptions and uses
    45  // them to upgrade a bundle.
    46  func (p *Porter) InvokeBundle(ctx context.Context, opts InvokeOptions) error {
    47  	// Figure out which bundle/installation we are working with
    48  	bundleRef, err := opts.GetBundleReference(ctx, p)
    49  	if err != nil {
    50  		return err
    51  	}
    52  
    53  	installation, err := p.Installations.GetInstallation(ctx, opts.Namespace, opts.Name)
    54  	if errors.Is(err, storage.ErrNotFound{}) {
    55  		action, actionErr := bundleRef.Definition.GetAction(opts.Action)
    56  		if actionErr != nil {
    57  			return fmt.Errorf("invalid --action %s", opts.Action)
    58  		}
    59  
    60  		// Only allow actions on a non-existing installation when it won't change anything
    61  		if action.Modifies || !action.Stateless {
    62  			return fmt.Errorf("could not find installation %s/%s: %w", opts.Namespace, opts.Name, err)
    63  		}
    64  
    65  		// Create an ephemeral installation just for this run
    66  		installation = storage.NewInstallation(opts.Namespace, opts.Name)
    67  	}
    68  
    69  	err = p.applyActionOptionsToInstallation(ctx, opts, &installation)
    70  	if err != nil {
    71  		return err
    72  	}
    73  
    74  	return p.ExecuteAction(ctx, installation, opts)
    75  }