get.porter.sh/porter@v1.3.0/pkg/porter/upgrade.go (about) 1 package porter 2 3 import ( 4 "context" 5 "errors" 6 "time" 7 8 "get.porter.sh/porter/pkg/cnab" 9 "get.porter.sh/porter/pkg/tracing" 10 "github.com/Masterminds/semver/v3" 11 ) 12 13 var _ BundleAction = NewUpgradeOptions() 14 15 // UpgradeOptions that may be specified when upgrading a bundle. 16 // Porter handles defaulting any missing values. 17 type UpgradeOptions struct { 18 *BundleExecutionOptions 19 20 // Version of the bundle to upgrade to 21 Version string 22 23 // ForceUpgrade allows the upgrade to run even if the current installation is marked as failed. 24 ForceUpgrade bool 25 } 26 27 func NewUpgradeOptions() *UpgradeOptions { 28 return &UpgradeOptions{ 29 BundleExecutionOptions: NewBundleExecutionOptions(), 30 } 31 } 32 33 func (o *UpgradeOptions) Validate(ctx context.Context, args []string, p *Porter) error { 34 if o.Version != "" && o.Reference != "" { 35 return errors.New("either --version or --reference may be set, but not both") 36 } 37 38 if o.Version != "" { 39 v, err := semver.NewVersion(o.Version) 40 if err != nil { 41 return errors.New("invalid bundle version --version. Must be a semantic version, for example 1.2.3") 42 } 43 44 o.Version = v.String() 45 } 46 47 return o.BundleExecutionOptions.Validate(ctx, args, p) 48 } 49 50 func (o *UpgradeOptions) GetAction() string { 51 return cnab.ActionUpgrade 52 } 53 54 func (o *UpgradeOptions) GetActionVerb() string { 55 return "upgrading" 56 } 57 58 // UpgradeBundle accepts a set of pre-validated UpgradeOptions and uses 59 // them to upgrade a bundle. 60 func (p *Porter) UpgradeBundle(ctx context.Context, opts *UpgradeOptions) error { 61 ctx, span := tracing.StartSpan(ctx) 62 defer span.EndSpan() 63 64 // Sync any changes specified by the user to the installation before running upgrade 65 i, err := p.Installations.GetInstallation(ctx, opts.Namespace, opts.Name) 66 if err != nil { 67 return span.Errorf("could not find installation %s/%s: %w", opts.Namespace, opts.Name, err) 68 } 69 70 if !i.IsInstalled() && !opts.ForceUpgrade { 71 return span.Errorf("The installation cannot be upgraded, because it is not installed. Verify the installation name and namespace, and if correct, use porter install.") 72 } 73 74 if opts.Reference != "" { 75 i.TrackBundle(opts.GetReference()) 76 } else if opts.Version != "" { 77 i.Bundle.Version = opts.Version 78 i.Bundle.Digest = "" 79 i.Bundle.Tag = "" 80 } 81 82 err = p.applyActionOptionsToInstallation(ctx, opts, &i) 83 if err != nil { 84 return span.Errorf("could not apply options to installation: %w", err) 85 } 86 i.Status.Modified = time.Now() 87 88 checkStrategy := p.GetSchemaCheckStrategy(ctx) 89 err = i.Validate(ctx, checkStrategy) 90 if err != nil { 91 return err 92 } 93 94 err = p.Installations.UpdateInstallation(ctx, i) 95 if err != nil { 96 return err 97 } 98 99 // Re-resolve the bundle after we have figured out the version we are upgrading to 100 opts.UnsetBundleReference() 101 if _, err := opts.GetBundleReference(ctx, p); err != nil { 102 return err 103 } 104 105 return p.ExecuteAction(ctx, i, opts) 106 }