winter 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -13,6 +13,9 @@
13
13
  # under the License.
14
14
 
15
15
  require 'winter/logger'
16
+ require 'fileutils'
17
+ require 'digest/md5'
18
+ require 'net/http'
16
19
 
17
20
  module Winter
18
21
 
@@ -37,15 +40,100 @@ module Winter
37
40
  @verbose = false
38
41
  @destination = '.'
39
42
  end
43
+
44
+ def get
45
+ if ! File.directory?(@destination)
46
+ $LOG.debug "Create the destination folder if its not already there."
47
+ FileUtils.mkdir_p @destination
48
+ end
49
+ #Try and get file in a couple different ways. If we succeed then move on.
50
+ #Artifacts in your local .m2 ALWAYS take precedence over a remote artifact...
51
+ #Unless we fail so hard we end up using mvn as a last ditched effort.
52
+ success = getLocalM2
53
+ success = getRestArtifactory if ! success and ! @offline
54
+ success = getMaven if ! success and system( 'which mvn > /dev/null' )
55
+ if ! success
56
+ $LOG.info "[failed] #{outputFilename}"
57
+ end
58
+ return success
59
+ end
60
+
61
+ def artifactory_path
62
+ "#{@group.gsub(/\./,'/')}/#{@artifact}/#{@version}/#{@artifact}-#{@version}.#{@package}"
63
+ end
40
64
 
41
- def getMaven
42
- dest_file = File.join(@destination,outputFilename)
65
+ def dest_file
66
+ File.join(@destination,outputFilename)
67
+ end
68
+
69
+ def restRequest(uri)
70
+ response = Net::HTTP.get_response(uri)
71
+ return response.body if response.is_a?(Net::HTTPSuccess)
72
+ $LOG.debug "#{outputFilename}: Rest request to #{uri.inspect} #{response.inspect}"
73
+ raise "Rest request got a bad response code back [#{response.code}]"
74
+ end
75
+
76
+ def getRestArtifactory
77
+ log_prefix = '[remote] '
78
+ $LOG.debug "#{log_prefix}#{outputFilename}: Attempting to fetch via the artifactory rest api."
79
+ #Loop through all the repos until something works
80
+ @repositories.each { |repo|
81
+ begin
82
+ open(dest_file,"wb") { |file|
83
+ file.write(restRequest(URI.parse("#{repo}/#{artifactory_path}")))
84
+ }
85
+ rescue SocketError,RuntimeError => e # :( Maybe do better handling later.
86
+ $LOG.error "#{log_prefix}#{outputFilename}: Unable to fetch Artifact from #{repo}/#{artifactory_path}"
87
+ $LOG.debug e
88
+ next
89
+ end
90
+ #Check to make sure the md5sum of what we downloaded matches what's in the artifactory.
91
+ begin
92
+ artifactory_md5 = restRequest(URI.parse("#{repo}/#{artifactory_path}.md5"))
93
+ my_md5 = Digest::MD5.file("#{dest_file}").hexdigest
94
+ rescue SocketError, RuntimeError => e # :( Do better handling later.
95
+ $LOG.error "#{log_prefix}#{outputFilename}: Blew up while attempting to get md5s."
96
+ else
97
+ if artifactory_md5 == my_md5
98
+ $LOG.debug "#{log_prefix}#{outputFilename}: Successfully fetched via artifactory rest api."
99
+ $LOG.info "#{log_prefix}#{outputFilename}"
100
+ return true
101
+ end
102
+ $LOG.error "#{log_prefix}#{outputFilename}: Comparing remote MD5 #{artifactory_md5} to local md5 #{my_md5} (#{dest_file})"
103
+ $LOG.error "#{log_prefix}#{outputFilename}: Comparison failed. Deleting the 'bad' jar and moving on."
104
+ FileUtils.rm(dest_file)
105
+ end
106
+ }
107
+ return false
108
+ end
109
+
110
+ def getLocalM2
111
+ log_prefix = "[local] "
112
+ begin
113
+ artifact = "#{ENV["HOME"]}/.m2/repository/#{artifactory_path}"
114
+ $LOG.debug "#{log_prefix}#{outputFilename}: Copying #{artifact} to #{dest_file}"
115
+ FileUtils.cp(artifact,dest_file)
116
+ rescue Errno::ENOENT
117
+ $LOG.debug "#{log_prefix}#{outputFilename}: #{artifact} does not exist."
118
+ rescue SystemCallError => e
119
+ $LOG.error "#{log_prefix}#{outputFilename}: Failed to copy file from local m2 repository."
120
+ $LOG.error e
121
+ else #Yay we got it
122
+ $LOG.debug "#{log_prefix}#{outputFilename}: Successfully copied from local m2 repository."
123
+ $LOG.info "#{log_prefix}#{outputFilename}"
124
+ return true
125
+ end
126
+ return false
127
+ end
43
128
 
