killbill-kpm 0.0.1 → 0.0.2

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.
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>