vanagon 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 71209b38d92410c93fd14043757199b43b7eb354
4
- data.tar.gz: 00e90c362e4e79b5301c8c2ca25d4e34756cc2c5
3
+ metadata.gz: 0277e8af73f3165f6e9b9dac09f09afbf92257d1
4
+ data.tar.gz: b6d18711b68b4ca2ce845bb1cae01bbf019dfd90
5
5
  SHA512:
6
- metadata.gz: a416ecdf1e5c8d44250d9dd4192ec0d9d45c711fab197a444739bd7c711644baa9c8541488293151e5bb96a10b3fc615997ccf1bf92718e666214773aee4634b
7
- data.tar.gz: 6e8aa16121c6d1c5a97abbe5569f98b032137402282d135e210c40b3981846e6f248a520a5ca1a38e2d9cf548d8ec398363c1f04e5e270c5e75bd6e382dde8bb
6
+ metadata.gz: b8cccacd01204b1474944ec8975597369883ea354e71e58724802ab27b2581af7a009dd3ab07fe770fadd121180fb35b53bed8ae6bd409b3e031839c5d353d4d
7
+ data.tar.gz: a8b4f78d37aa2844f1615b7aded498e6c5ca47c5d34d5a18e229125062928d1c6033d9bb97beb3725a1bfeb2250bf714262af187d2509014b4573e18c95bf338
data/README.md CHANGED
@@ -84,6 +84,7 @@ Currently supported engines are:
84
84
  * `local` - Build on the local machine; platform name must match the local machine
85
85
  * `docker` - Builds in a docker container
86
86
  * `pooler` - Selects a vm from Puppet Labs' vm pooler to build on
87
+ * `hardware` - Build on a specific taget and lock it in redis
87
88
 
88
89
  #### Flags (can be anywhere in the command)
89
90
 
@@ -110,6 +111,13 @@ Used in conjunction with the pooler engine, this is a token to pass to the
110
111
  vmpooler to access the API. Without this token, the default lifetime of vms
111
112
  will be much shorter.
112
113
 
114
+ ##### LOCK\_MANAGER\_HOST
115
+ The name of the host where redis is running. Redis is used to handle a lock
116
+ when using the hardware engine. It defaults to *redis*, with no domain.
117
+
118
+ #### LOCK\_MANAGER\_PORT
119
+ Port of the system where redis is running. Defaults to *6379*.
120
+
113
121
  #### Example usage
114
122
  `build --preserve puppet-agent el-6-i386` will build the puppet-agent project
115
123
  on the el-6-i386 platform and leave the host intact afterward.
data/bin/build CHANGED
@@ -2,7 +2,7 @@
2
2
  load File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "vanagon.rb"))
3
3
 
4
4
  optparse = Vanagon::OptParse.new("#{File.basename(__FILE__)} <project-name> <platform-name> [<target>] [options]",
5
- [:workdir, :configdir, :engine, :preserve, :verbose])
5
+ [:workdir, :configdir, :engine, :preserve, :verbose, :skipcheck])
6
6
  options = optparse.parse! ARGV
7
7
 
8
8
  project = ARGV[0]
data/lib/makefile.rb ADDED
@@ -0,0 +1,67 @@
1
+ class Makefile
2
+
3
+ # The Rule class defines a single Makefile rule.
4
+ #
5
+ # @see http://www.gnu.org/software/make/manual/make.html#Rule-Introduction
6
+ class Rule
7
+
8
+ # @!attribute [rw] target
9
+ # @return [String] The target generated by this rule.
10
+ attr_accessor :target
11
+
12
+ # @!attribute [rw] dependencies
13
+ # @return [Array<String>] A list of dependencies that this rule depends on.
14
+ attr_accessor :dependencies
15
+
16
+ # @!attribute [rw] recipe
17
+ # @return [Array<String>] A list of commands to execute upon invocation of this rule.
18
+ attr_accessor :recipe
19
+
20
+ # Create a new Makefile rule. When a block is provided then it is called and passed the
21
+ # newly created Rule object.
22
+ #
23
+ # @overload initialize(target, dependencies: [], recipe: [])
24
+ # @param target [String] target
25
+ # @param dependencies [Array<String>]]
26
+ # @param recipe [Array<String>]
27
+ #
28
+ # @overload initialize(target, dependencies: [], recipe: [], &block)
29
+ # @param target [String] target
30
+ # @param dependencies [Array<String>]]
31
+ # @param recipe [Array<String>]
32
+ # @yieldparam rule [Makefile::Rule]
33
+ #
34
+ # @example Providing a block to #initialize
35
+ # newrule = Makefile::Rule.new("test", dependencies: ["all"]) do |rule|
36
+ # rule.recipe = [
37
+ # "make test",
38
+ # "make cpplint",
39
+ # ]
40
+ # end
41
+ def initialize(target, dependencies: [], recipe: [], &block)
42
+ @target = target
43
+ @dependencies = dependencies
44
+ @recipe = recipe
45
+
46
+ block.call(self) if block
47
+ end
48
+
49
+ # Format this rule as a Makefile rule.
50
+ #
51
+ # Recipes that have multiline statements will have tabs inserted after each
52
+ # newline to ensure that the recipe is parsed as part of a single makefile rule.
53
+ #
54
+ # @return [String]
55
+ def format
56
+ s = @target + ":"
57
+ unless @dependencies.empty?
58
+ s << " " << @dependencies.join(" ")
59
+ end
60
+ s << "\n"
61
+ s << @recipe.map { |line| "\t" + line.gsub("\n", "\n\t") + "\n" }.join
62
+ s
63
+ end
64
+
65
+ alias to_s format
66
+ end
67
+ end
@@ -1,13 +1,14 @@
1
1
  require 'vanagon/component/source'
