staypuft 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/LICENSE +619 -0
  2. data/README.md +109 -0
  3. data/Rakefile +35 -0
  4. data/app/assets/javascripts/staypuft/staypuft.js +21 -0
  5. data/app/assets/stylesheets/staypuft/bootstrap_and_overrides.css.scss +80 -0
  6. data/app/assets/stylesheets/staypuft/staypuft.css.scss +35 -0
  7. data/app/controllers/staypuft/application_controller.rb +5 -0
  8. data/app/controllers/staypuft/deployment_steps_controller.rb +51 -0
  9. data/app/controllers/staypuft/deployments_controller.rb +37 -0
  10. data/app/helpers/staypuft/application_helper.rb +13 -0
  11. data/app/helpers/staypuft/deployments_helper.rb +12 -0
  12. data/app/lib/actions/staypuft/deployment/deploy.rb +32 -0
  13. data/app/lib/actions/staypuft/host/build.rb +55 -0
  14. data/app/lib/actions/staypuft/host/create.rb +69 -0
  15. data/app/lib/actions/staypuft/host/deploy.rb +40 -0
  16. data/app/lib/actions/staypuft/host/provision.rb +50 -0
  17. data/app/lib/actions/staypuft/host/puppet_run.rb +36 -0
  18. data/app/lib/actions/staypuft/host/wait_until_host_ready.rb +72 -0
  19. data/app/lib/actions/staypuft/host/wait_until_installed.rb +44 -0
  20. data/app/lib/actions/staypuft/hostgroup/deploy.rb +47 -0
  21. data/app/lib/actions/staypuft/hostgroup/ordered_deploy.rb +42 -0
  22. data/app/lib/actions/staypuft/middleware/as_current_user.rb +38 -0
  23. data/app/lib/staypuft/exception.rb +15 -0
  24. data/app/models/settings/staypuft.rb +21 -0
  25. data/app/models/staypuft/concerns/host_orchestration_build_hook.rb +23 -0
  26. data/app/models/staypuft/concerns/hostgroup_extensions.rb +41 -0
  27. data/app/models/staypuft/concerns/puppetclass_extensions.rb +12 -0
  28. data/app/models/staypuft/deployment.rb +61 -0
  29. data/app/models/staypuft/deployment_role_hostgroup.rb +18 -0
  30. data/app/models/staypuft/layout.rb +13 -0
  31. data/app/models/staypuft/layout_role.rb +14 -0
  32. data/app/models/staypuft/role.rb +20 -0
  33. data/app/models/staypuft/role_class.rb +12 -0
  34. data/app/models/staypuft/role_service.rb +13 -0
  35. data/app/models/staypuft/service.rb +13 -0
  36. data/app/models/staypuft/service_class.rb +13 -0
  37. data/app/views/staypuft/deployment_steps/_title.html.erb +2 -0
  38. data/app/views/staypuft/deployment_steps/deployment_settings.html.erb +54 -0
  39. data/app/views/staypuft/deployment_steps/services_configuration.html.erb +42 -0
  40. data/app/views/staypuft/deployment_steps/services_selection.html.erb +39 -0
  41. data/app/views/staypuft/deployments/index.html.erb +26 -0
  42. data/app/views/staypuft/deployments/show.html.erb +79 -0
  43. data/app/views/staypuft/layouts/staypuft.html.erb +9 -0
  44. data/config/routes.rb +12 -0
  45. data/config/staypuft.local.rb +1 -0
  46. data/db/migrate/20140309021811_create_staypuft_layouts.rb +10 -0
  47. data/db/migrate/20140310004533_create_staypuft_deployments.rb +17 -0
  48. data/db/migrate/20140310023613_create_staypuft_roles.rb +12 -0
  49. data/db/migrate/20140310174152_create_staypuft_layout_roles.rb +15 -0
  50. data/db/migrate/20140310194221_create_staypuft_services.rb +10 -0
  51. data/db/migrate/20140310203855_create_staypuft_role_services.rb +15 -0
  52. data/db/migrate/20140312044533_create_staypuft_deployment_role_hostgroups.rb +15 -0
  53. data/db/migrate/20140312050001_create_staypuft_hostgroup_roles.rb +15 -0
  54. data/db/migrate/20140312050615_create_staypuft_role_classes.rb +15 -0
  55. data/db/migrate/20140312051144_create_staypuft_service_classes.rb +15 -0
  56. data/db/migrate/20140315031754_add_networking_to_staypuft_layout.rb +5 -0
  57. data/db/migrate/20140318163222_add_deploy_order_to_staypuft_layout_role.rb +6 -0
  58. data/db/migrate/20140325211410_add_role_to_staypuft_deployment_role_hostgroup.rb +27 -0
  59. data/db/migrate/20140326032027_drop_staypuft_hostgroup_roles.rb +19 -0
  60. data/db/seeds.rb +243 -0
  61. data/lib/staypuft/engine.rb +56 -0
  62. data/lib/staypuft/version.rb +3 -0
  63. data/lib/staypuft.rb +6 -0
  64. data/lib/tasks/staypuft_tasks.rake +31 -0
  65. data/test/factories/staypuft_factories.rb +5 -0
  66. data/test/integration/navigation_test.rb +10 -0
  67. data/test/staypuft_test.rb +7 -0
  68. data/test/test_helper.rb +14 -0
  69. data/test/test_plugin_helper.rb +6 -0
  70. data/test/unit/staypuft_test.rb +12 -0
  71. metadata +153 -0
