diff options
author | Zeger-Jan van de Weg <git@zjvandeweg.nl> | 2018-05-02 22:41:47 +0300 |
---|---|---|
committer | Zeger-Jan van de Weg <git@zjvandeweg.nl> | 2018-05-03 17:53:23 +0300 |
commit | a5736b72d58b4d4fa8f777bccc24e744e10f369b (patch) | |
tree | a6c7c2499a44fc2b0d5282497f3ee93234b6353c | |
parent | 764b039cb604794b15facc5c4a59ecd8dc590483 (diff) |
Introduce small feature flag package
Feature flags on the Gitaly server weren't possible before and it was
suggested in https://gitlab.com/gitlab-org/gitaly/issues/1170 that
Gitaly could do this through gRPC metadata.
This gives control on wether of not to execute new code paths to Rails,
where the server needs to set a header in the form of
`gitaly-feature-<flag_name>` to "true".
-rw-r--r-- | CHANGELOG.md | 5 | ||||
-rw-r--r-- | internal/featureflag/grpc_header.go | 34 | ||||
-rw-r--r-- | internal/featureflag/grpc_header_test.go | 31 |
3 files changed, 70 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 589720c3f..4a1a75bad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Gitaly changelog +UNRELEASED + +- Introduce feature flag package based on gRPC metadata + https://gitlab.com/gitlab-org/gitaly/merge_requests/704 + v0.98.0 - Server implementation for repository raw_changes diff --git a/internal/featureflag/grpc_header.go b/internal/featureflag/grpc_header.go new file mode 100644 index 000000000..8d63fb41f --- /dev/null +++ b/internal/featureflag/grpc_header.go @@ -0,0 +1,34 @@ +package featureflag + +import ( + "fmt" + + "golang.org/x/net/context" + "google.golang.org/grpc/metadata" +) + +// IsEnabled checks if the feature flag is enabled for the passed context. +// Only return true if the metadata for the feature flag is set to "true" +func IsEnabled(ctx context.Context, flag string) bool { + if flag == "" { + return false + } + + md, ok := metadata.FromIncomingContext(ctx) + if !ok { + return false + } + + headerKey := fmt.Sprintf("gitaly-feature-%s", flag) + val, ok := md[headerKey] + if !ok { + return false + } + + return len(val) > 0 && val[0] == "true" +} + +// IsDisabled is the inverse operation of IsEnabled +func IsDisabled(ctx context.Context, flag string) bool { + return !IsEnabled(ctx, flag) +} diff --git a/internal/featureflag/grpc_header_test.go b/internal/featureflag/grpc_header_test.go new file mode 100644 index 000000000..76e0925c5 --- /dev/null +++ b/internal/featureflag/grpc_header_test.go @@ -0,0 +1,31 @@ +package featureflag + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "golang.org/x/net/context" + "google.golang.org/grpc/metadata" +) + +func TestGRPCMetadataFeatureFlag(t *testing.T) { + testCases := []struct { + flag string + headers map[string]string + enabled bool + }{ + {"", nil, false}, + {"flag", nil, false}, + {"flag", map[string]string{"flag": "true"}, false}, + {"flag", map[string]string{"gitaly-feature-flag": "TRUE"}, false}, + {"flag", map[string]string{"gitaly-feature-flag": "true"}, true}, + } + + for _, tc := range testCases { + md := metadata.New(tc.headers) + ctx := metadata.NewIncomingContext(context.Background(), md) + + assert.Equal(t, tc.enabled, IsEnabled(ctx, tc.flag)) + assert.NotEqual(t, tc.enabled, IsDisabled(ctx, tc.flag)) + } +} |