2
2
  require 'vanagon/component/dsl'
3
+ require 'vanagon/component/rules'
3
4
 
4
5
  class Vanagon
5
6
  class Component
6
7
  # @!attribute [r] files
7
8
  # @return [Set] the list of files marked for installation
8
9
 
9
- attr_accessor :name, :version, :source, :url, :configure, :build, :install
10
- attr_accessor :environment, :extract_with, :dirname, :build_requires
10
+ attr_accessor :name, :version, :source, :url, :configure, :build, :check, :install
11
+ attr_accessor :environment, :extract_with, :dirname, :build_requires, :build_dir
11
12
  attr_accessor :settings, :platform, :patches, :requires, :service, :options
12
13
  attr_accessor :directories, :replaces, :provides, :cleanup_source, :environment
13
14
  attr_accessor :sources, :preinstall_actions, :postinstall_actions
@@ -50,6 +51,7 @@ class Vanagon
50
51
  @configure = []
51
52
  @install = []
52
53
  @build = []
54
+ @check = []
53
55
  @patches = []
54
56
  @files = Set.new
55
57
  @directories = []
@@ -121,6 +123,14 @@ class Vanagon
121
123
  end
122
124
  end
123
125
 
126
+ # Expands the build directory
127
+ def get_build_dir
128
+ if @build_dir
129
+ File.join(@dirname, @build_dir)
130
+ else
131
+ @dirname
132
+ end
133
+ end
124
134
 
125
135
  # Fetches secondary sources for the component. These are just dumped into the workdir currently.
126
136
  #
@@ -156,5 +166,9 @@ class Vanagon
156
166
  "export #{env.join(' ')}"
157
167
  end
158
168
  end
169
+
170
+ def rules(project, platform)
171
+ Vanagon::Component::Rules.new(self, project, platform)
172
+ end
159
173
  end
160
174
  end
@@ -1,4 +1,5 @@
1
1
  require 'vanagon/component'
2
+ require 'vanagon/patch'
2
3
  require 'ostruct'
3
4
  require 'json'
4
5
 
@@ -56,13 +57,20 @@ class Vanagon
56
57
  @component.configure << block.call
57
58
  end
58
59
 
59
- # Set or add to the build call for the component. The commands required to build the component before installing it.
60
+ # Set or add to the build call for the component. The commands required to build the component before testing/installing it.
60
61
  #
61
62
  # @param block [Proc] the command(s) required to build the component
62
63
  def build(&block)
63
64
  @component.build << block.call
64
65
  end
65
66
 
67
+ # Set or add to the check call for the component. The commands required to test the component before installing it.
68
+ #
69
+ # @param block [Proc] the command(s) required to test the component
70
+ def check(&block)
71
+ @component.check << block.call
72
+ end
73
+
66
74
  # Set or add to the install call for the component. The commands required to install the component.
67
75
  #
68
76
  # @param block [Proc] the command(s) required to install the component
@@ -80,10 +88,12 @@ class Vanagon
80
88
  # Add a patch to the list of patches to apply to the component's source after unpacking
81
89
  #
82
90
  # @param patch [String] Path to the patch that should be applied
91
+ # @param destination [String] Path to the location where the patch should be applied
83
92
  # @param strip [String, Integer] directory levels to skip in applying patch
84
93
  # @param fuzz [String, Integer] levels of context miss to ignore in applying patch
