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 }