killbill-kpm 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +33 -0
  3. data/.travis.yml +38 -0
  4. data/Gemfile +3 -0
  5. data/Gemfile.head +5 -0
  6. data/Gemfile.lock +90 -0
  7. data/Jarfile +11 -0
  8. data/Jarfile.lock +56 -0
  9. data/LICENSE +201 -0
  10. data/README.md +2 -2
  11. data/Rakefile +16 -31
  12. data/VERSION +1 -0
  13. data/config.ru +4 -0
  14. data/killbill-kpm.gemspec +31 -0
  15. data/killbill.properties +3 -0
  16. data/lib/kpm/application.rb +91 -0
  17. data/lib/kpm/listener.rb +94 -0
  18. data/lib/kpm/plugins_installer.rb +113 -0
  19. data/lib/kpm_plugin.rb +13 -0
  20. data/pom.xml +44 -0
  21. data/release.sh +61 -0
  22. data/spec/kpm/base_plugin_spec.rb +25 -0
  23. data/spec/spec_helper.rb +14 -0
  24. metadata +49 -349
  25. data/MIT-LICENSE +0 -20
  26. data/app/assets/javascripts/application.js +0 -24
  27. data/app/assets/javascripts/kpm/kpm.js +0 -7
  28. data/app/assets/stylesheets/application.css +0 -19
  29. data/app/assets/stylesheets/bootstrap_and_overrides.css +0 -17
  30. data/app/assets/stylesheets/kpm/kpm.css +0 -6
  31. data/app/controllers/kpm/engine_controller.rb +0 -29
  32. data/app/controllers/kpm/nodes_info_controller.rb +0 -108
  33. data/app/controllers/kpm/plugins_controller.rb +0 -19
  34. data/app/helpers/kpm/application_helper.rb +0 -4
  35. data/app/views/kpm/layouts/kpm_application.html.erb +0 -31
  36. data/app/views/kpm/nodes_info/_logs_table.html.erb +0 -43
  37. data/app/views/kpm/nodes_info/_nodes_table.html.erb +0 -68
  38. data/app/views/kpm/nodes_info/index.html.erb +0 -68
  39. data/app/views/kpm/nodes_info/index.js.erb +0 -4
  40. data/app/views/kpm/plugins/_form.html.erb +0 -37
  41. data/app/views/kpm/plugins/_plugins_table.html.erb +0 -48
  42. data/app/views/kpm/plugins/index.html.erb +0 -18
  43. data/config/routes.rb +0 -17
  44. data/lib/kpm.rb +0 -24
  45. data/lib/kpm/client.rb +0 -31
  46. data/lib/kpm/engine.rb +0 -23
  47. data/lib/kpm/version.rb +0 -3
  48. data/lib/tasks/kpm_tasks.rake +0 -4
  49. data/test/dummy/README.rdoc +0 -28
  50. data/test/dummy/Rakefile +0 -6
  51. data/test/dummy/app/controllers/application_controller.rb +0 -5
  52. data/test/dummy/app/helpers/application_helper.rb +0 -2
  53. data/test/dummy/bin/bundle +0 -3
  54. data/test/dummy/bin/rails +0 -4
  55. data/test/dummy/bin/rake +0 -4
  56. data/test/dummy/bin/setup +0 -29
  57. data/test/dummy/config.ru +0 -4
  58. data/test/dummy/config/application.rb +0 -32
  59. data/test/dummy/config/boot.rb +0 -5
  60. data/test/dummy/config/database.yml +0 -23
  61. data/test/dummy/config/environment.rb +0 -5
  62. data/test/dummy/config/environments/development.rb +0 -41
  63. data/test/dummy/config/environments/production.rb +0 -79
  64. data/test/dummy/config/environments/test.rb +0 -42
  65. data/test/dummy/config/initializers/assets.rb +0 -11
  66. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  67. data/test/dummy/config/initializers/cookies_serializer.rb +0 -3
  68. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  69. data/test/dummy/config/initializers/inflections.rb +0 -16
  70. data/test/dummy/config/initializers/killbill_client.rb +0 -3
  71. data/test/dummy/config/initializers/mime_types.rb +0 -4
  72. data/test/dummy/config/initializers/session_store.rb +0 -3
  73. data/test/dummy/config/initializers/wrap_parameters.rb +0 -14
  74. data/test/dummy/config/locales/en.yml +0 -23
  75. data/test/dummy/config/routes.rb +0 -4
  76. data/test/dummy/config/secrets.yml +0 -22
  77. data/test/integration/navigation_test.rb +0 -8
  78. data/test/kpm_test.rb +0 -7
  79. data/test/test_helper.rb +0 -21
