centroid 0.1.1 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 88cda261ba612223506881320d31fc55cef45946
4
- data.tar.gz: d6fd6b798585da95fe94311ef96053c1451a0589
3
+ metadata.gz: f35b492a4ea8767187a77faae2f6b6bd5d5a66b6
4
+ data.tar.gz: 9fe53378ae98e8b4175dba7fe6af296e7fd9ad0d
5
5
  SHA512:
6
- metadata.gz: d8faf1555e47cd66426de9f35cf4befacdaec03398d426bdeb9cdecf328417b286683e6df56c1b9409b74ec8ca7edf19a5063687facf93fecf5a9c40391c77f2
7
- data.tar.gz: 5537aca1475d76f33b8b55d0220fb2fb679491229aa07683dc88ab0459bbe09f39497e1db67d21e79fcfd844655ac85d1831329b69e3f1a1aae962591a35ce01
6
+ metadata.gz: 7585bc76ed87101a41c3b46d7febd24f9fdefb4df32ed7bba4b5af60f15d6339f4a90d015d8a14a5aaa32b1d717a94af5acbc1a6ddd8410634fb6a07eaf87de0
7
+ data.tar.gz: fc57f08f83b93363132a68c6f866c9f5723834fd400c690d11a68776d826f5250f266eadc9a871e432f1f5fb5a92f3aed8e5ad91143113e054c4c86b7dcfdfda
data/README.md CHANGED
@@ -1,91 +1,91 @@
1
- # Centroid - Ruby
2
-
3
- ## Installation
4
-
5
- The Centroid Ruby package is hosted at [rubygems.org](https://rubygems.org/gems/centroid).
6
-
7
- You can install Centroid using gem with `gem install centroid`, or you can clone the repo, then `gem build centroid.gemspec`, and `gem install -l centroid` from the `ruby/` directory.
8
-
9
- ## Usage
10
-
11
- Begin by declaring your application's configuration values in JSON. The following example stores the database's server address.
12
-
13
- ```json
14
- {
15
- "database": {
16
- "serverAddress": "my-server.local"
17
- }
18
- }
19
- ```
20
-
21
- With Centroid's API, Ruby applications can then use the configuration values in this JSON.
22
-
23
- ### Ruby API
24
-
25
- The Ruby API is available through the `Centroid::Config` class, an instance of which is used to consume the JSON.
26
-
27
- The `Config` class exposes the `from_file` class method, an initializer, and the instance method `for_environment`.
28
-
29
- #### from_file(filename)
30
-
31
- You can create an instance of `Config` from a JSON file using the `Centroid::Config.from_file(filename)` class method.
32
-
33
- In the example below, note the `serverAddress` configuration value is retrieved using the snake_case `server_address` method even though the value is specified as camelCase in the JSON.
34
-
35
- ```rb
36
- # from_file.rb
37
- config = Centroid::Config.from_file("config.json")
38
- server = config.database.server_address # => "my-server.local"
39
- ```
40
-
41
- ### Config(json)
42
-
43
- Alternatively, you can create an instance of `Config` by passing a JSON string to the `Config` initializer.
44
-
45
- ```rb
46
- # from_string.rb
47
- json = '{ "database": { "serverAddress": "my-server.local" } }'
48
- config = Centroid::Config(json)
49
- server = config.database.server_address # => "my-server.local"
50
- ```
51
-
52
- ### for_enviroment(environment)
53
-
54
- Typically, real-world applications have different configuration values depending on the environment. For example, you might have *dev* and *prod* environments that use different servers, user accounts, etc. However, applications usually have other configuration values that are the same across all environments. Centroid makes it easy to retrieve all the configuration values you need for a specific environment.
55
-
56
- In environment-based configuration, the top-level objects in the JSON represent the various environments. Place the configuration values that are the same across all environments within the *all* environment.
57
-
58
- ```json
59
- {
60
- "dev": {
61
- "someResource": {
62
- "server": "resource-dev.local"
63
- }
64
- },
65
- "prod": {
66
- "someResource": {
67
- "server": "resource-prod.local"
68
- }
69
- },
70
- "all": {
71
- "keys": {
72
- "ssh": "path/to/id_rsa.pub"
73
- }
74
- }
75
- }
76
- ```
77
-
78
- Then, in the `Config` instance, use the instance method `for_environment` to retrieve the environment-based configuration. Centroid merges the requested environment's configuration values with the *all* environment configuration values.
79
-
80
- In the following example, the configuration for `prod` is merged with the configuration from `all`; the result is then available from a new instance of `Config`.
81
-
82
- ```rb
83
- # for_enviroment.rb
84
- config = Centroid::Config.from_file("config.json").for_environment("prod")
85
- server = config.some_resource.server # => "resource-prod.local"
86
- solution_path = config.keys.ssh # => "path/to/id_rsa.pub"
87
- ```
88
-
89
- ## Contributing
90
-
91
- See the [contributing section of the main README](../README.md#contributing)
1
+ # Centroid - Ruby
2
+
3
+ ## Installation
4
+
5
+ The Centroid Ruby package is hosted at [rubygems.org](https://rubygems.org/gems/centroid).
6
+
7
+ You can install Centroid using gem with `gem install centroid`, or you can clone the repo, then `gem build centroid.gemspec`, and `gem install -l centroid` from the `ruby/` directory.
8
+
9
+ ## Usage
10
+
11
+ Begin by declaring your application's configuration values in JSON. The following example stores the database's server address.
12
+
13
+ ```json
14
+ {
15
+ "database": {
16
+ "serverAddress": "my-server.local"
17
+ }
18
+ }
19
+ ```
20
+
21
+ With Centroid's API, Ruby applications can then use the configuration values in this JSON.
22
+
23
+ ### Ruby API
24
+
25
+ The Ruby API is available through the `Centroid::Config` class, an instance of which is used to consume the JSON.
26
+
27
+ The `Config` class exposes the `from_file` class method, an initializer, and the instance method `for_environment`.
28
+
29
+ #### from_file(filename)
30
+
31
+ You can create an instance of `Config` from a JSON file using the `Centroid::Config.from_file(filename)` class method.
32
+
33
+ In the example below, note the `serverAddress` configuration value is retrieved using the snake_case `server_address` method even though the value is specified as camelCase in the JSON.
34
+
35
+ ```rb
36
+ # from_file.rb
37
+ config = Centroid::Config.from_file("config.json")
38
+ server = config.database.server_address # => "my-server.local"
39
+ ```
40
+
41
+ ### Config(json)
42
+
43
+ Alternatively, you can create an instance of `Config` by passing a JSON string to the `Config` initializer.
44
+
45
+ ```rb
46
+ # from_string.rb
47
+ json = '{ "database": { "serverAddress": "my-server.local" } }'
48
+ config = Centroid::Config(json)
49
+ server = config.database.server_address # => "my-server.local"
50
+ ```
51
+
52
+ ### for_enviroment(environment)
53
+
54
+ Typically, real-world applications have different configuration values depending on the environment. For example, you might have *dev* and *prod* environments that use different servers, user accounts, etc. However, applications usually have other configuration values that are the same across all environments. Centroid makes it easy to retrieve all the configuration values you need for a specific environment.
55
+
56
+ In environment-based configuration, the top-level objects in the JSON represent the various environments. Place the configuration values that are the same across all environments within the *all* environment.
57
+
58
+ ```json
59
+ {
60
+ "dev": {
61
+ "someResource": {
62
+ "server": "resource-dev.local"
63
+ }
64
+ },
65
+ "prod": {
66
+ "someResource": {
67
+ "server": "resource-prod.local"
68
+ }
69
+ },
70
+ "all": {
71
+ "keys": {
72
+ "ssh": "path/to/id_rsa.pub"
73
+ }
74
+ }
75
+ }
76
+ ```
77
+
78
+ Then, in the `Config` instance, use the instance method `for_environment` to retrieve the environment-based configuration. Centroid merges the requested environment's configuration values with the *all* environment configuration values.
79
+
80
+ In the following example, the configuration for `prod` is merged with the configuration from `all`; the result is then available from a new instance of `Config`.
81
+
82
+ ```rb
83
+ # for_enviroment.rb
84
+ config = Centroid::Config.from_file("config.json").for_environment("prod")
85
+ server = config.some_resource.server # => "resource-prod.local"
86
+ solution_path = config.keys.ssh # => "path/to/id_rsa.pub"
87
+ ```
88
+
89
+ ## Contributing
90
+
91
+ See the [contributing section of the main README](../README.md#contributing)
data/centroid.gemspec CHANGED
@@ -1,11 +1,11 @@
1
- Gem::Specification.new do |s|
2
- s.name = 'centroid'
3
- s.version = '0.1.1'
4
- s.summary = 'A centralizaed paradigm to configuration management.'
5
- s.description = 'Centroid is a tool for loading configuration values declared in JSON, and accessing those configuration values using object properties.'
6
- s.author = 'Resource Data, Inc'
7
- s.email = 'oss@resdat.com'
8
- s.files = `git ls-files`.split("\n")
9
- s.homepage = 'https://github.com/ResourceDataInc/Centroid'
10
- s.license = 'MIT'
11
- end
1
+ Gem::Specification.new do |s|
2
+ s.name = 'centroid'
3
+ s.version = '1.0.0'
4
+ s.summary = 'A centralizaed paradigm to configuration management.'
5
+ s.description = 'Centroid is a tool for loading configuration values declared in JSON, and accessing those configuration values using object properties.'
6
+ s.author = 'Resource Data, Inc'
7
+ s.email = 'oss@resdat.com'
8
+ s.files = `git ls-files`.split("\n")
9
+ s.homepage = 'https://github.com/ResourceDataInc/Centroid'
10
+ s.license = 'MIT'
11
+ end
data/lib/centroid.rb CHANGED
@@ -1,63 +1,76 @@
1
- require "json"
2
-
3
- module Centroid
4
- class Config
5
- attr_reader :raw_config
6
-
7
- def initialize(config)
8
- if config.is_a?(Hash)
9
- @raw_config = config
10
- else
11
- @raw_config = JSON.parse(config)
12
- end
13
- end
14
-
15
- def method_missing(attrib, *)
16
- self[attrib]
17
- end
18
-
19
- def [](key)
20
- value = find_value(key, raw_config)
21
-
22
- raise Exception.new("Key not found in collection.") if value.nil?
23
-
24
- if value.is_a?(Hash)
25
- Config.new(value)
26
- else
27
- value
28
- end
29
- end
30
-
31
- def to_s
32
- JSON.dump(raw_config)
33
- end
34
-
35
- def for_environment(env)
36
- env_json = raw_config[env]
37
- all_key = actual_key("all", raw_config)
38
- if all_key.nil?
39
- Config.new(env_json)
40
- else
41
- all_json = raw_config[all_key]
42
- Config.new(all_json.merge(env_json))
43
- end
44
- end
45
-
46
- def self.from_file(filename)
47
- str_json = File.read(filename)
48
- self.new(str_json)
49
- end
50
-
51
- def normalised_key(unnormalised_key)
52
- unnormalised_key.to_s.gsub("_", "").downcase
53
- end
54
-
55
- def find_value(key, hashtable)
56
- hashtable[actual_key(key, hashtable)]
57
- end
58
-
59
- def actual_key(key, hashtable)
60
- hashtable.keys.find { |k| normalised_key(key) == normalised_key(k) }
61
- end
62
- end
63
- end
1
+ require "json"
2
+
3
+ module Centroid
4
+ class Config
5
+ attr_reader :raw_config
6
+
7
+ def initialize(config)
8
+ if config.is_a?(Hash)
9
+ @raw_config = config
10
+ else
11
+ @raw_config = JSON.parse(config)
12
+ validate_unique_keys!
13
+ end
14
+ end
15
+
16
+ def method_missing(attrib, *)
17
+ self[attrib]
18
+ end
19
+
20
+ def [](key)
21
+ value = find_value(key, raw_config)
22
+
23
+ raise KeyError.new("Centroid::Config instance does not contain key: #{key}") if value.nil?
24
+
25
+ if value.is_a?(Hash)
26
+ Config.new(value)
27
+ else
28
+ value
29
+ end
30
+ end
31
+
32
+ def to_s
33
+ JSON.dump(raw_config)
34
+ end
35
+
36
+ def for_environment(env)
37
+ env_json = raw_config[env]
38
+ all_key = actual_key("all", raw_config)
39
+ if all_key.nil?
40
+ Config.new(env_json)
41
+ else
42
+ all_json = raw_config[all_key]
43
+ Config.new(all_json.merge(env_json))
44
+ end
45
+ end
46
+
47
+ def self.from_file(filename)
48
+ str_json = File.read(filename)
49
+ self.new(str_json)
50
+ end
51
+
52
+ private
53
+
54
+ def normalize_key(unnormalised_key)
55
+ unnormalised_key.to_s.gsub("_", "").downcase
56
+ end
57
+
58
+ def find_value(key, hashtable)
59
+ hashtable[actual_key(key, hashtable)]
60
+ end
61
+
62
+ def actual_key(key, hashtable)
63
+ hashtable.keys.find { |k| normalize_key(key) == normalize_key(k) }
64
+ end
65
+
66
+ def validate_unique_keys!
67
+ normalized_keys = raw_config.keys.map { |k| { key: k, normalized_key: normalize_key(k) } }
68
+ dups = normalized_keys.group_by { |nk| nk[:normalized_key] }.select { |_, g| g.size > 1 }
69
+
70
+ return if dups.empty?
71
+
72
+ keys = dups.values.flat_map { |d| d.map { |e| e[:key] } }
73
+ raise KeyError, "Centroid::Config instance contains duplicate keys: #{keys.join(', ')}"
74
+ end
75
+ end
76
+ end
@@ -1,71 +1,87 @@
1
- require_relative "../lib/centroid"
2
- require "test/unit"
3
- require "json"
4
-
5
- class ConfigTests < Test::Unit::TestCase
6
- def json_config
7
- '{"Environment":{"TheKey":"TheValue"}}'
8
- end
9
-
10
- def shared_file_path
11
- 'config.json'
12
- end
13
-
14
- def test_create_from_string
15
- config = Centroid::Config.new(json_config)
16
- assert_equal(config.environment.the_key, "TheValue")
17
- end
18
-
19
- def test_create_from_file
20
- config = Centroid::Config.from_file(shared_file_path)
21
- assert_equal(config.dev.database.server, "sqldev01.centroid.local")
22
- end
23
-
24
- def test_raises_if_key_not_found
25
- config = Centroid::Config.new(json_config)
26
- assert_raise Exception do
27
- config = config.does_not_exist
28
- end
29
- end
30
-
31
- def test_readable_using_snake_case_property
32
- config = Centroid::Config.new(json_config)
33
- assert_equal(config.environment.the_key, "TheValue")
34
- end
35
-
36
- def test_environment_specific_config_is_included
37
- config = Centroid::Config.new(json_config)
38
- environment_config = config.for_environment("Environment")
39
- assert_equal(environment_config.the_key, "TheValue")
40
- end
41
-
42
- def test_shared_config_is_included
43
- config = Centroid::Config.from_file(shared_file_path)
44
- config = config.for_environment("Dev")
45
- assert_equal(config.ci.repo, "https://github.com/ResourceDataInc/Centroid")
46
- end
47
-
48
- def test_to_string_returns_json
49
- config = Centroid::Config.new(json_config)
50
- assert_equal(config.to_s, json_config)
51
- end
52
-
53
- def test_iterating_raw_config
54
- config = Centroid::Config.from_file(shared_file_path)
55
- keyCount = 0
56
- config.raw_config.each { |k| keyCount += 1 }
57
- assert_equal(keyCount, 4)
58
- end
59
-
60
- def test_modifying_raw_config
61
- config = Centroid::Config.new(json_config)
62
- config.raw_config["Environment"]["TheKey"] = "NotTheValue"
63
- assert_equal(config.environment.the_key, "NotTheValue")
64
- end
65
-
66
- def test_environment_specific_config_overrides_all
67
- config = Centroid::Config.new('{"Prod": {"Shared": "production!"}, "All": {"Shared": "none"}}')
68
- config = config.for_environment("Prod")
69
- assert_equal(config.shared, "production!")
70
- end
71
- end
1
+ require_relative "../lib/centroid"
2
+ require "test/unit"
3
+ require "json"
4
+
5
+ class ConfigTests < Test::Unit::TestCase
6
+ def json_config
7
+ '{"Environment":{"TheKey":"TheValue"}}'
8
+ end
9
+
10
+ def shared_file_path
11
+ 'config.json'
12
+ end
13
+
14
+ def test_create_from_string
15
+ config = Centroid::Config.new(json_config)
16
+ assert_equal(config.environment.the_key, "TheValue")
17
+ end
18
+
19
+ def test_create_from_file
20
+ config = Centroid::Config.from_file(shared_file_path)
21
+ assert_equal(config.dev.database.server, "sqldev01.centroid.local")
22
+ end
23
+
24
+ def test_raises_if_key_not_found
25
+ config = Centroid::Config.new(json_config)
26
+
27
+ exception = assert_raise KeyError do
28
+ config = config.does_not_exist
29
+ end
30
+
31
+ assert exception.message =~ /does not contain/i, "Message should indicate key does not exist"
32
+ assert exception.message =~ /does_not_exist/, "Message should contain missing key"
33
+ end
34
+
35
+ def test_raises_if_duplicate_normalized_keys_exist
36
+ json = '{ "someKey": "value", "some_key": "value" }'
37
+
38
+ exception = assert_raise KeyError do
39
+ Centroid::Config.new(json)
40
+ end
41
+
42
+ assert exception.message =~ /duplicate/i, "Message should indicate duplicate key"
43
+ assert exception.message =~ /someKey/, "Message should contain duplicate key"
44
+ assert exception.message =~ /some_key/, "Message should contain duplicate key"
45
+ end
46
+
47
+ def test_readable_using_snake_case_property
48
+ config = Centroid::Config.new(json_config)
49
+ assert_equal(config.environment.the_key, "TheValue")
50
+ end
51
+
52
+ def test_environment_specific_config_is_included
53
+ config = Centroid::Config.new(json_config)
54
+ environment_config = config.for_environment("Environment")
55
+ assert_equal(environment_config.the_key, "TheValue")
56
+ end
57
+
58
+ def test_shared_config_is_included
59
+ config = Centroid::Config.from_file(shared_file_path)
60
+ config = config.for_environment("Dev")
61
+ assert_equal(config.ci.repo, "https://github.com/ResourceDataInc/Centroid")
62
+ end
63
+
64
+ def test_to_string_returns_json
65
+ config = Centroid::Config.new(json_config)
66
+ assert_equal(config.to_s, json_config)
67
+ end
68
+
69
+ def test_iterating_raw_config
70
+ config = Centroid::Config.from_file(shared_file_path)
71
+ keyCount = 0
72
+ config.raw_config.each { |k| keyCount += 1 }
73
+ assert_equal(keyCount, 4)
74
+ end
75
+
76
+ def test_modifying_raw_config
77
+ config = Centroid::Config.new(json_config)
78
+ config.raw_config["Environment"]["TheKey"] = "NotTheValue"
79
+ assert_equal(config.environment.the_key, "NotTheValue")
80
+ end
81
+
82
+ def test_environment_specific_config_overrides_all
83
+ config = Centroid::Config.new('{"Prod": {"Shared": "production!"}, "All": {"Shared": "none"}}')
84
+ config = config.for_environment("Prod")
85
+ assert_equal(config.shared, "production!")
86
+ end
87
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: centroid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Resource Data, Inc
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-19 00:00:00.000000000 Z
11
+ date: 2014-02-20 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Centroid is a tool for loading configuration values declared in JSON,
14
14
  and accessing those configuration values using object properties.
@@ -31,17 +31,17 @@ require_paths:
31
31
  - lib
32
32
  required_ruby_version: !ruby/object:Gem::Requirement
33
33
  requirements:
34
- - - '>='
34
+ - - ">="
35
35
  - !ruby/object:Gem::Version
36
36
  version: '0'
37
37
  required_rubygems_version: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - '>='
39
+ - - ">="
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  requirements: []
43
43
  rubyforge_project:
44
- rubygems_version: 2.2.2
44
+ rubygems_version: 2.2.0
45
45
  signing_key:
46
46
  specification_version: 4
47
47
  summary: A centralizaed paradigm to configuration management.