Repository: derailed/k9s
File: internal/config/plugin.go (Go)

Code before:
	Override        bool          `yaml:"override"`
	Pipes           []string      `yaml:"pipes"`
	Description     string        `yaml:"description"`
	Command         string        `yaml:"command"`
	Confirm         bool          `yaml:"confirm"`
	Background      bool          `yaml:"background"`
	Dangerous       bool          `yaml:"dangerous"`
	OverwriteOutput bool          `yaml:"overwriteOutput"`
	Inputs          []PluginInput `yaml:"inputs"`
}

func (p Plugin) String() string {
	return fmt.Sprintf("[%s] %s(%s)", p.ShortCut, p.Command, strings.Join(p.Args, " "))
}

// Validate checks the plugin configuration for errors.
func (p *Plugin) Validate() error {
	seen := make(map[string]struct{}, len(p.Inputs))
	for _, input := range p.Inputs {
		if _, ok := seen[input.Name]; ok {
			return fmt.Errorf("duplicate input name %q", input.Name)
		}
		seen[input.Name] = struct{}{}

		// Validate default value for dropdown must be one of the options
		if input.Default != "" && input.Type == InputTypeDropdown {
			if !slices.Contains(input.Options, input.Default) {
				return fmt.Errorf("default value %q for input %q is not a valid option", input.Default, input.Name)
			}
		}

		// Validate default value for bool must be "true" or "false"
		if input.Default != "" && input.Type == InputTypeBool {
			if input.Default != "true" && input.Default != "false" {
				return fmt.Errorf("default value %q for bool input %q must be \"true\" or \"false\"", input.Default, input.Name)
			}
		}

		// Validate default value for number must be a valid number
		if input.Default != "" && input.Type == InputTypeNumber {
			if _, err := strconv.ParseFloat(input.Default, 64); err != nil {
				return fmt.Errorf("default value %q for number input %q is not a valid number", input.Default, input.Name)
			}
		}
	}

	return nil
}

// NewPlugins returns a new plugin.
func NewPlugins() Plugins {

Review comment (refactor):
nit: we could dry this up i.e if input.Default is not set then bail out. Also prefer a switch here since options are mutually exclusive.

Code after:
	Override        bool          `yaml:"override"`
	Pipes           []string      `yaml:"pipes"`
	Description     string        `yaml:"description"`
	Command         string        `yaml:"command"`
	Confirm         bool          `yaml:"confirm"`
	Background      bool          `yaml:"background"`
	Dangerous       bool          `yaml:"dangerous"`
	OverwriteOutput bool          `yaml:"overwriteOutput"`
	Inputs          []PluginInput `yaml:"inputs"`
}

func (p Plugin) String() string {
	return fmt.Sprintf("[%s] %s(%s)", p.ShortCut, p.Command, strings.Join(p.Args, " "))
}

// Validate checks the plugin configuration for errors.
func (p *Plugin) Validate() error {
	seen := make(map[string]struct{}, len(p.Inputs))
	for _, input := range p.Inputs {
		if _, ok := seen[input.Name]; ok {
			return fmt.Errorf("duplicate input name %q", input.Name)
		}
		seen[input.Name] = struct{}{}

		if input.Default == "" {
			continue
		}

		switch input.Type {
		case InputTypeDropdown:
			if !slices.Contains(input.Options, input.Default) {
				return fmt.Errorf("default value %q for input %q is not a valid option", input.Default, input.Name)
			}
		case InputTypeBool:
			if input.Default != "true" && input.Default != "false" {
				return fmt.Errorf("default value %q for bool input %q must be \"true\" or \"false\"", input.Default, input.Name)
			}
		case InputTypeNumber:
			if _, err := strconv.ParseFloat(input.Default, 64); err != nil {
				return fmt.Errorf("default value %q for number input %q is not a valid number", input.Default, input.Name)
			}
		}
	}

	return nil
}

// NewPlugins returns a new plugin.
func NewPlugins() Plugins {
	return Plugins{
		Plugins: make(map[string]Plugin),