Skip to content

Commit

Permalink
Merge pull request #630 from cloudflare/support-non-standard-binaries…
Browse files Browse the repository at this point in the history
…-and-registries

internal: provide a way to configure non-standard registries and binaries
  • Loading branch information
jacobbednarz committed Oct 31, 2023
2 parents 902ca88 + 0875f4f commit a4f51a3
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 29 deletions.
47 changes: 36 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,27 @@ Usage:
cf-terraforming [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
generate Fetch resources from the Cloudflare API and generate the respective Terraform stanzas
help Help about any command
import Output `terraform import` compatible commands in order to import resources into state
version Print the version number of cf-terraforming
Flags:
-a, --account string Use specific account ID for commands
-c, --config string Path to configuration file (default is $HOME/.cf-terraforming.yaml)
-e, --email string API Email address associated with your account
-h, --help Help for cf-terraforming
-k, --key string API Key generated on the 'My Profile' page. See: https://dash.cloudflare.com/profile
--resource-type string Which resource you wish to generate
--terraform-binary-path string Path to an existing Terraform binary (otherwise, one will be downloaded)
--terraform-install-path string Path to an initialized Terraform working directory (default ".")
-t, --token string API Token
-v, --verbose Specify verbose output (same as setting log level to debug)
-z, --zone string Limit the export to a single zone ID
-a, --account string Use specific account ID for commands
-c, --config string Path to config file (default "/Users/jacob/.cf-terraforming.yaml")
-e, --email string API Email address associated with your account
-h, --help help for cf-terraforming
--hostname string Hostname to use to query the API
-k, --key string API Key generated on the 'My Profile' page. See: https://dash.cloudflare.com/profile
--modern-import-block terraform import Whether to generate HCL import blocks for generated resources instead of terraform import compatible CLI commands. This is only compatible with Terraform 1.5+
--provider-registry-hostname string Hostname to use for provider registry lookups (default "registry.terraform.io")
--resource-type string Which resource you wish to generate
--terraform-binary-path string Path to an existing Terraform binary (otherwise, one will be downloaded)
--terraform-install-path string Path to an initialized Terraform working directory (default ".")
-t, --token string API Token
-v, --verbose Specify verbose output (same as setting log level to debug)
-z, --zone string Limit the export to a single zone ID
Use "cf-terraforming [command] --help" for more information about a command.
```
Expand Down Expand Up @@ -164,6 +168,27 @@ $ cf-terraforming import \
--zone $CLOUDFLARE_ZONE_ID
```

## Using non-standard registries

By default, we use the Hashicorp registry (registry.terraform.io) for looking up
the provider to introspect the schema. If you are attempting to use another
registry, you will need to provide the `--provider-registry-hostname` flag or
`CLOUDFLARE_PROVIDER_REGISTRY_HOSTNAME` environment variable to query the correct
registry.

## Using non-standard Terraform binaries

Internally, we use [`terraform-exec`](https://github.com/hashicorp/terraform-exec)
library to run Terraform operations in the same way that the CLI tooling would.
If a `terraform` binary is not available on your system path, we will attempt
to download the latest to use it.

Should you have the binary stored in a non-standard location, want to use an
existing binary, or you wish to provide a Terraform compatible binary (such as
`tofu`), you need to provide the `--terraform-binary-path` flag or
`CLOUDFLARE_TERRAFORM_BINARY_PATH` environment variable to instruct
`cf-terraforming` which you expect to use.

## Supported Resources

Any resources not listed are currently not supported.
Expand Down
2 changes: 1 addition & 1 deletion internal/app/cf-terraforming/cmd/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func generateResources() func(cmd *cobra.Command, args []string) {
if err != nil {
log.Fatal("failed to read provider schema", err)
}
s := ps.Schemas["registry.terraform.io/cloudflare/cloudflare"]
s := ps.Schemas[providerRegistryHostname+"/cloudflare/cloudflare"]
if s == nil {
log.Fatal("failed to detect provider installation")
}
Expand Down
32 changes: 15 additions & 17 deletions internal/app/cf-terraforming/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

var log = logrus.New()
var cfgFile, zoneID, hostname, apiEmail, apiKey, apiToken, accountID, terraformInstallPath, terraformBinaryPath string
var cfgFile, zoneID, hostname, apiEmail, apiKey, apiToken, accountID, terraformInstallPath, terraformBinaryPath, providerRegistryHostname string
var verbose, useModernImportBlock bool
var api *cloudflare.API
var terraformImportCmdPrefix = "terraform import"
Expand Down Expand Up @@ -42,12 +42,11 @@ func init() {
return
}

// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", home+"/.cf-terraforming.yaml", "Path to config file")
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Specify verbose output (same as setting log level to debug)")
rootCmd.PersistentFlags().StringVar(&resourceType, "resource-type", "", "Which resource you wish to generate")
rootCmd.PersistentFlags().BoolVarP(&useModernImportBlock, "modern-import-block", "", false, "Whether to generate HCL import blocks for generated resources instead of `terraform import` compatible CLI commands. This is only compatible with Terraform 1.5+")

// Zone selection
rootCmd.PersistentFlags().StringVarP(&zoneID, "zone", "z", "", "Limit the export to a single zone ID")
if err = viper.BindPFlag("zone", rootCmd.PersistentFlags().Lookup("zone")); err != nil {
log.Fatal(err)
Expand All @@ -56,7 +55,6 @@ func init() {
log.Fatal(err)
}

// Account
rootCmd.PersistentFlags().StringVarP(&accountID, "account", "a", "", "Use specific account ID for commands")
if err = viper.BindPFlag("account", rootCmd.PersistentFlags().Lookup("account")); err != nil {
log.Fatal(err)
Expand All @@ -65,7 +63,6 @@ func init() {
log.Fatal(err)
}

// API credentials
rootCmd.PersistentFlags().StringVarP(&apiEmail, "email", "e", "", "API Email address associated with your account")
if err = viper.BindPFlag("email", rootCmd.PersistentFlags().Lookup("email")); err != nil {
log.Fatal(err)
Expand Down Expand Up @@ -98,28 +95,29 @@ func init() {
log.Fatal(err)
}

// Debug logging mode
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "Specify verbose output (same as setting log level to debug)")

rootCmd.PersistentFlags().StringVar(&resourceType, "resource-type", "", "Which resource you wish to generate")

rootCmd.PersistentFlags().StringVar(&terraformInstallPath, "terraform-install-path", ".", "Path to an initialized Terraform working directory")

if err = viper.BindPFlag("terraform-install-path", rootCmd.PersistentFlags().Lookup("terraform-install-path")); err != nil {
log.Fatal(err)
}
if err = viper.BindEnv("terraform-install-path", "CLOUDFLARE_TERRAFORM_INSTALL_PATH"); err != nil {
log.Fatal(err)
}

rootCmd.PersistentFlags().StringVar(&terraformBinaryPath, "terraform-binary-path", "", "Path to an existing Terraform binary (otherwise, one will be downloaded)")

if err = viper.BindPFlag("terraform-binary-path", rootCmd.PersistentFlags().Lookup("terraform-binary-path")); err != nil {
log.Fatal(err)
}

if err = viper.BindEnv("terraform-install-path", "CLOUDFLARE_TERRAFORM_INSTALL_PATH"); err != nil {
if err = viper.BindEnv("terraform-binary-path", "CLOUDFLARE_TERRAFORM_BINARY_PATH"); err != nil {
log.Fatal(err)
}

rootCmd.PersistentFlags().BoolVarP(&useModernImportBlock, "modern-import-block", "", false, "Whether to generate HCL import blocks for generated resources instead of `terraform import` compatible CLI commands. This is only compatible with Terraform 1.5+")
rootCmd.PersistentFlags().StringVarP(&providerRegistryHostname, "provider-registry-hostname", "", "registry.terraform.io", "Hostname to use for provider registry lookups")
if err = viper.BindPFlag("provider-registry-hostname", rootCmd.PersistentFlags().Lookup("provider-registry-hostname")); err != nil {
log.Fatal(err)
}
if err = viper.BindEnv("provider-registry-hostname", "CLOUDFLARE_PROVIDER_REGISTRY_HOSTNAME"); err != nil {
log.Fatal(err)
}
}

// initConfig reads in config file and ENV variables if set.
Expand Down

0 comments on commit a4f51a3

Please sign in to comment.