etcenv 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: c67fca7ce92b7e16d5365bdc969aa6e974fc6cc9
4
- data.tar.gz: 99ad3db08fcc4e806a677cfe085bb475e1dceab7
3
+ metadata.gz: e08b420a67f38847ae025f781cbedb6484a0af74
4
+ data.tar.gz: 84cc434c7876ceb2f31e0158dde5665d4d005d73
5
5
  SHA512:
6
- metadata.gz: 3c1e239945d4bbbd0735f3f8ec451eab0da1ca607cdbfd9390543b10aec9718364ec51081fa521343d9d05607b55357fc73b8a2f2ff45a22f83d568edb26ea22
7
- data.tar.gz: d5b380c6fa77885aa7d0d1d522b185184fa959a9f6864018b01696061451aeea356b47f84a09e9adf9ae93f1e0f2b848928016c8e2415cb6b322a5d67fef7479
6
+ metadata.gz: 033c93840d0379655f653c87a5fcd551b171489c6bd24d859dda7be495b3c1ce45c831f53e98916acd31fdfea25d87ae8ed84a10975a28836c9b00e04e373c65
7
+ data.tar.gz: fa114bfa98c149a549cd0c68b1424b758ee57fb30a7d8d2a25a1919639ae49de6490925fc5f193978dd4acff3efce79b3fa84bc405ab908c267cdb50760fb198
data/README.md CHANGED
@@ -67,12 +67,12 @@ In docker mode, etcenv evaluates `${...}` expansion like dotenv do.
67
67
 
68
68
  ### Include other directory's variables
69
69
 
70
- Set directory path to `_include`. Directories can be specified multiple, separated by comma.
70
+ Set directory path to `.include`. Directories can be specified multiple, separated by comma.
71
71
 
72
72
  ```
73
73
  etcdctl mkdir /common
74
74
  etcdctl set /common/COMMON_SECRET xxx
75
- etcdctl set /my-app/_include /common
75
+ etcdctl set /my-app/.include /common
76
76
  ```
77
77
 
78
78
  Also, you can omit path of parent directory:
@@ -82,11 +82,11 @@ etcdctl mkdir /envs/common
82
82
  etcdctl set /envs/common/COMMON_SECRET xxx
83
83
 
84
84
  etcdctl mkdir /envs/my-app
