Class: Tfstats::Collector

Inherits:
Object
  • Object
show all
Defined in:
lib/tfstats/collector.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(directory, filespec) ⇒ Collector



133
134
135
136
137
# File 'lib/tfstats/collector.rb', line 133

def initialize(directory, filespec)
  @directory, @filespec = directory, filespec
  @stats = {}
  @stats.default = 0
end

Instance Attribute Details

#directoryObject

<< self



131
132
133
# File 'lib/tfstats/collector.rb', line 131

def directory
  @directory
end

#filespecObject

<< self



131
132
133
# File 'lib/tfstats/collector.rb', line 131

def filespec
  @filespec
end

#statsObject

<< self



131
132
133
# File 'lib/tfstats/collector.rb', line 131

def stats
  @stats
end

Class Method Details

.collect(directory, filespec, recursive, tabseparated) ⇒ Object



7
8
9
10
11
12
13
# File 'lib/tfstats/collector.rb', line 7

def collect(directory, filespec, recursive, tabseparated)
  statistics = {}
  process_dir(directory, filespec, recursive) do |collector, placeholder|
    statistics[placeholder] = collector.collect
  end
  puts output( statistics, tabseparated)
end

.empty?(stats) ⇒ Boolean



120
121
122
# File 'lib/tfstats/collector.rb', line 120

def empty?(stats)
  stats.values.sum == 0
end

.info(msg) ⇒ Object



124
125
126
127
128
# File 'lib/tfstats/collector.rb', line 124

def info(msg)
  if Tfstats.verbose
    puts msg
  end
end

.output(statistics, tabseparated) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/tfstats/collector.rb', line 41

def output(statistics, tabseparated)
  str = ''
  if tabseparated
    pattern = (["%s"] * 8).join("\t") + + "\n"
    separator = ''
  else
    max_name = statistics.keys.max_by { |s| s.size  }.size
    pattern = "| %-#{max_name}.#{max_name}s |" + " %9.9s |" * 7 + "\n"
    separator = '+-'+ ('-' * max_name) + '-+' + ('-' * 11 + '+') * 7 + "\n"
  end
  fields = i(files modules resources data variables lines loc)
  str << separator
  str << (pattern % %w(Directory Files modules resources data variables Lines LOC))
  str << separator
  statistics.each do |dir, filespecs|
    t = statistics[dir]
    unless empty?(t)
      str << (pattern % ([dir ] + t.values_at(*fields) ))
    end
  end
  str << separator
  str << (pattern % (["Total"] + sum(statistics).values_at(*fields) ))
  str << separator
  str
end

.output_versions(statistics, tabseparated) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/tfstats/collector.rb', line 67

def output_versions(statistics, tabseparated)
  str = ''
  info "statistics collected: #{statistics.inspect}"
  if tabseparated
    pattern = (["%s"] * 3).join("\t") + "\n"
    separator = ''
    str << (pattern % %w(Directory Provider Version))
    statistics.each do |dir, info|
      str << (pattern % [dir, 'terraform-version', info[:terraform_version]])
      if info[:providers].is_a? Hash
        info[:providers].each do |provider, version|
          str << (pattern % [dir, provider, version])
        end
      else
        str << (pattern % [dir, 'providers', info[:providers]])
      end
    end
  else
    max_name = statistics.map do |dir, info|
      if info[:providers].is_a? Hash
        info[:providers].map { |k,v| k.size }
      else
        info[:providers].size
      end
    end.flatten.max + 1
    pattern = "    %-#{max_name}.#{max_name}s %8s\n"
    statistics.each do |dir, info|
      str << "#{dir}:\n"
      str << "  terraform-version: #{info[:terraform_version]}\n"
      if info[:providers].is_a? Hash
        str << "  providers:\n"
        info[:providers].each do |provider,version|
          str << ( pattern % ["#{provider}:",version])
        end
      else
        str << "  providers: #{info[:providers]}\n"
      end
    end
  end
  str
end

.process_dir(directory, filespec, recursive) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/tfstats/collector.rb', line 24