data/README.md CHANGED
@@ -1,2 +1,2 @@
1
- # killbill-kpm-ui
2
- Rails mountable engine to manage the KPM plugin
1
+ # killbill-kpm-plugin
2
+ Kill Bill KPM plugin
data/Rakefile CHANGED
@@ -1,37 +1,22 @@
1
- begin
2
- require 'bundler/setup'
3
- rescue LoadError
4
- puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
- end
6
-
7
- require 'rdoc/task'
8
-
9
- RDoc::Task.new(:rdoc) do |rdoc|
10
- rdoc.rdoc_dir = 'rdoc'
11
- rdoc.title = 'KPM'
12
- rdoc.options << '--line-numbers'
13
- rdoc.rdoc_files.include('README.rdoc')
14
- rdoc.rdoc_files.include('lib/**/*.rb')
15
- end
16
-
17
- APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
- load 'rails/tasks/engine.rake'
19
-
20
-
21
- load 'rails/tasks/statistics.rake'
22
-
23
-
1
+ #!/usr/bin/env rake
24
2
 
3
+ # Install tasks to build and release the plugin
4
+ require 'bundler/setup'
25
5
  Bundler::GemHelper.install_tasks
26
6
 
27
- require 'rake/testtask'
28
-
29
- Rake::TestTask.new(:test) do |t|
30
- t.libs << 'lib'
31
- t.libs << 'test'
32
- t.pattern = 'test/**/*_test.rb'
33
- t.verbose = false
7
+ # Install test tasks
8
+ require 'rspec/core/rake_task'
9
+ namespace :test do
10
+ desc 'Run RSpec tests'
11
+ RSpec::Core::RakeTask.new do |task|
12
+ task.name = 'spec'
13
+ task.pattern = './spec/*/*_spec.rb'
14
+ end
34
15
  end
35
16
 
17
+ # Install tasks to package the plugin for Killbill
18
+ require 'killbill/rake_task'
19
+ Killbill::PluginHelper.install_tasks
36
20
 
