katello-foreman-engine 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.
- data/katello-foreman-engine.gemspec +1 -2
- data/lib/katello-foreman-engine.rb +0 -1
- data/lib/katello_foreman_engine/actions/changeset_promote.rb +31 -0
- data/lib/katello_foreman_engine/actions/content_view_promote.rb +4 -1
- data/lib/katello_foreman_engine/actions/distribution_publish.rb +104 -0
- data/lib/katello_foreman_engine/actions/distribution_unpublish.rb +26 -0
- data/lib/katello_foreman_engine/actions/repository_change.rb +50 -0
- data/lib/katello_foreman_engine/actions/user_destroy.rb +1 -1
- data/lib/katello_foreman_engine/bindings.rb +136 -8
- data/lib/katello_foreman_engine/engine.rb +1 -0
- data/lib/katello_foreman_engine/helpers.rb +15 -0
- data/lib/katello_foreman_engine/settings.rb +6 -1
- data/test/lib/actions/distribution_publish_test.rb +124 -0
- data/test/lib/actions/distribution_unpublish_test.rb +33 -0
- data/test/lib/actions/{env_create.rb → env_create_test.rb} +7 -9
- data/test/lib/actions/{env_destroy.rb → env_destroy_test.rb} +5 -8
- data/test/lib/actions/{org_create.rb → org_create_test.rb} +0 -0
- data/test/lib/actions/{org_destroy.rb → org_destroy_test.rb} +2 -4
- data/test/lib/actions/repository_change_test.rb +61 -0
- data/test/test_helper.rb +60 -3
- metadata +13 -21
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "katello-foreman-engine"
|
3
|
-
s.version = "0.0.
|
3
|
+
s.version = "0.0.2"
|
4
4
|
|
5
5
|
s.authors = ["Katello"]
|
6
6
|
s.date = "2013-04-19"
|
@@ -11,7 +11,6 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.licenses = ["GPL-2"]
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.add_dependency "foreman_api"
|
14
|
-
s.add_dependency "deface", "~> 0.7.2"
|
15
14
|
s.add_dependency "dynflow"
|
16
15
|
s.summary = "Foreman specific parts of Katello"
|
17
16
|
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This software is licensed to you under the GNU General Public
|
5
|
+
# License as published by the Free Software Foundation; either version
|
6
|
+
# 2 of the License (GPLv2) or (at your option) any later version.
|
7
|
+
# There is NO WARRANTY for this software, express or implied,
|
8
|
+
# including the implied warranties of MERCHANTABILITY,
|
9
|
+
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
10
|
+
# have received a copy of GPLv2 along with this software; if not, see
|
11
|
+
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
12
|
+
|
13
|
+
module KatelloForemanEngine
|
14
|
+
module Actions
|
15
|
+
|
16
|
+
class ChangesetPromote < Dynflow::Action
|
17
|
+
|
18
|
+
def self.subscribe
|
19
|
+
Katello::Actions::ChangesetPromote
|
20
|
+
end
|
21
|
+
|
22
|
+
def plan(changeset)
|
23
|
+
changeset.affected_repos.each do |repo|
|
24
|
+
repo = repo.get_clone(changeset.environment)
|
25
|
+
plan_action(RepositoryChange, repo)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -6,10 +6,13 @@ module KatelloForemanEngine
|
|
6
6
|
Katello::Actions::ContentViewPromote
|
7
7
|
end
|
8
8
|
|
9
|
-
def plan(
|
9
|
+
def plan(content_view, from_env, to_env)
|
10
10
|
unless Bindings.environment_find(input['organization_label'], input['to_env_label'], input['label'])
|
11
11
|
plan_self input
|
12
12
|
end
|
13
|
+
content_view.repos(to_env) do |repo|
|
14
|
+
plan_action(RepositoryChange, repo)
|
15
|
+
end
|
13
16
|
end
|
14
17
|
|
15
18
|
input_format do
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module KatelloForemanEngine
|
2
|
+
module Actions
|
3
|
+
class DistributionPublish < Dynflow::Action
|
4
|
+
|
5
|
+
input_format do
|
6
|
+
param :family, String, "Example: Red Hat Enterprise Linux"
|
7
|
+
param :variant, String, "Example: Server"
|
8
|
+
param :arch, String, "Example: x86_64"
|
9
|
+
param :version, String, "Example: 6.3"
|
10
|
+
param :repo, Hash do
|
11
|
+
param :pulp_id
|
12
|
+
param :uri, String, "Example: https://example.com/pulp/repos/org/env/pr/os/"
|
13
|
+
param :label
|
14
|
+
param :product_label
|
15
|
+
param :content_view_label
|
16
|
+
param :environment_label
|
17
|
+
param :organization_label
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
medium_name = construct_medium_name
|
23
|
+
medium_path = Helpers.installation_media_path(input['repo']['uri'])
|
24
|
+
return if Bindings.medium_find(medium_path)
|
25
|
+
|
26
|
+
arch = find_or_create_arch
|
27
|
+
os = find_or_create_operating_system
|
28
|
+
assign_arch_to_os(os, arch)
|
29
|
+
medium = Bindings.medium_create(medium_name, medium_path)
|
30
|
+
assign_medium_to_os(os, medium)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def find_or_create_arch
|
36
|
+
arch = Bindings.architecture_find(input['arch']) ||
|
37
|
+
Bindings.architecture_create(input['arch'])
|
38
|
+
return arch
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_or_create_operating_system
|
42
|
+
os_name = construct_operating_system_name
|
43
|
+
major, minor = input['version'].split('.')
|
44
|
+
|
45
|
+
os = Bindings.operating_system_find(os_name, major, minor)
|
46
|
+
unless os
|
47
|
+
os = Bindings.operating_system_create(os_name, major, minor)
|
48
|
+
end
|
49
|
+
|
50
|
+
return os
|
51
|
+
end
|
52
|
+
|
53
|
+
def assign_arch_to_os(os, arch)
|
54
|
+
if os['architectures']
|
55
|
+
arch_ids = os['architectures'].map { |a| a['architecture']['id'] }
|
56
|
+
else
|
57
|
+
arch_ids = []
|
58
|
+
end
|
59
|
+
unless arch_ids.include?(arch['id'])
|
60
|
+
arch_ids << arch['id']
|
61
|
+
data = {'architecture_ids' => arch_ids}
|
62
|
+
Bindings.operating_system_update(os['id'], data)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def assign_medium_to_os(os, medium)
|
67
|
+
if os['media']
|
68
|
+
medium_ids = os['media'].map { |a| a['medium']['id'] }
|
69
|
+
else
|
70
|
+
medium_ids = []
|
71
|
+
end
|
72
|
+
unless medium_ids.include?(medium['id'])
|
73
|
+
medium_ids << medium['id']
|
74
|
+
data = {'medium_ids' => medium_ids}
|
75
|
+
Bindings.operating_system_update(os['id'], data)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
def construct_medium_name
|
81
|
+
parts = []
|
82
|
+
parts << [
|
83
|
+
input['repo']['organization_label'],
|
84
|
+
input['repo']['environment_label'],
|
85
|
+
input['repo']['content_view_label']
|
86
|
+
].compact.join('/')
|
87
|
+
parts << input['family']
|
88
|
+
parts << input['variant']
|
89
|
+
parts << input['version']
|
90
|
+
parts << input['arch']
|
91
|
+
name = parts.join(' ')
|
92
|
+
# we need to make the name a bit shorter to get under 50
|
93
|
+
# charatcers for medium name
|
94
|
+
name.sub!('Red Hat Enterprise Linux','RHEL')
|
95
|
+
return name
|
96
|
+
end
|
97
|
+
|
98
|
+
def construct_operating_system_name
|
99
|
+
[input['family'], input['variant']].join(' ').gsub(' ', '_')
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module KatelloForemanEngine
|
2
|
+
module Actions
|
3
|
+
class DistributionUnpublish < Dynflow::Action
|
4
|
+
|
5
|
+
def self.subscribe
|
6
|
+
Katello::Actions::RepositoryDestroy
|
7
|
+
end
|
8
|
+
|
9
|
+
input_format do
|
10
|
+
param :medium_id, String
|
11
|
+
end
|
12
|
+
|
13
|
+
def plan(repo)
|
14
|
+
path = Helpers.installation_media_path(repo.uri)
|
15
|
+
if medium = Bindings.medium_find(path)
|
16
|
+
plan_self('medium_id' => medium['id'])
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run
|
21
|
+
Bindings.medium_destroy(input['medium_id'])
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# This software is licensed to you under the GNU General Public
|
5
|
+
# License as published by the Free Software Foundation; either version
|
6
|
+
# 2 of the License (GPLv2) or (at your option) any later version.
|
7
|
+
# There is NO WARRANTY for this software, express or implied,
|
8
|
+
# including the implied warranties of MERCHANTABILITY,
|
9
|
+
# NON-INFRINGEMENT, or FITNESS FOR A PARTICULAR PURPOSE. You should
|
10
|
+
# have received a copy of GPLv2 along with this software; if not, see
|
11
|
+
# http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
|
12
|
+
|
13
|
+
module KatelloForemanEngine
|
14
|
+
module Actions
|
15
|
+
|
16
|
+
class RepositoryChange < Dynflow::Action
|
17
|
+
|
18
|
+
def plan(repo)
|
19
|
+
if repo.distributions.empty?
|
20
|
+
# no distributions, no instalation media
|
21
|
+
plan_action(DistributionUnpublish, repo)
|
22
|
+
elsif(repo.unprotected)
|
23
|
+
repo_info = {
|
24
|
+
'pulp_id' => repo.pulp_id,
|
25
|
+
'uri' => repo.uri,
|
26
|
+
'label' => repo.label,
|
27
|
+
'product_label' => repo.product.label,
|
28
|
+
'environment_label' => repo.environment.label,
|
29
|
+
'organization_label' => repo.organization.label
|
30
|
+
}
|
31
|
+
|
32
|
+
if repo.content_view && !repo.content_view.default?
|
33
|
+
repo_info['content_view_label'] = repo.content_view.label
|
34
|
+
end
|
35
|
+
|
36
|
+
# Foreman's installation media don't distinguish between
|
37
|
+
# different variants. Using just a first one.
|
38
|
+
distribution = repo.distributions.first
|
39
|
+
plan_action(DistributionPublish,
|
40
|
+
{ 'repo' => repo_info,
|
41
|
+
'family' => distribution.family,
|
42
|
+
'variant' => distribution.variant,
|
43
|
+
'arch' => distribution.arch,
|
44
|
+
'version' => distribution.version })
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -24,6 +24,26 @@ module KatelloForemanEngine
|
|
24
24
|
resource(ForemanApi::Resources::Environment)
|
25
25
|
end
|
26
26
|
|
27
|
+
def architecture
|
28
|
+
resource(ForemanApi::Resources::Architecture)
|
29
|
+
end
|
30
|
+
|
31
|
+
def ptable
|
32
|
+
resource(ForemanApi::Resources::Ptable)
|
33
|
+
end
|
34
|
+
|
35
|
+
def operating_system
|
36
|
+
resource(ForemanApi::Resources::OperatingSystem)
|
37
|
+
end
|
38
|
+
|
39
|
+
def config_template
|
40
|
+
resource(ForemanApi::Resources::ConfigTemplate)
|
41
|
+
end
|
42
|
+
|
43
|
+
def medium
|
44
|
+
resource(ForemanApi::Resources::Medium)
|
45
|
+
end
|
46
|
+
|
27
47
|
def user(username = nil)
|
28
48
|
user_resource = resource(ForemanApi::Resources::User)
|
29
49
|
if username && User.current.username == username
|
@@ -34,12 +54,6 @@ module KatelloForemanEngine
|
|
34
54
|
return user_resource
|
35
55
|
end
|
36
56
|
|
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
57
|
def organization_find(name)
|
44
58
|
orgs, _ = base.http_call('get', '/api/organizations', 'search' => "name = #{name}")
|
45
59
|
return orgs.first
|
@@ -77,8 +91,7 @@ module KatelloForemanEngine
|
|
77
91
|
end
|
78
92
|
|
79
93
|
def user_find(username)
|
80
|
-
|
81
|
-
return users.first
|
94
|
+
find_resource(user(username), "login = #{username}")
|
82
95
|
end
|
83
96
|
|
84
97
|
def user_create(username, email)
|
@@ -93,6 +106,121 @@ module KatelloForemanEngine
|
|
93
106
|
user.destroy('id' => id)
|
94
107
|
end
|
95
108
|
|
109
|
+
def architecture_find(name)
|
110
|
+
find_resource(architecture, "name = #{name}")
|
111
|
+
end
|
112
|
+
|
113
|
+
def architecture_create(name)
|
114
|
+
without_root_key { architecture.create('architecture' => {'name' => name}) }
|
115
|
+
end
|
116
|
+
|
117
|
+
def operating_system_find(name, major, minor)
|
118
|
+
find_resource(operating_system, "name = #{name} AND major = #{major} AND minor = #{minor}")
|
119
|
+
end
|
120
|
+
|
121
|
+
def operating_system_create(name, major, minor)
|
122
|
+
data = {
|
123
|
+
'name' => name,
|
124
|
+
'major' => major.to_s,
|
125
|
+
'minor' => minor.to_s,
|
126
|
+
'family' => Settings['foreman_os_family']
|
127
|
+
}
|
128
|
+
templates_to_add = [template_find(Settings['foreman_os_provisioning_template']),
|
129
|
+
template_find(Settings['foreman_os_pxe_template'])].compact
|
130
|
+
data['os_default_templates_attributes'] = templates_to_add.map do |template|
|
131
|
+
{
|
132
|
+
"config_template_id" => template["id"],
|
133
|
+
"template_kind_id" => template["template_kind"]["id"],
|
134
|
+
}
|
135
|
+
end
|
136
|
+
|
137
|
+
if ptable = ptable_find(Settings['foreman_os_ptable'])
|
138
|
+
data['ptable_ids'] = [ptable['id']]
|
139
|
+
end
|
140
|
+
|
141
|
+
os = without_root_key { operating_system.create('operatingsystem' => data) }
|
142
|
+
|
143
|
+
oss, _ = operating_system.index
|
144
|
+
os_ids = oss.map { |o| o['operatingsystem']['id'] }
|
145
|
+
templates_to_add.each do |template|
|
146
|
+
# Because of http://projects.theforeman.org/issues/2500 we
|
147
|
+
# have not way to add only the created os to the template.
|
148
|
+
# As a workaround, we add all os to the template for now.
|
149
|
+
config_template.update("id" => template['id'],
|
150
|
+
'config_template' => {
|
151
|
+
"operatingsystem_ids" => os_ids
|
152
|
+
})
|
153
|
+
end
|
154
|
+
return os
|
155
|
+
end
|
156
|
+
|
157
|
+
def operating_system_update(id, data)
|
158
|
+
without_root_key do
|
159
|
+
operating_system.update('id' => id, 'operatingsystem' => data)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def template_find(name)
|
164
|
+
find_resource(config_template, %{name = "#{name}"})
|
165
|
+
end
|
166
|
+
|
167
|
+
def medium_find(path)
|
168
|
+
find_resource(medium, %{path = "#{path}"})
|
169
|
+
end
|
170
|
+
|
171
|
+
def medium_create(name, path)
|
172
|
+
without_root_key do
|
173
|
+
self.medium.create('medium' => {
|
174
|
+
'name' => name,
|
175
|
+
'path' => path,
|
176
|
+
'os_family' => Settings['foreman_os_family']})
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def medium_destroy(id)
|
181
|
+
self.medium.destroy('id' => id)
|
182
|
+
end
|
183
|
+
|
184
|
+
def ptable_find(name)
|
185
|
+
find_resource(ptable, %{name = "#{name}"})
|
186
|
+
end
|
187
|
+
|
188
|
+
private
|
189
|
+
|
190
|
+
# configure resource client to be used to call Foreman.
|
191
|
+
# We need to do this for every resoruce right now.
|
192
|
+
# We might improve this on foreman_api side later.
|
193
|
+
def resource(resource_class)
|
194
|
+
client = resource_class.new(client_config)
|
195
|
+
client.client.options[:headers][:foreman_user] = User.current.username
|
196
|
+
return client
|
197
|
+
end
|
198
|
+
|
199
|
+
# From Foreman, the resource comes in form:
|
200
|
+
#
|
201
|
+
# { 'resource' => { 'attr1' => 'val1', 'attr2' => 'val2' } }
|
202
|
+
#
|
203
|
+
# this method returns only the body, i.e.:
|
204
|
+
#
|
205
|
+
# { 'attr1' => 'val1', 'attr2' => 'val2' }
|
206
|
+
#
|
207
|
+
# If block given, it expects the call to foreman_api from that
|
208
|
+
#
|
209
|
+
# We might improve this on foreman_api side later
|
210
|
+
def without_root_key(resource_hash = nil, &block)
|
211
|
+
if block
|
212
|
+
resource_hash, _ = yield
|
213
|
+
end
|
214
|
+
if resource_hash
|
215
|
+
resource_hash.values.first
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def find_resource(resource, search_query)
|
220
|
+
results, _ = resource.index('search' => search_query)
|
221
|
+
return without_root_key(results.first)
|
222
|
+
end
|
223
|
+
|
96
224
|
end
|
97
225
|
end
|
98
226
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module KatelloForemanEngine
|
2
|
+
module Helpers
|
3
|
+
class << self
|
4
|
+
|
5
|
+
# takes repo uri from Katello and makes installation media url
|
6
|
+
# suitable for provisioning from it
|
7
|
+
def installation_media_path(repo_uri)
|
8
|
+
path = repo_uri.sub(/\Ahttps/, 'http')
|
9
|
+
path << "/" unless path.end_with?('/')
|
10
|
+
return path
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -5,7 +5,12 @@ module KatelloForemanEngine
|
|
5
5
|
@settings = {
|
6
6
|
'foreman_url' => Katello.config.foreman.url.sub(/\/+\Z/,''),
|
7
7
|
'oauth_consumer_key' => Katello.config.foreman.oauth_key,
|
8
|
-
'oauth_consumer_secret' => Katello.config.foreman.oauth_secret
|
8
|
+
'oauth_consumer_secret' => Katello.config.foreman.oauth_secret,
|
9
|
+
# TODO: make the following options configurable:
|
10
|
+
'foreman_os_family' => 'Redhat',
|
11
|
+
'foreman_os_provisioning_template' => 'Katello Kickstart Default',
|
12
|
+
'foreman_os_pxe_template' => 'Kickstart default PXElinux',
|
13
|
+
'foreman_os_ptable' => 'RedHat default',
|
9
14
|
}
|
10
15
|
end
|
11
16
|
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module KatelloForemanEngine
|
4
|
+
module Actions
|
5
|
+
class DistributionPublishTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@input = {
|
9
|
+
'family' => 'Red Hat Enterprise Linux',
|
10
|
+
'variant' => 'Server',
|
11
|
+
'arch' => 'x86_64',
|
12
|
+
'version' => '6.3',
|
13
|
+
'repo' => {
|
14
|
+
'pulp_id' => 'Org-Env-Prod-Repo',
|
15
|
+
'uri' => 'http://example.com/pulp/repos/os/',
|
16
|
+
'label' => 'Repo',
|
17
|
+
'product_label' => 'Prod',
|
18
|
+
'environment_label' => 'Env',
|
19
|
+
'organization_label' => 'Org'
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
23
|
+
@arch = 'x86_64'
|
24
|
+
@os_name = 'Red_Hat_Enterprise_Linux_Server'
|
25
|
+
@os_major = '6'
|
26
|
+
@os_minor = '3'
|
27
|
+
|
28
|
+
@medium_name = 'Org/Env Red Hat Enterprise Linux Server 6.3 x86_64'
|
29
|
+
@medium_path = 'http://example.com/pulp/repos/os/'
|
30
|
+
|
31
|
+
@arch_output = {'architecture' => { 'id' => 1, 'name' => @arch }}
|
32
|
+
@ptable_output = {'ptable' => { 'id' => 1, 'name' => 'RedHat default' }}
|
33
|
+
@os_output = {
|
34
|
+
'operatingsystem' => {
|
35
|
+
'id' => 1,
|
36
|
+
'name' => @os_name,
|
37
|
+
'major' => @os_major,
|
38
|
+
'minor' => @os_minor,
|
39
|
+
'family' => 'RedHat',
|
40
|
+
'architectures' => [@arch_output],
|
41
|
+
'media' => [],
|
42
|
+
'ptables' => [@ptable_output],
|
43
|
+
}
|
44
|
+
}
|
45
|
+
@medium_output = {
|
46
|
+
'medium' => {
|
47
|
+
'id' => 1,
|
48
|
+
'name' => @medium_name,
|
49
|
+
'path' => @medium_path
|
50
|
+
}
|
51
|
+
}
|
52
|
+
|
53
|
+
stub_foreman_search(:architecture, "name = #{@arch}", @arch_output)
|
54
|
+
stub_foreman_search(:ptable, %{name = "RedHat default"}, @ptable_output)
|
55
|
+
stub_foreman_call(:medium, :index, nil, [])
|
56
|
+
stub_foreman_call(:medium, :create, nil, @medium_output)
|
57
|
+
stub_foreman_call(:operating_system, :index, nil, [])
|
58
|
+
stub_foreman_call(:operating_system, :create, nil, @os_output)
|
59
|
+
stub_foreman_call(:operating_system, :update)
|
60
|
+
stub_foreman_search(:config_template, %{name = "Katello Kickstart Default"}, nil)
|
61
|
+
stub_foreman_search(:config_template, %{name = "Kickstart default PXElinux"}, nil)
|
62
|
+
stub_foreman_search(:ptable, %{name = "RedHat default"}, nil)
|
63
|
+
stub_foreman_call(:operating_system, :index, nil, [])
|
64
|
+
end
|
65
|
+
|
66
|
+
def run_action
|
67
|
+
action = DistributionPublish.new(@input)
|
68
|
+
action.run
|
69
|
+
return action
|
70
|
+
end
|
71
|
+
|
72
|
+
test "creates architecture in foreman if not created yet" do
|
73
|
+
stub_foreman_search(:architecture, "name = #{@arch}", nil)
|
74
|
+
expect_foreman_call(:architecture, :create, {'name' => @arch}, @arch_output)
|
75
|
+
run_action
|
76
|
+
end
|
77
|
+
|
78
|
+
test "creates operating system in foreman if not created yet" do
|
79
|
+
stub_foreman_search(:operating_system, "name = #{@os_name} AND major = #{@os_major} AND minor = #{@os_minor}", nil)
|
80
|
+
os_data = {
|
81
|
+
'name' => @os_name,
|
82
|
+
'major' => @os_major.to_s,
|
83
|
+
'minor' => @os_minor.to_s,
|
84
|
+
'family' => 'Redhat',
|
85
|
+
'os_default_templates_attributes' => [],
|
86
|
+
}
|
87
|
+
expect_foreman_call(:operating_system, :create, os_data, @os_output)
|
88
|
+
run_action
|
89
|
+
end
|
90
|
+
|
91
|
+
test "creates sets minor version empty if missing" do
|
92
|
+
stub_foreman_search(:operating_system, "name = #{@os_name} AND major = #{@os_major} AND minor = ", nil)
|
93
|
+
os_data = {
|
94
|
+
'name' => @os_name,
|
95
|
+
'major' => @os_major.to_s,
|
96
|
+
'minor' => '',
|
97
|
+
'family' => 'Redhat',
|
98
|
+
'os_default_templates_attributes' => [],
|
99
|
+
}
|
100
|
+
expect_foreman_call(:operating_system, :create, os_data, @os_output)
|
101
|
+
@input['version'] = '6'
|
102
|
+
run_action
|
103
|
+
end
|
104
|
+
|
105
|
+
test "assigns architecture to operating system if not assigned yet" do
|
106
|
+
os_without_arch = {
|
107
|
+
'operatingsystem' => @os_output['operatingsystem'].merge('architectures' => [])
|
108
|
+
}
|
109
|
+
stub_foreman_search(:operating_system, "name = #{@os_name} AND major = #{@os_major} AND minor = #{@os_minor}", os_without_arch)
|
110
|
+
expected_data = {'id' => 1, 'architecture_ids' => [@arch_output['architecture']['id']]}
|
111
|
+
expect_foreman_call(:operating_system, :update, expected_data)
|
112
|
+
run_action
|
113
|
+
end
|
114
|
+
|
115
|
+
test "creates medium and assigns it to the os in not created yet" do
|
116
|
+
expect_foreman_call(:medium, :create, {'name' => @medium_name, 'path' => @medium_path, 'os_family' => 'Redhat'}, @medium_output)
|
117
|
+
expected_data = {'id' => 1, 'medium_ids' => [@medium_output['medium']['id']]}
|
118
|
+
expect_foreman_call(:operating_system, :update, expected_data)
|
119
|
+
run_action
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module KatelloForemanEngine
|
4
|
+
module Actions
|
5
|
+
class DistributionUnpublishTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@https_path = "https://example.com/my/repo"
|
9
|
+
@http_path = "http://example.com/my/repo/"
|
10
|
+
@medium_output = {'medium' => {'id' => '123'}}
|
11
|
+
@repo = stub(:uri => @https_path)
|
12
|
+
end
|
13
|
+
|
14
|
+
test "deletes the instalation media using the repo" do
|
15
|
+
stub_foreman_search(:medium, %{path = "#{@http_path}"}, @medium_output)
|
16
|
+
step = run_steps(DistributionUnpublish, {}, @repo).first
|
17
|
+
assert_equal DistributionUnpublish, step.action_class
|
18
|
+
assert_equal({'medium_id' => '123'}, step.input)
|
19
|
+
end
|
20
|
+
|
21
|
+
test "does nothing if the installation media is not present" do
|
22
|
+
stub_foreman_search(:medium, %{path = "#{@http_path}"}, [])
|
23
|
+
assert_equal [], run_steps(DistributionUnpublish, {}, @repo)
|
24
|
+
end
|
25
|
+
|
26
|
+
test 'calls bindings to destroy environment' do
|
27
|
+
expect_foreman_call(:medium, :destroy, {'id' => '123'})
|
28
|
+
DistributionUnpublish.new('medium_id' => '123').run
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -10,21 +10,19 @@ module KatelloForemanEngine
|
|
10
10
|
env.organization = org
|
11
11
|
|
12
12
|
env.library = false
|
13
|
-
|
14
|
-
|
15
|
-
assert_equal
|
16
|
-
assert_equal step.input['
|
17
|
-
assert_equal step.input['
|
18
|
-
assert_equal step.input['cv_id'], 'env'
|
13
|
+
step = run_steps(EnvironmentCreate, {}, env).first
|
14
|
+
assert_equal EnvironmentCreate, step.action_class
|
15
|
+
assert_equal 'org', step.input['org_label']
|
16
|
+
assert_equal 'dev', step.input['label']
|
17
|
+
assert_equal 'env', step.input['content_view_id']
|
19
18
|
|
20
19
|
env.library = true
|
21
|
-
|
22
|
-
assert_equal [], plan.run_steps
|
20
|
+
assert_equal [], run_steps(EnvironmentCreate, {}, env)
|
23
21
|
end
|
24
22
|
|
25
23
|
test 'calls bindings to create environment' do
|
26
24
|
Bindings.expects(:environment_create).with('env', 'org', 'dev')
|
27
|
-
|
25
|
+
EnvironmentCreate.new('org_label' => 'org', 'label' => 'dev', 'content_view_id' => 'env').run
|
28
26
|
end
|
29
27
|
|
30
28
|
end
|
@@ -13,24 +13,21 @@ module KatelloForemanEngine
|
|
13
13
|
Bindings.expects(:environment_find).with('org', 'dev').returns(foreman_env)
|
14
14
|
|
15
15
|
env.library = false
|
16
|
-
|
17
|
-
|
18
|
-
assert_equal EnvDestroy, step.action_class
|
16
|
+
step = run_steps(EnvironmentDestroy,{}, env).first
|
17
|
+
assert_equal EnvironmentDestroy, step.action_class
|
19
18
|
assert_equal step.input['foreman_id'], '123'
|
20
19
|
|
21
20
|
env.library = true
|
22
|
-
|
23
|
-
assert_equal [], plan.run_steps
|
21
|
+
assert_equal [], run_steps(EnvironmentDestroy,{}, env)
|
24
22
|
|
25
23
|
env.library = false
|
26
24
|
Bindings.expects(:environment_find).returns(nil)
|
27
|
-
|
28
|
-
assert_equal [], plan.run_steps
|
25
|
+
assert_equal [], run_steps(EnvironmentDestroy,{}, env)
|
29
26
|
end
|
30
27
|
|
31
28
|
test 'calls bindings to destroy environment' do
|
32
29
|
Bindings.expects(:environment_destroy).with('123')
|
33
|
-
|
30
|
+
EnvironmentDestroy.new('foreman_id' => '123').run
|
34
31
|
end
|
35
32
|
|
36
33
|
end
|
File without changes
|
@@ -7,14 +7,12 @@ module KatelloForemanEngine
|
|
7
7
|
test "runs only when the org is present in Foreman" do
|
8
8
|
foreman_org = { 'organization' => { 'id' => '123' } }
|
9
9
|
Bindings.expects(:organization_find).with('KT-[test]').returns(foreman_org)
|
10
|
-
|
11
|
-
step = plan.run_steps.first
|
10
|
+
step = run_steps(OrgDestroy, {'label' => 'test'}, nil).first
|
12
11
|
assert_equal OrgDestroy, step.action_class
|
13
12
|
assert_equal step.input['foreman_id'], '123'
|
14
13
|
|
15
14
|
Bindings.expects(:organization_find).returns(nil)
|
16
|
-
|
17
|
-
assert_equal [], plan.run_steps
|
15
|
+
assert_equal [], run_steps(OrgDestroy, {'label' => 'test'}, nil)
|
18
16
|
end
|
19
17
|
|
20
18
|
test 'calls bindings to destroy organization' do
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module KatelloForemanEngine
|
4
|
+
module Actions
|
5
|
+
class RepositoryChangeTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@repo_with_distros = stub(:unprotected => true,
|
9
|
+
:distributions => [stub('family' => 'Family',
|
10
|
+
'variant' => 'Variant',
|
11
|
+
'arch' => 'Arch',
|
12
|
+
'version' => 'Version')],
|
13
|
+
:pulp_id => 'pulp_id',
|
14
|
+
:uri => 'https://example.com/repo/uri',
|
15
|
+
:label => 'label',
|
16
|
+
:product => stub(:label => 'product_label'),
|
17
|
+
:content_view => stub(:default? => true, :label => 'cv'),
|
18
|
+
:environment => stub(:label => 'environment_label'),
|
19
|
+
:organization => stub(:label => 'organization_label'))
|
20
|
+
|
21
|
+
@expected_publish_input = {
|
22
|
+
"repo"=>
|
23
|
+
{
|
24
|
+
"pulp_id"=>"pulp_id",
|
25
|
+
"uri"=>"https://example.com/repo/uri",
|
26
|
+
"label"=>"label",
|
27
|
+
"product_label"=>"product_label",
|
28
|
+
"environment_label"=>"environment_label",
|
29
|
+
"organization_label"=>"organization_label"
|
30
|
+
},
|
31
|
+
"family"=>"Family",
|
32
|
+
"variant"=>"Variant",
|
33
|
+
"arch"=>"Arch",
|
34
|
+
"version"=>"Version"
|
35
|
+
}
|
36
|
+
end
|
37
|
+
|
38
|
+
test "plans repository unpublish if no distros found for the repo" do
|
39
|
+
repo = stub(:distributions => [])
|
40
|
+
action_class, arg = planned_actions(RepositoryChange, {}, repo).first
|
41
|
+
assert_equal DistributionUnpublish, action_class
|
42
|
+
assert_equal repo, arg
|
43
|
+
end
|
44
|
+
|
45
|
+
test "plans distribution publish if repo is unprotected and has distirbutions" do
|
46
|
+
action_class, input = planned_actions(RepositoryChange, {}, @repo_with_distros).first
|
47
|
+
assert_equal DistributionPublish, action_class
|
48
|
+
assert_equal @expected_publish_input, input
|
49
|
+
end
|
50
|
+
|
51
|
+
test "passes the content view label unless repo in default content view" do
|
52
|
+
@repo_with_distros.content_view.stubs(:default? => false)
|
53
|
+
action_class, input = planned_actions(RepositoryChange, {}, @repo_with_distros).first
|
54
|
+
assert_equal DistributionPublish, action_class
|
55
|
+
@expected_publish_input['repo']['content_view_label'] = 'cv'
|
56
|
+
assert_equal input, @expected_publish_input
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/test/test_helper.rb
CHANGED
@@ -11,10 +11,67 @@ require 'mocha/setup'
|
|
11
11
|
|
12
12
|
Rails.backtrace_cleaner.remove_silencers!
|
13
13
|
|
14
|
-
# returns the
|
14
|
+
# returns the subactions being planned from the plan method of
|
15
|
+
# +action_class+. It prevents calling plan methods on the subactions,
|
16
|
+
# letting to test only the action_class in isolation.
|
17
|
+
def planned_actions(action_class, input, *args)
|
18
|
+
planned_actions = []
|
19
|
+
action = action_class.new(input)
|
20
|
+
action.stubs(:plan_action).with do |*args|
|
21
|
+
planned_actions << args
|
22
|
+
end
|
23
|
+
action.plan(*args)
|
24
|
+
return planned_actions
|
25
|
+
end
|
26
|
+
|
27
|
+
# returns the run steps planned for given action, given
|
15
28
|
# input from parent action and *args for plan method
|
16
|
-
def
|
29
|
+
def run_steps(action_class, input, *args)
|
17
30
|
action = action_class.new(input)
|
18
31
|
action.plan(*args)
|
19
|
-
return action.execution_plan
|
32
|
+
return action.execution_plan.run_steps
|
33
|
+
end
|
34
|
+
|
35
|
+
def expect_foreman_search(*args)
|
36
|
+
args = args + [true]
|
37
|
+
stub_foreman_search(*args)
|
38
|
+
end
|
39
|
+
|
40
|
+
def stub_foreman_search(resource, search, response, expect = false)
|
41
|
+
response = case response
|
42
|
+
when nil
|
43
|
+
[]
|
44
|
+
when Array
|
45
|
+
response
|
46
|
+
else
|
47
|
+
[response]
|
48
|
+
end
|
49
|
+
stub_foreman_call(resource, :index, {'search' => search}, response, expect)
|
50
|
+
end
|
51
|
+
|
52
|
+
def expect_foreman_call(*args)
|
53
|
+
args = args + [true]
|
54
|
+
stub_foreman_call(*args)
|
55
|
+
end
|
56
|
+
|
57
|
+
def stub_foreman_call(resource, action, request = nil, response = nil, expect = false)
|
58
|
+
setup_user
|
59
|
+
resource_key = resource.to_s
|
60
|
+
# difference between class name and resource key in the API
|
61
|
+
resource_key.gsub!('_','') if resource_key == 'operating_system'
|
62
|
+
if request && [:create, :update].include?(action) && !request.has_key?(resource_key)
|
63
|
+
request = {resource_key => request}
|
64
|
+
end
|
65
|
+
resource_class ="ForemanApi::Resources::#{resource.to_s.camelize}".constantize
|
66
|
+
stub = resource_class.any_instance.stubs(action)
|
67
|
+
if request
|
68
|
+
stub.with(request)
|
69
|
+
end
|
70
|
+
if response
|
71
|
+
stub.returns([response, response.to_json])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def setup_user
|
76
|
+
User.current ||= User.new(:username => 'admin')
|
20
77
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: katello-foreman-engine
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -27,22 +27,6 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: deface
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ~>
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: 0.7.2
|
38
|
-
type: :runtime
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: 0.7.2
|
46
30
|
- !ruby/object:Gem::Dependency
|
47
31
|
name: dynflow
|
48
32
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,22 +56,30 @@ files:
|
|
72
56
|
- katello-foreman-engine.gemspec
|
73
57
|
- lib/katello-foreman-engine.rb
|
74
58
|
- lib/katello_foreman_engine.rb
|
59
|
+
- lib/katello_foreman_engine/actions/changeset_promote.rb
|
75
60
|
- lib/katello_foreman_engine/actions/content_view_demote.rb
|
76
61
|
- lib/katello_foreman_engine/actions/content_view_promote.rb
|
62
|
+
- lib/katello_foreman_engine/actions/distribution_publish.rb
|
63
|
+
- lib/katello_foreman_engine/actions/distribution_unpublish.rb
|
77
64
|
- lib/katello_foreman_engine/actions/environment_create.rb
|
78
65
|
- lib/katello_foreman_engine/actions/environment_destroy.rb
|
79
66
|
- lib/katello_foreman_engine/actions/org_create.rb
|
80
67
|
- lib/katello_foreman_engine/actions/org_destroy.rb
|
68
|
+
- lib/katello_foreman_engine/actions/repository_change.rb
|
81
69
|
- lib/katello_foreman_engine/actions/user_create.rb
|
82
70
|
- lib/katello_foreman_engine/actions/user_destroy.rb
|
83
71
|
- lib/katello_foreman_engine/bindings.rb
|
84
72
|
- lib/katello_foreman_engine/engine.rb
|
73
|
+
- lib/katello_foreman_engine/helpers.rb
|
85
74
|
- lib/katello_foreman_engine/settings.rb
|
86
75
|
- script/rails
|
87
|
-
- test/lib/actions/
|
88
|
-
- test/lib/actions/
|
89
|
-
- test/lib/actions/
|
90
|
-
- test/lib/actions/
|
76
|
+
- test/lib/actions/distribution_publish_test.rb
|
77
|
+
- test/lib/actions/distribution_unpublish_test.rb
|
78
|
+
- test/lib/actions/env_create_test.rb
|
79
|
+
- test/lib/actions/env_destroy_test.rb
|
80
|
+
- test/lib/actions/org_create_test.rb
|
81
|
+
- test/lib/actions/org_destroy_test.rb
|
82
|
+
- test/lib/actions/repository_change_test.rb
|
91
83
|
- test/lib/bindings_test.rb
|
92
84
|
- test/lib/settings_test.rb
|
93
85
|
- test/test_helper.rb
|