github.com/Mirantis/virtlet@v1.5.2-0.20191204181327-1659b8a48e9b/pkg/version/version.go (about)

     1  /*
     2  Copyright 2018 Mirantis
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package version
    18  
    19  import (
    20  	"bytes"
    21  	"encoding/json"
    22  	"fmt"
    23  	"log"
    24  	"runtime"
    25  
    26  	"github.com/ghodss/yaml"
    27  )
    28  
    29  // Info specifies Virtlet version info
    30  type Info struct {
    31  	// NodeName denotes the name of the node this info belongs too
    32  	// (empty if not applicable)
    33  	NodeName string `json:",omitempty"`
    34  	// Major is the major version number
    35  	Major string `json:"major"`
    36  	// Minor is the minor version number
    37  	Minor string `json:"minor"`
    38  	// GitVersion is the full version string
    39  	GitVersion string `json:"gitVersion"`
    40  	// GitCommit is the git commit id
    41  	GitCommit string `json:"gitCommit"`
    42  	// GitTreeState is the git tree state, which can be either "clean" or "dirty"
    43  	GitTreeState string `json:"gitTreeState"`
    44  	// BuildDate is the build date, e.g. 2018-04-16T18:48:12Z
    45  	BuildDate string `json:"buildDate"`
    46  	// GoVersion is the Go version that was used to build Virtlet
    47  	GoVersion string `json:"goVersion"`
    48  	// Compiler is the name of the compiler toolchain that
    49  	// built the binary (either "gc" or "gccgo")
    50  	Compiler string `json:"compiler"`
    51  	// Platform denotes the platform such as "linux" or "darwin"
    52  	Platform string `json:"platform"`
    53  	// ImageTag specifies the image tag to use for Virtelt
    54  	ImageTag string `json:"imageTag"`
    55  }
    56  
    57  type formatVersion func(v Info) []byte
    58  
    59  func (v Info) text(indent string) []byte {
    60  	var b bytes.Buffer
    61  	fmt.Fprintf(&b, "%sVersion:    %s\n", indent, v.GitVersion)
    62  	fmt.Fprintf(&b, "%sCommit:     %s\n", indent, v.GitCommit)
    63  	fmt.Fprintf(&b, "%sBuild Date: %s\n", indent, v.BuildDate)
    64  	fmt.Fprintf(&b, "%sGo Version: %s\n", indent, v.GoVersion)
    65  	fmt.Fprintf(&b, "%sCompiler:   %s\n", indent, v.Compiler)
    66  	fmt.Fprintf(&b, "%sPlatform:   %s\n", indent, v.Platform)
    67  	if v.ImageTag != "" {
    68  		fmt.Fprintf(&b, "%sImageTag:   %s\n", indent, v.ImageTag)
    69  	}
    70  	return b.Bytes()
    71  }
    72  
    73  var versionFormats = map[string]formatVersion{
    74  	"text": func(v Info) []byte {
    75  		return v.text("")
    76  	},
    77  	"short": func(v Info) []byte {
    78  		return []byte(v.GitVersion)
    79  	},
    80  	"json": func(v Info) []byte {
    81  		out, err := json.Marshal(v)
    82  		if err != nil {
    83  			log.Panicf("Error marshaling version info to JSON: %#v: %v", v, err)
    84  		}
    85  		return out
    86  	},
    87  	"yaml": func(v Info) []byte {
    88  		out, err := yaml.Marshal(v)
    89  		if err != nil {
    90  			log.Panicf("Error marshaling version info to YAML: %#v: %v", v, err)
    91  		}
    92  		return out
    93  	},
    94  }
    95  
    96  // ToBytes returns a text representation of Info using the specified
    97  // format which can be one of "text", "short", "json" or "yaml"
    98  func (v Info) ToBytes(format string) ([]byte, error) {
    99  	f := versionFormats[format]
   100  	if f == nil {
   101  		return nil, fmt.Errorf("bad version format %q", format)
   102  	}
   103  	return f(v), nil
   104  }
   105  
   106  // Get returns the codebase version.
   107  func Get() Info {
   108  	return Info{
   109  		Major:        gitMajor,
   110  		Minor:        gitMinor,
   111  		GitVersion:   gitVersion,
   112  		GitCommit:    gitCommit,
   113  		GitTreeState: gitTreeState,
   114  		BuildDate:    buildDate,
   115  		GoVersion:    runtime.Version(),
   116  		Compiler:     runtime.Compiler,
   117  		Platform:     runtime.GOOS + "/" + runtime.GOARCH,
   118  		ImageTag:     imageTag,
   119  	}
   120  }
   121  
   122  // ClusterVersionInfo specifies Virtlet version info for the whole
   123  // cluster and the client
   124  type ClusterVersionInfo struct {
   125  	// ClientVersion denotes the version of Virtlet command line tool
   126  	ClientVersion Info `json:"clientVersion"`
   127  	// NodeVersions specify versions for each node that runs Virtlet
   128  	NodeVersions []Info `json:"nodeVersions,omitempty"`
   129  }
   130  
   131  type formatClusterVersion func(v ClusterVersionInfo) []byte
   132  
   133  var clusterVersionFormats = map[string]formatClusterVersion{
   134  	"text": func(v ClusterVersionInfo) []byte {
   135  		var b bytes.Buffer
   136  		fmt.Fprintf(&b, "Client:\n%s", v.ClientVersion.text("  "))
   137  		for _, nv := range v.NodeVersions {
   138  			fmt.Fprintf(&b, "Node %s:\n%s", nv.NodeName, nv.text("  "))
   139  		}
   140  		return b.Bytes()
   141  	},
   142  	"short": func(v ClusterVersionInfo) []byte {
   143  		var b bytes.Buffer
   144  		fmt.Fprintf(&b, "Client: %s\n", v.ClientVersion.GitVersion)
   145  		for _, nv := range v.NodeVersions {
   146  			fmt.Fprintf(&b, "Node %s: %s\n", nv.NodeName, nv.GitVersion)
   147  		}
   148  		return b.Bytes()
   149  	},
   150  	"json": func(v ClusterVersionInfo) []byte {
   151  		out, err := json.Marshal(v)
   152  		if err != nil {
   153  			log.Panicf("Error marshaling version info to JSON: %#v: %v", v, err)
   154  		}
   155  		return out
   156  	},
   157  	"yaml": func(v ClusterVersionInfo) []byte {
   158  		out, err := yaml.Marshal(v)
   159  		if err != nil {
   160  			log.Panicf("Error marshaling version info to YAML: %#v: %v", v, err)
   161  		}
   162  		return out
   163  	},
   164  }
   165  
   166  // ToBytes returns a text representation of ClusterVersionInfo using
   167  // the specified format which can be one of "text", "short", "json" or
   168  // "yaml"
   169  func (v ClusterVersionInfo) ToBytes(format string) ([]byte, error) {
   170  	f := clusterVersionFormats[format]
   171  	if f == nil {
   172  		return nil, fmt.Errorf("bad version format %q", format)
   173  	}
   174  	return f(v), nil
   175  }
   176  
   177  // AreNodesConsistent returns true if all the nodes that run Virtlet
   178  // run exactly same Virtlet build
   179  func (v ClusterVersionInfo) AreNodesConsistent() bool {
   180  	if len(v.NodeVersions) == 0 {
   181  		return true
   182  	}
   183  	nv := v.NodeVersions[0]
   184  	nv.NodeName = ""
   185  	for _, curNV := range v.NodeVersions[1:] {
   186  		curNV.NodeName = ""
   187  		if nv != curNV {
   188  			return false
   189  		}
   190  	}
   191  	return true
   192  }