class Dependabot::Terraform::RegistryClient
Terraform::RegistryClient
is a basic API client to interact with a terraform registry: www.terraform.io/docs/registry/api.html
Constants
- PUBLIC_HOSTNAME
Attributes
Public Class Methods
# File lib/dependabot/terraform/registry_client.rb, line 15 def initialize(hostname: PUBLIC_HOSTNAME, credentials: []) @hostname = hostname @tokens = credentials.each_with_object({}) do |item, memo| memo[item["host"]] = item["token"] if item["type"] == "terraform_registry" end end
Public Instance Methods
Fetch all the versions of a module, and return a Version
representation of them.
@param identifier [String] the identifier for the dependency, i.e: “hashicorp/consul/aws” @return [Array<Dependabot::Terraform::Version>] @raise [Dependabot::DependabotError] when the versions cannot be retrieved
# File lib/dependabot/terraform/registry_client.rb, line 45 def all_module_versions(identifier:) base_url = service_url_for("modules.v1") response = http_get!(URI.join(base_url, "#{identifier}/versions")) JSON.parse(response.body). fetch("modules").first.fetch("versions"). map { |release| version_class.new(release.fetch("version")) } end
Fetch all the versions of a provider, and return a Version
representation of them.
@param identifier [String] the identifier for the dependency, i.e: “hashicorp/aws” @return [Array<Dependabot::Terraform::Version>] @raise [Dependabot::DependabotError] when the versions cannot be retrieved
# File lib/dependabot/terraform/registry_client.rb, line 29 def all_provider_versions(identifier:) base_url = service_url_for("providers.v1") response = http_get!(URI.join(base_url, "#{identifier}/versions")) JSON.parse(response.body). fetch("versions"). map { |release| version_class.new(release.fetch("version")) } end
Perform service discovery and return the absolute URL for the requested service. www.terraform.io/docs/internals/remote-service-discovery.html
@param service_key [String] the service type described in www.terraform.io/docs/internals/remote-service-discovery.html#supported-services @param return String @raise [Dependabot::PrivateSourceAuthenticationFailure] when the service is not available
# File lib/dependabot/terraform/registry_client.rb, line 81 def service_url_for(service_key) url_for(services.fetch(service_key)) rescue KeyError raise Dependabot::PrivateSourceAuthenticationFailure, "Host does not support required Terraform-native service" end
Fetch the “source” for a module or provider. We use the API to fetch the source for a dependency, this typically points to a source code repository, and then instantiate a Dependabot::Source object that we can use to fetch Metadata about a specific version of the dependency.
@param dependency [Dependabot::Dependency] the dependency who's source we're attempting to find @return [nil, Dependabot::Source]
# File lib/dependabot/terraform/registry_client.rb, line 62 def source(dependency:) type = dependency.requirements.first[:source][:type] base_url = service_url_for(service_key_for(type)) response = http_get(URI.join(base_url, "#{dependency.name}/#{dependency.version}")) return nil unless response.status == 200 source_url = JSON.parse(response.body).fetch("source") Source.from_url(source_url) if source_url rescue JSON::ParserError, Excon::Error::Timeout nil end
Private Instance Methods
# File lib/dependabot/terraform/registry_client.rb, line 142 def error(message) Dependabot::DependabotError.new(message) end
# File lib/dependabot/terraform/registry_client.rb, line 95 def headers_for(hostname) token = tokens[hostname] token ? { "Authorization" => "Bearer #{token}" } : {} end
# File lib/dependabot/terraform/registry_client.rb, line 119 def http_get(url) Excon.get(url.to_s, idempotent: true, **SharedHelpers.excon_defaults(headers: headers_for(hostname))) end
# File lib/dependabot/terraform/registry_client.rb, line 123 def http_get!(url) response = http_get(url) raise Dependabot::PrivateSourceAuthenticationFailure, hostname if response.status == 401 raise error("Response from registry was #{response.status}") unless response.status == 200 response end
# File lib/dependabot/terraform/registry_client.rb, line 108 def service_key_for(type) case type when "module", "modules", "registry" "modules.v1" when "provider", "providers" "providers.v1" else raise error("Invalid source type") end end
# File lib/dependabot/terraform/registry_client.rb, line 100 def services @services ||= begin response = http_get(url_for("/.well-known/terraform.json")) response.status == 200 ? JSON.parse(response.body) : {} end end
# File lib/dependabot/terraform/registry_client.rb, line 132 def url_for(path) uri = URI.parse(path) return uri.to_s if uri.scheme == "https" raise error("Unsupported scheme provided") if uri.host && uri.scheme uri.host = hostname uri.scheme = "https" uri.to_s end
# File lib/dependabot/terraform/registry_client.rb, line 91 def version_class Version end