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

Allow configure replicas #5880

Merged
merged 3 commits into from
Jan 22, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,14 @@
import io.fabric8.kubernetes.api.model.apps.Deployment;
import io.fabric8.kubernetes.api.model.apps.DeploymentSpec;
import io.fabric8.kubernetes.api.model.networking.v1.Ingress;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

import static io.apicurio.registry.operator.Constants.DEFAULT_REPLICAS;
import static io.apicurio.registry.operator.api.v1.ContainerNames.*;
import static io.apicurio.registry.operator.resource.app.AppDeploymentResource.getContainerFromPodTemplateSpec;
import static io.apicurio.registry.operator.utils.Mapper.YAML_MAPPER;
Expand All @@ -28,8 +28,6 @@

public class ResourceFactory {

private static final Logger log = LoggerFactory.getLogger(ResourceFactory.class);

public static final ResourceFactory INSTANCE = new ResourceFactory();

public static final String COMPONENT_APP = "app";
Expand All @@ -41,8 +39,11 @@ public class ResourceFactory {
public static final String RESOURCE_TYPE_INGRESS = "ingress";

public Deployment getDefaultAppDeployment(ApicurioRegistry3 primary) {
var r = initDefaultDeployment(primary, COMPONENT_APP, 1, ofNullable(primary.getSpec())
.map(ApicurioRegistry3Spec::getApp).map(AppSpec::getPodTemplateSpec).orElse(null)); // TODO:
var r = initDefaultDeployment(primary, COMPONENT_APP,
Optional.ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getApp)
.map(AppSpec::getReplicas).orElse(DEFAULT_REPLICAS),
ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getApp)
.map(AppSpec::getPodTemplateSpec).orElse(null)); // TODO:
// Replicas
mergeDeploymentPodTemplateSpec(
// spotless:off
Expand All @@ -63,8 +64,11 @@ public Deployment getDefaultAppDeployment(ApicurioRegistry3 primary) {
}

public Deployment getDefaultUIDeployment(ApicurioRegistry3 primary) {
var r = initDefaultDeployment(primary, COMPONENT_UI, 1, ofNullable(primary.getSpec())
.map(ApicurioRegistry3Spec::getUi).map(UiSpec::getPodTemplateSpec).orElse(null)); // TODO:
var r = initDefaultDeployment(primary, COMPONENT_UI,
Optional.ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getUi)
.map(UiSpec::getReplicas).orElse(DEFAULT_REPLICAS),
ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getUi)
.map(UiSpec::getPodTemplateSpec).orElse(null)); // TODO:
// Replicas
mergeDeploymentPodTemplateSpec(
// spotless:off
Expand All @@ -85,9 +89,12 @@ public Deployment getDefaultUIDeployment(ApicurioRegistry3 primary) {
}

public Deployment getDefaultStudioUIDeployment(ApicurioRegistry3 primary) {
var r = initDefaultDeployment(primary, COMPONENT_STUDIO_UI, 1, ofNullable(primary.getSpec())
.map(ApicurioRegistry3Spec::getStudioUi).map(StudioUiSpec::getPodTemplateSpec).orElse(null)); // TODO:
// Replicas
var r = initDefaultDeployment(primary, COMPONENT_STUDIO_UI,
Optional.ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getStudioUi)
.map(StudioUiSpec::getReplicas).orElse(DEFAULT_REPLICAS),
ofNullable(primary.getSpec()).map(ApicurioRegistry3Spec::getStudioUi)
.map(StudioUiSpec::getPodTemplateSpec).orElse(null)); // TODO:
// Replicas
mergeDeploymentPodTemplateSpec(
// spotless:off
r.getSpec().getTemplate(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,52 @@ public void beforeEach(TestInfo testInfo) {
// spotless:on
}

protected static void checkDeploymentExists(ApicurioRegistry3 primary, String component, int replicas) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.apps().deployments()
.withName(primary.getMetadata().getName() + "-" + component + "-deployment").get()
.getStatus().getReadyReplicas()).isEqualTo(replicas);
});
}

protected static void checkDeploymentDoesNotExist(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.apps().deployments()
.withName(primary.getMetadata().getName() + "-" + component + "-deployment").get())
.isNull();
});
}

protected static void checkServiceExists(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.services()
.withName(primary.getMetadata().getName() + "-" + component + "-service").get())
.isNotNull();
});
}

protected static void checkServiceDoesNotExist(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.services()
.withName(primary.getMetadata().getName() + "-" + component + "-service").get()).isNull();
});
}

protected static void checkIngressExists(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.network().v1().ingresses()
.withName(primary.getMetadata().getName() + "-" + component + "-ingress").get())
.isNotNull();
});
}

