github.com/mponton/terratest@v0.44.0/modules/opa/download_policy.go (about)

     1  package opa
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  	"sync"
     9  
    10  	getter "github.com/hashicorp/go-getter"
    11  
    12  	"github.com/mponton/terratest/modules/logger"
    13  	"github.com/mponton/terratest/modules/testing"
    14  )
    15  
    16  var (
    17  	// A map that maps the go-getter base URL to the temporary directory where it is downloaded.
    18  	policyDirCache sync.Map
    19  )
    20  
    21  // DownloadPolicyE takes in a rule path written in go-getter syntax and downloads it to a temporary directory so that it
    22  // can be passed to opa. The temporary directory that is used is cached based on the go-getter base path, and reused
    23  // across calls.
    24  // For example, if you call DownloadPolicyE with the go-getter URL multiple times:
    25  //
    26  //	git::https://github.com/mponton/terratest.git//policies/foo.rego?ref=master
    27  //
    28  // The first time the gruntwork-io/terratest repo will be downloaded to a new temp directory. All subsequent calls will
    29  // reuse that first temporary dir where the repo was cloned. This is preserved even if a different subdir is requested
    30  // later, e.g.: git::https://github.com/mponton/terratest.git//examples/bar.rego?ref=master.
    31  // Note that the query parameters are always included in the base URL. This means that if you use a different ref (e.g.,
    32  // git::https://github.com/mponton/terratest.git//examples/bar.rego?ref=v0.39.3), then that will be cloned to a new
    33  // temporary directory rather than the cached dir.
    34  func DownloadPolicyE(t testing.TestingT, rulePath string) (string, error) {
    35  	cwd, err := os.Getwd()
    36  	if err != nil {
    37  		return "", err
    38  	}
    39  
    40  	detected, err := getter.Detect(rulePath, cwd, getter.Detectors)
    41  	if err != nil {
    42  		return "", err
    43  	}
    44  
    45  	// File getters are assumed to be a local path reference, so pass through the original path.
    46  	if strings.HasPrefix(detected, "file") {
    47  		return rulePath, nil
    48  	}
    49  
    50  	// At this point we assume the getter URL is a remote URL, so we start the process of downloading it to a temp dir.
    51  
    52  	// First, check if we had already downloaded the source and it is in our cache.
    53  	baseDir, subDir := getter.SourceDirSubdir(rulePath)
    54  	downloadPath, hasDownloaded := policyDirCache.Load(baseDir)
    55  	if hasDownloaded {
    56  		logger.Logf(t, "Previously downloaded %s: returning cached path", baseDir)
    57  		return filepath.Join(downloadPath.(string), subDir), nil
    58  	}
    59  
    60  	// Not downloaded, so use go-getter to download the remote source to a temp dir.
    61  	tempDir, err := ioutil.TempDir("", "terratest-opa-policy-*")
    62  	if err != nil {
    63  		return "", err
    64  	}
    65  	// go-getter doesn't work if you give it a directory that already exists, so we add an additional path in the
    66  	// tempDir to make sure we feed a directory that doesn't exist yet.
    67  	tempDir = filepath.Join(tempDir, "getter")
    68  
    69  	logger.Logf(t, "Downloading %s to temp dir %s", rulePath, tempDir)
    70  	if err := getter.GetAny(tempDir, baseDir); err != nil {
    71  		return "", err
    72  	}
    73  	policyDirCache.Store(baseDir, tempDir)
    74  	return filepath.Join(tempDir, subDir), nil
    75  }