Skip to content

ServiceConnection for K3sContainer #45717

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

Open
MichaelDausmann opened this issue May 28, 2025 · 4 comments
Open

ServiceConnection for K3sContainer #45717

MichaelDausmann opened this issue May 28, 2025 · 4 comments
Labels
status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged

Comments

@MichaelDausmann
Copy link

I would like to use K3sContainer for local Development, I already have Kafka and Neo4j working with @Serviceconnection. This would be nice...

    @Bean
    @ServiceConnection
    K3sContainer k3s() {
        return new K3sContainer(DockerImageName.parse("rancher/k3s:v1.21.3-k3s1"))
                .withCommand("server", "--disable", "metrics-server") // we don't need metrics
                .withLogConsumer(new Slf4jLogConsumer(logger)
                );
    }

K3sContainer is here (modules/k3s/src/main/java/org/testcontainers/k3s/K3sContainer.java)

Looks like it would require work here (spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection)
and here (spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure).

Workaround

Here is my workaround

    @Bean
    K3sContainer k3s() {
        K3sContainer k3sContainer = new K3sContainer(DockerImageName.parse("rancher/k3s:v1.21.3-k3s1"))
                .withCommand("server", "--disable", "metrics-server") // we don't need metrics
                .withLogConsumer(new Slf4jLogConsumer(logger)
                );

        // don't normally need to start the container in these @Bean methods but can't get the config unless its started
        k3sContainer.start();

        String kubeConfigYaml = k3sContainer.getKubeConfigYaml();
        Config config = Config.fromKubeconfig(kubeConfigYaml);  // requires io.fabric8:kubernetes-client:5.11.0 or higher

        // in the absence of @ServiceConnection integration for this testcontainer, Jack the test container URL into properties so it's picked up when I create a client in main app
        System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, config.getMasterUrl());
        System.setProperty(Config.KUBERNETES_CA_CERTIFICATE_DATA_SYSTEM_PROPERTY, config.getCaCertData());
        System.setProperty(Config.KUBERNETES_CLIENT_CERTIFICATE_DATA_SYSTEM_PROPERTY, config.getClientCertData());
        System.setProperty(Config.KUBERNETES_CLIENT_KEY_DATA_SYSTEM_PROPERTY, config.getClientKeyData());
        System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");

        return k3sContainer;
    }
@livk-cloud
Copy link

@SpringFactories(ConnectionDetailsFactory.class)
class MinIOContainerConnectionDetailsFactory
		extends ContainerConnectionDetailsFactory<MinIOContainer, ConnectionDetails> {

	MinIOContainerConnectionDetailsFactory() {
		super(DockerImageNames.MINIO_IMAGE);
	}

	@Override
	protected ConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<MinIOContainer> source) {
		return new MinIOContainerConnectionDetails(source);
	}

	private static final class MinIOContainerConnectionDetails extends ContainerConnectionDetails<MinIOContainer> {

		private MinIOContainerConnectionDetails(ContainerConnectionSource<MinIOContainer> source) {
			super(source);
		}

	}

}

You can handle K3sContainer like this, and you need to register this class in the spring.factories file.

@philwebb
Copy link
Member

The @ServiceConnection annotation is designed to provide a bridge between something that Spring Boot can connect to and a container that provides an appropriate service. For example, JdbcConnectionDetails provides details for a JDBC connection and JdbcContainerConnectionDetailsFactory allows any JdbcDatabaseContainer to be the data source.

In the case of K3sContainer, I'm not sure what we'd connect it to.

@MichaelDausmann can you provide a bit more background about what you're trying to achieve? Perhaps you can share a sample application that uses your current workaround?

@philwebb philwebb added the status: waiting-for-feedback We need additional information before we can continue label May 29, 2025
@MichaelDausmann
Copy link
Author

MichaelDausmann commented May 29, 2025

@philwebb ah ok, good point. I'm specifically setting up a local dev environment with TestContainers for a Spring/Boot application that interacts directly with Kubernetes via the io.fabric8.kubernetes.client. so I guess to answer your question directly, I am connecting to the Kubernetes API server inside the K3sContainer.

the workaround lets me create a KubernetesClient bean with an active client

@Configuration
public class KubernetesClientConfig {

    @Bean
    public KubernetesClient kubernetesClient() {
        Config config = Config.autoConfigure(null);
        return new DefaultKubernetesClient(config);
    }
}

... because I have set the application properties, the autoConfigure finds what it needs and connects without issue. At deployment .autoConfigure doesn't need e.g. a host because it is deployed in the cluster and the default url is fine

@MichaelDausmann
Copy link
Author

@livk-cloud I will give your approach a try

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels May 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: feedback-provided Feedback has been provided status: waiting-for-triage An issue we've not yet triaged
Projects
None yet
Development

No branches or pull requests

4 participants