129
+ #Depricated because its slow and expensive to use... leaving it here for now.
130
+ def getMaven
131
+ log_prefix = "[maven] "
44
132
  c = "mvn org.apache.maven.plugins:maven-dependency-plugin:2.5:get "
45
133
  c << " -DremoteRepositories=#{@repositories.join(',').shellescape}"
46
134
  c << " -Dtransitive=#{@transative}"
47
135
  c << " -Dartifact=#{@group.shellescape}:#{@artifact.shellescape}:#{@version.shellescape}:#{@package.shellescape}"
48
- c << " -Ddest=#{dest_file.shellescape}"
136
+ c << " -Ddest=#{dest_file.shellescape} &>/dev/null"
49
137
 
50
138
  if @offline
51
139
  c << " --offline"
@@ -56,13 +144,12 @@ module Winter
56
144
  c << " -q"
57
145
  end
58
146
 
59
- $LOG.debug c
60
147
  result = system( c )
61
148
  if result == false
62
- $LOG.error("Failed to retrieve artifact: #{@group}:#{@artifact}:#{@version}:#{@package}")
149
+ $LOG.error("#{log_prefix}#{outputFilename}: Failed to retrieve artifact. -- #{c}")
63
150
  else
64
- $LOG.info "#{@group}:#{@artifact}:#{@version}:#{@package}"
65
- $LOG.debug dest_file
151
+ $LOG.info "#{log_prefix}#{@group}:#{@artifact}:#{@version}:#{@package}"
152
+ $LOG.debug "#{log_prefix}#{dest_file}"
66
153
  end
67
154
  return result
68
155
  end
@@ -144,7 +144,9 @@ module Winter
144
144
  end
145
145
 
146
146
  def conf( dir )
147
- process_templates( dir, File.join(WINTERFELL_DIR,RUN_DIR,@name,'conf') )
147
+ #We strip off the final / to normalize the input.
148
+ #If we don't do that then process_templates will end up with crazy file names.
149
+ process_templates( dir.sub(/\/$/,""), File.join(WINTERFELL_DIR,RUN_DIR,@name,'conf') )
148
150
  end
149
151
 
150
152
  def read( file )
@@ -60,30 +60,32 @@ module Winter
60
60
  #I hate waiting so this is going to become faster.
61
61
  max_threads = 10 #make this configurable later.
62
62
  active_threads = 0
63
+ error = false
63
64
  Signal.trap("CHLD") do
64
65
  #Reap everything you possibly can.
65
66
  begin
66
- pid = waitpid(-1, Process::WNOHANG)
67
- #puts "reaped #{pid}" if pid
68
- active_threads -= 1 if pid
67
+ pid, status = waitpid2(-1, Process::WNOHANG)
68
+ if pid
69
+ active_threads -= 1
70
+ error = true if status.exitstatus > 0
71
+ end
69
72
  rescue Errno::ECHILD
70
73
  break
71
74
  end while pid
72
75
  end
73
76
 
74
- error = false
75
77
  dependencies.each do |dep|
76
78
  while (active_threads >= max_threads) do
77
79
  $LOG.debug "Total active threads: #{active_threads}"
