jenkins-peace 1.0.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.
@@ -0,0 +1,71 @@
1
+ require 'ruby-progressbar'
2
+ require 'net/http'
3
+ require 'uri'
4
+
5
+ module Jenkins
6
+ module Peace
7
+ class ContentDownloader
8
+
9
+ attr_reader :target_file
10
+ attr_reader :logger
11
+
12
+
13
+ def initialize(target_file, logger)
14
+ @target_file = target_file
15
+ @logger = logger
16
+ end
17
+
18
+
19
+ def download(url, limit = 10)
20
+ raise ArgumentError, 'too many HTTP redirects' if limit == 0
21
+
22
+ start_http_session(url) do |http, uri|
23
+ response = http.request_head(uri.path)
24
+ case response
25
+ when Net::HTTPSuccess
26
+ download_content(url)
27
+ when Net::HTTPRedirection
28
+ redirect = response['location']
29
+ logger.info "Redirected to : '#{redirect}'"
30
+ download(redirect, limit - 1)
31
+ else
32
+ logger.error response.value
33
+ end
34
+ end
35
+ rescue => e
36
+ logger.error "Error while downloading '#{url}' : #{e.message}"
37
+ end
38
+
39
+
40
+ def download_content(url)
41
+ logger.info "Downloading : '#{url}'"
42
+ start_http_session(url) do |http, uri|
43
+ response = http.request_head(uri.path)
44
+ progressbar = build_progress_bar(response['content-length'].to_i)
45
+ File.open(target_file, 'wb') do |file|
46
+ http.get(uri.path) do |chunk|
47
+ file.write chunk
48
+ progressbar.progress += chunk.length
49
+ end
50
+ end
51
+ end
52
+ rescue => e
53
+ logger.error "Error while downloading '#{url}' : #{e.message}"
54
+ end
55
+
56
+
57
+ def build_progress_bar(total)
58
+ ProgressBar.create(title: 'Downloading', starting_at: 0, total: total, format: '%a |%b>%i| %p%% %t')
59
+ end
60
+
61
+
62
+ def start_http_session(url)
63
+ uri = URI(url)
64
+ Net::HTTP.start(uri.host, uri.port) do |http|
65
+ yield http, uri
66
+ end
67
+ end
68
+
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,86 @@
1
+ module Jenkins
2
+ module Peace
3
+ module ThorExtensions
4
+
5
+ def warn(message)
6
+ say message, :yellow
7
+ end
8
+
9
+
10
+ def info(message)
11
+ say message, :green
12
+ end
13
+
14
+
15
+ def green(string)
16
+ set_color string, :green
17
+ end
18
+
19
+
20
+ def red(string)
21
+ set_color string, :red
22
+ end
23
+
24
+
25
+ def bold(string)
26
+ set_color string, :bold
27
+ end
28
+
29
+
30
+ def success_message
31
+ info 'Done !'
32
+ end
33
+
34
+
35
+ def yes_no_question(question, &block)
36
+ answer = yes? question, :bold
37
+ if answer
38
+ yield if block_given?
39
+ success_message
40
+ else
41
+ warn 'Canceled !'
42
+ end
43
+ end
44
+
45
+
46
+ def download_it_first!
47
+ warn "War file doesn't exist, you should install it first with : jenkins.peace install <version>"
48
+ warn 'Exiting !'
49
+ end
50
+
51
+
52
+ def check_conflicts_and_call_method(method, version, check_method = :exists?, &block)
53
+ war_file = Jenkins::Peace.build_war_file(version)
54
+ yield war_file if block_given?
55
+ message = "#{method.capitalize}ing Jenkins war file version : '#{version}'"
56
+ if war_file.send(check_method)
57
+ yes_no_question('Overwrite existing file?') do
58
+ info message
59
+ Jenkins::Peace.send(method, version, true)
60
+ end
61
+ else
62
+ info message
63
+ Jenkins::Peace.send(method, version)
64
+ success_message
65
+ end
66
+ end
67
+
68
+
69
+ def formated_war_files_list
70
+ list = []
71
+ Jenkins::Peace.list.each do |war_file|
72
+ installed = war_file.installed? ? green(war_file.installed?) : red(war_file.installed?)
73
+ version = war_file.latest_version? ? "latest (#{war_file.real_version})" : war_file.version
74
+ list << [green(version), war_file.location, war_file.classpath, installed]
75
+ end
76
+ list
77
+ end
78
+
79
+
80
+ def formated_headers
81
+ [bold('Version'), bold('Location'), bold('Classpath'), bold('Installed')]
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,5 @@
1
+ module Jenkins
2
+ module Peace
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,151 @@
1
+ require 'socket'
2
+
3
+ module Jenkins
4
+ module Peace
5
+ class WarFile
6
+
7
+ JENKINS_VERSION_REGEX = /jenkins-core-(1\.\d{3}).jar/
8
+
9
+ attr_reader :version
10
+ attr_reader :lib_path
11
+ attr_reader :base_path
12
+ attr_reader :base_url
13
+ attr_reader :server_path
14
+ attr_reader :logger
15
+
16
+ attr_reader :file_name
17
+ attr_reader :base_dir
18
+ attr_reader :lib_dir
19
+ attr_reader :klass_path
20
+ attr_reader :plugins_path
21
+ attr_reader :location
22
+ attr_reader :url
23
+
24
+
25
+ def initialize(version, opts = {})
26
+ @version = version
27
+ @lib_path = opts.fetch(:lib_path, '')
28
+ @base_path = opts.fetch(:base_path, '')
29
+ @base_url = opts.fetch(:base_url, '')
30
+ @server_path = opts.fetch(:server_path, '')
31
+ @logger = opts.fetch(:logger, $stdout)
32
+
33
+ @file_name = 'jenkins.war'
34
+ @base_dir = File.join(base_path, version)
35
+ @lib_dir = File.join(lib_path, version)
36
+ @klass_path = File.join(lib_dir, '**/*.jar')
37
+ @plugins_path = File.join(lib_dir, 'WEB-INF', 'plugins')
38
+ @location = File.join(base_dir, file_name)
39
+ @url = File.join(base_url, version, file_name)
40
+ end
41
+
42
+
43
+ def latest_version?
44
+ version == 'latest'
45
+ end
46
+
47
+
48
+ def real_version
49
+ return version unless latest_version?
50
+ klass = find_core_librairy
51
+ klass.nil? ? nil : klass.match(JENKINS_VERSION_REGEX)[1]
52
+ end
53
+
54
+
55
+ def classpath
56
+ File.join(lib_dir, 'WEB-INF', 'lib', "jenkins-core-#{real_version}.jar")
57
+ end
58
+
59
+
60
+ def exists?
61
+ File.exists?(location)
62
+ end
63
+
64
+
65
+ def unpacked?
66
+ File.exists?(lib_dir) && File.exists?(classpath)
67
+ end
68
+
69
+
70
+ def installed?
71
+ exists? && unpacked?
72
+ end
73
+
74
+
75
+ def download!
76
+ FileUtils.mkdir_p base_dir
77
+ fetch_content(url, location)
78
+ end
79
+
80
+
81
+ def install!
82
+ download!
83
+ unpack!
84
+ end
85
+
86
+
87
+ def remove!
88
+ FileUtils.rm_rf base_dir
89
+ FileUtils.rm_rf lib_dir
90
+ end
91
+
92
+
93
+ def unpack!
94
+ FileUtils.mkdir_p(lib_dir)
95
+ execute_command("cd #{lib_dir} && jar xvf #{location}")
96
+ end
97
+
98
+
99
+ def start!(options = {})
100
+ control = options.fetch(:control, 3002).to_i
101
+ kill = options.fetch(:kill, false)
102
+
103
+ if kill
104
+ TCPSocket.open('localhost', control) { |sock| sock.write('0') }
105
+ else
106
+ command = build_command_line(options)
107
+ exec(*command)
108
+ end
109
+ end
110
+
111
+
112
+ def build_command_line(options = {})
113
+ home = options.fetch(:home, server_path)
114
+ port = options.fetch(:port, 3001).to_i
115
+ control = options.fetch(:control, 3002).to_i
116
+ daemon = options.fetch(:daemon, false)
117
+ logfile = options.fetch(logfile, nil)
118
+
119
+ java_tmp = File.join(home, 'javatmp')
120
+ FileUtils.mkdir_p java_tmp
121
+
122
+ ENV['HUDSON_HOME'] = home
123
+ cmd = ['java', "-Djava.io.tmpdir=#{java_tmp}", '-jar', location]
124
+ cmd << '--daemon' if daemon
125
+ cmd << "--httpPort=#{port}"
126
+ cmd << "--controlPort=#{control}"
127
+ cmd << "--logfile=#{File.expand_path(logfile)}" if logfile
128
+ cmd
129
+ end
130
+
131
+
132
+ private
133
+
134
+
135
+ def execute_command(command)
136
+ `#{command}`
137
+ end
138
+
139
+
140
+ def fetch_content(url, target_file, limit = 10)
141
+ ContentDownloader.new(target_file, logger).download(url)
142
+ end
143
+
144
+
145
+ def find_core_librairy
146
+ Dir[File.join(lib_dir, 'WEB-INF', 'lib', '*.jar')].select { |f| f =~ JENKINS_VERSION_REGEX }.first
147
+ end
148
+
149
+ end
150
+ end
151
+ end
@@ -0,0 +1,7 @@
1
+ require 'yaml'
2
+ require 'jenkins/peace'
3
+ require 'jenkins/peace/thor_extensions'
4
+ require 'jenkins/peace/cli'
5
+ require 'jenkins/peace/console_logger'
6
+ require 'jenkins/peace/content_downloader'
7
+ require 'jenkins/peace/war_file'
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::Peace::ConsoleLogger do
4
+
5
+ def helper
6
+ Jenkins::Peace::ConsoleLogger.new([])
7
+ end
8
+
9
+
10
+ describe '.info' do
11
+ it 'should render colored message' do
12
+ # allow_any_instance_of(Jenkins::Peace::ConsoleLogger).to receive(:logger).and_return([])
13
+ expect(helper.info('foo')).to eq ["\e[32mfoo\e[0m\n"]
14
+ end
15
+ end
16
+
17
+
18
+ describe '.warn' do
19
+ it 'should render colored message' do
20
+ # allow_any_instance_of(Jenkins::Peace::ConsoleLogger).to receive(:logger).and_return([])
21
+ expect(helper.warn('bar')).to eq ["\e[33mbar\e[0m\n"]
22
+ end
23
+ end
24
+
25
+
26
+ describe '.error' do
27
+ it 'should render colored message' do
28
+ # allow_any_instance_of(Jenkins::Peace::ConsoleLogger).to receive(:logger).and_return([])
29
+ expect(helper.error('boo')).to eq ["\e[31mboo\e[0m\n"]
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,81 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::Peace::ContentDownloader do
4
+
5
+ VALID_URL = 'http://jenkins.mirror.isppower.de/war/1.629/jenkins.war'
6
+ REDIRECT_URL = 'http://mirrors.jenkins-ci.org/war/latest/jenkins.war'
7
+ INVALID_URL = 'http://mirrors.jenkins-ci.org/war/120000/jenkins.war'
8
+
9
+
10
+ def logger
11
+ Jenkins::Peace::ConsoleLogger.new([])
12
+ end
13
+
14
+
15
+ def build_content_downloader
16
+ Jenkins::Peace::ContentDownloader.new('/tmp/jenkins-test.war', logger)
17
+ end
18
+
19
+ let(:content_downloader) { build_content_downloader }
20
+
21
+
22
+ describe '#start_http_session' do
23
+ it 'should start a http session' do
24
+ uri = URI(VALID_URL)
25
+ expect(Net::HTTP).to receive(:start).with(uri.host, uri.port)
26
+ content_downloader.start_http_session(VALID_URL)
27
+ end
28
+ end
29
+
30
+
31
+ describe '#build_progress_bar' do
32
+ it 'should return a progress bar object' do
33
+ allow_any_instance_of(ProgressBar).to receive(:create)
34
+ content_downloader.build_progress_bar(100)
35
+ end
36
+ end
37
+
38
+
39
+ describe '#download' do
40
+ context 'when url is valid' do
41
+ it 'should download file' do
42
+ expect(content_downloader).to receive(:download_content).with(VALID_URL)
43
+ content_downloader.download(VALID_URL)
44
+ end
45
+ end
46
+
47
+ context 'when url is valid and redirecting' do
48
+ it 'should redirect' do
49
+ expect(content_downloader).to receive(:download_content)
50
+ expect_any_instance_of(Jenkins::Peace::ConsoleLogger).to receive(:info)
51
+ content_downloader.download(REDIRECT_URL)
52
+ end
53
+ end
54
+
55
+ context 'when url is invalid' do
56
+ it 'should not download file' do
57
+ expect_any_instance_of(Jenkins::Peace::ConsoleLogger).to receive(:error)
58
+ content_downloader.download(INVALID_URL)
59
+ end
60
+ end
61
+ end
62
+
63
+
64
+ describe '#download_content' do
65
+ context 'when url is valid' do
66
+ it 'should download file' do
67
+ expect_any_instance_of(Jenkins::Peace::ConsoleLogger).to receive(:info).with("Downloading : '#{VALID_URL}'")
68
+ expect(content_downloader).to receive(:start_http_session).with(VALID_URL)
69
+ content_downloader.download_content(VALID_URL)
70
+ end
71
+ end
72
+
73
+ context 'when url is invalid' do
74
+ it 'should not download file' do
75
+ expect_any_instance_of(Jenkins::Peace::ConsoleLogger).to receive(:error)
76
+ content_downloader.download_content(INVALID_URL)
77
+ end
78
+ end
79
+ end
80
+
81
+ end
@@ -0,0 +1,194 @@
1
+ require 'spec_helper'
2
+
3
+ describe Jenkins::Peace do
4
+
5
+ def helper
6
+ Jenkins::Peace
7
+ end
8
+
9
+
10
+ def infos
11
+ {
12
+ base_path: BASE_PATH,
13
+ war_files_cache: WAR_FILES_CACHE,
14
+ war_unpacked_cache: WAR_UNPACKED_CACHE,
15
+ server_path: SERVER_PATH,
16
+ jenkins_war_url: JENKINS_WAR_URL
17
+ }
18
+ end
19
+
20
+
21
+ describe '.jenkins_war_url' do
22
+ it { expect(helper.jenkins_war_url).to eq JENKINS_WAR_URL }
23
+ end
24
+
25
+
26
+ describe '.base_path' do
27
+ it { expect(helper.base_path).to eq BASE_PATH }
28
+ end
29
+
30
+
31
+ describe '.war_files_cache' do
32
+ it { expect(helper.war_files_cache).to eq WAR_FILES_CACHE }
33
+ end
34
+
35
+
36
+ describe '.war_unpacked_cache' do
37
+ it { expect(helper.war_unpacked_cache).to eq WAR_UNPACKED_CACHE }
38
+ end
39
+
40
+
41
+ describe '.server_path' do
42
+ it { expect(helper.server_path).to eq SERVER_PATH }
43
+ end
44
+
45
+
46
+ describe '.infos' do
47
+ it { expect(helper.infos).to eq infos }
48
+ end
49
+
50
+
51
+ def stub_all_war_files_with_return(value)
52
+ expect_any_instance_of(Jenkins::Peace).to receive(:all_war_files).at_least(:once).and_return(value)
53
+ end
54
+
55
+
56
+ describe '.list' do
57
+ context 'when no war file is installed' do
58
+ it 'should return empty array' do
59
+ stub_all_war_files_with_return([])
60
+ expect(helper.list).to eq []
61
+ end
62
+ end
63
+
64
+ context 'when war files are installed' do
65
+ it 'should return a list of war files' do
66
+ stub_all_war_files_with_return(['1.629', '1.628', '1.630'])
67
+ allow_any_instance_of(Jenkins::Peace::WarFile).to receive(:installed?).and_return(true)
68
+ expect(helper.list.first).to be_instance_of(Jenkins::Peace::WarFile)
69
+ expect(helper.list.first.version).to eq '1.630'
70
+ end
71
+ end
72
+ end
73
+
74
+
75
+ describe '.latest_war_file' do
76
+ context 'when no war file is installed' do
77
+ it 'should return nil' do
78
+ stub_all_war_files_with_return([])
79
+ expect(helper.latest_war_file).to be nil
80
+ end
81
+ end
82
+
83
+ context 'when war files are installed' do
84
+ it 'should return the last war file installed' do
85
+ stub_all_war_files_with_return(['1.629', '1.628'])
86
+ allow_any_instance_of(Jenkins::Peace::WarFile).to receive(:installed?).and_return(true)
87
+ expect(helper.latest_war_file).to be_instance_of(Jenkins::Peace::WarFile)
88
+ expect(helper.latest_war_file.version).to eq '1.629'
89
+ end
90
+ end
91
+ end
92
+
93
+
94
+ describe '.latest_version' do
95
+ context 'when no war file is installed' do
96
+ it 'should return nil' do
97
+ stub_all_war_files_with_return([])
98
+ expect(helper.latest_version).to be nil
99
+ end
100
+ end
101
+
102
+ context 'when war files are installed' do
103
+ it 'should return the classpath of the last war file installed' do
104
+ stub_all_war_files_with_return(['1.629', '1.628'])
105
+ allow_any_instance_of(Jenkins::Peace::WarFile).to receive(:installed?).and_return(true)
106
+ expect(helper.latest_version).to eq File.join(ENV['HOME'], '.jenkins/wars/1.629/WEB-INF/lib/jenkins-core-1.629.jar')
107
+ end
108
+ end
109
+ end
110
+
111
+
112
+ describe '.clean!' do
113
+ it 'should remove all war files' do
114
+ stub_all_war_files_with_return(['1.629', '1.628'])
115
+ allow_any_instance_of(Jenkins::Peace::WarFile).to receive(:remove!)
116
+ helper.clean!
117
+ end
118
+ end
119
+
120
+
121
+ describe '.download' do
122
+ it 'should download a war file' do
123
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:download!)
124
+ expect(helper.download('1.628')).to be_instance_of(Jenkins::Peace::WarFile)
125
+ end
126
+ end
127
+
128
+
129
+ describe '.install' do
130
+ it 'should install a war file' do
131
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:install!)
132
+ expect(helper.install('1.628')).to be_instance_of(Jenkins::Peace::WarFile)
133
+ end
134
+ end
135
+
136
+
137
+ describe '.unpack' do
138
+ it 'should unpack a war file' do
139
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:unpack!)
140
+ expect(helper.unpack('1.628')).to be_instance_of(Jenkins::Peace::WarFile)
141
+ end
142
+ end
143
+
144
+
145
+ describe '.remove' do
146
+ it 'should remove a war file' do
147
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:exists?).and_return(true)
148
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:remove!)
149
+ expect(helper.remove('1.628')).to be_instance_of(Jenkins::Peace::WarFile)
150
+ end
151
+ end
152
+
153
+
154
+ describe '.all_war_files' do
155
+ it 'should return a list of war files' do
156
+ expect(FileUtils).to receive(:mkdir_p).with(WAR_FILES_CACHE)
157
+ expect(Pathname).to receive(:new).with(WAR_FILES_CACHE).and_return(OpenStruct.new(children: []))
158
+ helper.all_war_files
159
+ end
160
+ end
161
+
162
+
163
+ describe 'check_for_presence_and_execute' do
164
+ context 'when file doesnt exist' do
165
+ it 'should check for file existence before executing method' do
166
+ war_file = helper.build_war_file('1.628')
167
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:exists?).and_return(false)
168
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:download!)
169
+ helper.check_for_presence_and_execute(war_file, :download!)
170
+ end
171
+ end
172
+
173
+ context 'when file exists' do
174
+ context 'and overwrite is false' do
175
+ it 'should do nothing' do
176
+ war_file = helper.build_war_file('1.628')
177
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:exists?).at_least(:twice).and_return(true)
178
+ expect_any_instance_of(Jenkins::Peace::WarFile).to_not receive(:download!)
179
+ helper.check_for_presence_and_execute(war_file, :download!, false)
180
+ end
181
+ end
182
+
183
+ context 'and overwrite is true' do
184
+ it 'should execute method' do
185
+ war_file = helper.build_war_file('1.628')
186
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:exists?).at_least(:twice).and_return(true)
187
+ expect_any_instance_of(Jenkins::Peace::WarFile).to receive(:download!)
188
+ helper.check_for_presence_and_execute(war_file, :download!, true)
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ end