Skip to content

Commit

Permalink
Config Generation: Add test for SM Check generation (#1741)
Browse files Browse the repository at this point in the history
- Add new `TestAccGenerate_CloudInstance` test function
- Add test helper to template the expected files dir (for incrementing IDs or random names in a persistent test env)
- Add helper function hook (`stateCheck`) to access the Terraform state. This is used to extract the check ID which is computed after applying. This ID is part of the expected files output
  • Loading branch information
julienduchesne authored Aug 2, 2024
1 parent 6ce2740 commit f12a63c
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 36 deletions.
191 changes: 155 additions & 36 deletions pkg/generate/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@ package generate_test

import (
"context"
"fmt"
"os"
"path/filepath"
"strconv"
"strings"
"testing"
"text/template"

"github.com/grafana/grafana-openapi-client-go/client/access_control"
"github.com/grafana/grafana-openapi-client-go/client/service_accounts"
Expand All @@ -23,7 +26,8 @@ import (

type generateTestCase struct {
name string
config string // Terraform configuration to apply
config string // Terraform configuration to apply
stateCheck func(s *terraform.State) error // Check the Terraform state after applying. Useful to extract computed attributes from state.
generateConfig func(cfg *generate.Config)
check func(t *testing.T, tempDir string) // Check the generated files
resultCheck func(t *testing.T, result generate.GenerationResult) // Check the generation result
Expand All @@ -32,47 +36,54 @@ type generateTestCase struct {
}

func (tc *generateTestCase) Run(t *testing.T) {
stateCheck := func(s *terraform.State) error { return nil }
if tc.stateCheck != nil {
stateCheck = tc.stateCheck
}
t.Run(tc.name, func(t *testing.T) {
resource.Test(t, resource.TestCase{
ProtoV5ProviderFactories: testutils.ProtoV5ProviderFactories,
Steps: []resource.TestStep{
{
Config: tc.config,
Check: func(s *terraform.State) error {
tempDir := t.TempDir()

// Default configs, use `generateConfig` to override
config := generate.Config{
OutputDir: tempDir,
Clobber: true,
Format: generate.OutputFormatHCL,
ProviderVersion: "999.999.999", // Using the code from the current branch
Grafana: &generate.GrafanaConfig{
URL: "http://localhost:3000",
Auth: "admin:admin",
},
TerraformInstallConfig: generate.TerraformInstallConfig{
InstallDir: tc.tfInstallDir,
PluginDir: pluginDir(t),
},
}
if tc.generateConfig != nil {
tc.generateConfig(&config)
}

result := generate.Generate(context.Background(), &config)
if tc.resultCheck != nil {
tc.resultCheck(t, result)
} else {
require.Len(t, result.Errors, 0, "expected no errors, got: %v", result.Errors)
}

if tc.check != nil {
tc.check(t, tempDir)
}

return nil
},
Check: resource.ComposeTestCheckFunc(
stateCheck,
func(s *terraform.State) error {
tempDir := t.TempDir()

// Default configs, use `generateConfig` to override
config := generate.Config{
OutputDir: tempDir,
Clobber: true,
Format: generate.OutputFormatHCL,
ProviderVersion: "999.999.999", // Using the code from the current branch
Grafana: &generate.GrafanaConfig{
URL: "http://localhost:3000",
Auth: "admin:admin",
},
TerraformInstallConfig: generate.TerraformInstallConfig{
InstallDir: tc.tfInstallDir,
PluginDir: pluginDir(t),
},
}
if tc.generateConfig != nil {
tc.generateConfig(&config)
}

result := generate.Generate(context.Background(), &config)
if tc.resultCheck != nil {
tc.resultCheck(t, result)
} else {
require.Len(t, result.Errors, 0, "expected no errors, got: %v", result.Errors)
}

if tc.check != nil {
tc.check(t, tempDir)
}

return nil
},
),
},
},
})
Expand Down Expand Up @@ -319,12 +330,120 @@ func TestAccGenerate_RestrictedPermissions(t *testing.T) {
tc.Run(t)
}

func TestAccGenerate_CloudInstance(t *testing.T) {
testutils.CheckCloudInstanceTestsEnabled(t)

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

randomString := acctest.RandString(10)
var smCheckID string
cases := []generateTestCase{
{
name: "sm-check",
config: testutils.TestAccExampleWithReplace(t, "resources/grafana_synthetic_monitoring_check/http_basic.tf", map[string]string{
`"HTTP Defaults"`: strconv.Quote(randomString),
}),
stateCheck: func(s *terraform.State) error {
checkResource, ok := s.RootModule().Resources["grafana_synthetic_monitoring_check.http"]
if !ok {
return fmt.Errorf("expected resource 'grafana_synthetic_monitoring_check.http' to be present")
}
smCheckID = checkResource.Primary.ID
return nil
},
generateConfig: func(cfg *generate.Config) {
cfg.Grafana = &generate.GrafanaConfig{
URL: os.Getenv("GRAFANA_URL"),
Auth: os.Getenv("GRAFANA_AUTH"),
SMURL: os.Getenv("GRAFANA_SM_URL"),
SMAccessToken: os.Getenv("GRAFANA_SM_ACCESS_TOKEN"),
}
cfg.IncludeResources = []string{"grafana_synthetic_monitoring_check._" + smCheckID}
},
check: func(t *testing.T, tempDir string) {
templateAttrs := map[string]string{
"ID": smCheckID,
"Job": randomString,
}
assertFilesWithTemplating(t, tempDir, "testdata/generate/sm-check", []string{
".terraform",
".terraform.lock.hcl",
}, templateAttrs)
},
},
}

for _, tc := range cases {
tc.tfInstallDir = installDir
tc.Run(t)
}
}

// assertFiles checks that all files in the "expectedFilesDir" directory match the files in the "gotFilesDir" directory.
func assertFiles(t *testing.T, gotFilesDir, expectedFilesDir string, ignoreDirEntries []string) {
t.Helper()
assertFilesWithTemplating(t, gotFilesDir, expectedFilesDir, ignoreDirEntries, nil)
}

// assertFilesWithTemplating checks that all files in the "expectedFilesDir" directory match the files in the "gotFilesDir" directory.
func assertFilesWithTemplating(t *testing.T, gotFilesDir, expectedFilesDir string, ignoreDirEntries []string, attributes map[string]string) {
t.Helper()

if attributes != nil {
expectedFilesDir = templateDir(t, expectedFilesDir, attributes)
}

assertFilesSubdir(t, gotFilesDir, expectedFilesDir, "", ignoreDirEntries)
}

func templateDir(t *testing.T, dir string, attributes map[string]string) string {
t.Helper()

templatedDir := t.TempDir()

// Copy all dirs and files from the expected directory to the templated directory
// Template all files that end with ".tmpl", renaming them to remove the ".tmpl" suffix
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}

relativePath, err := filepath.Rel(dir, path)
if err != nil {
return err
}

templatedPath := filepath.Join(templatedDir, relativePath)
if info.IsDir() {
return os.MkdirAll(templatedPath, 0755)
}

// Copy the file
isTmpl := strings.HasSuffix(info.Name(), ".tmpl")
templatedPath = strings.TrimSuffix(templatedPath, ".tmpl")
content, err := os.ReadFile(path)
if err != nil {
return err
}
if isTmpl {
fileTmpl, err := template.New(path).Parse(string(content))
if err != nil {
return err
}
var templatedContent strings.Builder
if err := fileTmpl.Execute(&templatedContent, attributes); err != nil {
return err
}
content = []byte(templatedContent.String())
}
return os.WriteFile(templatedPath, content, 0600)
})
require.NoError(t, err)

return templatedDir
}

func assertFilesSubdir(t *testing.T, gotFilesDir, expectedFilesDir, subdir string, ignoreDirEntries []string) {
t.Helper()

Expand Down
4 changes: 4 additions & 0 deletions pkg/generate/testdata/generate/sm-check/imports.tf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import {
to = grafana_synthetic_monitoring_check._{{ .ID }}
id = "{{ .ID }}"
}
15 changes: 15 additions & 0 deletions pkg/generate/testdata/generate/sm-check/provider.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
terraform {
required_providers {
grafana = {
source = "grafana/grafana"
version = "999.999.999"
}
}
}

provider "grafana" {
url = "https://tfprovidertests.grafana.net/"
auth = "REDACTED"
sm_url = "https://synthetic-monitoring-api-us-east-0.grafana.net"
sm_access_token = "REDACTED"
}
26 changes: 26 additions & 0 deletions pkg/generate/testdata/generate/sm-check/resources.tf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# __generated__ by Terraform
# Please review these resources and move them into your main configuration files.

# __generated__ by Terraform from "{{ .ID }}"
resource "grafana_synthetic_monitoring_check" "_{{ .ID }}" {
alert_sensitivity = "none"
basic_metrics_only = true
enabled = false
frequency = 60000
job = "{{ .Job }}"
labels = {
foo = "bar"
}
probes = [7]
target = "https://grafana.com"
timeout = 3000
settings {
http {
fail_if_not_ssl = false
fail_if_ssl = false
ip_version = "V4"
method = "GET"
no_follow_redirects = false
}
}
}

0 comments on commit f12a63c

Please sign in to comment.