78
- #$LOG.debug "threads: #{active_threads}"
79
80
  sleep 1
80
81
  end
81
- #File.join(@destination,"#{@artifact}-#{@version}.#{@package}")
82
82
  if !File.exists?(File.join(dep.destination,dep.outputFilename))
83
83
  active_threads += 1
84
84
  fork do
85
- result = dep.getMaven
86
- error = true if result == false
85
+ #Get the dependency and Vomit up an error code if we fail
86
+ #If we don't do this then the main proc has no idea the build
87
+ # was garbage
88
+ exit 1 unless dep.get
87
89
  end
88
90
  else
89
91
  $LOG.info "Already have #{dep.outputFilename}"
@@ -34,6 +34,7 @@ module Winter
34
34
  rescue Exception=>e
35
35
  $LOG.error "Could not fetch winter configuration from : #{url}"
36
36
  $LOG.debug e
37
+ exit(-1)
37
38
  end
38
39
 
39
40
  extract_jar file
@@ -61,6 +62,7 @@ module Winter
61
62
  rescue Exception=>e
62
63
  $LOG.error "#{file} is corrupt or invalid."
63
64
  $LOG.debug e
65
+ exit(-1)
64
66
  end
65
67
 
66
68
  cleanup file
@@ -70,86 +70,39 @@ module Winter
70
70
  @directives.merge! dsl[:directives]
71
71
 
72
72
  java_cmd = generate_java_invocation
73
- java_cmd << " > #{@config['console']} 2>&1"
73
+
74
+ if @config['daemonize']
75
+ java_cmd << " 2>&1 " #"don't eat the log thats evil"
76
+ else
77
+ java_cmd << " > #{@config['console']} 2>&1"
78
+ end
74
79
  $LOG.debug java_cmd
75
80
 
76
- # execute
81
+ #
77
82
  if( File.exists?(File.join(@service_dir, "pid")) )
78
83
  $LOG.error "PID file already exists. Is the process running?"
79
84
  exit
80
85
  end
81
- pid_file = File.open(File.join(@service_dir, "pid"), "w")
82
86
 
83
87
  # Normally, we'd just use Process.daemon for ruby 1.9, but for some
84
88
  # reason the OSGi container we're using crashes when the CWD is changed
85
89
  # to '/'. So, we'll just leave the CWD alone.
86
90
  #Process.daemon(Dir.getwd,nil)
87
-
91
+
92
+ exec(java_cmd) if @config['daemonize'] #Let the child eat winter so things are awesome for daemontools
93
+ #We never hit the past this point if we went to daemonize mode.
94
+
95
+ #If we're not trying to run as a daemon just fork and let the subprocess be eaten
88
96
  java_pid = fork do
89
97
  exec(java_cmd)
90
98
  end
91
99
 
100
+ pid_file = File.open(File.join(@service_dir, "pid"), "w")
92
101
  pid = java_pid
93
- pid = Process.pid if @config['daemonize']
94
102
  pid_file.write(pid)
95
103
  pid_file.close
96
104
 
97
105
  $LOG.info "Started #{@config['service']} (#{pid})"
