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  }