From d4d553e25a6ba617ad14c0ef3738a0b5aa2a6bc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Przemys=C5=82aw=20Niekra=C5=9B?= Date: Thu, 10 Oct 2019 13:29:28 +0200 Subject: [PATCH] Add Artifactory Fetcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow to search for latest created artifact in artifactory Signed-off-by: Przemysław Niekraś --- lib/omnibus.rb | 11 +-- lib/omnibus/fetcher.rb | 4 +- lib/omnibus/fetchers/artifactory_fetcher.rb | 93 +++++++++++++++++++++ lib/omnibus/software.rb | 3 +- 4 files changed, 104 insertions(+), 7 deletions(-) create mode 100644 lib/omnibus/fetchers/artifactory_fetcher.rb diff --git a/lib/omnibus.rb b/lib/omnibus.rb index 2dc7a8942..7f282f5a6 100644 --- a/lib/omnibus.rb +++ b/lib/omnibus.rb @@ -63,11 +63,12 @@ module Omnibus autoload :ThreadPool, "omnibus/thread_pool" autoload :Licensing, "omnibus/licensing" - autoload :GitFetcher, "omnibus/fetchers/git_fetcher" - autoload :NetFetcher, "omnibus/fetchers/net_fetcher" - autoload :NullFetcher, "omnibus/fetchers/null_fetcher" - autoload :PathFetcher, "omnibus/fetchers/path_fetcher" - autoload :FileFetcher, "omnibus/fetchers/file_fetcher" + autoload :GitFetcher, "omnibus/fetchers/git_fetcher" + autoload :NetFetcher, "omnibus/fetchers/net_fetcher" + autoload :ArtifactoryFetcher, "omnibus/fetchers/artifactory_fetcher" + autoload :NullFetcher, "omnibus/fetchers/null_fetcher" + autoload :PathFetcher, "omnibus/fetchers/path_fetcher" + autoload :FileFetcher, "omnibus/fetchers/file_fetcher" autoload :ArtifactoryPublisher, "omnibus/publishers/artifactory_publisher" autoload :NullPublisher, "omnibus/publishers/null_publisher" diff --git a/lib/omnibus/fetcher.rb b/lib/omnibus/fetcher.rb index 56c1f1a88..1128dbffe 100644 --- a/lib/omnibus/fetcher.rb +++ b/lib/omnibus/fetcher.rb @@ -187,7 +187,9 @@ def self.resolve_version(version, source) def self.fetcher_class_for_source(source) if source - if source[:url] + if source[:repository] + ArtifactoryFetcher + elsif source[:url] NetFetcher elsif source[:git] GitFetcher diff --git a/lib/omnibus/fetchers/artifactory_fetcher.rb b/lib/omnibus/fetchers/artifactory_fetcher.rb new file mode 100644 index 000000000..3ed5c0193 --- /dev/null +++ b/lib/omnibus/fetchers/artifactory_fetcher.rb @@ -0,0 +1,93 @@ +# +# Copyright 2012-2018 Chef Software, Inc. +# +# 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. +# + +require "fileutils" +require "omnibus/download_helpers" + +module Omnibus + class ArtifactoryFetcher < NetFetcher + private + + # + # A find_url is required if the search in artifactory is required to find its file name + # + # @return [String] + # + def find_source_url + require "base64" + require("digest") + require("artifactory") + + log.info(:info) { "Searching Artifactory for #{source[:path]}/#{source[:filename_pattern]} in #{source[:repository]} " } + + endpoint = source[:endpoint] || ENV["ARTIFACTORY_ENDPOINT"] || nil + raise "Artifactory endpoint not configured" if endpoint.nil? + + Artifactory.endpoint = endpoint + Artifactory.api_key = source[:authorization ] if source[:authorization] + + unless source.key?(:authorization) + username = ENV["ARTIFACTORY_USERNAME"] || nil + password = ENV["ARTIFACTORY_PASSWORD"] || nil + error_message = "You have to provide either source[:authorization] or environment variables for artifactory client" + raise error_message if username.nil? || password.nil? + + source[:authorization] = "Basic #{Base64.encode64("#{username}:#{password}")}" + end + + query = <<~EOM + items.find( + { + "repo": {"$eq":"#{source[:repository]}"}, + "name": {"$match":"#{source[:filename_pattern]}"}, + "path": {"$match":"#{source[:path]}"} + } + ).include("name", "repo", "created", "path", "actual_sha1").sort({"$desc" : ["created"]}).limit(1) + EOM + result = Artifactory.post("/api/search/aql", query, "Content-Type" => "text/plain") + results = result["results"] + + log.debug(:debug) { "Search Result #{result}" } + + raise "Unable to find #{source[:filename_pattern]} in #{source[:repository]}" if results.empty? + + artifact = results[0] + + source[:url] = "#{Artifactory.endpoint}/#{artifact['repo']}/#{artifact['path']}/#{artifact['name']}" + source[:sha1] = artifact["actual_sha1"] + + log.info(:info) { "Found Artifact #{source[:url]} #{source[:sha1]}" } + end + + # + # The path on disk to the downloaded asset. The filename is defined by + # +source :cached_name+. If ommited, then it comes from the software's + # +source :url+ value or from the artifactory search result for newest + # artifact + # + # @return [String] + # + def downloaded_file + unless source.key?(:url) + find_source_url + end + + filename = source[:cached_name] if source[:cached_name] + filename ||= File.basename(source[:url], "?*") + File.join(Config.cache_dir, filename) + end + end +end diff --git a/lib/omnibus/software.rb b/lib/omnibus/software.rb index a564d658f..ffebebf38 100644 --- a/lib/omnibus/software.rb +++ b/lib/omnibus/software.rb @@ -298,7 +298,8 @@ def source(val = NULL) :md5, :sha1, :sha256, :sha512, # hash type - common to all fetchers :cookie, :warning, :unsafe, :extract, :cached_name, :authorization, # used by net_fetcher :options, # used by path_fetcher - :submodules # used by git_fetcher + :submodules, # used by git_fetcher + :repository, :filename_pattern, :endpoint # used by artifactory_fetcher ] unless extra_keys.empty? raise InvalidValue.new(:source,