stork 0.1.0.pre

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.
Files changed (103) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +10 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +75 -0
  8. data/LICENSE +201 -0
  9. data/README.md +61 -0
  10. data/Rakefile +25 -0
  11. data/bin/stork +97 -0
  12. data/bin/storkctl +62 -0
  13. data/lib/stork/builder.rb +104 -0
  14. data/lib/stork/client/plugins/host_install.rb +19 -0
  15. data/lib/stork/client/plugins/host_list.rb +12 -0
  16. data/lib/stork/client/plugins/host_localboot.rb +19 -0
  17. data/lib/stork/client/plugins/host_show.rb +19 -0
  18. data/lib/stork/collection/base.rb +45 -0
  19. data/lib/stork/collection/chefs.rb +6 -0
  20. data/lib/stork/collection/distros.rb +6 -0
  21. data/lib/stork/collection/hosts.rb +6 -0
  22. data/lib/stork/collection/layouts.rb +6 -0
  23. data/lib/stork/collection/networks.rb +6 -0
  24. data/lib/stork/collection/snippets.rb +6 -0
  25. data/lib/stork/collection/templates.rb +6 -0
  26. data/lib/stork/collections.rb +38 -0
  27. data/lib/stork/configuration.rb +98 -0
  28. data/lib/stork/deploy/command.rb +59 -0
  29. data/lib/stork/deploy/install_script.rb +39 -0
  30. data/lib/stork/deploy/kickstart_binding.rb +222 -0
  31. data/lib/stork/deploy/section.rb +30 -0
  32. data/lib/stork/deploy/snippet_binding.rb +49 -0
  33. data/lib/stork/plugin.rb +54 -0
  34. data/lib/stork/pxe.rb +70 -0
  35. data/lib/stork/resource/base.rb +42 -0
  36. data/lib/stork/resource/chef.rb +81 -0
  37. data/lib/stork/resource/delegator.rb +50 -0
  38. data/lib/stork/resource/distro.rb +30 -0
  39. data/lib/stork/resource/firewall.rb +47 -0
  40. data/lib/stork/resource/host.rb +202 -0
  41. data/lib/stork/resource/interface.rb +125 -0
  42. data/lib/stork/resource/layout.rb +50 -0
  43. data/lib/stork/resource/logical_volume.rb +49 -0
  44. data/lib/stork/resource/network.rb +36 -0
  45. data/lib/stork/resource/partition.rb +47 -0
  46. data/lib/stork/resource/password.rb +26 -0
  47. data/lib/stork/resource/repo.rb +29 -0
  48. data/lib/stork/resource/snippet.rb +20 -0
  49. data/lib/stork/resource/template.rb +24 -0
  50. data/lib/stork/resource/timezone.rb +31 -0
  51. data/lib/stork/resource/volume_group.rb +31 -0
  52. data/lib/stork/resources.rb +17 -0
  53. data/lib/stork/server/application.rb +127 -0
  54. data/lib/stork/server/control.rb +38 -0
  55. data/lib/stork/version.rb +4 -0
  56. data/lib/stork.rb +30 -0
  57. data/specs/builder_spec.rb +14 -0
  58. data/specs/collections_spec.rb +72 -0
  59. data/specs/configuration_spec.rb +151 -0
  60. data/specs/keys/snakeoil-root.pem +27 -0
  61. data/specs/keys/snakeoil-validation.pem +27 -0
  62. data/specs/kickstart_spec.rb +36 -0
  63. data/specs/pxe_spec.rb +57 -0
  64. data/specs/resource_chef_spec.rb +122 -0
  65. data/specs/resource_distro_spec.rb +38 -0
  66. data/specs/resource_firewall_spec.rb +71 -0
  67. data/specs/resource_host_spec.rb +323 -0
  68. data/specs/resource_interface_spec.rb +158 -0
  69. data/specs/resource_layout_spec.rb +78 -0
  70. data/specs/resource_logical_volume_spec.rb +44 -0
  71. data/specs/resource_network_spec.rb +45 -0
  72. data/specs/resource_partition_spec.rb +51 -0
  73. data/specs/resource_password_spec.rb +10 -0
  74. data/specs/resource_repo_spec.rb +43 -0
  75. data/specs/resource_snippet_spec.rb +10 -0
  76. data/specs/resource_template_spec.rb +5 -0
  77. data/specs/resource_timezone_spec.rb +5 -0
  78. data/specs/resource_volume_group_spec.rb +23 -0
  79. data/specs/scripts/kssetup.sh +24 -0
  80. data/specs/scripts/ksvalidate.sh +21 -0
  81. data/specs/server_spec.rb +84 -0
  82. data/specs/spec_helper.rb +33 -0
  83. data/specs/stork/authorized_keys +1 -0
  84. data/specs/stork/bundles/chefs/default.rb +9 -0
  85. data/specs/stork/bundles/distros/centos.rb +5 -0
  86. data/specs/stork/bundles/hosts/example.org.rb +66 -0
  87. data/specs/stork/bundles/layouts/home.rb +33 -0
  88. data/specs/stork/bundles/networks/local.rb +6 -0
  89. data/specs/stork/bundles/networks/org.rb +7 -0
  90. data/specs/stork/bundles/snippets/authorized-keys.erb +10 -0
  91. data/specs/stork/bundles/snippets/chef-bootstrap.erb +104 -0
  92. data/specs/stork/bundles/snippets/chef-reconfigure.erb +22 -0
  93. data/specs/stork/bundles/snippets/etc-hosts.erb +6 -0
  94. data/specs/stork/bundles/snippets/network-config.erb +7 -0
  95. data/specs/stork/bundles/snippets/noop.erb +1 -0
  96. data/specs/stork/bundles/snippets/notify.erb +2 -0
  97. data/specs/stork/bundles/snippets/ntp.erb +2 -0
  98. data/specs/stork/bundles/snippets/resolv-conf.erb +6 -0
  99. data/specs/stork/bundles/snippets/setup.erb +1 -0
  100. data/specs/stork/bundles/templates/default.ks.erb +25 -0
  101. data/specs/stork/config.rb +11 -0
  102. data/stork.gemspec +35 -0
  103. metadata +329 -0
