github.com/simonferquel/app@v0.6.1-0.20181012141724-68b7cccf26ac/internal/inspect/inspect.go (about)

     1  package inspect
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"sort"
     7  	"strings"
     8  	"text/tabwriter"
     9  
    10  	"github.com/docker/app/render"
    11  	"github.com/docker/app/types"
    12  	"github.com/docker/app/types/settings"
    13  	composetypes "github.com/docker/cli/cli/compose/types"
    14  	units "github.com/docker/go-units"
    15  )
    16  
    17  // Inspect dumps the metadata of an app
    18  func Inspect(out io.Writer, app *types.App, argSettings map[string]string) error {
    19  	// Render the compose file
    20  	config, err := render.Render(app, argSettings)
    21  	if err != nil {
    22  		return err
    23  	}
    24  
    25  	// Extract all the settings
    26  	settingsKeys, allSettings, err := extractSettings(app, argSettings)
    27  	if err != nil {
    28  		return err
    29  	}
    30  
    31  	// Add Meta data
    32  	printMetadata(out, app)
    33  
    34  	// Add Service section
    35  	printSection(out, len(config.Services), func(w io.Writer) {
    36  		for _, service := range config.Services {
    37  			fmt.Fprintf(w, "%s\t%d\t%s\t%s\n", service.Name, getReplicas(service), getPorts(service.Ports), service.Image)
    38  		}
    39  	}, "Service", "Replicas", "Ports", "Image")
    40  
    41  	// Add Network section
    42  	printSection(out, len(config.Networks), func(w io.Writer) {
    43  		for name := range config.Networks {
    44  			fmt.Fprintln(w, name)
    45  		}
    46  	}, "Network")
    47  
    48  	// Add Volume section
    49  	printSection(out, len(config.Volumes), func(w io.Writer) {
    50  		for name := range config.Volumes {
    51  			fmt.Fprintln(w, name)
    52  		}
    53  	}, "Volume")
    54  
    55  	// Add Secret section
    56  	printSection(out, len(config.Secrets), func(w io.Writer) {
    57  		for name := range config.Secrets {
    58  			fmt.Fprintln(w, name)
    59  		}
    60  	}, "Secret")
    61  
    62  	// Add Setting section
    63  	printSection(out, len(settingsKeys), func(w io.Writer) {
    64  		for _, k := range settingsKeys {
    65  			fmt.Fprintf(w, "%s\t%s\n", k, allSettings[k])
    66  		}
    67  	}, "Setting", "Value")
    68  
    69  	// Add Attachments section
    70  	attachments := app.Attachments()
    71  	printSection(out, len(attachments), func(w io.Writer) {
    72  		for _, file := range attachments {
    73  			sizeString := units.HumanSize(float64(file.Size()))
    74  			fmt.Fprintf(w, "%s\t%s\n", file.Path(), sizeString)
    75  		}
    76  	}, "Attachment", "Size")
    77  
    78  	return nil
    79  }
    80  
    81  func printMetadata(out io.Writer, app *types.App) {
    82  	meta := app.Metadata()
    83  	fmt.Fprintln(out, meta.Name, meta.Version)
    84  	if maintainers := meta.Maintainers.String(); maintainers != "" {
    85  		fmt.Fprintln(out)
    86  		fmt.Fprintln(out, "Maintained by:", maintainers)
    87  	}
    88  	if meta.Description != "" {
    89  		fmt.Fprintln(out)
    90  		fmt.Fprintln(out, meta.Description)
    91  	}
    92  }
    93  
    94  func printSection(out io.Writer, len int, printer func(io.Writer), headers ...string) {
    95  	if len == 0 {
    96  		return
    97  	}
    98  	fmt.Fprintln(out)
    99  	w := tabwriter.NewWriter(out, 0, 0, 1, ' ', 0)
   100  	var plural string
   101  	if len > 1 {
   102  		plural = "s"
   103  	}
   104  	headers[0] = fmt.Sprintf("%s%s (%d)", headers[0], plural, len)
   105  	printHeaders(w, headers...)
   106  	printer(w)
   107  	w.Flush()
   108  }
   109  
   110  func printHeaders(w io.Writer, headers ...string) {
   111  	fmt.Fprintln(w, strings.Join(headers, "\t"))
   112  	dashes := make([]string, len(headers))
   113  	for i, h := range headers {
   114  		dashes[i] = strings.Repeat("-", len(h))
   115  	}
   116  	fmt.Fprintln(w, strings.Join(dashes, "\t"))
   117  }
   118  
   119  func getReplicas(service composetypes.ServiceConfig) int {
   120  	if service.Deploy.Replicas != nil {
   121  		return int(*service.Deploy.Replicas)
   122  	}
   123  	return 1
   124  }
   125  
   126  func extractSettings(app *types.App, argSettings map[string]string) ([]string, map[string]string, error) {
   127  	allSettings, err := mergeAndFlattenSettings(app, argSettings)
   128  	if err != nil {
   129  		return nil, nil, err
   130  	}
   131  	// sort the keys to get consistent output
   132  	var settingsKeys []string
   133  	for k := range allSettings {
   134  		settingsKeys = append(settingsKeys, k)
   135  	}
   136  	sort.Slice(settingsKeys, func(i, j int) bool { return settingsKeys[i] < settingsKeys[j] })
   137  	return settingsKeys, allSettings, nil
   138  }
   139  
   140  func mergeAndFlattenSettings(app *types.App, argSettings map[string]string) (map[string]string, error) {
   141  	sArgs, err := settings.FromFlatten(argSettings)
   142  	if err != nil {
   143  		return nil, err
   144  	}
   145  	s, err := settings.Merge(app.Settings(), sArgs)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	return s.Flatten(), nil
   150  }