98
-
99
- if( @config['daemonize'] )
100
- stay_resident(java_pid,winterfile)
101
- end
102
- end
103
-
104
- def stay_resident( child_pid, winterfile )
105
- interrupted = false
106
-
107
- #TERM, CONT STOP HUP ALRM INT and KILL
108
- Signal.trap("EXIT") do
109
- $LOG.debug "EXIT Terminating... #{$$}"
110
- interrupted = true
111
- begin
112
- stop winterfile
113
- # not working...
114
- # Process.getpgid child_pid
115
- # Process.kill child_pid #skipped if process is alredy dead
116
- rescue
117
- $LOG.debug "Child pid (#{child_pid}) is already gone."
118
- end
119
- end
120
- Signal.trap("HUP") do
121
- $LOG.debug "HUP Terminating... #{$$}"
122
- interrupted = true
123
- end
124
- Signal.trap("TERM") do
125
- $LOG.debug "TERM Terminating... #{$$}"
126
- interrupted = true
127
- end
128
- Signal.trap("KILL") do
129
- $LOG.debug "KILL Terminating... #{$$}"
130
- interrupted = true
131
- end
132
- Signal.trap("CONT") do
133
- $LOG.debug "CONT Terminating... #{$$}"
134
- interrupted = true
135
- end
136
- Signal.trap("ALRM") do
137
- $LOG.debug "ALRM Terminating... #{$$}"
138
- interrupted = true
139
- end
140
- Signal.trap("INT") do
141
- $LOG.debug "INT Terminating... #{$$}"
142
- interrupted = true
143
- end
144
- Signal.trap("CHLD") do
145
- $LOG.debug "CHLD Terminating... #{$$}"
146
- interrupted = true
147
- end
148
- #Process.detach(pid)
149
-
150
- while 1
151
- exit 0 if interrupted
152
- end
153
106
  end
154
107
 
155
108
  def find_java
@@ -172,7 +125,7 @@ module Winter
172
125
  felix_jar = File.join(@felix.destination,"#{@felix.artifact}-#{@felix.version}.#{@felix.package}")
173
126
 
174
127
  # start building the command
175
- cmd = [ "#{java_bin.shellescape} -server" ]
128
+ cmd = [ "exec #{java_bin.shellescape} -server" ]
176
129
  cmd << (@config["64bit"]==true ? " -d64 -XX:+UseCompressedOops":'')
177
130
  cmd << " -XX:MaxPermSize=256m -XX:NewRatio=3"
178
131
  cmd << " -Xmx#{@config['jvm.mx']}"