37
- task default: :test
21
+ # Run tests by default
22
+ task :default => 'test:spec'
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,4 @@
1
+ require 'kpm_plugin'
2
+ require 'kpm/application'
3
+
4
+ run Sinatra::Application
@@ -0,0 +1,31 @@
1
+ version = File.read(File.expand_path('../VERSION', __FILE__)).strip
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'killbill-kpm'
5
+ s.version = version
6
+ s.summary = 'Kill Bill KPM plugin'
7
+ s.description = 'Plugin to manage installed plugins'
8
+
9
+ s.required_ruby_version = '>= 1.9.3'
10
+
11
+ s.license = 'Apache License (2.0)'
12
+
13
+ s.author = 'Killbill core team'
14
+ s.email = 'killbilling-users@googlegroups.com'
15
+ s.homepage = 'http://killbill.io'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.bindir = 'bin'
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ['lib']
22
+
23
+ s.rdoc_options << '--exclude' << '.'
24
+
25
+ s.add_dependency 'killbill', '~> 6.2'
26
+ s.add_dependency 'kpm', '~> 0.1'
27
+
28
+ s.add_development_dependency 'jbundler', '~> 0.4.3'
29
+ s.add_development_dependency 'rake', '>= 10.0.0'
30
+ s.add_development_dependency 'rspec', '~> 2.12.0'
31
+ end
@@ -0,0 +1,3 @@
1
+ mainClass=KPM::Listener
2
+ require=kpm_plugin
3
+ pluginType=NOTIFICATION
@@ -0,0 +1,91 @@
1
+ configure do
2
+ # Usage: bundle exec rackup -Ilib -E test
3
+ if development? or test?
4
+ require 'logger'
5
+ ::KPM::PluginsInstaller.instance.initialize!('/var/tmp/bundles/plugins/ruby/kpm/0.0.1',
6
+ File.expand_path(File.dirname(__FILE__) + '../../../'),
7
+ nil,
8
+ Logger.new(STDOUT))
9
+ end
10
+ end
11
+
12
+ # Lookup plugins
13
+ get '/plugins/killbill-kpm/plugins', :provides => 'json' do
14
+ artifact_id = params[:artifact_id] || params[:name]
15
+ latest = params[:latest] == 'false' ? false : true
16
+
17
+ if artifact_id.nil?
18
+ ::KPM::PluginsInstaller.instance.all(latest).to_json
19
+ else
20
+ group_id, artifact_id, packaging, classifier, version, type = ::KPM::PluginsInstaller.instance.lookup artifact_id, latest
21
+
22
+ if artifact_id.nil?
23
+ status 404
24
+ else
25
+ {
26
+ :group_id => group_id,
27
+ :artifact_id => artifact_id,
28
+ :packaging => packaging,
29
+ :classifier => classifier,
30
+ :version => version,
31
+ :type => type
32
+ }.to_json
33
+ end
34
+ end
35
+ end
36
+
37
+ # Install a plugin
38
+ post '/plugins/killbill-kpm/plugins', :provides => 'json' do
39
+ if !request.body.nil?
40
+ type = (params[:type] || 'java').downcase
41
+
42
+ info = Dir.mktmpdir do |dir|
43
+ plugin_path = File.join(dir, params[:filename] || "#{params[:name]}.#{type == 'java' ? 'jar' : 'tar.gz'}")
44
+ File.open(plugin_path, 'w') do |file|
45
+ file.write(request.body.read)
46
+ end
47
+ ::KPM::PluginsInstaller.instance.install_from_fs plugin_path,
48
+ params[:name],
49
+ params[:version],
50
+ type
51
+ end
52
+ else
53
+ info = ::KPM::PluginsInstaller.instance.install params[:artifact_id] || params[:name],
54
+ params[:version],
55
+ params[:group_id],
56
+ params[:packaging],
57
+ params[:classifier],
58
+ params[:type],
59
+ params[:force_download]
60
+ end
61
+
62
+ if info.nil?
63
+ status 400
64
+ else
65
+ info.to_json
66
+ end
67
+ end
68
+
69
+ # Uninstall a plugin
70
+ delete '/plugins/killbill-kpm/plugins', :provides => 'json' do
71
+ modified = ::KPM::PluginsInstaller.instance.uninstall params[:name],
72
+ params[:version]
73
+
74
+ if modified.empty?
75
+ status 404
76
+ else
77
+ modified.to_json
78
+ end
79
+ end
80
+
81
+ # Restart a plugin
82
+ put '/plugins/killbill-kpm/plugins', :provides => 'json' do
83
+ modified = ::KPM::PluginsInstaller.instance.restart params[:name],
84
+ params[:version]
85
+
86
+ if modified.empty?
87
+ status 404
88
+ else
89
+ modified.to_json
90
+ end
91
+ end
@@ -0,0 +1,94 @@
1
+ require 'nexus_cli'
2
+
3
+ module KPM
4
+ class Listener < Killbill::Plugin::Notification
5
+
6
+ def start_plugin
7
+ super
8
+
9
+ ::KPM::PluginsInstaller.instance.initialize!(@root, @conf_dir, @kb_apis, @logger)
10
+ end
11
+
12
+ def on_event(event)
13
+ return unless [:BROADCAST_SERVICE].include?(event.event_type)
14
+
15
+ unless ::KPM::PluginsInstaller.instance.initialized?
16
+ @logger.warn "KPM plugin wasn't started properly - check logs"
17
+ return
18
+ end
19
+
20
+ broadcast_metadata = event.meta_data.nil? ? {} : JSON.parse(event.meta_data)
21
+ command = broadcast_metadata['commandType']
22
+ return if command != 'INSTALL_PLUGIN' && command != 'UNINSTALL_PLUGIN'
23
+
24
+ service = broadcast_metadata['service']
25
+ event_json = broadcast_metadata['eventJson'].nil? ? {} : JSON.parse(broadcast_metadata['eventJson'])
26
+
27
+ properties = properties_to_hash(event_json['properties'])
28
+
29
+ @logger.info "Received #{event.event_type} event: service=#{service} command=#{command} event=#{event_json}"
30
+
31
+ return if !validate_inputs(command, properties, Proc.new { |command, properties, property_name|
32
+ if properties[property_name].nil?
33
+ @logger.info("Cannot run #{command}: missing property #{property_name}")
34
+ return false
35
+ end
36
+ })
37
+
38
+ handle_event(command,
39
+ properties['pluginKey'],
40
+ properties['pluginName'],
41
+ properties['pluginArtifactId'],
42
+ properties['pluginVersion'],
43
+ properties['pluginGroupId'],
44
+ properties['pluginPackaging'],
45
+ properties['pluginClassifier'],
46
+ properties['pluginType'],
47
+ properties['forceDownload'] == 'true')
48
+ end
49
+
50
+ private
51
+
52
+ # Check for mandatory properties
53
+ def validate_inputs(command, properties, proc_validation)
54
+ # For installation we allow either to pass the pluginKey (entry in plugins_directory.yml), or the full pluginGroupId/pluginArtifactId/pluginVersion/pluginType
55
+ if command == 'INSTALL_PLUGIN'
56
+ if properties['pluginKey'].nil?
57
+ proc_validation.call(command, properties, 'pluginGroupId')
58
+ proc_validation.call(command, properties, 'pluginArtifactId')
59
+ proc_validation.call(command, properties, 'pluginVersion')
60
+ proc_validation.call(command, properties, 'pluginType')
61
+ end
62
+ return true
63
+ elsif command == 'UNINSTALL_PLUGIN'
64
+ proc_validation.call(command, properties, 'pluginName')
65
+ return true
66
+ end
67
+ end
68
+
69
+ def handle_event(command, plugin_key, plugin_name, artifact_id, version=nil, group_id=nil, packaging=nil, classifier=nil, type=nil, force_download=false)
70
+ @logger.info "handle_event command=#{command}, plugin_key=#{plugin_key}, plugin_name=#{plugin_name}, artifact_id=#{artifact_id}, version=#{version}, group_id=#{group_id}, packaging=#{packaging}, classifier=#{classifier}, type=#{type}, force_download=#{force_download}"
71
+
72
+ if command == 'INSTALL_PLUGIN'
73
+ plugin_key_or_artifact_id = plugin_key ? plugin_key : artifact_id
74
+ ::KPM::PluginsInstaller.instance.install(plugin_key_or_artifact_id, version, group_id, packaging, classifier, type, force_download)
75
+ elsif command == 'UNINSTALL_PLUGIN'
76
+ ::KPM::PluginsInstaller.instance.uninstall(plugin_name, version)
77
+ else
78
+ @logger.warn("Ignoring unsupported command #{command}")
79
+ end
80
+ rescue NexusCli::ArtifactNotFoundException
81
+ @logger.warn("Unable to #{command} #{plugin_name}: artifact was not found in Nexus")
82
+ end
83
+
84
+ def properties_to_hash(properties)
85
+ return {} if properties.nil?
86
+
87
+ h = {}
88
+ properties.each do |prop|
89
+ h[prop['key']] = prop['value']
90
+ end
91
+ h
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,113 @@
1
+ module KPM
2
+ class PluginsInstaller
3
+ include Singleton
4
+
5
+ attr_reader :initialized
6
+ alias_method :initialized?, :initialized
7
+
8
+ def initialize!(root_dir, conf_dir, kb_apis, logger)
9
+ @kb_apis = kb_apis
10
+ @logger = logger
11
+
12
+ configure!(Pathname.new(conf_dir).expand_path.join('kpm.yml'))
13
+
14
+ @bundles_dir = Pathname.new(root_dir).join('..').join('..').join('..').join('..').expand_path
15
+ plugins_dir = @bundles_dir.join('plugins')
16
+
17
+ @installer = ::KPM::BaseInstaller.new(@logger, @glob_config[:kpm][:nexus], @glob_config[:kpm][:ssl_verify])
18
+ @manager = ::KPM::PluginsManager.new(plugins_dir, @logger)
19
+
20
+ @initialized = true
21
+ end
22
+
23
+ # If an earlier version of the plugin is installed, Kill Bill will only start the latest one (see org.killbill.billing.osgi.FileInstall)
24
+ def install(specified_artifact_id, specified_version=nil, specified_group_id=nil, specified_packaging=nil, specified_classifier=nil, specified_type=nil, force_download=false)
25
+ @logger.info("Instructed to install artifact_id=#{specified_artifact_id} version=#{specified_version} group_id=#{specified_group_id} packaging=#{specified_packaging} classifier=#{specified_classifier} type=#{specified_type} force_download=#{force_download}")
26
+ info = @installer.install_plugin(specified_group_id, specified_artifact_id, specified_packaging, specified_classifier, specified_version, @bundles_dir, specified_type, force_download, @glob_config[:kpm][:verify_sha1])
27
+ if info.nil?
28
+ @logger.warn("Error during installation of plugin #{artifact_id}")
29
+ else
30
+ path = info[:bundle_dir] ? info[:bundle_dir] : info[:dir_name]
31
+ notify_fs_change(path, :NEW_VERSION)
32
+ end
33
+ info
34
+ end
35
+
36
+ def install_from_fs(file_path, name, version, type)
37
+ @logger.info("Instructed to install file_path=#{file_path} name=#{name} version=#{version} type=#{type}")
38
+ info = @installer.install_plugin_from_fs(file_path, name, version, @bundles_dir, type)
39
+ if info.nil?
40
+ @logger.warn("Error during installation of plugin #{name}")
41
+ else
42
+ notify_fs_change(info[:bundle_dir], :NEW_VERSION)
43
+ end
44
+ info
45
+ end
46
+
47
+ def uninstall(plugin_name, version=nil)
48
+ modified = @manager.uninstall(plugin_name, version || :all)
49
+ modified.each do |path|
50
+ notify_fs_change(path, :DISABLED)
51
+ end
52
+ end
53
+
54
+ def restart(plugin_name, version=nil)
55
+ @manager.restart(plugin_name, version || :all)
56
+ end
57
+
58
+ def lookup(artifact_id, latest=true)
59
+ KPM::PluginsDirectory.lookup(artifact_id, latest)
60
+ end
61
+
62
+ def all(latest=true)
63
+ KPM::PluginsDirectory.all(latest)
64
+ end
65
+
66
+ private
67
+
68
+ def notify_fs_change(path, state)
69
+ return if path.nil?
70
+
71
+ # Plugin name should be the directory name (path is something like /var/tmp/bundles/plugins/ruby/killbill-stripe/2.0.0)
72
+ fs_info = path.to_s.split('/')
73
+ plugin_type = fs_info[-3].upcase
74
+
75
+ unless %w(JAVA RUBY).include?(plugin_type)
76
+ @logger.warn("Invalid plugin type #{plugin_type} (path #{path}): Kill Bill won't be notified of new state #{state}")
77
+ return
78
+ end
79
+
80
+ if @kb_apis.nil?
81
+ @logger.warn("APIs not configured: Kill Bill won't be notified of new state #{state}")
82
+ return
83
+ end
84
+
85
+ plugin_name = fs_info[-2]
86
+ plugin_version = fs_info[-1]
87
+ @logger.info("Notifying Kill Bill: state=#{state} plugin_name=#{plugin_name} plugin_version=#{plugin_version} plugin_type=#{plugin_type}")
88
+ @kb_apis.plugins_info_api.notify_of_state_changed(state, plugin_name, plugin_version, plugin_type)
89
+ end
90
+
91
+ def configure!(config_file)
92
+ @glob_config = {}
93
+
94
+ # Look for global config
95
+ if !config_file.blank? && Pathname.new(config_file).file?
96
+ @glob_config = ::Killbill::Plugin::ActiveMerchant::Properties.new(config_file)
97
+ @glob_config.parse!
98
+ @glob_config = @glob_config.to_hash
99
+ end
100
+
101
+ @glob_config[:kpm] ||= {}
102
+
103
+ @glob_config[:kpm][:nexus] ||= {}
104
+ @glob_config[:kpm][:nexus][:url] ||= 'https://oss.sonatype.org'
105
+ @glob_config[:kpm][:nexus][:repository] ||= 'releases'
106
+
107
+ @glob_config[:kpm][:ssl_verify] = true if @glob_config[:kpm][:ssl_verify].nil?
108
+ @glob_config[:kpm][:verify_sha1] = true if @glob_config[:kpm][:verify_sha1].nil?
109
+
110
+ @logger.level = Logger::DEBUG if (@glob_config[:logger] || {})[:debug]
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,13 @@
1
+ require 'active_support/core_ext/object/blank'
2
+ require 'json'
3
+ require 'pathname'
4
+ require 'sinatra'
5
+ require 'yaml'
6
+
7
+ require 'kpm'
8
+
9
+ require 'killbill'
10
+ require 'killbill/helpers/active_merchant/properties'
11
+
12
+ require 'kpm/plugins_installer'
13
+ require 'kpm/listener'
data/pom.xml ADDED
@@ -0,0 +1,44 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!--
3
+ ~ Copyright 2014-2015 The Billing Project, LLC
4
+ ~
5
+ ~ The Billing Project licenses this file to you under the Apache License, version 2.0
6
+ ~ (the "License"); you may not use this file except in compliance with the
7
+ ~ License. You may obtain a copy of the License at:
8
+ ~
9
+ ~ http://www.apache.org/licenses/LICENSE-2.0
10
+ ~
11
+ ~ Unless required by applicable law or agreed to in writing, software
12
+ ~ distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
+ ~ WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14
+ ~ License for the specific language governing permissions and limitations
15
+ ~ under the License.
16
+ -->
17
+
18
+ <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
19
+ <parent>
20
+ <groupId>org.sonatype.oss</groupId>
21
+ <artifactId>oss-parent</artifactId>
22
+ <version>5</version>
23
+ </parent>
24
+ <modelVersion>4.0.0</modelVersion>
25
+ <groupId>org.kill-bill.billing.plugin.ruby</groupId>
26
+ <artifactId>kpm-plugin</artifactId>
27
+ <packaging>pom</packaging>
28
+ <version>0.0.2</version>
29
+ <name>kpm-plugin</name>
30
+ <url>http://github.com/killbill/killbill-kpm-plugin</url>
31
+ <description>Kill Bill KPM plugin</description>
32
+ <licenses>
33
+ <license>
34
+ <name>Apache License 2.0</name>
35
+ <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
36
+ <distribution>repo</distribution>
37
+ </license>
38
+ </licenses>
39
+ <scm>
40
+ <connection>scm:git:git://github.com/killbill/killbill-kpm-plugin.git</connection>
41
+ <url>https://github.com/killbill/killbill-kpm-plugin/</url>
42
+ <developerConnection>scm:git:git@github.com:killbill/killbill-kpm-plugin.git</developerConnection>
43
+ </scm>
44
+ </project>