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

     1  package porter
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"get.porter.sh/porter/pkg/cnab"
     8  	"get.porter.sh/porter/pkg/printer"
     9  	"github.com/cnabio/cnab-go/bundle"
    10  )
    11  
    12  type InspectableBundle struct {
    13  	Name             string                     `json:"name" yaml:"name"`
    14  	Description      string                     `json:"description,omitempty" yaml:"description,omitempty"`
    15  	Version          string                     `json:"version" yaml:"version"`
    16  	InvocationImages []PrintableInvocationImage `json:"invocationImages" yaml:"invocationImages"`
    17  	Images           []PrintableImage           `json:"images,omitempty" yaml:"images,omitempty"`
    18  }
    19  
    20  type PrintableInvocationImage struct {
    21  	bundle.InvocationImage
    22  	Original string `json:"originalImage" yaml:"originalImage"`
    23  }
    24  
    25  type PrintableImage struct {
    26  	Name string `json:"name" yaml:"name"`
    27  	bundle.Image
    28  	Original string `json:"originalImage" yaml:"originalImage"`
    29  }
    30  
    31  func (p *Porter) Inspect(ctx context.Context, o ExplainOpts) error {
    32  	bundleRef, err := o.GetBundleReference(ctx, p)
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	ib, err := generateInspectableBundle(bundleRef)
    38  	if err != nil {
    39  		return fmt.Errorf("unable to inspect bundle: %w", err)
    40  	}
    41  	return p.printBundleInspect(o, ib)
    42  }
    43  
    44  func generateInspectableBundle(bundleRef cnab.BundleReference) (*InspectableBundle, error) {
    45  	ib := &InspectableBundle{
    46  		Name:        bundleRef.Definition.Name,
    47  		Description: bundleRef.Definition.Description,
    48  		Version:     bundleRef.Definition.Version,
    49  	}
    50  	ib.InvocationImages, ib.Images = handleInspectRelocate(bundleRef)
    51  	return ib, nil
    52  }
    53  
    54  func handleInspectRelocate(bundleRef cnab.BundleReference) ([]PrintableInvocationImage, []PrintableImage) {
    55  	invoImages := []PrintableInvocationImage{}
    56  	for _, invoImage := range bundleRef.Definition.InvocationImages {
    57  		pii := PrintableInvocationImage{
    58  			InvocationImage: invoImage,
    59  		}
    60  		if mappedInvo, ok := bundleRef.RelocationMap[invoImage.Image]; ok {
    61  			pii.Original = pii.Image
    62  			pii.Image = mappedInvo
    63  		}
    64  		invoImages = append(invoImages, pii)
    65  	}
    66  	images := []PrintableImage{}
    67  	for alias, image := range bundleRef.Definition.Images {
    68  		pi := PrintableImage{
    69  			Name:  alias,
    70  			Image: image,
    71  		}
    72  		if mappedImg, ok := bundleRef.RelocationMap[image.Image]; ok {
    73  			pi.Original = pi.Image.Image
    74  			pi.Image.Image = mappedImg
    75  		}
    76  		images = append(images, pi)
    77  	}
    78  	return invoImages, images
    79  }
    80  
    81  func (p *Porter) printBundleInspect(o ExplainOpts, ib *InspectableBundle) error {
    82  	switch o.Format {
    83  	case printer.FormatJson:
    84  		return printer.PrintJson(p.Out, ib)
    85  	case printer.FormatYaml:
    86  		return printer.PrintYaml(p.Out, ib)
    87  	case printer.FormatPlaintext:
    88  		return p.printBundleInspectTable(ib)
    89  	default:
    90  		return fmt.Errorf("invalid format: %s", o.Format)
    91  	}
    92  }
    93  
    94  func (p *Porter) printBundleInspectTable(bun *InspectableBundle) error {
    95  	fmt.Fprintf(p.Out, "Name: %s\n", bun.Name)
    96  	fmt.Fprintf(p.Out, "Description: %s\n", bun.Description)
    97  	fmt.Fprintf(p.Out, "Version: %s\n", bun.Version)
    98  	fmt.Fprintln(p.Out, "")
    99  
   100  	err := p.printInvocationImageInspectBlock(bun)
   101  	if err != nil {
   102  		return err
   103  	}
   104  	err = p.printImagesInspectBlock(bun)
   105  	if err != nil {
   106  		return err
   107  	}
   108  	return nil
   109  }
   110  
   111  func (p *Porter) printInvocationImageInspectBlock(bun *InspectableBundle) error {
   112  	fmt.Fprintln(p.Out, "Bundle Images:")
   113  	err := p.printInvocationImageInspectTable(bun)
   114  	if err != nil {
   115  		return fmt.Errorf("unable to print bundle images table: %w", err)
   116  	}
   117  	fmt.Fprintln(p.Out, "") // force a blank line after this block
   118  	return nil
   119  }
   120  
   121  func (p *Porter) printInvocationImageInspectTable(bun *InspectableBundle) error {
   122  	printInvocationImageRow :=
   123  		func(v interface{}) []string {
   124  			ii, ok := v.(PrintableInvocationImage)
   125  			if !ok {
   126  				return nil
   127  			}
   128  			return []string{ii.Image, ii.ImageType, ii.Digest, ii.Original}
   129  		}
   130  	return printer.PrintTable(p.Out, bun.InvocationImages, printInvocationImageRow, "Image", "Type", "Digest", "Original Image")
   131  }
   132  
   133  func (p *Porter) printImagesInspectBlock(bun *InspectableBundle) error {
   134  	if len(bun.Images) == 0 {
   135  		return nil
   136  	}
   137  
   138  	fmt.Fprintln(p.Out, "Images:")
   139  	err := p.printImagesInspectTable(bun)
   140  	if err != nil {
   141  		return fmt.Errorf("unable to print images table: %w", err)
   142  	}
   143  	fmt.Fprintln(p.Out, "") // force a blank line after this block
   144  
   145  	return nil
   146  }
   147  
   148  func (p *Porter) printImagesInspectTable(bun *InspectableBundle) error {
   149  	printImageRow :=
   150  		func(v interface{}) []string {
   151  			pi, ok := v.(PrintableImage)
   152  			if !ok {
   153  				return nil
   154  			}
   155  			return []string{pi.Name, pi.ImageType, pi.Image.Image, pi.Digest, pi.Original}
   156  		}
   157  	return printer.PrintTable(p.Out, bun.Images, printImageRow, "Name", "Type", "Image", "Digest", "Original Image")
   158  }