Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expected URL scheme 'http' or 'https' but no scheme was found for /api/v... #3876

Open
Memo2782 opened this issue Jan 22, 2025 · 4 comments
Open

Comments

@Memo2782
Copy link

Hi

In the following days i have tried to setup and environmment where i can fetch kuerbenetes secrets and test them in junit, however in java kubernetes client i have faced some challenges in how to retrieve information about, in this case this is the code i am trying to test

package ocpm.certificatemanagement.service;

import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1Secret;
import org.junit.Test;
import org.mockito.Mockito;

import static org.junit.jupiter.api.Assertions.;
import static org.mockito.Mockito.
;

public class KubernetesSecretFetcherTest {

@Test
public void testFetchSecret() throws Exception {
    // Mock CoreV1Api
    CoreV1Api mockApi = mock(CoreV1Api.class);
    mockApi = new CoreV1Api();

    // Create a mock secret
    V1Secret mockSecret = new V1Secret();
    mockSecret.putDataItem("username", "admin".getBytes());
    mockSecret.putDataItem("password", "secret".getBytes());

    // Mock API response
    when(mockApi.readNamespacedSecret("example-secret", "default").execute()).thenReturn(mockSecret);

    // Call the mocked API method
    V1Secret secret = mockApi.readNamespacedSecret("example-secret", "default").execute();

    // Assertions
    assertNotNull(secret);
    assertEquals("admin", new String(secret.getData().get("username")));
    assertEquals("secret", new String(secret.getData().get("password")));
}

}

This code is returning back a error such as the following one

Expected URL scheme 'http' or 'https' but no scheme was found for /api/v...
java.lang.IllegalArgumentException: Expected URL scheme 'http' or 'https' but no scheme was found for /api/v...
at okhttp3.HttpUrl$Builder.parse$okhttp(HttpUrl.kt:1261)
at okhttp3.HttpUrl$Companion.get(HttpUrl.kt:1634)
at okhttp3.Request$Builder.url(Request.kt:184)
at io.kubernetes.client.openapi.ApiClient.buildRequest(ApiClient.java:1192)
at io.kubernetes.client.openapi.ApiClient.buildCall(ApiClient.java:1138)
at io.kubernetes.client.openapi.apis.CoreV1Api.readNamespacedSecretCall(CoreV1Api.java:41761)
at io.kubernetes.client.openapi.apis.CoreV1Api.readNamespacedSecretValidateBeforeCall(CoreV1Api.java:41776)
at io.kubernetes.client.openapi.apis.CoreV1Api.readNamespacedSecretWithHttpInfo(CoreV1Api.java:41782)
at io.kubernetes.client.openapi.apis.CoreV1Api$APIreadNamespacedSecretRequest.execute(CoreV1Api.java:41843)
at ocpm.certificatemanagement.service.KubernetesSecretFetcherTest.testFetchSecret(KubernetesSecretFetcherTest.java:25)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:61)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:108)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:57)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:39)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy2/jdk.proxy2.$Proxy5.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

This the implementation code tried to be tested

package ocpm.certificatemanagement.service;

import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.openapi.ApiException;
import io.kubernetes.client.openapi.apis.CoreV1Api;
import io.kubernetes.client.openapi.models.V1Secret;

public class KubernetesSecretFetcher {

public static V1Secret fetchSecret(String namespace, String secretName, ApiClient client) throws ApiException {
    // Use the provided client
    CoreV1Api api = new CoreV1Api(client);

    // Fetch the secret
    return api.readNamespacedSecret(secretName, namespace).execute();
}

public static void main(String[] args) {
    try {
        // Configure TLS
        ApiClient client = KubernetesTLSConfigurator.configureTls(
                "/path/to/ca.crt",         // Path to CA certificate
                "/path/to/client.crt",     // Path to client certificate
                "/path/to/client.key"      // Path to client key
        );

        // Fetch secret securely
        String namespace = "default";
        String secretName = "example-secret";

        V1Secret secret = fetchSecret(namespace, secretName, client);

        if (secret != null && secret.getData() != null) {
            secret.getData().forEach((key, value) -> {
                System.out.println(key + ": " + new String(value));
            });
        } else {
            System.out.println("Secret not found or has no data.");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

}

@Memo2782
Copy link
Author

Memo2782 commented Jan 22, 2025

This is reference as well with a issue reference #3859 i hope you can guide on it to sort it out

@yue9944882
Copy link
Member

    CoreV1Api mockApi = mock(CoreV1Api.class);

hey @Memo2782, you're hitting the error because the entire CoreV1Api class is mocked from the top. it's not the recommended way to write unit-tests for mocking client. a better alternative is to use wire-mock in your unit tests

@Memo2782
Copy link
Author

hi @yue9944882 any example how? cause i have used wire-mock but for usage in HTTP, i have never used for mocking kubernetes, in addition i have try to look at the documentation and looks like this one still not available here https://javadoc.io/doc/io.kubernetes/client-java/21.0.1/index.html, that is making just work in a blind side,

@brendandburns
Copy link
Contributor

There are lots of examples of how to use WireMock, here's one:

https://github.com/kubernetes-client/java/blob/master/util/src/test/java/io/kubernetes/client/PodLogsTest.java

Also, in this case, I think that the problem is that you re-assign mockAPI to be a real instance of the CoreV1API class in the second line of your code:

 mockApi = new CoreV1Api();

But @yue9944882 is right, the correct way to test is to mock the actual HTTP calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants