Class: VCSConnectorDriver

Inherits:
Object
  • Object
show all
Defined in:
lib/vcseif/vcs_connector_driver.rb

Constant Summary collapse

NUMBER_OF_REQUIRED_VCS_CONNECTOR_SECTIONS =
3
VCS_APP_ROOT =
'VCS_APP_ROOT'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(script_name) ⇒ VCSConnectorDriver

Returns a new instance of VCSConnectorDriver.



17
18
19
20
21
22
23
24
25
26
27
28
# File 'lib/vcseif/vcs_connector_driver.rb', line 17

def initialize(script_name)
    rationalizeEnvironment()
    @script_name = script_name
    logs_directory = "%s/logs" % ENV[VCS_APP_ROOT]
    if not Dir.exists?(logs_directory)
        begin
            FileUtils.mkdir(logs_directory)
        rescue
        end
    end
    @uber_log_name = "%s/%s.log"  % [logs_directory, script_name]
end

Instance Attribute Details

#logObject

Returns the value of attribute log.



15
16
17
# File 'lib/vcseif/vcs_connector_driver.rb', line 15

def log
  @log
end

#script_nameObject (readonly)

Returns the value of attribute script_name.



14
15
16
# File 'lib/vcseif/vcs_connector_driver.rb', line 14

def script_name
  @script_name
end

#uber_log_nameObject (readonly)

Returns the value of attribute uber_log_name.



14
15
16
# File 'lib/vcseif/vcs_connector_driver.rb', line 14

def uber_log_name
  @uber_log_name
end

Instance Method Details

#delegateToConnectorRunner(config) ⇒ Object



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
170
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
# File 'lib/vcseif/vcs_connector_driver.rb', line 145

def delegateToConnectorRunner(config)
    """
        Given a Hash with the configuration content, 
        obtain the correct _X_ConnectorRunner instance and feed it
        the config and call its run method.
    """
    hits = config.keys.select {|key| key =~ /^\w+Connector$/}
    if hits.nil? or hits.empty?
        @log.error("Config %s lacks an entry identifying the EIF Connector type" % config['ConfigName'])
        return 1
    end
    connector_type = hits.first

    runner_name = '%sRunner' % connector_type
    begin
        connector_runner_class = Kernel.const_get(runner_name)
    rescue => ex
        problem = 'Unable to locate/load the %sRunner class.  Is your vcseif gem properly installed?'
        @log.fatal(problem % connector_type)
        return 2
    end

    begin
        connector_runner = connector_runner_class.new(config)
    rescue => ex
        @log.error("#{ex.message}")
        problem = 'Unable to obtain an instance of the %sRunner class.  Is your vcseif gem properly installed?'
        @log.fatal(problem % connector_type)
        return 3
    end

    ret_code = 0
    blurtage = ""
    begin
        connector_runner.run()
    rescue VCSEIF_Exceptions::ConfigurationError => ex
        blurtage  = ex.verbiage
        err_text  = "ERROR: #{@script_name} detected a FATAL configuration error, #{blurtage}."
        log_entry = "FATAL: Configuration error: #{blurtage}"
        recordAnomaly(ex, err_text, blurtage, log_entry)
        ret_code = 4
    rescue VCSEIF_Exceptions::UnrecoverableException => ex
        blurtage  = ex.verbiage
        err_text  = "ERROR: #{@script_name}, #{blurtage}."
        log_entry = "UnrecoverableException: #{blurtage}"
        recordAnomaly(ex, err_text, blurtage, log_entry)
        ret_code = 5
    rescue VCSEIF_Exceptions::OperationalError => ex
        blurtage  = ex.verbiage
        err_text  = "ERROR: #{@script_name} detected an OperationalError condition"
        log_entry = "OperationalError: #{blurtage}"
        recordAnomaly(ex, err_text, blurtage, log_entry)
        ret_code = 6
    rescue Exception => ex
        blurtage  = ex.message
        err_text  = "ERROR: #{@script_name} detected an Exception condition"
        recordAnomaly(ex, err_text, blurtage, "")
        ret_code = 9
    end

    return ret_code
end

#execute(args) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/vcseif/vcs_connector_driver.rb', line 45

def execute(args)
    @log = RallyLogger.new(@uber_log_name)
    @log.info("#{@script_name} started with parameters of: #{args.join(', ')}")

    ret_code = 0
    for config_name in args do
        config = getConnectorConfiguration(config_name)
        next if config.nil?
        ret_code = delegateToConnectorRunner(config)
        @log.info("finished processing config #{config_name} with status code of #{ret_code}")
    end
    @log.info("#{@script_name} COMPLETED")
    return 0
end

#getConnectorConfiguration(config_name) ⇒ Object



60
61
62
63
64
65
66
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
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/vcseif/vcs_connector_driver.rb', line 60

