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 }