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.
- data/lib/winter/dependency.rb +94 -7
- data/lib/winter/dsl.rb +3 -1
- data/lib/winter/service/build.rb +10 -8
- data/lib/winter/service/fetch.rb +2 -0
- data/lib/winter/service/start.rb +14 -61
- data/lib/winter/service/status.rb +10 -7
- data/lib/winter/service/stop.rb +27 -11
- data/lib/winter/version.rb +1 -1
- data/spec/cli_spec.rb +6 -9
- data/winter.gemspec +1 -1
- metadata +4 -4
data/lib/winter/dependency.rb
CHANGED
@@ -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
|
42
|
-
|
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
|
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
|
data/lib/winter/dsl.rb
CHANGED
@@ -144,7 +144,9 @@ module Winter
|
|
144
144
|
end
|
145
145
|
|
146
146
|
def conf( dir )
|
147
|
-
|
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 )
|
data/lib/winter/service/build.rb
CHANGED
@@ -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 =
|
67
|
-
|
68
|
-
|
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
|
-
|
86
|
-
|
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}"
|
data/lib/winter/service/fetch.rb
CHANGED
@@ -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
|
data/lib/winter/service/start.rb
CHANGED
@@ -70,86 +70,39 @@ module Winter
|
|
70
70
|
@directives.merge! dsl[:directives]
|
71
71
|
|
72
72
|
java_cmd = generate_java_invocation
|
73
|
-
|
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
|
-
#
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
|
data/lib/winter/service/stop.rb
CHANGED
@@ -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
|
-
|
38
|
+
pid_string = f.read()
|
39
|
+
pid = pid_string.to_i
|
39
40
|
end
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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." )
|
data/lib/winter/version.rb
CHANGED
data/spec/cli_spec.rb
CHANGED
@@ -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', '
|
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"
|
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"
|
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
|
-
|
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
|
-
|
113
|
+
Winter::CLI.start ["stop"]
|
117
114
|
end
|
118
115
|
|
119
116
|
FileUtils.rm_r( "spec/sample_data/run" )
|
data/winter.gemspec
CHANGED
@@ -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.
|
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
|
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-
|
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.
|
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.
|
29
|
+
version: 0.14.0
|
30
30
|
- !ruby/object:Gem::Dependency
|
31
31
|
name: bundler
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|