github.com/vchain-us/vcn@v0.9.11-0.20210921212052-a2484d23c0b3/pkg/cmd/internal/cli/lc_output.go (about)

     1  /*
     2   * Copyright (c) 2018-2020 vChain, Inc. All Rights Reserved.
     3   * This software is released under GPL3.
     4   * The full license information can be found under:
     5   * https://www.gnu.org/licenses/gpl-3.0.en.html
     6   *
     7   */
     8  
     9  package cli
    10  
    11  import (
    12  	"encoding/json"
    13  	"fmt"
    14  	"io"
    15  	"reflect"
    16  	"strings"
    17  	"text/tabwriter"
    18  	"time"
    19  
    20  	"github.com/dustin/go-humanize"
    21  	"github.com/fatih/color"
    22  	"github.com/mattn/go-colorable"
    23  	"github.com/vchain-us/vcn/pkg/api"
    24  	"github.com/vchain-us/vcn/pkg/cmd/internal/types"
    25  	"github.com/vchain-us/vcn/pkg/meta"
    26  	"gopkg.in/yaml.v2"
    27  )
    28  
    29  func PrintLc(output string, r *types.LcResult) error {
    30  	switch output {
    31  	case "":
    32  		WriteLcResultTo(r, colorable.NewColorableStdout())
    33  	case "attachments":
    34  		WriteLcResultTo(r, colorable.NewColorableStdout())
    35  	case "yaml":
    36  		b, err := yaml.Marshal(r)
    37  		if err != nil {
    38  			return err
    39  		}
    40  		fmt.Println(string(b))
    41  	case "json":
    42  		b, err := json.MarshalIndent(r, "", "  ")
    43  		if err != nil {
    44  			return err
    45  		}
    46  		fmt.Println(string(b))
    47  	default:
    48  		return outputNotSupportedErr(output)
    49  	}
    50  	return nil
    51  }
    52  
    53  func WriteLcResultTo(r *types.LcResult, out io.Writer) (n int64, err error) {
    54  	if r == nil {
    55  		return 0, nil
    56  	}
    57  
    58  	w := new(tabwriter.Writer)
    59  	w.Init(out, 0, 8, 0, '\t', 0)
    60  
    61  	printf := func(format string, a ...interface{}) error {
    62  		m, err := fmt.Fprintf(w, format, a...)
    63  		n += int64(m)
    64  		return err
    65  	}
    66  
    67  	s := reflect.ValueOf(r).Elem()
    68  	s = s.FieldByName("LcArtifact")
    69  	typeOfT := s.Type()
    70  
    71  	for i, l := 0, s.NumField(); i < l; i++ {
    72  		f := s.Field(i)
    73  		if key, ok := typeOfT.Field(i).Tag.Lookup("vcn"); ok {
    74  			var value string
    75  			switch key {
    76  			case "Size":
    77  				if size, ok := f.Interface().(uint64); ok && size > 0 {
    78  					value = humanize.Bytes(size)
    79  				}
    80  			case "Metadata":
    81  				if metadata, ok := f.Interface().(api.Metadata); ok {
    82  					for k, v := range metadata {
    83  						if v == "" {
    84  							continue
    85  						}
    86  						if vv, err := json.MarshalIndent(v, "\t", "    "); err == nil {
    87  							value += fmt.Sprintf("\n\t\t%s=%s", k, string(vv))
    88  						}
    89  					}
    90  					value = strings.TrimPrefix(value, "\n")
    91  				}
    92  			case "Apikey revoked":
    93  				if f.IsZero() {
    94  					value = color.New(meta.StyleWarning()).Sprintf("not available")
    95  				} else {
    96  					if revoked, ok := f.Interface().(*time.Time); ok {
    97  						if revoked.IsZero() {
    98  							value = color.New(meta.StyleAffordance()).Sprintf("no")
    99  						} else {
   100  							value = color.New(meta.StyleError()).Sprintf(revoked.Format(time.UnixDate))
   101  						}
   102  					}
   103  				}
   104  			case "Attachments":
   105  				if attachments, ok := f.Interface().([]api.Attachment); ok {
   106  					for _, attach := range attachments {
   107  						if attach.Filename == "" {
   108  							continue
   109  						}
   110  						v := reflect.ValueOf(attach)
   111  
   112  						for i := 0; i < v.NumField(); i++ {
   113  							sep := "\n\t  %s:\t%s"
   114  							if i == 0 {
   115  								sep = "\n\t- %s:\t%s"
   116  							}
   117  							value += fmt.Sprintf(sep, v.Type().Field(i).Name, v.Field(i).String())
   118  						}
   119  					}
   120  				}
   121  			case "Status":
   122  				err = printf("Status:\t%s\n", meta.StatusNameStyled(r.Status))
   123  				if err != nil {
   124  					return
   125  				}
   126  			case "Included in":
   127  				if included, ok := f.Interface().([]api.PackageDetails); ok {
   128  					value += formatPackageDetails(included)
   129  				}
   130  			case "Dependencies":
   131  				if deps, ok := f.Interface().([]api.PackageDetails); ok {
   132  					value += formatPackageDetails(deps)
   133  				}
   134  			default:
   135  				value = fmt.Sprintf("%s", f.Interface())
   136  			}
   137  			if value != "" {
   138  				err = printf("%s:\t%s\n", key, value)
   139  				if err != nil {
   140  					return
   141  				}
   142  			}
   143  		}
   144  	}
   145  
   146  	// here extra data when --verbose flag is provided
   147  	if r.Verbose != nil {
   148  		err = printf("\nAdditional details:\n")
   149  		if err != nil {
   150  			return
   151  		}
   152  		s = reflect.ValueOf(r.Verbose).Elem()
   153  		typeOfT = s.Type()
   154  		for i, l := 0, s.NumField(); i < l; i++ {
   155  			if key, ok := typeOfT.Field(i).Tag.Lookup("vcn"); ok {
   156  				switch key {
   157  				case "LedgerName":
   158  					err = printf("Ledger Name:\t%s\n", r.Verbose.LedgerName)
   159  					if err != nil {
   160  						return
   161  					}
   162  				case "LocalSID":
   163  					err = printf("Local SignerID:\t%s\n", r.Verbose.LocalSID)
   164  					if err != nil {
   165  						return
   166  					}
   167  				case "ApiKey":
   168  					err = printf("Api-key:\t%s\n", r.Verbose.ApiKey)
   169  					if err != nil {
   170  						return
   171  					}
   172  				}
   173  			}
   174  		}
   175  	}
   176  
   177  	for _, e := range r.Errors {
   178  		err = printf("Error:\t%s\n", color.New(meta.StyleError()).Sprintf(e.Error()))
   179  		if err != nil {
   180  			return
   181  		}
   182  	}
   183  
   184  	return n, w.Flush()
   185  }
   186  
   187  func PrintLcSlice(output string, rs []*types.LcResult) error {
   188  	switch output {
   189  	case "":
   190  		for _, r := range rs {
   191  			WriteLcResultTo(r, colorable.NewColorableStdout())
   192  			fmt.Println()
   193  		}
   194  	case "yaml":
   195  		b, err := yaml.Marshal(rs)
   196  		if err != nil {
   197  			return err
   198  		}
   199  		fmt.Println(string(b))
   200  	case "json":
   201  		b, err := json.MarshalIndent(rs, "", "  ")
   202  		if err != nil {
   203  			return err
   204  		}
   205  		fmt.Println(string(b))
   206  	default:
   207  		return outputNotSupportedErr(output)
   208  	}
   209  	return nil
   210  }
   211  
   212  func PrintAttachmentList(attach string, attachmentList []api.Attachment) {
   213  	if len(attachmentList) == 0 {
   214  		fmt.Println("no attachments founded")
   215  		return
   216  	}
   217  	color.Set(meta.StyleAffordance())
   218  	attachDownloadMessage := "downloading attachments ..."
   219  	if attach != "" {
   220  		attachDownloadMessage = "downloading all notarizations attachments associated to the provided label ..."
   221  	}
   222  	fmt.Println(attachDownloadMessage)
   223  	color.Unset()
   224  
   225  	fmt.Printf("Download list:\n")
   226  	for _, a := range attachmentList {
   227  		fmt.Printf("\t\t- Filename:\t%s\n", a.Filename)
   228  		fmt.Printf("\t\t  Hash:\t\t%s\n", a.Hash)
   229  		fmt.Printf("\t\t  Mime:\t\t%s\n", a.Mime)
   230  	}
   231  	fmt.Printf("\n")
   232  }
   233  
   234  func formatPackageDetails(packages []api.PackageDetails) string {
   235  	var ret string
   236  	maxWidth := 0
   237  	for _, pkg := range packages {
   238  		width := len(pkg.Name) + len(pkg.Version)
   239  		if width > maxWidth {
   240  			maxWidth = width
   241  		}
   242  	}
   243  	maxWidth++
   244  	for i, pkg := range packages {
   245  		if i != 0 {
   246  			ret += "\n"
   247  		}
   248  		var line string
   249  		if pkg.Version != "" {
   250  			line = pkg.Name + "@" + pkg.Version
   251  		} else {
   252  			line = pkg.Name
   253  		}
   254  		ret += fmt.Sprintf("\t%-*s %s", maxWidth, line, pkg.Hash)
   255  	}
   256  
   257  	return ret
   258  }