protected static void checkIngressDoesNotExist(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.network().v1().ingresses()
.withName(primary.getMetadata().getName() + "-" + component + "-ingress").get()).isNull();
});
}

static KubernetesClient createK8sClient(String namespace) {
return new KubernetesClientBuilder()
.withConfig(new ConfigBuilder(Config.autoConfigure(null)).withNamespace(namespace).build())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import java.net.URI;

import static io.apicurio.registry.operator.api.v1.ContainerNames.REGISTRY_UI_CONTAINER_NAME;
import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_APP;
import static io.apicurio.registry.operator.resource.ResourceFactory.COMPONENT_UI;
import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
Expand Down Expand Up @@ -70,6 +72,36 @@ void smoke() {
});
}

@Test
void replicas() {
var registry = ResourceFactory.deserialize("/k8s/examples/simple.apicurioregistry3.yaml",
ApicurioRegistry3.class);

registry.getMetadata().setNamespace(namespace);
registry.getSpec().getApp().setHost(ingressManager.getIngressHost("app"));
registry.getSpec().getUi().setHost(ingressManager.getIngressHost("ui"));

client.resource(registry).create();

// Verify first replica
checkDeploymentExists(registry, COMPONENT_APP, 1);
checkDeploymentExists(registry, COMPONENT_UI, 1);

// Scale up
registry.getSpec().getApp().setReplicas(3);
registry.getSpec().getUi().setReplicas(3);
client.resource(registry).update();
checkDeploymentExists(registry, COMPONENT_APP, 3);
checkDeploymentExists(registry, COMPONENT_UI, 3);

// Scale down
registry.getSpec().getApp().setReplicas(2);
registry.getSpec().getUi().setReplicas(2);
client.resource(registry).update();
checkDeploymentExists(registry, COMPONENT_APP, 2);
checkDeploymentExists(registry, COMPONENT_UI, 2);
}

@Test
void testService() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import static io.apicurio.registry.operator.it.SmokeITTest.ingressDisabled;
import static io.apicurio.registry.operator.resource.ResourceFactory.*;
import static io.restassured.RestAssured.given;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

@QuarkusTest
Expand All @@ -36,8 +35,8 @@ void smoke() {

client.resource(simpleRegistry).create();

checkDeploymentExists(simpleRegistry, COMPONENT_APP);
checkDeploymentExists(simpleRegistry, COMPONENT_UI);
checkDeploymentExists(simpleRegistry, COMPONENT_APP, 1);
checkDeploymentExists(simpleRegistry, COMPONENT_UI, 1);
checkDeploymentDoesNotExist(simpleRegistry, COMPONENT_STUDIO_UI);

checkServiceExists(simpleRegistry, COMPONENT_APP);
Expand All @@ -52,9 +51,9 @@ void smoke() {
simpleRegistry.getSpec().withStudioUi().setEnabled(true);
client.resource(simpleRegistry).update();

checkDeploymentExists(simpleRegistry, COMPONENT_APP);
checkDeploymentExists(simpleRegistry, COMPONENT_UI);
checkDeploymentExists(simpleRegistry, COMPONENT_STUDIO_UI);
checkDeploymentExists(simpleRegistry, COMPONENT_APP, 1);
checkDeploymentExists(simpleRegistry, COMPONENT_UI, 1);
checkDeploymentExists(simpleRegistry, COMPONENT_STUDIO_UI, 1);

checkServiceExists(simpleRegistry, COMPONENT_APP);
checkServiceExists(simpleRegistry, COMPONENT_UI);
Expand Down Expand Up @@ -96,9 +95,9 @@ void smoke() {
simpleRegistry.getSpec().getStudioUi().getIngress().setHost(null);
client.resource(simpleRegistry).update();

checkDeploymentExists(simpleRegistry, COMPONENT_APP);
checkDeploymentExists(simpleRegistry, COMPONENT_UI);
checkDeploymentExists(simpleRegistry, COMPONENT_STUDIO_UI);
checkDeploymentExists(simpleRegistry, COMPONENT_APP, 1);
checkDeploymentExists(simpleRegistry, COMPONENT_UI, 1);
checkDeploymentExists(simpleRegistry, COMPONENT_STUDIO_UI, 1);

checkServiceExists(simpleRegistry, COMPONENT_APP);
checkServiceExists(simpleRegistry, COMPONENT_UI);
Expand All @@ -112,8 +111,8 @@ void smoke() {
simpleRegistry.getSpec().getStudioUi().setEnabled(false);
client.resource(simpleRegistry).update();

checkDeploymentExists(simpleRegistry, COMPONENT_APP);
checkDeploymentExists(simpleRegistry, COMPONENT_UI);
checkDeploymentExists(simpleRegistry, COMPONENT_APP, 1);
checkDeploymentExists(simpleRegistry, COMPONENT_UI, 1);
checkDeploymentDoesNotExist(simpleRegistry, COMPONENT_STUDIO_UI);

checkServiceExists(simpleRegistry, COMPONENT_APP);
Expand All @@ -125,49 +124,37 @@ void smoke() {
checkIngressDoesNotExist(simpleRegistry, COMPONENT_STUDIO_UI);
}

private static void checkDeploymentExists(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.apps().deployments()
.withName(primary.getMetadata().getName() + "-" + component + "-deployment").get()
.getStatus().getReadyReplicas()).isEqualTo(1);
});
}
/**
* Scenario: We want to check that the Studio component is not deployed by default unless the enabled
* field is set to true, and, when activated, the number of replicas is set to the value specified while
* checking that the basic Kubernetes resources are deployed as expected. We do not check Registry
* components in detail, because that's done in other tests.
*/
@Test
void replicas() {
var simpleRegistry = ResourceFactory.deserialize("/k8s/examples/simple.apicurioregistry3.yaml",
ApicurioRegistry3.class);

private static void checkDeploymentDoesNotExist(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.apps().deployments()
.withName(primary.getMetadata().getName() + "-" + component + "-deployment").get())
.isNull();
});
}
simpleRegistry.getMetadata().setNamespace(namespace);
simpleRegistry.getSpec().getApp().setHost(ingressManager.getIngressHost(COMPONENT_APP));
simpleRegistry.getSpec().getUi().setHost(ingressManager.getIngressHost(COMPONENT_UI));

