11use anyhow:: Result ;
22use spin_core:: wasmtime:: component:: Resource ;
33use spin_world:: spin:: postgres3_0_0:: postgres:: { self as v3} ;
4- use spin_world:: spin:: postgres4_0_0 :: postgres:: { self as v4} ;
4+ use spin_world:: spin:: postgres4_1_0 :: postgres:: { self as v4} ;
55use spin_world:: v1:: postgres as v1;
66use spin_world:: v1:: rdbms_types as v1_types;
77use spin_world:: v2:: postgres:: { self as v2} ;
@@ -17,11 +17,12 @@ impl<CF: ClientFactory> InstanceState<CF> {
1717 async fn open_connection < Conn : ' static > (
1818 & mut self ,
1919 address : & str ,
20+ root_ca : Option < & String > ,
2021 ) -> Result < Resource < Conn > , v4:: Error > {
2122 self . connections
2223 . push (
2324 self . client_factory
24- . get_client ( address)
25+ . get_client ( address, root_ca )
2526 . await
2627 . map_err ( |e| v4:: Error :: ConnectionFailed ( format ! ( "{e:?}" ) ) ) ?,
2728 )
@@ -102,7 +103,7 @@ impl<CF: ClientFactory> v3::HostConnection for InstanceState<CF> {
102103
103104 self . ensure_address_allowed ( & address) . await ?;
104105
105- Ok ( self . open_connection ( & address) . await ?)
106+ Ok ( self . open_connection ( & address, None ) . await ?)
106107 }
107108
108109 #[ instrument( name = "spin_outbound_pg.execute" , skip( self , connection, params) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "postgresql" , otel. name = statement) ) ]
@@ -140,14 +141,67 @@ impl<CF: ClientFactory> v3::HostConnection for InstanceState<CF> {
140141 }
141142}
142143
144+ pub ( crate ) struct ConnectionBuilder {
145+ address : String ,
146+ root_ca : Option < String > ,
147+ }
148+
149+ impl < CF : ClientFactory > v4:: HostConnectionBuilder for InstanceState < CF > {
150+ async fn new ( & mut self , address : String ) -> Result < Resource < v4:: ConnectionBuilder > > {
151+ let builder = ConnectionBuilder {
152+ address,
153+ root_ca : None ,
154+ } ;
155+ let rep = self
156+ . builders
157+ . push ( builder)
158+ . map_err ( |_| anyhow:: anyhow!( "out of builder table space" ) ) ?;
159+ let rsrc = Resource :: new_own ( rep) ;
160+ Ok ( rsrc)
161+ }
162+
163+ async fn set_ca_root (
164+ & mut self ,
165+ self_ : Resource < v4:: ConnectionBuilder > ,
166+ certificate : String ,
167+ ) -> Result < ( ) , v4:: Error > {
168+ let builder = self
169+ . builders
170+ . get_mut ( self_. rep ( ) )
171+ . ok_or_else ( || v4:: Error :: ConnectionFailed ( "no builder found" . into ( ) ) ) ?;
172+ builder. root_ca = Some ( certificate) ;
173+ Ok ( ( ) )
174+ }
175+
176+ async fn build (
177+ & mut self ,
178+ self_ : Resource < v4:: ConnectionBuilder > ,
179+ ) -> Result < Resource < v4:: Connection > , v4:: Error > {
180+ let builder = self
181+ . builders
182+ . get_mut ( self_. rep ( ) )
183+ . ok_or_else ( || v4:: Error :: ConnectionFailed ( "no builder found" . into ( ) ) ) ?;
184+ // borrow checker gets pedantic here, so we need to outsmart it
185+ let address = builder. address . clone ( ) ;
186+ let root_ca = builder. root_ca . clone ( ) ;
187+ let conn = self . open_connection ( & address, root_ca. as_ref ( ) ) . await ;
188+ conn
189+ }
190+
191+ async fn drop ( & mut self , builder : Resource < v4:: ConnectionBuilder > ) -> Result < ( ) > {
192+ self . builders . remove ( builder. rep ( ) ) ;
193+ Ok ( ( ) )
194+ }
195+ }
196+
143197impl < CF : ClientFactory > v4:: HostConnection for InstanceState < CF > {
144198 #[ instrument( name = "spin_outbound_pg.open" , skip( self , address) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "postgresql" , db. address = Empty , server. port = Empty , db. namespace = Empty ) ) ]
145199 async fn open ( & mut self , address : String ) -> Result < Resource < v4:: Connection > , v4:: Error > {
146200 spin_factor_outbound_networking:: record_address_fields ( & address) ;
147201
148202 self . ensure_address_allowed ( & address) . await ?;
149203
150- self . open_connection ( & address) . await
204+ self . open_connection ( & address, None ) . await
151205 }
152206
153207 #[ instrument( name = "spin_outbound_pg.execute" , skip( self , connection, params) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "postgresql" , otel. name = statement) ) ]
@@ -204,7 +258,7 @@ impl<CF: ClientFactory> v4::Host for InstanceState<CF> {
204258macro_rules! delegate {
205259 ( $self: ident. $name: ident( $address: expr, $( $arg: expr) ,* ) ) => { {
206260 $self. ensure_address_allowed( & $address) . await ?;
207- let connection = match $self. open_connection( & $address) . await {
261+ let connection = match $self. open_connection( & $address, None ) . await {
208262 Ok ( c) => c,
209263 Err ( e) => return Err ( e. into( ) ) ,
210264 } ;
@@ -224,7 +278,7 @@ impl<CF: ClientFactory> v2::HostConnection for InstanceState<CF> {
224278
225279 self . ensure_address_allowed ( & address) . await ?;
226280
227- Ok ( self . open_connection ( & address) . await ?)
281+ Ok ( self . open_connection ( & address, None ) . await ?)
228282 }
229283
230284 #[ instrument( name = "spin_outbound_pg.execute" , skip( self , connection, params) , err( level = Level :: INFO ) , fields( otel. kind = "client" , db. system = "postgresql" , otel. name = statement) ) ]
0 commit comments