ruby_yacht 0.1.1 → 0.2.0
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 +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
|