Skip to content
Snippets Groups Projects
index.ts 3 KiB
Newer Older
import { logger } from '../../logger';
import * as packageCache from '../../util/cache/package';
import { Http } from '../../util/http';
import { GetReleasesConfig, ReleaseResult } from '../common';

export const id = 'terraform-provider';
export const defaultRegistryUrls = [
  'https://registry.terraform.io',
  'https://releases.hashicorp.com',
];
export const registryStrategy = 'hunt';
const http = new Http(id);

interface TerraformProvider {
  namespace: string;
  name: string;
  provider: string;
  source?: string;
  versions: string[];
}

interface TerraformProviderReleaseBackend {
  [key: string]: {
    name: string;
    versions: VersionsReleaseBackend;
  };
}
interface VersionsReleaseBackend {
  [key: string]: Record<string, any>;
}

async function queryRegistry(
  lookupName: string,
  registryURL: string,
  repository: string
): Promise<ReleaseResult> {
  const backendURL = `${registryURL}/v1/providers/${repository}`;
  const res = (await http.getJson<TerraformProvider>(backendURL)).body;
  const dep: ReleaseResult = {
    name: repository,
    versions: {},
    releases: null,
  };
  if (res.source) {
    dep.sourceUrl = res.source;
  dep.releases = res.versions.map((version) => ({
    version,
  }));
  dep.homepage = `${registryURL}/providers/${repository}`;
  logger.trace({ dep }, 'dep');
  return dep;
}

async function queryReleaseBackend(
  lookupName: string,
  registryURL: string,
  repository: string
): Promise<ReleaseResult> {
  const backendLookUpName = `terraform-provider-${lookupName}`;
  const backendURL = registryURL + `/index.json`;
  const res = (await http.getJson<TerraformProviderReleaseBackend>(backendURL))
    .body;
  const dep: ReleaseResult = {
    name: repository,
    versions: {},
    releases: null,
  };
  dep.releases = Object.keys(res[backendLookUpName].versions).map(
    (version) => ({
      version,
    })
  );
  logger.trace({ dep }, 'dep');
  return dep;

/**
 * terraform-provider.getReleases
 *
 * This function will fetch a provider from the public Terraform registry and return all semver versions.
 */
export async function getReleases({
  lookupName,
  registryUrl,
}: GetReleasesConfig): Promise<ReleaseResult | null> {
  const repository = `hashicorp/${lookupName}`;

  const cacheNamespace = 'terraform-provider';
  const pkgUrl = `${registryUrl}/${repository}`;
  const cachedResult = await packageCache.get<ReleaseResult>(
    cacheNamespace,
    pkgUrl
  );
  // istanbul ignore if
  if (cachedResult) {
    return cachedResult;
  }

  logger.debug({ lookupName }, 'terraform-provider.getDependencies()');
  let dep: ReleaseResult = null;
  const registryHost = URL.parse(registryUrl).host;
  if (registryHost === 'registry.terraform.io') {
    dep = await queryRegistry(lookupName, registryUrl, repository);
  } else if (registryHost === 'releases.hashicorp.com') {
    dep = await queryReleaseBackend(lookupName, registryUrl, repository);
  }
  const cacheMinutes = 30;
  await packageCache.set(cacheNamespace, pkgUrl, dep, cacheMinutes);