Class: GrowthForecast::Spec

Inherits:
Object
  • Object
show all
Defined in:
lib/growthforecast/spec.rb

Constant Summary collapse

GRAPH_ATTRIBUTES =
[
  :description, :mode, :sort, :color, :gmode,
  :type, :ulimit, :llimit, :stype, :sulimit, :sllimit,
  :adjust, :adjustval, :unit,
]
COMPLEX_ATTRIBUTES =
[ :description, :sort, :sumup ]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(dic, spec_yaml, complex = false) ⇒ Spec

Returns a new instance of Spec.



9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/growthforecast/spec.rb', line 9

def initialize(dic, spec_yaml, complex=false)
  @dic = dic

  @spec = spec_yaml.dup

  @name = @spec.delete('name')
  @path = @spec.delete('path')
  @complex = @spec.delete('complex') || complex
  
  @service_name, @section_name, @graph_name = replace_keywords(@path).split('/')

  unless @service_name and @section_name and @graph_name and
      not @service_name.empty? and not @section_name.empty? and not @graph_name.empty?
    raise ArgumentError, "'path' must be as service/section/graph (#{@path})"
  end
end

Instance Attribute Details

#complexObject

Returns the value of attribute complex.



2
3
4
# File 'lib/growthforecast/spec.rb', line 2

def complex
  @complex
end

#graph_nameObject

Returns the value of attribute graph_name.



3
4
5
# File 'lib/growthforecast/spec.rb', line 3

def graph_name
  @graph_name
end

#nameObject

Returns the value of attribute name.



2
3
4
# File 'lib/growthforecast/spec.rb', line 2

def name
  @name
end

#pathObject

Returns the value of attribute path.



2
3
4
# File 'lib/growthforecast/spec.rb', line 2

def path
  @path
end

#section_nameObject

Returns the value of attribute section_name.



3
4
5
# File 'lib/growthforecast/spec.rb', line 3

def section_name
  @section_name
end

#service_nameObject

Returns the value of attribute service_name.



3
4
5
# File 'lib/growthforecast/spec.rb', line 3

def service_name
  @service_name
end

Instance Method Details

#check(cache) ⇒ Object

return [true/false, [error notifications]]



31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/growthforecast/spec.rb', line 31

def check(cache)
  target = cache.get(@service_name, @section_name, @graph_name)

  if target.nil?
    return false, ["target path #{@service_name}/#{@section_name}/#{@graph_name} not exists"]
  elsif self.complex? ^ target.complex?
    return false, ["complex type is not match"]
  end

  if self.complex?
    self.check_complex(cache, target)
  else
    self.check_graph(cache, target)
  end
end

#check_complex(cache, target) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/growthforecast/spec.rb', line 97

def check_complex(cache, target)
  errors = []
  COMPLEX_ATTRIBUTES.each do |attr|
    next unless @spec.has_key?(attr.to_s)
    target_val = target.send(attr)
    spec_val = if (attr == :description) && @spec[attr.to_s]
                 replace_keywords(@spec[attr.to_s])
               else
                 @spec[attr.to_s]
               end
    unless target_val == spec_val
      errors.push("attribute #{attr} value mismatch, spec '#{spec_val}' but '#{target_val}'")
    end
  end

  unless @spec.has_key?('data')
    return errors.empty?, errors
  end

  # @spec has 'data'
  spec_data_tmpl = {}
  spec_data_tmpl['gmode'] = @spec['gmode'] if @spec.has_key?('gmode')
  spec_data_tmpl['stack'] = @spec['stack'] if @spec.has_key?('stack')
  spec_data_tmpl['type'] = @spec['type'] if @spec.has_key?('type')

  target_data = target.send(:data)

  @spec['data'].each_with_index do |item, index|
    specitem = spec_data_tmpl.merge(item)

    #path
    unless specitem['path']
      errors.push("data: path missing")
      next
    end
    replaced_path = replace_keywords(specitem['path'])
    path_element = replaced_path.split('/')
    unless path_element.size == 3
      errors.push("data: path is not like SERVICE/SECTION/GRAPH")
      next
    end
    specitem_graph = cache.get(*path_element)
    unless specitem_graph
      errors.push("data: specified graph '#{replaced_path}' not found")
      next
    end

    current_target = target_data.select { |data| data.graph_id.to_i == specitem_graph.id.to_i }
    #data graph_id
    if current_target.size.zero?
      errors.push("data mismatch, spec '#{replaced_path}'(graph id #{specitem_graph.id}) does not include in complex graph.")
      next
    end
    if current_target.size > 1
      errors.push("data mismatch, spec '#{replaced_path}'(graph id #{specitem_graph.id}) found more than one.")
      next
    end
    current_target = current_target.first
    #gmode, type
    if specitem.has_key?('gmode') && specitem['gmode'] != current_target.gmode
      errors.push("data: gmode mismatch, spec '#{specitem['gmode']}' but '#{current_target.gmode}'")
    end
    if specitem.has_key?('type') && specitem['type'] != current_target.type
      errors.push("data: type mismatch, spec '#{specitem['type']}' but '#{current_target.type}'")
    end
    #stack: stack of first data item is nonsense
    if index > 0 && specitem.has_key?('stack') && specitem['stack'] != current_target.stack
      errors.push("data: stack mismatch, spec '#{specitem['stack']}' but '#{current_target.stack}'")
    end
  end

  return errors.empty?, errors