@@ -31,14 +31,17 @@ module Winter
31
31
  service = f_pid.sub( %r{#{WINTERFELL_DIR}/#{RUN_DIR}/([^/]+)/pid}, '\1')
32
32
  pid_file = File.open(f_pid, "r")
33
33
  pid = pid_file.read().to_i
34
-
35
- begin
36
- Process.getpgid( pid )
37
- running = "Running"
38
- rescue Errno::ESRCH
39
- running = "Dangling pid file : #{f_pid}"
34
+
35
+ if pid <= 0
36
+ running = "A pid of zero was found... something bad is going on"
37
+ else
38
+ begin
39
+ Process.getpgid( pid )
40
+ running = "Running"
41
+ rescue Errno::ESRCH
42
+ running = "Dangling pid file : #{f_pid}"
43
+ end
40
44
  end
41
-
42
45
  services["#{service} (#{pid})"] = "#{running}"
43
46
  end
44
47
 
@@ -31,23 +31,39 @@ module Winter
31
31
 
32
32
  @service_dir = File.join(File.split(winterfile)[0],RUN_DIR,service)
33
33
  f_pid = File.join(@service_dir, "pid")
34
-
35
34
  if File.exists?(f_pid)
36
- pid = nil;
35
+ pid = nil
36
+ pid_string = nil
37
37
  File.open(f_pid, "r") do |f|
38
- pid = f.read().to_i
38
+ pid_string = f.read()
39
+ pid = pid_string.to_i
39
40
  end
40
41
 
41
- begin
42
- pgid = Process.getpgid pid
43
- pgid *= -1 if !config['daemonize']
44
- Process.kill("TERM", pgid)
45
- rescue => e
46
- $LOG.debug( e )
47
- $LOG.info( "Process #{pid} does not exist. Removing pid file." )
42
+ #Send a TERM to the container if we have a non bogus pid
43
+ if pid > 0
44
+ begin
45
+ $LOG.info("Attempting to terminate #{pid}")
46
+ Process.kill("TERM", pid)
47
+ rescue => e
48
+ $LOG.debug( e )
49
+ $LOG.info("Unable to control process with pid #{pid}.")
50
+ $LOG.info("Either your user has insufficent rights, or the process doesn't exist")
51
+ end
52
+
53
+ #Wait for things to stop.
54
+ begin
55
+ $LOG.info("Waiting for the process with pid #{pid} to stop")
56
+ sleep 1 while Process.kill(0,pid)
57
+ rescue => e
58
+ $LOG.info("The container seems to have exited.")
59
+ end
60
+ else
61
+ $LOG.info("An invalid pid value was found in the pid file. (\"#{pid_string}\" was parsed as #{pid})")
48
62
  end
49
-
63
+
64
+ #If things worked (Or we couldn't find a pid)... then we're good to delete.
50
65
  begin
66
+ $LOG.info("Removing the pid file")
51
67
  File.unlink(f_pid)
52
68
  rescue
53
69
  $LOG.error( "Error deleting PID file." )
@@ -13,5 +13,5 @@
13
13
  # under the License.
14
14
 
15
15
  module Winter
16
- VERSION = "0.0.3"
16
+ VERSION = "0.1.0"
17
17
  end
@@ -34,7 +34,8 @@ describe Winter do
34
34
  begin
35
35
  lambda {
36
36
  cli = Winter::CLI.new
37
- cli.fetch 'com.liveops.sample', 'winter', '1.0.0-SNAPSHOT'
37
+ cli.fetch 'com.liveops.sample', 'sample', '1.0.0-SNAPSHOT'
38
+ #cli.fetch 'http://artifactory:8081/artifactory/libs-all/', 'sample', '1.0.0-SNAPSHOT'
38
39
  }.should_not raise_error
39
40
  end
40
41
  end
@@ -66,7 +67,7 @@ describe Winter do
66
67
  it "Build a service from a manifest" do
67
68
  begin
68
69
  lambda {
69
- args = ["build", "spec/sample_data/Winterfile", "--clean", "--local"]
70
+ args = ["build", "spec/sample_data/Winterfile", "--clean"]
70
71
  cli = Winter::CLI.start( args )
71
72
  }.should_not raise_error
72
73
  Dir["run/default/libs"].include? "maven-dependency-plugin-2.5.jar"
@@ -79,7 +80,7 @@ describe Winter do
79
80
  context "start, status and stop " do
80
81
  before "build service to get artifacts." do
81
82
  lambda {
82
- args = ["build", "spec/sample_data/Winterfile", "--clean", "--local"]
83
+ args = ["build", "spec/sample_data/Winterfile", "--clean"]
83
84
  cli = Winter::CLI.start( args )
84
85
  }.should_not raise_error
85
86
  end
@@ -90,12 +91,8 @@ describe Winter do
90
91
  lambda {
91
92
  Winter::CLI.start ["start"]
92
93
  Winter::CLI.start ["status"]
93
- #Winter::CLI.start ["stop"]
94
+ Winter::CLI.start ["stop"]
94
95
  }.should_not raise_error
95
- #lambda {
96
- # puts "TRYING STOP"
97
- # Winter::CLI.start ["stop"]
98
- #}.should_not raise_error
99
96
  end
100
97
  end
101
98
  end
@@ -113,7 +110,7 @@ describe Winter do
113
110
 
114
111
  after do
115
112
  Dir.chdir(File.split("spec/sample_data/Winterfile")[0]) do
116
- #Winter::CLI.start ["stop"]
113
+ Winter::CLI.start ["stop"]
117
114
  end
118
115
 
119
116
  FileUtils.rm_r( "spec/sample_data/run" )
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.required_ruby_version = '>= 1.9.1'
22
22
 
23
- spec.add_runtime_dependency "thor", "~> 0.18.0"
23
+ spec.add_runtime_dependency "thor", "~> 0.14.0"
24
24
  spec.add_development_dependency "bundler", "~> 1.3"
25
25
  spec.add_development_dependency "rake"
26
26
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: winter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-30 00:00:00.000000000 Z
12
+ date: 2014-04-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: thor
@@ -18,7 +18,7 @@ dependencies:
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 0.18.0
21
+ version: 0.14.0
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: 0.18.0
29
+ version: 0.14.0
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: bundler
32
32
  requirement: !ruby/object:Gem::Requirement