foreman_content 0.1

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 (81) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +113 -0
  3. data/Rakefile +111 -0
  4. data/app/assets/javascripts/content/content.js +12 -0
  5. data/app/assets/stylesheets/content/application.css +13 -0
  6. data/app/controllers/content/api/repositories_controller.rb +27 -0
  7. data/app/controllers/content/gpg_keys_controller.rb +42 -0
  8. data/app/controllers/content/products_controller.rb +51 -0
  9. data/app/controllers/content/repositories_controller.rb +57 -0
  10. data/app/helpers/content/application_helper.rb +5 -0
  11. data/app/helpers/content/repositories_helper.rb +56 -0
  12. data/app/models/content/custom_repository_paths.rb +27 -0
  13. data/app/models/content/environment_product.rb +19 -0
  14. data/app/models/content/gpg_key.rb +32 -0
  15. data/app/models/content/host_product.rb +20 -0
  16. data/app/models/content/hostgroup_product.rb +19 -0
  17. data/app/models/content/operatingsystem_repository.rb +19 -0
  18. data/app/models/content/orchestration/pulp.rb +93 -0
  19. data/app/models/content/product.rb +28 -0
  20. data/app/models/content/product_operatingsystem.rb +19 -0
  21. data/app/models/content/remote/pulp/repository.rb +46 -0
  22. data/app/models/content/repository.rb +70 -0
  23. data/app/models/content/validators/content_validator.rb +25 -0
  24. data/app/models/content/validators/description_format.rb +24 -0
  25. data/app/models/content/validators/name_format.rb +40 -0
  26. data/app/models/content/validators/no_trailing_space.rb +27 -0
  27. data/app/models/setting/content.rb +42 -0
  28. data/app/overrides/add_host_conent_tab.rb +9 -0
  29. data/app/overrides/add_hostgroup_conent_tab.rb +9 -0
  30. data/app/overrides/add_os_conent_tab.rb +9 -0
  31. data/app/services/content/pulp_event_handler.rb +25 -0
  32. data/app/views/content/gpg_keys/_form.html.erb +8 -0
  33. data/app/views/content/gpg_keys/edit.html.erb +3 -0
  34. data/app/views/content/gpg_keys/index.html.erb +20 -0
  35. data/app/views/content/gpg_keys/new.html.erb +3 -0
  36. data/app/views/content/products/_form.html.erb +26 -0
  37. data/app/views/content/products/_form_tab.html.erb +3 -0
  38. data/app/views/content/products/_host_tab_pane.html.erb +5 -0
  39. data/app/views/content/products/_hostgroup_tab_pane.html.erb +5 -0
  40. data/app/views/content/products/_operatingsystem_tab_pane.html.erb +5 -0
  41. data/app/views/content/products/edit.html.erb +3 -0
  42. data/app/views/content/products/index.html.erb +27 -0
  43. data/app/views/content/products/new.html.erb +3 -0
  44. data/app/views/content/products/welcome.html.erb +8 -0
  45. data/app/views/content/repositories/_form.html.erb +30 -0
  46. data/app/views/content/repositories/edit.html.erb +3 -0
  47. data/app/views/content/repositories/index.html.erb +32 -0
  48. data/app/views/content/repositories/new.html.erb +3 -0
  49. data/app/views/content/repositories/show.html.erb +98 -0
  50. data/app/views/content/repositories/welcome.html.erb +8 -0
  51. data/config/routes.rb +36 -0
  52. data/db/migrate/20130702140034_create_content_repositories.rb +19 -0
  53. data/db/migrate/20130702162629_create_content_products.rb +10 -0
  54. data/db/migrate/20130709001120_create_content_gpg_keys.rb +10 -0
  55. data/db/migrate/20130717032320_create_content_environments_products.rb +9 -0
  56. data/db/migrate/20130722084911_create_content_operatingsystem_repositories.rb +9 -0
  57. data/db/migrate/20130723084911_create_content_hostgroup_products.rb +9 -0
  58. data/db/migrate/20130723124911_create_content_host_products.rb +9 -0
  59. data/db/migrate/20130729032320_create_content_product_operatingsystems.rb +9 -0
  60. data/lib/content/engine.rb +59 -0
  61. data/lib/content/version.rb +3 -0
  62. data/lib/content_environment.rb +13 -0
  63. data/lib/content_home_helper_patch.rb +23 -0
  64. data/lib/content_host.rb +55 -0
  65. data/lib/content_hostgroup.rb +22 -0
  66. data/lib/content_operatingsystem.rb +17 -0
  67. data/lib/content_redhat.rb +36 -0
  68. data/lib/content_taxonomy.rb +18 -0
  69. data/lib/foreman_content.rb +4 -0
  70. data/lib/pulp_configuration.rb +23 -0
  71. data/lib/tasks/content_tasks.rake +4 -0
  72. data/test/content_test.rb +7 -0
  73. data/test/fixtures/content/products.yml +11 -0
  74. data/test/fixtures/content/repositories.yml +11 -0
  75. data/test/integration/navigation_test.rb +10 -0
  76. data/test/test_helper.rb +23 -0
  77. data/test/unit/content/description_format_validator_test.rb +20 -0
  78. data/test/unit/content/name_format_validator_test.rb +28 -0
  79. data/test/unit/content/product_validation_test.rb +18 -0
  80. data/test/unit/content/repositories_test.rb +7 -0
  81. metadata +194 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 66165cc1d29ef234bd0d15923511264f87045b55
