github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+incompatible/util/configv3/plugins_config.go (about) 1 package configv3 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "sort" 10 "strings" 11 12 "code.cloudfoundry.org/cli/util" 13 ) 14 15 // PluginsConfig represents the plugin configuration 16 type PluginsConfig struct { 17 Plugins map[string]Plugin `json:"Plugins"` 18 } 19 20 // Plugin represents the plugin as a whole, not be confused with PluginCommand 21 type Plugin struct { 22 Name string 23 Location string `json:"Location"` 24 Version PluginVersion `json:"Version"` 25 Commands []PluginCommand `json:"Commands"` 26 } 27 28 // CalculateSHA1 returns the sha1 value of the plugin executable. If an error 29 // is encountered calculating sha1, N/A is returned 30 func (p Plugin) CalculateSHA1() string { 31 fileSHA, err := util.NewSha1Checksum(p.Location).ComputeFileSha1() 32 33 if err != nil { 34 return "N/A" 35 } 36 37 return fmt.Sprintf("%x", fileSHA) 38 } 39 40 // PluginCommands returns the plugin's commands sorted by command name. 41 func (p Plugin) PluginCommands() []PluginCommand { 42 sort.Slice(p.Commands, func(i, j int) bool { 43 return strings.ToLower(p.Commands[i].Name) < strings.ToLower(p.Commands[j].Name) 44 }) 45 return p.Commands 46 } 47 48 // PluginVersion is the plugin version information 49 type PluginVersion struct { 50 Major int `json:"Major"` 51 Minor int `json:"Minor"` 52 Build int `json:"Build"` 53 } 54 55 // String returns the plugin's version in the format x.y.z. 56 func (v PluginVersion) String() string { 57 if v.Major == 0 && v.Minor == 0 && v.Build == 0 { 58 return "N/A" 59 } 60 return fmt.Sprintf("%d.%d.%d", v.Major, v.Minor, v.Build) 61 } 62 63 // PluginCommand represents an individual command inside a plugin 64 type PluginCommand struct { 65 Name string `json:"Name"` 66 Alias string `json:"Alias"` 67 HelpText string `json:"HelpText"` 68 UsageDetails PluginUsageDetails `json:"UsageDetails"` 69 } 70 71 // CommandName returns the name of the plugin. The name is concatenated with 72 // alias if alias is specified. 73 func (c PluginCommand) CommandName() string { 74 if c.Name != "" && c.Alias != "" { 75 return fmt.Sprintf("%s, %s", c.Name, c.Alias) 76 } 77 return c.Name 78 } 79 80 // PluginUsageDetails contains the usage metadata provided by the plugin 81 type PluginUsageDetails struct { 82 Usage string `json:"Usage"` 83 Options map[string]string `json:"Options"` 84 } 85 86 // AddPlugin adds the specified plugin to PluginsConfig 87 func (config *Config) AddPlugin(plugin Plugin) { 88 config.pluginsConfig.Plugins[plugin.Name] = plugin 89 } 90 91 func (config *Config) CreatePluginHome() error { 92 return os.MkdirAll(config.PluginHome(), 0700) 93 } 94 95 // GetPlugin returns the requested plugin and true if it exists. 96 func (config *Config) GetPlugin(pluginName string) (Plugin, bool) { 97 plugin, exists := config.pluginsConfig.Plugins[pluginName] 98 return plugin, exists 99 } 100 101 // GetPluginCaseInsensitive finds the first matching plugin name case 102 // insensitive and returns true if it exists. 103 func (config *Config) GetPluginCaseInsensitive(pluginName string) (Plugin, bool) { 104 for name, plugin := range config.pluginsConfig.Plugins { 105 if strings.ToLower(name) == strings.ToLower(pluginName) { 106 return plugin, true 107 } 108 } 109 110 return Plugin{}, false 111 } 112 113 // PluginHome returns the plugin configuration directory to: 114 // 1. The $CF_PLUGIN_HOME/.cf/plugins environment variable if set 115 // 2. Defaults to the home directory (outlined in LoadConfig)/.cf/plugins 116 func (config *Config) PluginHome() string { 117 if config.ENV.CFPluginHome != "" { 118 return filepath.Join(config.ENV.CFPluginHome, ".cf", "plugins") 119 } 120 121 return filepath.Join(homeDirectory(), ".cf", "plugins") 122 } 123 124 // Plugins returns installed plugins from the config sorted by name (case-insensitive). 125 func (config *Config) Plugins() []Plugin { 126 plugins := []Plugin{} 127 for _, plugin := range config.pluginsConfig.Plugins { 128 plugins = append(plugins, plugin) 129 } 130 sort.Slice(plugins, func(i, j int) bool { 131 return strings.ToLower(plugins[i].Name) < strings.ToLower(plugins[j].Name) 132 }) 133 return plugins 134 } 135 136 // RemovePlugin removes the specified plugin from PluginsConfig idempotently 137 func (config *Config) RemovePlugin(pluginName string) { 138 delete(config.pluginsConfig.Plugins, pluginName) 139 } 140 141 // WritePluginConfig writes the plugin config to config.json in the plugin home 142 // directory. 143 func (config *Config) WritePluginConfig() error { 144 // Marshal JSON 145 rawConfig, err := json.MarshalIndent(config.pluginsConfig, "", " ") 146 if err != nil { 147 return err 148 } 149 150 pluginFileDir := filepath.Join(config.PluginHome()) 151 err = os.MkdirAll(pluginFileDir, 0700) 152 if err != nil { 153 return err 154 } 155 156 // Write to file 157 return ioutil.WriteFile(filepath.Join(pluginFileDir, "config.json"), rawConfig, 0600) 158 }