Improve doc & fix import ordering
[govpp.git] / binapigen / vppapi / util.go
1 //  Copyright (c) 2020 Cisco and/or its affiliates.
2 //
3 //  Licensed under the Apache License, Version 2.0 (the "License");
4 //  you may not use this file except in compliance with the License.
5 //  You may obtain a copy of the License at:
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 //  Unless required by applicable law or agreed to in writing, software
10 //  distributed under the License is distributed on an "AS IS" BASIS,
11 //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 //  See the License for the specific language governing permissions and
13 //  limitations under the License.
14
15 package vppapi
16
17 import (
18         "fmt"
19         "io/ioutil"
20         "os"
21         "os/exec"
22         "path"
23         "strings"
24
25         "github.com/sirupsen/logrus"
26 )
27
28 const (
29         VPPVersionEnvVar  = "VPP_VERSION"
30         VPPDirEnvVar      = "VPP_DIR"
31         versionScriptPath = "./src/scripts/version"
32 )
33
34 // ResolveVPPVersion resolves version of the VPP for target directory.
35 //
36 // Version resolved here can be overriden by setting VPP_VERSION env var.
37 func ResolveVPPVersion(apidir string) string {
38         // check env variable override
39         if ver := os.Getenv(VPPVersionEnvVar); ver != "" {
40                 logrus.Infof("VPP version was manually set to %q via %s env var", ver, VPPVersionEnvVar)
41                 return ver
42         }
43
44         // assuming VPP package is installed
45         if path.Clean(apidir) == DefaultDir {
46                 version, err := GetVPPVersionInstalled()
47                 if err != nil {
48                         logrus.Warnf("resolving VPP version from installed package failed: %v", err)
49                 } else {
50                         logrus.Debugf("resolved VPP version from installed package: %v", version)
51                         return version
52                 }
53         }
54
55         // check if inside VPP repo
56         repoDir, err := findGitRepoRootDir(apidir)
57         if err != nil {
58                 logrus.Warnf("checking VPP git repo failed: %v", err)
59         } else {
60                 logrus.Debugf("resolved git repo root directory: %v", repoDir)
61                 version, err := GetVPPVersionRepo(repoDir)
62                 if err != nil {
63                         logrus.Warnf("resolving VPP version from version script failed: %v", err)
64                 } else {
65                         logrus.Infof("resolved VPP version from version script: %v", version)
66                         return version
67                 }
68         }
69
70         // try to read VPP_VERSION file
71         data, err := ioutil.ReadFile(path.Join(repoDir, "VPP_VERSION"))
72         if err == nil {
73                 return strings.TrimSpace(string(data))
74         }
75
76         logrus.Warnf("VPP version could not be resolved, you can set it manually using %s env var", VPPVersionEnvVar)
77         return ""
78 }
79
80 // GetVPPVersionInstalled retrieves VPP version of installed package using dpkg-query.
81 func GetVPPVersionInstalled() (string, error) {
82         cmd := exec.Command("dpkg-query", "-f", "${Version}", "-W", "vpp")
83         out, err := cmd.CombinedOutput()
84         if err != nil {
85                 return "", fmt.Errorf("dpkg-query command failed: %v\noutput: %s", err, out)
86         }
87         return strings.TrimSpace(string(out)), nil
88 }
89
90 // GetVPPVersionRepo retrieves VPP version using script in repo directory.
91 func GetVPPVersionRepo(repoDir string) (string, error) {
92         scriptPath := path.Join(repoDir, versionScriptPath)
93         if _, err := os.Stat(scriptPath); err != nil {
94                 return "", err
95         }
96         cmd := exec.Command(scriptPath)
97         cmd.Dir = repoDir
98         out, err := cmd.CombinedOutput()
99         if err != nil {
100                 return "", fmt.Errorf("version script failed: %v\noutput: %s", err, out)
101         }
102         return strings.TrimSpace(string(out)), nil
103 }
104
105 func findGitRepoRootDir(dir string) (string, error) {
106         if conf := os.Getenv(VPPDirEnvVar); conf != "" {
107                 logrus.Infof("VPP directory was manually set to %q via %s env var", conf, VPPDirEnvVar)
108                 return conf, nil
109         }
110         cmd := exec.Command("git", "rev-parse", "--show-toplevel")
111         cmd.Dir = dir
112         out, err := cmd.CombinedOutput()
113         if err != nil {
114                 return "", fmt.Errorf("git command failed: %v\noutput: %s", err, out)
115         }
116         return strings.TrimSpace(string(out)), nil
117 }