katello-foreman-engine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile ADDED
@@ -0,0 +1,90 @@
1
+ ENGINE_DIR = File.expand_path('..', __FILE__)
2
+ KATELLO_DIR = 'test/katello_app'
3
+ require 'fileutils'
4
+
5
+ namespace :test do
6
+ desc "Download latest katello devel source and install dependencies"
7
+ task :katello_prepare do
8
+ katello_repo = 'https://github.com/Katello/katello.git'
9
+ katello_gemfile = File.join(KATELLO_DIR, "Gemfile")
10
+ unless File.exists?(katello_gemfile)
11
+ puts "Katello source code is not present at #{KATELLO_DIR}"
12
+ puts "Downloading latest Katello development branch into #{KATELLO_DIR}..."
13
+ FileUtils.mkdir_p(KATELLO_DIR)
14
+
15
+ unless system("git clone #{katello_repo} #{KATELLO_DIR}")
16
+ puts "Error while getting latest Katello code from #{katello_repo} into #{KATELLO_DIR}"
17
+ fail
18
+ end
19
+ end
20
+
21
+ gemfile_content = File.read(katello_gemfile)
22
+ unless gemfile_content.include?('KATELLO_GEMFILE')
23
+ puts 'Preparing Gemfile'
24
+ gemfile_content.gsub!('__FILE__', 'KATELLO_GEMFILE')
25
+ gemfile_content.insert(0, "KATELLO_GEMFILE = __FILE__ unless defined? KATELLO_GEMFILE\n")
26
+ File.open(katello_gemfile, 'w') { |f| f << gemfile_content }
27
+ end
28
+
29
+ settings_file = "#{KATELLO_DIR}/config/katello.yml"
30
+ unless File.exists?(settings_file)
31
+ puts 'Preparing settings file'
32
+ File.open(settings_file, "w") { |f| f << <<SETTINGS }
33
+ common:
34
+ foreman:
35
+ url: https://localhost/foreman/
36
+
37
+ SETTINGS
38
+ end
39
+
40
+ ["#{ENGINE_DIR}/.bundle/config", "#{KATELLO_DIR}/.bundle/config"].each do |bundle_file|
41
+ unless File.exists?(bundle_file)
42
+ FileUtils.mkdir_p(File.dirname(bundle_file))
43
+ puts 'Preparing bundler configuration'
44
+ File.open(bundle_file, 'w') { |f| f << <<FILE }
45
+ BUNDLE_WITHOUT: assets:checking:debugging:development_boost:optional
46
+ FILE
47
+ end
48
+ end
49
+
50
+ puts 'Installing dependencies...'
51
+ unless system('bundle install')
52
+ fail
53
+ end
54
+ end
55
+
56
+ task :db_prepare do
57
+ unless File.exists?(KATELLO_DIR)
58
+ puts <<MESSAGE
59
+ Katello source code not prepared. Run
60
+
61
+ rake test:katello_prepare
62
+
63
+ to download katello source and its dependencies
64
+ MESSAGE
65
+ fail
66
+ end
67
+
68
+ # once we are Ruby19 only, switch to block variant of cd
69
+ pwd = FileUtils.pwd
70
+ FileUtils.cd(KATELLO_DIR)
71
+ unless system('rake db:test:prepare RAILS_ENV=test')
72
+ puts "Migrating database first"
73
+ system('rake db:create db:migrate db:schema:dump db:test:prepare RAILS_ENV=test') || fail
74
+ end
75
+ FileUtils.cd(pwd)
76
+ end
77
+
78
+ task :set_loadpath do
79
+ %w[lib test].each do |dir|
80
+ $:.unshift(File.expand_path(dir, ENGINE_DIR))
81
+ end
82
+ end
83
+
84
+ task :all => [:db_prepare, :set_loadpath] do
85
+ Dir.glob('test/**/*_test.rb') { |f| require f.sub('test/','') unless f.include? '/katello_app/' }
86
+ end
87
+
88
+ end
89
+
90
+ task :test => 'test:all'
@@ -0,0 +1,17 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = "katello-foreman-engine"
3
+ s.version = "0.0.1"
4
+
5
+ s.authors = ["Katello"]
6
+ s.date = "2013-04-19"
7
+ s.description = "Foreman specific parts in Katello"
8
+ s.email = "katello-devel@redhat.com"
9
+ s.files = `git ls-files`.split("\n")
10
+ s.homepage = "http://github.com/katello/katello-foreman-engine"
11
+ s.licenses = ["GPL-2"]
12
+ s.require_paths = ["lib"]
13
+ s.add_dependency "foreman_api"
14
+ s.add_dependency "deface", "~> 0.7.2"
15
+ s.add_dependency "dynflow"
16
+ s.summary = "Foreman specific parts of Katello"
17
+ end
@@ -0,0 +1,2 @@
1
+ require 'deface'
2
+ require 'katello_foreman_engine'
@@ -0,0 +1,25 @@
1
+ module KatelloForemanEngine
2
+ module Actions
3
+ class ContentViewDemote < Dynflow::Action
4
+
5
+ def self.subscribe
6
+ Katello::Actions::ContentViewDemote
7
+ end
8
+
9
+ def plan(content_view, from_env)
10
+ if foreman_env = Bindings.environment_find(content_view.organization.label,
11
+ from_env.label, content_view.label)
12
+ plan_self 'foreman_env_id' => foreman_env['environment']['id']
13
+ end
14
+ end
15
+
16
+ input_format do
17
+ param :foreman_env_id, Integer
18
+ end
19
+
20
+ def run
21
+ Bindings.environment_destroy(input['foreman_env_id'])
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,28 @@
1
+ module KatelloForemanEngine
2
+ module Actions
3
+ class ContentViewPromote < Dynflow::Action
4
+
5
+ def self.subscribe
6
+ Katello::Actions::ContentViewPromote
7
+ end
8
+
9
+ def plan(*args)
10
+ unless Bindings.environment_find(input['organization_label'], input['to_env_label'], input['label'])
11
+ plan_self input
12
+ end
13
+ end
14
+
15
+ input_format do
16
+ param :id, Integer
17
+ param :label, String
18
+ param :organization_label, String
19
+ param :from_env_label, String
20
+ param :to_env_label, String
21
+ end
22
+
23
+ def run
24
+ Bindings.environment_create(input['id'], input['organization_label'], input['to_env_label'], input['label'])
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,26 @@
1
+ module KatelloForemanEngine
2
+ module Actions
3
+ class EnvironmentCreate < Dynflow::Action
4
+
5
+ def self.subscribe
6
+ Katello::Actions::EnvironmentCreate
7
+ end
8
+
9
+ def plan(env)
10
+ unless env.library?
11
+ plan_self 'org_label' => env.organization.label, 'label' => env.label, 'content_view_id' => 'env'
12
+ end
13
+ end
14
+
15
+ input_format do
16
+ param :org_label, String
17
+ param :label, String
18
+ param :content_view_id, String
19
+ end
20
+
21
+ def run
22
+ Bindings.environment_create(input['content_view_id'], input['org_label'], input['label'])
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ module KatelloForemanEngine
2
+ module Actions
3
+ class EnvironmentDestroy < Dynflow::Action
4
+
5
+ input_format do
6
+ param :foreman_id, String
7
+ end
8
+
9
+ def self.subscribe
10
+ Katello::Actions::EnvironmentDestroy
11
+ end
12
+
13
+ def plan(env)
14
+ if !env.library? && foreman_env = Bindings.environment_find(env.organization.label, env.label)
15
+ env.content_views.each do |content_view|
16
+ plan_action(ContentViewDemote, content_view, env)
17
+ end
18
+ plan_self 'foreman_id' => foreman_env['environment']['id']
19
+ end
20
+ end
21
+
22
+ def run
23
+ Bindings.environment_destroy(input['foreman_id'])
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,14 @@
1
+ module KatelloForemanEngine
2
+ module Actions
3
+ class OrgCreate < Dynflow::Action
4
+
5
+ def self.subscribe
6
+ Headpin::Actions::OrgCreate
7
+ end
8
+
9
+ def run
10
+ Bindings.organization_create("KT-[#{input['label']}]")
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,24 @@
1
+ module KatelloForemanEngine
2
+ module Actions
3
+ class OrgDestroy < Dynflow::Action
4
+
5
+ input_format do
6
+ param :foreman_id, String
7
+ end
8
+
9
+ def self.subscribe
10
+ Headpin::Actions::OrgDestroy
11
+ end
12
+
13
+ def plan(org)
14
+ if foreman_org = Bindings.organization_find("KT-[#{input['label']}]")
15
+ plan_self('foreman_id' => foreman_org['organization']['id'])
16
+ end
17
+ end
18
+
19
+ def run
20
+ Bindings.organization_destroy(input['foreman_id'])
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,20 @@
1
+ module KatelloForemanEngine
2
+ module Actions
3
+ class UserCreate < Dynflow::Action
4
+
5
+ def self.subscribe
6
+ Headpin::Actions::UserCreate
7
+ end
8
+
9
+ def plan(user)
10
+ if !user.hidden? && !Bindings.user_find(input['username'])
11
+ plan_self input
12
+ end
13
+ end
14
+
15
+ def run
16
+ Bindings.user_create(input['username'], input['email'])
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module KatelloForemanEngine
2
+ module Actions
3
+ class UserDestroy < Dynflow::Action
4
+
5
+ def self.subscribe
6
+ Headpin::Actions::UserDestroy
7
+ end
8
+
9
+ def plan(user)
10
+ if foreman_user = Bindings.user_find(input['username'])
11
+ plan_self 'foreman_user_id' => foreman_user['user']['id']
12
+ end
13
+ end
14
+
15
+ input_format do
16
+ param :foreman_user_id, String
17
+ end
18
+
19
+ def run
20
+ Bindings.user_destroy(input['foreman_user_id'])
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,101 @@
1
+ require 'foreman_api'
2
+
3
+ module KatelloForemanEngine
4
+ module Bindings
5
+
6
+ class << self
7
+
8
+ def client_config
9
+ {
10
+ :base_url => Settings['foreman_url'],
11
+ :enable_validations => false,
12
+ :oauth => {
13
+ :consumer_key => Settings['oauth_consumer_key'],
14
+ :consumer_secret => Settings['oauth_consumer_secret']
15
+ },
16
+ }
17
+ end
18
+
19
+ def base
20
+ resource(ForemanApi::Base)
21
+ end
22
+
23
+ def environment
24
+ resource(ForemanApi::Resources::Environment)
25
+ end
26
+
27
+ def user(username = nil)
28
+ user_resource = resource(ForemanApi::Resources::User)
29
+ if username && User.current.username == username
30
+ # this means the first user is created: use the predefined
31
+ # Foreman admin user for this cases.
32
+ user_resource.client.options[:headers][:foreman_user] = 'admin'
33
+ end
34
+ return user_resource
35
+ end
36
+
37
+ def resource(resource_class)
38
+ client = resource_class.new(client_config)
39
+ client.client.options[:headers][:foreman_user] = User.current.username
40
+ return client
41
+ end
42
+
43
+ def organization_find(name)
44
+ orgs, _ = base.http_call('get', '/api/organizations', 'search' => "name = #{name}")
45
+ return orgs.first
46
+ end
47
+
48
+ def organization_create(name)
49
+ base.http_call('post', '/api/organizations',
50
+ :organization => {:name => name,
51
+ :ignore_types => %w[User SmartProxy Subnet ComputeResource Medium ConfigTemplate Domain Environment] })
52
+ end
53
+
54
+ def organization_destroy(id)
55
+ base.http_call('delete', "/api/organizations/#{id}")
56
+ end
57
+
58
+
59
+ def environment_find(org_label, env_label, content_view_label = nil)
60
+ env, _ = base.http_call('get', '/foreman_katello_engine/api/environments/show',
61
+ {:org => org_label, :env => env_label, :content_view => content_view_label})
62
+ return env
63
+ rescue RestClient::ResourceNotFound => e
64
+ return nil
65
+ end
66
+
67
+ def environment_create(content_view_id, org_label, env_label, content_view_label = nil)
68
+ params = {:org => org_label, :env => env_label, :content_view => content_view_label, :content_view_id => content_view_id}
69
+ if foreman_org = organization_find("KT-[#{org_label}]")
70
+ params[:org_id] = foreman_org['organization']['id']
71
+ end
72
+ base.http_call('post', '/foreman_katello_engine/api/environments', params)
73
+ end
74
+
75
+ def environment_destroy(id)
76
+ environment.destroy('id' => id)
77
+ end
78
+
79
+ def user_find(username)
80
+ users, _ = user(username).index('search' => "login = #{username}")
81
+ return users.first
82
+ end
83
+
84
+ def user_create(username, email)
85
+ user(username).create({ 'user' => {
86
+ 'login' => username,
87
+ 'mail' => email,
88
+ 'password' => Password.generate_random_string(25),
89
+ 'auth_source_id' => 1}})
90
+ end
91
+
92
+ def user_destroy(id)
93
+ user.destroy('id' => id)
94
+ end
95
+
96
+ end
97
+ end
98
+
99
+ end
100
+
101
+
@@ -0,0 +1,14 @@
1
+ module KatelloForemanEngine
2
+ #Inherit from the Rails module of the parent app (Foreman), not the plugin.
3
+ #Thus, inhereits from ::Rails::Engine and not from Rails::Engine
4
+ class Engine < ::Rails::Engine
5
+
6
+ config.after_initialize do
7
+ require 'katello_foreman_engine/settings'
8
+ Settings.initialize_settings
9
+ require 'katello_foreman_engine/bindings'
10
+ Dir[File.expand_path('../actions/*.rb', __FILE__)].each { |f| require f }
11
+ end
12
+
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ module KatelloForemanEngine
2
+ class Settings
3
+
4
+ def self.initialize_settings
5
+ @settings = {
6
+ 'foreman_url' => Katello.config.foreman.url.sub(/\/+\Z/,''),
7
+ 'oauth_consumer_key' => Katello.config.foreman.oauth_key,
8
+ 'oauth_consumer_secret' => Katello.config.foreman.oauth_secret
9
+ }
10
+ end
11
+
12
+ def self.[](key)
13
+ @settings[key.to_s]
14
+ end
15
+
16
+ def self.[]=(key, value)
17
+ @settings[key.to_s] = value
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ module KatelloForemanEngine
2
+ if defined?(Rails) && Rails::VERSION::MAJOR == 3
3
+ require 'katello_foreman_engine/engine'
4
+ end
5
+ end
data/script/rails ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/os_preference/engine', __FILE__)
6
+
7
+ require 'rails/all'
8
+ require 'rails/engine/commands'
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+
3
+ module KatelloForemanEngine
4
+ module Actions
5
+ class EnvCreateTest < ActiveSupport::TestCase
6
+
7
+ test "doesn't run for library" do
8
+ org = Organization.new(:label => 'org')
9
+ env = KTEnvironment.new(:label => 'dev')
10
+ env.organization = org
11
+
12
+ env.library = false
13
+ plan = prepare_plan(EnvCreate, {}, env)
14
+ step = plan.run_steps.first
15
+ assert_equal EnvCreate, step.action_class
16
+ assert_equal step.input['org_label'], 'org'
17
+ assert_equal step.input['label'], 'dev'
18
+ assert_equal step.input['cv_id'], 'env'
19
+
20
+ env.library = true
21
+ plan = prepare_plan(EnvCreate, {}, env)
22
+ assert_equal [], plan.run_steps
23
+ end
24
+
25
+ test 'calls bindings to create environment' do
26
+ Bindings.expects(:environment_create).with('env', 'org', 'dev')
27
+ EnvCreate.new('org_label' => 'org', 'label' => 'dev', 'cv_id' => 'env').run
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,38 @@
1
+ require 'test_helper'
2
+
3
+ module KatelloForemanEngine
4
+ module Actions
5
+ class EnvDestroyTest < ActiveSupport::TestCase
6
+
7
+ test "runs only when the env is present in Foreman and it's not library" do
8
+ org = Organization.new(:label => 'org')
9
+ env = KTEnvironment.new(:label => 'dev')
10
+ env.organization = org
11
+
12
+ foreman_env = { 'environment' => { 'id' => '123' } }
13
+ Bindings.expects(:environment_find).with('org', 'dev').returns(foreman_env)
14
+
15
+ env.library = false
16
+ plan = prepare_plan(EnvDestroy,{}, env)
17
+ step = plan.run_steps.first
18
+ assert_equal EnvDestroy, step.action_class
19
+ assert_equal step.input['foreman_id'], '123'
20
+
21
+ env.library = true
22
+ plan = prepare_plan(EnvDestroy, {}, env)
23
+ assert_equal [], plan.run_steps
24
+
25
+ env.library = false
26
+ Bindings.expects(:environment_find).returns(nil)
27
+ plan = prepare_plan(EnvDestroy, {}, env)
28
+ assert_equal [], plan.run_steps
29
+ end
30
+
31
+ test 'calls bindings to destroy environment' do
32
+ Bindings.expects(:environment_destroy).with('123')
33
+ EnvDestroy.new('foreman_id' => '123').run
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,14 @@
1
+ require 'test_helper'
2
+
3
+ module KatelloForemanEngine
4
+ module Actions
5
+ class OrgCreateTest < ActiveSupport::TestCase
6
+
7
+ test 'calls bindings to create organization' do
8
+ Bindings.expects(:organization_create). with('KT-[ACME]')
9
+ OrgCreate.new('label' => 'ACME').run
10
+ end
11
+
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ module KatelloForemanEngine
4
+ module Actions
5
+ class OrgDestroyTest < ActiveSupport::TestCase
6
+
7
+ test "runs only when the org is present in Foreman" do
8
+ foreman_org = { 'organization' => { 'id' => '123' } }
9
+ Bindings.expects(:organization_find).with('KT-[test]').returns(foreman_org)
10
+ plan = prepare_plan(OrgDestroy, {'label' => 'test'}, nil)
11
+ step = plan.run_steps.first
12
+ assert_equal OrgDestroy, step.action_class
13
+ assert_equal step.input['foreman_id'], '123'
14
+
15
+ Bindings.expects(:organization_find).returns(nil)
16
+ plan = prepare_plan(OrgDestroy, {'label' => 'test'}, nil)
17
+ assert_equal [], plan.run_steps
18
+ end
19
+
20
+ test 'calls bindings to destroy organization' do
21
+ Bindings.expects(:organization_destroy).with('123')
22
+ OrgDestroy.new('foreman_id' => '123').run
23
+ end
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ require 'test_helper'
2
+ require 'mocha/setup'
3
+
4
+ class BindingsTest < ActiveSupport::TestCase
5
+
6
+ def setup
7
+ KatelloForemanEngine::Settings.initialize_settings
8
+ end
9
+
10
+ test 'client lib setting' do
11
+ KatelloForemanEngine::Settings['foreman_url'] = 'https://example.com/foreman'
12
+ KatelloForemanEngine::Settings['oauth_consumer_key'] = 'key'
13
+ KatelloForemanEngine::Settings['oauth_consumer_secret'] = 'secret'
14
+ User.current = User.new(:username => 'test')
15
+ env_resource = KatelloForemanEngine::Bindings.environment
16
+ config = env_resource.config
17
+ assert_equal 'https://example.com/foreman', config[:base_url]
18
+ assert_equal 'key', config[:oauth][:consumer_key]
19
+ assert_equal 'secret', config[:oauth][:consumer_secret]
20
+ assert_equal 'test', env_resource.client.options[:headers][:foreman_user]
21
+ end
22
+
23
+ end
@@ -0,0 +1,10 @@
1
+ require 'test_helper'
2
+
3
+ class SettingsTest < ActiveSupport::TestCase
4
+
5
+ test "katello specific settings" do
6
+ KatelloForemanEngine::Settings.initialize_settings
7
+ assert_equal 'https://localhost/foreman', KatelloForemanEngine::Settings['foreman_url']
8
+ end
9
+
10
+ end
@@ -0,0 +1,20 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ ENV["RAILS_ENV"] ||= 'test'
5
+ require File.join("katello_app/config/environment.rb")
6
+
7
+ require 'test/unit'
8
+ require 'katello-foreman-engine'
9
+ require 'rails/test_help'
10
+ require 'mocha/setup'
11
+
12
+ Rails.backtrace_cleaner.remove_silencers!
13
+
14
+ # returns the execution plan for given action, given
15
+ # input from parent action and *args for plan method
16
+ def prepare_plan(action_class, input, *args)
17
+ action = action_class.new(input)
18
+ action.plan(*args)
19
+ return action.execution_plan
20
+ end