@@ -0,0 +1,125 @@
1
+ module Stork
2
+ module Resource
3
+ class Interface < Base
4
+ attr_accessor :ethtool
5
+ attr_accessor :ip
6
+ attr_accessor :mtu
7
+ attr_accessor :bootproto
8
+ attr_accessor :onboot
9
+ attr_accessor :ipv4
10
+ attr_accessor :ipv6
11
+ attr_accessor :dns
12
+ attr_accessor :defroute
13
+ attr_accessor :network
14
+
15
+ def setup
16
+ @network = Network.new
17
+ @bootproto = :dhcp
18
+ @ip = nil
19
+ @mtu = nil
20
+ @onboot = true
21
+ @ipv4 = true
22
+ @ipv6 = false
23
+ @defroute = true
24
+ @ethtool = nil
25
+ end
26
+
27
+ def validate!
28
+
29
+ end
30
+
31
+ def netmask
32
+ network.netmask
33
+ end
34
+
35
+ def gateway
36
+ network.gateway
37
+ end
38
+
39
+ def nameservers
40
+ network.nameservers
41
+ end
42
+
43
+ def search_paths
44
+ network.search_paths
45
+ end
46
+
47
+ def noipv4
48
+ !ipv4
49
+ end
50
+
51
+ def noipv6
52
+ !ipv6
53
+ end
54
+
55
+ def nodns
56
+ !dns
57
+ end
58
+
59
+ def nodefroute
60
+ !defroute
61
+ end
62
+
63
+ def static?
64
+ @bootproto == :static
65
+ end
66
+
67
+ def hashify
68
+ {
69
+ 'ip' => ip,
70
+ 'bootproto' => bootproto,
71
+ 'netmask' => netmask,
72
+ 'gateway' => gateway,
73
+ 'nameservers' => nameservers,
74
+ 'search_paths' => search_paths
75
+ }
76
+ end
77
+
78
+ alias_method :device, :name
79
+
80
+ class InterfaceDelegator < Stork::Resource::Delegator
81
+ flag :onboot
82
+ flag :ipv4
83
+ flag :ipv6
84
+ flag :dns
85
+ flag :defroute
86
+
87
+ def ethtool(ethtool)
88
+ delegated.ethtool = ethtool
89
+ end
90
+
91
+ def ip(ip)
92
+ delegated.ip = ip
93
+ end
94
+
95
+ def mtu(mtu)
96
+ delegated.mtu = mtu
97
+ end
98
+
99
+ def bootproto(bootproto)
100
+ delegated.bootproto = bootproto
101
+ end
102
+
103
+ def network(network)
104
+ delegated.network = get_collection_item(:network, network)
105
+ end
106
+
107
+ def netmask(netmask)
108
+ delegated.network.netmask = netmask
109
+ end
110
+
111
+ def gateway(gateway)
112
+ delegated.network.gateway = gateway
113
+ end
114
+
115
+ def nameserver(nameserver)
116
+ delegated.network.nameservers << nameserver
117
+ end
118
+
119
+ def search_path(search_path)
120
+ delegated.network.search_paths << search_path
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,50 @@
1
+ module Stork
2
+ module Resource
3
+ class Layout < Base
4
+ attr_accessor :zerombr
5
+ attr_accessor :clearpart
6
+ attr_accessor :partitions
7
+ attr_accessor :volume_groups
8
+ # attr_accessor :raid_groups
9
+
10
+ def setup
11
+ @zerombr = false
12
+ @clearpart = false
13
+ @partitions = Array.new
14
+ @volume_groups = Array.new
15
+ end
16
+
17
+ def validate!
18
+ if partitions.empty?
19
+ fail SyntaxError, 'You must supply a partition block'
20
+ end
21
+ end
22
+
23
+ def hashify
24
+ {
25
+ 'partitions' => partitions.map{|p| p.hashify},
26
+ 'volume_groups' => volume_groups.map{|v| v.hashify}
27
+ }
28
+ end
29
+
30
+ class LayoutDelegator < Stork::Resource::Delegator
31
+ flag :zerombr
32
+ flag :clearpart
33
+
34
+ def partition(name, options = {}, &block)
35
+ fail SyntaxError, 'You must supply a block to partition' unless block_given?
36
+ @delegated.partitions << Partition.build(name, options, &block)
37
+ end
38
+
39
+ alias_method :part, :partition
40
+
41
+ def volume_group(name, options = {}, &block)
42
+ fail SyntaxError, 'You must supply a block to volume_group' unless block_given?
43
+ @delegated.volume_groups << VolumeGroup.build(name, options, &block)
44
+ end
45
+
46
+ alias_method :volgroup, :volume_group
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,49 @@
1
+ module Stork
2
+ module Resource
3
+ class LogicalVolume < Base
4
+ attr_accessor :path
5
+ attr_accessor :size
6
+ attr_accessor :type
7
+ attr_accessor :primary
8
+ attr_accessor :grow
9
+ attr_accessor :recommended
10
+
11
+ def setup
12
+ @size = 1
13
+ @type = 'ext4'
14
+ @grow = false
15
+ @recommended = true
16
+ @path = '/'
17
+ end
18
+
19
+ def hashify
20
+ {
21
+ 'path' => path,
22
+ 'size' => size,
23
+ 'type' => type,
24
+ 'primary' => primary,
25
+ 'grow' => grow,
26
+ 'recommended' => recommended
27
+ }
28
+ end
29
+
30
+ class LogicalVolumeDelegator < Stork::Resource::Delegator
31
+ flag :grow
32
+ flag :recommended
33
+
34
+ def path(path)
35
+ delegated.path = path
36
+ end
37
+
38
+ def size(size)
39
+ delegated.size = size
40
+ delegated.recommended = false
41
+ end
42
+
43
+ def type(type)
44
+ delegated.type = type
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,36 @@
1
+ module Stork
2
+ module Resource
3
+ class Network < Base
4
+ attr_accessor :netmask
5
+ attr_accessor :gateway
6
+ attr_accessor :nameservers
7
+ attr_accessor :search_paths
8
+
9
+ def setup
10
+ @netmask = "255.255.255.0"
11
+ @gateway = nil
12
+ @nameservers = Array.new
13
+ @search_paths = Array.new
14
+ end
15
+
16
+ class NetworkDelegator < Stork::Resource::Delegator
17
+ def netmask(netmask)
18
+ delegated.netmask = netmask
19
+ end
20
+
21
+ def gateway(gateway)
22
+ delegated.gateway = gateway
23
+ end
24
+
25
+ def nameserver(nameserver)
26
+ delegated.nameservers << nameserver
27
+ end
28
+
29
+ def search_path(search_path)
30
+ delegated.search_paths << search_path
31
+ end
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,47 @@
1
+ module Stork
2
+ module Resource
3
+ class Partition < Base
4
+ attr_accessor :size
5
+ attr_accessor :type
6
+ attr_accessor :primary
7
+ attr_accessor :grow
8
+ attr_accessor :recommended
9
+
10
+ def setup
11
+ @size = 1
12
+ @type = 'ext4'
13
+ @grow = false
14
+ @primary = false
15
+ @recommended = false
16
+ end
17
+
18
+ def hashify
19
+ {
20
+ 'path' => path,
21
+ 'size' => size,
22
+ 'type' => type,
23
+ 'primary' => primary,
24
+ 'grow' => grow,
25
+ 'recommended' => recommended
26
+ }
27
+ end
28
+
29
+ alias_method :path, :name
30
+
31
+ class PartitionDelegator < Stork::Resource::Delegator
32
+ flag :primary
33
+ flag :grow
34
+ flag :recommended
35
+
36
+ def size(size)
37
+ delegated.size = size
38
+ delegated.recommended = false
39
+ end
40
+
41
+ def type(type)
42
+ delegated.type = type
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,26 @@
1
+ module Stork
2
+ module Resource
3
+ class Password
4
+ def random_encrypted_password
5
+ salt = rand(36**8).to_s(36)
6
+ random_password.crypt('$6$' + salt)
7
+ end
8
+
9
+ def random_password
10
+ SecureRandom.urlsafe_base64(40)
11
+ end
12
+
13
+ def value
14
+ random_encrypted_password
15
+ end
16
+
17
+ def locked?
18
+ false
19
+ end
20
+
21
+ def encrypted
22
+ true
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ module Stork
2
+ module Resource
3
+ class Repo < Base
4
+ attr_accessor :baseurl
5
+ attr_accessor :mirrorlist
6
+
7
+ def setup
8
+ @baseurl = options.key?(:baseurl) ? options[:baseurl] : nil
9
+ @mirrorlist = options.key?(:mirrorlist) ? options[:mirrorlist] : nil
10
+ end
11
+
12
+ def validate!
13
+ unless baseurl || mirrorlist
14
+ fail SyntaxError, 'One of baseurl or mirrorlist must be specified.'
15
+ end
16
+
17
+ if baseurl && mirrorlist
18
+ fail SyntaxError, 'You may use only baseurl or mirrorlist but not both.'
19
+ end
20
+ end
21
+
22
+ def is_local?
23
+ !(baseurl && mirrorlist)
24
+ end
25
+
26
+ class RepoDelegator < Stork::Resource::Delegator ; end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,20 @@
1
+ module Stork
2
+ module Resource
3
+ class Snippet
4
+ attr_reader :name
5
+ attr_reader :content
6
+
7
+ def initialize(path)
8
+ @name = File.basename(path, '.erb')
9
+ @content = read_content(path)
10
+ end
11
+
12
+ alias_method :id, :name
13
+
14
+ private
15
+ def read_content(path)
16
+ File.read(path)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module Stork
2
+ module Resource
3
+ class Template
4
+ attr_reader :name
5
+ attr_reader :content
6
+
7
+ def initialize(path)
8
+ @name = File.basename(path, '.ks.erb')
9
+ @content = read_content(path)
10
+ end
11
+
12
+ def hashify
13
+ {'name' => name}
14
+ end
15
+
16
+ alias_method :id, :name
17
+
18
+ private
19
+ def read_content(path)
20
+ File.read(path)
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,31 @@
1
+ module Stork
2
+ module Resource
3
+ class Timezone < Base
4
+ attr_accessor :utc
5
+ attr_accessor :ntp
6
+ attr_accessor :ntpservers
7
+
8
+ def setup
9
+ @utc = false
10
+ @ntp = true
11
+ @ntpservers = %w(
12
+ 0.pool.ntp.org
13
+ 1.pool.ntp.org
14
+ 2.pool.ntp.org
15
+ 3.pool.ntp.org
16
+ )
17
+ end
18
+
19
+ alias_method :zone, :name
20
+
21
+ class TimezoneDelegator < Stork::Resource::Delegator
22
+ flag :utc
23
+ flag :ntp
24
+
25
+ def ntpserver(ntpserver)
26
+ delegated.ntpservers << ntpserver
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,31 @@
1
+ module Stork
2
+ module Resource
3
+ class VolumeGroup < Base
4
+ attr_reader :name
5
+ attr_accessor :partition
6
+ attr_accessor :logical_volumes
7
+
8
+ def setup
9
+ @partition = options.key?(:part) ? options[:part] : nil
10
+ @logical_volumes = Array.new
11
+ end
12
+
13
+ def hashify
14
+ {
15
+ 'partition' => partition,
16
+ 'logical_volumes' => logical_volumes.map{|l| l.hashify}
17
+ }
18
+ end
19
+
20
+ class VolumeGroupDelegator < Stork::Resource::Delegator
21
+ def partition(partition)
22
+
23
+ end
24
+
25
+ def logical_volume(name, options = {}, &block)
26
+ @delegated.logical_volumes << LogicalVolume.build(name, options, &block)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,17 @@
1
+ require 'stork/resource/delegator'
2
+ require 'stork/resource/base'
3
+ require 'stork/resource/chef'
4
+ require 'stork/resource/distro'
5
+ require 'stork/resource/partition'
6
+ require 'stork/resource/logical_volume'
7
+ require 'stork/resource/volume_group'
8
+ require 'stork/resource/layout'
9
+ require 'stork/resource/network'
10
+ require 'stork/resource/interface'
11
+ require 'stork/resource/firewall'
12
+ require 'stork/resource/password'
13
+ require 'stork/resource/timezone'
14
+ require 'stork/resource/snippet'
15
+ require 'stork/resource/template'
16
+ require 'stork/resource/repo'
17
+ require 'stork/resource/host'
@@ -0,0 +1,127 @@
1
+ require 'sinatra'
2
+
3
+ module Stork
4
+ module Server
5
+ class Application < Sinatra::Base
6
+ configure do
7
+ enable :logging
8
+ mime_type :plain, 'text/plain'
9
+ mime_type :json, 'application/json'
10
+ end
11
+
12
+ before do
13
+ logger.datetime_format = '%Y/%m/%d @ %H:%M:%S '
14
+ logger.level = Logger::INFO
15
+ end
16
+
17
+ get '/' do
18
+ info 'GET /'
19
+ json_halt 200, 200, "Stork Version #{VERSION} - #{CODENAME}"
20
+ end
21
+
22
+ get '/api/v1/hosts' do
23
+ h = {'hosts' => hosts.hashify}
24
+ json_halt_ok_with_content(h.to_json)
25
+ end
26
+
27
+ get '/api/v1/host/:host' do |host|
28
+ h = hosts.get(host)
29
+ json_halt_ok_with_content(h.hashify.to_json)
30
+ end
31
+
32
+ get '/host/:host' do |host|
33
+ info "#{host} requested kickstart"
34
+
35
+ h = hosts.get(host)
36
+
37
+ if h
38
+ # hmm, should the host deploy?
39
+ ks = Stork::Deploy::InstallScript.new(h) # we will be passing the type in shortly
40
+ content_type :plain
41
+ ks.render
42
+ else
43
+ json_halt_not_found
44
+ end
45
+ end
46
+
47
+ get '/host/:host/installed' do |host|
48
+ info "#{host} has notified completed install"
49
+ h = hosts.get(host)
50
+
51
+ if h
52
+ set_localboot(h)
53
+ json_halt_ok
54
+ else
55
+ json_halt_not_found
56
+ end
57
+ end
58
+
59
+ get '/host/:host/install' do |host|
60
+ info "install requested for #{host}"
61
+ h = hosts.get(host)
62
+
63
+ if h
64
+ set_install(h)
65
+ json_halt_ok
66
+ else
67
+ json_halt_not_found
68
+ end
69
+ end
70
+
71
+ not_found do
72
+ json_halt_not_found
73
+ end
74
+
75
+ helpers do
76
+ def hosts
77
+ @hosts ||= settings.collection.hosts
78
+ end
79
+
80
+ def config
81
+ @config ||= settings.config
82
+ end
83
+
84
+ def set_localboot(host)
85
+ pxe(host).localboot
86
+ end
87
+
88
+ def set_install(host)
89
+ pxe(host).install
90
+ end
91
+
92
+ def pxe(host)
93
+ Stork::PXE.new(host, host.stork, config.port)
94
+ end
95
+
96
+ def info(msg)
97
+ logger.info "[#{request.ip}] INFO: #{msg}"
98
+ end
99
+
100
+ def json_halt(request_status, op_status, message)
101
+ content_type :json
102
+ halt request_status, { 'Content-Type' => 'application/json' }, "{ \"status\":\"#{op_status}\", \"message\": \"#{message}\" }"
103
+ end
104
+
105
+ def json_halt_ok
106
+ content_type :json
107
+ json_halt 200, 200, 'OK'
108
+ end
109
+
110
+ def json_halt_ok_with_content(content)
111
+ content_type :json
112
+ halt 200, { 'Content-Type' => 'application/json' }, content
113
+ end
114
+
115
+ def json_halt_internal_error
116
+ content_type :json
117
+ json_halt 500, 500, 'Internal error'
118
+ end
119
+
120
+ def json_halt_not_found
121
+ content_type :json
122
+ json_halt 404, 404, 'not found'
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,38 @@
1
+ require 'sinatra'
2
+ require 'json'
3
+ require 'rack'
4
+ require 'thin'
5
+
6
+ module Stork
7
+ module Server
8
+ class Control
9
+ def self.start(configuration, collection)
10
+ puts "Starting stork server on port #{configuration.port}."
11
+ app = Stork::Server::Application
12
+ app.set :collection, collection
13
+ app.set :config, configuration
14
+
15
+ @thin = Thin::Server.new(configuration.bind, configuration.port, app)
16
+ @thin.tag = "Stork #{VERSION}"
17
+ unless ENV['RACK_ENV'] == 'test'
18
+ @thin.pid_file = configuration.pid_file
19
+ @thin.log_file = configuration.log_file
20
+ @thin.daemonize
21
+ else
22
+ puts '!!! Running in test mode'
23
+ end
24
+ @thin.start
25
+ end
26
+
27
+ def self.stop(configuration, collection)
28
+ puts 'Stoping the stork server.'
29
+ Thin::Server.kill(configuration.pid_file)
30
+ end
31
+
32
+ def self.restart(configuration, collection)
33
+ stop(configuration, collection)
34
+ start(configuration, collection)
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,4 @@
1
+ module Stork
2
+ VERSION = '0.1.0.pre'
3
+ CODENAME = 'Psychotic Hamster'
4
+ end
data/lib/stork.rb ADDED
@@ -0,0 +1,30 @@
1
+ require 'erb'
2
+ require 'json'
3
+ require 'securerandom'
4
+
5
+ require 'stork/version'
6
+ require 'stork/configuration'
7
+ require 'stork/collections'
8
+ require 'stork/resources'
9
+
10
+ require 'stork/builder'
11
+
12
+ require 'stork/deploy/command'
13
+ require 'stork/deploy/section'
14
+ require 'stork/deploy/snippet_binding'
15
+ require 'stork/deploy/kickstart_binding'
16
+ require 'stork/deploy/install_script'
17
+
18
+ require 'stork/pxe'
19
+
20
+ require 'stork/server/application'
21
+ require 'stork/server/control'
22
+
23
+ require 'stork/plugin'
24
+ Dir[File.join('./lib/stork/client/plugins', '*.rb')].each do |plugin|
25
+ require plugin
26
+
27
+ Stork.add_plugin(plugin)
28
+ end
29
+
30
+ # Also make sure we allow a .stork/plugins dir