85
- def apply_patch(patch, strip: 1, fuzz: 0)
86
- @component.patches << OpenStruct.new('path' => patch, 'strip' => strip.to_s, 'fuzz' => fuzz.to_s)
94
+ # @param after [String] the location in the makefile where the patch command should be run
95
+ def apply_patch(patch, destination: @component.dirname, strip: 1, fuzz: 0, after: 'unpack')
96
+ @component.patches << Vanagon::Patch.new(patch, strip, fuzz, after, destination)
87
97
  end
88
98
 
89
99
  # Loads and parses json from a file. Will treat the keys in the
@@ -263,6 +273,27 @@ class Vanagon
263
273
  @component.options[:ref] = the_ref
264
274
  end
265
275
 
276
+ # Set a build dir relative to the source directory.
277
+ #
278
+ # The build dir will be created before the configure block runs and configure/build/install commands will be run
279
+ # in the build dir.
280
+ #
281
+ # @example
282
+ # pkg.build_dir "build"
283
+ # pkg.source "my-cmake-project" # Will create the path "my-cmake-project/build"
284
+ # pkg.configure { ["cmake .."] }
285
+ # pkg.build { ["make -j 3"] }
286
+ # pkg.install { ["make install"] }
287
+ #
288
+ # @param path [String] The build directory to use for building the project
289
+ def build_dir(path)
290
+ if Pathname.new(path).relative?
291
+ @component.build_dir = path
292
+ else
293
+ raise Vanagon::Error, "build_dir should be a relative path, but '#{path}' looks to be absolute."
294
+ end
295
+ end
296
+
266
297
  # This will add a source to the project and put it in the workdir alongside the other sources
267
298
  #
268
299
  # @param url [String] url of the source
