vara 0.17.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,110 @@
1
+ require 'tmpdir'
2
+ require 'vara/log'
3
+ require 'vara/product_artifact_validator'
4
+
5
+ module Vara
6
+ class ProductArtifactZipper
7
+ include Loggable
8
+
9
+ def initialize(artifact_path, product_contents)
10
+ @artifact_path = artifact_path
11
+ @product_contents = product_contents
12
+ end
13
+
14
+ def zip!
15
+ remove_previous_artifacts
16
+
17
+ in_tmp_dir do
18
+ copy_dirs_and_files
19
+ create_zip!
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :artifact_path, :product_contents
26
+
27
+ def remove_previous_artifacts
28
+ FileUtils.rm(artifact_path) if File.exist?(artifact_path)
29
+ end
30
+
31
+ def in_tmp_dir
32
+ Dir.mktmpdir do |temp_dir|
33
+ FileUtils.cd(temp_dir) do
34
+ yield
35
+ end
36
+ end
37
+ end
38
+
39
+ def copy_dirs_and_files
40
+ product_metadata = ProductMetadata.from_file(product_contents.metadata_path)
41
+
42
+ copy_and_validate_releases(product_metadata)
43
+
44
+ if product_metadata.explicit_stemcell?
45
+ copy_and_validate_stemcell(product_metadata)
46
+ copy_and_validate_compiled_packages(product_metadata)
47
+ end
48
+
49
+ FileUtils.mkdir('content_migrations')
50
+ FileUtils.cp(product_contents.content_migrations_path, 'content_migrations')
51
+
52
+ FileUtils.mkdir('metadata')
53
+ FileUtils.cp(product_contents.metadata_path, 'metadata')
54
+ end
55
+
56
+ def copy_and_validate_releases(product_metadata)
57
+ FileUtils.mkdir('releases')
58
+
59
+ product_contents.release_paths.each do |release_path|
60
+ FileUtils.cp(release_path, 'releases')
61
+ end
62
+
63
+ product_metadata.releases_metadata.each do |release_metadata|
64
+ ProductArtifactValidator.validate_file_checksum(
65
+ release_metadata,
66
+ File.join('releases', release_metadata.basename)
67
+ )
68
+ end
69
+ end
70
+
71
+ def copy_and_validate_stemcell(product_metadata)
72
+ FileUtils.mkdir('stemcells')
73
+ FileUtils.cp(product_contents.stemcell_path, 'stemcells')
74
+
75
+ ProductArtifactValidator.validate_file_checksum(
76
+ product_metadata.stemcell_metadata,
77
+ File.join('stemcells', product_metadata.stemcell_file)
78
+ )
79
+ end
80
+
81
+ def copy_and_validate_compiled_packages(product_metadata)
82
+ return unless product_contents.has_compiled_packages?
83
+
84
+ FileUtils.mkdir('compiled_packages')
85
+ FileUtils.cp(product_contents.compiled_packages_path, 'compiled_packages')
86
+
87
+ ProductArtifactValidator.validate_file_checksum(
88
+ product_metadata.compiled_packages_metadata,
89
+ File.join('compiled_packages', product_metadata.compiled_packages_file)
90
+ )
91
+ end
92
+
93
+ def create_zip!
94
+ log.info("Creating zip file #{artifact_path}")
95
+ # Split into two steps so that it works inside Docker on a mounted volume
96
+ `zip -r -0 local.pivotal .`
97
+ FileUtils.mv('local.pivotal', artifact_path)
98
+ log.info('Finished creating zip file')
99
+ end
100
+ end
101
+ end
102
+
103
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
104
+ # All rights reserved.
105
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
106
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
107
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
108
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
109
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
110
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ require 'vara/product_metadata'
2
+
3
+ module Vara
4
+ class ProductContents
5
+ # @param metadata_path [String] The path on disk to the metadata YAML file
6
+ # @return [Vara::ProductContents]
7
+ def self.from_metadata_path(metadata_path)
8
+ new(metadata_path, ProductMetadata.from_file(metadata_path))
9
+ end
10
+
11
+ attr_reader :metadata_path
12
+
13
+ # @param metadata_path [String] The path on disk to the metadata YAML file
14
+ # @param product_metadata [Vara::ProductMetadata] The Product Metadata as represented in the metadata_path file
15
+ def initialize(metadata_path, product_metadata)
16
+ @metadata_path = File.expand_path(metadata_path).freeze
17
+ @product_metadata = product_metadata
18
+ end
19
+
20
+ # @return [String] The path to the content migration file on disk
21
+ def content_migrations_path
22
+ paths = Dir.glob(File.expand_path(File.join(root_path, 'content_migrations', '*.yml')))
23
+ fail "Exactly one content_migrations file is required in #{root_path}/content_migrations" if paths.size != 1
24
+ paths.first
25
+ end
26
+
27
+ # @return [<String>] The paths to the release tarballs on disk
28
+ def release_paths
29
+ product_metadata.releases_metadata.map { |release_metadata| File.join(root_path, 'releases', release_metadata.basename) }
30
+ end
31
+
32
+ # @return [String] The path to the stemcell file on disk
33
+ def stemcell_path
34
+ File.join(root_path, 'stemcells', product_metadata.stemcell_file)
35
+ end
36
+
37
+ # @return [String] The path to the compiled packages file on disk
38
+ def compiled_packages_path
39
+ File.join(root_path, 'compiled_packages', product_metadata.compiled_packages_file)
40
+ end
41
+
42
+ # @return [Boolean] Whether the product metadata has a compiled packages field
43
+ def has_compiled_packages?
44
+ product_metadata.has_compiled_packages?
45
+ end
46
+
47
+ private
48
+
49
+ def root_path
50
+ File.expand_path(File.join(metadata_path, '..', '..'))
51
+ end
52
+
53
+ attr_reader :product_metadata
54
+ end
55
+ end
56
+
57
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
58
+ # All rights reserved.
59
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
60
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
61
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
62
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
63
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
64
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,113 @@
1
+ require 'yaml'
2
+ require 'vara/metadata/stemcell'
3
+ require 'vara/metadata/release'
4
+ require 'vara/metadata/compiled_packages'
5
+
6
+ module Vara
7
+ # "Struct" representing the information in metadata/<product_name>.yml
8
+ class ProductMetadata
9
+ # Build a ProductMetadata from a metadata.yml on disk
10
+ # @param metadata_path Path to the product metadata file on disk
11
+ # @return [Vara::ProductMetadata]
12
+ def self.from_file(metadata_path)
13
+ new(YAML.load_file(metadata_path))
14
+ end
15
+
16
+ # @param hash [Hash] the hash representing the product metadata
17
+ def initialize(hash)
18
+ @hash = hash
19
+ end
20
+
21
+ def explicit_stemcell?
22
+ hash.key? 'stemcell'
23
+ end
24
+
25
+ def stemcell_criteria
26
+ return nil if explicit_stemcell?
27
+ hash.fetch('stemcell_criteria')
28
+ end
29
+
30
+ def stemcell_criteria?
31
+ hash.key? 'stemcell_criteria'
32
+ end
33
+
34
+ # @return [Vara::Metadata::Stemcell] the stemcell metadata contained in this ProductMetadata
35
+ def stemcell_metadata
36
+ stemcell = hash.fetch('stemcell')
37
+ Metadata::Stemcell.new(
38
+ name: stemcell.fetch('name'),
39
+ version: stemcell.fetch('version'),
40
+ file: stemcell.fetch('file'),
41
+ md5: stemcell.fetch('md5', nil),
42
+ sha1: stemcell.fetch('sha1', nil)
43
+ )
44
+ end
45
+
46
+ # @return [<Vara::Metadata::Release>] the releases metadata contained in this ProductMetadata
47
+ def releases_metadata
48
+ releases = hash.fetch('releases')
49
+ releases.map { |release| release_metadata(release) }
50
+ end
51
+
52
+ # @raise [KeyNotFoundError] if this ProductMetadata does not contain compiled packages
53
+ # @return [Vara::Metadata::CompiledPackages] the compiled packages metadata contained in this ProductMetadata
54
+ def compiled_packages_metadata
55
+ c = hash.fetch('compiled_package')
56
+ Metadata::CompiledPackages.new(
57
+ c.fetch('name'), c.fetch('version'), c.fetch('file'), c.fetch('md5'), c.fetch('url', nil)
58
+ )
59
+ end
60
+
61
+ # @return [String] the filename of the stemcell
62
+ def stemcell_file
63
+ stemcell_metadata.basename
64
+ end
65
+
66
+ # @return [String] the name of the product
67
+ def name
68
+ hash.fetch('name')
69
+ end
70
+
71
+ # @return [String] the version of the product
72
+ def product_version
73
+ hash.fetch('product_version')
74
+ end
75
+
76
+ # @return [String] the filename of the compiled packages
77
+ def compiled_packages_file
78
+ compiled_packages_metadata.basename
79
+ end
80
+
81
+ # @return [Boolean] whether the compiled packages field is present
82
+ def has_compiled_packages?
83
+ hash.key?('compiled_package')
84
+ end
85
+
86
+ private
87
+
88
+ attr_reader :hash
89
+
90
+ # @return [Vara::Metadata::Release]
91
+ def release_metadata(release_hash)
92
+ release = release_hash
93
+ Metadata::Release.new(
94
+ name: release.fetch('name'),
95
+ version: release.fetch('version'),
96
+ file: release.fetch('file'),
97
+ md5: release.fetch('md5', nil),
98
+ sha1: release.fetch('sha1', nil),
99
+ url: release.fetch('url', nil),
100
+ aws: release.fetch('aws', nil)
101
+ )
102
+ end
103
+ end
104
+ end
105
+
106
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
107
+ # All rights reserved.
108
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
109
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
110
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
111
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
112
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
113
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,98 @@
1
+ require 'yaml'
2
+ require 'vara/log'
3
+
4
+ module Vara
5
+ class ProductMetadataProcessor
6
+ include Vara::Loggable
7
+
8
+ # @param product_dir [String] path to product directory root
9
+ # @param versioner [Vara::PrereleaseVersioner,Vara::StaticVersioner]
10
+ def initialize(product_dir, versioner, external_release_paths: [])
11
+ @product_dir = product_dir
12
+ @versioner = versioner
13
+ @external_release_paths = external_release_paths
14
+ end
15
+
16
+ # Composes metadata_parts/binaries.yml and metadata_parts/handcraft.yml into the properly named product metadata
17
+ # file under metadata/, expanding placeholders as necessary
18
+ # @return [String] The path to the generated metadata file
19
+ def process
20
+ metadata = merged_metadata
21
+
22
+ external_release_paths.each do |external_release_path|
23
+ update_release(external_release_path, metadata)
24
+ end
25
+
26
+ processed = versioner.update_metadata(metadata)
27
+ save_processed_metadata(processed)
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :product_dir, :versioner, :external_release_paths
33
+
34
+ ALLOWED_RELEASE_KEYS = %w(file name url md5 version)
35
+
36
+ def merged_metadata
37
+ binaries_path = File.join(product_dir, 'metadata_parts', 'binaries.yml')
38
+ binaries = YAML.load_file(binaries_path)
39
+ log.info("Composing metadata: loaded #{binaries_path}")
40
+
41
+ handcraft_path = File.join(product_dir, 'metadata_parts', 'handcraft.yml')
42
+ handcraft = YAML.load_file(handcraft_path)
43
+ log.info("Composing metadata: loaded #{handcraft_path}")
44
+
45
+ binaries.merge(handcraft)
46
+ end
47
+
48
+ def update_release(external_release_path, metadata)
49
+ log.info("Updating metadata: using #{File.expand_path(external_release_path)}")
50
+
51
+ external_releases = YAML.load_file(external_release_path)
52
+
53
+ external_releases.each do |release|
54
+ external_release = validate_release(release, external_release_path)
55
+
56
+ replace = metadata['releases'].find_index do |r|
57
+ r['name'] == external_release['name']
58
+ end
59
+
60
+ fail "Specified release #{external_release['name']} does not exist in binaries.yml" unless replace
61
+
62
+ metadata['releases'][replace] = external_release
63
+ end
64
+ end
65
+
66
+ def validate_release(external_release, external_release_path)
67
+ missing_keys = ALLOWED_RELEASE_KEYS - external_release.keys.to_a
68
+ fail "Specified release #{File.basename(external_release_path)} is missing keywords: #{missing_keys}" unless missing_keys.empty?
69
+ extra_keys = external_release.keys.to_a - ALLOWED_RELEASE_KEYS
70
+ fail "Specified release #{File.basename(external_release_path)} has extra keywords: #{extra_keys}" unless extra_keys.empty?
71
+ external_release
72
+ end
73
+
74
+ def save_processed_metadata(processed_metadata_hash)
75
+ product_name = processed_metadata_hash.fetch('name').tr('-', '_')
76
+ metadata_dir = File.join(product_dir, 'metadata')
77
+
78
+ FileUtils.mkdir_p(metadata_dir)
79
+
80
+ out_path = File.join(metadata_dir, "#{product_name}.yml")
81
+
82
+ File.open(out_path, 'w') do |out|
83
+ YAML.dump(processed_metadata_hash, out)
84
+ end
85
+
86
+ out_path
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,69 @@
1
+ require 'vara/product_metadata'
2
+ require 'vara/tarball'
3
+
4
+ module Vara
5
+ class ProductResourceDownloader
6
+ def self.build(product_metadata_path)
7
+ product_metadata = Vara::ProductMetadata.from_file(product_metadata_path)
8
+ product_basedir = File.expand_path(File.join(File.dirname(product_metadata_path), '..'))
9
+ new(product_metadata, product_basedir)
10
+ end
11
+
12
+ attr_reader :product_basedir, :product_metadata
13
+
14
+ def initialize(product_metadata, product_basedir)
15
+ @product_basedir = product_basedir
16
+ @product_metadata = product_metadata
17
+ end
18
+
19
+ def download
20
+ if product_metadata.explicit_stemcell? && product_metadata.stemcell_criteria?
21
+ fail 'binaries.yml includes both stemcell and stemcell criteria keys'
22
+ end
23
+
24
+ if product_metadata.explicit_stemcell?
25
+ download_stemcell
26
+ download_compiled_packages
27
+ end
28
+
29
+ download_releases
30
+ end
31
+
32
+ private
33
+
34
+ def download_stemcell
35
+ stemcell_metadata = product_metadata.stemcell_metadata
36
+ stemcell_directory = File.join(product_basedir, 'stemcells')
37
+ stemcell = Vara::Tarball.new(stemcell_metadata, stemcell_directory)
38
+ stemcell.sync_local_copy
39
+ end
40
+
41
+ def download_releases
42
+ releases_metadata = product_metadata.releases_metadata
43
+
44
+ releases_metadata.each do |release_metadata|
45
+ release_directory = File.join(product_basedir, 'releases')
46
+ release = Vara::Tarball.new(release_metadata, release_directory)
47
+ release.sync_local_copy
48
+ end
49
+ end
50
+
51
+ def download_compiled_packages
52
+ return unless product_metadata.has_compiled_packages?
53
+
54
+ compiled_packages_metadata = product_metadata.compiled_packages_metadata
55
+ compiled_packages_dir = File.join(product_basedir, 'compiled_packages')
56
+ compiled_package = Vara::Tarball.new(compiled_packages_metadata, compiled_packages_dir)
57
+ compiled_package.sync_local_copy
58
+ end
59
+ end
60
+ end
61
+
62
+ # Copyright (c) 2014-2015 Pivotal Software, Inc.
63
+ # All rights reserved.
64
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
65
+ # INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
66
+ # PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
67
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
68
+ # TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
69
+ # USE OR OTHER DEALINGS IN THE SOFTWARE.