envoku 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.ruby-version +1 -0
- data/.simplecov +8 -4
- data/README.md +29 -4
- data/Rakefile +2 -0
- data/circle.yml +2 -2
- data/codecov.yml +13 -0
- data/envoku.gemspec +6 -4
- data/lib/envoku/feature.rb +70 -0
- data/lib/envoku/rails.rb +5 -0
- data/lib/envoku/resource.rb +23 -0
- data/lib/envoku/version.rb +1 -1
- data/lib/envoku.rb +21 -2
- data/lib/tasks/envoku.rake +20 -0
- data/{bin → script}/console +0 -0
- metadata +45 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 12cb3de23b25c163a12dc7320786b5e8aef7e6c0
|
4
|
+
data.tar.gz: ec871654478e09acec6316f18249e274fff24848
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8cbf3e539206de10ccedb8f7b264320435ab131d0241adc5dc6eb6c36c17c0b89b6b29a0b1918920badf0add8c631777f510b1530f49b048603933a876be93c2
|
7
|
+
data.tar.gz: 7f501e221cfc0bd53b87aa77a0b1ba87cc792e1daef744f423fc65626e2b447bae169ee193cc468beb25c8b2801720c1de032d430a44b94a32a4739ac77bcff2
|
data/.gitignore
CHANGED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.3.1
|
data/.simplecov
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
+
require "codeclimate-test-reporter"
|
1
2
|
require 'codecov'
|
2
|
-
|
3
|
-
|
3
|
+
|
4
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
5
|
+
CodeClimate::TestReporter::Formatter,
|
4
6
|
SimpleCov::Formatter::Codecov,
|
5
|
-
|
7
|
+
SimpleCov::Formatter::HTMLFormatter,
|
8
|
+
])
|
6
9
|
SimpleCov.start do
|
7
|
-
add_filter
|
10
|
+
add_filter "spec"
|
11
|
+
add_group "Adapters", "lib/envoku/adapters/"
|
8
12
|
end
|
data/README.md
CHANGED
@@ -1,7 +1,10 @@
|
|
1
1
|
# Envoku
|
2
2
|
|
3
|
-
[](https://badge.fury.io/rb/envoku)
|
4
|
+
[](https://circleci.com/gh/marcqualie/envoku-ruby/tree/master)
|
5
|
+
[](https://codeclimate.com/github/marcqualie/envoku-ruby/coverage)
|
6
|
+
[](https://codeclimate.com/github/marcqualie/envoku-ruby)
|
7
|
+
[](https://codeclimate.com/github/marcqualie/envoku-ruby)
|
5
8
|
|
6
9
|
Configuration storage that can be loaded into your application transparently at boot-time.
|
7
10
|
|
@@ -10,7 +13,7 @@ Configuration storage that can be loaded into your application transparently at
|
|
10
13
|
|
11
14
|
Add this line to your application's Gemfile:
|
12
15
|
|
13
|
-
```ruby
|
16
|
+
``` ruby
|
14
17
|
gem 'envoku'
|
15
18
|
```
|
16
19
|
|
@@ -35,11 +38,33 @@ Envoku automatically pre-loads itself during `before_configuration` phase so no
|
|
35
38
|
|
36
39
|
Run the following code before you need access to the environment variables
|
37
40
|
|
38
|
-
```
|
41
|
+
``` ruby
|
39
42
|
Envoku.load
|
40
43
|
```
|
41
44
|
|
42
45
|
|
46
|
+
## Features
|
47
|
+
|
48
|
+
``` ruby
|
49
|
+
all_features = Envoku::Feature.all
|
50
|
+
feature = Envoku::Feature.new('FEATURE1')
|
51
|
+
feature.enabled? # global for all resources
|
52
|
+
feature.enabled_for?(current_user) # does current_user have this feature enabled
|
53
|
+
feature.enable_for!(current_user) # enable feature for current_user
|
54
|
+
feature.disable_for!(current_user) # disable feature for current_user
|
55
|
+
resource.feature_enabled?('FEATURE1')
|
56
|
+
resource.toggle_feature!('FEATURE1')
|
57
|
+
resource.features_enabled
|
58
|
+
```
|
59
|
+
|
60
|
+
Per-resource features are stored in Redis via the following keys:
|
61
|
+
|
62
|
+
```
|
63
|
+
(SET) envoku:features:[feature]:[class] 123 456 789 # IDs for resource grouped by feature and class
|
64
|
+
(SET) envoku:features:[class]:[id] FEATURE1 FEATURE2 # Features grouped by resource and ID
|
65
|
+
```
|
66
|
+
|
67
|
+
|
43
68
|
## Development
|
44
69
|
|
45
70
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/Rakefile
CHANGED
data/circle.yml
CHANGED
data/codecov.yml
ADDED
data/envoku.gemspec
CHANGED
@@ -19,9 +19,11 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
21
|
spec.add_dependency "dotenv", "~> 2.1"
|
22
|
+
spec.add_dependency "redis", "~> 3.3"
|
22
23
|
|
23
|
-
spec.add_development_dependency "bundler", "~> 1.
|
24
|
-
spec.add_development_dependency "codecov", "~> 0.1.
|
25
|
-
spec.add_development_dependency "
|
26
|
-
spec.add_development_dependency "
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.13"
|
25
|
+
spec.add_development_dependency "codecov", "~> 0.1.5"
|
26
|
+
spec.add_development_dependency "codeclimate-test-reporter", "~> 0.6"
|
27
|
+
spec.add_development_dependency "rake", "~> 11.3"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.5"
|
27
29
|
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Envoku
|
4
|
+
class Feature
|
5
|
+
ENV_NAMESPACE = "ENVOKU_FEATURE_"
|
6
|
+
REDIS_NAMESPACE = "envoku:features:"
|
7
|
+
|
8
|
+
attr_reader :name
|
9
|
+
attr_reader :description
|
10
|
+
|
11
|
+
def self.all
|
12
|
+
keys = ENV.select { |key, value| key.index(ENV_NAMESPACE) == 0 }
|
13
|
+
keys.keys.map do |key|
|
14
|
+
Feature.new(key[(ENV_NAMESPACE.length)..-1])
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(name)
|
19
|
+
@name = name
|
20
|
+
@enabled = false
|
21
|
+
var_string = ENV["#{ENV_NAMESPACE}#{name}"]
|
22
|
+
return nil unless var_string
|
23
|
+
attributes = ::YAML.safe_load(var_string) rescue {}
|
24
|
+
attributes.each do |key, value|
|
25
|
+
instance_variable_set(:"@#{key}", value)
|
26
|
+
end
|
27
|
+
@enabled = !!@enabled
|
28
|
+
end
|
29
|
+
|
30
|
+
def enabled?
|
31
|
+
@enabled
|
32
|
+
end
|
33
|
+
|
34
|
+
def enabled_for?(resource)
|
35
|
+
return true if enabled?
|
36
|
+
Envoku.redis.sismember("#{REDIS_NAMESPACE}#{@name}:#{resource.class.name}", "#{resource.id}")
|
37
|
+
end
|
38
|
+
|
39
|
+
def enable_for!(resource)
|
40
|
+
Envoku.redis.multi do
|
41
|
+
Envoku.redis.sadd("#{REDIS_NAMESPACE}#{@name}:#{resource.class.name}", resource.id.to_s)
|
42
|
+
Envoku.redis.sadd("#{REDIS_NAMESPACE}#{resource.class.name}:#{resource.id}", @name)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def disable_for!(resource)
|
47
|
+
Envoku.redis.multi do
|
48
|
+
Envoku.redis.del("#{REDIS_NAMESPACE}#{@name}:#{resource.class.name}")
|
49
|
+
Envoku.redis.del("#{REDIS_NAMESPACE}#{resource.class.name}:#{resource.id}")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def toggle_for!(resource)
|
54
|
+
enabled_for?(resource) ? disable_for!(resource) : enable_for!(resource)
|
55
|
+
end
|
56
|
+
|
57
|
+
def resources
|
58
|
+
list = []
|
59
|
+
feature_prefix = "#{REDIS_NAMESPACE}#{@name}"
|
60
|
+
klasses = Envoku.redis.keys("#{feature_prefix}:*").map { |klass| klass[(feature_prefix.length + 1)..-1] }
|
61
|
+
klasses.each do |klass|
|
62
|
+
ids = Envoku.redis.smembers("#{feature_prefix}:#{klass}")
|
63
|
+
ids.each do |id|
|
64
|
+
list.push("#{klass}:#{id}")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
list
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
data/lib/envoku/rails.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
module Envoku
|
2
|
+
module Resource
|
3
|
+
def disable_feature!(feature)
|
4
|
+
::Envoku::Feature.new(feature).disable_for!(self)
|
5
|
+
end
|
6
|
+
|
7
|
+
def enable_feature!(feature)
|
8
|
+
::Envoku::Feature.new(feature).enable_for!(self)
|
9
|
+
end
|
10
|
+
|
11
|
+
def feature_enabled?(feature)
|
12
|
+
::Envoku::Feature.new(feature).enabled_for?(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
def features_enabled
|
16
|
+
::Envoku.features_enabled_for(self)
|
17
|
+
end
|
18
|
+
|
19
|
+
def toggle_feature!(feature)
|
20
|
+
::Envoku::Feature.new(feature).toggle_for!(self)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/envoku/version.rb
CHANGED
data/lib/envoku.rb
CHANGED
@@ -1,13 +1,32 @@
|
|
1
|
+
require "redis"
|
2
|
+
|
1
3
|
require "envoku/version"
|
2
4
|
require "envoku/adapters/s3"
|
3
|
-
require "envoku/
|
5
|
+
require "envoku/feature"
|
6
|
+
require "envoku/resource"
|
7
|
+
|
8
|
+
require "envoku/rails" if defined?(Rails)
|
4
9
|
|
5
10
|
module Envoku
|
6
11
|
|
7
12
|
module_function
|
8
13
|
|
9
|
-
def load
|
14
|
+
def load(options = {})
|
10
15
|
instance = Envoku::Adapters::S3.new options
|
11
16
|
instance.load
|
12
17
|
end
|
18
|
+
|
19
|
+
def redis
|
20
|
+
@redis ||= ::Redis.new(
|
21
|
+
url: (ENV['ENVOKU_REDIS_URL'] || ENV['REDIS_URL']),
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def feature_enabled_for?(feature_name, resource)
|
26
|
+
Feature.new(feature_name).enabled_for?(resource)
|
27
|
+
end
|
28
|
+
|
29
|
+
def features_enabled_for(resource)
|
30
|
+
redis.smembers("#{Feature::REDIS_NAMESPACE}#{resource.class.name}:#{resource.id}")
|
31
|
+
end
|
13
32
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'envoku'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
namespace :envoku do
|
5
|
+
|
6
|
+
task :load do
|
7
|
+
Envoku.load
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "Show Envoku Info"
|
11
|
+
task :info => :load do
|
12
|
+
puts "URL: #{ENV['ENVOKU_URL'] ? ENV['ENVOKU_URL'] : "[not set]"}"
|
13
|
+
end
|
14
|
+
|
15
|
+
desc "List Envoku Features"
|
16
|
+
task :features => :load do
|
17
|
+
features = Envoku::Feature.all
|
18
|
+
puts features.to_yaml
|
19
|
+
end
|
20
|
+
end
|
data/{bin → script}/console
RENAMED
File without changes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: envoku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marc Qualie
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: dotenv
|
@@ -24,62 +24,90 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.1'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: redis
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '3.3'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '3.3'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
45
|
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '1.
|
47
|
+
version: '1.13'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
52
|
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '1.
|
54
|
+
version: '1.13'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: codecov
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
44
58
|
requirements:
|
45
59
|
- - "~>"
|
46
60
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1.
|
61
|
+
version: 0.1.5
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 0.1.5
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: codeclimate-test-reporter
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.6'
|
48
76
|
type: :development
|
49
77
|
prerelease: false
|
50
78
|
version_requirements: !ruby/object:Gem::Requirement
|
51
79
|
requirements:
|
52
80
|
- - "~>"
|
53
81
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.
|
82
|
+
version: '0.6'
|
55
83
|
- !ruby/object:Gem::Dependency
|
56
84
|
name: rake
|
57
85
|
requirement: !ruby/object:Gem::Requirement
|
58
86
|
requirements:
|
59
87
|
- - "~>"
|
60
88
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
89
|
+
version: '11.3'
|
62
90
|
type: :development
|
63
91
|
prerelease: false
|
64
92
|
version_requirements: !ruby/object:Gem::Requirement
|
65
93
|
requirements:
|
66
94
|
- - "~>"
|
67
95
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
96
|
+
version: '11.3'
|
69
97
|
- !ruby/object:Gem::Dependency
|
70
98
|
name: rspec
|
71
99
|
requirement: !ruby/object:Gem::Requirement
|
72
100
|
requirements:
|
73
101
|
- - "~>"
|
74
102
|
- !ruby/object:Gem::Version
|
75
|
-
version: '3.
|
103
|
+
version: '3.5'
|
76
104
|
type: :development
|
77
105
|
prerelease: false
|
78
106
|
version_requirements: !ruby/object:Gem::Requirement
|
79
107
|
requirements:
|
80
108
|
- - "~>"
|
81
109
|
- !ruby/object:Gem::Version
|
82
|
-
version: '3.
|
110
|
+
version: '3.5'
|
83
111
|
description:
|
84
112
|
email:
|
85
113
|
- marc@marcqualie.com
|
@@ -89,21 +117,26 @@ extra_rdoc_files: []
|
|
89
117
|
files:
|
90
118
|
- ".gitignore"
|
91
119
|
- ".rspec"
|
120
|
+
- ".ruby-version"
|
92
121
|
- ".simplecov"
|
93
122
|
- ".travis.yml"
|
94
123
|
- Gemfile
|
95
124
|
- LICENSE
|
96
125
|
- README.md
|
97
126
|
- Rakefile
|
98
|
-
- bin/console
|
99
127
|
- bin/setup
|
100
128
|
- circle.yml
|
129
|
+
- codecov.yml
|
101
130
|
- envoku.gemspec
|
102
131
|
- lib/envoku.rb
|
103
132
|
- lib/envoku/adapters.rb
|
104
133
|
- lib/envoku/adapters/s3.rb
|
134
|
+
- lib/envoku/feature.rb
|
105
135
|
- lib/envoku/rails.rb
|
136
|
+
- lib/envoku/resource.rb
|
106
137
|
- lib/envoku/version.rb
|
138
|
+
- lib/tasks/envoku.rake
|
139
|
+
- script/console
|
107
140
|
homepage: https://envoku.com
|
108
141
|
licenses:
|
109
142
|
- MIT
|
@@ -124,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
157
|
version: '0'
|
125
158
|
requirements: []
|
126
159
|
rubyforge_project:
|
127
|
-
rubygems_version: 2.
|
160
|
+
rubygems_version: 2.6.7
|
128
161
|
signing_key:
|
129
162
|
specification_version: 4
|
130
163
|
summary: Store environment variables securely on S3 away from your application
|