terrafaker 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +30 -25
  2. package/dist/commands/az/repo/clone.js +22 -0
  3. package/dist/commands/az/repo/delete.js +20 -0
  4. package/dist/commands/az/repo/list.js +13 -0
  5. package/dist/commands/generate/file.js +24 -19
  6. package/dist/commands/generate/repo.js +43 -36
  7. package/dist/commands/gh/repo/clone.js +7 -7
  8. package/dist/commands/gh/repo/delete.js +7 -7
  9. package/dist/commands/gh/repo/list.js +13 -0
  10. package/dist/commands/glab/repo/clone.js +7 -7
  11. package/dist/commands/glab/repo/delete.js +7 -7
  12. package/dist/commands/glab/repo/list.js +13 -0
  13. package/dist/commands/health.js +97 -0
  14. package/dist/enums/{providers.js → cloud-providers.js} +2 -2
  15. package/dist/enums/flag-names.js +19 -0
  16. package/dist/enums/help-messages.js +13 -3
  17. package/dist/enums/iac-types.js +5 -0
  18. package/dist/enums/vcs-providers.js +9 -3
  19. package/dist/utilities/azure.js +44 -0
  20. package/dist/utilities/base-command.js +62 -0
  21. package/dist/utilities/enum-utils.js +13 -0
  22. package/dist/utilities/flags.js +59 -13
  23. package/dist/utilities/generators/{aws-generator.js → aws-terraform-generator.js} +18 -20
  24. package/dist/utilities/generators/{azure-generator.js → azure-terraform-generator.js} +10 -10
  25. package/dist/utilities/generators/cloudformation-generator.js +103 -0
  26. package/dist/utilities/generators/file-generator.js +11 -8
  27. package/dist/utilities/generators/{gcp-generator.js → gcp-terraform-generator.js} +13 -13
  28. package/dist/utilities/generators/generator-factory.js +24 -0
  29. package/dist/utilities/generators/provider-generator.js +9 -35
  30. package/dist/utilities/generators/repo-generator.js +11 -6
  31. package/dist/utilities/generators/terraform-generator.js +44 -0
  32. package/dist/utilities/github.js +10 -5
  33. package/dist/utilities/gitlab.js +9 -4
  34. package/dist/utilities/random.js +91 -0
  35. package/dist/utilities/string-utils.js +54 -6
  36. package/dist/utilities/tag-utils.js +22 -18
  37. package/oclif.manifest.json +229 -35
  38. package/package.json +20 -1
  39. package/dist/topics/generate.js +0 -5
  40. package/dist/topics/gh.js +0 -6
  41. package/dist/topics/glab.js +0 -6
  42. package/dist/utilities/generators/generator-utils.js +0 -56
  43. package/dist/utilities/generators/provider-generator-factory.js +0 -18
package/README.md CHANGED
@@ -15,8 +15,8 @@ Obviously, you shouldn't use this tool to try to generate real production infras
15
15
  ## Features
16
16
 
17
17
  - Generate individual files
18
- - Generate git repos with multiple files (and optionally push them to GitHub)
19
- - Bulk clone and delete generated repos by prefix
18
+ - Generate git repos with multiple files (and optionally push them to a remote VCS)
19
+ - Bulk clone and delete generated repos on a remote VCS by prefix
20
20
 
21
21
  `terrafaker` can be used to randomly generate a file or repo of files like this:
22
22
 
@@ -48,35 +48,34 @@ resource "aws_lambda_function" "irresponsible_lavender_elephant" {
48
48
  }
