Skip to content

Add the possibility to configure a custom image for k8s dev container #48552

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/src/main/asciidoc/kubernetes-dev-services.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ quarkus.kubernetes-client.devservices.flavor=api-only # k3s or kind
quarkus.kubernetes-client.devservices.api-version=1.22
----

You can also configure a custom image compatible with standard images (kind, k3s & api-server) using the `quarkus.kubernetes-client.devservices.image-name` property. However, it must be consistent with the flavor and api-version properties:

[source, properties]
----
quarkus.kubernetes-client.devservices.flavor=api-only # k3s or kind
quarkus.kubernetes-client.devservices.api-version=1.24.1
quarkus.kubernetes-client.devservices.image-name=quay.io/giantswarm/kube-apiserver:v1.24.1
----

`api-only` only starts a Kubernetes API Server (plus the required etcd). If you need a fully-featured Kubernetes cluster that can spin up Pods, you can use `k3s` or `kind`. `k3s` requires to start the container with `privileged mode`. The `kind` test container now also supports using podman's rootless mode.

If `api-version` is not set, the latest version for the given flavor will be used. Otherwise, the version must match a https://github.com/dajudge/kindcontainer/blob/master/k8s-versions.json[version supported by the given flavor].
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;

Expand All @@ -30,6 +31,8 @@
import com.dajudge.kindcontainer.K3sContainerVersion;
import com.dajudge.kindcontainer.KindContainer;
import com.dajudge.kindcontainer.KindContainerVersion;
import com.dajudge.kindcontainer.KubernetesContainer;
import com.dajudge.kindcontainer.KubernetesImageSpec;
import com.dajudge.kindcontainer.KubernetesVersionEnum;
import com.dajudge.kindcontainer.client.KubeConfigUtils;
import com.dajudge.kindcontainer.client.config.Cluster;
Expand Down Expand Up @@ -225,18 +228,12 @@ private RunningDevService startKubernetes(DockerStatusBuildItem dockerStatusBuil
.orElse(api_only);

@SuppressWarnings("rawtypes")
final var container = switch (clusterType) {
case api_only -> new ApiServerContainer(
config.apiVersion
.map(version -> findOrElseThrow(clusterType, version, ApiServerContainerVersion.class))
.orElseGet(() -> latest(ApiServerContainerVersion.class)));
case k3s -> new K3sContainer(
config.apiVersion.map(version -> findOrElseThrow(clusterType, version, K3sContainerVersion.class))
.orElseGet(() -> latest(K3sContainerVersion.class)));
case kind -> new KindContainer(
config.apiVersion
.map(version -> findOrElseThrow(clusterType, version, KindContainerVersion.class))
.orElseGet(() -> latest(KindContainerVersion.class)));
KubernetesContainer container = switch (clusterType) {
case api_only -> createContainer(ApiServerContainer::new, ApiServerContainerVersion.class, config, clusterType);

case k3s -> createContainer(K3sContainer::new, K3sContainerVersion.class, config, clusterType);

case kind -> createContainer(KindContainer::new, KindContainerVersion.class, config, clusterType);
};

if (useSharedNetwork) {
Expand Down Expand Up @@ -270,7 +267,21 @@ private RunningDevService startKubernetes(DockerStatusBuildItem dockerStatusBuil
.orElseGet(defaultKubernetesClusterSupplier);
}

<T extends KubernetesVersionEnum<T>> T findOrElseThrow(final Flavor flavor, final String version,
@SuppressWarnings("rawtypes")
private <T extends KubernetesVersionEnum<T>, C extends KubernetesContainer> C createContainer(
Function<KubernetesImageSpec<T>, C> constructor,
Class<T> versionClass,
KubernetesDevServiceCfg config,
Flavor flavor) {
T version = config.apiVersion
.map(v -> findOrElseThrow(flavor, v, versionClass))
.orElseGet(() -> latest(versionClass));

KubernetesImageSpec<T> imageSpec = version.withImage(config.imageName);
return constructor.apply(imageSpec);
}

private <T extends KubernetesVersionEnum<T>> T findOrElseThrow(final Flavor flavor, final String version,
final Class<T> versions) {
final String versionWithPrefix = !version.startsWith("v") ? "v" + version : version;
return KubernetesVersionEnum.ascending(versions)
Expand Down Expand Up @@ -315,6 +326,7 @@ private KubernetesDevServiceCfg getConfiguration(KubernetesClientBuildConfig cfg
private static final class KubernetesDevServiceCfg {

public boolean devServicesEnabled;
public String imageName;
public Optional<Flavor> flavor;
public Optional<String> apiVersion;
public boolean overrideKubeconfig;
Expand All @@ -324,6 +336,8 @@ private static final class KubernetesDevServiceCfg {

public KubernetesDevServiceCfg(KubernetesDevServicesBuildTimeConfig config) {
this.devServicesEnabled = config.enabled();
this.imageName = config.imageName()
.orElse(null);
this.serviceName = config.serviceName();
this.apiVersion = config.apiVersion();
this.overrideKubeconfig = config.overrideKubeconfig();
Expand All @@ -334,7 +348,8 @@ public KubernetesDevServiceCfg(KubernetesDevServicesBuildTimeConfig config) {

@Override
public int hashCode() {
return Objects.hash(devServicesEnabled, flavor, apiVersion, overrideKubeconfig, shared, serviceName, containerEnv);
return Objects.hash(devServicesEnabled, imageName, flavor, apiVersion, overrideKubeconfig, shared, serviceName,
containerEnv);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,15 @@ public interface KubernetesDevServicesBuildTimeConfig {
*/
Optional<String> apiVersion();

/**
* The kubernetes image to use.
* <p>
* If not set, Dev Services for Kubernetes will use default image for the specified {@link #apiVersion()} for the given
* {@link #flavor()}.
*/

Optional<String> imageName();

/**
* The flavor to use (kind, k3s or api-only).
* <p>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package io.quarkus.kubernetes.client.devservices.it.profiles;

import java.util.Collections;
import java.util.Map;

import io.quarkus.test.junit.QuarkusTestProfile;
Expand All @@ -12,6 +11,8 @@ public class DevServiceKubernetes implements QuarkusTestProfile {
@Override
public Map<String, String> getConfigOverrides() {

return Collections.singletonMap("quarkus.kubernetes-client.devservices.api-version", API_VERSION);
return Map.of("quarkus.kubernetes-client.devservices.api-version", API_VERSION,
"quarkus.kubernetes-client.devservices.image-name",
"quay.io/giantswarm/kube-apiserver:v%s".formatted(API_VERSION));
}
}
Loading