ruby_yacht 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile.lock +1 -1
- data/doc/TODO.md +16 -6
- data/doc/configuration_sample.rb +8 -9
- data/lib/ruby_yacht/dsl/app.rb +29 -1
- data/lib/ruby_yacht/dsl/app_type.rb +112 -0
- data/lib/ruby_yacht/dsl/configuration.rb +163 -2
- data/lib/ruby_yacht/dsl/dsl.rb +51 -9
- data/lib/ruby_yacht/dsl/hook.rb +105 -0
- data/lib/ruby_yacht/dsl/project.rb +17 -21
- data/lib/ruby_yacht/dsl.rb +2 -0
- data/lib/ruby_yacht/images/app/Dockerfile.erb +20 -13
- data/lib/ruby_yacht/images/app/before_startup.bash.erb +8 -0
- data/lib/ruby_yacht/images/app/checkout.bash +6 -0
- data/lib/ruby_yacht/images/app/startup.bash.erb +5 -0
- data/lib/ruby_yacht/images/app-dependencies/Dockerfile.erb +23 -5
- data/lib/ruby_yacht/images/database/Dockerfile.erb +25 -11
- data/lib/ruby_yacht/images/database/checkout.bash +10 -0
- data/lib/ruby_yacht/images/database/setup.bash +15 -0
- data/lib/ruby_yacht/images/web/Dockerfile.erb +4 -3
- data/lib/ruby_yacht/plugins/rails/scripts/install_gems.rb +3 -0
- data/lib/ruby_yacht/plugins/rails/scripts/load_seeds.rb +34 -0
- data/lib/ruby_yacht/{images/app/startup.rb → plugins/rails/scripts/prepare_rails_for_launch.rb} +2 -8
- data/lib/ruby_yacht/{images/app/update_database_config.rb → plugins/rails/scripts/update_rails_config.rb} +0 -1
- data/lib/ruby_yacht/plugins/rails.rb +40 -0
- data/lib/ruby_yacht/plugins.rb +6 -0
- data/lib/ruby_yacht/runner/build_images.rb +72 -5
- data/lib/ruby_yacht/runner/checkout.rb +1 -1
- data/lib/ruby_yacht.rb +2 -1
- data/ruby_yacht.gemspec +2 -1
- data/spec/docker/Dockerfile +1 -1
- data/spec/dsl/app_spec.rb +34 -0
- data/spec/dsl/app_type_spec.rb +176 -0
- data/spec/dsl/configuration_spec.rb +161 -2
- data/spec/dsl/dsl_spec.rb +3 -3
- data/spec/dsl/hook_spec.rb +111 -0
- data/spec/dsl/project_spec.rb +19 -83
- data/spec/fixtures/app-dependencies-dockerfile-generic +21 -0
- data/spec/fixtures/app-dependencies-dockerfile-generic-with-library-install +28 -0
- data/spec/fixtures/app-dependencies-dockerfile-rails +32 -0
- data/spec/fixtures/database-dockerfile +16 -15
- data/spec/fixtures/database-dockerfile-rails +35 -0
- data/spec/fixtures/database-dockerfile-with-seed-hooks +34 -0
- data/spec/fixtures/hooks/hook1.rb +0 -0
- data/spec/fixtures/hooks/hook2.rb +0 -0
- data/spec/fixtures/mars-before-startup +4 -0
- data/spec/fixtures/mars-before-startup-rails +7 -0
- data/spec/fixtures/mars-before-startup-with-before-startup-hooks +7 -0
- data/spec/fixtures/mars-dockerfile +9 -14
- data/spec/fixtures/mars-dockerfile-rails +33 -0
- data/spec/fixtures/mars-dockerfile-with-after-checkout-hooks +30 -0
- data/spec/fixtures/mars-dockerfile-with-before-startup-hooks +29 -0
- data/spec/fixtures/mars-startup +3 -0
- data/spec/fixtures/mars-startup-rails +3 -0
- data/spec/fixtures/multi-project-web-dockerfile +0 -10
- data/spec/fixtures/web-dockerfile +0 -6
- data/spec/plugins/rails_spec.rb +198 -0
- data/spec/runner/build_images_spec.rb +181 -15
- data/spec/runner/checkout_spec.rb +2 -2
- data/spec/support/test_project.rb +16 -8
- metadata +62 -30
- data/lib/ruby_yacht/images/app/checkout.rb +0 -7
- data/lib/ruby_yacht/images/app-dependencies/install_gems.rb +0 -12
- data/lib/ruby_yacht/images/database/load_seeds.rb +0 -42
- data/lib/ruby_yacht/images/database/setup.rb +0 -19
- data/lib/ruby_yacht/images/database/setup_database.sql.erb +0 -12
- data/spec/fixtures/app-dependencies-dockerfile +0 -25
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8fe86d0666f935e2212841266623b3f2fc4b0fdc
|
4
|
+
data.tar.gz: 5f5c2ed02c41aaf4f9b98dd3fc79e8110a43d2cc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f4ad7a074ec77f4e8cfd1716ea69de349d0180125da4f7964420a1890c157c444a61eb7b06682e5dd672008fd55fdf01c4d037744286af4dd423be57cdccaa12
|
7
|
+
data.tar.gz: efc077fdd18c3485ce9f6ff25ad066c55dea2315324087aaa589a1ee6eb003b6bf0feb82c252ff9d4f96a91d335a0eb4a22d9a68cb341605edd3cc3d507d36f0
|
data/Gemfile.lock
CHANGED
data/doc/TODO.md
CHANGED
@@ -1,10 +1,20 @@
|
|
1
|
+
See the [GitHub Issue Tracker](https://github.com/brownleej/ruby-yacht/issues)
|
2
|
+
for open tickets.
|
3
|
+
|
1
4
|
# General
|
2
5
|
|
3
|
-
* Testing behavior of the scripts that run on the image.
|
4
6
|
* Do more testing with remote databases and non-development environments
|
5
7
|
* Consider whether deploy containers are worth including
|
6
8
|
* Consider whether using the same web server for multiple projects is the best
|
7
9
|
approach
|
10
|
+
* Look into issues with running shell command that has its own command-line
|
11
|
+
flags.
|
12
|
+
|
13
|
+
# Plugins
|
14
|
+
|
15
|
+
* Move more of the hooks to using the include_event helper
|
16
|
+
* Add documentation on plugin API
|
17
|
+
* Supporting shared databases between apps of different types
|
8
18
|
|
9
19
|
# More Command Line Options
|
10
20
|
|
@@ -16,9 +26,9 @@
|
|
16
26
|
|
17
27
|
* Add customizations for installation
|
18
28
|
* Add customization for post-checkout hooks
|
19
|
-
* HTTPS access for apps
|
20
|
-
* Distinguishing whether we should use local or remote connections for other
|
21
|
-
services
|
22
|
-
* Different types of app servers, i.e. non-rails apps
|
23
29
|
* Using one of the apps for the bare domain
|
24
|
-
* Defining custom commands
|
30
|
+
* Defining custom commands
|
31
|
+
* Allowing customization points at different levels, like adding hooks to
|
32
|
+
individual apps
|
33
|
+
* Customizing how we check out the repositories, so that people can use https
|
34
|
+
instead of SSH.
|
data/doc/configuration_sample.rb
CHANGED
@@ -23,6 +23,9 @@ RubyYacht.configure do
|
|
23
23
|
# ~/.ssh/id_rsa into the containers.
|
24
24
|
repository "github.com"
|
25
25
|
|
26
|
+
# The secret key that we use for session information in the Rails apps.
|
27
|
+
rails_secret_key_base 'abc'
|
28
|
+
|
26
29
|
# The configuration for the database the app uses.
|
27
30
|
database do
|
28
31
|
# A database host of localhost tells ruby-yacht to build a database
|
@@ -37,18 +40,15 @@ RubyYacht.configure do
|
|
37
40
|
password "test"
|
38
41
|
end
|
39
42
|
|
40
|
-
|
43
|
+
rails_app :mars do
|
41
44
|
# This app's repository is at github.com/brownleej/mars
|
42
45
|
repository_name 'brownleej/mars'
|
43
46
|
end
|
44
47
|
|
45
|
-
|
48
|
+
rails_app :saturn do
|
46
49
|
# This app's repository is at github.com/brownleej/saturn
|
47
50
|
repository_name 'brownleej/saturn'
|
48
51
|
end
|
49
|
-
|
50
|
-
# The secret key that we use for session information in the Rails apps.
|
51
|
-
secret_key_base 'abc'
|
52
52
|
end
|
53
53
|
|
54
54
|
# This is a second project that runs a different set of apps, with different
|
@@ -57,6 +57,7 @@ RubyYacht.configure do
|
|
57
57
|
system_prefix :jupiter
|
58
58
|
domain "jupiter.docker.local"
|
59
59
|
repository "github.com"
|
60
|
+
rails_secret_key_base 'abc'
|
60
61
|
|
61
62
|
database do
|
62
63
|
# Because this host has a real domain, we will not build a database
|
@@ -71,15 +72,13 @@ RubyYacht.configure do
|
|
71
72
|
password "test"
|
72
73
|
end
|
73
74
|
|
74
|
-
|
75
|
+
rails_app :venus do
|
75
76
|
repository_name 'brownleej/venus'
|
76
77
|
end
|
77
78
|
|
78
|
-
|
79
|
+
rails_app :saturn do
|
79
80
|
repository_name 'brownleej/saturn'
|
80
81
|
end
|
81
|
-
|
82
|
-
secret_key_base 'abc'
|
83
82
|
end
|
84
83
|
end
|
85
84
|
|
data/lib/ruby_yacht/dsl/app.rb
CHANGED
@@ -10,6 +10,12 @@ module RubyYacht
|
|
10
10
|
# To the project's repository domain.
|
11
11
|
attr_accessor :repository_name
|
12
12
|
|
13
|
+
# The type of app this is, which determines what hooks and scripts we run
|
14
|
+
# when building it.
|
15
|
+
#
|
16
|
+
# For instance, this would be `rails` for a Rails app.
|
17
|
+
attr_accessor :app_type
|
18
|
+
|
13
19
|
# The port that the app listens on.
|
14
20
|
attr_accessor :port
|
15
21
|
|
@@ -37,8 +43,10 @@ module RubyYacht
|
|
37
43
|
# ### Parameters
|
38
44
|
#
|
39
45
|
# * *name: String* The name of the app.
|
40
|
-
def initialize(name)
|
46
|
+
def initialize(name, app_type = nil)
|
41
47
|
@name = name.to_sym
|
48
|
+
@app_type = app_type
|
49
|
+
load_custom_attributes
|
42
50
|
end
|
43
51
|
|
44
52
|
add_attribute :name
|
@@ -48,12 +56,32 @@ module RubyYacht
|
|
48
56
|
# You can call `repository_name 'foo/bar'` to set the app's `repository_name`.
|
49
57
|
add_attribute :repository_name
|
50
58
|
|
59
|
+
##
|
60
|
+
# :method: app_type
|
61
|
+
# You can call `app_type :foo` to set the app's `app_type`.
|
62
|
+
add_attribute :app_type
|
63
|
+
|
51
64
|
##
|
52
65
|
# :method: port
|
53
66
|
# You can call `port 3000` to set the app's `port`. It defaults to 8080.
|
54
67
|
add_attribute :port, 8080
|
55
68
|
|
56
69
|
creates_object App
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
# This method checks that all of the required attributes have been set on
|
74
|
+
# the object.
|
75
|
+
#
|
76
|
+
# If they haven't, this will raise an exception.
|
77
|
+
#
|
78
|
+
# It also checks that the app type has been defined in the configuration.
|
79
|
+
def check_required_attributes
|
80
|
+
super
|
81
|
+
unless RubyYacht.configuration.find_app_type(@app_type)
|
82
|
+
raise "App has invalid app type `#{@app_type}`"
|
83
|
+
end
|
84
|
+
end
|
57
85
|
end
|
58
86
|
end
|
59
87
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module RubyYacht
|
2
|
+
# This class represents a type of app that the user can configure.
|
3
|
+
#
|
4
|
+
# An app type corresponds to a major app framework, like Ruby on Rails. App
|
5
|
+
# types are defined by plugins, which also provide the logic for installing
|
6
|
+
# and running the apps.
|
7
|
+
#
|
8
|
+
# You can configure this with RubyYacht::AppType::DSL
|
9
|
+
class AppType
|
10
|
+
# The name of the type.
|
11
|
+
attr_accessor :name
|
12
|
+
|
13
|
+
# The attributes that we define on the project DSL once this app type has
|
14
|
+
# been loaded.
|
15
|
+
#
|
16
|
+
# Each entry will be a hash with a key for `name`, and optionally a key for
|
17
|
+
# `default` and `required`. These values will be given to the
|
18
|
+
# `add_attribute` method in the project DSL.
|
19
|
+
#
|
20
|
+
# The attribute names will be prefixed with the app type's name. For
|
21
|
+
# instance, if the `rails` app type provides an `environment` attribute,
|
22
|
+
# it will be called `rails_environment` on the project's DSL. This prevents
|
23
|
+
# conflicts with attributes from other plugins.
|
24
|
+
attr_accessor :project_attributes
|
25
|
+
|
26
|
+
# The attributes that we define on the app DSL once this app type has
|
27
|
+
# been loaded.
|
28
|
+
#
|
29
|
+
# Each entry will be a hash with a key for `name`, and optionally a key for
|
30
|
+
# `default` and `required`. These values will be given to the
|
31
|
+
# `add_attribute` method in the project DSL.
|
32
|
+
#
|
33
|
+
# The attributes will only be defined on apps with this app type.
|
34
|
+
#
|
35
|
+
# The attribute names will be prefixed with the app type's name. For
|
36
|
+
# instance, if the `rails` app type provides an `environment` attribute,
|
37
|
+
# it will be called `rails_environment` on the app's DSL. This prevents
|
38
|
+
# conflicts with attributes from other plugins.
|
39
|
+
attr_accessor :app_attributes
|
40
|
+
|
41
|
+
# The docker image that we use as the source for the app images.
|
42
|
+
attr_accessor :baseline_image
|
43
|
+
|
44
|
+
# The custom environment variables that we set in the images for this app
|
45
|
+
# type.
|
46
|
+
#
|
47
|
+
# Each entry will be a hash with the following keys:
|
48
|
+
#
|
49
|
+
# * **name: String** The name of the environment variable
|
50
|
+
# * **image: String** The type of image that this is set in (e.g. app
|
51
|
+
# or database).
|
52
|
+
# * **block** A block that will be called inside the Dockerfile
|
53
|
+
# ERB for providing the value of the environment
|
54
|
+
# variable.
|
55
|
+
attr_accessor :environment_variables
|
56
|
+
|
57
|
+
# This class provides a DSL for configuring a RubyYacht::AppType.
|
58
|
+
class DSL
|
59
|
+
include RubyYacht::DSL::Base
|
60
|
+
extend RubyYacht::DSL::Base::ClassMethods
|
61
|
+
|
62
|
+
# This initiailzer creates the app type DSL.
|
63
|
+
#
|
64
|
+
# ### Parameters
|
65
|
+
#
|
66
|
+
# * **name: Symbol** The name of the app type.
|
67
|
+
def initialize(name)
|
68
|
+
@name = name
|
69
|
+
@environment_variables = []
|
70
|
+
load_custom_attributes
|
71
|
+
end
|
72
|
+
|
73
|
+
add_attribute :name
|
74
|
+
|
75
|
+
#
|
76
|
+
# :method: baseline_image
|
77
|
+
# You can call `baseline_image 'ubuntu'` to use ubuntu as the source
|
78
|
+
# image for the app containers for this app type.
|
79
|
+
add_attribute :baseline_image
|
80
|
+
|
81
|
+
#
|
82
|
+
# :method: project_attribute
|
83
|
+
# You can call `project_attribute name: :environment, default: 'staging'`
|
84
|
+
# to add an attribute to the project DSL.
|
85
|
+
add_list :project_attribute
|
86
|
+
|
87
|
+
#
|
88
|
+
# :method: app_attribute
|
89
|
+
# You can call `app_attribute name: :environment, default: 'staging'`
|
90
|
+
# to add an attribute to the app DSL.
|
91
|
+
add_list :app_attribute
|
92
|
+
|
93
|
+
creates_object RubyYacht::AppType, [:name, :baseline_image,
|
94
|
+
:project_attributes, :app_attributes, :environment_variables]
|
95
|
+
|
96
|
+
# This method defines a new environment variable set for this app type.
|
97
|
+
#
|
98
|
+
# ### Parameters
|
99
|
+
#
|
100
|
+
# * **image: Symbol** The type of image this environment variable is set
|
101
|
+
# for.
|
102
|
+
# * **name: String** The name of the environment variable.
|
103
|
+
# * **block** A block for generating the environment variable.
|
104
|
+
# This will have access to the project (as @project)
|
105
|
+
# and the app (as @app) that we are building the
|
106
|
+
# image for.
|
107
|
+
def environment_variable(image, name, &block)
|
108
|
+
@environment_variables << {image: image, name: name, block: block}
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
require_relative 'project'
|
2
|
+
require_relative 'hook'
|
3
|
+
require_relative 'app_type'
|
2
4
|
|
3
5
|
module RubyYacht
|
4
6
|
# This class stores the configuration for the system.
|
@@ -13,16 +15,65 @@ module RubyYacht
|
|
13
15
|
# This method erases all the configuration.
|
14
16
|
def clear
|
15
17
|
@projects = []
|
18
|
+
@hooks = []
|
19
|
+
@app_types = []
|
16
20
|
end
|
17
21
|
|
18
22
|
# The projects that are part of this system.
|
19
23
|
# Each entry is a RubyYacht::Project
|
20
24
|
attr_accessor :projects
|
25
|
+
|
26
|
+
# The hooks to customize the build and run processes.
|
27
|
+
# Each entry is a RubyYacht::Hook
|
28
|
+
attr_accessor :hooks
|
29
|
+
|
30
|
+
# The app types that we can support.
|
31
|
+
# Each entry is a Symbol.
|
32
|
+
attr_accessor :app_types
|
33
|
+
|
34
|
+
# This method pulls up the hooks that we have defined.
|
35
|
+
#
|
36
|
+
# The hooks can be filtered by the attributes on the hook, like `event_type`
|
37
|
+
# and `event_time`.
|
38
|
+
#
|
39
|
+
# ### Parameters
|
40
|
+
#
|
41
|
+
# * **attributes: Hash** The attributes to look for in the returned
|
42
|
+
# hooks.
|
43
|
+
#
|
44
|
+
# ### Returns
|
45
|
+
#
|
46
|
+
# The matching hooks. This will be an Array where each item is a Hook.
|
47
|
+
def fetch_hooks(attributes={})
|
48
|
+
self.hooks.select do |hook|
|
49
|
+
attributes.keys.all? do |key|
|
50
|
+
hook.send(key) == attributes[key]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# This method finds an app type by name.
|
56
|
+
#
|
57
|
+
# ### Parameters
|
58
|
+
#
|
59
|
+
# * **name: Symbol** The name of the app type to return.
|
60
|
+
#
|
61
|
+
# ### Returns
|
62
|
+
#
|
63
|
+
# The RubyYacht::AppType with that name.
|
64
|
+
def find_app_type(name)
|
65
|
+
self.app_types.find { |type| type.name == name }
|
66
|
+
end
|
21
67
|
|
22
68
|
# This method provides a DSL for top-level configuration.
|
23
69
|
class DSL
|
24
70
|
include RubyYacht::DSL::Base
|
25
71
|
extend RubyYacht::DSL::Base::ClassMethods
|
72
|
+
|
73
|
+
# This initializer creates an empty configuration DSL.
|
74
|
+
def initialize
|
75
|
+
self.load_custom_attributes
|
76
|
+
end
|
26
77
|
|
27
78
|
##
|
28
79
|
# :method: project
|
@@ -33,8 +84,109 @@ module RubyYacht
|
|
33
84
|
# which you can use to configure the project, using
|
34
85
|
# RubyYacht::Project::DSL.
|
35
86
|
add_object_list :project, RubyYacht::Project::DSL
|
87
|
+
|
88
|
+
##
|
89
|
+
# :method: hook
|
90
|
+
#
|
91
|
+
# This method adds a hook to the configuration.
|
92
|
+
#
|
93
|
+
# This takes hook's event_time and event_type as its arguments. It also
|
94
|
+
# takes a block which you can use to configure the hook, using
|
95
|
+
# RubyYacht::Hook::DSL.
|
96
|
+
add_object_list :hook, RubyYacht::Hook::DSL
|
97
|
+
|
98
|
+
##
|
99
|
+
# :method: app_type
|
100
|
+
#
|
101
|
+
# This method adds an app type to the configuration.
|
102
|
+
#
|
103
|
+
# This takes type's name as its argument. It also takes a block which you
|
104
|
+
# can use to configure the type, using
|
105
|
+
# RubyYacht::AppType::DSL.
|
106
|
+
add_object_list :app_type, RubyYacht::AppType::DSL
|
107
|
+
|
108
|
+
# The path for files and other resources from configuration hooks.
|
109
|
+
attr_accessor :hook_folder
|
110
|
+
|
111
|
+
# The app type for hooks that we are defining in the current block.
|
112
|
+
attr_accessor :hook_app_type
|
113
|
+
|
114
|
+
# This method sets default attributes for a group of hooks.
|
115
|
+
#
|
116
|
+
# Any hooks that you create in the associated block will have their script
|
117
|
+
# folder and app type specified by the attached properties.
|
118
|
+
#
|
119
|
+
# ### Parameters
|
120
|
+
#
|
121
|
+
# * **folder: String** The full path to the script folder.
|
122
|
+
# * **block** A block for adding the hooks.
|
123
|
+
def add_hooks(options = {}, &block)
|
124
|
+
keys = [:folder, :app_type]
|
125
|
+
old_options = {}
|
126
|
+
keys.each do |key|
|
127
|
+
old_options[key] = self.send("hook_#{key}")
|
128
|
+
self.send("hook_#{key}=", options[key]) if options.has_key?(key)
|
129
|
+
end
|
130
|
+
|
131
|
+
block.call
|
132
|
+
|
133
|
+
keys.each do |key|
|
134
|
+
self.send("hook_#{key}=", old_options[key])
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# This method adds a before hook.
|
139
|
+
#
|
140
|
+
# ### Parameters
|
141
|
+
#
|
142
|
+
# * **event_type: Symbol** The event type for the new hook.
|
143
|
+
# * **block** A block for configuring the hook. You can
|
144
|
+
# call the RubyYacht::Hook::DSL methods in
|
145
|
+
# this block.
|
146
|
+
def before(event_type, &block)
|
147
|
+
add_hook :before, event_type, &block
|
148
|
+
end
|
149
|
+
|
150
|
+
# This method adds an after hook.
|
151
|
+
#
|
152
|
+
# ### Parameters
|
153
|
+
#
|
154
|
+
# * **event_type: Symbol** The event type for the new hook.
|
155
|
+
# * **block** A block for configuring the hook. You can
|
156
|
+
# call the RubyYacht::Hook::DSL methods in
|
157
|
+
# this block.
|
158
|
+
def after(event_type, &block)
|
159
|
+
add_hook :after, event_type, &block
|
160
|
+
end
|
161
|
+
|
162
|
+
# This method adds a during hook.
|
163
|
+
#
|
164
|
+
# This hook will be run while event is happening, and provides the core
|
165
|
+
# logic for the event.
|
166
|
+
#
|
167
|
+
# ### Parameters
|
168
|
+
#
|
169
|
+
# * **event_type: Symbol** The event type for the new hook.
|
170
|
+
# * **block** A block for configuring the hook. You can
|
171
|
+
# call the RubyYacht::Hook::DSL methods in
|
172
|
+
# this block.
|
173
|
+
def during(event_type, &block)
|
174
|
+
add_hook :during, event_type, &block
|
175
|
+
end
|
36
176
|
|
37
|
-
creates_object Configuration
|
177
|
+
creates_object Configuration, %w(projects hooks app_types)
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
def add_hook(event_time, event_type, &block)
|
182
|
+
folder = hook_folder
|
183
|
+
type = hook_app_type
|
184
|
+
hook event_time, event_type do
|
185
|
+
script_folder folder
|
186
|
+
app_type type
|
187
|
+
instance_eval(&block)
|
188
|
+
end
|
189
|
+
end
|
38
190
|
end
|
39
191
|
end
|
40
192
|
|
@@ -47,7 +199,16 @@ module RubyYacht
|
|
47
199
|
# of projects.
|
48
200
|
def self.configure(&block)
|
49
201
|
new_configuration = Configuration::DSL.new.run(block).create_object
|
50
|
-
|
202
|
+
%w(projects hooks).each do |field|
|
203
|
+
self.configuration.send("#{field}=", self.configuration.send(field) + new_configuration.send(field))
|
204
|
+
end
|
205
|
+
|
206
|
+
new_configuration.app_types.each do |type|
|
207
|
+
if self.configuration.app_types.any? { |existing| existing.name == type.name }
|
208
|
+
raise "App type already registered: #{type.name}"
|
209
|
+
end
|
210
|
+
self.configuration.app_types << type
|
211
|
+
end
|
51
212
|
end
|
52
213
|
|
53
214
|
# This method gets the current configuration for the system.
|
data/lib/ruby_yacht/dsl/dsl.rb
CHANGED
@@ -130,8 +130,8 @@ module RubyYacht
|
|
130
130
|
#
|
131
131
|
# * **name: Symbol** The name of the method, which will also be the
|
132
132
|
# name of the attribute.
|
133
|
-
# * **type:
|
134
|
-
#
|
133
|
+
# * **type: Class** The class type that provides the DSL when they
|
134
|
+
# call this method.
|
135
135
|
# * **options: Hash** Other options about the DSL. Right now the only
|
136
136
|
# option is *required*, which indicates whether
|
137
137
|
# they must define this configuraiton.
|
@@ -157,14 +157,17 @@ module RubyYacht
|
|
157
157
|
#
|
158
158
|
# * **name: Symbol** The name of the method. The attribute name will
|
159
159
|
# be this, followed by an "s"
|
160
|
-
# * **type:
|
161
|
-
#
|
160
|
+
# * **type: Class** The class type that provides the DSL when they
|
161
|
+
# call this method.
|
162
162
|
def add_object_list(name, type)
|
163
163
|
add_generic_attribute name, "#{name}s", [], false do |*args, &config_block|
|
164
164
|
variable_name = "@#{name}s"
|
165
165
|
list = instance_variable_get(variable_name)
|
166
166
|
object_config = type.new(*args)
|
167
|
-
|
167
|
+
if config_block
|
168
|
+
object_config.run(config_block)
|
169
|
+
end
|
170
|
+
value = object_config.create_object
|
168
171
|
list << value
|
169
172
|
instance_variable_set(variable_name, list)
|
170
173
|
end
|
@@ -186,6 +189,46 @@ module RubyYacht
|
|
186
189
|
@created_type = type
|
187
190
|
end
|
188
191
|
end
|
192
|
+
|
193
|
+
# This initializer creates a new DSL instance.
|
194
|
+
def initialize
|
195
|
+
load_custom_attributes
|
196
|
+
end
|
197
|
+
|
198
|
+
# This method adds attributes to this DSL instance's singleton DSL, based
|
199
|
+
# on the attributes defined by the app types that have been loaded.
|
200
|
+
def load_custom_attributes
|
201
|
+
full_class = self.class
|
202
|
+
self.singleton_class.instance_eval do
|
203
|
+
@copied_attributes = (full_class.copied_attributes || []).dup
|
204
|
+
@all_attributes = full_class.all_attributes.dup
|
205
|
+
@required_attributes = full_class.required_attributes.dup
|
206
|
+
@default_values = full_class.default_values.dup
|
207
|
+
end
|
208
|
+
|
209
|
+
if self.class.created_type
|
210
|
+
dsl_type = self.class.created_type.name.split('::').last.downcase
|
211
|
+
copied_attributes = self.class.copied_attributes
|
212
|
+
|
213
|
+
RubyYacht.configuration.app_types.each do |app_type|
|
214
|
+
next if @app_type && app_type.name != @app_type
|
215
|
+
attributes = app_type.send("#{dsl_type}_attributes") || [] rescue []
|
216
|
+
attributes.each do |attribute|
|
217
|
+
if attribute.has_key?(:required)
|
218
|
+
required = attribute[:required]
|
219
|
+
else
|
220
|
+
required = true
|
221
|
+
end
|
222
|
+
name = "#{app_type.name}_#{attribute[:name]}"
|
223
|
+
self.singleton_class.add_attribute name, attribute[:default], required
|
224
|
+
self.singleton_class.copied_attributes << name
|
225
|
+
self.class.created_type.instance_eval do
|
226
|
+
attr_accessor name
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
189
232
|
|
190
233
|
# This method runs a block with DSL methods.
|
191
234
|
#
|
@@ -199,7 +242,7 @@ module RubyYacht
|
|
199
242
|
#
|
200
243
|
# * **block: Proc** The block to run.
|
201
244
|
def run(block)
|
202
|
-
defaults = self.
|
245
|
+
defaults = self.singleton_class.default_values || {}
|
203
246
|
defaults.each do |name, value|
|
204
247
|
copy =
|
205
248
|
case value
|
@@ -219,7 +262,7 @@ module RubyYacht
|
|
219
262
|
#
|
220
263
|
# If they haven't, this will raise an exception.
|
221
264
|
def check_required_attributes
|
222
|
-
attributes = self.
|
265
|
+
attributes = self.singleton_class.required_attributes || []
|
223
266
|
attributes.each do |name|
|
224
267
|
value = instance_variable_get("@#{name}")
|
225
268
|
if value == nil || value == ''
|
@@ -241,8 +284,7 @@ module RubyYacht
|
|
241
284
|
def create_object
|
242
285
|
check_required_attributes
|
243
286
|
object = self.class.created_type.new
|
244
|
-
|
245
|
-
self.class.copied_attributes.each do |name|
|
287
|
+
self.singleton_class.copied_attributes.each do |name|
|
246
288
|
object.send("#{name}=", instance_variable_get("@#{name}"))
|
247
289
|
end
|
248
290
|
object
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module RubyYacht
|
2
|
+
# This class provides a hook that a user or plugin can provide to customize
|
3
|
+
# the app images.
|
4
|
+
#
|
5
|
+
# You can configure this with RubyYacht::Hook::DSL
|
6
|
+
class Hook
|
7
|
+
# The permitted values for the `event_time` attribute.
|
8
|
+
EVENT_TIMES = [:before, :after, :during]
|
9
|
+
|
10
|
+
# The permitted values for the `event_type` attribute.
|
11
|
+
EVENT_TYPES = [:startup, :build_checkout, :install_libraries]
|
12
|
+
|
13
|
+
# When this hook should take effect, relative to the event.
|
14
|
+
attr_accessor :event_time
|
15
|
+
|
16
|
+
# The type of event that this hook is attached to.
|
17
|
+
attr_accessor :event_type
|
18
|
+
|
19
|
+
# The type of app that this hook applies to.
|
20
|
+
attr_accessor :app_type
|
21
|
+
|
22
|
+
# The path to the script that contains the code for this hook.
|
23
|
+
attr_accessor :script_path
|
24
|
+
|
25
|
+
# The command that we should run for this hook.
|
26
|
+
attr_accessor :command
|
27
|
+
|
28
|
+
# The name of the file containing the code for this hook.
|
29
|
+
def script_name
|
30
|
+
return '' unless script_path
|
31
|
+
File.basename(script_path)
|
32
|
+
end
|
33
|
+
|
34
|
+
# This class provides a DSL for configuring hooks.
|
35
|
+
class DSL
|
36
|
+
include RubyYacht::DSL::Base
|
37
|
+
extend RubyYacht::DSL::Base::ClassMethods
|
38
|
+
|
39
|
+
# This initializer creates a new Hook DSL.
|
40
|
+
#
|
41
|
+
# ### Parameters
|
42
|
+
#
|
43
|
+
# * **event_time: Symbol** The time for the hook, relative to the
|
44
|
+
# event.
|
45
|
+
# * **event_type: Symbol** The type of event the hook is attached to.
|
46
|
+
def initialize(event_time, event_type)
|
47
|
+
@event_time = event_time
|
48
|
+
@event_type = event_type
|
49
|
+
@script_path = nil
|
50
|
+
load_custom_attributes
|
51
|
+
end
|
52
|
+
|
53
|
+
##
|
54
|
+
# :method: app_type
|
55
|
+
#
|
56
|
+
# You can call `app_type :rails` to signify that this hook applies to
|
57
|
+
# rails apps.
|
58
|
+
add_attribute :app_type
|
59
|
+
|
60
|
+
##
|
61
|
+
# :method: command
|
62
|
+
#
|
63
|
+
# You can call `command 'whoami'` to signify that this hook runs the
|
64
|
+
# command `whoami`. You can also set the command through `run_script`, if
|
65
|
+
# the hook runs a script file included with the plugin.
|
66
|
+
add_attribute :command
|
67
|
+
|
68
|
+
##
|
69
|
+
# :method: script_folder
|
70
|
+
#
|
71
|
+
# You can call `script_folder './scripts'` to signify that the scripts for
|
72
|
+
# this hook are found in the `./scripts` folder.
|
73
|
+
add_attribute :script_folder, nil, false
|
74
|
+
|
75
|
+
# This method sets the name of the script containing the code for the
|
76
|
+
# hook.
|
77
|
+
#
|
78
|
+
# The script will be understood to be in the script folder that was given
|
79
|
+
# when the DSL was created.
|
80
|
+
#
|
81
|
+
# ### Parameters
|
82
|
+
#
|
83
|
+
# * **name: String** The filename of the script.
|
84
|
+
def run_script(name)
|
85
|
+
@script_path = File.join(@script_folder || '.', name)
|
86
|
+
@command = "/var/docker/#{name}"
|
87
|
+
end
|
88
|
+
|
89
|
+
# This method checks that all of the required attributes have been set on
|
90
|
+
# the object.
|
91
|
+
#
|
92
|
+
# If they haven't, this will raise an exception.
|
93
|
+
#
|
94
|
+
# This will also check that the app type is valid.
|
95
|
+
def check_required_attributes
|
96
|
+
super
|
97
|
+
unless RubyYacht.configuration.find_app_type(@app_type)
|
98
|
+
raise "Hook has invalid app type `#{@app_type}`"
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
creates_object RubyYacht::Hook, %w(event_time event_type script_path app_type command)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|