domo 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ # A sample Gemfile
2
+ source :rubygems
3
+
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,24 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ domo (0.0.1)
5
+ bundler
6
+ highline
7
+ mechanize
8
+ nokogiri
9
+ thor
10
+
11
+ GEM
12
+ remote: http://rubygems.org/
13
+ specs:
14
+ highline (1.6.2)
15
+ mechanize (1.0.0)
16
+ nokogiri (>= 1.2.1)
17
+ nokogiri (1.4.4)
18
+ thor (0.14.6)
19
+
20
+ PLATFORMS
21
+ ruby
22
+
23
+ DEPENDENCIES
24
+ domo!
data/LICENCE.txt ADDED
@@ -0,0 +1,18 @@
1
+ Permission is hereby granted, free of charge, to any person obtaining
2
+ a copy of this software and associated documentation files (the
3
+ 'Software'), to deal in the Software without restriction, including
4
+ without limitation the rights to use, copy, modify, merge, publish,
5
+ distribute, sublicense, and/or sell copies of the Software, and to
6
+ permit persons to whom the Software is furnished to do so, subject to
7
+ the following conditions:
8
+
9
+ The above copyright notice and this permission notice shall be
10
+ included in all copies or substantial portions of the Software.
11
+
12
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
13
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
14
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
15
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
16
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
17
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
18
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rst ADDED
@@ -0,0 +1,66 @@
1
+ ----
2
+ Domo
3
+ ----
4
+
5
+ Super-duper simple command client for Jenkins.
6
+
7
+ Requirements
8
+ ------------
9
+
10
+ * ruby-1.9.2 (probably work with 1.8 as well)
11
+ * bundler_
12
+
13
+
14
+ Install
15
+ -------
16
+
17
+ ::
18
+
19
+ rake install
20
+
21
+ Usage
22
+ -----
23
+
24
+ ::
25
+
26
+ Usage: domo [command] [options]
27
+ Commands:
28
+ domo help [command] # show help for domo
29
+ domo list <jenkins_url> # list the all of jobs on target jenkins
30
+ domo trigger <jenkins_url> <job_list_path> [options] # trigger jobs specified in the list file
31
+ domo toggle_all <jenkins_url> <enable|disable> # en[dis]able all jobs specified jenkins owns
32
+ domo toggle <jenkins_url> <enable|disable> <job_list> # en[dis]able jobs specified in the list file
33
+ domo clone <src_jenkins_url> <dest_jenkins_url> <job_list_path> # clone jobs from jenkins to another jenkins
34
+ domo delete <jenkins_url> <job_list_path> [options] # delete jobs specified in the list file
35
+ domo delete_all <jenkins_url> [options] # delete all jobs that specified jenkins owns
36
+ domo install <jenkins_url> <plugin_list_path> # install plugins specified in the list file
37
+ domo backup_config <jenkins_url> [options] # backup all job configs that specified jenkins owns
38
+ domo create_jobs <jenkins_url> <config_files_dir> # create jobs from specified 'config.xml's
39
+ domo version # show version information
40
+
41
+ License
42
+ -------
43
+
44
+ ::
45
+
46
+ Copyright (c) <2011> cynipe
47
+
48
+ Permission is hereby granted, free of charge, to any person obtaining
49
+ a copy of this software and associated documentation files (the "Software"),
50
+ to deal in the Software without restriction, including without limitation
51
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
52
+ and/or sell copies of the Software, and to permit persons to whom the
53
+ Software is furnished to do so, subject to the following conditions:
54
+
55
+ The above copyright notice and this permission notice shall be included
56
+ in all copies or substantial portions of the Software.
57
+
58
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
59
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
60
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
61
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
62
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
63
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
64
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
65
+
66
+ .. _bundler: https://rvm.beginrescueend.com/
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
data/bin/domo ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby -U
2
+ require "domo"
3
+
4
+ Domo::CLI.start
data/domo.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "domo/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "domo"
7
+ s.version = Domo::Version.to_s
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["cynipe"]
10
+ s.email = ["cynipe@cynipe.net"]
11
+ s.summary = %q{Domo is the super-duper simple client for Jenkins}
12
+
13
+ s.files = Dir.glob("**/*")
14
+ s.executables = ["domo"]
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency("bundler")
18
+ s.add_dependency("mechanize")
19
+ s.add_dependency("nokogiri")
20
+ s.add_dependency("highline")
21
+ s.add_dependency("thor")
22
+ end
data/lib/domo.rb ADDED
@@ -0,0 +1,3 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require "domo/core"
3
+ require "domo/cli"
data/lib/domo/cli.rb ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby -U
2
+ require "thor"
3
+ require "domo"
4
+
5
+ module Domo
6
+
7
+ class CLI < Thor
8
+
9
+ def initialize(args=[], options={}, config={})
10
+ super(args, options, config)
11
+ @domo = Domo::Core.new
12
+ end
13
+
14
+ map "-v" => :version, "--version" => :version, "-h" => :help, "--help" => :help
15
+
16
+ desc "list <jenkins_url>", "list the all of jobs on target jenkins"
17
+ def list(target)
18
+ @domo.list(target, true)
19
+ end
20
+
21
+ desc "trigger <jenkins_url> <job_list_path> [options]", "trigger jobs specified in the list file"
22
+ method_option :dryrun,
23
+ :desc => "execute except actually send request",
24
+ :type => :boolean,
25
+ :default => true
26
+ def trigger(target, job_list)
27
+ @domo.trigger(target, job_list, options[:dryrun])
28
+ end
29
+
30
+ desc "toggle_all <jenkins_url> <enable|disable>", "en[dis]able all jobs specified jenkins owns"
31
+ def toggle_all(target, action)
32
+ @domo.toggle_all(target, action)
33
+ end
34
+
35
+ desc "toggle <jenkins_url> <enable|disable> <job_list>", "en[dis]able jobs specified in the list file"
36
+ def toggle(target, action, job_list)
37
+ @domo.toggle(target, action, job_list)
38
+ end
39
+
40
+ desc "clone <src_jenkins_url> <dest_jenkins_url> <job_list_path>", "clone jobs from jenkins to another jenkins"
41
+ def clone(src, dest, job_list)
42
+ @domo.clone(src, dest, job_list)
43
+ end
44
+
45
+
46
+ desc "delete <jenkins_url> <job_list_path> [options]", "delete jobs specified in the list file"
47
+ method_option :dryrun,
48
+ :desc => "execute except actually send request",
49
+ :type => :boolean,
50
+ :default => true
51
+ def delete(target, job_list)
52
+ @domo.delete(target, job_list, options[:dryrun])
53
+ end
54
+
55
+ desc "delete_all <jenkins_url> [options]", "delete all jobs that specified jenkins owns"
56
+ method_option :dryrun,
57
+ :desc => "execute except actually send request",
58
+ :type => :boolean,
59
+ :default => true
60
+ def delete_all(target)
61
+ @domo.delete_all(target, options[:dryrun])
62
+ end
63
+
64
+ desc "install <jenkins_url> <plugin_list_path>", "install plugins specified in the list file"
65
+ def install(target, plugin_list)
66
+ @domo.install(target, plugin_list)
67
+ end
68
+
69
+ desc "backup_config <jenkins_url> [options]", "backup all job configs that specified jenkins owns"
70
+ method_option :dest,
71
+ :desc => "config.xml dest dir",
72
+ :type => :string,
73
+ :default => "#{Dir::pwd}/jobs"
74
+ def backup_config(target)
75
+ @domo.backup_config(target, options[:dest])
76
+ end
77
+
78
+ desc "create_jobs <jenkins_url> <config_files_dir>", "create jobs from specified 'config.xml's"
79
+ def create_jobs(target, config_dir)
80
+ @domo.create_jobs(target, config_dir)
81
+ end
82
+
83
+ desc "version", "show version information"
84
+ def version
85
+ puts Domo::Version.to_s
86
+ end
87
+
88
+ desc "help [command]", "show help for domo"
89
+ def help(*args)
90
+ super(*args)
91
+ end
92
+
93
+ def self.help(shell, *)
94
+ list = printable_tasks
95
+ shell.say "Usage: domo [command] [options]"
96
+ shell.say "Commands:"
97
+ shell.print_table(list, :ident => 2, :truncate => true)
98
+ shell.say
99
+ class_options_help(shell)
100
+ end
101
+
102
+ end
103
+
104
+ end
data/lib/domo/core.rb ADDED
@@ -0,0 +1,189 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'rubygems'
3
+ require 'bundler/setup'
4
+ require 'open-uri'
5
+ require 'nokogiri'
6
+ require 'mechanize'
7
+ require 'erb'
8
+ require 'highline'
9
+
10
+ # オレオレ証明を無視する為
11
+ require 'openssl'
12
+ module OpenSSL
13
+ module SSL
14
+ remove_const :VERIFY_PEER
15
+ end
16
+ end
17
+ OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
18
+
19
+ # work around problem where HighLine detects an eof on $stdin and raises an
20
+ # error.
21
+ HighLine.track_eof = false
22
+
23
+ module Domo
24
+
25
+ class Core
26
+ include ERB::Util
27
+
28
+ def initialize
29
+ @agent = Mechanize.new
30
+ end
31
+
32
+ # 対象とするJenkinsのジョブの一覧を返す
33
+ def list(target, verbose=false)
34
+ login(target) if auth_required?(target)
35
+ jenkins_info = Nokogiri.XML(@agent.get_file("#{target}/api/xml"))
36
+ jenkins_info.css("job>name").map do |name|
37
+ result = name.text
38
+ puts result if verbose
39
+ result
40
+ end
41
+ end
42
+
43
+ # ジョブ名一覧ファイルをもとにビルドをトリガリングする
44
+ def trigger(target, job_list, dryrun=true)
45
+ raise "target file unreadable" unless File.readable? job_list
46
+ puts "!!dryrun mode!!" if dryrun
47
+ login(target) if auth_required?(target)
48
+ File.read(job_list).each_line do |name|
49
+ encoded_name = url_encode(name.strip!)
50
+ @agent.post("#{target}/job/#{encoded_name}/build") unless dryrun
51
+ puts "#{name} triggerd"
52
+ end
53
+ end
54
+
55
+ # 対象のJenkins上にある全てのジョブを有効/無効化する
56
+ def toggle_all(target, action)
57
+ list(target).each do |name|
58
+ @agent.post("#{target}/job/#{url_encode(name)}/#{action}")
59
+ puts "#{name} #{action}d."
60
+ end
61
+ end
62
+
63
+ # ジョブ名一覧ファイルを元に対象のJenkins上にあるジョブを有効/無効化する
64
+ def toggle(target, action, job_list)
65
+ raise "target file unreadable" unless File.readable? job_list
66
+ File.read(job_list).each_line do |name|
67
+ encoded_name = url_encode(name.strip!)
68
+ @agent.post("#{target}/job/#{encoded_name}/#{action}")
69
+ puts "#{name} #{action}d."
70
+ end
71
+ end
72
+
73
+ # 対象のJenkinsから全てを削除する
74
+ # 破壊的なメソッドなのでdryrunがデフォルト
75
+ def delete_all(target, dryrun=true)
76
+ puts "!!dryrun mode!!" if dryrun
77
+ list(target).each do |name|
78
+ @agent.post("#{target}/job/#{url_encode(name)}/doDelete") unless dryrun
79
+ puts "#{name} deleted"
80
+ end
81
+ end
82
+
83
+ # ジョブ名一覧ファイルをもとに対象のJenkinsからジョブを削除する
84
+ # 破壊的なメソッドなのでdryrunがデフォルト
85
+ def delete(target, joblist, dryrun=true)
86
+ raise "target file unreadable" unless File.readable? job_list
87
+ login(target) if auth_required?(target)
88
+ puts "!!dryrun mode!!" if dryrun
89
+ File.read(job_list).each_line do |name|
90
+ @agent.post("#{target}/job/#{url_encode(name.strip!)}/doDelete") unless dryrun
91
+ puts "#{name} deleted"
92
+ end
93
+ end
94
+
95
+ # ジョブ名一覧ファイルを元に、Jenkins AからJenkins BへJobをクローンする
96
+ def clone(from, to, job_list)
97
+ raise "target file unreadable" unless File.readable? job_list
98
+
99
+ login(from) if auth_required?(from)
100
+ login(to) if auth_required?(to)
101
+ File.read(job_list).each_line do |name|
102
+ @agent.get("#{from}/job/#{url_encode(name.strip!)}/config.xml") do |res|
103
+ create_job(to, name, res.body)
104
+ end
105
+ end
106
+ end
107
+
108
+ # プラグイン一覧ファイルを元にJenkinsにプラグインをインストールする
109
+ # プラグイン一覧ファイルの内容はインストール可能なプラグインページのチェックボックスのname属性値
110
+ def install(target, plugin_list)
111
+ login(target) if auth_required?(target)
112
+ form = @agent.get("#{target}/pluginManager/available").form_with(:action => 'install')
113
+ File.read(plugin_list).each_line do |plugin|
114
+ form.checkbox_with(:name => plugin.strip!) do |checkbox|
115
+ puts "trying to mark: #{plugin}"
116
+ if checkbox != nil
117
+ puts " => #{plugin} marked as an install target."
118
+ checkbox.check
119
+ end
120
+ end
121
+ end
122
+ form.submit
123
+ puts "plugins installed, please restart your butler after installation done."
124
+ puts "see #{target}/updateCenter/ for instalation progress."
125
+ end
126
+
127
+ def backup_config(target, dest)
128
+ list(target).each do |name|
129
+ FileUtils.mkdir_p(dest) unless File.exists?(dest)
130
+ file_to_write = "#{dest}/#{name}.xml"
131
+ File.open(file_to_write, "w") do |f|
132
+ f.write @agent.get_file("#{target}/job/#{url_encode(name)}/config.xml")
133
+ end
134
+ puts "backed up successfully: #{file_to_write}"
135
+ end
136
+ end
137
+
138
+ def create_jobs(target, config_dir)
139
+ login(target) if auth_required?(target)
140
+ Dir.glob("#{config_dir}/*.xml").each do |file_name|
141
+ job_name = File.split(file_name)[1].sub(/\.xml$/, "")
142
+ create_job(target, job_name, File.read(file_name))
143
+ end
144
+ end
145
+
146
+ def create_job(target, name, config)
147
+ create_api = "#{target}/createItem?name=#{url_encode(name)}"
148
+ @agent.post(create_api, config, {'Content-Type'=>'text/xml'})
149
+ puts "#{name} successfully created at #{target}"
150
+
151
+ rescue Mechanize::ResponseCodeError => e
152
+ case e.response_code
153
+ when '400'
154
+ puts "#{name} already exists, so just skiped."
155
+ else
156
+ raise e
157
+ end
158
+ end
159
+
160
+ def auth_required?(target)
161
+ ui = HighLine.new
162
+ prompt = "Need login for #{target}?[y|n]: "
163
+ ui.ask(prompt) do |q|
164
+ q.overwrite = false
165
+ q.default = "n"
166
+ q.validate = /y|n|\n/i
167
+ q.responses[:not_valid] = prompt
168
+ end == "y"
169
+ end
170
+
171
+ def login(target)
172
+ ui = HighLine.new
173
+ user = ui.ask("User: ")
174
+ pass = ui.ask("Password: ") { |q| q.echo = false }
175
+
176
+ puts "logging in... => #{target}"
177
+ @agent.get("#{target}/login") do |page|
178
+ page.form_with(:name => 'login') {|form|
179
+ form['j_username'] = user
180
+ form['j_password'] = pass
181
+ }.submit
182
+ end
183
+ end
184
+
185
+ private :login, :auth_required?
186
+
187
+ end
188
+
189
+ end
@@ -0,0 +1,14 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require 'scanf'
3
+
4
+ module Domo
5
+
6
+ class Version
7
+
8
+ def self.to_s
9
+ File.read(File.expand_path("../../../VERSION", __FILE__))
10
+ end
11
+
12
+ end
13
+
14
+ end
Binary file
metadata ADDED
@@ -0,0 +1,116 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: domo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - cynipe
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-06-11 00:00:00.000000000 +09:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bundler
17
+ requirement: &2165237860 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2165237860
26
+ - !ruby/object:Gem::Dependency
27
+ name: mechanize
28
+ requirement: &2165237420 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: *2165237420
37
+ - !ruby/object:Gem::Dependency
38
+ name: nokogiri
39
+ requirement: &2165237000 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ type: :runtime
46
+ prerelease: false
47
+ version_requirements: *2165237000
48
+ - !ruby/object:Gem::Dependency
49
+ name: highline
50
+ requirement: &2165236580 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ type: :runtime
57
+ prerelease: false
58
+ version_requirements: *2165236580
59
+ - !ruby/object:Gem::Dependency
60
+ name: thor
61
+ requirement: &2165252520 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :runtime
68
+ prerelease: false
69
+ version_requirements: *2165252520
70
+ description:
71
+ email:
72
+ - cynipe@cynipe.net
73
+ executables:
74
+ - domo
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - bin/domo
79
+ - domo.gemspec
80
+ - Gemfile
81
+ - Gemfile.lock
82
+ - lib/domo/cli.rb
83
+ - lib/domo/core.rb
84
+ - lib/domo/version.rb
85
+ - lib/domo.rb
86
+ - LICENCE.txt
87
+ - pkg/domo-0.0.1.gem
88
+ - Rakefile
89
+ - README.rst
90
+ - VERSION
91
+ has_rdoc: true
92
+ homepage:
93
+ licenses: []
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 1.6.2
113
+ signing_key:
114
+ specification_version: 3
115
+ summary: Domo is the super-duper simple client for Jenkins
116
+ test_files: []