Skip to content

Commit

Permalink
Config Generation: TF Install settings
Browse files Browse the repository at this point in the history
Allow configuring the install dir and version. The benefit is that you can install it only once and reuse the executable
  • Loading branch information
julienduchesne committed Jul 10, 2024
1 parent 8926097 commit 97203d5
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 9 deletions.
25 changes: 24 additions & 1 deletion cmd/generate/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/grafana/terraform-provider-grafana/v3/pkg/generate"

"github.com/fatih/color"
goVersion "github.com/hashicorp/go-version"
"github.com/urfave/cli/v2"
)

Expand Down Expand Up @@ -74,6 +75,18 @@ This supports a glob format. Examples:
EnvVars: []string{"TFGEN_OUTPUT_CREDENTIALS"},
Value: false,
},
&cli.StringFlag{
Name: "terraform-install-dir",
Usage: `Directory to install Terraform to. If not set, a temporary directory will be created.`,
EnvVars: []string{"TFGEN_TERRAFORM_INSTALL_DIR"},
Required: false,
},
&cli.StringFlag{
Name: "terraform-install-version",
Usage: `Version of Terraform to install. If not set, the latest version _tested in this tool_ will be installed.`,
EnvVars: []string{"TFGEN_TERRAFORM_INSTALL_VERSION"},
Required: false,
},

// Grafana OSS flags
&cli.StringFlag{
Expand Down Expand Up @@ -184,14 +197,24 @@ func parseFlags(ctx *cli.Context) (*generate.Config, error) {
StackServiceAccountName: ctx.String("cloud-stack-service-account-name"),
},
IncludeResources: ctx.StringSlice("include-resources"),
TerraformInstallConfig: generate.TerraformInstallConfig{
InstallDir: ctx.String("terraform-install-dir"),
},
}
var err error
if tfVersion := ctx.String("terraform-install-version"); tfVersion != "" {
config.TerraformInstallConfig.Version, err = goVersion.NewVersion(ctx.String("terraform-install-version"))
if err != nil {
return nil, fmt.Errorf("terraform-install-version must be a valid version: %w", err)
}
}

if config.ProviderVersion == "" {
return nil, fmt.Errorf("terraform-provider-version must be set")
}

// Validate flags
err := newFlagValidations().
err = newFlagValidations().
atLeastOne("grafana-url", "cloud-access-policy-token").
conflicting(
[]string{"grafana-url", "grafana-auth", "synthetic-monitoring-url", "synthetic-monitoring-access-token", "oncall-url", "oncall-access-token"},
Expand Down
14 changes: 12 additions & 2 deletions pkg/generate/config.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package generate

import "github.com/hashicorp/terraform-exec/tfexec"
import (
"github.com/hashicorp/go-version"
"github.com/hashicorp/terraform-exec/tfexec"
)

type OutputFormat string

Expand Down Expand Up @@ -29,6 +32,11 @@ type CloudConfig struct {
StackServiceAccountName string
}

type TerraformInstallConfig struct {
InstallDir string
Version *version.Version
}

type Config struct {
// IncludeResources is a list of patterns to filter resources by.
// If a resource name matches any of the patterns, it will be included in the output.
Expand All @@ -43,5 +51,7 @@ type Config struct {
ProviderVersion string
Grafana *GrafanaConfig
Cloud *CloudConfig
Terraform *tfexec.Terraform

TerraformInstallConfig TerraformInstallConfig
Terraform *tfexec.Terraform
}
2 changes: 2 additions & 0 deletions pkg/generate/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ func Generate(ctx context.Context, cfg *Config) error {
cfg.Terraform = tf

if cfg.Cloud != nil {
log.Printf("Generating cloud resources")
stacks, err := generateCloudResources(ctx, cfg)
if err != nil {
return err
Expand All @@ -86,6 +87,7 @@ func Generate(ctx context.Context, cfg *Config) error {
onCallToken: cfg.Grafana.OnCallAccessToken,
onCallURL: cfg.Grafana.OnCallURL,
}
log.Printf("Generating Grafana resources")
if err := generateGrafanaResources(ctx, cfg, stack, true); err != nil {
return err
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/generate/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ func TestAccGenerate(t *testing.T) {
}
testutils.CheckOSSTestsEnabled(t)

// Install Terraform to a temporary directory to avoid reinstalling it for each test case.
installDir := t.TempDir()

cases := []struct {
name string
config string
Expand Down Expand Up @@ -175,6 +178,9 @@ func TestAccGenerate(t *testing.T) {
URL: "http://localhost:3000",
Auth: "admin:admin",
},
TerraformInstallConfig: generate.TerraformInstallConfig{
InstallDir: installDir,
},
}
if tc.generateConfig != nil {
tc.generateConfig(&config)
Expand Down
42 changes: 36 additions & 6 deletions pkg/generate/terraform.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ import (
"encoding/json"
"errors"
"fmt"
"log"
"os"
"path/filepath"
"strings"

"github.com/hashicorp/go-version"
"github.com/hashicorp/hc-install/fs"
"github.com/hashicorp/hc-install/product"
"github.com/hashicorp/hc-install/releases"
"github.com/hashicorp/hcl/v2"
Expand All @@ -20,14 +22,42 @@ import (
)

func setupTerraform(cfg *Config) (*tfexec.Terraform, error) {
installer := &releases.ExactVersion{
Product: product.Terraform,
Version: version.Must(version.NewVersion("1.8.4")),
var err error

tfVersion := cfg.TerraformInstallConfig.Version
if tfVersion == nil {
// Not using latest to avoid unexpected breaking changes
log.Printf("No Terraform version specified, defaulting to version 1.8.5")
tfVersion = version.Must(version.NewVersion("1.8.5"))
}

execPath, err := installer.Install(context.Background())
if err != nil {
return nil, fmt.Errorf("error installing Terraform: %s", err)
// Check if Terraform is already installed
var execPath string
if cfg.TerraformInstallConfig.InstallDir != "" {
finder := fs.ExactVersion{
Product: product.Terraform,
Version: tfVersion,
ExtraPaths: []string{
cfg.TerraformInstallConfig.InstallDir,
},
}

if execPath, err = finder.Find(context.Background()); err == nil {
log.Printf("Terraform %s already installed at %s", tfVersion, execPath)
}
}

// Install Terraform if not found
if execPath == "" {
log.Printf("Installing Terraform %s", tfVersion)
installer := &releases.ExactVersion{
Product: product.Terraform,
Version: tfVersion,
InstallDir: cfg.TerraformInstallConfig.InstallDir,
}
if execPath, err = installer.Install(context.Background()); err != nil {
return nil, fmt.Errorf("error installing Terraform: %s", err)
}
}

tf, err := tfexec.NewTerraform(cfg.OutputDir, execPath)
Expand Down

0 comments on commit 97203d5

Please sign in to comment.