jenkins2 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -22
- data/README.md +140 -76
- data/bin/jenkins2 +8 -1
- data/lib/jenkins2.rb +10 -5
- data/lib/jenkins2/api.rb +33 -0
- data/lib/jenkins2/api/computer.rb +49 -0
- data/lib/jenkins2/api/credentials.rb +151 -0
- data/lib/jenkins2/api/job.rb +50 -0
- data/lib/jenkins2/api/plugins.rb +55 -0
- data/lib/jenkins2/api/root.rb +34 -0
- data/lib/jenkins2/api/rud.rb +21 -0
- data/lib/jenkins2/api/user.rb +35 -0
- data/lib/jenkins2/api/view.rb +40 -0
- data/lib/jenkins2/cli.rb +157 -0
- data/lib/jenkins2/cli/credentials.rb +232 -0
- data/lib/jenkins2/cli/job.rb +48 -0
- data/lib/jenkins2/cli/nodes.rb +233 -0
- data/lib/jenkins2/cli/plugins.rb +101 -0
- data/lib/jenkins2/cli/root.rb +65 -0
- data/lib/jenkins2/cli/user.rb +16 -0
- data/lib/jenkins2/cli/view.rb +155 -0
- data/lib/jenkins2/connection.rb +90 -0
- data/lib/jenkins2/errors.rb +37 -0
- data/lib/jenkins2/log.rb +8 -7
- data/lib/jenkins2/resource_proxy.rb +46 -0
- data/lib/jenkins2/util.rb +67 -0
- data/lib/jenkins2/version.rb +3 -1
- metadata +33 -49
- data/lib/jenkins2/client.rb +0 -127
- data/lib/jenkins2/client/credential_commands.rb +0 -134
- data/lib/jenkins2/client/node_commands.rb +0 -105
- data/lib/jenkins2/client/plugin_commands.rb +0 -53
- data/lib/jenkins2/cmdparse.rb +0 -51
- data/lib/jenkins2/command_line.rb +0 -221
- data/lib/jenkins2/try.rb +0 -36
- data/lib/jenkins2/uri.rb +0 -10
- data/lib/jenkins2/wait.rb +0 -29
@@ -1,105 +0,0 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
|
3
|
-
module Jenkins2
|
4
|
-
class Client
|
5
|
-
module NodeCommands
|
6
|
-
# Connects a node.
|
7
|
-
# +node+:: Node name, <tt>(master)</tt> for master.
|
8
|
-
def connect_node( node: '(master)' )
|
9
|
-
api_request( :post, "/computer/#{node}/launchSlaveAgent" )
|
10
|
-
end
|
11
|
-
|
12
|
-
# Creates a new node, by providing node definition XML.
|
13
|
-
# Keyword parameters:
|
14
|
-
# +node+:: Node name.
|
15
|
-
# +xml_config+:: New configuration in xml format.
|
16
|
-
def create_node( node: nil, xml_config: nil )
|
17
|
-
xml_config = STDIN.read if xml_config.nil?
|
18
|
-
api_request( :post, "/computer/doCreateItem", :raw ) do |req|
|
19
|
-
req.form_data = { 'name' => node, type: "hudson.slaves.DumbSlave$DescriptorImpl",
|
20
|
-
json: {}.to_json }
|
21
|
-
end
|
22
|
-
update_node( node: node, xml_config: xml_config )
|
23
|
-
end
|
24
|
-
|
25
|
-
# Deletes a node
|
26
|
-
# +node+:: Node name. Master cannot be deleted.
|
27
|
-
def delete_node( node: nil )
|
28
|
-
raise ArgumentError, 'node must be provided' if node.nil?
|
29
|
-
api_request( :post, "/computer/#{node}/doDelete" )
|
30
|
-
end
|
31
|
-
|
32
|
-
# Disconnects a node.
|
33
|
-
# +node+:: Node name, <tt>(master)</tt> for master.
|
34
|
-
# +message+:: Reason why the node is being disconnected.
|
35
|
-
def disconnect_node( node: '(master)', message: nil )
|
36
|
-
api_request( :post, "/computer/#{node}/doDisconnect" ) do |req|
|
37
|
-
req.body = "offlineMessage=#{CGI::escape message}" unless message.nil?
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
# Returns the node definition XML.
|
42
|
-
# +node+:: Node name, <tt>(master)</tt> for master.
|
43
|
-
def get_node_xml( node: '(master)' )
|
44
|
-
api_request( :get, "/computer/#{node}/config.xml", :body )
|
45
|
-
end
|
46
|
-
|
47
|
-
# Returns the node state
|
48
|
-
# +node+:: Node name, <tt>(master)</tt> for master.
|
49
|
-
def get_node( node: '(master)' )
|
50
|
-
api_request( :get, "/computer/#{node}/api/json" )
|
51
|
-
end
|
52
|
-
|
53
|
-
# Sets node temporarily offline. Does nothing, if node is already offline.
|
54
|
-
# +node+:: Node name, or <tt>(master)</tt> for master.
|
55
|
-
# +message+:: Record the note about this node is being disconnected.
|
56
|
-
def offline_node( node: '(master)', message: nil )
|
57
|
-
if node_online?( node: node )
|
58
|
-
api_request( :post, "/computer/#{node}/toggleOffline" ) do |req|
|
59
|
-
req.body = "offlineMessage=#{CGI::escape message}" unless message.nil?
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
# Sets node back online, if node is temporarily offline.
|
65
|
-
# +node+:: Node name, <tt>(master)</tt> for master.
|
66
|
-
def online_node( node: '(master)' )
|
67
|
-
api_request( :post, "/computer/#{node}/toggleOffline" ) unless node_online?( node: node )
|
68
|
-
end
|
69
|
-
|
70
|
-
# Updates the node definition XML
|
71
|
-
# Keyword parameters:
|
72
|
-
# +node+:: Node name, <tt>(master)</tt> for master.
|
73
|
-
# +xml_config+:: New configuration in xml format.
|
74
|
-
def update_node( node: '(master)', xml_config: nil )
|
75
|
-
xml_config = STDIN.read if xml_config.nil?
|
76
|
-
api_request( :post, "/computer/#{node}/config.xml", :body ) do |req|
|
77
|
-
req.body = xml_config
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Waits for node to become idle or until +max_wait_minutes+ pass.
|
82
|
-
# +node+:: Node name, <tt>(master)</tt> for master.
|
83
|
-
# +max_wait_minutes+:: Maximum wait time in minutes. Default 60.
|
84
|
-
def wait_node_idle( node: '(master)', max_wait_minutes: 60 )
|
85
|
-
Jenkins2::Wait.wait( max_wait_minutes: max_wait_minutes ){ node_idle? node: node }
|
86
|
-
end
|
87
|
-
|
88
|
-
def node_idle?( node: '(master)' )
|
89
|
-
get_node( node: node )['idle']
|
90
|
-
end
|
91
|
-
|
92
|
-
# Checks if node is online (= not temporarily offline )
|
93
|
-
# +node+:: Node name. Use <tt>(master)</tt> for master.
|
94
|
-
def node_online?( node: '(master)' )
|
95
|
-
!get_node( node: node )['temporarilyOffline']
|
96
|
-
end
|
97
|
-
|
98
|
-
# Checks if node is connected, i.e. Master connected and launched client on it.
|
99
|
-
# +node+:: Node name. Use <tt>(master)</tt> for master.
|
100
|
-
def node_connected?( node: '(master)' )
|
101
|
-
!get_node( node: node )['offline']
|
102
|
-
end
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
module Jenkins2
|
2
|
-
class Client
|
3
|
-
module PluginCommands
|
4
|
-
# Installs plugins by short name (like +thinBackup+).
|
5
|
-
# +names+:: List of short names.
|
6
|
-
def install_plugins( *names )
|
7
|
-
api_request( :post, '/pluginManager/install' ) do |req|
|
8
|
-
req.form_data = names.flatten.inject({}) do |memo,obj|
|
9
|
-
memo.merge "plugin.#{obj}.default" => 'on'
|
10
|
-
end.merge( 'dynamicLoad' => 'Install without restart' )
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
# Installs a plugin by uploading *.hpi or *.jpi file.
|
15
|
-
# +plugin_file+:: A *.hpi or *.jpi file itself ( not some path )
|
16
|
-
def upload_plugin( plugin_file )
|
17
|
-
api_request( :post, '/pluginManager/uploadPlugin' ) do |req|
|
18
|
-
req.body = plugin_file
|
19
|
-
req.content_type = 'multipart/form-data'
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Lists installed plugins
|
24
|
-
def list_plugins
|
25
|
-
api_request( :get, '/pluginManager/api/json?depth=1' )['plugins']
|
26
|
-
end
|
27
|
-
|
28
|
-
# Checks, if all of the plugins from the passed list are installed
|
29
|
-
# +names+:: List of short names of plugins (like +thinBackup+).
|
30
|
-
def plugins_installed?( *names )
|
31
|
-
plugins = list_plugins
|
32
|
-
return false if plugins.nil?
|
33
|
-
names.flatten.all? do |name|
|
34
|
-
plugins.detect{|p| p['shortName'] == name and !p['deleted'] }
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
# Uninstalls a plugin
|
39
|
-
# +name+:: Plugin short name
|
40
|
-
def uninstall_plugin( name )
|
41
|
-
api_request( :post, "/pluginManager/plugin/#{name}/doUninstall" ) do |req|
|
42
|
-
req.form_data = { 'Submit' => 'Yes', 'json' => '{}' }
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def wait_plugins_installed( *names, max_wait_minutes: 2 )
|
47
|
-
Wait.wait( max_wait_minutes: max_wait_minutes ) do
|
48
|
-
plugins_installed? names
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
data/lib/jenkins2/cmdparse.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'optparse'
|
2
|
-
|
3
|
-
module Jenkins2
|
4
|
-
class CommandParser < OptionParser
|
5
|
-
attr_reader :command_name
|
6
|
-
|
7
|
-
def command( key, desc, &block )
|
8
|
-
sw = OptionParser::Switch::NoArgument.new( key, nil, [key], nil, nil, [desc],
|
9
|
-
Proc.new{ OptionParser.new( &block ) } ), [], [key]
|
10
|
-
commands[key.to_s] = sw[0]
|
11
|
-
end
|
12
|
-
|
13
|
-
def parse!( argv=default_argv )
|
14
|
-
@command_name = argv.detect{|c| commands.has_key? c }
|
15
|
-
if command_name
|
16
|
-
#create temporary parser with option definitions from both: globalparse and subparse
|
17
|
-
OptionParser.new do |parser|
|
18
|
-
parser.instance_variable_set(:@stack,
|
19
|
-
commands[command_name.to_s].block.call.instance_variable_get(:@stack) + @stack)
|
20
|
-
end.parse! argv
|
21
|
-
else
|
22
|
-
super( argv )
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def commands
|
27
|
-
@commands ||= {}
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
def summarize(to = [], width = @summary_width, max = width - 1, indent = @summary_indent, &blk)
|
32
|
-
super(to, width, max, indent, &blk)
|
33
|
-
if command_name and commands.has_key?( command_name )
|
34
|
-
to << "Command:\n"
|
35
|
-
commands[command_name].summarize( {}, {}, width, max, indent ) do |l|
|
36
|
-
to << (l.index($/, -1) ? l : l + $/)
|
37
|
-
end
|
38
|
-
to << "Command options:\n"
|
39
|
-
commands[command_name].block.call.summarize( to, width, max, indent, &blk )
|
40
|
-
else
|
41
|
-
to << "Commands:\n"
|
42
|
-
commands.each do |name, command|
|
43
|
-
command.summarize( {}, {}, width, max, indent ) do |l|
|
44
|
-
to << (l.index($/, -1) ? l : l + $/)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
to
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
@@ -1,221 +0,0 @@
|
|
1
|
-
require 'optparse/uri'
|
2
|
-
require_relative 'cmdparse'
|
3
|
-
require_relative 'client'
|
4
|
-
require_relative 'log'
|
5
|
-
|
6
|
-
module Jenkins2
|
7
|
-
class CommandLine
|
8
|
-
attr_accessor :global_options
|
9
|
-
attr_accessor :command_options
|
10
|
-
|
11
|
-
def initialize( args )
|
12
|
-
@global_options = OptionParser::OptionMap.new
|
13
|
-
@log_options = { verbose: 0, log: STDOUT }
|
14
|
-
@command_options = OptionParser::OptionMap.new
|
15
|
-
global = CommandParser.new 'Usage: jenkins [global-options] <command> [options]' do |opts|
|
16
|
-
opts.separator ''
|
17
|
-
opts.separator "Global options (accepted by all commands):"
|
18
|
-
opts.on '-s', '--server URL', ::URI, 'Jenkins Server Url' do |opt|
|
19
|
-
@global_options[:server] = opt
|
20
|
-
end
|
21
|
-
opts.on '-u', '--user USER', 'Jenkins API user' do |opt|
|
22
|
-
@global_options[:user] = opt
|
23
|
-
end
|
24
|
-
opts.on '-k', '--key KEY', 'Jenkins API key' do |opt|
|
25
|
-
@global_options[:key] = opt
|
26
|
-
end
|
27
|
-
opts.on '-c', '--config [PATH]', 'Use configuration file. Instead of providing '\
|
28
|
-
'server, user and key through command line, you can do that with configuration file. '\
|
29
|
-
'File format is json: { "server": "http://jenkins.example.com", "user": "admin", '\
|
30
|
-
'"key": "123456" }. Options provided in command line will overwrite ones from '\
|
31
|
-
'configuration file. Program looks for ~/.jenkins2.json if no PATH is provided.' do |opt|
|
32
|
-
@global_options[:config] = opt || ::File.join( ENV['HOME'], '.jenkins2.json' )
|
33
|
-
end
|
34
|
-
opts.on '-l', '--log FILE', 'Log file. Prints to standard out, if not provided' do |opt|
|
35
|
-
@log_options[:log] = opt
|
36
|
-
end
|
37
|
-
opts.on '-v', '--verbose', 'Print more info. Up to -vvv. Prints only errors by default.' do
|
38
|
-
@log_options[:verbose] += 1
|
39
|
-
end
|
40
|
-
opts.on '-h', '--help', 'Show help' do
|
41
|
-
@global_options[:help] = true
|
42
|
-
end
|
43
|
-
opts.on '-V', '--version', 'Show version' do
|
44
|
-
puts VERSION
|
45
|
-
exit
|
46
|
-
end
|
47
|
-
|
48
|
-
opts.separator ''
|
49
|
-
opts.separator 'For command specific options run: jenkins2 --help <command>'
|
50
|
-
opts.separator ''
|
51
|
-
opts.command 'version', 'Outputs the current version of Jenkins'
|
52
|
-
opts.command 'prepare-for-shutdown', 'Stop executing new builds, so that the system can '\
|
53
|
-
'be eventually shut down safely.'
|
54
|
-
opts.command 'cancel-shutdown', 'Cancel the effect of "prepare-for-shutshow" command.'
|
55
|
-
opts.command 'wait-nodes-idle', 'Wait for all nodes to become idle. Is expected to be '\
|
56
|
-
'called after "prepare_for_shutdown", otherwise new builds will still be run.' do |cmd|
|
57
|
-
cmd.on '-m', '--max-wait-minutes INT', Integer, 'Wait for INT minutes at most. '\
|
58
|
-
'Default 60' do |opt|
|
59
|
-
@command_options[:max_wait_minutes] = opt
|
60
|
-
end
|
61
|
-
end
|
62
|
-
opts.command 'offline-node', 'Stop using a node for performing builds temporarily, until '\
|
63
|
-
'the next "online-node" command.' do |cmd|
|
64
|
-
cmd.on '-n', '--node NAME', 'Name of the node or empty for master' do |opt|
|
65
|
-
@command_options[:node] = opt
|
66
|
-
end
|
67
|
-
cmd.on '-m', '--message MESSAGE', 'Record the note about why you are '\
|
68
|
-
'disconnecting this node' do |opt|
|
69
|
-
@command_options[:message] = opt
|
70
|
-
end
|
71
|
-
end
|
72
|
-
opts.command 'online-node', 'Resume using a node for performing builds, to cancel out '\
|
73
|
-
'the earlier "offline-node" command.' do |cmd|
|
74
|
-
cmd.on '-n', '--node [NAME]', 'Name of the node or empty for master' do |opt|
|
75
|
-
@command_options[:node] = opt
|
76
|
-
end
|
77
|
-
end
|
78
|
-
opts.command 'connect-node', 'Connects a node, i.e. starts Jenkins slave on a node.' do |cmd|
|
79
|
-
cmd.on '-n', '--node [NAME]', 'Name of the node or empty for master' do |opt|
|
80
|
-
@command_options[:node] = opt
|
81
|
-
end
|
82
|
-
end
|
83
|
-
opts.command 'create-node', 'Creates a new node from XML' do |cmd|
|
84
|
-
cmd.on '-n', '--node NAME', 'Name of the new node' do |opt|
|
85
|
-
@command_options[:node] = opt
|
86
|
-
end
|
87
|
-
cmd.on '-x', '--xml FILE', 'Path to XML configuration file' do |opt|
|
88
|
-
@command_options[:xml] = IO.read opt
|
89
|
-
end
|
90
|
-
end
|
91
|
-
opts.command 'delete-node', 'Deletes a node' do |cmd|
|
92
|
-
cmd.on '-n', '--node NAME', 'Node name' do |opt|
|
93
|
-
@command_options[:node] = opt
|
94
|
-
end
|
95
|
-
end
|
96
|
-
opts.command 'create-credential', 'Creates credential.' do |cmd|
|
97
|
-
cmd.on '-S', '--scope SCOPE', 'GLOBAL or SYSTEM scope' do |opt|
|
98
|
-
@command_options[:scope] = opt
|
99
|
-
end
|
100
|
-
cmd.on '-i', '--id ID', 'Unique Id of credential. Will be generated automactically, if '\
|
101
|
-
'not provided' do |opt|
|
102
|
-
@command_options[:id] = opt
|
103
|
-
end
|
104
|
-
cmd.on '-d', '--description DESC', 'Human readable text, what this credential is used for.' do |opt|
|
105
|
-
@command_options[:description] = opt
|
106
|
-
end
|
107
|
-
cmd.on '-n', '--username NAME', 'Username for Username-Password or SSH credential' do |opt|
|
108
|
-
@command_options[:username] = opt
|
109
|
-
end
|
110
|
-
cmd.on '-p', '--password PASS', 'Password in plain text for Username-Password credential' do |opt|
|
111
|
-
@command_options[:password] = opt
|
112
|
-
end
|
113
|
-
cmd.on '-f', '--private-key FILE', 'Path to private key file for SSH credential' do |opt|
|
114
|
-
@command_options[:private_key] = IO.read( opt ).gsub( "\n", "\\n" )
|
115
|
-
end
|
116
|
-
cmd.on '-P', '--passphrase PHRASE', 'Passphrase for the private key for SSH credential' do |opt|
|
117
|
-
@command_options[:passphrase] = opt
|
118
|
-
end
|
119
|
-
cmd.on '-e', '--secret SECRET', 'Some secret text for Secret credential' do |opt|
|
120
|
-
@command_options[:secret] = opt
|
121
|
-
end
|
122
|
-
cmd.on '-F', '--secret-file FILE', 'Path to secret file for Secret File credential' do |opt|
|
123
|
-
@command_options[:filename] = File.basename opt
|
124
|
-
@command_options[:content] = IO.read opt
|
125
|
-
end
|
126
|
-
end
|
127
|
-
opts.command 'delete-credential', 'Deletes credential.' do |cmd|
|
128
|
-
cmd.on '-i', '--id ID', 'Credential id' do |opt|
|
129
|
-
@command_options[:id] = opt
|
130
|
-
end
|
131
|
-
end
|
132
|
-
opts.command 'get-credential', 'Returns credential as json.' do |cmd|
|
133
|
-
cmd.on '-i', '--id ID', 'Credential id' do |opt|
|
134
|
-
@command_options[:id] = opt
|
135
|
-
end
|
136
|
-
end
|
137
|
-
opts.command 'list-credentials', 'Lists all credentials.'
|
138
|
-
opts.command 'disconnect-node', 'Disconnects a node.' do |cmd|
|
139
|
-
cmd.on '-n', '--node [NAME]', 'Name of the node or empty for master' do |opt|
|
140
|
-
@command_options[:node] = opt
|
141
|
-
end
|
142
|
-
cmd.on '-m', '--message MESSAGE', 'Reason, why the node is being disconnected.' do |opt|
|
143
|
-
@command_options[:message] = opt
|
144
|
-
end
|
145
|
-
end
|
146
|
-
opts.command 'wait-node-idle', 'Wait for the node to become idle. Make sure you run '\
|
147
|
-
'"offline-node" first.' do |cmd|
|
148
|
-
cmd.on '-n', '--node [NAME]', 'Name of the node or empty for master' do |opt|
|
149
|
-
@command_options[:node] = opt
|
150
|
-
end
|
151
|
-
cmd.on '-m', '--max-wait-minutes INT', Integer, 'Wait for INT minutes at most. '\
|
152
|
-
'Default 60' do |opt|
|
153
|
-
@command_options[:max_wait_minutes] = opt
|
154
|
-
end
|
155
|
-
end
|
156
|
-
opts.command 'get-node-xml', 'Returns the node definition XML.' do |cmd|
|
157
|
-
cmd.on '-n', '--node [NAME]', 'Name of the node or empty for master' do |opt|
|
158
|
-
@command_options[:node] = opt
|
159
|
-
end
|
160
|
-
end
|
161
|
-
opts.command 'get-node', 'Returns the node state.' do |cmd|
|
162
|
-
cmd.on '-n', '--node [NAME]', 'Name of the node or empty for master' do |opt|
|
163
|
-
@command_options[:node] = opt
|
164
|
-
end
|
165
|
-
end
|
166
|
-
opts.command 'update-node', 'Updates the node definition XML from stdin or file.' do |cmd|
|
167
|
-
cmd.on '-n', '--node [NAME]', 'Name of the node or empty for master' do |opt|
|
168
|
-
@command_options[:node] = opt
|
169
|
-
end
|
170
|
-
cmd.on '-x', '--xml-config FILE', 'File to read definition from. Omit this to read from stdin' do |opt|
|
171
|
-
@command_options[:xml_config] = IO.read( opt )
|
172
|
-
end
|
173
|
-
end
|
174
|
-
opts.command 'build', 'Starts a build.' do |cmd|
|
175
|
-
cmd.on '-j', '--job NAME', 'Name of the job' do |opt|
|
176
|
-
@command_options[:job] = opt
|
177
|
-
end
|
178
|
-
cmd.on '-p', '--params KEY=VALUE[,KEY=VALUE...]', Array, 'Build parameters, where keys are'\
|
179
|
-
' names of variables' do |opt|
|
180
|
-
@command_options[:params] = opt.collect{|i| i.split( '=', 2 ) }.to_h
|
181
|
-
end
|
182
|
-
end
|
183
|
-
opts.command 'install-plugin', 'Installs a plugin from url or by short name. '\
|
184
|
-
'Provide either --url or --name.' do |cmd|
|
185
|
-
cmd.on '-u', '--uri URI', ::URI, 'Uri to install plugin from.' do |opt|
|
186
|
-
@command_options[:uri] = opt
|
187
|
-
end
|
188
|
-
cmd.on '-n', '--name SHORTNAME', 'Plugin short name (like thinBackup).' do |opt|
|
189
|
-
@command_options[:name] = opt
|
190
|
-
end
|
191
|
-
end
|
192
|
-
opts.command 'list-plugins', 'Lists installed plugins'
|
193
|
-
end
|
194
|
-
begin
|
195
|
-
global.parse!( args )
|
196
|
-
@global_options[:command] = global.command_name
|
197
|
-
if @global_options[:config]
|
198
|
-
from_file = JSON.parse( IO.read( @global_options[:config] ), symbolize_names: true )
|
199
|
-
@global_options = from_file.merge( @global_options )
|
200
|
-
end
|
201
|
-
Log.init @log_options
|
202
|
-
if @global_options[:help]
|
203
|
-
Log.unknown { global.help }
|
204
|
-
exit
|
205
|
-
end
|
206
|
-
raise OptionParser::MissingArgument, :command unless @global_options[:command]
|
207
|
-
rescue OptionParser::InvalidOption, OptionParser::MissingArgument => e
|
208
|
-
Log.fatal { e.message }
|
209
|
-
Log.fatal { global.help }
|
210
|
-
exit 1
|
211
|
-
end
|
212
|
-
Log.debug { "Options: #{@global_options}\nUnparsed args: #{ARGV}" }
|
213
|
-
end
|
214
|
-
|
215
|
-
def run
|
216
|
-
jc = Client.new( @global_options )
|
217
|
-
jc.send( @global_options[:command].gsub( '-', '_' ), @command_options )
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
data/lib/jenkins2/try.rb
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
require 'net/http'
|
2
|
-
|
3
|
-
require_relative 'log'
|
4
|
-
|
5
|
-
module Jenkins2
|
6
|
-
module Try
|
7
|
-
# Tries a block several times, if raised exception is <tt>Net::HTTPFatalError</tt>,
|
8
|
-
# <tt>Errno::ECONNREFUSED</tt> or <tt>Net::ReadTimeout</tt>.
|
9
|
-
# +retries+:: Number of retries.
|
10
|
-
# +retry_delay+:: Seconds to sleep, before attempting next retry.
|
11
|
-
# +&block+:: Code to run inside <tt>retry</tt> loop.
|
12
|
-
#
|
13
|
-
# Returns the result of a block, if it eventually succeeded or throws the exception, thown by
|
14
|
-
# the block on last try.
|
15
|
-
#
|
16
|
-
# Note that this is both a method of module Try, so you can <tt>include Jenkins::Try</tt>
|
17
|
-
# into your classes so they have a #try method, as well as a module method, so you can call it
|
18
|
-
# directly as ::try().
|
19
|
-
def try( retries: 3, retry_delay: 5, &block )
|
20
|
-
yield
|
21
|
-
rescue Errno::ECONNREFUSED, Net::HTTPFatalError, Net::ReadTimeout => e
|
22
|
-
i ||= 0
|
23
|
-
unless ( i += 1 ) == retries
|
24
|
-
Log.warn { "Received error: #{e}." }
|
25
|
-
Log.warn { "Retry request in #{retry_delay} seconds." }
|
26
|
-
sleep retry_delay
|
27
|
-
retry
|
28
|
-
end
|
29
|
-
Log.error { "Received error: #{e}." }
|
30
|
-
Log.error { "Reached maximum number of retries (#{retries}). Give up." }
|
31
|
-
raise e
|
32
|
-
end
|
33
|
-
|
34
|
-
module_function :try
|
35
|
-
end
|
36
|
-
end
|