Class: Freud::Config

Inherits:
Object
  • Object
show all
Includes:
Agrippa::Delegation
Defined in:
lib/freud/config.rb

Constant Summary collapse

UNDEFINED =
Object.new

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeConfig



16
17
18
19
# File 'lib/freud/config.rb', line 16

def initialize
    @config = {}
    @vars = Variables.new
end

Instance Attribute Details

#configObject (readonly)

Returns the value of attribute config.



12
13
14
# File 'lib/freud/config.rb', line 12

def config
  @config
end

#varsObject (readonly)

Returns the value of attribute vars.



12
13
14
# File 'lib/freud/config.rb', line 12

def vars
  @vars
end

Instance Method Details

#deep_merge(under, over) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
# File 'lib/freud/config.rb', line 206

def deep_merge(under, over)
    over.each_pair do |key, over_value|
        under_value = under[key]
        if(under_value.is_a?(Hash) and over_value.is_a?(Hash))
            under.store(key, deep_merge(under_value, over_value))
        else
            under.store(key, over_value)
        end
    end
    under
end

#deep_stringify_keys(hash) ⇒ Object



218
219
220
221
222
223
224
225
# File 'lib/freud/config.rb', line 218

def deep_stringify_keys(hash)
    output = {}
    hash.each_pair do |key, value|
        next(output.store(key.to_s, value)) unless value.is_a?(Hash)
        output.store(key.to_s, deep_stringify_keys(value))
    end
    output
end

#default_config(file) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'lib/freud/config.rb', line 166

def default_config(file)
    deep_stringify_keys(
        name: File.basename(file.path).gsub(/\..*$/, ''),
        root: File.dirname(file.path),
        background: false,
        create_pidfile: false,
        reset_env: false,
        pidfile: "tmp/%name.pid",
        vars: {},
        env: { FREUD_CONFIG: file.path },
        stages: { development: {}, production: {} },
        commands: {
            stop: "%self checkpid quiet && kill -TERM %pid",
            restart: "%self stop && %self start",
            reload: "%self checkpid quiet && kill -HUP %pid",
            kill: "%self checkpid quiet && kill -KILL %pid",
            status: "%self checkpid" })
end

#default_name(file) ⇒ Object



78
79
80
# File 'lib/freud/config.rb', line 78

def default_name(file)
    File.basename(file.path).gsub(/\.\w*$/, '')
end

#dump(root = nil, level = 0) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/freud/config.rb', line 35

def dump(root = nil, level = 0)
    root ||= @config
    indent = "    " * level
    root.each_pair do |key, value|
        if value.respond_to?(:each_pair)
            puts "#{indent}#{key}:"
            dump(value, level + 1)
        else
            puts "#{indent}#{key}: #{value}"
        end
    end
    self
end

#expand_path(path, relative_to) ⇒ Object



128
129
130
131
# File 'lib/freud/config.rb', line 128

def expand_path(path, relative_to)
    return(File.expand_path(path)) if is_absolute_path(path)
    File.expand_path(File.join(relative_to, path))
end

#fetch(key, default = UNDEFINED) ⇒ Object



95
96
97
98
# File 'lib/freud/config.rb', line 95

def fetch(key, default = UNDEFINED)
    return(@config.fetch(key.to_s)) if (default == UNDEFINED)
    @config.fetch(key.to_s, default)
end

#global_config(json) ⇒ Object



185
186
187
# File 'lib/freud/config.rb', line 185

def global_config(json)
    snakify_keys(json)
end

#initialize_vars(file) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'lib/freud/config.rb', line 59

def initialize_vars(file)
    merge_vars(ENV)
    merge_vars(name: default_name(file))
    merge_vars(self: path_to_running_script)
    merge_vars(fetch(:vars))
    default_root = File.dirname(file.path)
    root_path = expand_path(fetch(:root), default_root)
    store_vars(:root, root_path)
    store(:root, root_path)
    interpolate(:pidfile)
    interpolate(:sudo_user)
    pidfile_path = expand_path(fetch(:pidfile), root_path)
    store(:pidfile, Pidfile.new(pidfile_path))
    interpolate(:logfile)
    logfile = fetch(:logfile)
    store(:logfile, expand_path(logfile, root_path)) if logfile
    store_vars(:pid, read_pidfile)
end

#interpolate(key) ⇒ Object



200
201
202
203
204
# File 'lib/freud/config.rb', line 200

def interpolate(key)
    value = apply_vars(fetch(key, nil))
    store_vars(key, value)
    store(key, value)
end