4
+ data.tar.gz: 2166c67ba266eaf2c9d478ba4e64839fb7a703a9
5
+ SHA512:
6
+ metadata.gz: 851db5cbe0dda9500b5bd6d30506d4ab63c565e0802cd5365b81a1b5a53c15d3362410e3ae347fbe82dc1da385c8e881953f72117253925bcc973916e3d0f444
7
+ data.tar.gz: c202eedf2998d5baca4d8a76ad2df98c745b280fd2a02726ae604c43477aea38a2c1a658e0b9bbea85276a518fa9e6623fa7b1db78247e5da2dfd3d728428377
data/README.md ADDED
@@ -0,0 +1,113 @@
1
+ # foreman\_content
2
+
3
+ This plugin aims to enable repository synconrinzation and managament in Foreman. It is of alpha quality
4
+ right now and currently handles only yum/rpm repositories ;)
5
+
6
+ # Dependencies
7
+
8
+ * Foreman running development or 1.2.1 (maybe 1.2 but was not tested)
9
+ * You must have a fully working pulp server, see http://www.pulpproject.org/docs/
10
+
11
+
12
+ # Installation
13
+
14
+ Require the gem in Foreman by creating `bundler.d/Gemfile.local.rb` with the
15
+ following:
16
+
17
+ ```
18
+ gem 'foreman_content'
19
+ ```
20
+
21
+ Update & Restart Foreman:
22
+ ```
23
+ bundle update
24
+ rake db:migrate
25
+ touch tmp/restart.txt (if using passeger)
26
+ ```
27
+
28
+ # Configuration
29
+
30
+ ## Pulp
31
+ * enable oauth authentication
32
+
33
+ ## UI config
34
+
35
+ You would need to allow foreman to communicate with pulp, under More ->
36
+ Settings -> Content, you would need to enable pulp, and set the pulp url and
37
+ oauth creds, for example:
38
+
39
+ * pulp_oauth_key foreman
40
+ * pulp_oauth_secret super_secret
41
+ * pulp_url https://pulp.server.com/pulp/api/v2/
42
+ * use_pulp true
43
+
44
+ # Usage
45
+
46
+ ## Setting up
47
+
48
+ You would see in the UI under More, a new sub menu called content, in it:
49
+
50
+ * Product - The actual product you are managing, for example CentOS 6
51
+ * Repository - list of repositories that belong to the above product, for
52
+ example, CentOS 6.4 + CentOS updates.
53
+
54
+ ## Syncing Repositories
55
+
56
+ Under Content -> Repository create a new repo
57
+
58
+ * Name - user friendly name, this would be reflected later on in yum configuration
59
+ * Feed URL - where we are cloning from, normally a public mirror
60
+ * Content type - Kickstart (e.g. bootable) or a plain yum repo, if the repo
61
+ contains a full OS, choose kickstart, later on foreman would use that instead
62
+ of an Installation media.
63
+ * Architecture - type of files within the repo, usually X86_64 or noarch etc.
64
+ * Operating Systems - list of valid OS's that this repo applies to.
65
+ * Enabled - true / false
66
+ * Unprotected - weather pulp should expose this repo via http and https or just
67
+ over https.
68
+ * Product - the product from above.
69
+ * GPG key - not implemented
70
+
71
+ Once created, the repo would automatically be synced and published.
72
+
73
+ ## Consuming Repos within your Kickstart
74
+
75
+ Once a kickstart repo has been assigned to an OS, it would automatically prefer
76
+ that repo as an install media, so if that is all you want to do, its done
77
+ automatically.
78
+
79
+ if you wish to add more yum type repos during KS, you may add the following
80
+ snippet to your provisioning template.
81
+
82
+ ```erb
83
+ <% @repos.each do |repo| %>
84
+ repo --name=<%= repo[:name] %> --baseurl=<%= repo[:baseurl] %>
85
+ <% end %>
86
+ ```
87
+
88
+ ## Consuming Repos with Puppet
89
+
90
+ Assuming you are using puppet with ENC functionality, its pretty simple to
91
+ let puppet manage the repositories, Foreman would expose all repository
92
+ information via the ENC as a global parameter, you can later on simply consume
93
+ it with create resources, e.g:
94
+
95
+ ```puppet
96
+ if $::repositories {
97
+ create_resources('yumrepo', $::repositories)
98
+ }
99
+ ```
100
+
101
+ ## Callback notifications from pulp
102
+
103
+ Pulp can notify foreman when events happen (e.g. repo sync is finished etc), in
104
+ order to configure it run on your pulp server:
105
+
106
+ ```
107
+ pulp-admin event listener http create --event-type '*' --url https://foreman.example.com/api/repositories/events
108
+ ```
109
+
110
+ # TODO
111
+
112
+ * https://trello.com/b/NtzVcPkD/foreman-backlog
113
+ filter engine spike
data/Rakefile ADDED
@@ -0,0 +1,111 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'fileutils'
6
+
7
+ task :default => :test
8
+
9
+ ENGINE_DIR = File.expand_path('..', __FILE__)
10
+ FOREMAN_DIR = 'test/foreman_app'
11
+
12
+ namespace :test do
13
+ desc "Download latest foreman devel source and install dependencies"
14
+ task :foreman_prepare do
15
+ foreman_repo = 'https://github.com/theforeman/foreman.git'
16
+ foreman_gemfile = File.join(FOREMAN_DIR, "Gemfile")
17
+ unless File.exists?(foreman_gemfile)
18
+ puts "Foreman source code is not present at #{FOREMAN_DIR}"
19
+ puts "Downloading latest Foreman development branch into #{FOREMAN_DIR}..."
20
+ FileUtils.mkdir_p(FOREMAN_DIR)
21
+
22
+ unless system("git clone #{foreman_repo} #{FOREMAN_DIR}")
23
+ puts "Error while getting latest Foreman code from #{foreman_repo} into #{FOREMAN_DIR}"
24
+ fail
25
+ end
26
+ end
27
+
28
+ gemfile_content = File.read(foreman_gemfile)
29
+ unless gemfile_content.include?('FOREMAN_GEMFILE')
30
+ puts 'Preparing Gemfile'
31
+ gemfile_content.gsub!('__FILE__', 'FOREMAN_GEMFILE')
32
+ gemfile_content.insert(0, "FOREMAN_GEMFILE = __FILE__ unless defined? FOREMAN_GEMFILE\n")
33
+ File.open(foreman_gemfile, 'w') { |f| f << gemfile_content }
34
+ end
35
+
36
+ settings_file = "#{FOREMAN_DIR}/config/settings.yaml"
37
+ unless File.exists?(settings_file)
38
+ puts 'Preparing settings file'
39
+ FileUtils.copy("#{settings_file}.example", settings_file)
40
+ settings_content = File.read(settings_file)
41
+ settings_content.sub!('organizations_enabled: false', 'organizations_enabled: true')
42
+ settings_content << ":puppetgem: true\n"
43
+ File.open(settings_file, 'w') { |f| f << settings_content }
44
+ end
45
+
46
+ db_file = "#{FOREMAN_DIR}/config/database.yml"
47
+ unless File.exists?(db_file)
48
+ puts 'Preparing database file'
49
+ FileUtils.copy("#{db_file}.example", db_file)
50
+ end
51
+
52
+ ["#{ENGINE_DIR}/.bundle/config", "#{FOREMAN_DIR}/.bundle/config"].each do |bundle_file|
53
+ unless File.exists?(bundle_file)
54
+ FileUtils.mkdir_p(File.dirname(bundle_file))
55
+ puts 'Preparing bundler configuration'
56
+ File.open(bundle_file, 'w') { |f| f << <<FILE }
57
+ ---
58
+ BUNDLE_WITHOUT: console:development:fog:jsonp:libvirt:mysql:mysql2:ovirt:postgresql:vmware
59
+ FILE
60
+ end
61
+ end
62
+
63
+ local_gemfile = "#{FOREMAN_DIR}/bundler.d/Gemfile.local.rb"
64
+ unless File.exist?(local_gemfile)
65
+ File.open(local_gemfile, 'w') { |f| f << <<GEMFILE }
66
+ gem "puppet"
67
+ gem "facter"
68
+ GEMFILE
69
+ end
70
+
71
+ puts 'Installing dependencies...'
72
+ unless system('bundle install')
73
+ fail
74
+ end
75
+ end
76
+
77
+ task :db_prepare do
78
+ unless File.exists?(FOREMAN_DIR)
79
+ puts <<MESSAGE
80
+ Foreman source code not prepared. Run
81
+
82
+ rake test:foreman_prepare
83
+
84
+ to download foreman source and its dependencies
85
+ MESSAGE
86
+ fail
87
+ end
88
+
89
+ # once we are Ruby19 only, switch to block variant of cd
90
+ pwd = FileUtils.pwd
91
+ FileUtils.cd(FOREMAN_DIR)
92
+ unless system('rake db:test:prepare RAILS_ENV=test')
93
+ puts "Migrating database first"
94
+ system('rake db:migrate db:schema:dump db:test:prepare RAILS_ENV=test') || fail
95
+ end
96
+ FileUtils.cd(pwd)
97
+ end
98
+
99
+ task :set_loadpath do
100
+ %w[lib test].each do |dir|
101
+ $:.unshift(File.expand_path(dir, ENGINE_DIR))
102
+ end
103
+ end
104
+
105
+ task :all => [:db_prepare, :set_loadpath] do
106
+ Dir.glob('test/**/*_test.rb') { |f| require f.sub('test/','') unless f.include? '/foreman_app/' }
107
+ end
108
+
109
+ end
110
+
111
+ task :test => 'test:all'
@@ -0,0 +1,12 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,27 @@
1
+ module Content
2
+ module Api
3
+ class RepositoriesController < ::Api::V2::BaseController
4
+
5
+ before_filter :validate_access_to_events, :only => :events
6
+ skip_before_filter :authorize, :only => :events
7
+
8
+ # callback event from pulp upon tasks/events finished up
9
+ def events
10
+ if (repo_id = params['payload'] && params['payload']['repo_id'])
11
+ repo = Content::Repository.where(:pulp_id => repo_id).first
12
+ end
13
+ render_error 'not_found', :status => :not_found and return false if repo.nil?
14
+ PulpEventHandler.new(repo_id, params)
15
+ head :status => 202
16
+ end
17
+
18
+ private
19
+
20
+ def validate_access_to_events
21
+ #validate our pulp server here
22
+ # we really want to use existing smart proxy infrastructure to do this.
23
+ true
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,42 @@
1
+ module Content
2
+ class GpgKeysController < ::ApplicationController
3
+ include Foreman::Controller::AutoCompleteSearch
4
+ before_filter :find_by_name, :only => %w{show edit update destroy}
5
+
6
+ def index
7
+ @gpg_keys = GpgKey.search_for(params[:search], :order => params[:order]).paginate(:page => params[:page])
8
+ end
9
+
10
+ def new
11
+ @gpg_key = GpgKey.new
12
+ end
13
+
14
+ def create
15
+ @gpg_key = GpgKey.new(params[:content_gpg_key])
16
+ if @gpg_key.save
17
+ process_success
18
+ else
19
+ process_error
20
+ end
21
+ end
22
+
23
+ def edit
24
+ end
25
+
26
+ def update
27
+ if @gpg_key.update_attributes(params[:content_gpg_key])
28
+ process_success
29
+ else
30
+ process_error
31
+ end
32
+ end
33
+
34
+ def destroy
35
+ if @gpg_key.destroy
36
+ process_success
37
+ else
38
+ process_error
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,51 @@
1
+ module Content
2
+ class ProductsController < ::ApplicationController
3
+ include Foreman::Controller::AutoCompleteSearch
4
+ before_filter :find_by_name, :only => %w{show edit update destroy sync}
5
+
6
+ def index
7
+ @products = Product.search_for(params[:search], :order => params[:order]).
8
+ paginate(:page => params[:page])
9
+ @counter = Repository.group(:product_id).where(:product_id => @products.map(&:id)).count
10
+ end
11
+
12
+ def new
13
+ @product = Product.new
14
+ end
15
+
16
+ def create
17
+ @product = Product.new(params[:content_product])
18
+ if @product.save
19
+ process_success
20
+ else
21
+ process_error
22
+ end
23
+ end
24
+
25
+ def edit
26
+ end
27
+
28
+ def update
29
+ if @product.update_attributes(params[:content_product])
30
+ process_success
31
+ else
32
+ process_error
33
+ end
34
+ end
35
+
36
+ def sync
37
+ @product.sync
38
+ process_success(:success_msg => _("Successfully started sync for %s") % @product.name)
39
+ rescue => e
40
+ process_error(:error_msg => _("Failed to start sync for %s") % @product.name)
41
+ end
42
+
43
+ def destroy
44
+ if @product.destroy
45
+ process_success
46
+ else
47
+ process_error
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,57 @@
1
+ module Content
2
+ class RepositoriesController < ::ApplicationController
3
+ include Foreman::Controller::AutoCompleteSearch
4
+ before_filter :find_by_name, :only => %w{show edit update destroy sync}
5
+
6
+ def index
7
+ @repositories = Repository.search_for(params[:search], :order => params[:order]).
8
+ paginate(:page => params[:page]).includes(:product, :operatingsystems)
9
+ end
10
+
11
+ def new
12
+ @repository = Repository.new(:unprotected => true)
13
+ end
14
+
15
+ def create
16
+ @repository = Repository.new(params[:content_repository])
17
+ if @repository.save
18
+ process_success
19
+ else
20
+ process_error
21
+ end
22
+ end
23
+
24
+ def edit
25
+ end
26
+
27
+ def update
28
+ if @repository.update_attributes(params[:content_repository])
29
+ process_success
30
+ else
31
+ process_error
32
+ end
33
+ end
34
+
35
+ def show
36
+ @details = @repository.retrieve_with_details
37
+ @sync_history = @repository.sync_history
38
+ rescue
39
+ redirect_back_or_to(edit_repository_path)
40
+ end
41
+
42
+ def destroy
43
+ if @repository.destroy
44
+ process_success
45
+ else
46
+ process_error
47
+ end
48
+ end
49
+
50
+ def sync
51
+ @repository.sync
52
+ process_success(:success_msg => _("Successfully started sync for %s") % @repository.to_label)
53
+ rescue => e
54
+ process_error(:error_msg => _("Failed to start sync for %s") % @repository.to_label)
55
+ end
56
+ end
57
+ end