From 82b1775618bfd344987b35b3b847a08da181ca9a Mon Sep 17 00:00:00 2001 From: tplevko Date: Tue, 15 Nov 2022 12:57:36 +0100 Subject: [PATCH] Add Telegram client for Openshift --- .../telegram/resource/TelegramContainer.java | 14 -- .../resource/local/LocalTelegram.java | 47 +++++++ .../local/TelegramClientContainer.java | 14 ++ .../resource/openshift/OpenshiftTelegram.java | 133 ++++++++++++++++++ .../tnb/telegram/service/Telegram.java | 42 +++--- .../validation/TelegramValidation.java | 12 +- 6 files changed, 217 insertions(+), 45 deletions(-) delete mode 100644 system-x/services/telegram/src/main/java/software/tnb/telegram/resource/TelegramContainer.java create mode 100644 system-x/services/telegram/src/main/java/software/tnb/telegram/resource/local/LocalTelegram.java create mode 100644 system-x/services/telegram/src/main/java/software/tnb/telegram/resource/local/TelegramClientContainer.java create mode 100644 system-x/services/telegram/src/main/java/software/tnb/telegram/resource/openshift/OpenshiftTelegram.java diff --git a/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/TelegramContainer.java b/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/TelegramContainer.java deleted file mode 100644 index 807f27af4..000000000 --- a/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/TelegramContainer.java +++ /dev/null @@ -1,14 +0,0 @@ -package software.tnb.telegram.resource; - -import org.testcontainers.containers.GenericContainer; - -import java.util.Map; - -public class TelegramContainer extends GenericContainer { - private static final String IMAGE = System.getProperty("telegram.image", "quay.io/fuse_qe/telegram-client:latest"); - - public TelegramContainer(Map env) { - super(IMAGE); - withEnv(env); - } -} diff --git a/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/local/LocalTelegram.java b/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/local/LocalTelegram.java new file mode 100644 index 000000000..672fa6b60 --- /dev/null +++ b/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/local/LocalTelegram.java @@ -0,0 +1,47 @@ +package software.tnb.telegram.resource.local; + +import software.tnb.common.deployment.Deployable; +import software.tnb.telegram.service.Telegram; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.auto.service.AutoService; + +import java.io.IOException; + +@AutoService(LocalTelegram.class) +public class LocalTelegram extends Telegram implements Deployable { + + private static final Logger LOG = LoggerFactory.getLogger(LocalTelegram.class); + private TelegramClientContainer container; + + @Override + public String execInContainer(String... commands) { + try { + return container.execInContainer(commands).getStdout(); + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + @Override + public void deploy() { + LOG.debug("Starting Telegram client container"); + container = new TelegramClientContainer(image(), getEnv()); + container.start(); + } + + @Override + public void undeploy() { + container.stop(); + } + + @Override + public void openResources() { + } + + @Override + public void closeResources() { + } +} diff --git a/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/local/TelegramClientContainer.java b/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/local/TelegramClientContainer.java new file mode 100644 index 000000000..da9ff286c --- /dev/null +++ b/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/local/TelegramClientContainer.java @@ -0,0 +1,14 @@ +package software.tnb.telegram.resource.local; + +import org.testcontainers.containers.GenericContainer; + +import java.util.Map; + +public class TelegramClientContainer extends GenericContainer { + + public TelegramClientContainer(String image, Map env) { + super(image); + withEnv(env); + } + +} diff --git a/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/openshift/OpenshiftTelegram.java b/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/openshift/OpenshiftTelegram.java new file mode 100644 index 000000000..81d7ad764 --- /dev/null +++ b/system-x/services/telegram/src/main/java/software/tnb/telegram/resource/openshift/OpenshiftTelegram.java @@ -0,0 +1,133 @@ +package software.tnb.telegram.resource.openshift; + +import software.tnb.common.config.OpenshiftConfiguration; +import software.tnb.common.deployment.OpenshiftDeployable; +import software.tnb.common.deployment.WithName; +import software.tnb.common.openshift.OpenshiftClient; +import software.tnb.telegram.service.Telegram; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.auto.service.AutoService; + +import java.io.ByteArrayOutputStream; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +import cz.xtf.core.openshift.OpenShiftWaiters; +import cz.xtf.core.openshift.helpers.ResourceFunctions; +import io.fabric8.kubernetes.api.model.EnvVar; +import io.fabric8.kubernetes.api.model.ObjectReferenceBuilder; +import io.fabric8.kubernetes.api.model.Pod; +import io.fabric8.openshift.api.model.DeploymentConfigBuilder; +import io.fabric8.openshift.api.model.DeploymentTriggerImageChangeParams; +import io.fabric8.openshift.api.model.ImageStream; +import io.fabric8.openshift.api.model.ImageStreamBuilder; + +@AutoService(OpenshiftTelegram.class) +public class OpenshiftTelegram extends Telegram implements OpenshiftDeployable, WithName { + + private static final Logger LOG = LoggerFactory.getLogger(OpenshiftTelegram.class); + + @Override + public void undeploy() { + LOG.info("Undeploying Telegram client"); + OpenshiftClient.get().deploymentConfigs().withName(name()).delete(); + OpenShiftWaiters.get(OpenshiftClient.get(), () -> false).areNoPodsPresent(OpenshiftConfiguration.openshiftDeploymentLabel(), name()) + .timeout(120_000).waitFor(); + OpenshiftClient.get().imageStreams().withLabel(OpenshiftConfiguration.openshiftDeploymentLabel(), name()).delete(); + } + + @Override + public void openResources() { + } + + @Override + public void closeResources() { + } + + @Override + public void create() { + LOG.info("Deploying Telegram client"); + + ImageStream imageStream = new ImageStreamBuilder() + .withNewMetadata() + .withName(name()) + .endMetadata() + .withNewSpec() + .addNewTag() + .withName("latest") + .withFrom(new ObjectReferenceBuilder().withKind("DockerImage").withName(image()).build()) + .endTag() + .endSpec() + .build(); + + OpenshiftClient.get().imageStreams().createOrReplace(imageStream); + + LOG.debug("Creating deployment {}", name()); + OpenshiftClient.get().deploymentConfigs().createOrReplace( + new DeploymentConfigBuilder() + .editOrNewMetadata() + .withName(name()) + .addToLabels(OpenshiftConfiguration.openshiftDeploymentLabel(), name()) + .endMetadata() + .editOrNewSpec() + .addToSelector(OpenshiftConfiguration.openshiftDeploymentLabel(), name()) + .withReplicas(1) + .editOrNewTemplate() + .editOrNewMetadata() + .addToLabels(OpenshiftConfiguration.openshiftDeploymentLabel(), name()) + .endMetadata() + .editOrNewSpec() + .addNewContainer() + .withName(name()) + .withImagePullPolicy("IfNotPresent") + .addAllToEnv(getEnv().entrySet().stream().map(e -> new EnvVar(e.getKey(), e.getValue(), null)) + .collect(Collectors.toList())) + .endContainer() + .endSpec() + .endTemplate() + .addNewTrigger() + .withType("ConfigChange") + .endTrigger() + .addNewTrigger() + .withType("ImageChange") + .withImageChangeParams( + new DeploymentTriggerImageChangeParams(true, Arrays.asList(name()), + new ObjectReferenceBuilder().withKind("ImageStreamTag").withName(name() + ":latest").build() + , null) + ) + .endTrigger() + .endSpec() + .build() + ); + } + + @Override + public boolean isReady() { + List pods = OpenshiftClient.get().getLabeledPods(OpenshiftConfiguration.openshiftDeploymentLabel(), name()); + return ResourceFunctions.areExactlyNPodsReady(1).apply(pods); + } + + @Override + public boolean isDeployed() { + return OpenshiftClient.get().getLabeledPods(OpenshiftConfiguration.openshiftDeploymentLabel(), name()).size() != 0; + } + + @Override + public String execInContainer(String... commands) { + ByteArrayOutputStream baosOutput = new ByteArrayOutputStream(); + + OpenshiftClient.get().pods().withName(OpenshiftClient.get().getAnyPod(name()).getMetadata().getName()) + .writingOutput(baosOutput).exec(commands); + + return baosOutput.toString(); + } + + @Override + public String name() { + return "telegram-client"; + } +} diff --git a/system-x/services/telegram/src/main/java/software/tnb/telegram/service/Telegram.java b/system-x/services/telegram/src/main/java/software/tnb/telegram/service/Telegram.java index 1db95a1ad..5b84a913a 100644 --- a/system-x/services/telegram/src/main/java/software/tnb/telegram/service/Telegram.java +++ b/system-x/services/telegram/src/main/java/software/tnb/telegram/service/Telegram.java @@ -1,35 +1,27 @@ package software.tnb.telegram.service; import software.tnb.common.account.AccountFactory; +import software.tnb.common.deployment.WithDockerImage; import software.tnb.common.service.Service; import software.tnb.telegram.account.TelegramAccount; -import software.tnb.telegram.resource.TelegramContainer; +import software.tnb.telegram.resource.local.LocalTelegram; import software.tnb.telegram.validation.TelegramValidation; -import org.junit.jupiter.api.extension.ExtensionContext; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.auto.service.AutoService; - import java.util.HashMap; import java.util.Map; -@AutoService(Telegram.class) -public class Telegram implements Service { +public abstract class Telegram implements Service, WithDockerImage { + + private static final Logger LOG = LoggerFactory.getLogger(LocalTelegram.class); private TelegramAccount account; private TelegramValidation validation; - private TelegramContainer container; - private static final Logger LOG = LoggerFactory.getLogger(Telegram.class); @Override - public void beforeAll(ExtensionContext context) { - LOG.debug("Creating new Telegram validation"); - account(); //initialize account - container = new TelegramContainer(getEnv()); //init container - validation = new TelegramValidation(container); //create validation with container - container.start(); + public String defaultImage() { + return "quay.io/fuse_qe/telegram-client:latest"; } public TelegramAccount account() { @@ -40,23 +32,23 @@ public TelegramAccount account() { return account; } - @Override - public void afterAll(ExtensionContext context) { - container.stop(); - } + public abstract String execInContainer(String... commands); public TelegramValidation validation() { + if (validation == null) { + validation = new TelegramValidation(this); + } return validation; } public Map getEnv() { Map env = new HashMap<>(); - env.put("TELEGRAM_DC_ID", account.getDcId()); - env.put("TELEGRAM_DC_IP", account.getDcIp()); - env.put("TELEGRAM_API_ID", account.getAppId()); - env.put("TELEGRAM_API_HASH", account.getAppHash()); - env.put("TELEGRAM_SESSION", account.getSessionString()); - env.put("TELEGRAM_USERNAME", account.getUsername()); + env.put("TELEGRAM_DC_ID", account().getDcId()); + env.put("TELEGRAM_DC_IP", account().getDcIp()); + env.put("TELEGRAM_API_ID", account().getAppId()); + env.put("TELEGRAM_API_HASH", account().getAppHash()); + env.put("TELEGRAM_SESSION", account().getSessionString()); + env.put("TELEGRAM_USERNAME", account().getUsername()); return env; } } diff --git a/system-x/services/telegram/src/main/java/software/tnb/telegram/validation/TelegramValidation.java b/system-x/services/telegram/src/main/java/software/tnb/telegram/validation/TelegramValidation.java index bce70338c..0fa980d3e 100644 --- a/system-x/services/telegram/src/main/java/software/tnb/telegram/validation/TelegramValidation.java +++ b/system-x/services/telegram/src/main/java/software/tnb/telegram/validation/TelegramValidation.java @@ -2,7 +2,7 @@ import static org.junit.jupiter.api.Assertions.fail; -import software.tnb.telegram.resource.TelegramContainer; +import software.tnb.telegram.service.Telegram; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -11,18 +11,18 @@ import java.util.List; public class TelegramValidation { - private final TelegramContainer container; + private final Telegram client; private static final Logger LOG = LoggerFactory.getLogger(TelegramValidation.class); - public TelegramValidation(TelegramContainer container) { - this.container = container; + public TelegramValidation(Telegram client) { + this.client = client; } public void sendMessage(String text) { LOG.debug("Send message " + text + " from telegram-client "); try { - container.execInContainer("python3", "/app/send_message.py", text); + client.execInContainer("python3", "/app/send_message.py", text); } catch (Exception e) { fail("Failed to send message", e); } @@ -32,7 +32,7 @@ public List getLastNMessages(int n) { LOG.debug("Get last " + n + " messages: "); List messages; try { - String messagesInStr = container.execInContainer("python3", "/app/get_messages.py", n + "").getStdout(); + String messagesInStr = client.execInContainer("python3", "/app/get_messages.py", n + ""); LOG.debug(messagesInStr); messages = Arrays.asList(messagesInStr.split("\n")); } catch (Exception e) {