Skip to content

Commit

Permalink
Update feature flags apis (vmware-tanzu#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
mpanchajanya authored and vuil committed Jan 22, 2024
1 parent b4215d6 commit 362fffc
Show file tree
Hide file tree
Showing 8 changed files with 521 additions and 185 deletions.
30 changes: 30 additions & 0 deletions config/clientconfig_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,36 @@ import (
configtypes "github.com/vmware-tanzu/tanzu-plugin-runtime/config/types"
)

// GetClientConfig retrieves the config from the local directory with file lock
func GetClientConfig() (cfg *configtypes.ClientConfig, err error) {
// Retrieve client config node
node, err := getClientConfigNode()
if err != nil {
return nil, err
}

cfg, err = convertNodeToClientConfig(node)
if err != nil {
return nil, err
}

return cfg, nil
}

// GetClientConfigNoLock retrieves the config from the local directory without acquiring the lock
func GetClientConfigNoLock() (cfg *configtypes.ClientConfig, err error) {
node, err := getClientConfigNodeNoLock()
if err != nil {
return nil, err
}

cfg, err = convertNodeToClientConfig(node)
if err != nil {
return nil, err
}
return cfg, nil
}

// getClientConfigNode retrieves the multi config from the local directory with file lock
func getClientConfigNode() (*yaml.Node, error) {
useUnifiedConfig, err := UseUnifiedConfig()
Expand Down
72 changes: 72 additions & 0 deletions config/features.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,24 @@ import (
"strings"

"github.com/pkg/errors"

"github.com/vmware-tanzu/tanzu-plugin-runtime/config/types"

"gopkg.in/yaml.v3"

"github.com/vmware-tanzu/tanzu-plugin-runtime/config/nodeutils"
)

// GetAllFeatureFlags retrieves all feature flags values from config
func GetAllFeatureFlags() (map[string]types.FeatureMap, error) {
// Retrieve client config node
cfg, err := GetClientConfig()
if err != nil {
return nil, err
}
return cfg.GetAllFeatureFlags()
}

// IsFeatureEnabled checks and returns whether specific plugin and key is true
func IsFeatureEnabled(plugin, key string) (bool, error) {
// Retrieve client config node
Expand Down Expand Up @@ -204,3 +217,62 @@ func IsFeatureActivated(feature string) bool {
}
return status
}

// FeatureOptions is a struct that defines the options for feature flag configuration.
type FeatureOptions struct {
SkipIfExists bool // SkipIfExists indicates whether to skip setting the feature flag if it already exists.
}

// Options is a function type that applies configuration options to FeatureOptions.
type Options func(opts *FeatureOptions)

// SkipIfExists returns an Options function that sets the SkipIfExists option to true.
func SkipIfExists() Options {
return func(opts *FeatureOptions) {
opts.SkipIfExists = true // Sets the SkipIfExists field of FeatureOptions to true.
}
}

// ConfigureFeatureFlags sets default feature flags to ClientConfig if they are missing.
// It accepts a map of feature flags and a variadic Options parameter to apply additional settings.
func ConfigureFeatureFlags(defaultFeatureFlags map[string]bool, opts ...Options) error {
options := new(FeatureOptions) // Initialize FeatureOptions.
for _, opt := range opts {
opt(options) // Apply each Options function to the FeatureOptions.
}

cfg, err := GetClientConfig() // Retrieves the current client configuration.
if err != nil {
return errors.Wrap(err, "error while getting client config") // Returns an error if fetching client config fails.
}

return configureFlags(cfg, defaultFeatureFlags, options) // Sets the feature flags based on the provided configuration and options.
}

// configureFlags processes and sets the feature flags based on the provided configuration and options.
// It iterates over each flag in the provided map and sets them using the setFlag function.
func configureFlags(cfg *types.ClientConfig, flags map[string]bool, options *FeatureOptions) error {
for path, activated := range flags {
if err := setFlag(cfg, path, activated, options); err != nil {
return err // Returns an error if setting any feature flag fails.
}
}
return nil
}

// setFlag configures a single feature flag based on the specified path and activation status.
// It extracts the plugin and feature from the path and sets the feature flag accordingly.
func setFlag(cfg *types.ClientConfig, path string, activated bool, options *FeatureOptions) error {
plugin, feature, err := cfg.SplitFeaturePath(path)
if err != nil {
return errors.Wrap(err, "failed to configure feature flags") // Returns an error if splitting the feature path fails.
}

// Checks if the feature flag should be skipped if it already exists.
if options.SkipIfExists && cfg.IsFeatureFlagSet(plugin, feature) {
return nil // Skips setting the flag.
}

// Sets the feature flag with the specified activation status.
return SetFeature(plugin, feature, strconv.FormatBool(activated))
}
Loading

0 comments on commit 362fffc

Please sign in to comment.