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

     1  package porter
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sort"
     7  	"time"
     8  
     9  	"get.porter.sh/porter/pkg/cnab"
    10  	"get.porter.sh/porter/pkg/portercontext"
    11  	"get.porter.sh/porter/pkg/printer"
    12  	"get.porter.sh/porter/pkg/storage"
    13  	dtprinter "github.com/carolynvs/datetime-printer"
    14  )
    15  
    16  var (
    17  	ShowAllowedFormats = []printer.Format{printer.FormatPlaintext, printer.FormatYaml, printer.FormatJson}
    18  	ShowDefaultFormat  = printer.FormatPlaintext
    19  )
    20  
    21  // ShowOptions represent options for showing a particular installation
    22  type ShowOptions struct {
    23  	installationOptions
    24  	printer.PrintOptions
    25  }
    26  
    27  // Validate prepares for a show bundle action and validates the args/options.
    28  func (so *ShowOptions) Validate(args []string, cxt *portercontext.Context) error {
    29  	// Ensure only one argument exists (installation name) if args length non-zero
    30  	err := so.installationOptions.validateInstallationName(args)
    31  	if err != nil {
    32  		return err
    33  	}
    34  
    35  	err = so.installationOptions.defaultBundleFiles(cxt)
    36  	if err != nil {
    37  		return err
    38  	}
    39  
    40  	return so.PrintOptions.Validate(ShowDefaultFormat, ShowAllowedFormats)
    41  }
    42  
    43  // GetInstallation retrieves information about an installation, including its most recent run.
    44  func (p *Porter) GetInstallation(ctx context.Context, opts ShowOptions) (storage.Installation, *storage.Run, error) {
    45  	err := p.applyDefaultOptions(ctx, &opts.installationOptions)
    46  	if err != nil {
    47  		return storage.Installation{}, nil, err
    48  	}
    49  
    50  	installation, err := p.Installations.GetInstallation(ctx, opts.Namespace, opts.Name)
    51  	if err != nil {
    52  		return storage.Installation{}, nil, err
    53  	}
    54  
    55  	if installation.Status.RunID != "" {
    56  		run, err := p.Installations.GetRun(ctx, installation.Status.RunID)
    57  		if err != nil {
    58  			return storage.Installation{}, nil, err
    59  		}
    60  		return installation, &run, nil
    61  	}
    62  
    63  	return installation, nil, nil
    64  
    65  }
    66  
    67  // ShowInstallation shows a bundle installation, along with any
    68  // associated outputs
    69  func (p *Porter) ShowInstallation(ctx context.Context, opts ShowOptions) error {
    70  	installation, run, err := p.GetInstallation(ctx, opts)
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	displayInstallation, err := p.NewDisplayInstallationWithSecrets(ctx, installation, run)
    76  	if err != nil {
    77  		return err
    78  	}
    79  
    80  	switch opts.Format {
    81  	case printer.FormatJson:
    82  		return printer.PrintJson(p.Out, displayInstallation)
    83  	case printer.FormatYaml:
    84  		return printer.PrintYaml(p.Out, displayInstallation)
    85  	case printer.FormatPlaintext:
    86  		// Set up human friendly time formatter
    87  		now := time.Now()
    88  		tp := dtprinter.DateTimePrinter{
    89  			Now: func() time.Time { return now },
    90  		}
    91  
    92  		// Print installation details
    93  		fmt.Fprintf(p.Out, "Name: %s\n", displayInstallation.Name)
    94  		fmt.Fprintf(p.Out, "Namespace: %s\n", displayInstallation.Namespace)
    95  		fmt.Fprintf(p.Out, "Created: %s\n", tp.Format(displayInstallation.Status.Created))
    96  		fmt.Fprintf(p.Out, "Modified: %s\n", tp.Format(displayInstallation.Status.Modified))
    97  
    98  		if displayInstallation.Bundle.Repository != "" {
    99  			fmt.Fprintln(p.Out)
   100  			fmt.Fprintln(p.Out, "Bundle:")
   101  			fmt.Fprintf(p.Out, "  Repository: %s\n", displayInstallation.Bundle.Repository)
   102  			if displayInstallation.Bundle.Version != "" {
   103  				fmt.Fprintf(p.Out, "  Version: %s\n", displayInstallation.Bundle.Version)
   104  			}
   105  			if displayInstallation.Bundle.Digest != "" {
   106  				fmt.Fprintf(p.Out, "  Digest: %s\n", displayInstallation.Bundle.Digest)
   107  			}
   108  		}
   109  
   110  		// Print labels, if any
   111  		if len(displayInstallation.Labels) > 0 {
   112  			fmt.Fprintln(p.Out)
   113  			fmt.Fprintln(p.Out, "Labels:")
   114  
   115  			// Print labels in alphabetical order
   116  			labels := make([]string, 0, len(installation.Labels))
   117  			for k, v := range installation.Labels {
   118  				labels = append(labels, fmt.Sprintf("%s: %s", k, v))
   119  			}
   120  			sort.Strings(labels)
   121  
   122  			for _, label := range labels {
   123  				fmt.Fprintf(p.Out, "  %s\n", label)
   124  			}
   125  		}
   126  
   127  		// Print parameters, if any
   128  		if len(displayInstallation.Parameters) > 0 {
   129  			fmt.Fprintln(p.Out)
   130  			fmt.Fprintln(p.Out, "Parameters:")
   131  
   132  			err = p.printDisplayValuesTable(displayInstallation.ResolvedParameters)
   133  			if err != nil {
   134  				return err
   135  			}
   136  
   137  		}
   138  
   139  		// Print parameter sets, if any
   140  		if len(displayInstallation.ParameterSets) > 0 {
   141  			fmt.Fprintln(p.Out)
   142  			fmt.Fprintln(p.Out, "Parameter Sets:")
   143  			for _, ps := range displayInstallation.ParameterSets {
   144  				fmt.Fprintf(p.Out, "  - %s\n", ps)
   145  			}
   146  		}
   147  
   148  		// Print credential sets, if any
   149  		if len(displayInstallation.CredentialSets) > 0 {
   150  			fmt.Fprintln(p.Out)
   151  			fmt.Fprintln(p.Out, "Credential Sets:")
   152  			for _, cs := range displayInstallation.CredentialSets {
   153  				fmt.Fprintf(p.Out, "  - %s\n", cs)
   154  			}
   155  		}
   156  
   157  		// Print the status (it may not be present if it's newly created using apply)
   158  		if installation.Status != (storage.InstallationStatus{}) {
   159  			fmt.Fprintln(p.Out)
   160  			fmt.Fprintln(p.Out, "Status:")
   161  			fmt.Fprintf(p.Out, "  Reference: %s\n", displayInstallation.Status.BundleReference)
   162  			fmt.Fprintf(p.Out, "  Version: %s\n", displayInstallation.Status.BundleVersion)
   163  			fmt.Fprintf(p.Out, "  Last Action: %s\n", displayInstallation.Status.Action)
   164  			fmt.Fprintf(p.Out, "  Status: %s\n", displayInstallation.Status.ResultStatus)
   165  			fmt.Fprintf(p.Out, "  Digest: %s\n", displayInstallation.Status.BundleDigest)
   166  		}
   167  
   168  		return nil
   169  	default:
   170  		return fmt.Errorf("invalid format: %s", opts.Format)
   171  	}
   172  }
   173  
   174  func (p *Porter) NewDisplayInstallationWithSecrets(ctx context.Context, installation storage.Installation, run *storage.Run) (DisplayInstallation, error) {
   175  	displayInstallation := NewDisplayInstallation(installation)
   176  
   177  	if run != nil {
   178  		bun := cnab.NewBundle(run.Bundle)
   179  		installParams, err := p.Sanitizer.RestoreParameterSet(ctx, installation.Parameters, bun)
   180  		if err != nil {
   181  			return DisplayInstallation{}, err
   182  		}
   183  		displayInstallation.Parameters = installParams
   184  
   185  		runParams, err := p.Sanitizer.RestoreParameterSet(ctx, run.Parameters, bun)
   186  		if err != nil {
   187  			return DisplayInstallation{}, err
   188  		}
   189  		displayInstallation.ResolvedParameters = NewDisplayValuesFromParameters(bun, runParams)
   190  	}
   191  
   192  	return displayInstallation, nil
   193  }