@@ -17,14 +17,21 @@ limitations under the License.
1717package k0smotronio
1818
1919import (
20+ "os"
21+ "os/exec"
22+ "strings"
2023 "testing"
2124
2225 km "github.com/k0sproject/k0smotron/api/k0smotron.io/v1beta1"
2326 "github.com/stretchr/testify/assert"
27+ "github.com/stretchr/testify/require"
28+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+ "k8s.io/apimachinery/pkg/runtime"
30+ "sigs.k8s.io/controller-runtime/pkg/client/fake"
2431)
2532
2633func TestGetControllerFlags (t * testing.T ) {
27- var tests = []struct {
34+ tests : = []struct {
2835 name string
2936 kmc km.Cluster
3037 result string
@@ -60,3 +67,130 @@ func TestGetControllerFlags(t *testing.T) {
6067 assert .Equal (t , test .result , getControllerFlags (& test .kmc ), test .name )
6168 }
6269}
70+
71+ func TestKineDataSourceURLSubstitution (t * testing.T ) {
72+ if _ , err := exec .LookPath ("sed" ); err != nil {
73+ t .Skip ("sed command not available, skipping test" )
74+ }
75+
76+ tests := []struct {
77+ name string
78+ kineDataSourceURL string
79+ expectedSubstitution string
80+ }{
81+ {
82+ name : "URL without ampersands" ,
83+ kineDataSourceURL : "postgres://user:pass@host:5432/db?sslmode=disable" ,
84+ expectedSubstitution : "postgres://user:pass@host:5432/db?sslmode=disable" ,
85+ },
86+ {
87+ name : "URL with single ampersand" ,
88+ kineDataSourceURL : "postgres://user:pass@host:5432/db?param1=value1¶m2=value2" ,
89+ expectedSubstitution : "postgres://user:pass@host:5432/db?param1=value1¶m2=value2" ,
90+ },
91+ {
92+ name : "URL with multiple ampersands" ,
93+ kineDataSourceURL : "postgres://user:pass@host:5432/db?param1=value1¶m2=value2¶m3=value3" ,
94+ expectedSubstitution : "postgres://user:pass@host:5432/db?param1=value1¶m2=value2¶m3=value3" ,
95+ },
96+ {
97+ name : "URL with ampersand in password" ,
98+ kineDataSourceURL : "postgres://user:pa&ss@host:5432/db" ,
99+ expectedSubstitution : "postgres://user:pa&ss@host:5432/db" ,
100+ },
101+ }
102+
103+ for _ , tc := range tests {
104+ t .Run (tc .name , func (t * testing.T ) {
105+ kmc := & km.Cluster {
106+ ObjectMeta : metav1.ObjectMeta {
107+ Name : "test-cluster" ,
108+ Namespace : "default" ,
109+ },
110+ Spec : km.ClusterSpec {
111+ Service : km.ServiceSpec {
112+ APIPort : 6443 ,
113+ },
114+ KineDataSourceURL : tc .kineDataSourceURL ,
115+ },
116+ }
117+
118+ scheme := runtime .NewScheme ()
119+ require .NoError (t , km .AddToScheme (scheme ))
120+
121+ client := fake .NewClientBuilder ().
122+ WithScheme (scheme ).
123+ WithObjects (kmc ).
124+ Build ()
125+
126+ scope := & kmcScope {
127+ client : client ,
128+ }
129+
130+ cm , err := scope .generateEntrypointCM (kmc )
131+ require .NoError (t , err )
132+
133+ entrypointScript := cm .Data ["k0smotron-entrypoint.sh" ]
134+
135+ lines := strings .Split (entrypointScript , "\n " )
136+ var printfLine , sedLine string
137+ for _ , line := range lines {
138+ line = strings .TrimSpace (line )
139+ if strings .Contains (line , "escaped_url=$(printf" ) && strings .Contains (line , "K0SMOTRON_KINE_DATASOURCE_URL" ) {
140+ printfLine = line
141+ }
142+ if strings .Contains (line , "sed -i" ) && strings .Contains (line , "$escaped_url" ) {
143+ sedLine = line
144+ }
145+ }
146+ require .NotEmpty (t , printfLine , "printf command not found in entrypoint script" )
147+ require .NotEmpty (t , sedLine , "sed command not found in entrypoint script" )
148+
149+ testK0sConfig := `apiVersion: k0s.k0sproject.io/v1beta1
150+ kind: ClusterConfig
151+ metadata:
152+ name: k0s
153+ spec:
154+ storage:
155+ type: kine
156+ kine:
157+ dataSource: ` + kineDataSourceURLPlaceholder + `
158+ api:
159+ port: 6443`
160+
161+ tmpFile , err := os .CreateTemp ("" , "k0s-test-*.yaml" )
162+ require .NoError (t , err )
163+ t .Cleanup (func () { os .Remove (tmpFile .Name ()) })
164+
165+ _ , err = tmpFile .WriteString (testK0sConfig )
166+ require .NoError (t , err )
167+ require .NoError (t , tmpFile .Close ())
168+
169+ os .Setenv ("K0SMOTRON_KINE_DATASOURCE_URL" , tc .kineDataSourceURL )
170+ t .Cleanup (func () { os .Unsetenv ("K0SMOTRON_KINE_DATASOURCE_URL" ) })
171+
172+ actualSedCmd := strings .Replace (sedLine , "/etc/k0s/k0s.yaml" , tmpFile .Name (), 1 )
173+
174+ combinedScript := printfLine + "\n " + actualSedCmd
175+
176+ cmd := exec .Command ("sh" , "-c" , combinedScript )
177+ cmd .Env = append (os .Environ (), "K0SMOTRON_KINE_DATASOURCE_URL=" + tc .kineDataSourceURL )
178+
179+ output , err := cmd .CombinedOutput ()
180+ if err != nil {
181+ t .Logf ("Combined script: %s" , combinedScript )
182+ t .Logf ("Script output: %s" , string (output ))
183+ }
184+ require .NoError (t , err , "Shell script failed: %s" , string (output ))
185+
186+ modifiedContent , err := os .ReadFile (tmpFile .Name ())
187+ require .NoError (t , err )
188+
189+ modifiedStr := string (modifiedContent )
190+ assert .Contains (t , modifiedStr , tc .expectedSubstitution ,
191+ "Expected URL %q not found in modified config" , tc .expectedSubstitution )
192+ assert .NotContains (t , modifiedStr , kineDataSourceURLPlaceholder ,
193+ "Placeholder should be completely replaced" )
194+ })
195+ }
196+ }
0 commit comments