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  }