Skip to content

Commit 143748c

Browse files
committed
Add configuration to control ServiceAccount generation for Knative image pull secrets
Relates to: #32545
1 parent 5fe1704 commit 143748c

File tree

4 files changed

+108
-6
lines changed

4 files changed

+108
-6
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.quarkus.kubernetes.deployment;
2+
3+
import io.dekorate.kubernetes.decorator.NamedResourceDecorator;
4+
import io.fabric8.knative.serving.v1.RevisionSpecFluent;
5+
import io.fabric8.kubernetes.api.model.ObjectMeta;
6+
7+
public class AddImagePullSecretToRevisionSpecDecorator extends NamedResourceDecorator<RevisionSpecFluent<?>> {
8+
9+
private final String imagePullSecret;
10+
11+
public AddImagePullSecretToRevisionSpecDecorator(String name, String imagePullSecret) {
12+
super(name);
13+
this.imagePullSecret = imagePullSecret;
14+
}
15+
16+
@Override
17+
public void andThenVisit(RevisionSpecFluent<?> revisionSpec, ObjectMeta resourceMeta) {
18+
revisionSpec.addNewImagePullSecret(imagePullSecret);
19+
}
20+
}

extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeConfig.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,14 @@ default String targetPlatformName() {
7979
*/
8080
@WithDefault("CreateOrUpdate")
8181
DeployStrategy deployStrategy();
82+
83+
/**
84+
* Whether to add image pull secrets to a generated ServiceAccount.
85+
* When set to true (default), image pull secrets are added to a ServiceAccount resource.
86+
* When set to false, image pull secrets are added directly to the pod spec.
87+
* Setting this to false is useful when deploying to environments like IBM Code Engine where users do not have
88+
* permission to create ServiceAccount resources.
89+
*/
90+
@WithDefault("true")
91+
boolean addImagePullSecretsToServiceAccount();
8292
}

extensions/kubernetes/vanilla/deployment/src/main/java/io/quarkus/kubernetes/deployment/KnativeProcessor.java

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -301,12 +301,20 @@ public List<DecoratorBuildItem> createDecorators(ApplicationInfoBuildItem applic
301301

302302
//Handle Image Pull Secrets
303303
config.imagePullSecrets().ifPresent(imagePullSecrets -> {
304-
String serviceAccountName = config.serviceAccount().orElse(name);
305-
result.add(new DecoratorBuildItem(KNATIVE, new AddServiceAccountResourceDecorator(name)));
306-
result.add(
307-
new DecoratorBuildItem(KNATIVE, new ApplyServiceAccountToRevisionSpecDecorator(name, serviceAccountName)));
308-
result.add(new DecoratorBuildItem(KNATIVE,
309-
new AddImagePullSecretToServiceAccountDecorator(serviceAccountName, imagePullSecrets)));
304+
if (config.addImagePullSecretsToServiceAccount()) {
305+
String serviceAccountName = config.serviceAccount().orElse(name);
306+
result.add(new DecoratorBuildItem(KNATIVE, new AddServiceAccountResourceDecorator(name)));
307+
result.add(
308+
new DecoratorBuildItem(KNATIVE,
309+
new ApplyServiceAccountToRevisionSpecDecorator(name, serviceAccountName)));
310+
result.add(new DecoratorBuildItem(KNATIVE,
311+
new AddImagePullSecretToServiceAccountDecorator(serviceAccountName, imagePullSecrets)));
312+
} else {
313+
for (String imagePullSecret : imagePullSecrets) {
314+
result.add(new DecoratorBuildItem(KNATIVE,
315+
new AddImagePullSecretToRevisionSpecDecorator(name, imagePullSecret)));
316+
}
317+
}
310318
});
311319

312320
return result;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package io.quarkus.it.kubernetes;
2+
3+
import static org.assertj.core.api.Assertions.assertThat;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Path;
7+
import java.util.List;
8+
9+
import org.junit.jupiter.api.Test;
10+
import org.junit.jupiter.api.extension.RegisterExtension;
11+
12+
import io.fabric8.knative.serving.v1.Service;
13+
import io.fabric8.kubernetes.api.model.HasMetadata;
14+
import io.quarkus.builder.Version;
15+
import io.quarkus.maven.dependency.Dependency;
16+
import io.quarkus.test.ProdBuildResults;
17+
import io.quarkus.test.ProdModeTestResults;
18+
import io.quarkus.test.QuarkusProdModeTest;
19+
20+
public class KnativeWithImagePullSecretsTest {
21+
22+
@RegisterExtension
23+
static final QuarkusProdModeTest config = new QuarkusProdModeTest()
24+
.withApplicationRoot((jar) -> jar.addClasses(GreetingResource.class))
25+
.setApplicationName("knative-with-image-pull-secrets")
26+
.setApplicationVersion("0.1-SNAPSHOT")
27+
.overrideConfigKey("quarkus.kubernetes.deployment-target", "knative")
28+
.overrideConfigKey("quarkus.knative.image-pull-secrets", "my-secret")
29+
.overrideConfigKey("quarkus.knative.add-image-pull-secrets-to-service-account", "false")
30+
.setForcedDependencies(List.of(Dependency.of("io.quarkus", "quarkus-kubernetes", Version.getVersion())));
31+
32+
@ProdBuildResults
33+
private ProdModeTestResults prodModeTestResults;
34+
35+
@Test
36+
public void assertGeneratedResources() throws IOException {
37+
Path kubernetesDir = prodModeTestResults.getBuildDir().resolve("kubernetes");
38+
assertThat(kubernetesDir)
39+
.isDirectoryContaining(p -> p.getFileName().endsWith("knative.json"))
40+
.isDirectoryContaining(p -> p.getFileName().endsWith("knative.yml"));
41+
List<HasMetadata> kubernetesList = DeserializationUtil
42+
.deserializeAsList(kubernetesDir.resolve("knative.yml"));
43+
44+
assertThat(kubernetesList).filteredOn(i -> "Service".equals(i.getKind())).singleElement().satisfies(i -> {
45+
assertThat(i).isInstanceOfSatisfying(Service.class, s -> {
46+
assertThat(s.getMetadata()).satisfies(m -> {
47+
assertThat(m.getName()).isEqualTo("knative-with-image-pull-secrets");
48+
});
49+
50+
assertThat(s.getSpec()).satisfies(spec -> {
51+
assertThat(spec.getTemplate()).satisfies(template -> {
52+
assertThat(template.getSpec()).satisfies(revisionSpec -> {
53+
assertThat(revisionSpec.getImagePullSecrets()).hasSize(1);
54+
assertThat(revisionSpec.getImagePullSecrets().get(0).getName()).isEqualTo("my-secret");
55+
});
56+
});
57+
});
58+
});
59+
});
60+
61+
// Ensure no ServiceAccount was generated
62+
assertThat(kubernetesList).filteredOn(i -> "ServiceAccount".equals(i.getKind())).isEmpty();
63+
}
64+
}

0 commit comments

Comments
 (0)