terraform-module-test-helper/version_helper.go

179 строки
4.5 KiB
Go
Исходник Обычный вид История

2023-01-12 07:21:53 +03:00
package terraform_module_test_helper
import (
"fmt"
"io"
2023-01-12 07:21:53 +03:00
"os"
"path/filepath"
"sync"
2023-01-12 07:21:53 +03:00
"testing"
"time"
2023-01-19 10:22:18 +03:00
"github.com/gruntwork-io/terratest/modules/files"
"github.com/gruntwork-io/terratest/modules/logger"
2023-01-12 07:21:53 +03:00
"github.com/gruntwork-io/terratest/modules/terraform"
test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
)
2023-01-31 11:59:10 +03:00
var initE = terraform.InitE
var runTerraformCommandE = terraform.RunTerraformCommandE
var recordFileLocks = &KeyedMutex{}
type KeyedMutex struct {
mutexes sync.Map // Zero value is empty and ready for use
}
func (m *KeyedMutex) Lock(key string) func() {
value, _ := m.mutexes.LoadOrStore(key, &sync.Mutex{})
mtx := value.(*sync.Mutex)
mtx.Lock()
return func() { mtx.Unlock() }
}
2023-01-31 11:59:10 +03:00
2023-01-12 07:21:53 +03:00
type TestVersionSnapshot struct {
2023-01-31 11:59:10 +03:00
ModuleRootFolder string
SubModuleRelativeFolder string
Time time.Time
Success bool
2023-01-31 13:05:52 +03:00
Versions string
ErrorMsg string
2023-01-31 11:59:10 +03:00
}
2023-02-02 09:13:59 +03:00
func SuccessTestVersionSnapshot(rootFolder, exampleRelativePath string) *TestVersionSnapshot {
return &TestVersionSnapshot{
2023-01-31 11:59:10 +03:00
ModuleRootFolder: rootFolder,
SubModuleRelativeFolder: exampleRelativePath,
Time: time.Now(),
Success: true,
}
2023-01-12 07:21:53 +03:00
}
2023-02-02 09:13:59 +03:00
func FailedTestVersionSnapshot(rootFolder, exampleRelativePath, errMsg string) *TestVersionSnapshot {
return &TestVersionSnapshot{
2023-01-31 11:59:10 +03:00
ModuleRootFolder: rootFolder,
SubModuleRelativeFolder: exampleRelativePath,
Time: time.Now(),
Success: false,
2023-01-31 13:05:52 +03:00
ErrorMsg: errMsg,
2023-01-31 11:59:10 +03:00
}
}
func (s *TestVersionSnapshot) ToString() string {
2023-01-12 07:21:53 +03:00
return fmt.Sprintf(`## %s
Success: %t
2023-01-31 13:05:52 +03:00
### Versions
%s
### Error
2023-01-12 07:21:53 +03:00
%s
---
2023-01-31 13:05:52 +03:00
`, s.Time.Format(time.RFC822), s.Success, s.Versions, s.ErrorMsg)
2023-01-12 07:21:53 +03:00
}
2023-02-01 18:41:43 +03:00
func (s *TestVersionSnapshot) Save(t *testing.T) error {
2023-02-17 09:33:14 +03:00
path, err := filepath.Abs(filepath.Clean(filepath.Join(s.ModuleRootFolder, s.SubModuleRelativeFolder, "TestRecord.md.tmp")))
if err != nil {
return err
}
unlock := recordFileLocks.Lock(path)
defer unlock()
2023-02-01 18:41:43 +03:00
s.load(t)
2023-02-17 09:33:14 +03:00
err = s.saveToLocal(path)
if err != nil {
return err
}
2023-02-17 09:33:14 +03:00
return s.copyForUploadArtifact(path)
2023-02-01 18:41:43 +03:00
}
func (s *TestVersionSnapshot) copyForUploadArtifact(localPath string) error {
2023-01-31 11:59:10 +03:00
_, dir := filepath.Split(filepath.Join(s.ModuleRootFolder, s.SubModuleRelativeFolder))
2023-01-31 13:05:52 +03:00
pathForUpload := filepath.Join(s.ModuleRootFolder, "TestRecord", dir, "TestRecord.md.tmp")
2023-02-01 18:41:43 +03:00
return copyFile(localPath, pathForUpload)
}
2023-02-17 09:33:14 +03:00
func (s *TestVersionSnapshot) saveToLocal(path string) error {
return writeStringToFile(path, s.ToString())
}
func copyFile(src, dst string) error {
2023-02-02 16:48:15 +03:00
cleanedSrc := filepath.Clean(src)
cleanedDst := filepath.Clean(dst)
if _, err := os.Stat(cleanedSrc); os.IsNotExist(err) {
return fmt.Errorf("source file does not exist: %s", src)
}
2023-02-02 16:48:15 +03:00
dstDir := filepath.Dir(cleanedDst)
2024-09-14 05:40:44 +03:00
if _, err := os.Stat(dstDir); os.IsNotExist(err) && os.MkdirAll(dstDir, 0750) != nil {
return fmt.Errorf("failed to create destination folder: %s", dstDir)
}
2023-02-02 16:48:15 +03:00
if _, err := os.Stat(cleanedDst); !os.IsNotExist(err) && os.Remove(cleanedDst) != nil {
return fmt.Errorf("failed to delete destination file: %s", dst)
}
2023-02-02 16:48:15 +03:00
srcFile, err := os.Open(cleanedSrc)
if err != nil {
return fmt.Errorf("failed to open source file: %s", src)
}
defer func() { _ = srcFile.Close() }()
2023-02-02 16:48:15 +03:00
dstFile, err := os.Create(cleanedDst)
if err != nil {
return fmt.Errorf("failed to create destination file: %s", dst)
}
defer func() { _ = dstFile.Close() }()
if _, err = io.Copy(dstFile, srcFile); err != nil {
return fmt.Errorf("failed to copy file: %s", err)
}
return nil
2023-01-12 07:21:53 +03:00
}
2023-01-31 13:05:52 +03:00
func writeStringToFile(filePath, str string) error {
2023-02-02 16:48:15 +03:00
cleanedFilePath := filepath.Clean(filePath)
if files.FileExists(cleanedFilePath) {
if err := os.Remove(cleanedFilePath); err != nil {
2023-01-31 13:05:52 +03:00
return err
}
}
2023-02-02 16:48:15 +03:00
f, err := os.Create(cleanedFilePath)
2023-01-31 13:05:52 +03:00
if err != nil {
return err
}
defer func() { _ = f.Close() }()
_, err = f.WriteString(str)
return err
}
2023-02-01 18:41:43 +03:00
func (s *TestVersionSnapshot) load(t *testing.T) {
2023-01-31 13:05:52 +03:00
tmpDir := test_structure.CopyTerraformFolderToTemp(t, s.ModuleRootFolder, s.SubModuleRelativeFolder)
2023-01-31 11:59:10 +03:00
defer func() {
2023-01-31 13:05:52 +03:00
_ = os.RemoveAll(tmpDir)
2023-01-31 11:59:10 +03:00
}()
2023-01-31 13:05:52 +03:00
opts := terraform.Options{
TerraformDir: tmpDir,
2023-01-31 11:59:10 +03:00
NoColor: true,
Logger: logger.Discard,
}
if output, err := func() (string, error) {
initLock.Lock()
defer initLock.Unlock()
return initE(t, &opts)
}(); err != nil {
2023-01-31 11:59:10 +03:00
s.Success = false
2023-01-31 13:05:52 +03:00
s.ErrorMsg = output
2023-01-31 11:59:10 +03:00
return
}
2023-01-31 13:05:52 +03:00
output, err := runTerraformCommandE(t, &opts, "version")
2023-01-31 11:59:10 +03:00
if err != nil {
s.Success = false
2023-01-31 13:05:52 +03:00
s.ErrorMsg = output
2023-01-31 11:59:10 +03:00
return
}
2023-01-31 13:05:52 +03:00
s.Versions = output
2023-01-31 11:59:10 +03:00
}