87f2e55086390bd51523ac79e0adefb8b803018c
[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 )
31
32 // ResolveVPPVersion resolves version of the VPP for target directory.
33 //
34 // Version resolved here can be overriden by setting VPP_VERSION env var.
35 func ResolveVPPVersion(apidir string) string {
36         // check env variable override
37         if ver := os.Getenv(VPPVersionEnvVar); ver != "" {
38                 logrus.Debugf("VPP version was manually set to %q via %s env var", ver, VPPVersionEnvVar)
39                 return ver
40         }
41
42         // assuming VPP package is installed
43         if path.Clean(apidir) == DefaultDir {
44                 version, err := GetVPPVersionInstalled()
45                 if err != nil {
46                         logrus.Warnf("resolving VPP version from installed package failed: %v", err)
47                 } else {
48                         logrus.Debugf("resolved VPP version from installed package: %v", version)
49                         return version
50                 }
51         }
52
53         // check if inside VPP repo
54         repoDir, err := findGitRepoRootDir(apidir)
55         if err != nil {
56                 logrus.Warnf("checking VPP git repo failed: %v", err)
57         } else {
58                 logrus.Debugf("resolved git repo root directory: %v", repoDir)
59                 version, err := GetVPPVersionRepo(repoDir)
60                 if err != nil {
61                         logrus.Warnf("resolving VPP version from version script failed: %v", err)
62                 } else {
63                         logrus.Debugf("resolved VPP version from version script: %v", version)
64                         return version
65                 }
66         }
67
68         // try to read VPP_VERSION file
69         data, err := ioutil.ReadFile(path.Join(repoDir, "VPP_VERSION"))
70         if err == nil {
71                 return strings.TrimSpace(string(data))
72         }
73
74         logrus.Warnf("VPP version could not be resolved, you can set it manually using %s env var", VPPVersionEnvVar)
75         return ""
76 }
77
78 // GetVPPVersionInstalled retrieves VPP version of installed package using dpkg-query.
79 func GetVPPVersionInstalled() (string, error) {
80         cmd := exec.Command("dpkg-query", "-f", "${Version}", "-W", "vpp")
81         out, err := cmd.CombinedOutput()
82         if err != nil {
83                 return "", fmt.Errorf("dpkg-query command failed: %v\noutput: %s", err, out)
84         }
85         return strings.TrimSpace(string(out)), nil
86 }
87
88 const versionScriptPath = "./src/scripts/version"
89
90 // GetVPPVersionRepo retrieves VPP version using script in repo directory.
91 func GetVPPVersionRepo(repoDir string) (string, error) {
92         if _, err := os.Stat(versionScriptPath); err != nil {
93                 return "", err
94         }
95         cmd := exec.Command(versionScriptPath)
96         cmd.Dir = repoDir
97         out, err := cmd.CombinedOutput()
98         if err != nil {
99                 return "", fmt.Errorf("version script failed: %v\noutput: %s", err, out)
100         }
101         return strings.TrimSpace(string(out)), nil
102 }
103
104 func findGitRepoRootDir(dir string) (string, error) {
105         cmd := exec.Command("git", "rev-parse", "--show-toplevel")
106         cmd.Dir = dir
107         out, err := cmd.CombinedOutput()
108         if err != nil {
109                 return "", fmt.Errorf("git command failed: %v\noutput: %s", err, out)
110         }
111         return strings.TrimSpace(string(out)), nil
112 }