summaryrefslogtreecommitdiff
path: root/vendor/github.com/testcontainers/testcontainers-go/internal/config/config.go
blob: dda7e282bcf5b23bac7ccdf74f67765bb820b6f1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package config

import (
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"sync"
	"time"

	"github.com/magiconair/properties"
)

const ReaperDefaultImage = "testcontainers/ryuk:0.12.0"

var (
	tcConfig     Config
	tcConfigOnce = new(sync.Once)
)

// testcontainersConfig {

// Config represents the configuration for Testcontainers.
// User values are read from ~/.testcontainers.properties file which can be overridden
// using the specified environment variables. For more information, see [Custom Configuration].
//
// The Ryuk prefixed fields controls the [Garbage Collector] feature, which ensures that
// resources are cleaned up after the test execution.
//
// [Garbage Collector]: https://golang.testcontainers.org/features/garbage_collector/
// [Custom Configuration]: https://golang.testcontainers.org/features/configuration/
type Config struct {
	// Host is the address of the Docker daemon.
	//
	// Environment variable: DOCKER_HOST
	Host string `properties:"docker.host,default="`

	// TLSVerify is a flag to enable or disable TLS verification when connecting to a Docker daemon.
	//
	// Environment variable: DOCKER_TLS_VERIFY
	TLSVerify int `properties:"docker.tls.verify,default=0"`

	// CertPath is the path to the directory containing the Docker certificates.
	// This is used when connecting to a Docker daemon over TLS.
	//
	// Environment variable: DOCKER_CERT_PATH
	CertPath string `properties:"docker.cert.path,default="`

	// HubImageNamePrefix is the prefix used for the images pulled from the Docker Hub.
	// This is useful when running tests in environments with restricted internet access.
	//
	// Environment variable: TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX
	HubImageNamePrefix string `properties:"hub.image.name.prefix,default="`

	// RyukDisabled is a flag to enable or disable the Garbage Collector.
	// Setting this to true will prevent testcontainers from automatically cleaning up
	// resources, which is particularly important in tests which timeout as they
	// don't run test clean up.
	//
	// Environment variable: TESTCONTAINERS_RYUK_DISABLED
	RyukDisabled bool `properties:"ryuk.disabled,default=false"`

	// RyukPrivileged is a flag to enable or disable the privileged mode for the Garbage Collector container.
	// Setting this to true will run the Garbage Collector container in privileged mode.
	//
	// Environment variable: TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED
	RyukPrivileged bool `properties:"ryuk.container.privileged,default=false"`

	// RyukReconnectionTimeout is the time to wait before attempting to reconnect to the Garbage Collector container.
	//
	// Environment variable: RYUK_RECONNECTION_TIMEOUT
	RyukReconnectionTimeout time.Duration `properties:"ryuk.reconnection.timeout,default=10s"`

	// RyukConnectionTimeout is the time to wait before timing out when connecting to the Garbage Collector container.
	//
	// Environment variable: RYUK_CONNECTION_TIMEOUT
	RyukConnectionTimeout time.Duration `properties:"ryuk.connection.timeout,default=1m"`

	// RyukVerbose is a flag to enable or disable verbose logging for the Garbage Collector.
	//
	// Environment variable: RYUK_VERBOSE
	RyukVerbose bool `properties:"ryuk.verbose,default=false"`

	// TestcontainersHost is the address of the Testcontainers host.
	//
	// Environment variable: TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE
	TestcontainersHost string `properties:"tc.host,default="`
}

// }

// Read reads from testcontainers properties file, if it exists
// it is possible that certain values get overridden when set as environment variables
func Read() Config {
	tcConfigOnce.Do(func() {
		tcConfig = read()
	})

	return tcConfig
}

// Reset resets the singleton instance of the Config struct,
// allowing to read the configuration again.
// Handy for testing, so do not use it in production code
// This function is not thread-safe
func Reset() {
	tcConfigOnce = new(sync.Once)
}

func read() Config {
	config := Config{}

	applyEnvironmentConfiguration := func(config Config) Config {
		ryukDisabledEnv := os.Getenv("TESTCONTAINERS_RYUK_DISABLED")
		if parseBool(ryukDisabledEnv) {
			config.RyukDisabled = ryukDisabledEnv == "true"
		}

		hubImageNamePrefix := os.Getenv("TESTCONTAINERS_HUB_IMAGE_NAME_PREFIX")
		if hubImageNamePrefix != "" {
			config.HubImageNamePrefix = hubImageNamePrefix
		}

		ryukPrivilegedEnv := os.Getenv("TESTCONTAINERS_RYUK_CONTAINER_PRIVILEGED")
		if parseBool(ryukPrivilegedEnv) {
			config.RyukPrivileged = ryukPrivilegedEnv == "true"
		}

		ryukVerboseEnv := readTestcontainersEnv("RYUK_VERBOSE")
		if parseBool(ryukVerboseEnv) {
			config.RyukVerbose = ryukVerboseEnv == "true"
		}

		ryukReconnectionTimeoutEnv := readTestcontainersEnv("RYUK_RECONNECTION_TIMEOUT")
		if timeout, err := time.ParseDuration(ryukReconnectionTimeoutEnv); err == nil {
			config.RyukReconnectionTimeout = timeout
		}

		ryukConnectionTimeoutEnv := readTestcontainersEnv("RYUK_CONNECTION_TIMEOUT")
		if timeout, err := time.ParseDuration(ryukConnectionTimeoutEnv); err == nil {
			config.RyukConnectionTimeout = timeout
		}

		return config
	}

	home, err := os.UserHomeDir()
	if err != nil {
		return applyEnvironmentConfiguration(config)
	}

	tcProp := filepath.Join(home, ".testcontainers.properties")
	// init from a file
	properties, err := properties.LoadFile(tcProp, properties.UTF8)
	if err != nil {
		return applyEnvironmentConfiguration(config)
	}

	if err := properties.Decode(&config); err != nil {
		fmt.Printf("invalid testcontainers properties file, returning an empty Testcontainers configuration: %v\n", err)
		return applyEnvironmentConfiguration(config)
	}

	return applyEnvironmentConfiguration(config)
}

func parseBool(input string) bool {
	_, err := strconv.ParseBool(input)
	return err == nil
}

// readTestcontainersEnv reads the environment variable with the given name.
// It checks for the environment variable with the given name first, and then
// checks for the environment variable with the given name prefixed with "TESTCONTAINERS_".
func readTestcontainersEnv(envVar string) string {
	value := os.Getenv(envVar)
	if value != "" {
		return value
	}

	// TODO: remove this prefix after the next major release
	const prefix string = "TESTCONTAINERS_"

	return os.Getenv(prefix + envVar)
}