@@ -0,0 +1,217 @@
1
+ require 'vanagon/component'
2
+ require 'vanagon/utilities/shell_utilities'
3
+ require 'makefile'
4
+
5
+ class Vanagon
6
+ class Component
7
+ # Vanagon::Component::Rules creates all Makefile rules for a given component.
8
+ class Rules
9
+
10
+ include Vanagon::Utilities::ShellUtilities
11
+
12
+ # Create methods that generate Makefile rules.
13
+ #
14
+ # This method cuts out some of the boilerplate of creating Makefile rules
15
+ # by creating methods and Makefile objects with a common name.
16
+ #
17
+ # @param target [Symbol] The rule target name.
18
+ # @param dependencies [Array<String>] An optional list of dependencies for the rule
19
+ # @yieldparam rule [Makefile::Rule] The generated Makefile rule
20
+ # @return [void]
21
+ #
22
+ # @!macro [attach] rule
23
+ # @return [Makefile::Rule] The $1 rule
24
+ def self.rule(target, dependencies: [], &block)
25
+ define_method("#{target}_rule") do
26
+ Makefile::Rule.new("#{@component.name}-#{target}", dependencies: dependencies) do |rule|
27
+ instance_exec(rule, &block)
28
+ end
29
+ end
30
+ end
31
+
32
+ # @param component [Vanagon::Component] The component to create rules for.
33
+ # @param project [Vanagon::Project] The project associated with the component.
34
+ # @param platform [Vanagon::Platform] The platform where this component will be built.
35
+ def initialize(component, project, platform)
36
+ @component = component
37
+ @project = project
38
+ @platform = platform
39
+ end
40
+
41
+ # Generate all Makefile rules for this component.
42
+ #
43
+ # If the project has the cleanup attribute set, a cleanup rule will be included
44
+ # in the returned rules.
45
+ #
46
+ # @return [Array<Makefile::Rule>]
47
+ def rules
48
+ list = [
49
+ component_rule,
50
+ unpack_rule,
51
+ patch_rule,
52
+ configure_rule,
53
+ build_rule,
54
+ check_rule,
55
+ install_rule,
56
+ clean_rule,
57
+ clobber_rule,
58
+ ]
59
+ if @project.cleanup
60
+ list << cleanup_rule
61
+ end
62
+
63
+ list
64
+ end
65
+
66
+ # Generate a top level rule to build this component.
67
+ #
68
+ # @return [Makefile::Rule]
69
+ def component_rule
70
+ Makefile::Rule.new("#{@component.name}", dependencies: ["#{@component.name}-install"])
71
+ end
72
+
73
+ # Unpack the source for this component. The unpacking behavior depends on
74
+ # the source type of the component.
75
+ #
76
+ # @see [Vanagon::Component::Source]
77
+ rule("unpack", dependencies: ['file-list-before-build']) do |r|
78
+ r.recipe << andand(@component.get_environment, @component.extract_with)
79
+ r.recipe << "touch #{r.target}"
80
+ end
81
+
82
+ # Apply any patches for this component.
83
+ rule("patch") do |r|
84
+ r.dependencies = ["#{@component.name}-unpack"]
85
+
86
+ after_unpack_patches = @component.patches.select { |patch| patch.after == "unpack" }
87
+ unless after_unpack_patches.empty?
88
+ r.recipe << andand_multiline(
89
+ "cd #{@component.dirname}",
90
+ after_unpack_patches.map { |patch| patch.cmd(@platform) }
91
+ )
92
+ end
93
+
94
+ r.recipe << "touch #{r.target}"
95
+ end
96
+
97
+ # Create a build directory for this component if an out of source tree build is specified,
98
+ # and any configure steps, if any.
99
+ rule("configure") do |r|
100
+ r.dependencies = ["#{@component.name}-patch"].concat(@project.list_component_dependencies(@component))
101
+
102
+ if @component.get_build_dir
103
+ r.recipe << "[ -d #{@component.get_build_dir} ] || mkdir -p #{@component.get_build_dir}"
104
+ end
105
+
106
+ unless @component.configure.empty?
107
+ r.recipe << andand_multiline(
108
+ "cd #{@component.get_build_dir}",
109
+ @component.get_environment,
110
+ @component.configure
111
+ )
112
+ end
113
+
114
+ r.recipe << "touch #{r.target}"
115
+ end
116
+
117
+ # Build this component.
118
+ rule("build") do |r|
119
+ r.dependencies = ["#{@component.name}-configure"]
120
+
121
+ unless @component.build.empty?
122
+ r.recipe << andand_multiline(
123
+ "cd #{@component.get_build_dir}",
124
+ @component.get_environment,
125
+ @component.build
126
+ )
127
+ end
128
+
129
+ r.recipe << "touch #{r.target}"
130
+ end
131
+
132
+ # Run tests for this component.
133
+ rule("check") do |r|
134
+ r.dependencies = ["#{@component.name}-build"]
135
+
136
+ unless @component.check.empty? || @project.settings[:skipcheck]
137
+ r.recipe << andand_multiline(
138
+ "cd #{@component.get_build_dir}",
139
+ @component.get_environment,
140
+ @component.check
141
+ )
142
+ end
143
+
144
+ r.recipe << "touch #{r.target}"
145
+ end
146
+
147
+ # Install this component.
148
+ rule("install") do |r|
149
+ r.dependencies = ["#{@component.name}-check"]
150
+
151
+ unless @component.install.empty?
152
+ r.recipe << andand_multiline(
153
+ "cd #{@component.get_build_dir}",
154
+ @component.get_environment,
155
+ @component.install
156
+ )
157
+ end
158
+
159
+ after_install_patches = @component.patches.select { |patch| patch.after == "install" }
160
+ after_install_patches.each do |patch|
161
+ r.recipe << andand(
162
+ "cd #{patch.destination}",
163
+ patch.cmd(@platform),
164
+ )
165
+ end
166
+
167
+ r.recipe << "touch #{r.target}"
168
+ end
169
+
170
+ # Run any post-installation cleanup steps for this component.
171
+ #
172
+ # This component is only included by {#rules} if the associated project has
173
+ # the `cleanup` attribute set.
174
+ rule("cleanup") do |r|
175
+ r.dependencies = ["#{@component.name}-install"]
176
+ r.recipe = [@component.cleanup_source, "touch #{r.target}"]
177
+ end
178
+
179
+ # Clean up any files generated while building this project.
180
+ #
181
+ # This cleans up the project by invoking `make clean` and removing the touch files
182
+ # for the configure/build/install steps.
183
+ rule("clean") do |r|
184
+ r.recipe << andand(
185
+ "[ -d #{@component.get_build_dir} ]",
186
+ "cd #{@component.get_build_dir}",
187
+ "#{@platform[:make]} clean"
188
+ )
189
+
190
+ %w(configure build install).each do |type|
191
+ touchfile = "#{@component.name}-#{type}"
192
+ r.recipe << andand(
193
+ "[ -e #{touchfile} ]",
194
+ "rm #{touchfile}"
195
+ )
196
+ end
197
+ end
198
+
199
+ # Remove all files associated with this component.
200
+ rule("clobber") do |r|
201
+ r.dependencies = ["#{@component.name}-clean"]
202
+ r.recipe = [
203
+ andand("[ -d #{@component.dirname} ]", "rm -r #{@component.dirname}"),
204
+ andand("[ -e #{@component.name}-unpack ]", "rm #{@component.name}-unpack")
205
+ ]
206
+ end
207
+
208
+ # Generate a Makefile fragment that contains all of the rules for the component.
209
+ # @return [String]
210
+ def format
211
+ rules.map(&:to_s).join("\n")
212
+ end
213
+
214
+ alias to_s format
215
+ end
216
+ end
217
+ end