-
Notifications
You must be signed in to change notification settings - Fork 1
/
root.go
129 lines (108 loc) · 3.69 KB
/
root.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Copyright (C) 2019-2021, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package cmd
import (
"fmt"
"os"
"path/filepath"
"github.com/ava-labs/avalanchego/utils/wrappers"
"github.com/go-git/go-git/v5/plumbing/transport/http"
"github.com/spf13/afero"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"gopkg.in/yaml.v3"
"github.com/ava-labs/apm/apm"
"github.com/ava-labs/apm/config"
"github.com/ava-labs/apm/constant"
)
var (
goPath = os.ExpandEnv("$GOPATH")
homeDir = os.ExpandEnv("$HOME")
apmDir = filepath.Join(homeDir, fmt.Sprintf(".%s", constant.AppName))
)
const (
configFileKey = "config-file"
apmPathKey = "apm-path"
pluginPathKey = "plugin-path"
credentialsFileKey = "credentials-file"
adminAPIEndpointKey = "admin-api-endpoint"
)
func New(fs afero.Fs) (*cobra.Command, error) {
rootCmd := &cobra.Command{
Use: "apm",
Short: "apm is a plugin manager to help manage virtual machines and subnets",
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
// we need to initialize our config here before each command starts,
// since Cobra doesn't actually parse any of the flags until
// cobra.Execute() is called.
return initializeConfig()
},
}
rootCmd.PersistentFlags().String(configFileKey, "", "path to configuration file for the apm")
rootCmd.PersistentFlags().String(apmPathKey, apmDir, "path to the directory apm creates its artifacts")
rootCmd.PersistentFlags().String(pluginPathKey, filepath.Join(goPath, "src", "github.com", "ava-labs", "avalanchego", "build", "plugins"), "path to avalanche plugin directory")
rootCmd.PersistentFlags().String(credentialsFileKey, "", "path to credentials file")
rootCmd.PersistentFlags().String(adminAPIEndpointKey, "127.0.0.1:9650/ext/admin", "endpoint for the avalanche admin api")
errs := wrappers.Errs{}
errs.Add(
viper.BindPFlag(configFileKey, rootCmd.PersistentFlags().Lookup(configFileKey)),
viper.BindPFlag(apmPathKey, rootCmd.PersistentFlags().Lookup(apmPathKey)),
viper.BindPFlag(pluginPathKey, rootCmd.PersistentFlags().Lookup(pluginPathKey)),
viper.BindPFlag(credentialsFileKey, rootCmd.PersistentFlags().Lookup(credentialsFileKey)),
viper.BindPFlag(adminAPIEndpointKey, rootCmd.PersistentFlags().Lookup(adminAPIEndpointKey)),
)
if errs.Errored() {
return nil, errs.Err
}
rootCmd.AddCommand(
install(fs),
uninstall(fs),
update(fs),
upgrade(fs),
listRepositories(fs),
joinSubnet(fs),
addRepository(fs),
removeRepository(fs),
)
return rootCmd, nil
}
// initializes config from file, if available.
func initializeConfig() error {
if viper.IsSet(configFileKey) {
cfgFile := os.ExpandEnv(viper.GetString(configFileKey))
viper.SetConfigFile(cfgFile)
return viper.ReadInConfig()
}
return nil
}
// If we need to use custom git credentials (say for private repos).
// the zero value for credentials is safe to use.
func initCredentials() (http.BasicAuth, error) {
result := http.BasicAuth{}
if viper.IsSet(credentialsFileKey) {
credentials := &config.Credential{}
bytes, err := os.ReadFile(viper.GetString(credentialsFileKey))
if err != nil {
return result, err
}
if err := yaml.Unmarshal(bytes, credentials); err != nil {
return result, err
}
result.Username = credentials.Username
result.Password = credentials.Password
}
return result, nil
}
func initAPM(fs afero.Fs) (*apm.APM, error) {
credentials, err := initCredentials()
if err != nil {
return nil, err
}
return apm.New(apm.Config{
Directory: viper.GetString(apmPathKey),
Auth: credentials,
AdminAPIEndpoint: viper.GetString(adminAPIEndpointKey),
PluginDir: viper.GetString(pluginPathKey),
Fs: fs,
})
}