def getConnectorConfiguration(config_name)
    """
        Allow a config_name to map to a file with the same value 
        exsiting within the ENV[VCS_APP_ROOT]/configs directory.
        If such a file exists, it must be in YAML format and have at least 3 sections.
        Allow specifying a config_name by 'name', 'name.yml', 'name.yaml' or 'name.txt'.
    """
    # suffix-full options: in ENV[VCS_APP_ROOT]/configs subdir
    # suffix-less options: try '%s.yml'  % config_name in ENV[VCS_APP_ROOT]/configs subdir
    #                      try '%s.yaml' % config_name in ENV[VCS_APP_ROOT]/configs subdir
    #                      try '%s.txt'  % config_name in ENV[VCS_APP_ROOT]/configs subdir
    #  TODO: consider cleaning this processing up in another method devoted solely to the sussing the options above

    config_dir = "%s/configs" % ENV[VCS_APP_ROOT]
    ext_name = File.extname(config_name)
    if ext_name != ""  # suffix-full
        config_file_path = '%s/%s' % [config_dir, config_name]
        if Dir.glob("#{config_dir}/*").include?(config_name)
            config_name = config_name.sub(/#{ext_name}$/, '')
        end
    else  # suffix-less
        conf_root = "%s/%s" % [config_dir, config_name]
        config_file_path = conf_root
        if File.exists?('%s.yml' % conf_root)
            config_file_path = "%s.yml" % conf_root
        elsif File.exists?('%s.yaml' % conf_root)
            config_file_path = "%s.yaml" % conf_root
        elsif File.exists?('%s.txt' % conf_root)
            config_file_path = "%s.txt" % conf_root
        end
    end

    if not File.exists?(config_file_path)
      problem = "Config file for name: %s not found" % config_name
      @log.error(problem)
      return nil
    end

    if not File.file?(config_file_path)
      problem = 'Config file: %s is not a file' % config_file_path
      @log.error(problem)
      return nil
    end

    if not File.readable?(config_file_path)
      problem = 'Config file: %s not a readable file' % config_file_path
      @log.error(problem)
      return nil
    end

    config = loadConfiguration(config_file_path)
    config_file_name = config_file_path.split("/")[-1]
    if not config.nil?
        config['ConfigName'] = File.basename(config_file_name, '.*')
        config['ConfigPath'] = config_file_path
    end

    return config
end

#loadConfiguration(config_file_path) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/vcseif/vcs_connector_driver.rb', line 120

def loadConfiguration(config_file_path)
    begin
      content = "" and File.open(config_file_path, 'r') { |f| content = f.read() }
      # As YAML forbids tab chars, we have to rid the content of tab chars,
      # but emit a log warning that tabs were detected and transformed if we do
      if content =~ /\t/
        content.gsub!(/\t/, '    ')  
        @log.warning('One or more tab characters (\\t) was detected in the config file and transformed to spaces.  YAML does not allow tab characters.')
      end
      config = YAML.load(content)
      raise "config file: #{} is not a valid YAML file" unless config.class.name == 'Hash' 
      sections = config.keys
    rescue Exception => ex
       @log.error("Unable to load YAML from config_file '%s' : %s" % [config_file_path, ex.message])
       return nil
    end

    if config.keys.length < NUMBER_OF_REQUIRED_VCS_CONNECTOR_SECTIONS
       @log.error("config '%s' not in required YAML format or has too few sections" % config_file_path)
       return nil
    end

    return config
end

#rationalizeEnvironmentObject



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/vcseif/vcs_connector_driver.rb', line 30

def rationalizeEnvironment()
    # set vcs_app_root to the directory where either <vcs>2rally.exe or <vcs>2rally.rb is located
    if ENV.keys.include?('OCRA_EXECUTABLE')
      vcs_app_root = File.dirname(ENV['OCRA_EXECUTABLE'].gsub(/\\/, '/'))
    else
      vcs_app_root = File.expand_path(File.dirname($PROGRAM_NAME))
    end

    unless ENV.keys.include?(VCS_APP_ROOT)
      ENV[VCS_APP_ROOT] = vcs_app_root  # make this available everywhere...
      $LOAD_PATH.unshift(vcs_app_root)
      $LOAD_PATH.unshift("#{vcs_app_root}/lib")
    end
end

#recordAnomaly(ex, issue, blurtage, log_entry) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
# File 'lib/vcseif/vcs_connector_driver.rb', line 208

def recordAnomaly(ex, issue, blurtage, log_entry)
    $stderr.write("%s\n" % issue)
    #$stderr.write("ERROR: #{blurtage}\n") if !blurtage.empty?
    #$stderr.write("#{ex.message}\n")
    @log.error(log_entry) if not log_entry.empty?

    @log.entry("ERROR: #{blurtage} #{ex.message}")
    @log.entry(ex.backtrace.join("\n"))
    @log.write("call chain follows:")
    # blurt out a formatted stack trace in outermost to innermost call sequence
    for bt_line in ex.backtrace.reverse do
        short_bt =  bt_line.sub(/#{Dir.pwd}\//, "... /")
        short_bt = short_bt.sub(/^.*\/gems\//,  "... gems/")
           @log.write("    #{short_bt}") 
        $stderr.write("    #{short_bt}\n")
    end
    @log.write("!!!") 
end