def process_dir(directory, filespec, recursive)
  basename = File.basename File.expand_path(directory)
  info "directory: #{directory}"
  info "basename: #{basename}"
  info "filespec: #{filespec}"
  info "recursive: #{recursive}"
  if recursive
    Dir.glob("#{directory}/**/").each do |dir|
      info "traversing: #{dir}"
      placeholder = dir.sub(/^#{Regexp.escape(directory.to_s)}/, basename).chop
      yield new(dir, filespec), placeholder
    end
  else
    yield new(directory,filespec), basename
  end
end

.sum(statistics) ⇒ Object



109
110
111
112
113
114
115
116
117
118
# File 'lib/tfstats/collector.rb', line 109

def sum(statistics)
  s = {}
  s.default = 0
  statistics.each do |k, stats|
    stats.each do |k,v|
      s[k] += v
    end
  end
  s
end

.versions(directory, filespec, recursive, tabseparated) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/tfstats/collector.rb', line 15

def versions(directory, filespec, recursive, tabseparated)
  versions = {}
  process_dir(directory, filespec, recursive) do |collector, placeholder|
    versions[placeholder] = collector.versions if collector.any? # Check versions only if there are any relevant files in the directory
  end
  puts output_versions( versions, tabseparated)
end

Instance Method Details

#any?Boolean



139
140
141
142
# File 'lib/tfstats/collector.rb', line 139

def any?
  spec = File.join(directory, filespec)
  Dir[spec].any?
end

#collectObject



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/tfstats/collector.rb', line 148

def collect
  spec = File.join(directory, filespec)
  info "Fetching data from: #{spec}"
  Dir[spec].each do |file|
    info "Reading file: #{file}"
    @stats[:files] += 1
    begin
      File.read(file).each_line.with_index do |line,i|
        begin
          case line
          when /^\s*#/, /^\s*$/
          when /^\s*resource/
            @stats[:resources] += 1
          when /^\s*module/
            @stats[:modules] += 1
          when /^\s*variable/
            @stats[:variables] += 1
          when /^\s*data/
            @stats[:data] += 1
          else
            @stats[:loc] += 1
          end
        rescue ArgumentError => e
          STDERR.puts "#{file}:#{i+1} #{e}"
        end
        @stats[:lines] += 1
      end
    rescue => e
      STDERR.puts e
    end

  end
  @stats
end

#info(msg) ⇒ Object



144
145
146
# File 'lib/tfstats/collector.rb', line 144

def info(msg)
  self.class.info msg
end

#provider_versionsObject



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
# File 'lib/tfstats/collector.rb', line 201

def provider_versions
  file = File.join(directory, '.terraform.lock.hcl')
  providers = {}
  if File.exist? file
    state = :root
    provider = nil
    begin
      info "Fetching provider versions from: #{file}"
      File.read(file).each_line.with_index do |line,i|
        begin
          case state
          when :root
            if line =~ /^\s*provider\s*\"(.+)\"\s*\{\s*$/
              provider = $1
              state = :provider
            end
          when :provider
            if line =~ /^\s*version\s*=\s*"(.*)"\s*$/
              providers[provider] = $1
              state = :version
            end
          when :version
            if line =~ /^\s*\}\s*$/
              provider = nil
              state = :root
            end
          else
            raise ArgumentError, "File out of sync."
          end
        rescue ArgumentError => e
          STDERR.puts "#{file}:#{i+1} #{e}"
        end
      end
    rescue => e
      STDERR.puts e
    end
  end
  providers == {} ? 'undefined' : providers
end

#terraform_versionObject



189
190
191
192
193
194
195
196
197
198
199
# File 'lib/tfstats/collector.rb', line 189

def terraform_version
  file = File.join(directory, '.terraform-version')
  version = ''
  if File.exist? file
    info "Fetching version from: #{file}"
    version = File.read(file).chomp
  else
    info "No terraform version file found (#{file})"
  end
  version == '' ? 'undefined' : version
end

#versionsObject



183
184
185
186
187
# File 'lib/tfstats/collector.rb', line 183

def versions
  @stats[:terraform_version] = terraform_version
  @stats[:providers] = provider_versions
  @stats
end