github.com/YousefHaggyHeroku/pack@v1.5.5/internal/builder/writer/structured_format.go (about) 1 package writer 2 3 import ( 4 "fmt" 5 6 "github.com/YousefHaggyHeroku/pack/internal/style" 7 8 "github.com/YousefHaggyHeroku/pack" 9 pubbldr "github.com/YousefHaggyHeroku/pack/builder" 10 "github.com/YousefHaggyHeroku/pack/internal/builder" 11 "github.com/YousefHaggyHeroku/pack/internal/config" 12 "github.com/YousefHaggyHeroku/pack/internal/dist" 13 "github.com/YousefHaggyHeroku/pack/logging" 14 ) 15 16 type InspectOutput struct { 17 SharedBuilderInfo 18 RemoteInfo *BuilderInfo `json:"remote_info" yaml:"remote_info" toml:"remote_info"` 19 LocalInfo *BuilderInfo `json:"local_info" yaml:"local_info" toml:"local_info"` 20 } 21 22 type RunImage struct { 23 Name string `json:"name" yaml:"name" toml:"name"` 24 UserConfigured bool `json:"user_configured,omitempty" yaml:"user_configured,omitempty" toml:"user_configured,omitempty"` 25 } 26 27 type Lifecycle struct { 28 builder.LifecycleInfo `yaml:"lifecycleinfo,inline"` 29 BuildpackAPIs builder.APIVersions `json:"buildpack_apis" yaml:"buildpack_apis" toml:"buildpack_apis"` 30 PlatformAPIs builder.APIVersions `json:"platform_apis" yaml:"platform_apis" toml:"platform_apis"` 31 } 32 33 type Stack struct { 34 ID string `json:"id" yaml:"id" toml:"id"` 35 Mixins []string `json:"mixins,omitempty" yaml:"mixins,omitempty" toml:"mixins,omitempty"` 36 } 37 38 type BuilderInfo struct { 39 Description string `json:"description,omitempty" yaml:"description,omitempty" toml:"description,omitempty"` 40 CreatedBy builder.CreatorMetadata `json:"created_by" yaml:"created_by" toml:"created_by"` 41 Stack Stack `json:"stack" yaml:"stack" toml:"stack"` 42 Lifecycle Lifecycle `json:"lifecycle" yaml:"lifecycle" toml:"lifecycle"` 43 RunImages []RunImage `json:"run_images" yaml:"run_images" toml:"run_images"` 44 Buildpacks []dist.BuildpackInfo `json:"buildpacks" yaml:"buildpacks" toml:"buildpacks"` 45 pubbldr.DetectionOrder `json:"detection_order" yaml:"detection_order" toml:"detection_order"` 46 } 47 48 type StructuredFormat struct { 49 MarshalFunc func(interface{}) ([]byte, error) 50 } 51 52 func (w *StructuredFormat) Print( 53 logger logging.Logger, 54 localRunImages []config.RunImage, 55 local, remote *pack.BuilderInfo, 56 localErr, remoteErr error, 57 builderInfo SharedBuilderInfo, 58 ) error { 59 if localErr != nil { 60 return fmt.Errorf("preparing output for %s: %w", style.Symbol(builderInfo.Name), localErr) 61 } 62 63 if remoteErr != nil { 64 return fmt.Errorf("preparing output for %s: %w", style.Symbol(builderInfo.Name), remoteErr) 65 } 66 67 outputInfo := InspectOutput{SharedBuilderInfo: builderInfo} 68 69 if local != nil { 70 stack := Stack{ID: local.Stack} 71 72 if logger.IsVerbose() { 73 stack.Mixins = local.Mixins 74 } 75 76 outputInfo.LocalInfo = &BuilderInfo{ 77 Description: local.Description, 78 CreatedBy: local.CreatedBy, 79 Stack: stack, 80 Lifecycle: Lifecycle{ 81 LifecycleInfo: local.Lifecycle.Info, 82 BuildpackAPIs: local.Lifecycle.APIs.Buildpack, 83 PlatformAPIs: local.Lifecycle.APIs.Platform, 84 }, 85 RunImages: runImages(local.RunImage, localRunImages, local.RunImageMirrors), 86 Buildpacks: local.Buildpacks, 87 DetectionOrder: local.Order, 88 } 89 } 90 91 if remote != nil { 92 stack := Stack{ID: remote.Stack} 93 94 if logger.IsVerbose() { 95 stack.Mixins = remote.Mixins 96 } 97 98 outputInfo.RemoteInfo = &BuilderInfo{ 99 Description: remote.Description, 100 CreatedBy: remote.CreatedBy, 101 Stack: stack, 102 Lifecycle: Lifecycle{ 103 LifecycleInfo: remote.Lifecycle.Info, 104 BuildpackAPIs: remote.Lifecycle.APIs.Buildpack, 105 PlatformAPIs: remote.Lifecycle.APIs.Platform, 106 }, 107 RunImages: runImages(remote.RunImage, localRunImages, remote.RunImageMirrors), 108 Buildpacks: remote.Buildpacks, 109 DetectionOrder: remote.Order, 110 } 111 } 112 113 if outputInfo.LocalInfo == nil && outputInfo.RemoteInfo == nil { 114 return fmt.Errorf("unable to find builder %s locally or remotely", style.Symbol(builderInfo.Name)) 115 } 116 117 var ( 118 output []byte 119 err error 120 ) 121 if output, err = w.MarshalFunc(outputInfo); err != nil { 122 return fmt.Errorf("untested, unexpected failure while marshaling: %w", err) 123 } 124 125 logger.Info(string(output)) 126 127 return nil 128 } 129 130 func runImages(runImage string, localRunImages []config.RunImage, buildRunImages []string) []RunImage { 131 var images = []RunImage{} 132 133 for _, i := range localRunImages { 134 if i.Image == runImage { 135 for _, m := range i.Mirrors { 136 images = append(images, RunImage{Name: m, UserConfigured: true}) 137 } 138 } 139 } 140 141 if runImage != "" { 142 images = append(images, RunImage{Name: runImage}) 143 } 144 145 for _, m := range buildRunImages { 146 images = append(images, RunImage{Name: m}) 147 } 148 149 return images 150 }