lib/mixlib/install/backend/artifactory.rb in mixlib-install-0.8.0.alpha.3 vs lib/mixlib/install/backend/artifactory.rb in mixlib-install-0.8.0.alpha.4
- old
+ new
@@ -25,10 +25,11 @@
class Install
class Backend
class Artifactory
class ConnectionError < StandardError; end
class AuthenticationError < StandardError; end
+ class NoArtifactsError < StandardError; end
ENDPOINT = "http://artifactory.chef.co".freeze
attr_accessor :options
@@ -42,53 +43,102 @@
# channel, product name, and product version.
# @return [ArtifactInfo] arifact info for the configured
# channel, product name, product version and platform info
#
def info
- artifacts = artifactory_info.collect { |a| create_artifact(a) }
-
- artifacts_for_version = artifacts.find_all do |a|
- a.version == options.resolved_version(artifacts)
+ artifacts = if options.latest_version?
+ artifactory_latest
+ else
+ artifactory_artifacts(options.product_version)
end
if options.platform
- artifacts_for_version.find do |a|
+ artifacts.select! do |a|
a.platform == options.platform &&
a.platform_version == options.platform_version &&
a.architecture == options.architecture
end
- else
- artifacts_for_version
end
+
+ artifacts.length == 1 ? artifacts.first : artifacts
end
- # Fetches all artifacts from the configured Artifactory repository using
- # channel and product name as search criteria
#
- # @return [Array<Hash>] list of artifactory hash data
+ # Get artifacts for the latest version, channel and product_name
#
- # Hash data:
- # download_uri: The full url download path
- # <property_name>: The names of the properties associcated to the artifact
+ # @return [Array<ArtifactInfo>] Array of info about found artifacts
+ def artifactory_latest
+ # Get the list of builds from the REST api.
+ # We do this because a user in the readers group does not have
+ # permissions to run aql against builds.
+ builds = client.get("/api/build/#{options.product_name}")
+
+ if builds.nil?
+ raise NoArtifactsError, <<-MSG
+Can not find any builds for #{options.product_name} in #{::Artifactory.endpoint}.
+ MSG
+ end
+
+ # Output we get is something like:
+ # {
+ # "buildsNumbers": [
+ # {"uri"=>"/12.5.1+20151213083009", "started"=>"2015-12-13T08:40:19.238+0000"},
+ # {"uri"=>"/12.6.0+20160111212038", "started"=>"2016-01-12T00:25:35.762+0000"},
+ # ...
+ # ]
+ # }
+ # First we sort based on started
+ builds["buildsNumbers"].sort_by! { |b| b["started"] }.reverse!
+
+ # Now check if the build is in the requested channel or not
+ # Note that if you do this for any channel other than :unstable
+ # it will run a high number of queries but it is fine because we
+ # are using artifactory only for :unstable channel
+ builds["buildsNumbers"].each do |build|
+ version = build["uri"].gsub("/", "")
+ artifacts = artifactory_artifacts(version)
+
+ return artifacts unless artifacts.empty?
+ end
+
+ # we could not find any matching artifacts
+ []
+ end
+
#
- def artifactory_info
- query = <<-QUERY
+ # Get artifacts for a given version, channel and product_name
+ #
+ # @return [Array<ArtifactInfo>] Array of info about found artifacts
+ def artifactory_artifacts(version)
+ results = artifactory_query(<<-QUERY)
items.find(
{"repo": "omnibus-#{options.channel}-local"},
- {"@omnibus.project": "#{options.product_name}"}
+ {"@omnibus.project": "#{options.product_name}"},
+ {"@omnibus.version": "#{version}"}
).include("repo", "path", "name", "property")
QUERY
- results = artifactory_request do
- client.post("/api/search/aql", query, "Content-Type" => "text/plain")
- end
-
# Merge artifactory properties and downloadUri to a flat Hash
- results["results"].collect do |result|
+ results.collect! do |result|
{ "downloadUri" => generate_download_uri(result) }.merge(
map_properties(result["properties"])
)
end
+
+ # Convert results to build records
+ results.map { |a| create_artifact(a) }
+ end
+
+ #
+ # Run an artifactory query for the given query.
+ #
+ # @return [Array<Hash>] Array of results returned from artifactory
+ def artifactory_query(query)
+ results = artifactory_request do
+ client.post("/api/search/aql", query, "Content-Type" => "text/plain")
+ end
+
+ results["results"]
end
def create_artifact(artifact_map)
ArtifactInfo.new(
md5: artifact_map["omnibus.md5"],