chefrepo-manifest-builder 0.1.0 → 0.1.1

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.
data/Rakefile ADDED
@@ -0,0 +1,36 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+
5
+ begin
6
+ require 'bundler'
7
+ rescue LoadError => e
8
+ warn e.message
9
+ warn "Run `gem install bundler` to install Bundler."
10
+ exit -1
11
+ end
12
+
13
+ begin
14
+ Bundler.setup(:development)
15
+ rescue Bundler::BundlerError => e
16
+ warn e.message
17
+ warn "Run `bundle install` to install missing gems."
18
+ exit e.status_code
19
+ end
20
+
21
+ require 'rake'
22
+
23
+ require 'rubygems/tasks'
24
+ Gem::Tasks.new
25
+
26
+ require 'rspec/core/rake_task'
27
+ RSpec::Core::RakeTask.new
28
+
29
+ task :test => :spec
30
+ task :default => :spec
31
+
32
+ require 'cucumber/rake/task'
33
+
34
+ Cucumber::Rake::Task.new do |t|
35
+ t.cucumber_opts = %w[--format pretty]
36
+ end
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ path = File.dirname(__FILE__)
6
+ if File.exists?("#{path}/../.gitignore")
7
+ %w(chefrepo-builder cicd-builder).each do |mod|
8
+ add_path = File.expand_path(File.join(path, "../../#{mod}", "lib"))
9
+ $:.unshift(add_path)
10
+ end
11
+ else
12
+ # Borrowing from "whiches" gem ...
13
+ cmd = File.basename(__FILE__, '.rb')
14
+ exes = []
15
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
16
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |pth|
17
+ exts.each { |ext|
18
+ exe = File.join(pth, "#{cmd}#{ext}")
19
+ exes << exe if File.executable? exe
20
+ }
21
+ end
22
+ if exes.size > 0
23
+ path = File.dirname(exes[0])
24
+ end
25
+
26
+ end
27
+ add_path = File.expand_path(File.join(path, "..", "lib"))
28
+ $:.unshift(add_path)
29
+
30
+ require 'cicd/builder/chefrepo-manifest'
31
+
32
+ # =====================================================================================================================
33
+ exit CiCd::Builder::ChefRepoManifest::Runner.new().run()
@@ -0,0 +1,32 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.expand_path('../lib/cicd/builder/chefrepo-manifest/version', __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = 'chefrepo-manifest-builder'
7
+ gem.version = CiCd::Builder::ChefRepoManifest::VERSION
8
+ gem.summary = %q{ChefRepo builder for a software manifest}
9
+ gem.description = %q{ChefRepo builder of the software manifest for Continuous Integration/Continuous Delivery artifact promotion style deployments}
10
+ gem.license = "Apachev2"
11
+ gem.authors = ["Christo De Lange"]
12
+ gem.email = "rubygems@dldinternet.com"
13
+ gem.homepage = "https://rubygems.org/gems/manifest-builder"
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
+ gem.require_paths = ['lib']
19
+
20
+ gem.add_dependency 'manifest-builder', '>= 0.6.2', '< 1.1'
21
+ # gem.add_dependency 'cicd-builder', '>= 0.9.48', '< 1.1'
22
+ # gem.add_dependency 'chefrepo-builder', '>= 0.9.31', '< 1.1'
23
+ gem.add_dependency 'json', '>= 1.8.1', '< 1.9'
24
+ gem.add_dependency 's3etag', '>= 0.0.1', '< 0.1.0'
25
+ gem.add_dependency 'archive-tar-minitar', '= 0.5.2'
26
+
27
+ gem.add_development_dependency 'bundler', '>= 1.7', '< 2.0'
28
+ gem.add_development_dependency 'rake', '>= 10.3', '< 11'
29
+ gem.add_development_dependency 'rubygems-tasks', '>= 0.2', '< 1.1'
30
+ gem.add_development_dependency 'cucumber', '>= 0.10.7', '< 0.11'
31
+ gem.add_development_dependency 'rspec', '>= 2.99', '< 3.0'
32
+ end
data/features/.gitkeep ADDED
File without changes
@@ -0,0 +1 @@
1
+ Feature: Blah blah blah
File without changes
@@ -0,0 +1,62 @@
1
+
2
+ module CiCd
3
+ module Builder
4
+ # noinspection RubySuperCallWithoutSuperclassInspection
5
+ module ChefRepoManifest
6
+ module Build
7
+
8
+ # ---------------------------------------------------------------------------------------------------------------
9
+ # noinspection RubyHashKeysTypesInspection
10
+ def prepareBuild()
11
+ super
12
+ if @vars[:return_code] == 0
13
+ end
14
+ @vars[:return_code]
15
+ end
16
+
17
+ # ---------------------------------------------------------------------------------------------------------------
18
+ def packageBuild()
19
+ @logger.step __method__.to_s
20
+ if isSameDirectory(Dir.pwd, ENV['WORKSPACE'])
21
+ if @vars.has_key?(:components) and not @vars[:components].empty?
22
+ @vars[:return_code] = 0
23
+
24
+ clazz = getRepoClass('S3')
25
+ @logger.debug "Repo class == '#{clazz}'"
26
+ if clazz.is_a?(Class) and not clazz.nil?
27
+ @repo = clazz.new(self)
28
+
29
+ if @vars[:return_code] == 0
30
+ lines = []
31
+ @vars[:artifacts] = []
32
+ # Deal with all artifacts of each component
33
+ @vars[:components].each { |comp|
34
+ processComponent(comp, lines)
35
+ }
36
+ if @vars[:return_code] == 0
37
+ cleanupAfterPackaging(lines)
38
+ end
39
+
40
+ else
41
+ @logger.fatal "S3 repo error: Bucket #{ENV['AWS_S3_BUCKET']}"
42
+ end
43
+ else
44
+ @logger.error "CiCd::Builder::Repo::#{type} is not a valid repo class"
45
+ @vars[:return_code] = Errors::BUILDER_REPO_TYPE
46
+ end
47
+ else
48
+ @logger.error 'No components found during preparation?'
49
+ @vars[:return_code] = Errors::NO_COMPONENTS
50
+ end
51
+ else
52
+ @logger.error "Not in WORKSPACE? '#{pwd}' does not match WORKSPACE='#{workspace}'"
53
+ @vars[:return_code] = Errors::WORKSPACE_DIR
54
+ end
55
+
56
+ @vars[:return_code]
57
+ end
58
+
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,323 @@
1
+ require 'artifactory'
2
+ require 'tmpdir'
3
+
4
+ module CiCd
5
+ module Builder
6
+ # noinspection RubySuperCallWithoutSuperclassInspection
7
+ module Manifest
8
+ module Repo
9
+ class Artifactory < CiCd::Builder::Repo::Artifactory
10
+ # include ::Artifactory::Resource
11
+
12
+ # ---------------------------------------------------------------------------------------------------------------
13
+ def initialize(builder)
14
+ super
15
+ end
16
+
17
+ # ---------------------------------------------------------------------------------------------------------------
18
+ def uploadToRepo(artifacts)
19
+ @manifest = {}
20
+ super
21
+ if @vars[:return_code] == 0
22
+ # Preserve the manifest (maybeUploadArtifactoryObject will add everything we upload to the instance var)
23
+ manifest = @manifest.dup
24
+ # Create a manifest for each product and store it.
25
+ createProductManifests(manifest)
26
+ # Get a super manifest of all products and store as learning-manifest
27
+ createSuperManifest(manifest) # -#{@vars[:variant]}
28
+ @manifest = manifest
29
+ end
30
+ # If we are asked to produce a PROJECTS_FILE then we do that from the manifest and components.
31
+ unless ENV['PROJECTS_FILE'].nil?
32
+ if @vars[:return_code] == 0
33
+ if File.directory?(File.realdirpath(File.dirname(ENV['PROJECTS_FILE'])))
34
+ createProjectsFile
35
+ else
36
+ @logger.error "The path to the PROJECTS_FILE (#{File.dirname(ENV['PROJECTS_FILE'])}) does not exist!"
37
+ @vars[:return_code] = Errors::NO_PROJECTS_PATH
38
+ end
39
+ end
40
+ end
41
+ @vars[:artifacts].each do |art|
42
+ if art[:data][:temp].is_a?(FalseClass)
43
+ if File.exists?(art[:data][:file])
44
+ File.unlink(art[:data][:file]) if File.exists?(art[:data][:file])
45
+ art[:data].delete(:file)
46
+ art[:data].delete(:temp)
47
+ else
48
+ @logger.warn "Temporary file disappeared: #{data.ai}"
49
+ @vars[:return_code] = Errors::TEMP_FILE_MISSING
50
+ end
51
+ end
52
+ end
53
+ @vars[:return_code]
54
+ end
55
+
56
+ # ---------------------------------------------------------------------------------------------------------------
57
+ def createProjectsFile
58
+ @logger.info __method__.to_s
59
+ projects = {}
60
+ project_names = loadProjectNames()
61
+ exts = {}
62
+ exts = Hash[@vars[:artifacts].map { |a| [a[:data][:name], File.basename(a[:data][:file]).match(CiCd::Builder::Manifest::Build::EXT_RGX)[1]] }]
63
+
64
+ createClassesFile()
65
+
66
+ @vars[:artifacts].each do |art|
67
+ prod = art[:data][:name]
68
+ mod = art[:data][:module]
69
+ projects[prod] = {
70
+ name: project_names[prod] || prod,
71
+ module: mod,
72
+ ext: exts[prod],
73
+ class_filter: @vars[:filters][prod] || @vars[:filters][prod.gsub(/-manifest$/, '')],
74
+ }
75
+ end
76
+
77
+ require 'chef/mash'
78
+ require 'chef/mixin/deep_merge'
79
+
80
+ projects_hash = File.exists?(ENV['PROJECTS_FILE']) ? loadConfigFile(ENV['PROJECTS_FILE']) : {}
81
+ old_projects = ::Chef::Mash.new(projects_hash)
82
+ projects = ::Chef::Mash.new(projects)
83
+ projects = ::Chef::Mash.new(::Chef::Mixin::DeepMerge.deep_merge(projects, old_projects))
84
+ saveConfigFile(ENV['PROJECTS_FILE'], projects)
85
+ data = {
86
+ name: 'projects-file',
87
+ module: 'projects-file',
88
+ file: ENV['PROJECTS_FILE'],
89
+ version: @vars[:build_ver],
90
+ build: @vars[:build_num],
91
+ properties: @properties_matrix,
92
+ temp: false,
93
+ sha1: Digest::SHA1.file(ENV['PROJECTS_FILE']).hexdigest,
94
+ md5: Digest::MD5.file(ENV['PROJECTS_FILE']).hexdigest,
95
+ }
96
+
97
+ maybeUploadArtifactoryObject(
98
+ data: data,
99
+ artifact_module: data[:name],
100
+ artifact_version: data[:version] || @vars[:version],
101
+ file_name: '',
102
+ file_ext: (ENV['PROJECTS_FILE'] and ENV['PROJECTS_FILE'].downcase.match(/\.ya?ml$/)) ? 'yaml' : 'json'
103
+ )
104
+ end
105
+
106
+ # ---------------------------------------------------------------------------------------------------------------
107
+ # noinspection RubyHashKeysTypesInspection
108
+ def createClassesFile()
109
+ @logger.info __method__.to_s
110
+ project_names = loadProjectNames()
111
+
112
+ @vars[:classes] = YAML.load(IO.read(ENV['CLASSES_MANIFEST_FILE']))
113
+ # keys = Hash[classes.keys.map.with_index.to_a].keys.sort
114
+
115
+ @vars[:filters] = {}
116
+ filters = {}
117
+ @vars[:classes].each do |role,apps|
118
+ apps.map{ |app|
119
+ filters[app] ||= []
120
+ filters[app] << role
121
+ }
122
+ end
123
+ filters.each do |app,roles|
124
+ @vars[:filters][app] = Hash[roles.map.with_index.to_a].keys.join('|')
125
+ end
126
+
127
+ saveConfigFile(ENV['CLASSES_FILE'],@vars[:classes])
128
+ data = {
129
+ name: 'classes-file',
130
+ module: 'classes-file',
131
+ file: ENV['CLASSES_FILE'],
132
+ version: @vars[:build_ver],
133
+ build: @vars[:build_num],
134
+ properties: @properties_matrix,
135
+ temp: false,
136
+ sha1: Digest::SHA1.file(ENV['CLASSES_FILE']).hexdigest,
137
+ md5: Digest::MD5.file(ENV['CLASSES_FILE']).hexdigest,
138
+ }
139
+
140
+ maybeUploadArtifactoryObject(
141
+ data: data,
142
+ artifact_module: data[:name],
143
+ artifact_version: data[:version] || @vars[:version],
144
+ file_name: '',
145
+ file_ext: 'yaml'
146
+ )
147
+ end
148
+
149
+ def saveConfigFile(file, projects)
150
+ @logger.info "Save config file: #{file}"
151
+ ext = file.gsub(/\.(\w+)$/, '\1')
152
+ IO.write(file, case ext.downcase
153
+ when /ya?ml/
154
+ projects.to_hash.to_yaml line_width: 1024, indentation: 4, canonical: false
155
+ when /json|js/
156
+ JSON.pretty_generate(projects.to_hash, {indent: "\t", space: ' '})
157
+ else
158
+ raise "Unsupported extension: #{ext}"
159
+ end)
160
+ end
161
+
162
+ def loadConfigFile(file)
163
+ ext = file.gsub(/\.(\w+)$/, '\1')
164
+ hash = case ext.downcase
165
+ when /ya?ml/
166
+ YAML.load_file(ENV['PROJECTS_FILE'])
167
+ when /json|js/
168
+ JSON.load(IO.read(ENV['PROJECTS_FILE']))
169
+ else
170
+ raise "Unsupported extension: #{ext}"
171
+ end
172
+ end
173
+
174
+ def loadProjectNames(fresh=false)
175
+ if fresh
176
+ @project_names = nil
177
+ end
178
+ unless @project_names
179
+ @project_names = {}
180
+ unless ENV['PROJECT_NAMES'].nil?
181
+ if File.exists?(ENV['PROJECT_NAMES'])
182
+ @logger.info "Load PROJECT_NAMES: #{ENV['PROJECT_NAMES']}"
183
+ @project_names = JSON.load(IO.read(ENV['PROJECT_NAMES'])) || {}
184
+ else
185
+ @logger.error "The PROJECT_NAMES file (#{ENV['PROJECT_NAMES']}) does not exist!"
186
+ @vars[:return_code] = Errors::NO_PROJECT_NAMES
187
+ end
188
+ end
189
+ end
190
+ @project_names
191
+ end
192
+
193
+ def createSuperManifest(manifest)
194
+ manifest_data = ''
195
+ manifest.each do |mod, man|
196
+ man.each do |k, v|
197
+ manifest_data += "#{k}=#{v}\n"
198
+ end
199
+ end
200
+ amn = artifactory_manifest_name # Just using a local iso invoking method_missing repeatedly ... ;)
201
+ data = {module: amn, data: manifest_data, version: @vars[:build_ver], build: @vars[:build_num], properties: @properties_matrix}
202
+ # tempArtifactFile(amn, data)
203
+
204
+ data[:file] = Dir::Tmpname.create(amn) do |tmpnam, n, opts|
205
+ mode = File::RDWR|File::CREAT|File::EXCL
206
+ perm = 0600
207
+ opts = perm
208
+ end + '.properties'
209
+ IO.write(data[:file], data[:data])
210
+ data[:temp] = false
211
+ data[:sha1] = Digest::SHA1.file(data[:file]).hexdigest
212
+ data[:md5] = Digest::MD5.file(data[:file]).hexdigest
213
+ data[:name] = amn
214
+ @vars[:artifacts] << {
215
+ key: amn,
216
+ data: data.dup,
217
+ }
218
+ # manifest[amn]={ amn => "#{@vars[:build_ver]}-#{@vars[:build_num]}" }
219
+
220
+ maybeUploadArtifactoryObject(data: data, artifact_module: amn, artifact_version: data[:version] || @vars[:version], file_name: '', file_ext: 'properties')
221
+ end
222
+
223
+ # ---------------------------------------------------------------------------------------------------------------
224
+ def createProductManifests(manifest)
225
+ manifest.dup.each do |mod, man|
226
+ manifest_data = ''
227
+ man.each do |k, v|
228
+ manifest_data += "#{k}=#{v}\n"
229
+ end
230
+ data = {
231
+ name: "#{mod}-manifest",
232
+ module: "#{mod}-manifest",
233
+ component: mod,
234
+ data: manifest_data,
235
+ version: @vars[:build_ver],
236
+ build: @vars[:build_num],
237
+ properties: @properties_matrix
238
+ }
239
+ # tempArtifactFile("#{mod}-manifest", data)
240
+
241
+ data[:file] = Dir::Tmpname.create("#{mod}-manifest") do |tmpnam, n, opts|
242
+ mode = File::RDWR|File::CREAT|File::EXCL
243
+ perm = 0600
244
+ opts = perm
245
+ end + '.properties'
246
+ IO.write(data[:file], data[:data])
247
+ data[:temp] = false
248
+ data[:sha1] = Digest::SHA1.file(data[:file]).hexdigest
249
+ data[:md5] = Digest::MD5.file(data[:file]).hexdigest
250
+ @vars[:artifacts] << {
251
+ key: "#{mod}-manifest",
252
+ data: data.dup,
253
+ }
254
+ # noinspection RubyStringKeysInHashInspection
255
+ # manifest["#{mod}-manifest"]={ "#{mod}-manifest" => "#{@vars[:build_ver]}-#{@vars[:build_num]}" }
256
+
257
+ maybeUploadArtifactoryObject(data: data, artifact_module: data[:name], artifact_version: data[:version] || @vars[:version], file_name: '', file_ext: 'properties') # -#{@vars[:variant]}
258
+ end
259
+ end
260
+
261
+ # ---------------------------------------------------------------------------------------------------------------
262
+ def maybeUploadArtifactoryObject(args)
263
+ super
264
+ if @vars[:return_code] == 0
265
+ data = args[:data]
266
+ artifact_module = args[:artifact_module]
267
+ artifact_version = args[:artifact_version]
268
+ # file_ext = args[:file_ext]
269
+ # file_name = args[:file_name]
270
+ if @manifest[artifact_module].nil?
271
+ @manifest[artifact_module] = {}
272
+ file_name = artifact_module
273
+ else
274
+ file_name, _ = get_artifact_file_name_ext(data)
275
+ if file_name.empty?
276
+ file_name = artifact_module
277
+ else
278
+ file_name = "#{artifact_module}#{file_name}"
279
+ end
280
+ end
281
+ @manifest[artifact_module][file_name] = artifact_version
282
+ end
283
+
284
+ @vars[:return_code]
285
+ end
286
+
287
+ private :createProductManifests, :createProjectsFile, :createSuperManifest
288
+ end
289
+ end
290
+ end
291
+ end
292
+ end
293
+
294
+ =begin
295
+
296
+ {
297
+ "test-project": {
298
+ "name": "test-project",
299
+ "module": "test-server",
300
+ "ext": "war",
301
+ "class_filter": "role.role-1"
302
+ },
303
+ "test-project-2": {
304
+ "name": "test-project-2",
305
+ "module": "test-server2",
306
+ "ext": "zip",
307
+ "class_filter": "role.role-2"
308
+ },
309
+ "test-manifest": {
310
+ "name": "test-manifest",
311
+ "module": "test-manifest",
312
+ "ext": "properties",
313
+ "class_filter": ""
314
+ },
315
+ "test-manifest2": {
316
+ "name": "test-manifest2",
317
+ "module": "test-manifest2",
318
+ "ext": "properties",
319
+ "class_filter": ""
320
+ }
321
+ }
322
+
323
+ =end
@@ -0,0 +1,10 @@
1
+ module CiCd
2
+ module Builder
3
+ module ChefRepoManifest
4
+ # chefrepo-manifest-builder version
5
+ VERSION = '0.1.1'
6
+ MAJOR, MINOR, TINY = VERSION.split('.')
7
+ PATCH = TINY
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,39 @@
1
+ require 'cicd/builder/manifest'
2
+
3
+ module CiCd
4
+ module Builder
5
+ _lib=File.dirname(__FILE__)
6
+ $:.unshift(_lib) unless $:.include?(_lib)
7
+
8
+ require 'cicd/builder/chefrepo-manifest/version'
9
+
10
+ module ChefRepoManifest
11
+ class Runner < Manifest::Runner
12
+
13
+ # ---------------------------------------------------------------------------------------------------------------
14
+ def initialize()
15
+ super
16
+ @default_options[:builder] = VERSION
17
+ end
18
+
19
+ # ---------------------------------------------------------------------------------------------------------------
20
+ def getBuilderVersion
21
+ {
22
+ version: VERSION,
23
+ major: MAJOR,
24
+ minor: MINOR,
25
+ patch: PATCH,
26
+ }
27
+ end
28
+
29
+ # ---------------------------------------------------------------------------------------------------------------
30
+ def setup()
31
+ $stdout.write("ChefRepoManifestBuilder v#{CiCd::Builder::ChefRepoManifest::VERSION}\n")
32
+ super
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+ end
39
+ end
data/openssl ADDED
File without changes
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'cicd/builder'
3
+
4
+ describe ManifestBuilder::Builder do
5
+ it "should have a VERSION constant" do
6
+ subject.const_get('VERSION').should_not be_empty
7
+ end
8
+ end
@@ -0,0 +1,4 @@
1
+ require 'rspec'
2
+ require 'cicd/builder/version'
3
+
4
+ include ManifestBuilder::Builder