staypuft 0.1.5 → 0.1.6
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 +8 -8
- data/app/assets/javascripts/staypuft/staypuft.js +99 -1
- data/app/assets/stylesheets/staypuft/bootstrap_and_overrides.css.scss +48 -4
- data/app/assets/stylesheets/staypuft/staypuft.css.scss +7 -11
- data/app/controllers/staypuft/deployments_controller.rb +23 -20
- data/app/controllers/staypuft/steps_controller.rb +18 -24
- data/app/helpers/staypuft/application_helper.rb +16 -1
- data/app/helpers/staypuft/deployments_helper.rb +1 -1
- data/app/lib/actions/staypuft/host/wait_until_host_ready.rb +2 -8
- data/app/lib/staypuft/seeder.rb +702 -0
- data/app/models/staypuft/concerns/host_open_stack_affiliation.rb +29 -2
- data/app/models/staypuft/concerns/hostgroup_extensions.rb +28 -3
- data/app/models/staypuft/concerns/lookup_key_extensions.rb +72 -0
- data/app/models/staypuft/deployment/abstract_param_scope.rb +31 -0
- data/app/models/staypuft/deployment/attribute_param_storage.rb +41 -0
- data/app/models/staypuft/deployment/cinder_service.rb +87 -0
- data/app/models/staypuft/deployment/glance_service.rb +85 -0
- data/app/models/staypuft/deployment/ips.rb +26 -0
- data/app/models/staypuft/deployment/neutron_service.rb +165 -0
- data/app/models/staypuft/deployment/nova_service.rb +84 -0
- data/app/models/staypuft/deployment/passwords.rb +66 -0
- data/app/models/staypuft/deployment/vips.rb +36 -0
- data/app/models/staypuft/deployment.rb +179 -72
- data/app/models/staypuft/deployment_role_hostgroup.rb +1 -1
- data/app/models/staypuft/role.rb +8 -1
- data/app/models/staypuft/service/ui_params.rb +12 -1
- data/app/views/staypuft/deployments/_assigned_hosts_table.html.erb +60 -0
- data/app/views/staypuft/deployments/_deployed_hosts_table.html.erb +51 -0
- data/app/views/staypuft/deployments/_free_hosts_table.html.erb +47 -0
- data/app/views/staypuft/deployments/edit.html.erb +50 -0
- data/app/views/staypuft/deployments/show.html.erb +41 -79
- data/app/views/staypuft/deployments/summary.html.erb +4 -1
- data/app/views/staypuft/steps/_cinder.html.erb +17 -0
- data/app/views/staypuft/steps/_glance.html.erb +16 -0
- data/app/views/staypuft/steps/_neutron.html.erb +57 -0
- data/app/views/staypuft/steps/_nova.html.erb +34 -0
- data/app/views/staypuft/steps/deployment_settings.html.erb +41 -17
- data/app/views/staypuft/steps/services_configuration.html.erb +19 -32
- data/app/views/staypuft/steps/{services_selection.html.erb → services_overview.html.erb} +7 -3
- data/config/routes.rb +2 -0
- data/db/migrate/20140623142500_remove_amqp_provider_from_staypuft_deployment.rb +6 -0
- data/db/seeds.rb +1 -314
- data/lib/staypuft/engine.rb +1 -0
- data/lib/staypuft/version.rb +1 -1
- metadata +23 -3
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZjllNGYyYjkzYTQwOTFhMDBiYmVmMzdiN2E4ZjlhY2EyZDRmN2VjNw==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MzNiNDViNTcwZWJmNTg3N2VlNzAxZDM2MWIzNTVlNDEyZWUyZmQ5Nw==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NzUzNDAwZTNlMzQxYzdkNDY5YzM2MWNiNTRjMzgyMjNlNDNjMDhlOTQ2OGIz
|
10
|
+
MmE3NTQxMjgyNGNhZTA1ODM4YjJlODY2YzdlNzRlYjMzOThmNmJlZjI2Mjkx
|
11
|
+
YmM1NDE3MTcwNWIzMDc5OWQxODgwYTFhZjBkNjkzOWUzNGQ4OTE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MjYyMTg1ODk3NTc2MmQzZmI4YjEzZTRlYzU1NTFiYjhkZmY2YmJmZjk1M2E1
|
14
|
+
MGE3MDU5Y2M3MDQ5Y2RhNDE2NjljYzU1ZWU0MzI4NjViNTFlOTczMzc2ZjM0
|
15
|
+
MGFjZGQyZTI4NGUyMGRmMmNlMmY0ZDNjYzEzZTVlYWM3MzQzNzI=
|
@@ -24,7 +24,105 @@ $(function () {
|
|
24
24
|
var tr = $(this).closest("tr");
|
25
25
|
tr.toggleClass("info", this.checked);
|
26
26
|
if (tr.hasClass("deployed")) {
|
27
|
-
tr.toggleClass("danger",
|
27
|
+
tr.toggleClass("danger", this.checked);
|
28
28
|
}
|
29
29
|
});
|
30
|
+
|
31
|
+
// Workaround to properly activate and deactivate tabs in tabbed_side_nav_table
|
32
|
+
// Should be probably done properly by extending Bootstrap Tab
|
33
|
+
$(".tabbed_side_nav_table").on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
|
34
|
+
e.preventDefault();
|
35
|
+
$(this).closest('ul').find('.activated').removeClass('activated');
|
36
|
+
$(this).addClass("activated");
|
37
|
+
$(this).closest('li').addClass('activated');
|
38
|
+
});
|
39
|
+
|
40
|
+
$('.tabbed_side_nav_table').on('click', 'button.close', function() {
|
41
|
+
$(this).closest('.tab-pane.active').removeClass('active');
|
42
|
+
$(this).closest('.tabbed_side_nav_table').find('.activated').removeClass('activated');
|
43
|
+
})
|
44
|
+
|
45
|
+
var duration = 150;
|
46
|
+
|
47
|
+
showPasswords();
|
48
|
+
$("input[name='staypuft_deployment[passwords][mode]']").change(showPasswords);
|
49
|
+
function showPasswords() {
|
50
|
+
if ($('#staypuft_deployment_passwords_mode_single').is(":checked")) {
|
51
|
+
$('.single_password').fadeIn(duration);
|
52
|
+
}
|
53
|
+
else {
|
54
|
+
$('.single_password').fadeOut(duration)
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
showNovaVlanRange();
|
59
|
+
$("input[name='staypuft_deployment[nova][network_manager]']").change(showNovaVlanRange);
|
60
|
+
function showNovaVlanRange() {
|
61
|
+
if ($('#staypuft_deployment_nova_network_manager_vlanmanager').is(":checked")) {
|
62
|
+
$('.nova_vlan_range').fadeIn(duration);
|
63
|
+
}
|
64
|
+
else {
|
65
|
+
$('.nova_vlan_range').fadeOut(duration)
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
showNeutronVlanRange();
|
70
|
+
$("input[name='staypuft_deployment[neutron][network_segmentation]']").change(showNeutronVlanRange);
|
71
|
+
function showNeutronVlanRange() {
|
72
|
+
if ($('#staypuft_deployment_neutron_network_segmentation_vlan').is(":checked")) {
|
73
|
+
$('.neutron_tenant_vlan_ranges').fadeIn(duration);
|
74
|
+
}
|
75
|
+
else {
|
76
|
+
$('.neutron_tenant_vlan_ranges').fadeOut(duration)
|
77
|
+
}
|
78
|
+
}
|
79
|
+
|
80
|
+
showNeutronExternalInterface();
|
81
|
+
$("input[name='staypuft_deployment[neutron][use_external_interface]']").change(showNeutronExternalInterface);
|
82
|
+
function showNeutronExternalInterface() {
|
83
|
+
if ($('#staypuft_deployment_neutron_use_external_interface').is(":checked")) {
|
84
|
+
$('.neutron_external_interface').fadeIn(duration);
|
85
|
+
}
|
86
|
+
else {
|
87
|
+
$('.neutron_external_interface').fadeOut(duration)
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
showNeutronExternalVlan();
|
92
|
+
$("input[name='staypuft_deployment[neutron][use_vlan_for_external_network]']").change(showNeutronExternalVlan);
|
93
|
+
function showNeutronExternalVlan() {
|
94
|
+
if ($('#staypuft_deployment_neutron_use_vlan_for_external_network').is(":checked")) {
|
95
|
+
$('.neutron_external_vlan').fadeIn(duration);
|
96
|
+
}
|
97
|
+
else {
|
98
|
+
$('.neutron_external_vlan').fadeOut(duration)
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
showGlanceNfsNetworkPath();
|
103
|
+
$("input[name='staypuft_deployment[glance][driver_backend]']").change(showGlanceNfsNetworkPath);
|
104
|
+
function showGlanceNfsNetworkPath() {
|
105
|
+
if ($('#staypuft_deployment_glance_driver_backend_nfs').is(":checked")) {
|
106
|
+
$('.glance_nfs_network_path').show();
|
107
|
+
}
|
108
|
+
else {
|
109
|
+
$('.glance_nfs_network_path').hide();
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
showCinderNfsUri();
|
114
|
+
$("input[name='staypuft_deployment[cinder][driver_backend]']").change(showCinderNfsUri);
|
115
|
+
function showCinderNfsUri() {
|
116
|
+
if ($('#staypuft_deployment_cinder_driver_backend_nfs').is(":checked")) {
|
117
|
+
$('.cinder_nfs_uri').show();
|
118
|
+
}
|
119
|
+
else {
|
120
|
+
$('.cinder_nfs_uri').hide();
|
121
|
+
}
|
122
|
+
}
|
123
|
+
|
124
|
+
if ($('.configuration').length > 0) {
|
125
|
+
$('.configuration').find('li').first().find('a')[0].click();
|
126
|
+
}
|
127
|
+
|
30
128
|
});
|
@@ -86,12 +86,12 @@
|
|
86
86
|
}
|
87
87
|
|
88
88
|
.tabbed_side_nav_table{
|
89
|
-
.nav
|
89
|
+
.nav {
|
90
90
|
padding-top: 5px;
|
91
91
|
padding-right: 4px;
|
92
|
-
& > li.
|
92
|
+
& > li.activated {
|
93
93
|
z-index: 1;
|
94
|
-
|
94
|
+
&:after, &:before {
|
95
95
|
content: "";
|
96
96
|
position: absolute;
|
97
97
|
top: 0px;
|
@@ -103,13 +103,51 @@
|
|
103
103
|
border-color: rgba(238, 238, 238, 0) rgb(238, 238, 238) rgba(238, 238, 238, 0) rgba(238, 238, 238, 0);
|
104
104
|
-webkit-transform:rotate(360deg);
|
105
105
|
}
|
106
|
-
|
106
|
+
&:before {
|
107
107
|
border-width: 21px 16px 21px 0;
|
108
108
|
top: -1px;
|
109
109
|
right: -9px;
|
110
110
|
border-right-color: rgb(217, 217, 217);
|
111
111
|
}
|
112
112
|
}
|
113
|
+
li {
|
114
|
+
border: 1px solid rgb(227, 227, 227);
|
115
|
+
height: 42px;
|
116
|
+
margin-bottom: 3px;
|
117
|
+
border-radius: 4px;
|
118
|
+
line-height: 40px;
|
119
|
+
box-sizing: border-box;
|
120
|
+
padding: 0;
|
121
|
+
text-align: center;
|
122
|
+
&:hover, &.activated {
|
123
|
+
background: rgb(238, 238, 238);
|
124
|
+
}
|
125
|
+
& > div {
|
126
|
+
padding: 0;
|
127
|
+
div.group_name {
|
128
|
+
text-align: left;
|
129
|
+
padding: 0 8px;
|
130
|
+
}
|
131
|
+
&:not(:first-child) {
|
132
|
+
border-left: 1px solid rgb(227, 227, 227);
|
133
|
+
}
|
134
|
+
&:last-child > a {
|
135
|
+
border-top-right-radius: 4px;
|
136
|
+
border-bottom-right-radius: 4px;
|
137
|
+
}
|
138
|
+
& > a {
|
139
|
+
box-sizing: border-box;
|
140
|
+
display: block;
|
141
|
+
&.activated {
|
142
|
+
background: $brand-primary;
|
143
|
+
color: white;
|
144
|
+
}
|
145
|
+
&.disabled {
|
146
|
+
color: $btn-link-disabled-color;
|
147
|
+
}
|
148
|
+
}
|
149
|
+
}
|
150
|
+
}
|
113
151
|
}
|
114
152
|
.tab-content {
|
115
153
|
padding-left: 4px;
|
@@ -119,3 +157,9 @@
|
|
119
157
|
}
|
120
158
|
}
|
121
159
|
}
|
160
|
+
|
161
|
+
.panel-body {
|
162
|
+
ul {
|
163
|
+
padding-left: 1em;
|
164
|
+
}
|
165
|
+
}
|
@@ -24,17 +24,13 @@
|
|
24
24
|
overflow: auto;
|
25
25
|
}
|
26
26
|
|
27
|
-
.nav > li > a.roles_list {
|
28
|
-
padding: 0;
|
29
|
-
border: 1px solid #ddd;
|
30
|
-
& > div {
|
31
|
-
padding: 10px;
|
32
|
-
&:not(:first-child) {
|
33
|
-
border-left: 1px solid #ddd;
|
34
|
-
}
|
35
|
-
}
|
36
|
-
}
|
37
|
-
|
38
27
|
.association.well {
|
39
28
|
min-height: 500px;
|
29
|
+
margin-top: 50px;
|
30
|
+
h4{
|
31
|
+
margin: 6px 0 6px 0;
|
32
|
+
&.pull-left {
|
33
|
+
margin-left: 10px;
|
34
|
+
}
|
35
|
+
}
|
40
36
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Staypuft
|
2
|
-
class DeploymentsController < ApplicationController
|
2
|
+
class DeploymentsController < Staypuft::ApplicationController
|
3
3
|
include Foreman::Controller::AutoCompleteSearch
|
4
4
|
|
5
5
|
def index
|
@@ -7,16 +7,7 @@ module Staypuft
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def new
|
10
|
-
|
11
|
-
|
12
|
-
deployment = Deployment.new(:name => Deployment::NEW_NAME_PREFIX+SecureRandom.hex,
|
13
|
-
:amqp_provider => Deployment::AMQP_RABBITMQ)
|
14
|
-
deployment.layout = Layout.where(:name => "Distributed",
|
15
|
-
:networking => "neutron").first
|
16
|
-
deployment_hostgroup = ::Hostgroup.new name: deployment.name, parent: base_hostgroup
|
17
|
-
deployment_hostgroup.save!
|
18
|
-
|
19
|
-
deployment.hostgroup = deployment_hostgroup
|
10
|
+
deployment = Deployment.new(:name => Deployment::NEW_NAME_PREFIX+SecureRandom.hex)
|
20
11
|
deployment.save!
|
21
12
|
|
22
13
|
redirect_to deployment_steps_path(deployment_id: deployment)
|
@@ -33,6 +24,12 @@ module Staypuft
|
|
33
24
|
@service_hostgroup_map = @deployment.services_hostgroup_map
|
34
25
|
end
|
35
26
|
|
27
|
+
# FIXME: missing update action, there is no way how to submit the edited params
|
28
|
+
def edit
|
29
|
+
@deployment = Deployment.find(params[:id])
|
30
|
+
@service_hostgroup_map = @deployment.services_hostgroup_map
|
31
|
+
end
|
32
|
+
|
36
33
|
def destroy
|
37
34
|
Deployment.find(params[:id]).destroy
|
38
35
|
process_success
|
@@ -58,10 +55,7 @@ module Staypuft
|
|
58
55
|
hostgroup = ::Hostgroup.find params[:hostgroup_id]
|
59
56
|
deployment_in_progress = ForemanTasks::Lock.locked?(deployment, nil)
|
60
57
|
|
61
|
-
|
62
|
-
assigned_hosts = hostgroup.hosts
|
63
|
-
hosts_to_assign = targeted_hosts - assigned_hosts
|
64
|
-
hosts_to_remove = assigned_hosts - targeted_hosts
|
58
|
+
hosts_to_assign = ::Host::Base.find Array(params[:host_ids])
|
65
59
|
|
66
60
|
unassigned_hosts = hosts_to_assign.reduce([]) do |unassigned_hosts, discovered_host|
|
67
61
|
success, host = assign_host_to_hostgroup discovered_host, hostgroup
|
@@ -77,11 +71,20 @@ module Staypuft
|
|
77
71
|
join("\n"))
|
78
72
|
end
|
79
73
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
74
|
+
redirect_to show_with_hostgroup_selected_deployment_path(
|
75
|
+
id: deployment, hostgroup_id: hostgroup)
|
76
|
+
end
|
77
|
+
|
78
|
+
def unassign_host
|
79
|
+
deployment = Deployment.find(params[:id])
|
80
|
+
hostgroup = ::Hostgroup.find params[:hostgroup_id]
|
81
|
+
deployment_in_progress = ForemanTasks::Lock.locked?(deployment, nil)
|
82
|
+
|
83
|
+
hosts_to_unassign = ::Host::Base.find Array(params[:host_ids])
|
84
|
+
|
85
|
+
hosts_to_unassign.each do |host|
|
86
|
+
unless host.open_stack_deployed? && deployment_in_progress
|
87
|
+
host.open_stack_unassign
|
85
88
|
host.environment = Environment.get_discovery
|
86
89
|
host.save!
|
87
90
|
host.setBuild
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Staypuft
|
2
|
-
class StepsController < ApplicationController
|
2
|
+
class StepsController < Staypuft::ApplicationController
|
3
3
|
include Wicked::Wizard
|
4
|
-
steps :deployment_settings, :
|
4
|
+
steps :deployment_settings, :services_overview, :services_configuration
|
5
5
|
|
6
6
|
before_filter :get_deployment
|
7
7
|
|
@@ -10,7 +10,7 @@ module Staypuft
|
|
10
10
|
when :deployment_settings
|
11
11
|
@layouts = ordered_layouts
|
12
12
|
when :services_configuration
|
13
|
-
@
|
13
|
+
@services_map = [:nova, :neutron, :glance, :cinder]
|
14
14
|
end
|
15
15
|
|
16
16
|
render_wizard
|
@@ -18,33 +18,27 @@ module Staypuft
|
|
18
18
|
|
19
19
|
def update
|
20
20
|
case step
|
21
|
+
|
21
22
|
when :deployment_settings
|
22
|
-
@layouts
|
23
|
+
@layouts = ordered_layouts
|
24
|
+
# FIXME: validate that deployment is valid when leaving wizard with cancel button
|
25
|
+
@deployment.form_step = Deployment::STEP_SETTINGS
|
26
|
+
@deployment.passwords.attributes = params[:staypuft_deployment].delete(:passwords)
|
27
|
+
@deployment.attributes = params[:staypuft_deployment]
|
28
|
+
|
29
|
+
when :services_overview
|
30
|
+
@deployment.form_step = Deployment::STEP_OVERVIEW
|
23
31
|
|
24
|
-
Deployment.transaction do
|
25
|
-
@deployment.form_step = Deployment::STEP_SETTINGS unless @deployment.form_complete?
|
26
|
-
@deployment.update_attributes(params[:staypuft_deployment])
|
27
|
-
@deployment.update_hostgroup_list
|
28
|
-
@deployment.set_custom_params
|
29
|
-
end
|
30
|
-
when :services_selection
|
31
|
-
@deployment.form_step = Deployment::STEP_SELECTION unless @deployment.form_complete?
|
32
32
|
when :services_configuration
|
33
|
-
|
34
|
-
@service_hostgroup_map = @deployment.services_hostgroup_map
|
33
|
+
@services_map = [:nova, :neutron, :glance, :cinder]
|
35
34
|
if params[:staypuft_deployment]
|
36
|
-
@deployment.form_step = Deployment::STEP_CONFIGURATION
|
37
|
-
|
38
|
-
|
39
|
-
hostgroup = Hostgroup.find(hostgroup_id)
|
40
|
-
hostgroup_params[:puppetclass_params].each do |puppetclass_id, puppetclass_params|
|
41
|
-
puppetclass = Puppetclass.find(puppetclass_id)
|
42
|
-
puppetclass_params.each do |param_name, param_value|
|
43
|
-
hostgroup.set_param_value_if_changed(puppetclass, param_name, param_value)
|
44
|
-
end
|
45
|
-
end
|
35
|
+
@deployment.form_step = Deployment::STEP_CONFIGURATION
|
36
|
+
@services_map.each do |service|
|
37
|
+
@deployment.send(service).attributes = params[:staypuft_deployment].delete(service)
|
46
38
|
end
|
47
39
|
end
|
40
|
+
else
|
41
|
+
raise 'unknown step'
|
48
42
|
end
|
49
43
|
|
50
44
|
render_wizard @deployment
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Staypuft
|
2
2
|
module ApplicationHelper
|
3
3
|
def radio_button_f_non_inline(f, attr, options = {})
|
4
|
-
text
|
4
|
+
text = options.delete(:text)
|
5
5
|
value = options.delete(:value)
|
6
6
|
content_tag(:div, :class => 'radio') do
|
7
7
|
label_tag('') do
|
@@ -9,5 +9,20 @@ module Staypuft
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
end
|
12
|
+
|
13
|
+
def check_box_f_non_inline(f, attr, options = {})
|
14
|
+
text = options.delete(:text)
|
15
|
+
checked_value = options.delete(:checked_value)
|
16
|
+
unchecked_value = options.delete(:unchecked_value)
|
17
|
+
content_tag(:div, :class => 'checkbox') do
|
18
|
+
label_tag('') do
|
19
|
+
f.check_box(attr, options, checked_value, unchecked_value) + " #{text} "
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def change_label_width(width, html)
|
25
|
+
html.gsub(/class="col-md-2 control-label"/, "class=\"col-md-#{width} control-label\"").html_safe
|
26
|
+
end
|
12
27
|
end
|
13
28
|
end
|
@@ -57,15 +57,10 @@ module Actions
|
|
57
57
|
5
|
58
58
|
end
|
59
59
|
|
60
|
-
# TODO The puppet modules sometimes fail then become ready
|
61
|
-
# after subsequent hosts have started. For this reason
|
62
|
-
# we can not check to see if the host is ready using the
|
63
|
-
# stats on the host only. This needs fixing in the puppet
|
64
|
-
# modules then reflecting here.
|
65
60
|
def host_ready?(host_id)
|
66
61
|
host = ::Host.find(host_id)
|
67
62
|
host.reports.order('reported_at DESC').any? do |report|
|
68
|
-
|
63
|
+
check_for_failures(report, host.id)
|
69
64
|
report_change?(report)
|
70
65
|
end
|
71
66
|
end
|
@@ -74,10 +69,9 @@ module Actions
|
|
74
69
|
report.status['applied'] > 0
|
75
70
|
end
|
76
71
|
|
77
|
-
# TODO To aid logging add the report ID to the exception or
|
78
|
-
# the output object.
|
79
72
|
def check_for_failures(report, id)
|
80
73
|
if report.status['failed'] > 0
|
74
|
+
output[:report_id] = report.id
|
81
75
|
fail(::Staypuft::Exception, "Latest Puppet Run Contains Failures for Host: #{id}")
|
82
76
|
end
|
83
77
|
end
|