winter 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|