github.com/quay/claircore@v1.5.28/test/integration/github_actions.go (about) 1 package integration 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "os/exec" 9 "path/filepath" 10 "sort" 11 "testing" 12 13 "github.com/jackc/pgx/v4/pgxpool" 14 ) 15 16 func startGithubActions(t testing.TB) func() { 17 const config string = `# Installed by claircore's test harness. 18 fsync = off 19 ` 20 const debugConfig = `session_preload_libraries = 'auto_explain' 21 auto_explain.log_min_duration = 0 22 auto_explain.log_analyze = true 23 auto_explain.log_buffers = true 24 auto_explain.log_wal = true 25 ` 26 // GitHub Actions has Postgres installed, so we can just run some commands 27 // to set it up: 28 return func() { 29 // On success, this function leaves [pkgDB] unset, so that the test 30 // binary's teardown logic leaves it running as if it's an external 31 // database. Which it is, just happening to be one that some test or 32 // previous shell command started. 33 defer func() { 34 if t.Failed() { 35 return 36 } 37 // Just fill out the config and it's all good to go. 38 cfg, err := pgxpool.ParseConfig(`host=/var/run/postgresql user=postgres database=postgres sslmode=disable`) 39 if err != nil { 40 t.Fatal(err) 41 } 42 pkgConfig = cfg 43 }() 44 // See if a previous test binary already enabled the service: 45 cmd := exec.Command("sudo", "systemctl", "--quiet", "is-active", "postgresql.service") 46 // BUG(hank) If some other process starts "postgresql.service", it need 47 // to ensure that local passwordless authentication is configured. If 48 // processes after a test using this package needs any other 49 // authentication setup, be aware that this package overwrites the 50 // default "pg_hba.conf" with a minimal, local-only configuration. 51 if err := cmd.Run(); err == nil { 52 // Looking for exit 0 to indicate we don't need to do anything. 53 return 54 } 55 56 // Figure out the destination path. 57 ms, _ := filepath.Glob(`/etc/postgresql/*/main/conf.d`) 58 sort.Strings(ms) 59 confd := ms[0] 60 // TODO(hank) This lock is too broad, it covers the entire test when it 61 // really only needs to cover this function. 62 if !lockDir(t, confd) { 63 // If this process couldn't get an exclusive lock, then another 64 // process configured everything and this one should be able to just 65 // return here. 66 return 67 } 68 69 // Lay down the config snippet into a temporary directory. 70 f, err := os.Create(filepath.Join(t.TempDir(), "clair.conf")) 71 if err != nil { 72 t.Fatal(err) 73 } 74 defer f.Close() 75 if _, err := io.WriteString(f, config); err != nil { 76 t.Fatal(err) 77 } 78 if testing.Verbose() { 79 if _, err := io.WriteString(f, debugConfig); err != nil { 80 t.Fatal(err) 81 } 82 } 83 if exp, ok := os.LookupEnv("PGEXPLAIN_FORMAT"); ok { 84 fmt.Fprintf(f, `auto_explain.log_format = %q\n`, exp) 85 } 86 if err := f.Sync(); err != nil { 87 t.Fatal(err) 88 } 89 90 // Use sudo+install because that's just a much easier way to put a file 91 // in a specific place with specific permissions. 92 var buf bytes.Buffer 93 cmd = exec.Command("sudo", "install", "-m", "0644", "-o", "postgres", f.Name(), confd) 94 cmd.Stdout = &buf 95 cmd.Stderr = &buf 96 if err := cmd.Run(); err != nil { 97 t.Logf("running %+v: %v", cmd.Args, err) 98 t.Logf("output:\n%s", buf.String()) 99 t.FailNow() 100 } 101 buf.Reset() 102 // Really hose up the database security model: 103 cmd = exec.Command("sudo", "sh", "-c", "echo local all all trust >"+filepath.Join(filepath.Dir(confd), "pg_hba.conf")) 104 cmd.Stdout = &buf 105 cmd.Stderr = &buf 106 if err := cmd.Run(); err != nil { 107 t.Logf("running %+v: %v", cmd.Args, err) 108 t.Logf("output:\n%s", buf.String()) 109 t.FailNow() 110 } 111 buf.Reset() 112 // Start the database engine. 113 cmd = exec.Command("sudo", "systemctl", "start", "postgresql.service") 114 cmd.Stdout = &buf 115 cmd.Stderr = &buf 116 if err := cmd.Run(); err != nil { 117 t.Logf("running %+v: %v", cmd.Args, err) 118 t.Logf("output:\n%s", buf.String()) 119 t.FailNow() 120 } 121 } 122 }