#interpolate_commandsObject



147
148
149
150
151
# File 'lib/freud/config.rb', line 147

def interpolate_commands
    commands = fetch(:commands)
    commands.each_pair { |k, v| commands[k] = apply_vars(v) }
    self
end

#interpolate_envObject



141
142
143
144
145
# File 'lib/freud/config.rb', line 141

def interpolate_env
    env = fetch(:env)
    env.each_pair { |k, v| env[k] = apply_vars(v) }
    self
end

#is_absolute_path(path) ⇒ Object



133
134
135
# File 'lib/freud/config.rb', line 133

def is_absolute_path(path)
    (path =~ /^\//) ? true : false
end

#load(file, stage) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/freud/config.rb', line 21

def load(file, stage)
    json = load_json(file)
    merge(default_config(file))
    merge(global_config(json))
    merge(stage_config(stage))
    merge(override_config(stage))
    initialize_vars(file)
    interpolate_env
    interpolate_commands
    config.delete("stages")
    config.delete("vars")
    self
end

#load_json(file) ⇒ Object



49
50
51
52
53
# File 'lib/freud/config.rb', line 49

def load_json(file)
    output = JSON.parse(file.read)
    file.close
    output
end

#merge(hash) ⇒ Object



86
87
88
# File 'lib/freud/config.rb', line 86

def merge(hash)
    deep_merge(@config, validate(hash))
end

#override_config(stage) ⇒ Object



194
195
196
197
198
# File 'lib/freud/config.rb', line 194

def override_config(stage)
    deep_stringify_keys(
        vars: { stage: stage },
        env: { FREUD_STAGE: "%stage" })
end

#path_to_running_scriptObject



82
83
84
# File 'lib/freud/config.rb', line 82

def path_to_running_script
    File.expand_path($PROGRAM_NAME)
end

#read_pidfileObject



137
138
139
# File 'lib/freud/config.rb', line 137

def read_pidfile
    fetch(:pidfile).read
end

#snakify_keys(hash) ⇒ Object



153
154
155
156
157
# File 'lib/freud/config.rb', line 153

def snakify_keys(hash)
    output = {}
    hash.each_pair { |k, v| output.store(snakify_string(k), v) }
    output
end

#snakify_string(input) ⇒ Object



159
160
161
162
163
164
# File 'lib/freud/config.rb', line 159

def snakify_string(input)
    input.gsub(/(.)([A-Z][a-z]+)/, '\1_\2')
        .gsub(/(.)([0-9]+)/, '\1_\2')
        .gsub(/([a-z0-9])([A-Z])/, '\1_\2')
        .downcase
end

#stage_config(name) ⇒ Object



189
190
191
192
# File 'lib/freud/config.rb', line 189

def stage_config(name)
    stages = snakify_keys(config.fetch("stages"))
    stages.fetch(name) { raise("Unknown stage: #{name}")}
end

#store(key, value) ⇒ Object



90
91
92
93
# File 'lib/freud/config.rb', line 90

def store(key, value)
    @config.store(key.to_s, value)
    self
end

#to_hashObject



55
56
57
# File 'lib/freud/config.rb', line 55

def to_hash
    config
end

#validate(hash) ⇒ Object



100
101
102
103
104
105
106
107
108
# File 'lib/freud/config.rb', line 100

def validate(hash)
    strings = %w(root pidfile logfile sudo_user)
    strings.each { |key| validate_string(key, hash[key]) }
    booleans = %w(background create_pidfile reset_env)
    booleans.each { |key| validate_boolean(key, hash[key]) }
    hashes = %w(vars env commands)
    hashes.each { |key| validate_hash(key, hash[key]) }
    hash
end

#validate_boolean(key, value) ⇒ Object



115
116
117
118
119
# File 'lib/freud/config.rb', line 115

def validate_boolean(key, value)
    return(true) if value.nil?
    return(true) if (value == true or value == false)
    raise("#{key} must be a boolean.")
end

#validate_hash(key, value) ⇒ Object



121
122
123
124
125
126
# File 'lib/freud/config.rb', line 121

def validate_hash(key, value)
    return(true) if value.nil?
    raise("#{key} must be a hash.") unless value.is_a?(Hash)
    value.each_pair { |k, v| validate_string("#{key}.#{k}", v) }
    true
end

#validate_string(key, value) ⇒ Object



110
111
112
113
# File 'lib/freud/config.rb', line 110

def validate_string(key, value)
    return(true) if (value.nil? or value.is_a?(String))
    raise("#{key} must be a string.")
end