Skip to content

Commit 327e858

Browse files
Config Generation: TF Install settings
Allow configuring the install dir and version. The benefit is that you can install it only once and reuse the executable
1 parent e43d121 commit 327e858

File tree

5 files changed

+80
-9
lines changed

5 files changed

+80
-9
lines changed

cmd/generate/main.go

+24-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/grafana/terraform-provider-grafana/v3/pkg/generate"
1010

1111
"github.com/fatih/color"
12+
goVersion "github.com/hashicorp/go-version"
1213
"github.com/urfave/cli/v2"
1314
)
1415

@@ -68,6 +69,18 @@ This supports a glob format. Examples:
6869
EnvVars: []string{"TFGEN_INCLUDE_RESOURCES"},
6970
Required: false,
7071
},
72+
&cli.StringFlag{
73+
Name: "terraform-install-dir",
74+
Usage: `Directory to install Terraform to. If not set, a temporary directory will be created.`,
75+
EnvVars: []string{"TFGEN_TERRAFORM_INSTALL_DIR"},
76+
Required: false,
77+
},
78+
&cli.StringFlag{
79+
Name: "terraform-install-version",
80+
Usage: `Version of Terraform to install. If not set, the latest version _tested in this tool_ will be installed.`,
81+
EnvVars: []string{"TFGEN_TERRAFORM_INSTALL_VERSION"},
82+
Required: false,
83+
},
7184

7285
// Grafana OSS flags
7386
&cli.StringFlag{
@@ -177,14 +190,24 @@ func parseFlags(ctx *cli.Context) (*generate.Config, error) {
177190
StackServiceAccountName: ctx.String("cloud-stack-service-account-name"),
178191
},
179192
IncludeResources: ctx.StringSlice("include-resources"),
193+
TerraformInstallConfig: generate.TerraformInstallConfig{
194+
InstallDir: ctx.String("terraform-install-dir"),
195+
},
196+
}
197+
var err error
198+
if tfVersion := ctx.String("terraform-install-version"); tfVersion != "" {
199+
config.TerraformInstallConfig.Version, err = goVersion.NewVersion(ctx.String("terraform-install-version"))
200+
if err != nil {
201+
return nil, fmt.Errorf("terraform-install-version must be a valid version: %w", err)
202+
}
180203
}
181204

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

186209
// Validate flags
187-
err := newFlagValidations().
210+
err = newFlagValidations().
188211
atLeastOne("grafana-url", "cloud-access-policy-token").
189212
conflicting(
190213
[]string{"grafana-url", "grafana-auth", "synthetic-monitoring-url", "synthetic-monitoring-access-token", "oncall-url", "oncall-access-token"},

pkg/generate/config.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
package generate
22

3-
import "github.com/hashicorp/terraform-exec/tfexec"
3+
import (
4+
"github.com/hashicorp/go-version"
5+
"github.com/hashicorp/terraform-exec/tfexec"
6+
)
47

58
type OutputFormat string
69

@@ -29,6 +32,11 @@ type CloudConfig struct {
2932
StackServiceAccountName string
3033
}
3134

35+
type TerraformInstallConfig struct {
36+
InstallDir string
37+
Version *version.Version
38+
}
39+
3240
type Config struct {
3341
// IncludeResources is a list of patterns to filter resources by.
3442
// If a resource name matches any of the patterns, it will be included in the output.
@@ -42,5 +50,7 @@ type Config struct {
4250
ProviderVersion string
4351
Grafana *GrafanaConfig
4452
Cloud *CloudConfig
45-
Terraform *tfexec.Terraform
53+
54+
TerraformInstallConfig TerraformInstallConfig
55+
Terraform *tfexec.Terraform
4656
}

pkg/generate/generate.go

+2
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ func Generate(ctx context.Context, cfg *Config) error {
6363
cfg.Terraform = tf
6464

6565
if cfg.Cloud != nil {
66+
log.Printf("Generating cloud resources")
6667
stacks, err := generateCloudResources(ctx, cfg)
6768
if err != nil {
6869
return err
@@ -86,6 +87,7 @@ func Generate(ctx context.Context, cfg *Config) error {
8687
onCallToken: cfg.Grafana.OnCallAccessToken,
8788
onCallURL: cfg.Grafana.OnCallURL,
8889
}
90+
log.Printf("Generating Grafana resources")
8991
if err := generateGrafanaResources(ctx, cfg, stack, true); err != nil {
9092
return err
9193
}

pkg/generate/generate_test.go

+6
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ func TestAccGenerate(t *testing.T) {
2222
}
2323
testutils.CheckOSSTestsEnabled(t)
2424

25+
// Install Terraform to a temporary directory to avoid reinstalling it for each test case.
26+
installDir := t.TempDir()
27+
2528
cases := []struct {
2629
name string
2730
config string
@@ -161,6 +164,9 @@ func TestAccGenerate(t *testing.T) {
161164
URL: "http://localhost:3000",
162165
Auth: "admin:admin",
163166
},
167+
TerraformInstallConfig: generate.TerraformInstallConfig{
168+
InstallDir: installDir,
169+
},
164170
}
165171
if tc.generateConfig != nil {
166172
tc.generateConfig(&config)

pkg/generate/terraform.go

+36-6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import (
55
"encoding/json"
66
"errors"
77
"fmt"
8+
"log"
89
"os"
910
"path/filepath"
1011
"strings"
1112

1213
"github.com/hashicorp/go-version"
14+
"github.com/hashicorp/hc-install/fs"
1315
"github.com/hashicorp/hc-install/product"
1416
"github.com/hashicorp/hc-install/releases"
1517
"github.com/hashicorp/hcl/v2"
@@ -20,14 +22,42 @@ import (
2022
)
2123

2224
func setupTerraform(cfg *Config) (*tfexec.Terraform, error) {
23-
installer := &releases.ExactVersion{
24-
Product: product.Terraform,
25-
Version: version.Must(version.NewVersion("1.8.4")),
25+
var err error
26+
27+
tfVersion := cfg.TerraformInstallConfig.Version
28+
if tfVersion == nil {
29+
// Not using latest to avoid unexpected breaking changes
30+
log.Printf("No Terraform version specified, defaulting to version 1.8.5")
31+
tfVersion = version.Must(version.NewVersion("1.8.5"))
2632
}
2733

28-
execPath, err := installer.Install(context.Background())
29-
if err != nil {
30-
return nil, fmt.Errorf("error installing Terraform: %s", err)
34+
// Check if Terraform is already installed
35+
var execPath string
36+
if cfg.TerraformInstallConfig.InstallDir != "" {
37+
finder := fs.ExactVersion{
38+
Product: product.Terraform,
39+
Version: tfVersion,
40+
ExtraPaths: []string{
41+
cfg.TerraformInstallConfig.InstallDir,
42+
},
43+
}
44+
45+
if execPath, err = finder.Find(context.Background()); err == nil {
46+
log.Printf("Terraform %s already installed at %s", tfVersion, execPath)
47+
}
48+
}
49+
50+
// Install Terraform if not found
51+
if execPath == "" {
52+
log.Printf("Installing Terraform %s", tfVersion)
53+
installer := &releases.ExactVersion{
54+
Product: product.Terraform,
55+
Version: tfVersion,
56+
InstallDir: cfg.TerraformInstallConfig.InstallDir,
57+
}
58+
if execPath, err = installer.Install(context.Background()); err != nil {
59+
return nil, fmt.Errorf("error installing Terraform: %s", err)
60+
}
3161
}
3262

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

0 commit comments

Comments
 (0)