github.com/tommi2day/tnscli@v0.0.0-20240401211958-338fc0647b73/cmd/oracle_docker_test.go (about) 1 package cmd 2 3 import ( 4 "database/sql" 5 "fmt" 6 "os" 7 "time" 8 9 "github.com/tommi2day/tnscli/test" 10 11 "github.com/ory/dockertest/v3" 12 "github.com/ory/dockertest/v3/docker" 13 "github.com/tommi2day/gomodules/common" 14 ) 15 16 // DBPort is the port of the Oracle DB to access (default:21521) 17 const DBPort = "21521" 18 const repo = "docker.io/gvenzl/oracle-free" 19 const repoTag = "23.3-slim" 20 const containerTimeout = 600 21 22 // SYSTEMUSER is the name of the default DBA user 23 const SYSTEMUSER = "system" 24 25 // SYSTEMSERVICE is the name of the root service 26 const SYSTEMSERVICE = "FREE" 27 28 var containerName string 29 30 // prepareContainer create an Oracle Docker Container 31 func prepareContainer() (container *dockertest.Resource, err error) { 32 if os.Getenv("SKIP_ORACLE") != "" { 33 err = fmt.Errorf("skipping ORACLE Container in CI environment") 34 return 35 } 36 containerName = os.Getenv("CONTAINER_NAME") 37 if containerName == "" { 38 containerName = "tnscli-oracledb" 39 } 40 var pool *dockertest.Pool 41 pool, err = common.GetDockerPool() 42 if err != nil { 43 return 44 } 45 46 vendorImagePrefix := os.Getenv("VENDOR_IMAGE_PREFIX") 47 repoString := vendorImagePrefix + repo 48 49 fmt.Printf("Try to start docker container for %s:%s\n", repoString, repoTag) 50 container, err = pool.RunWithOptions(&dockertest.RunOptions{ 51 Repository: repoString, 52 Tag: repoTag, 53 54 Hostname: containerName, 55 Name: containerName, 56 Env: []string{ 57 "ORACLE_PASSWORD=" + DBPASSWORD, 58 }, 59 ExposedPorts: []string{"1521"}, 60 // need fixed mapping here 61 PortBindings: map[docker.Port][]docker.PortBinding{ 62 "1521": { 63 {HostIP: "0.0.0.0", HostPort: DBPort}, 64 }, 65 }, 66 Mounts: []string{ 67 test.TestDir + "/docker/oracle-db:/container-entrypoint-initdb.d:ro", 68 }, 69 }, func(config *docker.HostConfig) { 70 // set AutoRemove to true so that stopped container goes away by itself 71 config.AutoRemove = true 72 config.RestartPolicy = docker.RestartPolicy{Name: "no"} 73 }) 74 75 if err != nil { 76 err = fmt.Errorf("error starting DB docker %s container: %v", containerName, err) 77 _ = pool.Purge(container) 78 return 79 } 80 81 start := time.Now() 82 err = WaitForOracle(pool) 83 if err != nil { 84 _ = pool.Purge(container) 85 return 86 } 87 elapsed := time.Since(start) 88 fmt.Printf("DB Container is available after %s\n", elapsed.Round(time.Millisecond)) 89 err = nil 90 return 91 } 92 93 // WaitForOracle waits to successfully connect to Oracle 94 func WaitForOracle(pool *dockertest.Pool) (err error) { 95 if os.Getenv("SKIP_ORACLE") != "" { 96 err = fmt.Errorf("skipping ORACLE Container in CI environment") 97 return 98 } 99 100 if pool == nil { 101 pool, err = common.GetDockerPool() 102 if err != nil { 103 return 104 } 105 } 106 107 pool.MaxWait = containerTimeout * time.Second 108 target = fmt.Sprintf("oracle://%s:%s@%s:%s/%s", SYSTEMUSER, DBPASSWORD, dbhost, DBPort, SYSTEMSERVICE) 109 fmt.Printf("Wait to successfully init db with %s (max %ds)...\n", target, containerTimeout) 110 start := time.Now() 111 if err = pool.Retry(func() error { 112 var err error 113 var db *sql.DB 114 db, err = sql.Open("oracle", target) 115 if err != nil { 116 // cannot open connection 117 return err 118 } 119 err = db.Ping() 120 if err != nil { 121 // db not answering 122 return err 123 } 124 // check if init_done table exists, then we are ready 125 checkSQL := "select count(*) from init_done" 126 row := db.QueryRow(checkSQL) 127 var count int64 128 err = row.Scan(&count) 129 if err != nil { 130 // query failed, final init table not there 131 return err 132 } 133 return nil 134 }); err != nil { 135 fmt.Printf("DB Container not ready: %s", err) 136 return 137 } 138 elapsed := time.Since(start) 139 fmt.Printf("DB Ready is available after %s\n", elapsed.Round(time.Millisecond)) 140 // wait for init scripts finished 141 err = nil 142 return 143 }