jenkins2 0.1.0 → 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.
- 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
|