Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config Generation: Configurable Terraform Install #1659

Merged
merged 1 commit into from
Jul 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading