File: flags.go

package info (click to toggle)
golang-github-juju-utils 0.0~git20171220.f38c0b0-5
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 1,748 kB
  • sloc: makefile: 20
file content (102 lines) | stat: -rw-r--r-- 3,052 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.

// The featureflag package gives other parts of Juju the ability to easily
// check to see if a feature flag has been defined. Feature flags give the
// Juju developers a way to add new commands or features to Juju but hide
// them from the general user-base while things are still in development.
//
// Feature flags are defined through environment variables, and the value
// is comma separated.
//    # this defines two flags: "special" and "magic"
//    export JUJU_SOME_ENV_VAR=special,magic
//
// The feature flags should be read and identified at program initialisation
// time using an init function.  This function should call the
// `SetFlagsFromEnvironment` or the `SetFlagsFromRegistry` function.
package featureflag

import (
	"fmt"
	"os"
	"strings"
	"sync"

	"github.com/juju/loggo"
	"github.com/juju/utils/set"
)

var (
	logger   = loggo.GetLogger("utils.featureflag")
	flaglock sync.Mutex // seralises access to flags
	flags    = set.NewStrings()
)

// SetFlagsFromEnvironment populates the global set from the environment.
// White space between flags is ignored, and the flags are lower cased. Under
// normal circumstances this method is only ever called from the init
// function.
//
// NOTE: since SetFlagsFromEnvironment should only ever called during the
// program startup (or tests), and it is serialized by the runtime, we don't
// use any mutux when setting the flag set.  Should this change in the future,
// a mutex should be used.
func SetFlagsFromEnvironment(envVarName string) {
	setFlags(os.Getenv(envVarName))
}

// setFlags populates the global set using a string passed to it containing the
// flags.
func setFlags(val string) {
	values := strings.ToLower(val)

	flaglock.Lock()
	defer flaglock.Unlock()
	flags = set.NewStrings()
	for _, flag := range strings.Split(values, ",") {
		if flag = strings.TrimSpace(flag); flag != "" {
			flags.Add(flag)
		}
	}
}

// Enabled is used to determine if a particular feature flag is enabled for
// the process.
func Enabled(flag string) bool {
	flaglock.Lock()
	defer flaglock.Unlock()
	flag = strings.TrimSpace(strings.ToLower(flag))
	if flag == "" {
		// The empty feature is always enabled.
		return true
	}
	return flags.Contains(flag)
}

// All returns all the current feature flags.
func All() []string {
	flaglock.Lock()
	defer flaglock.Unlock()
	return flags.Values()
}

// AsEnvironmentValue returns a single string suitable to be assigned into an
// environment value that will be parsed into the same set of values currently
// set.
func AsEnvironmentValue() string {
	flaglock.Lock()
	defer flaglock.Unlock()
	return strings.Join(flags.SortedValues(), ",")
}

// String provides a nice human readable string for the feature flags that
// are set.
func String() string {
	flaglock.Lock()
	defer flaglock.Unlock()
	var quoted []string
	for _, flag := range flags.SortedValues() {
		quoted = append(quoted, fmt.Sprintf("%q", flag))
	}
	return strings.Join(quoted, ", ")
}