openfeature-flagd-provider 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +4 -0
- data/.rubocop.yml +10 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +30 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +92 -0
- data/README.md +83 -0
- data/Rakefile +8 -0
- data/bin/console +15 -0
- data/bin/setup +8 -0
- data/docker/docker-compose.yml +10 -0
- data/docker/flags.json +92 -0
- data/lib/openfeature/flagd/provider/client.rb +142 -0
- data/lib/openfeature/flagd/provider/configuration.rb +42 -0
- data/lib/openfeature/flagd/provider/flagd/evaluation/v1/evaluation_pb.rb +61 -0
- data/lib/openfeature/flagd/provider/flagd/evaluation/v1/evaluation_services_pb.rb +44 -0
- data/lib/openfeature/flagd/provider/flagd/sync/v1/sync_pb.rb +52 -0
- data/lib/openfeature/flagd/provider/flagd/sync/v1/sync_services_pb.rb +39 -0
- data/lib/openfeature/flagd/provider/version.rb +7 -0
- data/lib/openfeature/flagd/provider.rb +83 -0
- data/openfeature-flagd-provider.gemspec +39 -0
- metadata +154 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: '080ce76815c057f001cd65068841a1d73287a0f31a68e45e078b09846ebaf926'
|
4
|
+
data.tar.gz: 1bbde9f180b72331cfb50541e3d1572c3ed2092ca76f9093969d0bb2329acdc2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 11ecdbebda3241daf7ed79a117ccbf0f90f6e13d8197aebca07f91cf949c4afc26b434b5ebf2a3d36037d4be543580c17250e0584c7ed7efae9e2581a90281a1
|
7
|
+
data.tar.gz: fb31f4675243aea5d23deef97270336ec53a9f7a9c2d8ca717f4f18c8de8f11ee23c71ef9cd30ebab06c4b2bf6349b0a8568a900393c65f491c2b0a49a02aa82
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
3.1.4
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## [0.1.0](https://github.com/open-feature/ruby-sdk-contrib/compare/openfeature-flagd-provider-v0.0.1...openfeature-flagd-provider/v0.1.0) (2024-05-16)
|
4
|
+
|
5
|
+
|
6
|
+
### ⚠ BREAKING CHANGES
|
7
|
+
|
8
|
+
* update flagd name and grpc schema ([#30](https://github.com/open-feature/ruby-sdk-contrib/issues/30))
|
9
|
+
|
10
|
+
### ✨ New Features
|
11
|
+
|
12
|
+
* Add flagd provider ([#2](https://github.com/open-feature/ruby-sdk-contrib/issues/2)) ([98b695b](https://github.com/open-feature/ruby-sdk-contrib/commit/98b695b05eb1525cb796479be8b36c2751297b98))
|
13
|
+
* Add support for unix socket path and secure connection ([#8](https://github.com/open-feature/ruby-sdk-contrib/issues/8)) ([88436c7](https://github.com/open-feature/ruby-sdk-contrib/commit/88436c7175373552bc7cad236297028bb655e12d))
|
14
|
+
* Flagd provider uses structs from sdk ([#24](https://github.com/open-feature/ruby-sdk-contrib/issues/24)) ([d437e7f](https://github.com/open-feature/ruby-sdk-contrib/commit/d437e7f72f3790d6c82ce1d006efdd528da7402e))
|
15
|
+
* integrate flagd provider with OpenFeature SDK ([#18](https://github.com/open-feature/ruby-sdk-contrib/issues/18)) ([80d6d02](https://github.com/open-feature/ruby-sdk-contrib/commit/80d6d028fbe762fae243d687bba7f9642bb2c116))
|
16
|
+
* Return default value on error ([#25](https://github.com/open-feature/ruby-sdk-contrib/issues/25)) ([f365c6d](https://github.com/open-feature/ruby-sdk-contrib/commit/f365c6db6ab8465c39d55764c7715f81d6d7f922))
|
17
|
+
* update flagd name and grpc schema ([#30](https://github.com/open-feature/ruby-sdk-contrib/issues/30)) ([ddd438a](https://github.com/open-feature/ruby-sdk-contrib/commit/ddd438abc3c7b6d586c36ea94060c75448e99f27))
|
18
|
+
|
19
|
+
|
20
|
+
### 🧹 Chore
|
21
|
+
|
22
|
+
* Format with standard ([#20](https://github.com/open-feature/ruby-sdk-contrib/issues/20)) ([bf25043](https://github.com/open-feature/ruby-sdk-contrib/commit/bf25043f87bdd9cd2bc8527fead8f4a0c3b95eff))
|
23
|
+
* Make things work ([#13](https://github.com/open-feature/ruby-sdk-contrib/issues/13)) ([5968037](https://github.com/open-feature/ruby-sdk-contrib/commit/5968037b7290f7f84ca96e621bf136f7c7a42e8a))
|
24
|
+
* update link to use new doc domain ([#12](https://github.com/open-feature/ruby-sdk-contrib/issues/12)) ([9baff65](https://github.com/open-feature/ruby-sdk-contrib/commit/9baff65051522705606e336ba1fe614115907418))
|
25
|
+
* upgrade grpc client ([#16](https://github.com/open-feature/ruby-sdk-contrib/issues/16)) ([23ed78a](https://github.com/open-feature/ruby-sdk-contrib/commit/23ed78a830c81030e1fb40d0aef04ea5458d2d6d))
|
26
|
+
|
27
|
+
|
28
|
+
### 🔄 Refactoring
|
29
|
+
|
30
|
+
* OpenFeature::FlagD::Provider::Configuration ([#14](https://github.com/open-feature/ruby-sdk-contrib/issues/14)) ([3686eb5](https://github.com/open-feature/ruby-sdk-contrib/commit/3686eb5c31ec0e6af97bc74ff58ffb815b78e114))
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
openfeature-flagd-provider (0.1.0)
|
5
|
+
grpc (~> 1.50)
|
6
|
+
openfeature-sdk (~> 0.3)
|
7
|
+
|
8
|
+
GEM
|
9
|
+
remote: https://rubygems.org/
|
10
|
+
specs:
|
11
|
+
ast (2.4.2)
|
12
|
+
diff-lcs (1.5.1)
|
13
|
+
google-protobuf (3.25.3-arm64-darwin)
|
14
|
+
google-protobuf (3.25.3-x86_64-linux)
|
15
|
+
googleapis-common-protos-types (1.14.0)
|
16
|
+
google-protobuf (~> 3.18)
|
17
|
+
grpc (1.62.0-arm64-darwin)
|
18
|
+
google-protobuf (~> 3.25)
|
19
|
+
googleapis-common-protos-types (~> 1.0)
|
20
|
+
grpc (1.62.0-x86_64-linux)
|
21
|
+
google-protobuf (~> 3.25)
|
22
|
+
googleapis-common-protos-types (~> 1.0)
|
23
|
+
json (2.7.2)
|
24
|
+
language_server-protocol (3.17.0.3)
|
25
|
+
lint_roller (1.1.0)
|
26
|
+
openfeature-sdk (0.3.1)
|
27
|
+
parallel (1.24.0)
|
28
|
+
parser (3.3.0.5)
|
29
|
+
ast (~> 2.4.1)
|
30
|
+
racc
|
31
|
+
racc (1.7.3)
|
32
|
+
rainbow (3.1.1)
|
33
|
+
rake (13.2.1)
|
34
|
+
regexp_parser (2.9.0)
|
35
|
+
rexml (3.2.6)
|
36
|
+
rspec (3.12.0)
|
37
|
+
rspec-core (~> 3.12.0)
|
38
|
+
rspec-expectations (~> 3.12.0)
|
39
|
+
rspec-mocks (~> 3.12.0)
|
40
|
+
rspec-core (3.12.3)
|
41
|
+
rspec-support (~> 3.12.0)
|
42
|
+
rspec-expectations (3.12.4)
|
43
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
+
rspec-support (~> 3.12.0)
|
45
|
+
rspec-mocks (3.12.7)
|
46
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
47
|
+
rspec-support (~> 3.12.0)
|
48
|
+
rspec-support (3.12.2)
|
49
|
+
rubocop (1.62.1)
|
50
|
+
json (~> 2.3)
|
51
|
+
language_server-protocol (>= 3.17.0)
|
52
|
+
parallel (~> 1.10)
|
53
|
+
parser (>= 3.3.0.2)
|
54
|
+
rainbow (>= 2.2.2, < 4.0)
|
55
|
+
regexp_parser (>= 1.8, < 3.0)
|
56
|
+
rexml (>= 3.2.5, < 4.0)
|
57
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
58
|
+
ruby-progressbar (~> 1.7)
|
59
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
60
|
+
rubocop-ast (1.31.2)
|
61
|
+
parser (>= 3.3.0.4)
|
62
|
+
rubocop-performance (1.20.2)
|
63
|
+
rubocop (>= 1.48.1, < 2.0)
|
64
|
+
rubocop-ast (>= 1.30.0, < 2.0)
|
65
|
+
ruby-progressbar (1.13.0)
|
66
|
+
standard (1.35.1)
|
67
|
+
language_server-protocol (~> 3.17.0.2)
|
68
|
+
lint_roller (~> 1.0)
|
69
|
+
rubocop (~> 1.62.0)
|
70
|
+
standard-custom (~> 1.0.0)
|
71
|
+
standard-performance (~> 1.3)
|
72
|
+
standard-custom (1.0.2)
|
73
|
+
lint_roller (~> 1.0)
|
74
|
+
rubocop (~> 1.50)
|
75
|
+
standard-performance (1.3.1)
|
76
|
+
lint_roller (~> 1.1)
|
77
|
+
rubocop-performance (~> 1.20.2)
|
78
|
+
unicode-display_width (2.5.0)
|
79
|
+
|
80
|
+
PLATFORMS
|
81
|
+
arm64-darwin-21
|
82
|
+
x86_64-linux
|
83
|
+
|
84
|
+
DEPENDENCIES
|
85
|
+
openfeature-flagd-provider!
|
86
|
+
rake (~> 13.0)
|
87
|
+
rspec (~> 3.12.0)
|
88
|
+
rubocop
|
89
|
+
standard
|
90
|
+
|
91
|
+
BUNDLED WITH
|
92
|
+
2.3.25
|
data/README.md
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# OpenFeature flagd Provider for Ruby
|
2
|
+
|
3
|
+
This is the Ruby [provider](https://openfeature.dev/docs/specification/sections/providers) implementation of the [flagd](https://flagd.dev/)
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'openfeature-flagd-provider'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
```sh
|
16
|
+
bundle install
|
17
|
+
```
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
```sh
|
22
|
+
gem install openfeature-flagd-provider
|
23
|
+
```
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
The `OpenFeature::Flagd` supports multiple configuration options that dictate how the SDK communicates with flagd.
|
28
|
+
Options can be defined in the constructor or as environment variables, with constructor options having the highest precedence.
|
29
|
+
|
30
|
+
### Available options
|
31
|
+
|
32
|
+
| Option name | Environment variable name | Type | Default |
|
33
|
+
| ----------- | ------------------------- | ------- | --------- |
|
34
|
+
| host | FLAGD_HOST | string | localhost |
|
35
|
+
| port | FLAGD_PORT | number | 8013 |
|
36
|
+
| tls | FLAGD_TLS | boolean | false |
|
37
|
+
| unix_socket_path | FLAGD_SOCKET_PATH | string | nil |
|
38
|
+
| root_cert_path | FLAGD_SERVER_CERT_PATH | string | nil |
|
39
|
+
|
40
|
+
### Example using TCP
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
OpenFeature::SDK.configure do |config|
|
44
|
+
# your provider of choice
|
45
|
+
config.provider = OpenFeature::Flagd::Provider.configure do |provider_config|
|
46
|
+
provider_config.host = "localhost"
|
47
|
+
provider_config.port = 8013
|
48
|
+
provider_config.tls = false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
### Example using a Unix socket
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
OpenFeature::SDK.configure do |config|
|
57
|
+
# your provider of choice
|
58
|
+
config.provider = OpenFeature::Flagd::Provider.configure do |provider_config|
|
59
|
+
provider_config.unix_socket_path = "tmp/flagd.sock"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
|
65
|
+
### Example using a secure connection
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
OpenFeature::SDK.configure do |config|
|
69
|
+
# your provider of choice
|
70
|
+
config.provider = OpenFeature::Flagd::Provider.configure do |provider_config|
|
71
|
+
provider_config.host = "localhost"
|
72
|
+
provider_config.port = 8013
|
73
|
+
provider_config.tls = true
|
74
|
+
provider_config.root_cert_path = './ca.pem'
|
75
|
+
end
|
76
|
+
end
|
77
|
+
```
|
78
|
+
|
79
|
+
If no environment variables are set the [default configuration](./lib/openfeature/flagd/provider/configuration.rb) is set
|
80
|
+
|
81
|
+
## Contributing
|
82
|
+
|
83
|
+
https://github.com/open-feature/ruby-sdk-contrib
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require "bundler/setup"
|
5
|
+
require "openfeature/flagd/provider"
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require "irb"
|
15
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/docker/flags.json
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
{
|
2
|
+
"$schema": "https://flagd.dev/schema/v0/flags.json",
|
3
|
+
"flags": {
|
4
|
+
"boolean-flag": {
|
5
|
+
"state": "ENABLED",
|
6
|
+
"variants": {
|
7
|
+
"on": true,
|
8
|
+
"off": false
|
9
|
+
},
|
10
|
+
"defaultVariant": "off"
|
11
|
+
},
|
12
|
+
"integer-flag": {
|
13
|
+
"state": "ENABLED",
|
14
|
+
"variants": {
|
15
|
+
"fourty-two": 42
|
16
|
+
},
|
17
|
+
"defaultVariant": "fourty-two"
|
18
|
+
},
|
19
|
+
"float-flag": {
|
20
|
+
"state": "ENABLED",
|
21
|
+
"variants": {
|
22
|
+
"four-point-two": 4.2
|
23
|
+
},
|
24
|
+
"defaultVariant": "four-point-two"
|
25
|
+
},
|
26
|
+
"string-flag": {
|
27
|
+
"state": "ENABLED",
|
28
|
+
"variants": {
|
29
|
+
"lilili": "lalala"
|
30
|
+
},
|
31
|
+
"defaultVariant": "lilili"
|
32
|
+
},
|
33
|
+
"object-flag": {
|
34
|
+
"state": "ENABLED",
|
35
|
+
"variants": {
|
36
|
+
"real-object": { "real": "value" }
|
37
|
+
},
|
38
|
+
"defaultVariant": "real-object"
|
39
|
+
},
|
40
|
+
"boolean-flag-targeting": {
|
41
|
+
"state": "ENABLED",
|
42
|
+
"variants": {
|
43
|
+
"on": true,
|
44
|
+
"off": false
|
45
|
+
},
|
46
|
+
"defaultVariant": "off",
|
47
|
+
"targeting": {
|
48
|
+
"if": [
|
49
|
+
{
|
50
|
+
"==": [
|
51
|
+
{
|
52
|
+
"var": "be_true"
|
53
|
+
},
|
54
|
+
true
|
55
|
+
]
|
56
|
+
},
|
57
|
+
"on"
|
58
|
+
]
|
59
|
+
}
|
60
|
+
},
|
61
|
+
"color-palette-experiment": {
|
62
|
+
"state": "ENABLED",
|
63
|
+
"defaultVariant": "grey",
|
64
|
+
"variants": {
|
65
|
+
"red": "#b91c1c",
|
66
|
+
"blue": "#0284c7",
|
67
|
+
"green": "#16a34a",
|
68
|
+
"grey": "#4b5563"
|
69
|
+
},
|
70
|
+
"targeting": {
|
71
|
+
"fractional": [
|
72
|
+
[
|
73
|
+
"red",
|
74
|
+
25
|
75
|
+
],
|
76
|
+
[
|
77
|
+
"blue",
|
78
|
+
25
|
79
|
+
],
|
80
|
+
[
|
81
|
+
"green",
|
82
|
+
25
|
83
|
+
],
|
84
|
+
[
|
85
|
+
"grey",
|
86
|
+
25
|
87
|
+
]
|
88
|
+
]
|
89
|
+
}
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
@@ -0,0 +1,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "grpc"
|
4
|
+
require "google/protobuf/well_known_types"
|
5
|
+
|
6
|
+
require_relative "flagd/evaluation/v1/evaluation_services_pb"
|
7
|
+
require_relative "configuration"
|
8
|
+
|
9
|
+
module OpenFeature
|
10
|
+
module Flagd
|
11
|
+
module Provider
|
12
|
+
# Client represents a wrapper for the GRPC stub that allows for resolution of boolean, string, number, and object
|
13
|
+
# values. The implementation follows the details specified in https://openfeature.dev/docs/specification/sections/providers
|
14
|
+
#
|
15
|
+
#
|
16
|
+
# The Client provides the following methods and attributes:
|
17
|
+
#
|
18
|
+
# * <tt>metadata</tt> - Returns the associated provider metadata with the name
|
19
|
+
#
|
20
|
+
# * <tt>fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)</tt>
|
21
|
+
# manner; <tt>client.fetch_boolean(flag_key: 'boolean-flag', default_value: false)</tt>
|
22
|
+
#
|
23
|
+
# * <tt>fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)</tt>
|
24
|
+
# manner; <tt>client.fetch_integer_value(flag_key: 'integer-flag', default_value: 2)</tt>
|
25
|
+
#
|
26
|
+
# * <tt>fetch_float_value(flag_key:, default_value:, evaluation_context: nil)</tt>
|
27
|
+
# manner; <tt>client.fetch_float_value(flag_key: 'float-flag', default_value: 2.0)</tt>
|
28
|
+
#
|
29
|
+
# * <tt>fetch_string_value(flag_key:, default_value:, evaluation_context: nil)</tt>
|
30
|
+
# manner; <tt>client.fetch_string_value(flag_key: 'string-flag', default_value: 'some-default-value')</tt>
|
31
|
+
#
|
32
|
+
# * <tt>fetch_object_value(flag_key:, default_value:, evaluation_context: nil)</tt>
|
33
|
+
# manner; <tt>client.fetch_object_value(flag_key: 'flag', default_value: { default_value: 'value'})</tt>
|
34
|
+
class Client
|
35
|
+
PROVIDER_NAME = "flagd Provider"
|
36
|
+
|
37
|
+
attr_reader :metadata
|
38
|
+
|
39
|
+
def initialize(configuration: nil)
|
40
|
+
@metadata = OpenFeature::SDK::Provider::ProviderMetadata.new(name: PROVIDER_NAME)
|
41
|
+
@grpc_client = grpc_client(configuration)
|
42
|
+
end
|
43
|
+
|
44
|
+
def fetch_boolean_value(flag_key:, default_value:, evaluation_context: nil)
|
45
|
+
request = Grpc::Evaluation::ResolveBooleanRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
|
46
|
+
process_request(default_value) { @grpc_client.resolve_boolean(request) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def fetch_number_value(flag_key:, default_value:, evaluation_context: nil)
|
50
|
+
case default_value
|
51
|
+
when Integer
|
52
|
+
fetch_integer_value(flag_key: flag_key, default_value: default_value, evaluation_context: evaluation_context)
|
53
|
+
when Float
|
54
|
+
fetch_float_value(flag_key: flag_key, default_value: default_value, evaluation_context: evaluation_context)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def fetch_integer_value(flag_key:, default_value:, evaluation_context: nil)
|
59
|
+
request = Grpc::Evaluation::ResolveIntRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
|
60
|
+
process_request(default_value) { @grpc_client.resolve_int(request) }
|
61
|
+
end
|
62
|
+
|
63
|
+
def fetch_float_value(flag_key:, default_value:, evaluation_context: nil)
|
64
|
+
request = Grpc::Evaluation::ResolveFloatRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
|
65
|
+
process_request(default_value) { @grpc_client.resolve_float(request) }
|
66
|
+
end
|
67
|
+
|
68
|
+
def fetch_string_value(flag_key:, default_value:, evaluation_context: nil)
|
69
|
+
request = Grpc::Evaluation::ResolveStringRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
|
70
|
+
process_request(default_value) { @grpc_client.resolve_string(request) }
|
71
|
+
end
|
72
|
+
|
73
|
+
def fetch_object_value(flag_key:, default_value:, evaluation_context: nil)
|
74
|
+
request = Grpc::Evaluation::ResolveObjectRequest.new(flag_key: flag_key, context: prepare_evaluation_context(evaluation_context))
|
75
|
+
process_request(default_value) { @grpc_client.resolve_object(request) }
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def process_request(default_value, &block)
|
81
|
+
response = block.call
|
82
|
+
OpenFeature::SDK::Provider::ResolutionDetails.new(
|
83
|
+
value: response.value,
|
84
|
+
reason: response.reason,
|
85
|
+
variant: response.variant,
|
86
|
+
error_code: nil,
|
87
|
+
error_message: nil,
|
88
|
+
flag_metadata: nil
|
89
|
+
)
|
90
|
+
rescue GRPC::NotFound => e
|
91
|
+
error_response(default_value, "FLAG_NOT_FOUND", e.message)
|
92
|
+
rescue GRPC::InvalidArgument => e
|
93
|
+
error_response(default_value, "TYPE_MISMATCH", e.message)
|
94
|
+
rescue GRPC::Unavailable => e
|
95
|
+
error_response(default_value, "FLAG_NOT_FOUND", e.message)
|
96
|
+
rescue GRPC::DataLoss => e
|
97
|
+
error_response(default_value, "PARSE_ERROR", e.message)
|
98
|
+
rescue => e
|
99
|
+
error_response(default_value, "GENERAL", e.message)
|
100
|
+
end
|
101
|
+
|
102
|
+
def prepare_evaluation_context(evaluation_context)
|
103
|
+
return nil unless evaluation_context
|
104
|
+
|
105
|
+
fields = evaluation_context.fields
|
106
|
+
fields["targetingKey"] = fields.delete(:targeting_key)
|
107
|
+
Google::Protobuf::Struct.from_hash(fields)
|
108
|
+
end
|
109
|
+
|
110
|
+
def error_response(default_value, error_code, error_message)
|
111
|
+
OpenFeature::SDK::Provider::ResolutionDetails.new(
|
112
|
+
value: default_value,
|
113
|
+
reason: "ERROR",
|
114
|
+
variant: nil,
|
115
|
+
error_code: error_code,
|
116
|
+
error_message: error_message,
|
117
|
+
flag_metadata: nil
|
118
|
+
)
|
119
|
+
end
|
120
|
+
|
121
|
+
def grpc_client(configuration)
|
122
|
+
options = :this_channel_is_insecure
|
123
|
+
if configuration.tls
|
124
|
+
options = GRPC::Core::ChannelCredentials.new(
|
125
|
+
configuration.root_cert_path
|
126
|
+
)
|
127
|
+
end
|
128
|
+
|
129
|
+
Grpc::Evaluation::Service::Stub.new(server_address(configuration), options).freeze
|
130
|
+
end
|
131
|
+
|
132
|
+
def server_address(configuration)
|
133
|
+
if configuration.unix_socket_path
|
134
|
+
"unix://#{configuration.unix_socket_path}"
|
135
|
+
else
|
136
|
+
"#{configuration.host}:#{configuration.port}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module OpenFeature
|
4
|
+
module Flagd
|
5
|
+
module Provider
|
6
|
+
# Represents the configuration object for the Flagd provider,
|
7
|
+
# This class is not meant to be interacted with directly but instead through the
|
8
|
+
# <tt>OpenFeature::Flagd::Provider.configure</tt> method
|
9
|
+
class Configuration < Struct.new(:host, :port, :tls, :unix_socket_path, :root_cert_path, keyword_init: true)
|
10
|
+
ENVIRONMENT_CONFIG_NAME = {
|
11
|
+
host: "FLAGD_HOST",
|
12
|
+
port: "FLAGD_PORT",
|
13
|
+
tls: "FLAGD_TLS",
|
14
|
+
unix_socket_path: "FLAGD_SOCKET_PATH",
|
15
|
+
root_cert_path: "FLAGD_SERVER_CERT_PATH"
|
16
|
+
}.freeze
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def default_config
|
20
|
+
new(host: "localhost", port: 8013, tls: false, unix_socket_path: nil, root_cert_path: nil)
|
21
|
+
end
|
22
|
+
|
23
|
+
def environment_variables_config
|
24
|
+
new(
|
25
|
+
host: ENV.fetch(ENVIRONMENT_CONFIG_NAME[:host], nil),
|
26
|
+
port: ENV[ENVIRONMENT_CONFIG_NAME[:port]].nil? ? nil : Integer(ENV[ENVIRONMENT_CONFIG_NAME[:port]]),
|
27
|
+
tls: ENV[ENVIRONMENT_CONFIG_NAME[:tls]].nil? ? nil : ENV.fetch(ENVIRONMENT_CONFIG_NAME[:tls], nil) == "true",
|
28
|
+
unix_socket_path: ENV.fetch(ENVIRONMENT_CONFIG_NAME[:unix_socket_path], nil),
|
29
|
+
root_cert_path: ENV.fetch(ENVIRONMENT_CONFIG_NAME[:root_cert_path], nil)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def merge(other_configuration)
|
35
|
+
return self if other_configuration.nil?
|
36
|
+
|
37
|
+
self.class.new(**to_h.compact.merge(other_configuration.to_h.compact))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
3
|
+
# source: flagd/evaluation/v1/evaluation.proto
|
4
|
+
|
5
|
+
require 'google/protobuf'
|
6
|
+
|
7
|
+
require 'google/protobuf/struct_pb'
|
8
|
+
|
9
|
+
|
10
|
+
descriptor_data = "\n$flagd/evaluation/v1/evaluation.proto\x12\x13\x66lagd.evaluation.v1\x1a\x1cgoogle/protobuf/struct.proto\"F\n\x11ResolveAllRequest\x12\x31\n\x07\x63ontext\x18\x01 \x01(\x0b\x32\x17.google.protobuf.StructR\x07\x63ontext\"\xb6\x01\n\x12ResolveAllResponse\x12H\n\x05\x66lags\x18\x01 \x03(\x0b\x32\x32.flagd.evaluation.v1.ResolveAllResponse.FlagsEntryR\x05\x66lags\x1aV\n\nFlagsEntry\x12\x10\n\x03key\x18\x01 \x01(\tR\x03key\x12\x32\n\x05value\x18\x02 \x01(\x0b\x32\x1c.flagd.evaluation.v1.AnyFlagR\x05value:\x02\x38\x01\"\xed\x01\n\x07\x41nyFlag\x12\x16\n\x06reason\x18\x01 \x01(\tR\x06reason\x12\x18\n\x07variant\x18\x02 \x01(\tR\x07variant\x12\x1f\n\nbool_value\x18\x03 \x01(\x08H\x00R\tboolValue\x12#\n\x0cstring_value\x18\x04 \x01(\tH\x00R\x0bstringValue\x12#\n\x0c\x64ouble_value\x18\x05 \x01(\x01H\x00R\x0b\x64oubleValue\x12<\n\x0cobject_value\x18\x06 \x01(\x0b\x32\x17.google.protobuf.StructH\x00R\x0bobjectValueB\x07\n\x05value\"e\n\x15ResolveBooleanRequest\x12\x19\n\x08\x66lag_key\x18\x01 \x01(\tR\x07\x66lagKey\x12\x31\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x17.google.protobuf.StructR\x07\x63ontext\"\x95\x01\n\x16ResolveBooleanResponse\x12\x14\n\x05value\x18\x01 \x01(\x08R\x05value\x12\x16\n\x06reason\x18\x02 \x01(\tR\x06reason\x12\x18\n\x07variant\x18\x03 \x01(\tR\x07variant\x12\x33\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"d\n\x14ResolveStringRequest\x12\x19\n\x08\x66lag_key\x18\x01 \x01(\tR\x07\x66lagKey\x12\x31\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x17.google.protobuf.StructR\x07\x63ontext\"\x94\x01\n\x15ResolveStringResponse\x12\x14\n\x05value\x18\x01 \x01(\tR\x05value\x12\x16\n\x06reason\x18\x02 \x01(\tR\x06reason\x12\x18\n\x07variant\x18\x03 \x01(\tR\x07variant\x12\x33\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"c\n\x13ResolveFloatRequest\x12\x19\n\x08\x66lag_key\x18\x01 \x01(\tR\x07\x66lagKey\x12\x31\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x17.google.protobuf.StructR\x07\x63ontext\"\x93\x01\n\x14ResolveFloatResponse\x12\x14\n\x05value\x18\x01 \x01(\x01R\x05value\x12\x16\n\x06reason\x18\x02 \x01(\tR\x06reason\x12\x18\n\x07variant\x18\x03 \x01(\tR\x07variant\x12\x33\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"a\n\x11ResolveIntRequest\x12\x19\n\x08\x66lag_key\x18\x01 \x01(\tR\x07\x66lagKey\x12\x31\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x17.google.protobuf.StructR\x07\x63ontext\"\x91\x01\n\x12ResolveIntResponse\x12\x14\n\x05value\x18\x01 \x01(\x03R\x05value\x12\x16\n\x06reason\x18\x02 \x01(\tR\x06reason\x12\x18\n\x07variant\x18\x03 \x01(\tR\x07variant\x12\x33\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"d\n\x14ResolveObjectRequest\x12\x19\n\x08\x66lag_key\x18\x01 \x01(\tR\x07\x66lagKey\x12\x31\n\x07\x63ontext\x18\x02 \x01(\x0b\x32\x17.google.protobuf.StructR\x07\x63ontext\"\xad\x01\n\x15ResolveObjectResponse\x12-\n\x05value\x18\x01 \x01(\x0b\x32\x17.google.protobuf.StructR\x05value\x12\x16\n\x06reason\x18\x02 \x01(\tR\x06reason\x12\x18\n\x07variant\x18\x03 \x01(\tR\x07variant\x12\x33\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadata\"V\n\x13\x45ventStreamResponse\x12\x12\n\x04type\x18\x01 \x01(\tR\x04type\x12+\n\x04\x64\x61ta\x18\x02 \x01(\x0b\x32\x17.google.protobuf.StructR\x04\x64\x61ta\"\x14\n\x12\x45ventStreamRequest2\xd9\x05\n\x07Service\x12_\n\nResolveAll\x12&.flagd.evaluation.v1.ResolveAllRequest\x1a\'.flagd.evaluation.v1.ResolveAllResponse\"\x00\x12k\n\x0eResolveBoolean\x12*.flagd.evaluation.v1.ResolveBooleanRequest\x1a+.flagd.evaluation.v1.ResolveBooleanResponse\"\x00\x12h\n\rResolveString\x12).flagd.evaluation.v1.ResolveStringRequest\x1a*.flagd.evaluation.v1.ResolveStringResponse\"\x00\x12\x65\n\x0cResolveFloat\x12(.flagd.evaluation.v1.ResolveFloatRequest\x1a).flagd.evaluation.v1.ResolveFloatResponse\"\x00\x12_\n\nResolveInt\x12&.flagd.evaluation.v1.ResolveIntRequest\x1a\'.flagd.evaluation.v1.ResolveIntResponse\"\x00\x12h\n\rResolveObject\x12).flagd.evaluation.v1.ResolveObjectRequest\x1a*.flagd.evaluation.v1.ResolveObjectResponse\"\x00\x12\x64\n\x0b\x45ventStream\x12\'.flagd.evaluation.v1.EventStreamRequest\x1a(.flagd.evaluation.v1.EventStreamResponse\"\x00\x30\x01\x42\xc6\x01\n%dev.openfeature.flagd.grpc.evaluationZ\x13\x66lagd/evaluation/v1\xaa\x02!OpenFeature.Flagd.Grpc.Evaluation\xca\x02\x32OpenFeature\\Providers\\Flagd\\Schema\\Grpc\\Evaluation\xea\x02.OpenFeature::Flagd::Provider::Grpc::Evaluationb\x06proto3"
|
11
|
+
|
12
|
+
pool = Google::Protobuf::DescriptorPool.generated_pool
|
13
|
+
|
14
|
+
begin
|
15
|
+
pool.add_serialized_file(descriptor_data)
|
16
|
+
rescue TypeError => e
|
17
|
+
# Compatibility code: will be removed in the next major version.
|
18
|
+
require 'google/protobuf/descriptor_pb'
|
19
|
+
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
|
20
|
+
parsed.clear_dependency
|
21
|
+
serialized = parsed.class.encode(parsed)
|
22
|
+
file = pool.add_serialized_file(serialized)
|
23
|
+
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
|
24
|
+
imports = [
|
25
|
+
["google.protobuf.Struct", "google/protobuf/struct.proto"],
|
26
|
+
]
|
27
|
+
imports.each do |type_name, expected_filename|
|
28
|
+
import_file = pool.lookup(type_name).file_descriptor
|
29
|
+
if import_file.name != expected_filename
|
30
|
+
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
warn "Each proto file must use a consistent fully-qualified name."
|
34
|
+
warn "This will become an error in the next major version."
|
35
|
+
end
|
36
|
+
|
37
|
+
module OpenFeature
|
38
|
+
module Flagd
|
39
|
+
module Provider
|
40
|
+
module Grpc
|
41
|
+
module Evaluation
|
42
|
+
ResolveAllRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveAllRequest").msgclass
|
43
|
+
ResolveAllResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveAllResponse").msgclass
|
44
|
+
AnyFlag = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.AnyFlag").msgclass
|
45
|
+
ResolveBooleanRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveBooleanRequest").msgclass
|
46
|
+
ResolveBooleanResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveBooleanResponse").msgclass
|
47
|
+
ResolveStringRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveStringRequest").msgclass
|
48
|
+
ResolveStringResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveStringResponse").msgclass
|
49
|
+
ResolveFloatRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveFloatRequest").msgclass
|
50
|
+
ResolveFloatResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveFloatResponse").msgclass
|
51
|
+
ResolveIntRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveIntRequest").msgclass
|
52
|
+
ResolveIntResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveIntResponse").msgclass
|
53
|
+
ResolveObjectRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveObjectRequest").msgclass
|
54
|
+
ResolveObjectResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.ResolveObjectResponse").msgclass
|
55
|
+
EventStreamResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.EventStreamResponse").msgclass
|
56
|
+
EventStreamRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.evaluation.v1.EventStreamRequest").msgclass
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# Source: flagd/evaluation/v1/evaluation.proto for package 'OpenFeature.Flagd.Provider.Grpc.Evaluation'
|
3
|
+
# Original file comments:
|
4
|
+
# *
|
5
|
+
# Flag evaluation API
|
6
|
+
#
|
7
|
+
# This proto forms the basis of a flag-evaluation API.
|
8
|
+
# It supports single and bulk evaluation RPCs, and flags of various types, as well as establishing a stream for getting notifications about changes in a flag definition.
|
9
|
+
# It supports the inclusion of a "context" with each evaluation, which may contain arbitrary attributes relevant to flag evaluation.
|
10
|
+
|
11
|
+
require 'grpc'
|
12
|
+
require_relative 'evaluation_pb'
|
13
|
+
|
14
|
+
module OpenFeature
|
15
|
+
module Flagd
|
16
|
+
module Provider
|
17
|
+
module Grpc
|
18
|
+
module Evaluation
|
19
|
+
module Service
|
20
|
+
# Service defines the exposed rpcs of flagd
|
21
|
+
class Service
|
22
|
+
|
23
|
+
include ::GRPC::GenericService
|
24
|
+
|
25
|
+
self.marshal_class_method = :encode
|
26
|
+
self.unmarshal_class_method = :decode
|
27
|
+
self.service_name = 'flagd.evaluation.v1.Service'
|
28
|
+
|
29
|
+
rpc :ResolveAll, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveAllRequest, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveAllResponse
|
30
|
+
rpc :ResolveBoolean, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveBooleanRequest, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveBooleanResponse
|
31
|
+
rpc :ResolveString, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveStringRequest, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveStringResponse
|
32
|
+
rpc :ResolveFloat, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveFloatRequest, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveFloatResponse
|
33
|
+
rpc :ResolveInt, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveIntRequest, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveIntResponse
|
34
|
+
rpc :ResolveObject, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveObjectRequest, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::ResolveObjectResponse
|
35
|
+
rpc :EventStream, ::OpenFeature::Flagd::Provider::Grpc::Evaluation::EventStreamRequest, stream(::OpenFeature::Flagd::Provider::Grpc::Evaluation::EventStreamResponse)
|
36
|
+
end
|
37
|
+
|
38
|
+
Stub = Service.rpc_stub_class
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
3
|
+
# source: flagd/sync/v1/sync.proto
|
4
|
+
|
5
|
+
require 'google/protobuf'
|
6
|
+
|
7
|
+
require 'google/protobuf/struct_pb'
|
8
|
+
|
9
|
+
|
10
|
+
descriptor_data = "\n\x18\x66lagd/sync/v1/sync.proto\x12\rflagd.sync.v1\x1a\x1cgoogle/protobuf/struct.proto\"O\n\x10SyncFlagsRequest\x12\x1f\n\x0bprovider_id\x18\x01 \x01(\tR\nproviderId\x12\x1a\n\x08selector\x18\x02 \x01(\tR\x08selector\"B\n\x11SyncFlagsResponse\x12-\n\x12\x66lag_configuration\x18\x01 \x01(\tR\x11\x66lagConfiguration\"S\n\x14\x46\x65tchAllFlagsRequest\x12\x1f\n\x0bprovider_id\x18\x01 \x01(\tR\nproviderId\x12\x1a\n\x08selector\x18\x02 \x01(\tR\x08selector\"F\n\x15\x46\x65tchAllFlagsResponse\x12-\n\x12\x66lag_configuration\x18\x01 \x01(\tR\x11\x66lagConfiguration\"\x14\n\x12GetMetadataRequest\"P\n\x13GetMetadataResponse\x12\x33\n\x08metadata\x18\x02 \x01(\x0b\x32\x17.google.protobuf.StructR\x08metadataJ\x04\x08\x01\x10\x02\x32\x9b\x02\n\x0f\x46lagSyncService\x12R\n\tSyncFlags\x12\x1f.flagd.sync.v1.SyncFlagsRequest\x1a .flagd.sync.v1.SyncFlagsResponse\"\x00\x30\x01\x12\\\n\rFetchAllFlags\x12#.flagd.sync.v1.FetchAllFlagsRequest\x1a$.flagd.sync.v1.FetchAllFlagsResponse\"\x00\x12V\n\x0bGetMetadata\x12!.flagd.sync.v1.GetMetadataRequest\x1a\".flagd.sync.v1.GetMetadataResponse\"\x00\x42\xa8\x01\n\x1f\x64\x65v.openfeature.flagd.grpc.syncZ\rflagd/sync/v1\xaa\x02\x1bOpenFeature.Flagd.Grpc.Sync\xca\x02,OpenFeature\\Providers\\Flagd\\Schema\\Grpc\\Sync\xea\x02(OpenFeature::Flagd::Provider::Grpc::Syncb\x06proto3"
|
11
|
+
|
12
|
+
pool = Google::Protobuf::DescriptorPool.generated_pool
|
13
|
+
|
14
|
+
begin
|
15
|
+
pool.add_serialized_file(descriptor_data)
|
16
|
+
rescue TypeError => e
|
17
|
+
# Compatibility code: will be removed in the next major version.
|
18
|
+
require 'google/protobuf/descriptor_pb'
|
19
|
+
parsed = Google::Protobuf::FileDescriptorProto.decode(descriptor_data)
|
20
|
+
parsed.clear_dependency
|
21
|
+
serialized = parsed.class.encode(parsed)
|
22
|
+
file = pool.add_serialized_file(serialized)
|
23
|
+
warn "Warning: Protobuf detected an import path issue while loading generated file #{__FILE__}"
|
24
|
+
imports = [
|
25
|
+
["google.protobuf.Struct", "google/protobuf/struct.proto"],
|
26
|
+
]
|
27
|
+
imports.each do |type_name, expected_filename|
|
28
|
+
import_file = pool.lookup(type_name).file_descriptor
|
29
|
+
if import_file.name != expected_filename
|
30
|
+
warn "- #{file.name} imports #{expected_filename}, but that import was loaded as #{import_file.name}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
warn "Each proto file must use a consistent fully-qualified name."
|
34
|
+
warn "This will become an error in the next major version."
|
35
|
+
end
|
36
|
+
|
37
|
+
module OpenFeature
|
38
|
+
module Flagd
|
39
|
+
module Provider
|
40
|
+
module Grpc
|
41
|
+
module Sync
|
42
|
+
SyncFlagsRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.sync.v1.SyncFlagsRequest").msgclass
|
43
|
+
SyncFlagsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.sync.v1.SyncFlagsResponse").msgclass
|
44
|
+
FetchAllFlagsRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.sync.v1.FetchAllFlagsRequest").msgclass
|
45
|
+
FetchAllFlagsResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.sync.v1.FetchAllFlagsResponse").msgclass
|
46
|
+
GetMetadataRequest = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.sync.v1.GetMetadataRequest").msgclass
|
47
|
+
GetMetadataResponse = ::Google::Protobuf::DescriptorPool.generated_pool.lookup("flagd.sync.v1.GetMetadataResponse").msgclass
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Generated by the protocol buffer compiler. DO NOT EDIT!
|
2
|
+
# Source: flagd/sync/v1/sync.proto for package 'OpenFeature.Flagd.Provider.Grpc.Sync'
|
3
|
+
# Original file comments:
|
4
|
+
# *
|
5
|
+
# Flag definition sync API
|
6
|
+
#
|
7
|
+
# This proto defines a simple API to synchronize a feature flag definition.
|
8
|
+
# It supports establishing a stream for getting notifications about changes in a flag definition.
|
9
|
+
|
10
|
+
require 'grpc'
|
11
|
+
require 'flagd/sync/v1/sync_pb'
|
12
|
+
|
13
|
+
module OpenFeature
|
14
|
+
module Flagd
|
15
|
+
module Provider
|
16
|
+
module Grpc
|
17
|
+
module Sync
|
18
|
+
module FlagSyncService
|
19
|
+
# FlagService implements a server streaming to provide realtime flag configurations
|
20
|
+
class Service
|
21
|
+
|
22
|
+
include ::GRPC::GenericService
|
23
|
+
|
24
|
+
self.marshal_class_method = :encode
|
25
|
+
self.unmarshal_class_method = :decode
|
26
|
+
self.service_name = 'flagd.sync.v1.FlagSyncService'
|
27
|
+
|
28
|
+
rpc :SyncFlags, ::OpenFeature::Flagd::Provider::Grpc::Sync::SyncFlagsRequest, stream(::OpenFeature::Flagd::Provider::Grpc::Sync::SyncFlagsResponse)
|
29
|
+
rpc :FetchAllFlags, ::OpenFeature::Flagd::Provider::Grpc::Sync::FetchAllFlagsRequest, ::OpenFeature::Flagd::Provider::Grpc::Sync::FetchAllFlagsResponse
|
30
|
+
rpc :GetMetadata, ::OpenFeature::Flagd::Provider::Grpc::Sync::GetMetadataRequest, ::OpenFeature::Flagd::Provider::Grpc::Sync::GetMetadataResponse
|
31
|
+
end
|
32
|
+
|
33
|
+
Stub = Service.rpc_stub_class
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "grpc"
|
4
|
+
|
5
|
+
require_relative "provider/configuration"
|
6
|
+
require_relative "provider/client"
|
7
|
+
require_relative "provider/version"
|
8
|
+
|
9
|
+
module OpenFeature
|
10
|
+
module Flagd
|
11
|
+
# Provider represents the entry point for interacting with the Flagd provider
|
12
|
+
# values. The implementation follows the details specified in https://openfeature.dev/docs/specification/sections/providers
|
13
|
+
#
|
14
|
+
# Provider contains functionality to configure the GRPC connection via
|
15
|
+
# flagd_client = OpenFeature::Flagd::Provider.get_client
|
16
|
+
# flagd_client.configure do |config|
|
17
|
+
# config.host = 'localhost'
|
18
|
+
# config.port = 8379
|
19
|
+
# config.tls = false
|
20
|
+
# end
|
21
|
+
# The Provider provides the following methods and attributes:
|
22
|
+
#
|
23
|
+
# * <tt>metadata</tt> - Returns the associated provider metadata with the name
|
24
|
+
#
|
25
|
+
# * <tt>resolve_boolean_value(flag_key:, default_value:, context: nil)</tt>
|
26
|
+
# manner; <tt>client.resolve_boolean(flag_key: 'boolean-flag', default_value: false)</tt>
|
27
|
+
#
|
28
|
+
# * <tt>resolve_integer_value(flag_key:, default_value:, context: nil)</tt>
|
29
|
+
# manner; <tt>client.resolve_integer_value(flag_key: 'integer-flag', default_value: 2)</tt>
|
30
|
+
#
|
31
|
+
# * <tt>resolve_float_value(flag_key:, default_value:, context: nil)</tt>
|
32
|
+
# manner; <tt>client.resolve_float_value(flag_key: 'float-flag', default_value: 2.0)</tt>
|
33
|
+
#
|
34
|
+
# * <tt>resolve_string_value(flag_key:, default_value:, context: nil)</tt>
|
35
|
+
# manner; <tt>client.resolve_string_value(flag_key: 'string-flag', default_value: 'some-default-value')</tt>
|
36
|
+
#
|
37
|
+
# * <tt>resolve_object_value(flag_key:, default_value:, context: nil)</tt>
|
38
|
+
# manner; <tt>client.resolve_object_value(flag_key: 'object-flag', default_value: { default_value: 'value'})</tt>
|
39
|
+
module Provider
|
40
|
+
class << self
|
41
|
+
def build_client
|
42
|
+
ConfiguredClient.new
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class ConfiguredClient
|
47
|
+
def method_missing(method_name, ...)
|
48
|
+
if client.respond_to?(method_name)
|
49
|
+
client.send(method_name, ...)
|
50
|
+
else
|
51
|
+
super
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def respond_to_missing?(method_name, include_private = false)
|
56
|
+
client.respond_to?(method_name, include_private) || super
|
57
|
+
end
|
58
|
+
|
59
|
+
def configuration
|
60
|
+
@configuration ||= Configuration.default_config
|
61
|
+
.merge(Configuration.environment_variables_config)
|
62
|
+
.merge(explicit_configuration)
|
63
|
+
end
|
64
|
+
|
65
|
+
def configure(&block)
|
66
|
+
return unless block
|
67
|
+
|
68
|
+
block.call(explicit_configuration)
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
def explicit_configuration
|
74
|
+
@explicit_configuration ||= Configuration.new
|
75
|
+
end
|
76
|
+
|
77
|
+
def client
|
78
|
+
@client ||= Client.new(configuration: configuration)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/openfeature/flagd/provider/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "openfeature-flagd-provider"
|
7
|
+
spec.version = OpenFeature::Flagd::VERSION
|
8
|
+
spec.authors = ["OpenFeature Authors"]
|
9
|
+
spec.email = ["cncf-openfeature-contributors@lists.cncf.io"]
|
10
|
+
|
11
|
+
spec.summary = "The flagd provider for the OpenFeature Ruby SDK"
|
12
|
+
spec.description = "The flagd provider for the OpenFeature Ruby SDK"
|
13
|
+
spec.homepage = "https://github.com/open-feature/ruby-sdk-contrib/providers/openfeature-flagd-provider"
|
14
|
+
spec.license = "Apache-2.0"
|
15
|
+
spec.required_ruby_version = ">= 3.1"
|
16
|
+
|
17
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
18
|
+
spec.metadata["source_code_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/providers/openfeature-flagd-provider"
|
19
|
+
spec.metadata["changelog_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/blob/main/providers/openfeature-flagd-provider/CHANGELOG.md"
|
20
|
+
spec.metadata["bug_tracker_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/issues"
|
21
|
+
spec.metadata["documentation_uri"] = "https://github.com/open-feature/ruby-sdk-contrib/README.md"
|
22
|
+
|
23
|
+
# Specify which files should be added to the gem when it is released.
|
24
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
25
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
26
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
27
|
+
end
|
28
|
+
spec.bindir = "exe"
|
29
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
|
+
spec.require_paths = ["lib"]
|
31
|
+
|
32
|
+
spec.add_runtime_dependency "grpc", "~> 1.50"
|
33
|
+
spec.add_runtime_dependency "openfeature-sdk", "~> 0.3"
|
34
|
+
|
35
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
36
|
+
spec.add_development_dependency "rspec", "~> 3.12.0"
|
37
|
+
spec.add_development_dependency "standard"
|
38
|
+
spec.add_development_dependency "rubocop"
|
39
|
+
end
|
metadata
ADDED
@@ -0,0 +1,154 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: openfeature-flagd-provider
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- OpenFeature Authors
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-05-16 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: grpc
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.50'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.50'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: openfeature-sdk
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.3'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '13.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '13.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.12.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.12.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: standard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: The flagd provider for the OpenFeature Ruby SDK
|
98
|
+
email:
|
99
|
+
- cncf-openfeature-contributors@lists.cncf.io
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".rubocop.yml"
|
107
|
+
- ".ruby-version"
|
108
|
+
- CHANGELOG.md
|
109
|
+
- Gemfile
|
110
|
+
- Gemfile.lock
|
111
|
+
- README.md
|
112
|
+
- Rakefile
|
113
|
+
- bin/console
|
114
|
+
- bin/setup
|
115
|
+
- docker/docker-compose.yml
|
116
|
+
- docker/flags.json
|
117
|
+
- lib/openfeature/flagd/provider.rb
|
118
|
+
- lib/openfeature/flagd/provider/client.rb
|
119
|
+
- lib/openfeature/flagd/provider/configuration.rb
|
120
|
+
- lib/openfeature/flagd/provider/flagd/evaluation/v1/evaluation_pb.rb
|
121
|
+
- lib/openfeature/flagd/provider/flagd/evaluation/v1/evaluation_services_pb.rb
|
122
|
+
- lib/openfeature/flagd/provider/flagd/sync/v1/sync_pb.rb
|
123
|
+
- lib/openfeature/flagd/provider/flagd/sync/v1/sync_services_pb.rb
|
124
|
+
- lib/openfeature/flagd/provider/version.rb
|
125
|
+
- openfeature-flagd-provider.gemspec
|
126
|
+
homepage: https://github.com/open-feature/ruby-sdk-contrib/providers/openfeature-flagd-provider
|
127
|
+
licenses:
|
128
|
+
- Apache-2.0
|
129
|
+
metadata:
|
130
|
+
homepage_uri: https://github.com/open-feature/ruby-sdk-contrib/providers/openfeature-flagd-provider
|
131
|
+
source_code_uri: https://github.com/open-feature/ruby-sdk-contrib/providers/openfeature-flagd-provider
|
132
|
+
changelog_uri: https://github.com/open-feature/ruby-sdk-contrib/blob/main/providers/openfeature-flagd-provider/CHANGELOG.md
|
133
|
+
bug_tracker_uri: https://github.com/open-feature/ruby-sdk-contrib/issues
|
134
|
+
documentation_uri: https://github.com/open-feature/ruby-sdk-contrib/README.md
|
135
|
+
post_install_message:
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - ">="
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '3.1'
|
144
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
145
|
+
requirements:
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
149
|
+
requirements: []
|
150
|
+
rubygems_version: 3.5.9
|
151
|
+
signing_key:
|
152
|
+
specification_version: 4
|
153
|
+
summary: The flagd provider for the OpenFeature Ruby SDK
|
154
|
+
test_files: []
|