49
49
  ```
50
50
 
51
- ### Supported IAC providers and resources
52
-
53
- - Terraform
54
- - AWS
55
- - Compute instances
56
- - Functions
57
- - GCP
58
- - Compute instances
59
- - Functions
60
- - Azure
61
- - Compute instances
62
- - Functions
63
-
64
51
  ### Supported VCS providers
65
52
 
66
- - GitHub ([`brew install gh`](https://cli.github.com/))
67
- - GitLab ([`brew install glab`](https://docs.gitlab.com/cli/))
53
+ | VCS Provider | Supported | Dependency |
54
+ | ------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
55
+ | GitHub | ✅ | [`brew install gh`](https://cli.github.com/) |
56
+ | GitLab | ✅ | [`brew install glab`](https://docs.gitlab.com/cli/) |
57
+ | Azure | ✅ | [`brew install azure-cli`](https://learn.microsoft.com/en-us/cli/azure)[`&& az extension add --name azure-devops`](https://learn.microsoft.com/en-us/cli/azure/repos) |
68
58
 
69
- ## Issues
59
+ ### Supported cloud providers and IAC tooling
70
60
 
71
- If you find a bug, feel free to [open up an issue](https://github.com/brandongregoryscott/terrafaker/issues/new) and try to describe it in detail with reproduction steps if possible.
61
+ | Cloud Provider | Terraform | CloudFormation | CDK | Pulumi |
62
+ | -------------- | --------- | -------------- | --- | ------ |
63
+ | AWS | ✅ | ✅ | ❌ | ❌ |
64
+ | GCP | ✅ | ⛔️ | ⛔️ | ❌ |
65
+ | Azure | ✅ | ⛔️ | ⛔️ | ❌ |
72
66
 
73
- If you would like to see a feature, and it isn't [already documented](https://github.com/brandongregoryscott/terrafaker/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement), feel free to open up a new issue and describe the desired behavior.
67
+ ### Supported resources
68
+
69
+ | Resource Type | AWS | GCP | Azure |
70
+ | ----------------- | --- | --- | ----- |
71
+ | Compute Instances | ✅ | ✅ | ✅ |
72
+ | Functions | ✅ | ✅ | ✅ |
73
+ | Object Storage | ❌ | ❌ | ❌ |
74
+ | Managed Databases | ❌ | ❌ | ❌ |
74
75
 
75
- - [terrafaker](#terrafaker)
76
- - [Usage](#usage)
77
- - [Commands](./COMMANDS.md)
76
+ ## Usage
78
77
 
79
- # Usage
78
+ See [`COMMANDS.MD`](./COMMANDS.md) for documentation on available commands.
80
79
 
81
80
  <!-- usage -->
82
81
 
@@ -85,7 +84,7 @@ $ npm install -g terrafaker
85
84
  $ terrafaker COMMAND
86
85
  running command...
87
86
  $ terrafaker (--version)
88
- terrafaker/0.0.8 darwin-arm64 node-v24.8.0
87
+ terrafaker/0.0.10 darwin-arm64 node-v24.8.0
89
88
  $ terrafaker --help [COMMAND]
90
89
  USAGE
91
90
  $ terrafaker COMMAND
@@ -93,3 +92,9 @@ USAGE
93
92
  ```
94
93
 
95
94
  <!-- usagestop -->
