func (opts *InstallationOptions) Populate(reader OptionsReader) (*InstallationOptions, error) {
	newOpts := InstallationOptions{}
	for _, opt := range *opts {
		err := reader.Read(&opt)
		if err != nil {
			return opts, err
		}
		newOpts = append(newOpts, opt)
	}
	return &newOpts, nil
}
Populate will try to give values to the needed options
using the given OptionsReader. If none is given, the default is the
InteractiveOptionsReader which will ask in the terminal.
This method only populates what is possible and leaves the rest empty.
TODO: Implement another method to validate that all options have been set.
package kubernetes
import (
	"errors"
	"fmt"
	"strings"
	"github.com/spf13/cobra"
)
const (
	BooleanType = iota
	StringType
	IntType
	ListType
)
type OptionsReader interface {
	Read(*InstallationOption) error
}
type InstallationOptionDynamicDefault func(o *InstallationOption) error
type InstallationOptionType int
type InstallationOption struct {
	Name           string                            
	Value          interface{}                       
	Default        interface{}                       
	DynDefaultFunc InstallationOptionDynamicDefault  
	UserSpecified  bool                              
	Description    string                            
	Type           InstallationOptionType            
	DeploymentID   string                            
}
type InstallationOptions []InstallationOption
func (opts InstallationOptions) AsCobraFlagsFor(cmd *cobra.Command) {
	for _, opt := range opts {
		flagName := strings.ReplaceAll(opt.Name, "_", "-")
		switch opt.Type {
		case BooleanType:
			if opt.Default == nil {
				cmd.Flags().Bool(flagName, false, opt.Description)
			} else {
				cmd.Flags().Bool(flagName, opt.Default.(bool), opt.Description)
			}
		case StringType:
			if opt.Default == nil {
				cmd.Flags().String(flagName, "", opt.Description)
			} else {
				cmd.Flags().String(flagName, opt.Default.(string), opt.Description)
			}
		case ListType:
			if opt.Default == nil {
				cmd.Flags().StringSlice(flagName, []string{}, opt.Description)
			} else {
				cmd.Flags().StringSlice(flagName, opt.Default.([]string), opt.Description)
			}
		case IntType:
			if opt.Default == nil {
				cmd.Flags().Int(flagName, 0, opt.Description)
			} else {
				cmd.Flags().Int(flagName, opt.Default.(int), opt.Description)
			}
		}
	}
	return
}
func (opts InstallationOptions) ToOptMap() map[string]InstallationOption {
	result := map[string]InstallationOption{}
	for _, opt := range opts {
		result[opt.ToOptMapKey()] = opt
	}
	return result
}
func (opt InstallationOption) ToOptMapKey() string {
	return fmt.Sprintf("%s-%s", opt.Name, opt.DeploymentID)
}
func (opt *InstallationOption) DynDefault() error {
	return opt.DynDefaultFunc(opt)
}
func (opt *InstallationOption) SetDefault() error {
	if opt.DynDefaultFunc != nil {
		err := opt.DynDefault()
		if err != nil {
			return err
		}
	} else if opt.Default != nil {
		opt.Value = opt.Default
	}
	return nil
}
func (opts InstallationOptions) Merge(toMerge InstallationOptions) InstallationOptions {
	result := InstallationOptions{}
	optMap := opts.ToOptMap()
	for _, mergeOpt := range toMerge {
		optMap[mergeOpt.ToOptMapKey()] = mergeOpt
	}
	for _, v := range optMap {
		result = append(result, v)
	}
	return result
}
func (opts InstallationOptions) GetOpt(optionName string, deploymentID string) (*InstallationOption, error) {
	if deploymentID != "" {
		for i, option := range opts {
			if option.Name == optionName && option.DeploymentID == deploymentID {
				return &opts[i], nil
			}
		}
	}
	for i, option := range opts {
		if option.Name == optionName && option.DeploymentID == "" {
			return &opts[i], nil
		}
	}
	return nil, errors.New(optionName + " not set")
}
func (opts InstallationOptions) GetString(optionName string, deploymentID string) (string, error) {
	option, err := opts.GetOpt(optionName, deploymentID)
	if err != nil {
		return "", err
	}
	result, ok := option.Value.(string)
	if !ok {
		panic("wrong type assertion")
	}
	return result, nil
}
func (opts InstallationOptions) GetBool(optionName string, deploymentID string) (bool, error) {
	option, err := opts.GetOpt(optionName, deploymentID)
	if err != nil {
		return false, err
	}
	result, ok := option.Value.(bool)
	if !ok {
		panic("wrong type assertion")
	}
	return result, nil
}
func (opts InstallationOptions) GetInt(optionName string, deploymentID string) (int, error) {
	option, err := opts.GetOpt(optionName, deploymentID)
	if err != nil {
		return 0, err
	}
	result, ok := option.Value.(int)
	if !ok {
		panic("wrong type assertion")
	}
	return result, nil
}
func (opts InstallationOptions) ForDeployment(deploymentID string) InstallationOptions {
	result := InstallationOptions{}
	for _, opt := range opts {
		if opt.DeploymentID == deploymentID || opt.DeploymentID == "" {
			result = append(result, opt)
		}
	}
	return result
}