vara 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,87 @@
1
+ module Vara
2
+ module Metadata
3
+ # "Struct" representing the information about the compiled_packages field in metadata.yml
4
+ # @example entry from metadata.yml
5
+ # compiled_package:
6
+ # name: cf
7
+ # file: cf-170-bosh-vsphere-esxi-ubuntu-2366.tgz
8
+ # version: "170"
9
+ # md5: 048f9e546bb2bb490f44cd9ea074b22a
10
+ # url: https://s3-us-west-1.amazonaws.com/releng-artifacts/cf-170-build-99/cf-170-bosh-vsphere-esxi-ubuntu-2366.tgz
11
+ class CompiledPackages
12
+ # The name field of the YAML. Typically the name of the contained release.
13
+ # @return [String]
14
+ attr_reader :name
15
+
16
+ # The version field of the YAML. Typically the version of the contained release.
17
+ # @return [String]
18
+ attr_reader :version
19
+
20
+ # The filename of the compiled package
21
+ # @return [String]
22
+ attr_reader :basename
23
+
24
+ # Checksum of the compiled_packages tarball
25
+ # @return [String]
26
+ attr_reader :md5
27
+
28
+ # SHA1 Checksum is not supported for compiled_packages
29
+ # @return nil
30
+ attr_reader :sha1
31
+
32
+ # Infers the metadata given a compiled packages file on disk
33
+ # @param path_to_compiled_packages [String] The path to the compiled packages file on disk
34
+ # @return [Vara::CompiledPackagesMetadata]
35
+ def self.from_file(path_to_compiled_packages)
36
+ md5 = Digest::MD5.file(path_to_compiled_packages).hexdigest
37
+ basename = File.basename(path_to_compiled_packages)
38
+
39
+ name, rest = basename.split('-', 2)
40
+ version = rest.gsub(/-bosh.*$/, '')
41
+
42
+ new(name, version, basename, md5)
43
+ end
44
+
45
+ # @param name [String]
46
+ # @param version [String]
47
+ # @param file [String]
48
+ # @param md5 [String]
49
+ # @param url [String]
50
+ def initialize(name, version, file, md5, url = nil)
51
+ @name = name
52
+ @version = version
53
+ @basename = file
54
+ @md5 = md5
55
+ @url = url
56
+ end
57
+
58
+ # The blobstore URL for the compiled_package.
59
+ # @raise [RuntimeError] if the URL is not set.
60
+ # @return [String]
61
+ def url
62
+ @url || fail("URL unknown for compiled_packages #{name}")
63
+ end
64
+
65
+ # @return [nil] the interface for downloader requires this method
66
+ def aws
67
+ nil
68
+ end
69
+
70
+ # If the URL is set, a markdown-style URL with the basename attribute.
71
+ # Otherwise, just the basename.
72
+ # @return [String]
73
+ def to_s
74
+ @url ? "[#{basename}](#{@url})" : basename
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
81
+ # All rights reserved.
82
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
83
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
84
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
85
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
86
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
87
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,86 @@
1
+ require 'ostruct'
2
+
3
+ module Vara
4
+ module Metadata
5
+ # "Struct" representing the information about a single release in metadata.yml's releases array
6
+ # @example entry from metadata.yml
7
+ # releases:
8
+ # - file: cf-170.tgz
9
+ # name: cf
10
+ # version: '170'
11
+ # md5: 8a0700de688b4fdd270b41c4a4de9d0e
12
+ # url: https://releng-artifacts.s3.amazonaws.com/cf-170.tgz
13
+ class Release
14
+ # @return [String] Name of the release
15
+ attr_reader :name
16
+
17
+ # @return [String] Version of the release
18
+ attr_reader :version
19
+
20
+ # @return [String] The name of the release file
21
+ attr_reader :basename
22
+
23
+ # @return [String] The md5 of the release file's content
24
+ attr_reader :md5
25
+
26
+ # @return [String] The sha1 of the release file's content
27
+ attr_reader :sha1
28
+
29
+ # @return [OpenStruct] The AWS Configuration
30
+ attr_reader :aws
31
+
32
+ # Infers the metadata given a release file on disk
33
+ # @param release_tarball_path [String] The path to the release file on disk
34
+ # @return [Vara::ReleaseMetadata]
35
+ def self.from_file(release_tarball_path)
36
+ md5 = Digest::MD5.file(release_tarball_path).hexdigest
37
+ sha1 = Digest::SHA1.file(release_tarball_path).hexdigest
38
+ basename = File.basename(release_tarball_path)
39
+
40
+ release_parts = basename.gsub(/\.tgz$/, '')
41
+ name, version = release_parts.split('-', 2)
42
+
43
+ new(name: name, version: version, file: basename, md5: md5, sha1: sha1)
44
+ end
45
+
46
+ # @param name [String]
47
+ # @param version [String]
48
+ # @param file [String]
49
+ # @param md5 [String]
50
+ # @param url [String]
51
+ def initialize(name:, version:, file:, md5:, sha1:, url: nil, aws: nil)
52
+ @name = name
53
+ @version = version
54
+ @basename = file
55
+ @md5 = md5
56
+ @sha1 = sha1
57
+ @url = url
58
+ @aws = OpenStruct.new(aws) if aws
59
+ end
60
+
61
+ def url
62
+ if @url
63
+ @url
64
+ elsif @aws
65
+ "#{aws.bucket_name}/#{aws.filename}"
66
+ end
67
+ end
68
+
69
+ # If the URL is set, a markdown-style URL with the basename attribute.
70
+ # Otherwise, just the basename.
71
+ # @return [String]
72
+ def to_s
73
+ @url ? "[#{basename}](#{@url})" : basename
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
80
+ # All rights reserved.
81
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
82
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
83
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
84
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
85
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
86
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,84 @@
1
+ module Vara
2
+ module Metadata
3
+ # "Struct" representing the information about the stemcell field in metadata.yml
4
+ # @note Unlike Vara::ReleaseMetadata and Vara::CompiledPackagesMetadata, this class does not have a settable URL
5
+ # because there is an inferred URL from the global BOSH stemcell blobstore.
6
+ # @example entry from metadata.yml
7
+ # stemcell:
8
+ # name: bosh-vsphere-esxi-ubuntu
9
+ # version: '2366'
10
+ # file: bosh-stemcell-2366-vsphere-esxi-ubuntu.tgz
11
+ # md5: 0fbdcd100f716d127f821b1b4335135a
12
+ class Stemcell
13
+ # @return [String] the name of the stemcell.
14
+ attr_reader :name
15
+
16
+ # @return [String] the version of the stemcell.
17
+ attr_reader :version
18
+
19
+ # @return [String] the filename of the stemcell
20
+ attr_reader :basename
21
+
22
+ # @return [String] md5 checksum of the stemcell
23
+ attr_reader :md5
24
+
25
+ # @return [String] sha1 checksum of the stemcell
26
+ attr_reader :sha1
27
+
28
+ # Infers the metadata given a stemcell file on disk
29
+ # @param path_to_stemcell [String] The path to the stemcell file on disk
30
+ # @return [Vara::StemcellMetadata]
31
+ def self.from_file(path_to_stemcell)
32
+ md5 = Digest::MD5.file(path_to_stemcell).hexdigest
33
+ sha1 = Digest::SHA1.file(path_to_stemcell).hexdigest
34
+ basename = File.basename(path_to_stemcell)
35
+
36
+ stemcell_parts = basename.gsub(/^bosh-stemcell-/, '').gsub(/\.tgz$/, '')
37
+
38
+ raw_version, iaas, hypervisor, os = stemcell_parts.split('-')
39
+ version = raw_version.tr('_', '.')
40
+
41
+ name = ['bosh', iaas, hypervisor, os].join('-')
42
+
43
+ new(name: name, version: version, file: basename, md5: md5, sha1: sha1)
44
+ end
45
+
46
+ # @param name [String]
47
+ # @param version [String]
48
+ # @param file [String]
49
+ # @param md5 [String]
50
+ def initialize(name:, version:, file:, md5:, sha1:)
51
+ @name = name
52
+ @version = version
53
+ @basename = file
54
+ @md5 = md5
55
+ @sha1 = sha1
56
+ end
57
+
58
+ # @return [String] the inferred blobstore URL of the stemcell, assuming it is a BOSH public stemcell
59
+ def url
60
+ iaas = basename.gsub(/.*\d-(\w+)-.*/, '\1')
61
+ "http://bosh-jenkins-artifacts.cf-app.com/bosh-stemcell/#{iaas}/#{basename}"
62
+ end
63
+
64
+ # @return [nil] the interface for downloader requires this method
65
+ def aws
66
+ nil
67
+ end
68
+
69
+ # @return [String] a markdown-style URL with the basename attribute.
70
+ def to_s
71
+ "[#{basename}](#{url})"
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
78
+ # All rights reserved.
79
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
80
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
81
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
82
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
83
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
84
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,79 @@
1
+ require 'vara/git_inspector'
2
+
3
+ module Vara
4
+ class PrereleaseVersioner
5
+ PRERELEASE_VERSION_PLACEHOLDER = '$PRERELEASE_VERSION$'.freeze
6
+ PRODUCT_VERSION_KEY = 'product_version'.freeze
7
+ TO_VERSION_KEY = 'to_version'.freeze
8
+ MIGRATIONS_KEY = 'migrations'.freeze
9
+ MIGRATIONS_RULES_KEY = 'rules'.freeze
10
+ MIGRATIONS_RULES_TO_KEY = 'to'.freeze
11
+
12
+ # @param product_directory_path [String]
13
+ # @param cycle [String] cycle (e.g. alpha, beta, etc.) to use in expanded prerelease version value
14
+ def initialize(product_directory_path, cycle)
15
+ @product_directory_path = product_directory_path
16
+ @cycle = cycle
17
+ end
18
+
19
+ # @param new_prerelease_version [String] explicit value to override the prerelease version. Use with caution.
20
+ # @return [void]
21
+ def override_prerelease_version!(new_prerelease_version)
22
+ @prerelease_version = new_prerelease_version
23
+ end
24
+
25
+ # @param metadata_hash [Hash] Hash contents of full product metadata
26
+ # @return [Hash] product metadata with product version value updated if necessary
27
+ def update_metadata(metadata_hash)
28
+ return metadata_hash unless metadata_hash.fetch(PRODUCT_VERSION_KEY).include?(PRERELEASE_VERSION_PLACEHOLDER)
29
+ metadata_hash[PRODUCT_VERSION_KEY].gsub!(PRERELEASE_VERSION_PLACEHOLDER, prerelease_version)
30
+ metadata_hash
31
+ end
32
+
33
+ # @param migrations_hash [Hash] Hash contents of full content migrations
34
+ # @return [Hash] content migrations with product version value updated if necessary
35
+ def update_content_migrations(migrations_hash)
36
+ migrations_hash[TO_VERSION_KEY].gsub!(PRERELEASE_VERSION_PLACEHOLDER, prerelease_version) if migrations_hash.key?(TO_VERSION_KEY)
37
+ migrations_hash.fetch(MIGRATIONS_KEY, []).each do |migration|
38
+ migration.fetch(MIGRATIONS_RULES_KEY, []).each do |rule|
39
+ next unless updates_product_version?(rule)
40
+ rule[MIGRATIONS_RULES_TO_KEY].gsub!(PRERELEASE_VERSION_PLACEHOLDER, prerelease_version)
41
+ end
42
+ end
43
+ migrations_hash
44
+ end
45
+
46
+ private
47
+
48
+ attr_reader :product_directory_path, :cycle
49
+
50
+ def updates_product_version?(rule_hash)
51
+ rule_hash['type'] == 'update' && rule_hash['selector'] == 'product_version'
52
+ end
53
+
54
+ def prerelease_version
55
+ @prerelease_version ||= ".#{cycle}.#{commit_number}.#{short_sha}"
56
+ end
57
+
58
+ def commit_number
59
+ git_inspector.commit_count
60
+ end
61
+
62
+ def short_sha
63
+ git_inspector.short_sha
64
+ end
65
+
66
+ def git_inspector
67
+ @git_inspector ||= GitInspector.new(product_directory_path)
68
+ end
69
+ end
70
+ end
71
+
72
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
73
+ # All rights reserved.
74
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
75
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
76
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
77
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
78
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
79
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,98 @@
1
+ require 'vara/product_metadata'
2
+ require 'vara/product_resource_downloader'
3
+ require 'vara/product_artifact_zipper'
4
+ require 'vara/product_contents'
5
+ require 'vara/md5_creator'
6
+ require 'vara/materials'
7
+
8
+ module Vara
9
+ class Product
10
+ METADATA_DIR = 'metadata'.freeze
11
+ METADATA_PARTS_DIR = 'metadata_parts'.freeze
12
+
13
+ attr_reader :base_dir
14
+
15
+ def initialize(base_dir)
16
+ @base_dir = base_dir
17
+ end
18
+
19
+ def metadata_file
20
+ @metadata_file ||= find_metadata_file || fail('No metadata file found.')
21
+ end
22
+
23
+ def build
24
+ if metadata.explicit_stemcell? && metadata.stemcell_criteria?
25
+ fail 'binaries.yml includes both stemcell and stemcell criteria keys'
26
+ end
27
+
28
+ ProductArtifactZipper.new(path, ProductContents.from_metadata_path(metadata_file)).zip!
29
+
30
+ MD5Creator.md5(path)
31
+
32
+ Materials.build(metadata_file, path).save_to(bom_path)
33
+
34
+ path
35
+ end
36
+
37
+ def path
38
+ File.join(base_dir, "#{filename_components.join('-')}.pivotal")
39
+ end
40
+
41
+ def bom_path
42
+ "#{path}.yml"
43
+ end
44
+
45
+ def md5_path
46
+ "#{path}.md5"
47
+ end
48
+
49
+ def stemcell_version
50
+ metadata.stemcell_metadata.version
51
+ end
52
+
53
+ def metadata_ref
54
+ `cd #{base_dir} && git log -1 --format=format:%h`
55
+ end
56
+
57
+ def releases
58
+ metadata.releases_metadata.map do |release_metadata|
59
+ {
60
+ 'name' => release_metadata['name'],
61
+ 'version' => release_metadata['version']
62
+ }
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def metadata
69
+ ProductMetadata.from_file(metadata_file)
70
+ end
71
+
72
+ def filename_components
73
+ [metadata.name, metadata.product_version]
74
+ end
75
+
76
+ def find_metadata_file
77
+ files = Dir.glob(File.join(base_dir, METADATA_DIR, '*.yml')).sort
78
+
79
+ case files.size
80
+ when 0 then
81
+ nil
82
+ when 1 then
83
+ files.first
84
+ else
85
+ fail("Found: #{files.map { |f| File.basename(f) }}. Vara supports one .yml file under metadata/")
86
+ end
87
+ end
88
+ end
89
+ end
90
+
91
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
92
+ # All rights reserved.
93
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
94
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
95
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
96
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
97
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
98
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,32 @@
1
+ module Vara
2
+ class ProductArtifactValidator
3
+ def self.validate_file_checksum(file_metadata, file_name)
4
+ fail "No checksum for file #{file_name}!" unless file_metadata.md5 || file_metadata.sha1
5
+
6
+ validate_md5(file_metadata, file_name) if file_metadata.md5
7
+
8
+ validate_sha1(file_metadata, file_name) if file_metadata.sha1
9
+ end
10
+
11
+ def self.validate_sha1(file_metadata, file_name)
12
+ sha1_got = Digest::SHA1.file(file_name).hexdigest
13
+ sha1_expected = file_metadata.sha1
14
+ fail "sha1 mismatch for file #{file_name}, expected #{sha1_expected}, got #{sha1_got}" if sha1_got != sha1_expected
15
+ end
16
+
17
+ def self.validate_md5(file_metadata, file_name)
18
+ md5_got = Digest::MD5.file(file_name).hexdigest
19
+ md5_expected = file_metadata.md5
20
+ fail "md5 mismatch for file #{file_name}, expected #{md5_expected}, got #{md5_got}" if md5_got != md5_expected
21
+ end
22
+ end
23
+ end
24
+
25
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
26
+ # All rights reserved.
27
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
28
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
29
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
31
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
32
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.