Class: Fig::Protocol::Artifactory
- Inherits:
-
Object
- Object
- Fig::Protocol::Artifactory
- Includes:
- Fig::Protocol, NetRCEnabled
- Defined in:
- lib/fig/protocol/artifactory.rb
Overview
file transfers/storage using https as the transport and artifactory as the backing store
Constant Summary collapse
- BROWSER_API_PATH =
Artifactory browser API endpoint (undocumented API)
'ui/api/v1/ui/v2/nativeBrowser/'- INITIAL_LIST_FETCH_SIZE =
Default number of list entries to fetch on initial iteration
20000
Instance Method Summary collapse
- #download(art_uri, path, prompt_for_login) ⇒ Object
-
#download_list(uri) ⇒ Object
must return a list of strings in the form <package_name>/<version>.
-
#initialize ⇒ Artifactory
constructor
A new instance of Artifactory.
-
#path_up_to_date?(uri, path, prompt_for_login) ⇒ Boolean
we can know this most of the time with the stat api.
- #upload(local_file, uri) ⇒ Object
Constructor Details
#initialize ⇒ Artifactory
Returns a new instance of Artifactory.
35 36 37 |
# File 'lib/fig/protocol/artifactory.rb', line 35 def initialize initialize_netrc end |
Instance Method Details
#download(art_uri, path, prompt_for_login) ⇒ Object
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 |
# File 'lib/fig/protocol/artifactory.rb', line 82 def download(art_uri, path, prompt_for_login) Fig::Logging.info("Downloading from artifactory: #{art_uri}") uri = httpify_uri(art_uri) # Log equivalent curl command for debugging authentication = get_authentication_for(uri.host, prompt_for_login) if authentication Fig::Logging.debug("Equivalent curl: curl -u #{authentication.username}:*** -o '#{path}' '#{uri}'") else Fig::Logging.debug("Equivalent curl: curl -o '#{path}' '#{uri}'") end ::File.open(path, 'wb') do |file| file.binmode begin download_via_http_get(uri.to_s, file) rescue SystemCallError => error Fig::Logging.debug error. raise Fig::FileNotFoundError.new error., uri rescue SocketError => error Fig::Logging.debug error. raise Fig::FileNotFoundError.new error., uri end end return true end |
#download_list(uri) ⇒ Object
must return a list of strings in the form <package_name>/<version>
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 |
# File 'lib/fig/protocol/artifactory.rb', line 40 def download_list(uri) Fig::Logging.info("Downloading list of packages at #{uri}") package_versions = [] begin # Parse URI to extract base endpoint and repository key # Expected format: https://artifacts.example.com/artifactory/repo-name/ parse_uri(uri) => { repo_key:, base_endpoint: } # Create Artifactory client instance authentication = get_authentication_for(uri.host, :prompt_for_login) client_config = { endpoint: base_endpoint } if authentication client_config[:username] = authentication.username client_config[:password] = authentication.password end client = ::Artifactory::Client.new(client_config) # Use Artifactory browser API to list directories at repo root list_url = URI.join(base_endpoint, BROWSER_API_PATH, "#{repo_key}/") packages = get_all_artifactory_entries(list_url, client) # Filter to only valid package names upfront valid_packages = packages.select do |package_item| package_item['folder'] && package_item['name'] =~ Fig::PackageDescriptor::COMPONENT_PATTERN end Fig::Logging.debug("Found #{valid_packages.size} valid packages, fetching versions concurrently...") # Use concurrent requests to fetch version lists (major performance improvement) package_versions = fetch_versions_concurrently(valid_packages, base_endpoint, repo_key, client_config) rescue => e # Follow FTP pattern: log error but don't fail completely Fig::Logging.debug("Could not retrieve package list from #{uri}: #{e.}") end return package_versions.sort end |
#path_up_to_date?(uri, path, prompt_for_login) ⇒ Boolean
we can know this most of the time with the stat api
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/fig/protocol/artifactory.rb', line 158 def path_up_to_date?(uri, path, prompt_for_login) Fig::Logging.info("Checking if #{path} is up to date at #{uri}") begin parse_uri(uri) => { repo_key:, base_endpoint:, target_path: } # Create Artifactory client instance (same as upload method) authentication = get_authentication_for(uri.host, prompt_for_login) client_config = { endpoint: base_endpoint } if authentication client_config[:username] = authentication.username client_config[:password] = authentication.password end client = ::Artifactory::Client.new(client_config) # use storage api instead of search - more reliable for virtual repos storage_url = "/api/storage/#{repo_key}/#{target_path}" response = client.get(storage_url) # compare sizes first remote_size = response['size'].to_i if remote_size != ::File.size(path) # TODO VERBOSE return false end # compare modification times remote_mtime = Time.parse(response['lastModified']) local_mtime = ::File.mtime(path) if remote_mtime <= local_mtime return true end # TODO VERBOSE return false rescue => error Fig::Logging.debug "Error checking if #{path} is up to date: #{error.}" return nil end end |
#upload(local_file, uri) ⇒ Object
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 |
# File 'lib/fig/protocol/artifactory.rb', line 112 def upload(local_file, uri) Fig::Logging.info("Uploading #{local_file} to artifactory at #{uri}") begin parse_uri(uri) => { repo_key:, base_endpoint:, target_path: } # Configure Artifactory gem globally - unlike other methods that can use client instances, # the artifact.upload() method ignores the client: parameter and only uses global config. # This is a limitation of the artifactory gem's upload implementation. authentication = get_authentication_for(uri.host, :prompt_for_login) ::Artifactory.configure do |config| config.endpoint = base_endpoint if authentication config.username = authentication.username config.password = authentication.password end end # Log equivalent curl command for debugging if authentication Fig::Logging.debug("Equivalent curl: curl -u #{authentication.username}:*** -T '#{local_file}' '#{uri}'") else Fig::Logging.debug("Equivalent curl: curl -T '#{local_file}' '#{uri}'") end # Create artifact and upload artifact = ::Artifactory::Resource::Artifact.new(local_path: local_file) # Collect metadata for upload = (local_file, target_path, uri) # Upload with metadata (no client parameter needed - uses global config) artifact.upload(repo_key, target_path, ) Fig::Logging.info("Successfully uploaded #{local_file} to #{uri}") rescue ArgumentError => e # Let ArgumentError bubble up for invalid URIs raise e rescue => e Fig::Logging.debug("Upload failed: #{e.}") raise Fig::NetworkError.new("Failed to upload #{local_file} to #{uri}: #{e.}") end end |