foreman_deployments 0.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.
- checksums.yaml +15 -0
- data/LICENSE +619 -0
- data/README.md +52 -0
- data/Rakefile +30 -0
- data/app/controllers/foreman_deployments/api/v2/base_controller.rb +25 -0
- data/app/controllers/foreman_deployments/api/v2/deployments_controller.rb +102 -0
- data/app/controllers/foreman_deployments/api/v2/stacks_controller.rb +52 -0
- data/app/controllers/foreman_deployments/create_resources_controller.rb +62 -0
- data/app/controllers/foreman_deployments/deployments_controller.rb +5 -0
- data/app/controllers/foreman_deployments/stacks_controller.rb +5 -0
- data/app/lib/foreman_deployments/base_dereference_visitor.rb +55 -0
- data/app/lib/foreman_deployments/config.rb +16 -0
- data/app/lib/foreman_deployments/config/array.rb +91 -0
- data/app/lib/foreman_deployments/config/configurator.rb +23 -0
- data/app/lib/foreman_deployments/config/hash.rb +81 -0
- data/app/lib/foreman_deployments/config/load_visitor.rb +23 -0
- data/app/lib/foreman_deployments/config/merge_visitor.rb +23 -0
- data/app/lib/foreman_deployments/config/save_visitor.rb +23 -0
- data/app/lib/foreman_deployments/inputs/base_input_definition.rb +39 -0
- data/app/lib/foreman_deployments/inputs/value.rb +25 -0
- data/app/lib/foreman_deployments/planner_visitor.rb +26 -0
- data/app/lib/foreman_deployments/registry.rb +67 -0
- data/app/lib/foreman_deployments/stack_definition.rb +37 -0
- data/app/lib/foreman_deployments/stack_parser.rb +121 -0
- data/app/lib/foreman_deployments/task_reference.rb +48 -0
- data/app/lib/foreman_deployments/tasks/base_action.rb +6 -0
- data/app/lib/foreman_deployments/tasks/base_definition.rb +72 -0
- data/app/lib/foreman_deployments/tasks/creation_task_definition.rb +68 -0
- data/app/lib/foreman_deployments/tasks/host_creation_task_definition.rb +44 -0
- data/app/lib/foreman_deployments/tasks/search_task_definition.rb +55 -0
- data/app/lib/foreman_deployments/tasks/stack_deploy_action.rb +10 -0
- data/app/lib/foreman_deployments/tasks/wait_until_built_task_definition.rb +65 -0
- data/app/lib/foreman_deployments/validation/dereference_visitor.rb +18 -0
- data/app/lib/foreman_deployments/validation/remove_ids_visitor.rb +59 -0
- data/app/lib/foreman_deployments/validation/validation_error.rb +12 -0
- data/app/lib/foreman_deployments/validation/validation_result.rb +26 -0
- data/app/lib/foreman_deployments/validation/validation_visitor.rb +20 -0
- data/app/lib/foreman_deployments/validation/validator.rb +29 -0
- data/app/models/foreman_deployments/concerns/belongs_to_single_taxonomy.rb +42 -0
- data/app/models/foreman_deployments/concerns/belongs_to_stack_taxonomy.rb +24 -0
- data/app/models/foreman_deployments/configuration.rb +26 -0
- data/app/models/foreman_deployments/deployment.rb +57 -0
- data/app/models/foreman_deployments/resource_models/create_resource.rb +18 -0
- data/app/models/foreman_deployments/stack.rb +20 -0
- data/app/views/foreman_deployments/api/v2/deployments/base.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/deployments/create.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/deployments/index.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/deployments/main.json.rabl +5 -0
- data/app/views/foreman_deployments/api/v2/deployments/merge_configuration.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/deployments/replace_configuration.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/deployments/run.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/deployments/show.json.rabl +11 -0
- data/app/views/foreman_deployments/api/v2/deployments/update.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/stacks/base.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/stacks/create.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/stacks/index.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/stacks/main.json.rabl +3 -0
- data/app/views/foreman_deployments/api/v2/stacks/show.json.rabl +7 -0
- data/app/views/foreman_deployments/api/v2/stacks/update.json.rabl +3 -0
- data/app/views/foreman_deployments/create_resources/new.html.erb +6 -0
- data/config/routes.rb +41 -0
- data/db/migrate/20150623140612_create_stacks.rb +10 -0
- data/db/migrate/20150814092932_create_deployment.rb +20 -0
- data/db/migrate/20150916133305_add_task_to_deployments.rb +5 -0
- data/db/migrate/20150917130618_add_taxonomy_to_deployments.rb +8 -0
- data/db/seeds.d/03-permissions.rb +14 -0
- data/doc/deployment_process.md +112 -0
- data/doc/design/capsule_stack.puml +51 -0
- data/doc/design/complete_stack.puml +17 -0
- data/doc/design/config_resource_overview.puml +15 -0
- data/doc/design/design.md +230 -0
- data/doc/design/diagrams/capsule_stack.png +0 -0
- data/doc/design/diagrams/capsule_stack.svg +1 -0
- data/doc/design/diagrams/complete_stack.png +0 -0
- data/doc/design/diagrams/complete_stack.svg +1 -0
- data/doc/design/diagrams/config_resource_overview.png +0 -0
- data/doc/design/diagrams/config_resource_overview.svg +1 -0
- data/doc/design/diagrams/ordered_resource_overview.png +0 -0
- data/doc/design/diagrams/ordered_resource_overview.svg +1 -0
- data/doc/design/diagrams/overview.png +0 -0
- data/doc/design/diagrams/overview.svg +1 -0
- data/doc/design/diagrams/overview_class.png +0 -0
- data/doc/design/diagrams/overview_class.svg +1 -0
- data/doc/design/diagrams/sat_stack.png +0 -0
- data/doc/design/diagrams/sat_stack.svg +1 -0
- data/doc/design/diagrams/solr_usecase.png +0 -0
- data/doc/design/diagrams/solr_usecase.svg +1 -0
- data/doc/design/examples.md +192 -0
- data/doc/design/generate-diagrams.sh +7 -0
- data/doc/design/implementation.md +128 -0
- data/doc/design/ordered_resource_overview.puml +15 -0
- data/doc/design/overview.puml +42 -0
- data/doc/design/overview_class.puml +64 -0
- data/doc/design/resources.md +134 -0
- data/doc/design/sat_stack.puml +37 -0
- data/doc/design/shared.puml +171 -0
- data/doc/design/solr_usecase.puml +189 -0
- data/doc/design/tasks.md +74 -0
- data/doc/design/user_interfaces.md +189 -0
- data/doc/introduction.md +84 -0
- data/doc/writing_stacks.md +102 -0
- data/lib/foreman_deployments.rb +7 -0
- data/lib/foreman_deployments/engine.rb +94 -0
- data/lib/foreman_deployments/monkey_patches.rb +9 -0
- data/lib/foreman_deployments/version.rb +3 -0
- data/lib/tasks/foreman_deployments_tasks.rake +22 -0
- data/locale/Makefile +62 -0
- data/test/factories/foreman_deployments.rb +70 -0
- data/test/functional/api/v2/deployments_controller_test.rb +318 -0
- data/test/functional/api/v2/stacks_controller_test.rb +140 -0
- data/test/test_plugin_helper.rb +14 -0
- data/test/unit/lib/config/array_test.rb +217 -0
- data/test/unit/lib/config/configurator_test.rb +66 -0
- data/test/unit/lib/config/hash_test.rb +178 -0
- data/test/unit/lib/inputs/value_test.rb +47 -0
- data/test/unit/lib/registry_test.rb +117 -0
- data/test/unit/lib/stack_definition_test.rb +54 -0
- data/test/unit/lib/stack_parser_test.rb +129 -0
- data/test/unit/lib/task_reference_test.rb +63 -0
- data/test/unit/lib/tasks/base_definition_test.rb +137 -0
- data/test/unit/lib/tasks/creation_task_definition_test.rb +57 -0
- data/test/unit/lib/tasks/host_creation_task_definition_test.rb +10 -0
- data/test/unit/lib/tasks/search_task_definition_test.rb +49 -0
- data/test/unit/lib/tasks/stack_deploy_action_test.rb +83 -0
- data/test/unit/lib/tasks/wait_until_built_task_definition_test.rb +71 -0
- data/test/unit/lib/validation/dereference_visitor_test.rb +48 -0
- data/test/unit/lib/validation/remove_ids_visitor_test.rb +90 -0
- data/test/unit/lib/validation/validation_result_test.rb +40 -0
- data/test/unit/lib/validation/validation_visitor_test.rb +67 -0
- data/test/unit/model/configuration_test.rb +88 -0
- data/test/unit/model/deployment_test.rb +159 -0
- data/test/unit/model/stack_test.rb +33 -0
- metadata +241 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module ForemanDeployments
|
|
2
|
+
class TaskReference
|
|
3
|
+
attr_accessor :task, :task_id, :output_key
|
|
4
|
+
|
|
5
|
+
def initialize(task_id, output_key, task = nil)
|
|
6
|
+
@task_id = task_id
|
|
7
|
+
@output_key = output_key
|
|
8
|
+
@task = task
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def dereference(output)
|
|
12
|
+
output_keys.each do |key|
|
|
13
|
+
return nil if output.nil?
|
|
14
|
+
if output.is_a?(Hash) || output.is_a?(Dynflow::ExecutionPlan::OutputReference)
|
|
15
|
+
output = output[key]
|
|
16
|
+
else
|
|
17
|
+
output = output.send(key)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
return output
|
|
21
|
+
rescue NoMethodError
|
|
22
|
+
return nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def accept(visitor)
|
|
26
|
+
visitor.visit(self)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def to_hash
|
|
30
|
+
{
|
|
31
|
+
'_type' => 'reference',
|
|
32
|
+
'_name' => self.class.tag_name,
|
|
33
|
+
'object' => task_id,
|
|
34
|
+
'field' => output_key
|
|
35
|
+
}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.tag_name
|
|
39
|
+
'reference'
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
private
|
|
43
|
+
|
|
44
|
+
def output_keys
|
|
45
|
+
@output_key.to_s.split('.')
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
module ForemanDeployments
|
|
2
|
+
module Tasks
|
|
3
|
+
class BaseDefinition
|
|
4
|
+
attr_accessor :task_id, :parameters
|
|
5
|
+
attr_reader :planned
|
|
6
|
+
|
|
7
|
+
def initialize(params = nil)
|
|
8
|
+
@parameters = ForemanDeployments::Config.cast_to_configuration(params || {})
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def plan(parent_task)
|
|
12
|
+
@planned ||= parent_task.send(:plan_action, dynflow_action, parameters.configured)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def dynflow_action
|
|
16
|
+
fail NotImplementedError, "Method 'dynflow_action' method needs to be implemented"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def validate
|
|
20
|
+
fail NotImplementedError, "Method 'validate' needs to be implemented"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def preliminary_output
|
|
24
|
+
fail NotImplementedError, "Method 'preliminary_output' needs to be implemented"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def configure(parameters)
|
|
28
|
+
@parameters.configure(parameters)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def merge_configuration(additional_parameters)
|
|
32
|
+
@parameters.merge_configuration(additional_parameters)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def configuration
|
|
36
|
+
@parameters.configuration
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def accept(visitor)
|
|
40
|
+
visit_parameters(visitor, parameters)
|
|
41
|
+
visitor.visit(self)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_hash
|
|
45
|
+
@parameters.configured.merge(
|
|
46
|
+
'_type' => 'task',
|
|
47
|
+
'_name' => self.class.tag_name
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def self.tag_name
|
|
52
|
+
name.split('::').last
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.build(params = {})
|
|
56
|
+
new(params)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def visit_parameters(visitor, value)
|
|
62
|
+
if value.respond_to?(:accept)
|
|
63
|
+
value.accept(visitor)
|
|
64
|
+
elsif value.is_a? Array
|
|
65
|
+
value.each { |item| visit_parameters(visitor, item) }
|
|
66
|
+
elsif value.is_a? Hash
|
|
67
|
+
value.each { |_key, item| visit_parameters(visitor, item) }
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
module ForemanDeployments
|
|
2
|
+
module Tasks
|
|
3
|
+
class CreationTaskDefinition < ForemanDeployments::Tasks::BaseDefinition
|
|
4
|
+
class Action < BaseAction
|
|
5
|
+
def run
|
|
6
|
+
obj = CreationTaskDefinition.create_object(input)
|
|
7
|
+
obj.save!
|
|
8
|
+
CreationTaskDefinition.create_output(obj, output)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def validate
|
|
13
|
+
obj = self.class.create_object(parameters.configured)
|
|
14
|
+
obj.valid?
|
|
15
|
+
ForemanDeployments::Validation::ValidationResult.new(obj.errors.full_messages)
|
|
16
|
+
rescue ActiveRecord::ActiveRecordError => e
|
|
17
|
+
ForemanDeployments::Validation::ValidationResult.new([e.message])
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def preliminary_output
|
|
21
|
+
self.class.create_output(self.class.create_object(parameters.configured))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def dynflow_action
|
|
25
|
+
self.class::Action
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.create_object(parameters)
|
|
29
|
+
object_type = parameters['class']
|
|
30
|
+
object_params = parameters['params'] || {}
|
|
31
|
+
|
|
32
|
+
object_type = object_type.constantize if object_type.is_a? String
|
|
33
|
+
object = object_type.new
|
|
34
|
+
|
|
35
|
+
set_parameters(object, object_params)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.set_parameters(object, object_params)
|
|
39
|
+
object_params.each do |key, value|
|
|
40
|
+
if object.respond_to?("#{key}=")
|
|
41
|
+
object.send("#{key}=", value)
|
|
42
|
+
# TODO: else, add warning message
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
object
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.create_output(obj, output_hash = {})
|
|
50
|
+
output_hash['object'] = obj
|
|
51
|
+
output_hash
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def self.tag_name
|
|
55
|
+
'CreateResource'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.build(parameters)
|
|
59
|
+
case parameters['class']
|
|
60
|
+
when 'Host', 'Host::Managed'
|
|
61
|
+
HostCreationTaskDefinition.new(parameters)
|
|
62
|
+
else
|
|
63
|
+
CreationTaskDefinition.new(parameters)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
module ForemanDeployments
|
|
2
|
+
module Tasks
|
|
3
|
+
class HostCreationTaskDefinition < ForemanDeployments::Tasks::CreationTaskDefinition
|
|
4
|
+
class Action < BaseAction
|
|
5
|
+
def run
|
|
6
|
+
obj = HostCreationTaskDefinition.create_object(input)
|
|
7
|
+
obj.save!
|
|
8
|
+
HostCreationTaskDefinition.create_output(obj, output)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.create_object(parameters)
|
|
13
|
+
object_type = parameters['class']
|
|
14
|
+
object_params = parameters['params']
|
|
15
|
+
object_params['managed'] ||= true
|
|
16
|
+
|
|
17
|
+
object_type = object_type.constantize if object_type.is_a? String
|
|
18
|
+
|
|
19
|
+
initial_params = {
|
|
20
|
+
:interfaces_attributes => object_params.delete('interfaces_attributes') || {}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
object = object_type.new(initial_params)
|
|
24
|
+
object = set_parameters(object, object_params)
|
|
25
|
+
|
|
26
|
+
initialize_manged_host(object, object_params) if object.is_a? Host::Managed
|
|
27
|
+
|
|
28
|
+
object
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.initialize_manged_host(object, object_params)
|
|
32
|
+
object_params['build'] ||= true
|
|
33
|
+
# Set compute attributes from a compute profile
|
|
34
|
+
if object.compute_resource_id && object.compute_profile_id
|
|
35
|
+
profile_attributes = object.compute_resource.compute_profile_attributes_for(object.compute_profile_id)
|
|
36
|
+
object.compute_attributes = profile_attributes.merge(object.compute_attributes || {})
|
|
37
|
+
end
|
|
38
|
+
# Merge interfaces from a compute profile
|
|
39
|
+
merge = InterfaceMerge.new
|
|
40
|
+
merge.run(object.interfaces, object.compute_resource.try(:compute_profile_for, object.compute_profile_id))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module ForemanDeployments
|
|
2
|
+
module Tasks
|
|
3
|
+
class SearchTaskDefinition < BaseDefinition
|
|
4
|
+
class Action < BaseAction
|
|
5
|
+
def run
|
|
6
|
+
results = SearchTaskDefinition.search(input)
|
|
7
|
+
results = SerializableArray.new(results)
|
|
8
|
+
SearchTaskDefinition.create_output(results, output)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
class SerializableArray < Array
|
|
13
|
+
def to_hash
|
|
14
|
+
{}
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def validate
|
|
19
|
+
results = SearchTaskDefinition.search(parameters.configured)
|
|
20
|
+
messages = []
|
|
21
|
+
unless results.any?
|
|
22
|
+
messages = [
|
|
23
|
+
_('%s didn\'t return valid objects') % "#{parameters['class']}.search_for('#{parameters['search_term']}')"]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
ForemanDeployments::Validation::ValidationResult.new(messages)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def preliminary_output
|
|
30
|
+
SearchTaskDefinition.create_output(SearchTaskDefinition.search(parameters.configured))
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def dynflow_action
|
|
34
|
+
ForemanDeployments::Tasks::SearchTaskDefinition::Action
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.search(parameters)
|
|
38
|
+
object_type = parameters['class']
|
|
39
|
+
object_type = object_type.constantize if object_type.is_a? String
|
|
40
|
+
results = object_type.search_for(parameters[:search_term])
|
|
41
|
+
results
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.create_output(obj, output_hash = {})
|
|
45
|
+
output_hash['results'] = obj
|
|
46
|
+
output_hash['result'] = { 'ids' => obj.map(&:id) }
|
|
47
|
+
output_hash
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.tag_name
|
|
51
|
+
'FindResource'
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
module ForemanDeployments
|
|
2
|
+
module Tasks
|
|
3
|
+
class WaitUntilBuiltTaskDefinition < ForemanDeployments::Tasks::BaseDefinition
|
|
4
|
+
class Action < BaseAction
|
|
5
|
+
include Dynflow::Action::Polling
|
|
6
|
+
|
|
7
|
+
def done?
|
|
8
|
+
external_task['built'] == true
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def timeout
|
|
12
|
+
input['timeout'] || 2 * 60 * 60 # 2 hours default
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def invoke_external_task
|
|
16
|
+
schedule_timeout(timeout) unless timeout <= 0
|
|
17
|
+
WaitUntilBuiltTaskDefinition.build_status
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def poll_external_task
|
|
21
|
+
fail(_("'%s' is a required parameter") % 'host_id') unless input.key?('host_id')
|
|
22
|
+
|
|
23
|
+
host = Host.find(input['host_id'])
|
|
24
|
+
WaitUntilBuiltTaskDefinition.create_output(host, output)
|
|
25
|
+
WaitUntilBuiltTaskDefinition.build_status(host)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def poll_interval
|
|
29
|
+
30
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def validate
|
|
34
|
+
result = ForemanDeployments::Validation::ValidationResult.new([])
|
|
35
|
+
unless parameters.configured.key?('host_id')
|
|
36
|
+
result.messages << _("'%s' is a required parameter") % 'host_id'
|
|
37
|
+
end
|
|
38
|
+
result
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def preliminary_output(_parameters)
|
|
42
|
+
WaitUntilBuiltTaskDefinition.create_output(Host::Managed.new)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def dynflow_action
|
|
46
|
+
ForemanDeployments::Tasks::WaitUntilBuiltTaskDefinition::Action
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.create_output(host, output_hash = {})
|
|
50
|
+
output_hash['object'] = host
|
|
51
|
+
output_hash['object']['facts'] = host.facts
|
|
52
|
+
output_hash
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.build_status(host = nil)
|
|
56
|
+
status = (!host.nil? && (host.reports.count > 1) && !host.reports.last.error?)
|
|
57
|
+
{ 'build' => status }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def self.tag_name
|
|
61
|
+
'WaitUntilBuilt'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module ForemanDeployments
|
|
2
|
+
module Validation
|
|
3
|
+
class DereferenceVisitor < ForemanDeployments::BaseDereferenceVisitor
|
|
4
|
+
protected
|
|
5
|
+
|
|
6
|
+
def get_dereference(ref)
|
|
7
|
+
ref.dereference(get_preliminary_output(ref.task))
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def get_preliminary_output(task)
|
|
11
|
+
cached(task) do
|
|
12
|
+
task.parameters = dereference(task.parameters)
|
|
13
|
+
task.preliminary_output
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
module ForemanDeployments
|
|
2
|
+
module Validation
|
|
3
|
+
class RemoveIdsVisitor
|
|
4
|
+
def visit(subject)
|
|
5
|
+
if subject.is_a? ForemanDeployments::Tasks::CreationTaskDefinition
|
|
6
|
+
remove_ids(subject.parameters)
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def remove_ids(value)
|
|
13
|
+
case value
|
|
14
|
+
when Config::Hash
|
|
15
|
+
remove_ids_from_hash(value)
|
|
16
|
+
when Config::Array
|
|
17
|
+
remove_ids_from_array(value)
|
|
18
|
+
when TaskReference
|
|
19
|
+
remove_id_from_reference(value)
|
|
20
|
+
else
|
|
21
|
+
value
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def remove_ids_from_hash(hash)
|
|
26
|
+
hash.transform! do |key, item|
|
|
27
|
+
if singular_reference?(key, item) || multiple_references?(key, item)
|
|
28
|
+
[key.to_s.sub('_id', ''), remove_ids(item)]
|
|
29
|
+
else
|
|
30
|
+
[key, remove_ids(item)]
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def remove_ids_from_array(array)
|
|
36
|
+
array.transform! do |item|
|
|
37
|
+
remove_ids(item)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def remove_id_from_reference(ref)
|
|
42
|
+
if ref.output_key.end_with?('.ids')
|
|
43
|
+
ref.output_key.gsub!(/[.]ids$/, 's')
|
|
44
|
+
elsif ref.output_key.end_with?('.id')
|
|
45
|
+
ref.output_key.gsub!(/[.]id$/, '')
|
|
46
|
+
end
|
|
47
|
+
ref
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def singular_reference?(key, value)
|
|
51
|
+
key.to_s.end_with?('_id') && value.is_a?(TaskReference)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def multiple_references?(key, values)
|
|
55
|
+
key.to_s.end_with?('_ids') && (values.is_a?(TaskReference) || values.all? { |v| v.is_a?(TaskReference) })
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|