95
+
96
+ ## Issues
97
+
98
+ If you find a bug, feel free to [open up an issue](https://github.com/brandongregoryscott/terrafaker/issues/new) and try to describe it in detail with reproduction steps if possible.
99
+
100
+ If you would like to see a feature, and it isn't [already documented](https://github.com/brandongregoryscott/terrafaker/issues?q=is%3Aissue+is%3Aopen+label%3Aenhancement), feel free to open up a new issue and describe the desired behavior.
@@ -0,0 +1,22 @@
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
+ import { Azure } from "../../../utilities/azure.js";
3
+ import { BaseCommand } from "../../../utilities/base-command.js";
4
+ import { directoryFlag, requiredPrefixFlag, toCamelCaseFlags, } from "../../../utilities/flags.js";
5
+ class Clone extends BaseCommand {
6
+ static description = `Clones repos from your ${VcsProviderNames.Azure} account, useful for pulling down generated repos for manual modifications.`;
7
+ static flags = {
8
+ directory: directoryFlag,
9
+ prefix: requiredPrefixFlag,
10
+ };
11
+ async run() {
12
+ const { flags } = await this.parse(Clone);
13
+ const { directory, prefix } = toCamelCaseFlags(flags);
14
+ await this.cloneRepos({
15
+ cloneRepo: Azure.cloneRepo,
16
+ directory,
17
+ listRepos: Azure.listRepos,
18
+ prefix,
19
+ });
20
+ }
21
+ }
22
+ export { Clone };
@@ -0,0 +1,20 @@
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
+ import { Azure } from "../../../utilities/azure.js";
3
+ import { BaseCommand } from "../../../utilities/base-command.js";
4
+ import { requiredPrefixFlag, toCamelCaseFlags, } from "../../../utilities/flags.js";
5
+ class Delete extends BaseCommand {
6
+ static description = `Deletes repos from your ${VcsProviderNames.Azure} account, useful for cleaning up generated test data.`;
7
+ static flags = {
8
+ prefix: requiredPrefixFlag,
9
+ };
10
+ async run() {
11
+ const { flags } = await this.parse(Delete);
12
+ const { prefix } = toCamelCaseFlags(flags);
13
+ await this.deleteRepos({
14
+ deleteRepo: Azure.deleteRepo,
15
+ listRepos: Azure.listRepos,
16
+ prefix,
17
+ });
18
+ }
19
+ }
20
+ export { Delete };
@@ -0,0 +1,13 @@
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
+ import { Azure } from "../../../utilities/azure.js";
3
+ import { BaseCommand } from "../../../utilities/base-command.js";
4
+ import { RepoUtils } from "../../../utilities/repo-utils.js";
5
+ class List extends BaseCommand {
6
+ static description = `Lists repos from your ${VcsProviderNames.Azure} account, useful for debugging.`;
7
+ async run() {
8
+ await this.parse(List);
9
+ const repos = await Azure.listRepos();
10
+ this.log(RepoUtils.stringifyRepos(repos));
11
+ }
12
+ }
13
+ export { List };
@@ -1,39 +1,44 @@
1
1
  import { Flags } from "@oclif/core";
2
+ import { FlagNames } from "../../enums/flag-names.js";
2
3
  import { BaseCommand } from "../../utilities/base-command.js";
3
- import { chaosTagsFlag, formatFlag, getTagsOption, noTagsFlag, providerFlag, quietFlag, resourceCountFlag, tagsFlag, } from "../../utilities/flags.js";
4
+ import { chaosTagsFlag, cloudProviderFlag, formatFlag, getTagsOption, iacTypeFlag, noTagsFlag, quietFlag, resourceCountFlag, tagsFlag, toCamelCaseFlags, } from "../../utilities/flags.js";
4
5
  import { FileGenerator } from "../../utilities/generators/file-generator.js";
5
- import { randomProvider } from "../../utilities/generators/generator-utils.js";
6
- import { formatTfFileName, success } from "../../utilities/string-utils.js";
6
+ import { StringUtils } from "../../utilities/string-utils.js";
7
7
  class File extends BaseCommand {
8
- static description = "Generates a terraform file.";
8
+ static description = "Generates an infrastructure-as-code file.";
9
9
  static flags = {
10
- "chaos-tags": chaosTagsFlag,
11
- format: formatFlag,
12
- name: Flags.string({
13
- description: "Name for the generated file, which must end in .tf",
10
+ [FlagNames.ChaosTags]: chaosTagsFlag,
11
+ [FlagNames.CloudProvider]: cloudProviderFlag(),
12
+ [FlagNames.Format]: formatFlag,
13
+ [FlagNames.IacType]: iacTypeFlag(),
14
+ [FlagNames.Name]: Flags.string({
15
+ description: `Name for the generated file (extension added automatically based on ${FlagNames.IacType})`,
14
16
  }),
15
- "no-tags": noTagsFlag,
16
- provider: providerFlag,
17
- quiet: quietFlag,
18
- "resource-count": resourceCountFlag,
19
- tags: tagsFlag(),
17
+ [FlagNames.NoTags]: noTagsFlag,
18
+ [FlagNames.Quiet]: quietFlag,
19
+ [FlagNames.ResourceCount]: resourceCountFlag,
20
+ [FlagNames.Tags]: tagsFlag(),
20
21
  };
21
22
  async run() {
22
23
  const { flags } = await this.parse(File);
23
- const { format, name, quiet, "resource-count": resourceCount } = flags;
24
+ const { cloudProvider, format, iacType, name, quiet, resourceCount } = toCamelCaseFlags(flags);
24
25
  const tags = getTagsOption(flags);
25
- const provider = flags.provider ?? randomProvider();
26
- const fileName = formatTfFileName(name ?? "main.tf");
26
+ const fileName = StringUtils.formatFileName({
27
+ fileName: name,
28
+ iacType,
29
+ });
27
30
  FileGenerator.generate({
31
+ cloudProvider,
28
32
  fileName,
29
33
  format,
30
- provider,
34
+ iacType,
31
35
  resourceCount,
32
36
  tags,
33
37
  });
34
- if (!quiet) {
35
- this.log(success(`Successfully generated '${fileName}'`));
38
+ if (quiet) {
39
+ return;
36
40
  }
41
+ this.log(StringUtils.success(`Successfully generated '${fileName}'`));
37
42
  }
38
43
  }
39
44
  export { File };
@@ -1,75 +1,82 @@
1
1
  import { Flags } from "@oclif/core";
2
2
  import path from "node:path";
3
+ import { FlagNames } from "../../enums/flag-names.js";
3
4
  import { HelpMessages } from "../../enums/help-messages.js";
4
5
  import { VcsProviders } from "../../enums/vcs-providers.js";
6
+ import { Azure } from "../../utilities/azure.js";
5
7
  import { BaseCommand } from "../../utilities/base-command.js";
6
- import { chaosTagsFlag, directoryFlag, formatFlag, getTagsOption, noTagsFlag, providerFlag, quietFlag, resourceCountFlag, tagsFlag, vcsProviderFlag, } from "../../utilities/flags.js";
8
+ import { chaosTagsFlag, cloudProviderFlag, directoryFlag, formatFlag, getTagsOption, iacTypeFlag, noTagsFlag, quietFlag, resourceCountFlag, tagsFlag, toCamelCaseFlags, vcsProviderFlag, } from "../../utilities/flags.js";
7
9
  import { RepoGenerator } from "../../utilities/generators/repo-generator.js";
8
- import { GitHub } from "../../utilities/github.js";
9
- import { GitLab } from "../../utilities/gitlab.js";
10
- import { success } from "../../utilities/string-utils.js";
10
+ import { Github } from "../../utilities/github.js";
11
+ import { Gitlab } from "../../utilities/gitlab.js";
12
+ import { StringUtils } from "../../utilities/string-utils.js";
11
13
  class Repo extends BaseCommand {
12
- static description = "Generates repo(s) with multiple terraform files.";
14
+ static description = "Generates repo(s) with multiple infrastructure-as-code files.";
13
15
  static flags = {
14
- "chaos-tags": chaosTagsFlag,
15
- count: Flags.integer({
16
+ [FlagNames.ChaosTags]: chaosTagsFlag,
17
+ [FlagNames.CloudProvider]: cloudProviderFlag(),
18
+ [FlagNames.Count]: Flags.integer({
16
19
  default: 1,
17
20
  description: "Number of repos to generate",
18
21
  }),
19
- "create-remote": Flags.boolean({
22
+ [FlagNames.CreateRemote]: Flags.boolean({
20
23
  description: `Create and push a remote repo. ${HelpMessages.RequiresVcsCLI}`,
21
24
  }),
22
- directory: directoryFlag,
23
- "file-count": Flags.integer({
25
+ [FlagNames.Directory]: directoryFlag,
26
+ [FlagNames.FileCount]: Flags.integer({
24
27
  default: 3,
25
28
  description: "Number of files per repo to generate",
26
29
  }),
27
- format: formatFlag,
28
- "no-tags": noTagsFlag,
29
- prefix: Flags.string({
30
- default: "tf_",
31
- description: "Prefix for repo names, useful for quickly identifying generated content",
30
+ [FlagNames.Format]: formatFlag,
31
+ [FlagNames.IacType]: iacTypeFlag(),
32
+ [FlagNames.NoTags]: noTagsFlag,
33
+ [FlagNames.Prefix]: Flags.string({
34
+ description: "Prefix for repo names, useful for quickly identifying generated content. Defaults to 'tf_' for Terraform or 'cf_' for CloudFormation.",
32
35
  }),
33
- provider: providerFlag,
34
- public: Flags.boolean({
36
+ [FlagNames.Public]: Flags.boolean({
35
37
  default: false,
36
38
  description: "Whether the remote repo(s) created are public.",
37
39
  }),
38
- quiet: quietFlag,
39
- "resource-count": resourceCountFlag,
40
- tags: tagsFlag(),
41
- "vcs-provider": vcsProviderFlag,
40
+ [FlagNames.Quiet]: quietFlag,
41
+ [FlagNames.ResourceCount]: resourceCountFlag,
42
+ [FlagNames.Tags]: tagsFlag(),
43
+ [FlagNames.VcsProvider]: vcsProviderFlag(),
42
44
  };
43
45
  async run() {
44
46
  const { flags } = await this.parse(Repo);
45
- const { count, "create-remote": createRemote, "file-count": fileCount, format, prefix, public: isPublic, quiet, "resource-count": resourceCount, "vcs-provider": vcsProvider, } = flags;
47
+ const { cloudProvider, count, createRemote, fileCount, format, iacType, prefix, public: isPublic, quiet, resourceCount, vcsProvider, } = toCamelCaseFlags(flags);
46
48
  const tags = getTagsOption(flags);
47
- const provider = flags.provider;
48
49
  const directory = path.resolve(process.cwd(), flags.directory);
49
50
  for (let i = 0; i < count; i++) {
50
51
  const { name, path } = await RepoGenerator.generate({
52
+ cloudProvider,
51
53
  directory,
52
54
  fileCount,
53
55
  format,
56
+ iacType,
54
57
  prefix,
55
- provider,
56
58
  quiet,
57
59
  resourceCount,
58
60
  tags,
59
61
  });
60
- if (createRemote) {
61
- switch (vcsProvider) {
62
- case VcsProviders.GitHub:
63
- await GitHub.pushRepo({ isPublic, path });
64
- break;
65
- case VcsProviders.GitLab:
66
- await GitLab.pushRepo({ isPublic, path });
67
- break;
68
- }
69
- if (!quiet) {
70
- this.log(success(`Successfully pushed '${name}'`));
71
- }
62
+ if (!createRemote) {
63
+ return;
72
64
  }
65
+ switch (vcsProvider) {
66
+ case VcsProviders.Azure:
67
+ await Azure.pushRepo({ path });
68
+ break;
69
+ case VcsProviders.Github:
70
+ await Github.pushRepo({ isPublic, path });
71
+ break;
72
+ case VcsProviders.Gitlab:
73
+ await Gitlab.pushRepo({ isPublic, path });
74
+ break;
75
+ }
76
+ if (quiet) {
77
+ return;
78
+ }
79
+ this.log(StringUtils.success(`Successfully pushed '${name}'`));
73
80
  }
74
81
  }
75
82
  }
@@ -1,20 +1,20 @@
1
- import { HelpMessages } from "../../../enums/help-messages.js";
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
2
  import { BaseCommand } from "../../../utilities/base-command.js";
3
- import { directoryFlag, requiredPrefixFlag } from "../../../utilities/flags.js";
4
- import { GitHub } from "../../../utilities/github.js";
3
+ import { directoryFlag, requiredPrefixFlag, toCamelCaseFlags, } from "../../../utilities/flags.js";
4
+ import { Github } from "../../../utilities/github.js";
5
5
  class Clone extends BaseCommand {
6
- static description = `Clones repos from your GitHub account, useful for pulling down generated repos for manual modifications. ${HelpMessages.RequiresGhCli}`;
6
+ static description = `Clones repos from your ${VcsProviderNames.Github} account, useful for pulling down generated repos for manual modifications.`;
7
7
  static flags = {
8
8
  directory: directoryFlag,
9
9
  prefix: requiredPrefixFlag,
10
10
  };
11
11
  async run() {
12
12
  const { flags } = await this.parse(Clone);
13
- const { directory, prefix } = flags;
13
+ const { directory, prefix } = toCamelCaseFlags(flags);
14
14
  await this.cloneRepos({
15
- cloneRepo: GitHub.cloneRepo,
15
+ cloneRepo: Github.cloneRepo,
16
16
  directory,
17
- listRepos: GitHub.listRepos,
17
+ listRepos: Github.listRepos,
18
18
  prefix,
19
19
  });
20
20
  }
@@ -1,9 +1,9 @@
1
- import { HelpMessages } from "../../../enums/help-messages.js";
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
2
  import { BaseCommand } from "../../../utilities/base-command.js";
3
- import { requiredPrefixFlag } from "../../../utilities/flags.js";
4
- import { GitHub } from "../../../utilities/github.js";
3
+ import { requiredPrefixFlag, toCamelCaseFlags, } from "../../../utilities/flags.js";
4
+ import { Github } from "../../../utilities/github.js";
5
5
  class Delete extends BaseCommand {
6
- static description = `Deletes repos from your GitHub account, useful for cleaning up generated test data. ${HelpMessages.RequiresGhCli}
6
+ static description = `Deletes repos from your ${VcsProviderNames.Github} account, useful for cleaning up generated test data.
7
7
 
8
8
  If the deletion fails, you may need to refresh your CLI permissions with \`gh auth refresh -s delete_repo\``;
9
9
  static flags = {
@@ -11,10 +11,10 @@ If the deletion fails, you may need to refresh your CLI permissions with \`gh au
11
11
  };
12
12
  async run() {
13
13
  const { flags } = await this.parse(Delete);
14
- const { prefix } = flags;
14
+ const { prefix } = toCamelCaseFlags(flags);
15
15
  await this.deleteRepos({
16
- deleteRepo: GitHub.deleteRepo,
17
- listRepos: GitHub.listRepos,
16
+ deleteRepo: Github.deleteRepo,
17
+ listRepos: Github.listRepos,
18
18
  prefix,
19
19
  });
20
20
  }
@@ -0,0 +1,13 @@
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
+ import { BaseCommand } from "../../../utilities/base-command.js";
3
+ import { Github } from "../../../utilities/github.js";
4
+ import { RepoUtils } from "../../../utilities/repo-utils.js";
5
+ class List extends BaseCommand {
6
+ static description = `Lists repos from your ${VcsProviderNames.Github} account, useful for debugging.`;
7
+ async run() {
8
+ await this.parse(List);
9
+ const repos = await Github.listRepos();
10
+ this.log(RepoUtils.stringifyRepos(repos));
11
+ }
12
+ }
13
+ export { List };
@@ -1,20 +1,20 @@
1
- import { HelpMessages } from "../../../enums/help-messages.js";
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
2
  import { BaseCommand } from "../../../utilities/base-command.js";
3
- import { directoryFlag, requiredPrefixFlag } from "../../../utilities/flags.js";
4
- import { GitLab } from "../../../utilities/gitlab.js";
3
+ import { directoryFlag, requiredPrefixFlag, toCamelCaseFlags, } from "../../../utilities/flags.js";
4
+ import { Gitlab } from "../../../utilities/gitlab.js";
5
5
  class Clone extends BaseCommand {
6
- static description = `Clones repos from your GitLab account, useful for pulling down generated repos for manual modifications. ${HelpMessages.RequiresGlabCli}`;
6
+ static description = `Clones repos from your ${VcsProviderNames.Gitlab} account, useful for pulling down generated repos for manual modifications.`;
7
7
  static flags = {
8
8
  directory: directoryFlag,
9
9
  prefix: requiredPrefixFlag,
10
10
  };
11
11
  async run() {
12
12
  const { flags } = await this.parse(Clone);
13
- const { directory, prefix } = flags;
13
+ const { directory, prefix } = toCamelCaseFlags(flags);
14
14
  await this.cloneRepos({
15
- cloneRepo: GitLab.cloneRepo,
15
+ cloneRepo: Gitlab.cloneRepo,
16
16
  directory,
17
- listRepos: GitLab.listRepos,
17
+ listRepos: Gitlab.listRepos,
18
18
  prefix,
19
19
  });
20
20
  }
@@ -1,18 +1,18 @@
1
- import { HelpMessages } from "../../../enums/help-messages.js";
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
2
  import { BaseCommand } from "../../../utilities/base-command.js";
3
- import { requiredPrefixFlag } from "../../../utilities/flags.js";
4
- import { GitLab } from "../../../utilities/gitlab.js";
3
+ import { requiredPrefixFlag, toCamelCaseFlags, } from "../../../utilities/flags.js";
4
+ import { Gitlab } from "../../../utilities/gitlab.js";
5
5
  class Delete extends BaseCommand {
6
- static description = `Deletes repos from your GitLab account, useful for cleaning up generated test data. ${HelpMessages.RequiresGlabCli}`;
6
+ static description = `Deletes repos from your ${VcsProviderNames.Gitlab} account, useful for cleaning up generated test data.`;
7
7
  static flags = {
8
8
  prefix: requiredPrefixFlag,
9
9
  };
10
10
  async run() {
11
11
  const { flags } = await this.parse(Delete);
12
- const { prefix } = flags;
12
+ const { prefix } = toCamelCaseFlags(flags);
13
13
  await this.deleteRepos({
14
- deleteRepo: GitLab.deleteRepo,
15
- listRepos: GitLab.listRepos,
14
+ deleteRepo: Gitlab.deleteRepo,
15
+ listRepos: Gitlab.listRepos,
16
16
  prefix,
17
17
  });
18
18
  }
@@ -0,0 +1,13 @@
1
+ import { VcsProviderNames } from "../../../enums/vcs-providers.js";
2
+ import { BaseCommand } from "../../../utilities/base-command.js";
3
+ import { Gitlab } from "../../../utilities/gitlab.js";
4
+ import { RepoUtils } from "../../../utilities/repo-utils.js";
5
+ class List extends BaseCommand {
6
+ static description = `Lists repos from your ${VcsProviderNames.Gitlab} account, useful for debugging.`;
7
+ async run() {
8
+ await this.parse(List);
9
+ const repos = await Gitlab.listRepos();
10
+ this.log(RepoUtils.stringifyRepos(repos));
11
+ }
12
+ }
13
+ export { List };
@@ -0,0 +1,97 @@
1
+ import ora from "ora";
2
+ import { HelpMessages } from "../enums/help-messages.js";
3
+ import { VcsProviderNames } from "../enums/vcs-providers.js";
4
+ import { BaseCommand } from "../utilities/base-command.js";
5
+ import { StringUtils } from "../utilities/string-utils.js";
6
+ class Health extends BaseCommand {
7
+ static description = "Utility command for checking overall CLI status.";
8
+ async run() {
9
+ await this.parse(Health);
10
+ await this.#checkGithubCli();
11
+ await this.#checkGitlabCli();
12
+ await this.#checkAzureCli();
13
+ }
14
+ async #checkAzureCli() {
15
+ const provider = VcsProviderNames.Azure;
16
+ await this.#checkVcsCli({
17
+ check: this.isAzureCliInstalled,
18
+ helpMessage: HelpMessages.InstallAzureCli,
19
+ provider,
20
+ type: "installed",
21
+ });
22
+ await this.#checkWithSpinner({
23
+ check: this.isAzureCliDevopsExtensionInstalled,
24
+ failureMessage: `${provider} CLI is missing \`azure-devops\` extension.${StringUtils.formatInstructions(HelpMessages.InstallAzureCli)}`,
25
+ loadingMessage: `Checking for ${provider} CLI \`azure-devops\` extension`,
26
+ successMessage: `${provider} CLI has \`azure-devops\` extension installed`,
27
+ });
28
+ await this.#checkVcsCli({
29
+ check: this.isAzureCliAuthenticated,
30
+ helpMessage: HelpMessages.AuthenticateAzureCli,
31
+ provider,
32
+ type: "authenticated",
33
+ });
34
+ await this.#checkWithSpinner({
35
+ check: this.isAzureCliDefaultOrganizationConfigured,
36
+ failureMessage: `${provider} CLI is missing a default organization.\n${StringUtils.formatInstructions(HelpMessages.ConfigureAzureCliDefaultOrganization)}`,
37
+ loadingMessage: `Checking for ${provider} CLI default organization`,
38
+ successMessage: `${provider} CLI has a default organization configured`,
39
+ });
40
+ await this.#checkWithSpinner({
41
+ check: this.isAzureCliDefaultProjectConfigured,
42
+ failureMessage: `${provider} CLI is missing a default project.\n${StringUtils.formatInstructions(HelpMessages.ConfigureAzureCliDefaultProject, HelpMessages.CreateAzureProject)}`,
43
+ loadingMessage: `Checking for ${provider} CLI default project`,
44
+ successMessage: `${provider} CLI has a default project configured`,
45
+ });
46
+ }
47
+ async #checkGithubCli() {
48
+ const provider = VcsProviderNames.Github;
49
+ await this.#checkVcsCli({
50
+ check: this.isGithubCliInstalled,
51
+ helpMessage: HelpMessages.InstallGithubCli,
52
+ provider,
53
+ type: "installed",
54
+ });
55
+ await this.#checkVcsCli({
56
+ check: this.isGithubCliAuthenticated,
57
+ helpMessage: HelpMessages.AuthenticateGithubCli,
58
+ provider,
59
+ type: "authenticated",
60
+ });
61
+ }
62
+ async #checkGitlabCli() {
63
+ const provider = VcsProviderNames.Gitlab;
64
+ await this.#checkVcsCli({
65
+ check: this.isGitlabCliInstalled,
66
+ helpMessage: HelpMessages.InstallGitlabCli,
67
+ provider,
68
+ type: "installed",
69
+ });
70
+ await this.#checkVcsCli({
71
+ check: this.isGitlabCliAuthenticated,
72
+ helpMessage: HelpMessages.AuthenticateGitlabCli,
73
+ provider,
74
+ type: "authenticated",
75
+ });
76
+ }
77
+ async #checkVcsCli(options) {
78
+ const { check, helpMessage, provider, type } = options;
79
+ return this.#checkWithSpinner({
80
+ check,
81
+ failureMessage: `${provider} CLI is not ${type}.\n${StringUtils.formatInstructions(helpMessage)}`,
82
+ loadingMessage: `Checking ${provider} CLI ${type === "authenticated" ? "authentication" : "installation"}`,
83
+ successMessage: `${provider} CLI is ${type}`,
84
+ });
85
+ }
86
+ async #checkWithSpinner(options) {
87
+ const { check, failureMessage, loadingMessage, successMessage } = options;
88
+ const spinner = ora(loadingMessage).start();
89
+ const result = await check();
90
+ if (result) {
91
+ spinner.succeed(successMessage);
92
+ return;
93
+ }
94
+ spinner.fail(failureMessage);
95
+ }
96
+ }
97
+ export { Health };
@@ -1,6 +1,6 @@
1
- const Providers = {
1
+ const CloudProviders = {
2
2
  AWS: "aws",
3
3
  Azure: "azure",
4
4
  GCP: "gcp",
5
5
  };
6
- export { Providers };
6
+ export { CloudProviders };
@@ -0,0 +1,19 @@
1
+ const FlagNames = {
2
+ ChaosTags: "chaos-tags",
3
+ CloudProvider: "cloud-provider",
4
+ Count: "count",
5
+ CreateRemote: "create-remote",
6
+ Directory: "directory",
7
+ FileCount: "file-count",
8
+ Format: "format",
9
+ IacType: "iac-type",
10
+ Name: "name",
11
+ NoTags: "no-tags",
12
+ Prefix: "prefix",
13
+ Public: "public",
14
+ Quiet: "quiet",
15
+ ResourceCount: "resource-count",
16
+ Tags: "tags",
17
+ VcsProvider: "vcs-provider",
18
+ };
19
+ export { FlagNames };
@@ -1,6 +1,16 @@
1
1
  const HelpMessages = {
2
- RequiresGhCli: `Requires the \`gh\` CLI to be installed. To install, run \`brew install gh\`.`,
3
- RequiresGlabCli: `Requires the \`glab\` CLI to be installed. To install, run \`brew install glab\`.`,
4
- RequiresVcsCLI: `Requires the \`gh\` or \`glab\` CLI to be installed. To install, run \`brew install gh|glab\`.`,
2
+ AuthenticateAzureCli: `Run \`az login --allow-no-subscriptions\` and try again.`,
3
+ AuthenticateGithubCli: `Run \`gh auth login\` and try again.`,
4
+ AuthenticateGitlabCli: `Run \`glab auth login\` and try again.`,
5
+ ConfigureAzureCliDefaultOrganization: "To configure a default organization, run \`az devops configure --defaults organization=https://dev.azure.com/brandongregoryscott\`.",
6
+ ConfigureAzureCliDefaultProject: "To configure a default project, run \`az devops configure --defaults project=terrafaker\`.",
7
+ CreateAzureProject: "To create a project, run \`az devops project create --name=terrafaker\`.",
8
+ InstallAzureCli: `To install, run \`brew install azure-cli && az extension add --name azure-devops\`.`,
9
+ InstallGithubCli: `To install, run \`brew install gh\`.`,
10
+ InstallGitlabCli: `To install, run \`brew install glab\`.`,
11
+ RequiresAzureCli: `Requires the \`az\` CLI to be installed.`,
12
+ RequiresGhCli: "Requires the \`gh\` CLI to be installed.",
13
+ RequiresGitlabCli: `Requires the \`glab\` CLI to be installed.`,
14
+ RequiresVcsCLI: `Requires the \`gh\`, \`glab\` or \`az\` CLIs to be installed.`,
5
15
  };
6
16
  export { HelpMessages };
@@ -0,0 +1,5 @@
1
+ const IacTypes = {
2
+ CloudFormation: "cloudformation",
3
+ Terraform: "terraform",
4
+ };
5
+ export { IacTypes };
@@ -1,5 +1,11 @@
1
1
  const VcsProviders = {
2
- GitHub: "github",
3
- GitLab: "gitlab",
2
+ Azure: "azure",
3
+ Github: "github",
4
+ Gitlab: "gitlab",
4
5
  };
5
- export { VcsProviders };
6
+ const VcsProviderNames = {
7
+ Azure: "Azure",
8
+ Github: "GitHub",
9
+ Gitlab: "GitLab",
10
+ };
11
+ export { VcsProviderNames, VcsProviders };