/
package_release.rb
163 lines (136 loc) · 4.24 KB
/
package_release.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
#
# Copyright:: Copyright (c) 2012-2014 Chef Software, Inc.
# License:: Apache License, Version 2.0
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# internal
require 'omnibus/exceptions'
# stdlib
require 'json'
# external
require 'uber-s3'
module Omnibus
class PackageRelease
attr_reader :package_path
attr_reader :access_policy
# @param package_path [String] file system path to the package artifact
# @option opts [:private, :public_read] :access specifies access control on
# uploaded files
# @yield callback triggered by successful upload. Allows users of this
# class to add UI feedback.
# @yieldparam s3_object_key [String] the S3 key of the uploaded object.
def initialize(package_path, opts={:access=>:private}, &block)
@package_path = package_path
@metadata = nil
@s3_client = nil
@after_upload = if block_given?
block
else
lambda { |item_key| nil }
end
# sets @access_policy
handle_opts(opts)
end
# Primary API for this class. Validates S3 configuration and package files,
# then runs the upload.
# @return [void]
# @raise [NoPackageFile, NoPackageMetadataFile] when the package or
# associated metadata file do not exist.
# @raise [InvalidS3ReleaseConfiguration] when the Omnibus configuration is
# missing required settings.
# @raise Also may raise errors from uber-s3 or net/http.
def release
validate_config!
validate_package!
s3_client.store(metadata_key, metadata_json, :access => access_policy)
uploaded(metadata_key)
s3_client.store(package_key, package_content, :access => access_policy, :content_md5 => md5)
uploaded(package_key)
end
def uploaded(key)
@after_upload.call(key)
end
def package_key
File.join(platform_path, File.basename(package_path))
end
def metadata_key
File.join(platform_path, File.basename(package_metadata_path))
end
def platform_path
File.join(metadata["platform"], metadata["platform_version"], metadata["arch"])
end
def md5
metadata["md5"]
end
def metadata
@metadata ||= JSON.parse(metadata_json)
end
def metadata_json
IO.read(package_metadata_path)
end
def package_content
IO.read(package_path)
end
def package_metadata_path
"#{package_path}.metadata.json"
end
def validate_package!
if !File.exist?(package_path)
raise NoPackageFile.new(package_path)
elsif !File.exist?(package_metadata_path)
raise NoPackageMetadataFile.new(package_metadata_path)
else
true
end
end
def validate_config!
if s3_access_key && s3_secret_key && s3_bucket
true
else
err = InvalidS3ReleaseConfiguration.new(s3_bucket, s3_access_key, s3_secret_key)
raise err
end
end
def s3_client
@s3_client ||= UberS3.new(
:access_key => s3_access_key,
:secret_access_key => s3_secret_key,
:bucket => s3_bucket,
:adaper => :net_http
)
end
def s3_access_key
config[:release_s3_access_key]
end
def s3_secret_key
config[:release_s3_secret_key]
end
def s3_bucket
config[:release_s3_bucket]
end
def config
Omnibus.config
end
def handle_opts(opts)
access_policy = opts[:access]
if access_policy.nil?
raise ArgumentError, "options to #{self.class} must specify `:access' (given: #{opts.inspect})"
elsif not [:private, :public_read].include?(access_policy)
raise ArgumentError, "option `:access' must be one of `[:private, :public_read]' (given: #{access_policy.inspect})"
else
@access_policy = access_policy
end
end
end
end