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