foreman_content 0.1

Sign up to get free protection for your applications and to get access to all the features.
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