end

#check_graph(cache, target) ⇒ Object



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

def check_graph(cache, target)
  errors = []
  GRAPH_ATTRIBUTES.each do |attr|
    next unless @spec.has_key?(attr.to_s)
    target_val = target.send(attr)
    spec_val = if (attr == :description) && @spec[attr.to_s]
                 replace_keywords(@spec[attr.to_s])
               else
                 @spec[attr.to_s]
               end
    unless target_val == spec_val
      errors.push("attribute #{attr} value mismatch, spec '#{spec_val}' but '#{target_val}'")
    end
  end
  return errors.empty?, errors
end

#complex?Boolean

Returns:

  • (Boolean)


5
6
7
# File 'lib/growthforecast/spec.rb', line 5

def complex?
  @complex
end

#merge(cache, target) ⇒ Object



47
48
49
50
51
52
53
# File 'lib/growthforecast/spec.rb', line 47

def merge(cache, target)
  if self.complex?
    self.merge_complex(cache, target)
  else
    self.merge_graph(cache, target)
  end
end

#merge_complex(cache, target) ⇒ Object



171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/growthforecast/spec.rb', line 171

def merge_complex(cache, target)
  if target.nil?
    target = GrowthForecast::Complex.new({
        complex: true,
        service_name: @service_name, section_name: @section_name, graph_name: @graph_name,
        description: '',
      })
  end

  COMPLEX_ATTRIBUTES.each do |attr|
    next unless @spec.has_key?(attr.to_s)

    val = if attr == :description
            replace_keywords(@spec[attr.to_s])
          else
            @spec[attr.to_s]
          end
    target.send((attr.to_s + '=').to_sym, val)
  end

  unless @spec.has_key?('data')
    return target
  end

  # @spec has 'data'
  spec_data_tmpl = {}
  spec_data_tmpl['gmode'] = @spec['gmode'] if @spec.has_key?('gmode')
  spec_data_tmpl['stack'] = @spec['stack'] if @spec.has_key?('stack')
  spec_data_tmpl['type'] = @spec['type'] if @spec.has_key?('type')

  target.data = target.data.dup

  @spec['data'].each_with_index do |item, index|
    specitem = spec_data_tmpl.merge(item)

    #path
    unless specitem['path']
      warn "data[#{index}]: path missing"
      return nil
    end
    replaced_path = replace_keywords(specitem['path'])
    path_element = replaced_path.split('/')
    unless path_element.size == 3
      warn "data[#{index}]: path '#{replaced_path}' is not like SERVICE/SECTION/GRAPH"
      return nil
    end
    specitem_graph = cache.get(*path_element)
    unless specitem_graph
      warn "data[#{index}]: path '#{replaced_path}' not found"
      return nil
    end

    #data(sub graph) size
    unless target.data[index]
      target.data[index] = GrowthForecast::Complex::Item.new({
          graph_id: specitem_graph.id,
          gmode: (specitem['gmode'] || nil), # nil: default
          stack: (specitem.has_key?('stack') ? specitem['stack'] : nil),
          type: (specitem['type'] || nil),
        })
      next
    end

    target.data[index].graph_id = specitem_graph.id if specitem_graph.id != target.data[index].graph_id
    target.data[index].gmode = specitem['gmode'] if specitem.has_key?('gmode') && specitem['gmode'] != target.data[index].gmode
    target.data[index].type  = specitem['type']  if specitem.has_key?('type') && specitem['type'] != target.data[index].type
    target.data[index].stack = specitem['stack'] if index > 0 && specitem.has_key?('stack') && specitem['stack'] != target.data[index].stack
  end

  target
end

#merge_graph(cache, target) ⇒ Object



77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/growthforecast/spec.rb', line 77

def merge_graph(cache, target)
  if target.nil?
    target = GrowthForecast::Graph.new({
        service_name: @service_name, section_name: @section_name, graph_name: @graph_name,
        description: '',
      })
  end
  GRAPH_ATTRIBUTES.each do |attr|
    next unless @spec.has_key?(attr.to_s)
    val = if attr == :description
            replace_keywords(@spec[attr.to_s])
          else
            @spec[attr.to_s]
          end
    target.send((attr.to_s + '=').to_sym, val)
  end
  target
end

#replace_keywords(str) ⇒ Object



26
27
28
# File 'lib/growthforecast/spec.rb', line 26

def replace_keywords(str)
  @dic.reduce(str){|r, pair| r.gsub('${' + pair[0] + '}', pair[1])}
end