Skip to content

Commit

Permalink
feat: Support OpenTofu (#245)
Browse files Browse the repository at this point in the history
  • Loading branch information
lechnerc77 authored Feb 6, 2025
1 parent 38be8fa commit c7b6a18
Show file tree
Hide file tree
Showing 15 changed files with 279 additions and 57 deletions.
30 changes: 30 additions & 0 deletions .devcontainer/default-opentofu/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "Terraform exporter for SAP BTP - Dev OpenTofu",
//https://mcr.microsoft.com/en-us/product/devcontainers/go/tags
"image": "mcr.microsoft.com/devcontainers/go:1.23-bullseye",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/robbert229/devcontainer-features/opentofu:1": {
"version": "1.9.0"
},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"customizations": {
"vscode": {
"settings": {},
"extensions": [
"golang.go",
"gamunu.opentofu",
"ms-vscode.makefile-tools"
]
},
"codespaces": {}
},
// If you want to use SSO in the devcontainer, you must install the xdg-utils package (see .devcontainer/scripts/install-xdg.sh).
"hostRequirements": {
"memory": "4gb"
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
"remoteUser": "vscode"
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Terraform exporter for SAP BTP - Development",
"name": "Terraform exporter for SAP BTP - Dev",
//https://mcr.microsoft.com/en-us/product/devcontainers/go/tags
"image": "mcr.microsoft.com/devcontainers/go:1.23-bullseye",
// Features to add to the dev container. More info: https://containers.dev/features.
Expand Down
37 changes: 37 additions & 0 deletions .devcontainer/withenvfile-opentofu/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "Terraform exporter for SAP BTP - Dev OpenTofu (with env file)",
"image": "mcr.microsoft.com/devcontainers/go:1.23-bullseye",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
"ghcr.io/robbert229/devcontainer-features/opentofu:1": {
"version": "1.9.0"
},
"ghcr.io/devcontainers/features/github-cli:1": {}
},
"customizations": {
"vscode": {
"settings": {},
"extensions": [
"golang.go",
"gamunu.opentofu",
"ms-vscode.makefile-tools"
]
},
"codespaces": {}
},
// If you want to use SSO in the devcontainer, you must install the xdg-utils package (see .devcontainer/scripts/install-xdg.sh).
"hostRequirements": {
"memory": "4gb"
},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
// "forwardPorts": [],
"remoteUser": "vscode",
// This devcontainer expects a file named .devcontainer/devcontainer.env to exist.
// you should place the following environment variables in that file:
// - BTP_USERNAME
// - BTP_PASSWORD
"runArgs": [
"--env-file",
".devcontainer/devcontainer.env"
]
}
2 changes: 1 addition & 1 deletion .devcontainer/withenvfile/devcontainer.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "Terraform exporter for SAP BTP - Development (with env file)",
"name": "Terraform exporter for SAP BTP - Dev (with env file)",
"image": "mcr.microsoft.com/devcontainers/go:1.23-bullseye",
// Features to add to the dev container. More info: https://containers.dev/features.
"features": {
Expand Down
3 changes: 3 additions & 0 deletions .wordlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ btptf
btpResources
CLA
CLI
CLIs
CodeQL
config
Copilot
customizations
DCO
dependabot
devcontainer
devcontainers
dir
faq
Github
Expand All @@ -38,6 +40,7 @@ md
NextSteps
OAuth
OpenSSF
OpenTofu
PEM
Pre
pre
Expand Down
8 changes: 4 additions & 4 deletions docs/concepts.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
# Concepts
The Terraform Exporter for SAP BTP (btptf CLI) provides a convenience functionality to import existing subaccounts on SAP BTP into Terraform configurations. The configurations delivered by the btptf CLI are:
The Terraform Exporter for SAP BTP (btptf CLI) provides a convenience functionality to import existing subaccounts on SAP BTP into Terraform/OpenTofu configurations. The configurations delivered by the btptf CLI are:

- Provider configuration (excluding credentials)
- [Import](https://developer.hashicorp.com/terraform/language/import) blocks for the resources
- Resource configuration retrieved from the platform
- Resource configuration retrieved from the platform

The btptf CLI offers two options for the import:

1. As a one-step process via creating the import configuration by naming the resource types.

2. As a two-step process via creating a local JSON file with the resources to be imported. This file can be adjusted and then used as a configuration for the import.
2. As a two-step process via creating a local JSON file with the resources to be imported. This file can be adjusted and then used as a configuration for the import.

## Basic Flow

Expand All @@ -19,7 +19,7 @@ The btptf CLI offers two options for the import:

2. Creating the files with the import block based on the information from the documentation and reading the data from the platform leveraging the corresponding Terraform [data sources](https://registry.terraform.io/providers/SAP/btp/latest/docs).

3. Executing the Terraform commands via Terraform CLI to generate the resource configuration and store the results in the file system.
3. Executing the Terraform/OpenTofu commands via Terraform/OpenTofu CLI to generate the resource configuration and store the results in the file system.

The following points should be mentioned:

Expand Down
6 changes: 4 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Terraform Exporter for SAP BTP

The *Terraform Exporter for SAP BTP* (btptf CLI) is a handy tool that makes it easier to bring your existing SAP Business Technology Platform ([BTP](https://www.sap.com/products/technology-platform/what-is-sap-business-technology-platform.html)) resources into [Terraform](https://www.terraform.io/). With it, you can take things like subaccounts and directories in BTP and turn them into Terraform state and configuration files. It's especially useful for teams who are moving to Terraform but still need to manage older infrastructure or SAP BTP accounts that are already set up.
The *Terraform Exporter for SAP BTP* (btptf CLI) is a handy tool that makes it easier to bring your existing SAP Business Technology Platform ([BTP](https://www.sap.com/products/technology-platform/what-is-sap-business-technology-platform.html)) resources into [Terraform](https://www.terraform.io/) or [OpenTofu](https://opentofu.org/).

With it, you can take things like subaccounts and directories in BTP and turn them into Terraform/OpenTofu state and configuration files. It is especially useful for teams who are moving to Terraform/OpenTofu but still need to manage older infrastructure or SAP BTP accounts that are already set up.


## How does it work
Expand All @@ -9,4 +11,4 @@ The *Terraform Exporter for SAP BTP* (btptf CLI) is a handy tool that makes it e
- **Import Process**: The tool utilizes Terraform's [import](https://developer.hashicorp.com/terraform/cli/import) function to integrate each resource into Terraform's state.
- **Configuration Generation**: After import, it generates the Terraform code (in HashiCorp Configuration Language - HCL) for each resource, enabling further customizations as needed.


The same steps apply when using OpenTofu.
6 changes: 3 additions & 3 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

You have two options to install the btptf CLI:

1. Download the pre-built binary.
1. Download the pre-built binary.
2. Local build

The following sections describe the details for the two options.
Expand All @@ -19,7 +19,7 @@ If you want to build the binary from scratch, follow these steps:

1. Open [this](https://github.com/SAP/terraform-exporter-btp) repository inside VS Code Editor

2. We have setup a [devcontainer](https://code.visualstudio.com/docs/devcontainers/tutorial), so reopen the repository in the devcontainer.
2. We have setup a [devcontainer](https://code.visualstudio.com/docs/devcontainers/tutorial), so reopen the repository in the devcontainer. We provide devcontainers for Terraform and OpenTofu.

3. Open a terminal in VS Code and install the binary by running

Expand All @@ -31,4 +31,4 @@ If you want to build the binary from scratch, follow these steps:
4. The system will store the binary as `btptf` (`btptf.exe` in case of Windows) in the default binary path of your Go installation `$GOPATH/bin`.

!!! tip
You find the value of the GOPATH via `go env GOPATH`
You find the value of the GOPATH via `go env GOPATH`
2 changes: 1 addition & 1 deletion docs/limitations.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Supported Resources for Import

The btptf CLI can create import blocks and the corresponding configurations only for resources that support the import functionality of Terraform. Not all resources available in the Terraform providers support this feature and can hence not be imported.
The btptf CLI can create import blocks and the corresponding configurations only for resources that support the import functionality of Terraform/OpenTofu. Not all resources available in the Terraform providers support this feature and can hence not be imported.

You find a list of supported resources for the Terraform Provider for SAP BTP in the corresponding repository on GitHub under the [Overview on importable resources](https://github.com/SAP/terraform-provider-btp/blob/main/guides/IMPORT.md).

Expand Down
12 changes: 9 additions & 3 deletions docs/prerequisites.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
# Prerequisite

## Terraform CLI
## Terraform/OpenTofu CLI

The btptf CLI requires a installation of the Terraform CLI. The Terraform CLI will be called by the btptf CLI.
The btptf CLI requires a installation of the Terraform CLI or the OpenTofu CLI. The corresponding CLI will be detected and called by the btptf CLI.

You find the necessary information in the [official Terraform documentation](https://developer.hashicorp.com/terraform/install#darwin).
You find the necessary information in the official documentation:

- [Terraform](https://developer.hashicorp.com/terraform/install).
- [OpenTofu](https://opentofu.org/docs/intro/install/).

!!! info
If you have both CLIs installed you can enforce the usage of one via the environment variable `BTPTF_IAC_TOOL` namely setting its value to `terraform`or `tofu`.

## Setting of Environment Variables

Expand Down
10 changes: 5 additions & 5 deletions pkg/tfutils/tfConfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,16 @@ func GenerateConfig(resourceFileName string, configFolder string, isMainCmd bool
return fmt.Errorf("error changing directory to %s: %v", terraformConfigPath, err)
}

if err := runTerraformCommand("init"); err != nil {
if err := runTfCmdGeneric("init"); err != nil {
return fmt.Errorf("error running Terraform init: %v", err)
}

planOption := "--generate-config-out=" + resourceFileName
if err := runTerraformCommand("plan", planOption); err != nil {
if err := runTfCmdGeneric("plan", planOption); err != nil {
return fmt.Errorf("error running Terraform plan: %v", err)
}

if err := runTerraformCommand("fmt", "-recursive", "-list=false"); err != nil {
if err := runTfCmdGeneric("fmt", "-recursive", "-list=false"); err != nil {
return fmt.Errorf("error running Terraform fmt: %v", err)
}

Expand Down Expand Up @@ -436,13 +436,13 @@ func FinalizeTfConfig(configFolder string) {
log.Fatalf("error changing directory to %s: %v \n", terraformConfigPath, err)
}

if err := runTerraformCommand("init"); err != nil {
if err := runTfCmdGeneric("init"); err != nil {
CleanupProviderConfig()
fmt.Print("\r\n")
log.Fatalf("error initializing Terraform: %v", err)
}

if err := runTerraformCommand("fmt", "-recursive", "-list=false"); err != nil {
if err := runTfCmdGeneric("fmt", "-recursive", "-list=false"); err != nil {
CleanupProviderConfig()
fmt.Print("\r\n")
log.Fatalf("error running Terraform fmt: %v", err)
Expand Down
41 changes: 5 additions & 36 deletions pkg/tfutils/tfImport.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
package tfutils

import (
"context"
"encoding/json"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"slices"
"strings"

files "github.com/SAP/terraform-exporter-btp/pkg/files"
output "github.com/SAP/terraform-exporter-btp/pkg/output"
"github.com/hashicorp/terraform-exec/tfexec"
"github.com/spf13/viper"
)

// Constants for TF version for Terraform providers
Expand Down Expand Up @@ -304,34 +300,21 @@ func readDataSource(subaccountId string, directoryId string, organizationId stri
}

func getTfStateData(configDir string, resourceName string, identifier string) ([]byte, error) {
execPath, err := exec.LookPath("terraform")
if err != nil {
fmt.Print("\r\n")
log.Fatalf("error finding Terraform: %v", err)
return nil, err
}

chDir := fmt.Sprintf("-chdir=%s", configDir)
// Set custom user agent for call of TF Provider via exporter
addUserAgent()
defer removeUserAgent()

// create a new Terraform instance
tf, err := tfexec.NewTerraform(configDir, execPath)
if err != nil {
removeUserAgent()
fmt.Print("\r\n")
log.Fatalf("error running NewTerraform: %v", err)
return nil, err
}

err = tf.Init(context.Background(), tfexec.Upgrade(true))
err := runTfCmdGeneric(chDir, "init", "-upgrade")
if err != nil {
removeUserAgent()
fmt.Print("\r\n")
log.Fatalf("error running Init: %v", err)
return nil, err
}
err = tf.Apply(context.Background())

err = runTfCmdGeneric(chDir, "apply", "-auto-approve")
if err != nil {
err = handleNotFoundError(err, resourceName, identifier)
removeUserAgent()
Expand All @@ -340,7 +323,7 @@ func getTfStateData(configDir string, resourceName string, identifier string) ([
return nil, err
}

state, err := tf.Show(context.Background())
state, err := runTfShowJson(configDir)
if err != nil {
removeUserAgent()
fmt.Print("\r\n")
Expand Down Expand Up @@ -448,20 +431,6 @@ func generateDataSourcesForList(subaccountId string, directoryId string, organiz
return transformDataToStringArray(btpResourceType, data), extractFeatureList(data, btpResourceType), nil
}

func runTerraformCommand(args ...string) error {

verbose := viper.GetViper().GetBool("verbose")
cmd := exec.Command("terraform", args...)
if verbose {
cmd.Stdout = os.Stdout
} else {
cmd.Stdout = nil
}

cmd.Stderr = os.Stderr
return cmd.Run()
}

func GetExecutionLevelAndId(subaccountID string, directoryID string, organizationID string) (level string, id string) {
if subaccountID != "" {
return SubaccountLevel, subaccountID
Expand Down
Loading

0 comments on commit c7b6a18

Please sign in to comment.