1
- use testcontainers:: {
2
- core:: { ContainerPort , WaitFor } ,
3
- Image ,
4
- } ;
1
+ use testcontainers:: { core:: { ContainerPort , WaitFor } , Image , CopyDataSource , CopyToContainer , } ;
2
+ use std:: collections:: BTreeMap ;
3
+ use std:: borrow:: Cow ;
5
4
6
5
const NAME : & str = "valkey/valkey" ;
7
- const TAG : & str = "8.0.1 -alpine" ;
6
+ const TAG : & str = "8.0.2 -alpine" ;
8
7
9
8
/// Default port (6379) on which Valkey is exposed
10
9
pub const VALKEY_PORT : ContainerPort = ContainerPort :: Tcp ( 6379 ) ;
@@ -42,10 +41,63 @@ pub const VALKEY_PORT: ContainerPort = ContainerPort::Tcp(6379);
42
41
/// [`VALKEY_PORT`]: super::VALKEY_PORT
43
42
#[ derive( Debug , Default , Clone ) ]
44
43
pub struct Valkey {
45
- /// (remove if there is another variable)
46
- /// Field is included to prevent this struct to be a unit struct.
47
- /// This allows extending functionality (and thus further variables) without breaking changes
48
- _priv : ( ) ,
44
+ env_vars : BTreeMap < String , String > ,
45
+ tag : Option < String > ,
46
+ copy_to_container : Vec < CopyToContainer > ,
47
+ }
48
+
49
+ impl Valkey {
50
+ /// Create a new Valkey instance with the latest image.
51
+ ///
52
+ /// # Example
53
+ /// ```
54
+ /// use testcontainers_modules::{
55
+ /// testcontainers::runners::SyncRunner,
56
+ /// valkey::{Valkey, VALKEY_PORT},
57
+ /// };
58
+ ///
59
+ /// let valkey_instance = Valkey::latest().start().unwrap();
60
+ /// ```
61
+ pub fn latest ( ) -> Self {
62
+ Self {
63
+ tag : Some ( "latest" . to_string ( ) ) ,
64
+ ..Default :: default ( )
65
+ }
66
+ }
67
+
68
+ /// Add extra flags by passing additional start arguments.
69
+ ///
70
+ /// # Example
71
+ /// ```
72
+ /// use testcontainers_modules::{
73
+ /// testcontainers::runners::SyncRunner,
74
+ /// valkey::{Valkey, VALKEY_PORT},
75
+ /// };
76
+ ///
77
+ /// let valkey_instance = Valkey::default().with_valkey_extra_flags("--maxmemory 2mb").start().unwrap();
78
+ /// ```
79
+ pub fn with_valkey_extra_flags ( self , valkey_extra_flags : & str ) -> Self {
80
+ let mut env_vars = self . env_vars ;
81
+ env_vars. insert ( "VALKEY_EXTRA_FLAGS" . to_string ( ) , valkey_extra_flags. to_string ( ) ) ;
82
+ Self { env_vars, tag : self . tag , copy_to_container : self . copy_to_container }
83
+ }
84
+
85
+ /// Add custom valkey configuration.
86
+ ///
87
+ /// # Example
88
+ /// ```
89
+ /// use testcontainers_modules::{
90
+ /// testcontainers::runners::SyncRunner,
91
+ /// valkey::{Valkey, VALKEY_PORT},
92
+ /// };
93
+ ///
94
+ /// let valkey_instance = Valkey::default().with_valkey_conf("maxmemory 2mb".to_string().into_bytes(),).start().unwrap();
95
+ /// ```
96
+ pub fn with_valkey_conf ( self , valky_conf : impl Into < CopyDataSource > ) -> Self {
97
+ let mut copy_to_container = self . copy_to_container ;
98
+ copy_to_container. push ( CopyToContainer :: new ( valky_conf. into ( ) , "/usr/local/etc/valkey/valkey.conf" ) ) ;
99
+ Self { env_vars : self . env_vars , tag : self . tag , copy_to_container }
100
+ }
49
101
}
50
102
51
103
impl Image for Valkey {
@@ -54,28 +106,76 @@ impl Image for Valkey {
54
106
}
55
107
56
108
fn tag ( & self ) -> & str {
57
- TAG
109
+ self . tag . as_deref ( ) . unwrap_or ( TAG )
58
110
}
59
111
60
112
fn ready_conditions ( & self ) -> Vec < WaitFor > {
61
113
vec ! [ WaitFor :: message_on_stdout( "Ready to accept connections" ) ]
62
114
}
115
+
116
+ fn env_vars ( & self , ) -> impl IntoIterator < Item = ( impl Into < Cow < ' _ , str > > , impl Into < Cow < ' _ , str > > ) > {
117
+ & self . env_vars
118
+ }
119
+
120
+ fn copy_to_sources ( & self ) -> impl IntoIterator < Item = & CopyToContainer > {
121
+ & self . copy_to_container
122
+ }
123
+
124
+ fn cmd ( & self ) -> impl IntoIterator < Item = impl Into < Cow < ' _ , str > > > {
125
+ let command;
126
+ if self . copy_to_container . len ( ) > 0 {
127
+ command = vec ! [ "valkey-server" , "/usr/local/etc/valkey/valkey.conf" ] ;
128
+ } else {
129
+ command = Vec :: new ( ) ;
130
+ }
131
+ command
132
+ }
63
133
}
64
134
65
135
#[ cfg( test) ]
66
136
mod tests {
67
137
use redis:: Commands ;
68
-
69
- use crate :: { testcontainers:: runners:: SyncRunner , valkey:: Valkey } ;
138
+ use std:: collections:: HashMap ;
139
+ use testcontainers:: Image ;
140
+ use crate :: { testcontainers:: runners:: SyncRunner , valkey:: Valkey , valkey:: VALKEY_PORT , valkey:: TAG } ;
70
141
71
142
#[ test]
72
143
fn valkey_fetch_an_integer ( ) -> Result < ( ) , Box < dyn std:: error:: Error + ' static > > {
73
144
let _ = pretty_env_logger:: try_init ( ) ;
74
145
let node = Valkey :: default ( ) . start ( ) ?;
146
+
147
+ let tag = node. image ( ) . tag . clone ( ) ;
148
+ assert_eq ! ( None , tag) ;
149
+ let tag_from_method = node. image ( ) . tag ( ) ;
150
+ assert_eq ! ( TAG , tag_from_method) ;
151
+ assert_eq ! ( 0 , node. image( ) . copy_to_container. len( ) ) ;
152
+
75
153
let host_ip = node. get_host ( ) ?;
76
- let host_port = node. get_host_port_ipv4 ( 6379 ) ?;
154
+ let host_port = node. get_host_port_ipv4 ( VALKEY_PORT ) ?;
77
155
let url = format ! ( "redis://{host_ip}:{host_port}" ) ;
156
+ let client = redis:: Client :: open ( url. as_ref ( ) ) . unwrap ( ) ;
157
+ let mut con = client. get_connection ( ) . unwrap ( ) ;
158
+
159
+ con. set :: < _ , _ , ( ) > ( "my_key" , 42 ) . unwrap ( ) ;
160
+ let result: i64 = con. get ( "my_key" ) . unwrap ( ) ;
161
+ assert_eq ! ( 42 , result) ;
162
+ Ok ( ( ) )
163
+ }
164
+
165
+ #[ test]
166
+ fn valkey_latest ( ) -> Result < ( ) , Box < dyn std:: error:: Error + ' static > > {
167
+ let _ = pretty_env_logger:: try_init ( ) ;
168
+ let node = Valkey :: latest ( ) . start ( ) ?;
78
169
170
+ let tag = node. image ( ) . tag . clone ( ) ;
171
+ assert_eq ! ( Some ( "latest" . to_string( ) ) , tag) ;
172
+ let tag_from_method = node. image ( ) . tag ( ) ;
173
+ assert_eq ! ( "latest" , tag_from_method) ;
174
+ assert_eq ! ( 0 , node. image( ) . copy_to_container. len( ) ) ;
175
+
176
+ let host_ip = node. get_host ( ) ?;
177
+ let host_port = node. get_host_port_ipv4 ( VALKEY_PORT ) ?;
178
+ let url = format ! ( "redis://{host_ip}:{host_port}" ) ;
79
179
let client = redis:: Client :: open ( url. as_ref ( ) ) . unwrap ( ) ;
80
180
let mut con = client. get_connection ( ) . unwrap ( ) ;
81
181
@@ -84,4 +184,48 @@ mod tests {
84
184
assert_eq ! ( 42 , result) ;
85
185
Ok ( ( ) )
86
186
}
187
+
188
+ #[ test]
189
+ fn valkey_extra_flags ( ) -> Result < ( ) , Box < dyn std:: error:: Error + ' static > > {
190
+ let _ = pretty_env_logger:: try_init ( ) ;
191
+ let node = Valkey :: default ( ) . with_valkey_extra_flags ( "--maxmemory 2mb" ) . start ( ) ?;
192
+ let tag = node. image ( ) . tag . clone ( ) ;
193
+ assert_eq ! ( None , tag) ;
194
+ let tag_from_method = node. image ( ) . tag ( ) ;
195
+ assert_eq ! ( TAG , tag_from_method) ;
196
+ assert_eq ! ( 0 , node. image( ) . copy_to_container. len( ) ) ;
197
+
198
+ let host_ip = node. get_host ( ) ?;
199
+ let host_port = node. get_host_port_ipv4 ( VALKEY_PORT ) ?;
200
+ let url = format ! ( "redis://{host_ip}:{host_port}" ) ;
201
+
202
+ let client = redis:: Client :: open ( url. as_ref ( ) ) . unwrap ( ) ;
203
+ let mut con = client. get_connection ( ) . unwrap ( ) ;
204
+ let max_memory: HashMap < String , isize > = redis:: cmd ( "CONFIG" ) . arg ( "GET" ) . arg ( "maxmemory" ) . query ( & mut con) . unwrap ( ) ;
205
+ let max = * max_memory. get ( "maxmemory" ) . unwrap ( ) ;
206
+ assert_eq ! ( 2097152 , max) ;
207
+ Ok ( ( ) )
208
+ }
209
+
210
+ #[ test]
211
+ fn valkey_conf ( ) -> Result < ( ) , Box < dyn std:: error:: Error + ' static > > {
212
+ let _ = pretty_env_logger:: try_init ( ) ;
213
+ let node = Valkey :: default ( ) . with_valkey_conf ( "maxmemory 2mb" . to_string ( ) . into_bytes ( ) , ) . start ( ) ?;
214
+ let tag = node. image ( ) . tag . clone ( ) ;
215
+ assert_eq ! ( None , tag) ;
216
+ let tag_from_method = node. image ( ) . tag ( ) ;
217
+ assert_eq ! ( TAG , tag_from_method) ;
218
+ assert_eq ! ( 1 , node. image( ) . copy_to_container. len( ) ) ;
219
+
220
+ let host_ip = node. get_host ( ) ?;
221
+ let host_port = node. get_host_port_ipv4 ( VALKEY_PORT ) ?;
222
+ let url = format ! ( "redis://{host_ip}:{host_port}" ) ;
223
+
224
+ let client = redis:: Client :: open ( url. as_ref ( ) ) . unwrap ( ) ;
225
+ let mut con = client. get_connection ( ) . unwrap ( ) ;
226
+ let max_memory: HashMap < String , isize > = redis:: cmd ( "CONFIG" ) . arg ( "GET" ) . arg ( "maxmemory" ) . query ( & mut con) . unwrap ( ) ;
227
+ let max = * max_memory. get ( "maxmemory" ) . unwrap ( ) ;
228
+ assert_eq ! ( 2097152 , max) ;
229
+ Ok ( ( ) )
230
+ }
87
231
}
0 commit comments