private static void checkServiceExists(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.services()
.withName(primary.getMetadata().getName() + "-" + component + "-service").get())
.isNotNull();
});
}
client.resource(simpleRegistry).create();

private static void checkServiceDoesNotExist(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.services()
.withName(primary.getMetadata().getName() + "-" + component + "-service").get()).isNull();
});
}
// We start with one replica for Registry
checkDeploymentExists(simpleRegistry, COMPONENT_APP, 1);
checkDeploymentExists(simpleRegistry, COMPONENT_UI, 1);
checkDeploymentDoesNotExist(simpleRegistry, COMPONENT_STUDIO_UI);

private static void checkIngressExists(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.network().v1().ingresses()
.withName(primary.getMetadata().getName() + "-" + component + "-ingress").get())
.isNotNull();
});
}
// Now let's enable the Studio component and scale Registry to 3 replicas
simpleRegistry.getSpec().withStudioUi().setEnabled(true);
simpleRegistry.getSpec().getApp().setReplicas(3);
simpleRegistry.getSpec().getUi().setReplicas(3);
simpleRegistry.getSpec().getStudioUi().setReplicas(3);
client.resource(simpleRegistry).update();

private static void checkIngressDoesNotExist(ApicurioRegistry3 primary, String component) {
await().ignoreExceptions().untilAsserted(() -> {
assertThat(client.network().v1().ingresses()
.withName(primary.getMetadata().getName() + "-" + component + "-ingress").get()).isNull();
});
checkDeploymentExists(simpleRegistry, COMPONENT_APP, 3);
checkDeploymentExists(simpleRegistry, COMPONENT_UI, 3);
checkDeploymentExists(simpleRegistry, COMPONENT_STUDIO_UI, 3);
}
}
9 changes: 9 additions & 0 deletions operator/install/install.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3019,6 +3019,9 @@ spec:
type: array
type: object
type: object
replicas:
description: Number of replicas for the component
type: integer
sql:
description: |-
DEPRECATED: Use the `app.storage.type` and `app.storage.sql` fields instead.
Expand Down Expand Up @@ -6088,6 +6091,9 @@ spec:
type: array
type: object
type: object
replicas:
description: Number of replicas for the component
type: integer
type: object
ui:
description: |
Expand Down Expand Up @@ -9074,6 +9080,9 @@ spec:
type: array
type: object
type: object
replicas:
description: Number of replicas for the component
type: integer
type: object
type: object
status:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ public abstract class ComponentSpec {
@JsonSetter(nulls = Nulls.SKIP)
private String host;

/**
* Number of replicas for the component
*/
@JsonProperty("replicas")
@JsonPropertyDescription("Number of replicas for the component")
@JsonSetter(nulls = Nulls.SKIP)
private Integer replicas;

public IngressSpec withIngress() {
if (ingress == null) {
ingress = new IngressSpec();
Expand Down
Loading