diff --git a/src/api/CliApiFacadeFactory.ts b/src/api/CliApiFacadeFactory.ts index d3ffa3b..8b98b6d 100644 --- a/src/api/CliApiFacadeFactory.ts +++ b/src/api/CliApiFacadeFactory.ts @@ -35,7 +35,8 @@ import { TerraformDocsCliFacade } from "./terraform-docs/TerraformDocsCliFacade. import { CollieRepository } from "../model/CollieRepository.ts"; import { GitCliDetector } from "./git/GitCliDetector.ts"; import { GitCliFacade } from "./git/GitCliFacade.ts"; -import { TerraformCliFacade } from "./terraform/TerraformCliFacade.ts"; +import { TofuOrTerraformCliDetector } from "./terraform/TofuOrTerraformCliDetector.ts"; +import { OpenTofuCliDetector } from "./terraform/OpenTofuCliDetector.ts"; export class CliApiFacadeFactory { constructor( @@ -49,7 +50,10 @@ export class CliApiFacadeFactory { new AzCliDetector(processRunner), new GcloudCliDetector(processRunner), new GitCliDetector(processRunner), - new TerraformCliDetector(processRunner), + new TofuOrTerraformCliDetector( + new OpenTofuCliDetector(processRunner), + new TerraformCliDetector(processRunner), + ), new TerragruntCliDetector(processRunner), new TerraformDocsCliDetector(processRunner), new NpmCliDetector(processRunner), diff --git a/src/api/CliDetector.ts b/src/api/CliDetector.ts index a61cdcc..41e3723 100644 --- a/src/api/CliDetector.ts +++ b/src/api/CliDetector.ts @@ -19,7 +19,12 @@ export type CliDetectionResult = info: string; }; -export abstract class CliDetector { +export interface ICliDetector { + tryRaiseInstallationStatusError(): Promise; + detect(): Promise; +} + +export abstract class CliDetector implements ICliDetector { constructor( protected readonly cli: string, protected readonly runner: IProcessRunner, diff --git a/src/api/terraform/OpenTofuCliDetector.ts b/src/api/terraform/OpenTofuCliDetector.ts new file mode 100644 index 0000000..c7c9326 --- /dev/null +++ b/src/api/terraform/OpenTofuCliDetector.ts @@ -0,0 +1,17 @@ +import { IProcessRunner } from "../../process/IProcessRunner.ts"; +import { ProcessResultWithOutput } from "../../process/ProcessRunnerResult.ts"; +import { CliDetector } from "../CliDetector.ts"; + +export class OpenTofuCliDetector extends CliDetector { + constructor(runner: IProcessRunner) { + super("tofu", runner); + } + + protected parseVersion(versionCmdOutput: string): string { + return versionCmdOutput.split("\n")[0].substring("OpenTofu ".length); + } + + protected isSupportedVersion(version: string): boolean { + return CliDetector.testSemverSatisfiesRange(version, ">=1.0.0"); + } +} diff --git a/src/api/terraform/TofuOrTerraformCliDetector.ts b/src/api/terraform/TofuOrTerraformCliDetector.ts new file mode 100644 index 0000000..4d0c168 --- /dev/null +++ b/src/api/terraform/TofuOrTerraformCliDetector.ts @@ -0,0 +1,32 @@ +import { CliDetectionResult, ICliDetector } from "../CliDetector.ts"; +import { InstallationStatus } from "/api/CliInstallationStatus.ts"; +import { CliInstallationStatusError } from "/errors.ts"; +import { OpenTofuCliDetector } from "./OpenTofuCliDetector.ts"; +import { TerraformCliDetector } from "./TerraformCliDetector.ts"; + +export class TofuOrTerraformCliDetector implements ICliDetector { + constructor( + private readonly tofu: OpenTofuCliDetector, + private readonly terraform: TerraformCliDetector, + ) { + } + async detect(): Promise { + const tofuResult = await this.tofu.detect(); + if (tofuResult.status === InstallationStatus.Installed) { + return tofuResult; + } + + return this.terraform.detect(); + } + + async tryRaiseInstallationStatusError() { + const { status } = await this.detect(); + switch (status) { + case InstallationStatus.Installed: + break; + case InstallationStatus.NotInstalled: + case InstallationStatus.UnsupportedVersion: + throw new CliInstallationStatusError("tofu or terraform", status); + } + } +}