@@ -0,0 +1,72 @@
1
+ #
2
+ # Copyright 2014 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 Actions
14
+ module Staypuft
15
+ module Host
16
+
17
+ class WaitUntilHostReady < Actions::Base
18
+
19
+ middleware.use Actions::Staypuft::Middleware::AsCurrentUser
20
+ include Dynflow::Action::Polling
21
+
22
+ def plan(host_id)
23
+ plan_self host_id: host_id
24
+ end
25
+
26
+ def external_task
27
+ output[:status]
28
+ end
29
+
30
+ def done?
31
+ external_task
32
+ end
33
+
34
+ private
35
+
36
+ def invoke_external_task
37
+ nil
38
+ end
39
+
40
+ def external_task=(external_task_data)
41
+ output[:status] = external_task_data
42
+ end
43
+
44
+ def poll_external_task
45
+ host_ready?(input[:host_id])
46
+ end
47
+
48
+ def poll_interval
49
+ 5
50
+ end
51
+
52
+ def host_ready?(host_id)
53
+ host = ::Host.find(host_id)
54
+ host.reports.order('reported_at DESC').any? do |report|
55
+ check_for_failures(report)
56
+ report_change?(report)
57
+ end
58
+ end
59
+
60
+ def report_change?(report)
61
+ report.status['applied'] > 0
62
+ end
63
+
64
+ def check_for_failures(report)
65
+ if report.status['failed'] > 0
66
+ fail(::Staypuft::Exception, "Latest Puppet Run Contains Failures for Host: #{host.id}")
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,44 @@
1
+ #
2
+ # Copyright 2014 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 Actions
14
+ module Staypuft
15
+ module Host
16
+
17
+ class WaitUntilInstalled < Actions::Base
18
+
19
+ middleware.use Actions::Staypuft::Middleware::AsCurrentUser
20
+
21
+ def run(event = nil)
22
+ case event
23
+ when nil
24
+ suspend do |suspended_action|
25
+ Rails.cache.write(
26
+ ::Staypuft::Concerns::HostOrchestrationBuildHook.cache_id(input[:host_id]),
27
+ { execution_plan_id: suspended_action.execution_plan_id,
28
+ step_id: suspended_action.step_id })
29
+ end
30
+ when Hash
31
+ output[:installed_at] = event.fetch(:installed_at).to_s
32
+ else
33
+ raise TypeError
34
+ end
35
+ end
36
+
37
+ def plan(host_id)
38
+ plan_self host_id: host_id
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,47 @@
1
+ #
2
+ # Copyright 2014 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 Actions
14
+ module Staypuft
15
+ module Hostgroup
16
+ class Deploy < Actions::Base
17
+
18
+ middleware.use Actions::Staypuft::Middleware::AsCurrentUser
19
+
20
+ def plan(hostgroup, hosts)
21
+ Type! hostgroup, ::Hostgroup
22
+ (Type! hosts, Array).all? { |v| Type! v, ::Host::Base }
23
+
24
+ input.update id: hostgroup.id, name: hostgroup.name
25
+
26
+ # hostgroup.hosts returns already converted hosts from Host::Discovered with build flag
27
+ # set to false so they are not built when assigned to the hostgroup in wizard
28
+ # run Hostgroup's Hosts filtered by hosts
29
+ (hostgroup.hosts & hosts).each do |host|
30
+ # planned in concurrence
31
+ plan_action Host::Deploy, host
32
+ end
33
+ end
34
+
35
+ def humanized_input
36
+ input[:name]
37
+ end
38
+
39
+ def humanized_output
40
+ format "Hostgroup: %s\n%s", input[:name],
41
+ planned_actions.map(&:humanized_output).map { |l| ' ' + l }.join("\n")
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,42 @@
1
+ #
2
+ # Copyright 2014 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 Actions
14
+ module Staypuft
15
+ module Hostgroup
16
+ # deploys Hostgroups in given order
17
+ class OrderedDeploy < Actions::Base
18
+
19
+ middleware.use Actions::Staypuft::Middleware::AsCurrentUser
20
+
21
+ def plan(hostgroups, hosts = hostgroups.inject([]) { |a, hg| a + hg.hosts })
22
+ (Type! hostgroups, Array).all? { |v| Type! v, ::Hostgroup }
23
+ (Type! hosts, Array).all? { |v| Type! v, ::Host::Base }
24
+
25
+ sequence do
26
+ hostgroups.each do |hostgroup|
27
+ plan_action Hostgroup::Deploy, hostgroup, hosts
28
+ end
29
+ end
30
+ end
31
+
32
+ def humanized_input
33
+ planned_actions.map(&:humanized_input).join(', ')
34
+ end
35
+
36
+ def humanized_output
37
+ planned_actions.map(&:humanized_output).join("\n")
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,38 @@
1
+ module Actions
2
+ module Staypuft
3
+ module Middleware
4
+ class AsCurrentUser < Dynflow::Middleware
5
+
6
+ def plan(*args)
7
+ pass(*args).tap do
8
+ raise 'no current user' unless Type? User.current, User
9
+ action.input.update current_user_id: User.current.id
10
+ end
11
+ end
12
+
13
+ def run(*args)
14
+ as_current_user { pass(*args) }
15
+ end
16
+
17
+ def finalize
18
+ as_current_user { pass }
19
+ end
20
+
21
+ private
22
+
23
+ def current_user_id
24
+ action.input.fetch(:current_user_id)
25
+ end
26
+
27
+ def as_current_user
28
+ old = User.current
29
+ User.current = User.find current_user_id
30
+ yield
31
+ ensure
32
+ User.current = old
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,15 @@
1
+ #
2
+ # Copyright 2014 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 Staypuft
14
+ class Exception < ::Foreman::Exception; end
15
+ end
@@ -0,0 +1,21 @@
1
+ class Setting::Staypuft < ::Setting
2
+ BLANK_ATTRS << "base_hostgroup"
3
+
4
+ def self.load_defaults
5
+ # Check the table exists
6
+ return unless super
7
+
8
+ # fixme: not sure about the best way to store AR objects in settings.
9
+ # for now, since we know type, store ID. It might be good to add custom
10
+ # get/set code to decode the ID value into a hostgroup (which methods to call?)
11
+ Setting.transaction do
12
+ [
13
+ self.set("base_hostgroup", _("The base hostgroup which contains the base provisioning config"), nil)
14
+ ].compact.each { |s| self.create s.update(:category => "Setting::Staypuft")}
15
+ end
16
+
17
+ true
18
+
19
+ end
20
+
21
+ end
@@ -0,0 +1,23 @@
1
+ module Staypuft
2
+ module Concerns
3
+ module HostOrchestrationBuildHook
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ before_provision :wake_up_orchestration
8
+ end
9
+
10
+ def wake_up_orchestration
11
+ key = HostOrchestrationBuildHook.cache_id(id)
12
+ ids = Rails.cache.read(key)
13
+ Rails.cache.delete key
14
+ ForemanTasks.dynflow.world.event *ids.values_at(:execution_plan_id, :step_id),
15
+ installed_at: installed_at
16
+ end
17
+
18
+ def self.cache_id(host_id)
19
+ "host.#{host_id}.wake_up_orchestration"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,41 @@
1
+ module Staypuft::Concerns::HostgroupExtensions
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ has_one :deployment_role_hostgroup, :dependent => :destroy, :class_name => 'Staypuft::DeploymentRoleHostgroup'
6
+ has_one :parent_deployment, :through => :deployment_role_hostgroup, :class_name => 'Staypuft::Deployment'
7
+ has_one :role, :through => :deployment_role_hostgroup, :class_name => 'Staypuft::Role'
8
+
9
+ has_one :deployment, :class_name => 'Staypuft::Deployment'
10
+
11
+ def add_puppetclasses_from_resource(resource)
12
+ if resource.respond_to?(:puppetclasses)
13
+ resource.puppetclasses.each do |puppetclass|
14
+ unless puppetclasses.include?(puppetclass)
15
+ puppetclasses << puppetclass
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ module ClassMethods
23
+ Gem::Version.new(SETTINGS[:version].to_s.gsub(/-develop$/, '')) < Gem::Version.new('1.5') or
24
+ raise 'remove nest method, nesting Hostgroups is fixed in Foreman 1.5, use just parent_id'
25
+
26
+ def nest(name, parent)
27
+ new = parent.dup
28
+ new.parent_id = parent.id
29
+ new.name = name
30
+
31
+ new.puppetclasses = parent.puppetclasses
32
+ new.locations = parent.locations
33
+ new.organizations = parent.organizations
34
+
35
+ # Clone any parameters as well
36
+ new.group_parameters.each { |param| parent.group_parameters << param.dup }
37
+ new
38
+ end
39
+ end
40
+
41
+ end
@@ -0,0 +1,12 @@
1
+ module Staypuft::Concerns::PuppetclassExtensions
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ has_many :role_classes, :dependent => :destroy, :class_name => 'Staypuft::RoleClass'
6
+ has_many :roles, :through => :role_classes, :class_name => 'Staypuft::Role'
7
+
8
+ has_many :service_classes, :dependent => :destroy, :class_name => 'Staypuft::ServiceClass'
9
+ has_many :services, :through => :service_classes, :class_name => 'Staypuft::Service'
10
+
11
+ end
12
+ end
@@ -0,0 +1,61 @@
1
+ module Staypuft
2
+ class Deployment < ActiveRecord::Base
3
+ attr_accessible :description, :name, :layout_id, :layout
4
+ after_save :update_hostgroup_name
5
+
6
+ belongs_to :layout
7
+ belongs_to :hostgroup, :dependent => :destroy
8
+
9
+ has_many :deployment_role_hostgroups, :dependent => :destroy
10
+ has_many :child_hostgroups, :through => :deployment_role_hostgroups, :class_name => 'Hostgroup',
11
+ :source => :hostgroup
12
+ has_many :roles, :through => :deployment_role_hostgroups
13
+
14
+ validates :name, :presence => true, :uniqueness => true
15
+
16
+ validates :layout, :presence => true
17
+ validates :hostgroup, :presence => true
18
+
19
+ scoped_search :on => :name, :complete_value => :true
20
+
21
+ def destroy
22
+ child_hostgroups.each do |h|
23
+ h.destroy
24
+ end
25
+ #do the main destroy
26
+ super
27
+ end
28
+
29
+ # After setting or changing layout, update the set of child hostgroups,
30
+ # adding groups for any roles not already represented, and removing others
31
+ # no longer needed.
32
+ def update_hostgroup_list
33
+ old_role_hostgroups_arr = deployment_role_hostgroups.to_a
34
+ layout.layout_roles.each do |layout_role|
35
+ role_hostgroup = deployment_role_hostgroups.where(:role_id=>layout_role.role).first_or_initialize do |drh|
36
+ drh.hostgroup = Hostgroup.nest(layout_role.role.name, hostgroup)
37
+ end
38
+
39
+ role_hostgroup.hostgroup.add_puppetclasses_from_resource(layout_role.role)
40
+ role_hostgroup.hostgroup.save!
41
+
42
+ role_hostgroup.deploy_order = layout_role.deploy_order
43
+ role_hostgroup.save!
44
+
45
+ old_role_hostgroups_arr.delete(role_hostgroup)
46
+ end
47
+ # delete any prior mappings that remain
48
+ old_role_hostgroups_arr.each do |role_hostgroup|
49
+ role_hostgroup.hostgroup.destroy
50
+ end
51
+ end
52
+
53
+ private
54
+ def update_hostgroup_name
55
+ hostgroup.name = self.name
56
+ hostgroup.save!
57
+ end
58
+
59
+
60
+ end
61
+ end
@@ -0,0 +1,18 @@
1
+ module Staypuft
2
+ class DeploymentRoleHostgroup < ActiveRecord::Base
3
+ attr_accessible :deployment, :deployment_id, :hostgroup, :hostgroup_id, :role, :role_id, :deploy_order
4
+
5
+ belongs_to :deployment
6
+ belongs_to :hostgroup
7
+ belongs_to :role
8
+
9
+ validates :deployment, :presence => true
10
+ validates :role, :presence => true
11
+ validates :role_id, :uniqueness => {:scope => :deployment_id}
12
+ validates :hostgroup, :presence => true
13
+ validates :hostgroup_id, :uniqueness => true
14
+
15
+ validates :deploy_order, :presence => true
16
+
17
+ end
18
+ end
@@ -0,0 +1,13 @@
1
+ module Staypuft
2
+ class Layout < ActiveRecord::Base
3
+ has_many :deployments, :dependent => :destroy
4
+
5
+ has_many :layout_roles, :dependent => :destroy, :order => "staypuft_layout_roles.deploy_order ASC"
6
+ has_many :roles, :through => :layout_roles, :order => "staypuft_layout_roles.deploy_order ASC"
7
+
8
+ attr_accessible :description, :name, :networking
9
+
10
+ validates :name, :presence => true, :uniqueness => {:scope => :networking}
11
+ validates :networking, :presence => true, :inclusion => {:in =>['nova', 'neutron']}
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module Staypuft
2
+ class LayoutRole < ActiveRecord::Base
3
+ attr_accessible :layout, :layout_id, :role, :role_id, :deploy_order
4
+
5
+ belongs_to :layout
6
+ belongs_to :role
7
+
8
+ validates :layout, :presence => true
9
+ validates :role, :presence => true
10
+ validates :role_id, :uniqueness => {:scope => :layout_id}
11
+ validates :deploy_order, :presence => true, :uniqueness => {:scope => :layout_id}
12
+
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ module Staypuft
2
+ class Role < ActiveRecord::Base
3
+ has_many :layout_roles, :dependent => :destroy
4
+ has_many :layouts, :through => :layout_roles
5
+
6
+ has_many :role_classes, :dependent => :destroy
7
+ has_many :puppetclasses, :through => :role_classes
8
+
9
+ has_many :deployment_role_hostgroups, :dependent => :destroy
10
+ has_many :hostgroups, :through => :deployment_role_hostgroups
11
+ has_many :deployments, :through => :deployment_role_hostgroups
12
+
13
+ has_many :role_services, :dependent => :destroy
14
+ has_many :services, :through => :role_services
15
+
16
+ attr_accessible :description, :max_hosts, :min_hosts, :name
17
+
18
+ validates :name, :presence => true, :uniqueness => true
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ module Staypuft
2
+ class RoleClass < ActiveRecord::Base
3
+ attr_accessible :role_id, :role, :puppetclass_id, :puppetclass
4
+
5
+ belongs_to :role
6
+ belongs_to :puppetclass
7
+
8
+ validates :role, :presence => true
9
+ validates :puppetclass, :presence => true
10
+ validates :puppetclass_id, :uniqueness => {:scope => :role_id}
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Staypuft
2
+ class RoleService < ActiveRecord::Base
3
+ attr_accessible :service, :service_id, :role, :role_id
4
+
5
+ belongs_to :service
6
+ belongs_to :role
7
+
8
+ validates :service, :presence => true
9
+ validates :role, :presence => true
10
+ validates :role_id, :uniqueness => {:scope => :service_id}
11
+
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Staypuft
2
+ class Service < ActiveRecord::Base
3
+ has_many :role_services, :dependent => :destroy
4
+ has_many :roles, :through => :role_services
5
+
6
+ has_many :service_classes, :dependent => :destroy
7
+ has_many :puppetclasses, :through => :service_classes
8
+
9
+ attr_accessible :description, :name
10
+
11
+ validates :name, :presence => true, :uniqueness => true
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module Staypuft
2
+ class ServiceClass < ActiveRecord::Base
3
+ attr_accessible :service_id, :service, :puppetclass_id, :puppetclass
4
+
5
+ belongs_to :service
6
+ belongs_to :puppetclass
7
+
8
+ validates :service, :presence => true
9
+ validates :puppetclass, :presence => true
10
+ validates :puppetclass_id, :uniqueness => {:scope => :service_id}
11
+
12
+ end
13
+ end
@@ -0,0 +1,2 @@
1
+ <% title _("New OpenStack Deployment") %>
2
+ <%= yield %>
@@ -0,0 +1,54 @@
1
+ <%= render :layout => 'title' do %>
2
+ <%= form_for(@deployment, :url => wizard_path, :method => 'PUT') do |f| %>
3
+ <%= base_errors_for @deployment %>
4
+
5
+ <div class="wizard-container">
6
+ <%= deployment_wizard 1 %>
7
+ </div>
8
+ <%= text_f f, :name %><br />
9
+ <%= textarea_f f, :description, :rows => 3 %><br />
10
+
11
+ <div class="row">
12
+ <div class="clearfix">
13
+ <div class="form-group">
14
+ <label class="col-md-2 control-label" for="layout_id"><%= _("Deployment Layout") %></label>
15
+ <div class="col-md-4">
16
+ <% @layouts.each do |layout| %>
17
+ <%= radio_button_f_non_inline(f, :layout_id, :checked => layout.id == @deployment.layout_id,:value=>layout.id, :text=> "#{layout.name}, #{layout.networking.capitalize} " + _("Networking")) %>
18
+ <% end %>
19
+ </div>
20
+ </div>
21
+ </div>
22
+ </div>
23
+
24
+ <!-- <div class="row">
25
+ <%= f.label :services_password, _("Services Password"), :class => "col-md-2 control-label" %><br />
26
+ <div class="row">
27
+ <div class="col-md-8">
28
+ <%= f.radio_button :services_password, false, :checked => true %>
29
+ <%= f.label :services_password, _("Use single password for all services"), :value => "single_password" %><br />
30
+ <div class="row">
31
+ <%= f.label :password, _("Password*"), :class=>"col-md-3 control-label"%>
32
+ <%= f.password_field :password, :class=>"col-md-5" %>
33
+ </div><br />
34
+ <div class="row">
35
+ <%= f.label :confirm_password, _("Confirm Password*"), :class=>"col-md-3 control-label" %>
36
+ <%= f.password_field :confirm_password, :class=>"col-md-5" %>
37
+ </div><br />
38
+ <%= f.radio_button :services_password, false, :checked => false %>
39
+ <%= f.label :services_password, _("Generate random passwords for all services"), :value => "random_password" %>
40
+ </div>
41
+ </div>
42
+ </div>
43
+ -->
44
+ <div class="form_actions">
45
+ <%= link_to _("Cancel"), deployment_path(@deployment), :method => :delete,
46
+ :confirm => _("This will clear whole deployment configuration. Are you sure?"),
47
+ :class => "btn btn-danger" %>
48
+ <%= button_tag(:type => 'submit', :class => "btn btn-primary pull-right") do %>
49
+ <%= _("Next") %>
50
+ <span class="glyphicon glyphicon-chevron-right"></span>
51
+ <% end %>
52
+ </div>
53
+ <% end %>
54
+ <% end %>
@@ -0,0 +1,42 @@
1
+ <%= render :layout => 'title' do %>
2
+ <%= form_for(@deployment, :url => wizard_path, :method => 'PUT') do |f| %>
3
+ <%= base_errors_for @deployment %>
4
+
5
+ <%= deployment_wizard 3 %>
6
+ <div class="form-group tabbed_side_nav_form row">
7
+ <ul class="nav nav-pills nav-stacked col-md-3" data-tabs="pills">
8
+ <h3><%= _("Services") %></h3>
9
+ <% @services.each_with_index do |service, i| %>
10
+ <li class="<%= 'active' if i == 0 %>">
11
+ <a href="#<%= service.name.parameterize.underscore %>" data-toggle="tab">
12
+ <%= service.name %>
13
+ </a>
14
+ </li>
15
+ <% end %>
16
+ </ul>
17
+
18
+ <div class="tab-content col-md-9">
19
+ <% @services.each_with_index do |service, i| %>
20
+ <div class="tab-pane <%= 'active' if i == 0 %>" id="<%= service.name.parameterize.underscore %>">
21
+ <h3><%= "#{service.name} " + _("Service Configuration") %></h3>
22
+ <%= text_f f, :name %><br />
23
+ <%= text_f f, :description %><br />
24
+ </div>
25
+ <% end %>
26
+ </div>
27
+ </div>
28
+
29
+ <div class="form_actions">
30
+ <a class="btn btn-default" href="<%= previous_wizard_path %>">
31
+ <span class="glyphicon glyphicon-chevron-left"></span>
32
+ <%= _("Back") %>
33
+ </a>
34
+ <%= link_to _("Cancel"), deployment_path(@deployment), :method => :delete,
35
+ :confirm => _("This will clear whole deployment configuration. Are you sure?"),
36
+ :class => "btn btn-danger" %>
37
+ <%= button_tag(:type => 'submit', :class => "btn btn-primary pull-right") do %>
38
+ <%= _("Submit") %>
39
+ <% end %>
40
+ </div>
41
+ <% end %>
42
+ <% end %>