85
- etcdctl set /envs/my-app/_include common
85
+ etcdctl set /envs/my-app/.include common
86
86
  ```
87
87
 
88
- - `_include` will be applied recursively (up to 10 times by default). If `_include` is looping, it'll be an error.
89
- - For multiple `_include`, value for same key may be overwritten.
88
+ - `.include` will be applied recursively (up to 10 times by default). If `.include` is looping, it'll be an error.
89
+ - For multiple `.include`, value for same key may be overwritten.
90
90
  - If `a` includes `b`,`c` and `b` includes `d`, result for `a` will be: `d`, `b`, `c`, then `a`.
91
91
 
92
92
  ## Development
data/lib/etcenv/cli.rb CHANGED
@@ -104,7 +104,7 @@ module Etcenv
104
104
  return 1
105
105
  end
106
106
  env = argv.inject(nil) do |env, key|
107
- new_env = Environment.new(etcd, key).env
107
+ new_env = Environment.new(etcd, key).expanded_env
108
108
  env ? env.merge(new_env) : new_env
109
109
  end
110
110
  dump_env(env)
@@ -129,7 +129,6 @@ module Etcenv
129
129
  envs = argv.map { |key| Environment.new(etcd, key) }
130
130
 
131
131
  watchers = envs.map { |env| Watcher.new(env, verbose: true) }
132
- Thread.abort_on_exception = true
133
132
 
134
133
  dumper_ch = Queue.new
135
134
  dumper = Thread.new do
@@ -142,6 +141,7 @@ module Etcenv
142
141
  dumper_ch.pop
143
142
  end
144
143
  end
144
+ dumper.abort_on_exception = true
145
145
 
146
146
  watchers.map do |watcher|
147
147
  Thread.new do
@@ -8,12 +8,8 @@ module Etcenv
8
8
 
9
9
  attr_reader :env
10
10
 
11
- def expanded_env
12
- VariableExpander.expand @env
13
- end
14
-
15
11
  def lines
16
- expanded_env.map { |k,v| "#{k}=#{v}" }
12
+ env.map { |k,v| "#{k}=#{v}" }
17
13
  end
18
14
 
19
15
  def to_s
@@ -8,12 +8,8 @@ module Etcenv
8
8
 
9
9
  attr_reader :env
10
10
 
11
- def expanded_env
12
- VariableExpander.expand @env
13
- end
14
-
15
11
  def lines
16
- expanded_env.map { |k, v| make_dotenv_line(k, v) }
12
+ env.map { |k, v| make_dotenv_line(k, v) }
17
13
  end
18
14
 
19
15
  def to_s
@@ -1,10 +1,12 @@
1
+ require 'etcenv/variable_expander'
2
+
1
3
  module Etcenv
2
4
  class Environment
3
5
  class NotDirectory < StandardError; end
4
6
  class DepthLimitError < StandardError; end
5
7
  class LoopError < StandardError; end
6
8
 
7
- INCLUDE_KEY = '_include'
9
+ INCLUDE_KEY = '.include'
8
10
  MAX_DEPTH_DEFAULT = 10
9
11
 
10
12
  def initialize(etcd, root_key, max_depth: MAX_DEPTH_DEFAULT)
@@ -18,6 +20,10 @@ module Etcenv
18
20
  attr_reader :root_key, :env, :etcd
19
21
  attr_accessor :max_depth
20
22
 
23
+ def expanded_env
24
+ VariableExpander.expand(env)
25
+ end
26
+
21
27
  def modified_indices
22
28
  @modified_indices ||= {}
23
29
  end
@@ -29,7 +35,7 @@ module Etcenv
29
35
  includes.each do |name|
30
36
  env.merge! fetch(name)
31
37
  end
32
- env.delete '_include'
38
+ env.delete '.include'
33
39
  @env = env
34
40
  end
35
41
  self
@@ -50,7 +56,7 @@ module Etcenv
50
56
  end
51
57
 
52
58
  def default_prefix
53
- root_key.sub(/^.*\//, '')
59
+ root_key.sub(/^(.*)\/.+?$/, '\1')
54
60
  end
55
61
 
56
62
  def resolve_key(key)
@@ -80,11 +86,12 @@ module Etcenv
80
86
 
81
87
  node.children.each do |child|
82
88
  name = child.key.sub(/^.*\//, '')
89
+
90
+ index = [index, child.modified_index].max
83
91
  if child.dir
84
92
  next
85
93
  else
86
94
  dir[name] = child.value
87
- index = [index, child.modified_index].max
88
95
  end
89
96
  end
90
97
 
@@ -1,3 +1,3 @@
1
1
  module Etcenv
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -2,9 +2,13 @@ require 'thread'
2
2
 
3
3
  module Etcenv
4
4
  class Watcher
5
+ WATCH_TIMEOUT = 120
6
+
5
7
  def initialize(env, verbose: false)
6
8
  @env = env
7
9
  @verbose = verbose
10
+ @indices = {}
11
+ @lock = Mutex.new
8
12
  end
9
13
 
10
14
  attr_reader :env, :verbose
@@ -16,11 +20,8 @@ module Etcenv
16
20
  def watch
17
21
  ch = Queue.new
18
22
  threads = env.modified_indices.map do |key, index|
19
- Thread.new do
20
- $stderr.puts "[watcher] waiting for change on #{key} (index: #{index.succ})" if verbose
21
- etcd.watch(key, recursive: true, index: index.succ)
22
- $stderr.puts "[watcher] dir #{key} has updated" if verbose
23
- ch << key
23
+ Thread.new(ch, key, index, &method(:watch_thread)).tap do |th|
24
+ th.abort_on_exception = true
24
25
  end
25
26
  end
26
27
  report = ch.pop
@@ -30,11 +31,32 @@ module Etcenv
30
31
 
31
32
  def auto_reload_loop
32
33
  loop do
33
- watch
34
- $stderr.puts "[watcher] reloading env #{env.root_key}" if verbose
35
- env.load
36
- yield env if block_given?
34
+ begin
35
+ watch
36
+ $stderr.puts "[watcher] reloading env #{env.root_key}" if verbose
37
+ env.load
38
+ yield env if block_given?
39
+ rescue => e
40
+ $stderr.puts "[watcher][error] Failed to reload env #{env.root_key}: #{e.inspect}"
41
+ $stderr.puts "\t#{e.backtrace.join("\n\t")}"
42
+ end
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ def watch_thread(ch, key, index)
49
+ $stderr.puts "[watcher] waiting for change on #{key} (index: #{index.succ})" if verbose
50
+ response = etcd.watch(key, recursive: true, index: [@indices[key] || 0, index].max.succ, timeout: WATCH_TIMEOUT)
51
+ @lock.synchronize do
52
+ # Record modified_index in watcher itself; Because the latest index may be hidden in normal response
53
+ # e.g. unlisted keys, removed keys
54
+ @indices[key] = response.node.modified_index
37
55
  end
56
+ $stderr.puts "[watcher] dir #{key} has updated" if verbose
57
+ ch << key
58
+ rescue Net::ReadTimeout
59
+ retry
38
60
  end
39
61
  end
40
62
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: etcenv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shota Fukumori (sora_h)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-07 00:00:00.000000000 Z
11
+ date: 2015-04-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
114
114
  version: '0'
115
115
  requirements: []
116
116
  rubyforge_project:
117
- rubygems_version: 2.2.2
117
+ rubygems_version: 2.4.5
118
118
  signing_key:
119
119
  specification_version: 4
120
120
  summary: Dump etcd keys into dotenv file or docker env file