]> source.dussan.org Git - sonarqube.git/blob
3ec1d0e158205184daa88a5164cef2b488aa1220
[sonarqube.git] /
1 /*
2  * SonarQube
3  * Copyright (C) 2009-2024 SonarSource SA
4  * mailto:info AT sonarsource DOT com
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 3 of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19  */
20 package org.sonar.server.telemetry;
21
22 import java.io.ByteArrayInputStream;
23 import java.io.IOException;
24 import java.net.URISyntaxException;
25 import java.nio.file.Paths;
26 import javax.annotation.Nullable;
27 import okhttp3.Call;
28 import okhttp3.MediaType;
29 import okhttp3.OkHttpClient;
30 import okhttp3.Protocol;
31 import okhttp3.Request;
32 import okhttp3.Response;
33 import okhttp3.ResponseBody;
34 import org.junit.Before;
35 import org.junit.Test;
36 import org.mockito.Mockito;
37 import org.sonar.api.utils.System2;
38 import org.sonar.server.platform.ContainerSupport;
39 import org.sonar.server.util.Paths2;
40 import org.sonarqube.ws.MediaTypes;
41
42 import static java.util.Objects.requireNonNull;
43 import static org.assertj.core.api.Assertions.assertThat;
44 import static org.mockito.ArgumentMatchers.any;
45 import static org.mockito.ArgumentMatchers.anyString;
46 import static org.mockito.Mockito.mock;
47 import static org.mockito.Mockito.when;
48 import static org.sonar.server.telemetry.CloudUsageDataProvider.DOCKER_RUNNING;
49 import static org.sonar.server.telemetry.CloudUsageDataProvider.KUBERNETES_SERVICE_HOST;
50 import static org.sonar.server.telemetry.CloudUsageDataProvider.KUBERNETES_SERVICE_PORT;
51 import static org.sonar.server.telemetry.CloudUsageDataProvider.SONAR_HELM_CHART_VERSION;
52
53 public class CloudUsageDataProviderTest {
54
55   private final System2 system2 = Mockito.mock(System2.class);
56   private final Paths2 paths2 = Mockito.mock(Paths2.class);
57   private final OkHttpClient httpClient = Mockito.mock(OkHttpClient.class);
58   private final ContainerSupport containerSupport = mock(ContainerSupport.class);
59   private final ProcessBuilder processBuilder = mock(ProcessBuilder.class);
60   private final CloudUsageDataProvider underTest = new CloudUsageDataProvider(containerSupport, system2, paths2, () -> processBuilder,
61     httpClient);
62
63   @Before
64   public void setUp() throws Exception {
65     when(system2.envVariable(KUBERNETES_SERVICE_HOST)).thenReturn("localhost");
66     when(system2.envVariable(KUBERNETES_SERVICE_PORT)).thenReturn("443");
67
68     mockHttpClientCall(200, "OK", ResponseBody.create("""
69       {
70           "major": "1",
71           "minor": "25",
72           "gitVersion": "v1.25.3",
73           "gitCommit": "434bfd82814af038ad94d62ebe59b133fcb50506",
74           "gitTreeState": "clean",
75           "buildDate": "2022-11-02T03:24:50Z",
76           "goVersion": "go1.19.2",
77           "compiler": "gc",
78           "platform": "linux/arm64"
79       }
80       """, MediaType.parse(MediaTypes.JSON)));
81   }
82
83   private void mockHttpClientCall(int code, String message, @Nullable ResponseBody body) throws IOException {
84     Call callMock = mock(Call.class);
85     when(callMock.execute()).thenReturn(new Response.Builder()
86       .request(new Request.Builder().url("http://any.test/").build())
87       .protocol(Protocol.HTTP_1_1)
88       .code(code)
89       .message(message)
90       .body(body)
91       .build());
92     when(httpClient.newCall(any())).thenReturn(callMock);
93   }
94
95   @Test
96   public void containerRuntime_whenContainerSupportContextExists_shouldNotBeNull() {
97     when(containerSupport.getContainerContext()).thenReturn("docker");
98     assertThat(underTest.getCloudUsage().containerRuntime()).isEqualTo("docker");
99   }
100
101   @Test
102   public void containerRuntime_whenContainerSupportContextMissing_shouldBeNull() {
103     when(containerSupport.getContainerContext()).thenReturn(null);
104     assertThat(underTest.getCloudUsage().containerRuntime()).isNull();
105   }
106
107   @Test
108   public void kubernetes_whenEnvVarExists_shouldReturnTrue() {
109     assertThat(underTest.getCloudUsage().kubernetes()).isTrue();
110   }
111
112   @Test
113   public void kubernetes_whenEnvVarDoesNotExist_shouldReturnFalse() {
114     when(system2.envVariable(KUBERNETES_SERVICE_HOST)).thenReturn(null);
115     assertThat(underTest.getCloudUsage().kubernetes()).isFalse();
116   }
117
118   @Test
119   public void kubernetesVersion_whenOnKubernetes_shouldReturnValue() {
120     assertThat(underTest.getCloudUsage().kubernetesVersion()).isEqualTo("1.25");
121   }
122
123   @Test
124   public void kubernetesVersion_whenNotOnKubernetes_shouldReturnNull() {
125     when(system2.envVariable(KUBERNETES_SERVICE_HOST)).thenReturn(null);
126     assertThat(underTest.getCloudUsage().kubernetesVersion()).isNull();
127   }
128
129   @Test
130   public void kubernetesVersion_whenApiCallFails_shouldReturnNull() throws IOException {
131     mockHttpClientCall(404, "not found", null);
132     assertThat(underTest.getCloudUsage().kubernetesVersion()).isNull();
133   }
134
135   @Test
136   public void kubernetesPlatform_whenOnKubernetes_shouldReturnValue() {
137     assertThat(underTest.getCloudUsage().kubernetesPlatform()).isEqualTo("linux/arm64");
138   }
139
140   @Test
141   public void kubernetesPlatform_whenNotOnKubernetes_shouldReturnNull() {
142     when(system2.envVariable(KUBERNETES_SERVICE_HOST)).thenReturn(null);
143     assertThat(underTest.getCloudUsage().kubernetesPlatform()).isNull();
144   }
145
146   @Test
147   public void kubernetesPlatform_whenApiCallFails_shouldReturnNull() throws IOException {
148     mockHttpClientCall(404, "not found", null);
149     assertThat(underTest.getCloudUsage().kubernetesPlatform()).isNull();
150   }
151
152   @Test
153   public void kubernetesProvider_shouldReturnValue() throws IOException {
154     Process processMock = mock(Process.class);
155     when(processMock.getInputStream()).thenReturn(new ByteArrayInputStream("some-provider".getBytes()));
156     when(processBuilder.command(any(String[].class))).thenReturn(processBuilder);
157     when(processBuilder.start()).thenReturn(processMock);
158
159     assertThat(underTest.getCloudUsage().kubernetesProvider()).isEqualTo("some-provider");
160   }
161
162   @Test
163   public void kubernetesProvider_whenValueContainsNullChars_shouldReturnValueWithoutNullChars() throws IOException {
164     Process processMock = mock(Process.class);
165     when(processMock.getInputStream()).thenReturn(new ByteArrayInputStream("so\u0000me-prov\u0000ider".getBytes()));
166     when(processBuilder.command(any(String[].class))).thenReturn(processBuilder);
167     when(processBuilder.start()).thenReturn(processMock);
168
169     assertThat(underTest.getCloudUsage().kubernetesProvider()).isEqualTo("some-provider");
170   }
171
172   @Test
173   public void officialHelmChart_whenEnvVarExists_shouldReturnValue() {
174     when(system2.envVariable(SONAR_HELM_CHART_VERSION)).thenReturn("10.1.0");
175     assertThat(underTest.getCloudUsage().officialHelmChart()).isEqualTo("10.1.0");
176   }
177
178   @Test
179   public void officialHelmChart_whenEnvVarDoesNotExist_shouldReturnNull() {
180     when(system2.envVariable(SONAR_HELM_CHART_VERSION)).thenReturn(null);
181     assertThat(underTest.getCloudUsage().officialHelmChart()).isNull();
182   }
183
184   @Test
185   public void officialImage_whenEnvVarTrue_shouldReturnTrue() {
186     when(system2.envVariable(DOCKER_RUNNING)).thenReturn("True");
187     assertThat(underTest.getCloudUsage().officialImage()).isTrue();
188   }
189
190   @Test
191   public void officialImage_whenEnvVarFalse_shouldReturnFalse() {
192     when(system2.envVariable(DOCKER_RUNNING)).thenReturn("False");
193     assertThat(underTest.getCloudUsage().officialImage()).isFalse();
194   }
195
196   @Test
197   public void officialImage_whenEnvVarDoesNotExist_shouldReturnFalse() {
198     when(system2.envVariable(DOCKER_RUNNING)).thenReturn(null);
199     assertThat(underTest.getCloudUsage().officialImage()).isFalse();
200   }
201
202   @Test
203   public void initHttpClient_whenValidCertificate_shouldCreateClient() throws URISyntaxException {
204     when(paths2.get(anyString())).thenReturn(Paths.get(requireNonNull(getClass().getResource("dummy.crt")).toURI()));
205
206     CloudUsageDataProvider provider = new CloudUsageDataProvider(containerSupport, system2, paths2);
207     assertThat(provider.getHttpClient()).isNotNull();
208   }
209
210   @Test
211   public void initHttpClient_whenNotOnKubernetes_shouldNotCreateClient() throws URISyntaxException {
212     when(paths2.get(anyString())).thenReturn(Paths.get(requireNonNull(getClass().getResource("dummy.crt")).toURI()));
213     when(system2.envVariable(KUBERNETES_SERVICE_HOST)).thenReturn(null);
214
215     CloudUsageDataProvider provider = new CloudUsageDataProvider(containerSupport, system2, paths2);
216     assertThat(provider.getHttpClient()).isNull();
217   }
218
219   @Test
220   public void initHttpClient_whenCertificateNotFound_shouldFail() {
221     when(paths2.get(any())).thenReturn(Paths.get("dummy.crt"));
222
223     CloudUsageDataProvider provider = new CloudUsageDataProvider(containerSupport, system2, paths2);
224     assertThat(provider.getHttpClient()).isNull();
225   }
226 }