Permalink
Browse files

Implement most of ConfCreator, ProcessDefinitoin, ProcessRunner, and …

…Support
  • Loading branch information...
Brandon Tilley
Brandon Tilley committed Jan 6, 2011
1 parent 89a225d commit 66302b64aa6927d45ee33c7ed34312d80e630d73
@@ -0,0 +1,48 @@
+require 'dataloaderb/process_definition'
+require 'dataloaderb/support'
+require 'erb'
+require 'fileutils'
+require 'tmpdir'
+require 'yaml'
+
+module Dataloaderb
+ class ConfCreator
+ attr_reader :processes
+
+ # Create a new instance of a ConfCreator
+ def initialize(*yamls)
+ @processes = []
+ build_process_definitions(yamls)
+ end
+
+ def build_process_definitions(yamls)
+ yamls.each do |yaml|
+ proc_def = Dataloaderb::ProcessDefinition.new(yaml)
+ @processes << proc_def
+ end
+ end
+
+ # Return the text for an Apex Data Loader process-conf.xml file
+ def to_xml
+ # TODO: Don't unindent <%%
+ erb = ERB.new File.new(File.expand_path('templates/process-conf.xml.erb',File.dirname(__FILE__))).readlines.join.gsub(/^\s+<%/, "<%"), nil, '<>'
+ erb.result(get_binding)
+ end
+
+ private
+
+ def get_binding
+ binding
+ end
+
+ # def write_xml(xml)
+ # base_tmpdir = @options[:tmp_dir] || Dir.tmpdir
+ # dir = Dir.mktmpdir(['', Dataloaderb::Support.unique_id], base_tmpdir)
+ # begin
+ # ##
+ # ensure
+ # FileUtils.remove_entry_secure dir
+ # end
+ # end
+ end
+end
@@ -0,0 +1,35 @@
+module Dataloaderb
+ class ProcessDefinition
+
+ attr_reader :id
+ attr_reader :description
+ attr_reader :entries
+
+ # Create a new instance of a ConfCreator
+ def initialize(yaml)
+ @id = ''
+ @description = ''
+ @entries = {}
+ load_yaml(yaml)
+ end
+
+ def set(key, value)
+ @entries[key] = value
+ end
+
+ def get(key)
+ @entries[key]
+ end
+
+ # Load a process definition from a Yaml file
+ def load_yaml(yaml_file)
+ raise ArgumentError, "Cannot find file #{yaml_file}" unless File.exist?(yaml_file)
+ proc = YAML.load_file(yaml_file)
+ @id = proc['id']
+ @description = proc['description']
+ proc['properties'].each do |key, value|
+ self.set(key, value)
+ end
+ end
+ end
+end
@@ -1,4 +1,43 @@
-module DataLoaderb
+require 'dataloaderb/conf_creator'
+
+module Dataloaderb
class ProcessRunner
+ # Create the process runner and specify the path to
+ # the Apex Data Loader executable (batch) files.
+ def initialize(bin_path)
+ @bin_path = bin_path
+ end
+
+ # Run one or more processes. Specify the processes to run by passing
+ # one or more paths to process Yaml definitions.
+ def run(*yamls)
+ if yamls.empty? || yamls.flatten.empty?
+ raise ArgumentError, "You must pass at least one argument to Dataloaderb::ProcessRunner#run"
+ end
+
+ creator = Dataloaderb::ConfCreator.new(yamls)
+ end
+
+ def execute_process(process_name)
+ # @bin_path and @conf_path are full paths at this point
+ `#{get_process_execute_command}`
+ end
+
+ protected
+
+ # Given the path to the Apex Data Loader bin directory, the
+ # path to the folder with the process-conf.xml file, and the
+ # name of a process defined in the XML to run, return the
+ # command that the operating system needs to run to execute
+ # the process.
+ def get_process_execute_command(bin_path, conf_path, process_name)
+ "#{get_process_bat_path(bin_path)} #{conf_path} #{process_name}"
+ end
+
+ # Given the path to the Apex Data Loader bin directory, return
+ # the expanded path of the process.bat file to be executed.
+ def get_process_bat_path(bin_path)
+ File.expand_path "#{bin_path}/process.bat"
+ end
end
end
@@ -0,0 +1,18 @@
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+<beans>
+<% @processes.each do |proc| %>
+ <bean id="<%= proc.id %>"
+ class="com.salesforce.dataloader.process.ProcessRunner"
+ singleton="false">
+ <description><%= proc.description %></description>
+ <property name="name" value="<%= proc.id %>"/>
+ <property name="configOverrideMap">
+ <map>
+ <% proc.entries.each do |key, value| %>
+ <entry key="<%= key %>" value="<%= value %>"/>
+ <% end %>
+ </map>
+ </property>
+ </bean>
+<% end %>
+</beans>
@@ -0,0 +1,35 @@
+require 'rspec'
+require 'dataloaderb/conf_creator'
+require 'tmpdir'
+
+describe Dataloaderb::ConfCreator do
+ before :each do
+ @yamls = [
+ 'spec/fixtures/processes/sample_proc.yml'
+ ]
+ # ConfCreator#new expects multiple arguments, not an array, thus we splat
+ @creator = Dataloaderb::ConfCreator.new(*@yamls)
+ end
+
+ context "#build_process_definitions" do
+ it "should build a process definition for each yaml file" do
+ @creator.processes.count.should == 1
+ @creator = Dataloaderb::ConfCreator.new('spec/fixtures/processes/sample_proc.yml', 'spec/fixtures/processes/sample_proc.yml')
+ @creator.processes.count.should == 2
+ end
+ end
+
+ context "#to_xml" do
+ it "should create XML with the correct values" do
+ @creator.to_xml.include?('<entry key="sfdc.endpoint" value="https://www.salesforce.com"/>').should be_true
+ @creator.to_xml.include?('<bean id="firstUpsert"').should be_true
+ @creator.to_xml.include?('<description>Upsert of some data somewhere</description>').should be_true
+ end
+ end
+
+ context "#get_binding" do
+ it "should get an object of class Binding" do
+ @creator.send(:get_binding).class.should == Binding
+ end
+ end
+end
@@ -0,0 +1,36 @@
+require 'rspec'
+require 'dataloaderb/process_definition'
+require 'tmpdir'
+
+describe Dataloaderb::ProcessDefinition do
+ before :each do
+ @conf = Dataloaderb::ProcessDefinition.new('spec/fixtures/processes/sample_proc.yml')
+ end
+
+ context "#set/#get" do
+ it "should allow setting process conf variables via the XML entry key as a string" do
+ @conf.set('sfdc.endpoint', 'https://test.salesforce.com')
+ @conf.get('sfdc.endpoint').should == 'https://test.salesforce.com'
+ end
+
+ it "should allow setting process conf variables via the XML entry key as a symbol" do
+ @conf.set(:testsymbol, 'https://test.salesforce.com')
+ @conf.get(:testsymbol).should == 'https://test.salesforce.com'
+ end
+ end
+
+ context "#load_yaml" do
+ it "should raise an ArgumentError if the file doesn't exist" do
+ lambda {
+ @conf.load_yaml('fakefile.yaml')
+ }.should raise_error ArgumentError
+ end
+
+ it "should set the appropriate values via set()" do
+ @conf.load_yaml('spec/fixtures/processes/sample_proc.yml')
+ @conf.get('sfdc.timeoutSecs').should == '600'
+ @conf.get('sfdc.debugMessages').should == 'true'
+ @conf.get('process.initialLastRunDate').should == '2010-01-01T00:00:00.000-0800'
+ end
+ end
+end
@@ -0,0 +1,60 @@
+require 'rspec'
+require 'dataloaderb/process_runner'
+
+describe Dataloaderb::ProcessRunner do
+ before :each do
+ @runner = Dataloaderb::ProcessRunner.new('spec/fixtures/bin')
+ end
+
+ describe "#get_process_bat_path" do
+ it "should return the right process.bat path given a relative path" do
+ path = @runner.send(:get_process_bat_path, 'sf/bin')
+ path.should == "#{Dir.getwd}/sf/bin/process.bat"
+ end
+
+ it "should return the right process.bat path given a relative path with a trailing slash" do
+ path = @runner.send(:get_process_bat_path, 'sf/bin/')
+ path.should == "#{Dir.getwd}/sf/bin/process.bat"
+ end
+
+ it "should return the right process.bat path given an absolute path" do
+ path = @runner.send(:get_process_bat_path, '/sf/bin')
+ path.should == "/sf/bin/process.bat"
+ end
+
+ it "should return the right process.bat path given an absolute path with a trailing slash" do
+ path = @runner.send(:get_process_bat_path, '/sf/bin/')
+ path.should == "/sf/bin/process.bat"
+ end
+ end
+
+ describe "#get_process_execute_command" do
+ it "should return the correct execution command" do
+ path = @runner.send(:get_process_execute_command, "sf/bin", "myconf", "someUpserts")
+ ex_path = @runner.send(:get_process_bat_path, "sf/bin")
+ path.should == "#{ex_path} myconf someUpserts"
+ end
+ end
+
+ context "#run" do
+ it "should raise an exception if no arguments are passed" do
+ lambda {
+ @runner.run
+ }.should raise_error ArgumentError
+ end
+
+ it "should raise an exception if an empty array is passed" do
+ lambda {
+ @runner.run([])
+ }.should raise_error ArgumentError
+ end
+ end
+
+ describe "#execute_process" do
+ it "should return the result of the executable" do
+ @runner.stub!(:get_process_execute_command).and_return("./spec/fixtures/bin/test.sh")
+ result = @runner.execute_process 'fixutres/processes/sample_proc.yml'
+ result.strip.should == "result of process"
+ end
+ end
+end
@@ -0,0 +1,2 @@
+#!/bin/bash
+echo "result of process"
@@ -0,0 +1,26 @@
+id: 'firstUpsert'
+description: 'Upsert of some data somewhere'
+properties:
+ # endpoint config
+ sfdc.endpoint: 'https://www.salesforce.com'
+ sfdc.username: 'xxxxxxxxxx@xxxxxxxxxx.xxx'
+ sfdc.password: 'xxxxxxxxxxxxxxxxxxxxxxxxx'
+ process.encryptionKeyFile: 'C:/salesforce/dataloader/enc_pass.key'
+
+ # operation config
+ sfdc.timeoutSecs: '600'
+ sfdc.loadBatchSize: '100'
+ sfdc.externalIdField: 'Custom_Field__c'
+ sfdc.entity: 'Account'
+ process.operation: 'upsert'
+ process.mappingFile: '//shared/salesforce/upserts/first.Mapping.sdl'
+ dataAccess.name: '//shared/salesforce/upserts/first.csv'
+ dataAccess.type: 'csvRead'
+
+ # logging config
+ sfdc.debugMessages: 'true'
+ process.statusOutputDirectory: '//shared/salesforce/upserts/first/lastrun'
+
+ # misc config
+ process.enableLastRunOutput: 'false'
+ process.initialLastRunDate: '2010-01-01T00:00:00.000-0800'
View
@@ -0,0 +1 @@
+# spec helpers

0 comments on commit 66302b6

Please sign in to comment.